Mon travail▲
Dans le cadre d'un projet d'étude mené lors de ma dernière année de cycle ingénieur, j'ai développé avec l'aide d'un ami, Julien Peyre, un début de moteur physique. Nous avons géré les collisions pour des primitives de base.
- Ce projet a été développé sous Visual C++ Express.
- Pour faire le rendu de nos calculs, nous avons utilisé OpenGL
- Quelques vidéos d'exemples sont disponibles ici
- Les sources sont là
- Le plus intéressant à mon sens est le rapport écrit dans lequel on trouve les principes physiques et mathématiques permettant une implémentation.
Introduction▲
Avant de devenir une science à part entière, la mécanique a longtemps été une section des mathématiques. Elle en était un domaine applicatif totalement naturel.
La mécanique statique a été le premier domaine étudié avec des notions fondamentales comme l'équilibre ou les forces. Ensuite, ces notions ont laissé place à la dynamique, basée sur les phénomènes qui régissent les mouvements des solides. Deux scientifiques ont apporté une immense contribution à ce domaine : Galilée, avec sa théorie sur la chute des corps, et Newton, avec ses célèbres lois du mouvement.
La puissance des processeurs actuels permet la réalisation de ces calculs en temps réels. Ainsi il devient possible de modéliser et de visualiser le comportement des solides. Dès lors on s'aperçoit que les lois, établies depuis le XVIe siècle, fournissent des résultats très satisfaisants. Elles sont d'ailleurs communément utilisées dans les jeux vidéo.
Quel est le lien entre les jeux vidéo et Newton nous direz-vous ? Suite à l'essor des jeux vidéo en tant que loisirs de masse, les développeurs sont à la recherche d'univers toujours plus immersifs. Pour cela, ils souhaitent modéliser le plus fidèlement possible les phénomènes naturels. Des efforts importants ont été faits ces dernières années dans deux domaines de recherche : la qualité graphique et la dynamique.
Un nouveau type d'applications est alors apparu : les moteurs physiques. Un moteur physique est une bibliothèque intégrable à un programme qui permet la résolution des équations physiques. Typiquement, il permet de détecter les collisions entre plusieurs solides et de calculer leurs réponses.
Ce rapport a pour but de présenter un projet qui pourrait constituer un début de moteur physique. Reposant sur des formes géométriques de base, nous avons souhaité implémenter les lois de la dynamique.
Algorithme général▲
Les objets de la scène sont donc décrits dans un fichier texte qui va être lu par le programme. Ce fichier va notamment initialiser les positions des objets. Leur position initiale est ainsi fixée dans ce fichier. Ensuite, à chaque frame, le moteur va réaliser ce même processus.
- Calculs des nouvelles positions grâce à une intégration dans le temps des équations de la dynamique sans tenir compte des collisions.
- Détection des collisions grâce à des algorithmes spécifiques à chaque type de collisions.
- Gestion éventuelle de ces collisions pour relancer le système dans un état valide : calcul des vitesses réfléchies.
- Mise à jour de l'état des solides.
Leçon 1 : Calculs des nouvelles positions▲
Pour simuler le mouvement des objets, nous avons basé notre implémentation sur la mécanique des solides indéformables. Pour décrire le mouvement d'un objet, cinq paramètres indispensables doivent être définis.
- Sa position, .
- Sa masse, .
- Son repère locale, .
- Sa vitesse linéaire (vitesse du centre de masse), .
- Sa vitesse angulaire, .
Cependant il est à noter que dans l'implémentation de notre moteur nous n'avons pas tenu compte de la vitesse angulaire des sphères. En effet, nous avons décidé de mettre de côté cet aspect puisque si l'on associe une texture uniforme à une sphère, sa rotation n'est pas perceptible. En outre, ceci peut être considéré comme amélioration future.
Équations de la dynamique▲
Nous utilisons dans ce projet les deux équations fondamentales suivantes :
À chaque frame, nous réalisons un bilan des forces exercées sur l'objet pour calculer la nouvelle accélération ainsi que le bilan des moments pour en déduire la nouvelle vitesse angulaire.
La matrice d'inertie permet de traduire la répartition de la masse du solide et ainsi de favoriser certains couples. Elle joue grossièrement le même rôle pour la vitesse angulaire que la masse pour la vitesse linéaire. La matrice d'inertie d'un solide a la forme suivante :
où est la densité volumique du solide.
Matrice d'inertie des solides utilisés :
Équation de la cinématique▲
La cinématique du solide peut être représentée mathématiquement comme l'intégration sur le temps des équations différentielles liant position, vitesse et accélération.
Il est également possible de définir la vitesse d'un point quelconque, , du solide : où est le vecteur liant au centre de masse.
Leçon 2 : Gestion d'une sphère▲
Collision Sphère/Plan▲
Détection de la collision▲
Une fois le calcul des nouvelles positions des objets effectué, il est nécessaire de détecter s’ils rentrent en collision avec un autre objet. Dans le cas de la collision Sphère/Plan, cette détection se fait aisément en comparant la distance du centre de la sphère au plan avec le rayon de la sphère :
La condition de collision est , avec R rayon de la sphère.
Gestion de la collision▲
Une première idée pour gérer la collision entre deux corps rigides est d'appliquer une force de réaction aux objets. Cependant cette force ne va pas arrêter les objets immédiatement et ne va donc pas empêcher leur interpénétration, car elle ne pourra pas changer instantanément le sens des vitesses.
Une force va mettre trop de temps à inverser les vitesses or les corps sont déjà en contact, il faut donc agir immédiatement sur leur vitesse. C'est pourquoi nous allons calculer la vitesse réfléchie par rapport à la normale de la collision (la normale du plan dans ce cas). Celle-ci remplacera ensuite l'ancienne vitesse.
La vitesse réfléchie peut être obtenue grâce à la relation suivante :
Recalage au point de contact exact▲
Du fait que le calcul des positions ne peut se réaliser de manière continue (il s'effectue à chaque frame donc tous les Dt secondes), les objets seront déjà interpénétrés au moment où l'on détecte la collision. Il est alors nécessaire de replacer les objets au point de contact exact pour être certain qu'à la frame suivante, les deux objets se seront bien séparés.
En effet si l'on ne réalise pas ce recalage, il est possible que les objets n'aient pas eu le temps de compenser l'interpénétration à la frame suivante (notamment si le Dt suivant est faible). Dès lors, le moteur va détecter de nouveau une collision, etc.
On recale l'objet dans la direction de sa vitesse au moment ou l'on détecte la collision. On cherche en fait à « remonter dans le temps » afin de trouver le point de collision exact. On calcule dans un premier temps la pente de la vitesse (représentée par des pointillés bleus sur le schéma ci-dessus).
On a alors or d'où et donc finalement :
Connaissant on peut alors aisément replacer la sphère à la bonne position.
Dans le cas où la sphère entre en collision avec plusieurs objets (par exemple avec deux plans), on calcule pour chacune des collisions la distance nécessaire au recalage de la sphère. Finalement, on garde le plus grand pour recaler physiquement la sphère et ainsi éviter toute interpénétration avec les autres objets :
Collision Sphère/Sphère▲
Détection de la collision▲
La détection de la collision Sphère/Sphère est relativement simple. Soit deux sphères :
- de centre et de rayon
- de centre et de rayon
On forme le vecteur et l'on pose . Ensuite, il suffit de vérifier que pour s'assurer de la collision.
Gestion de la collision▲
Notre gestion de la collision va prendre en compte l'inertie des deux objets. En effet, une boule de bowling lancée à grande vitesse ne sera pas influencée par le contact avec une balle de ping-pong.
Tout d'abord, on se place dans le repère local défini par l'axe de direction et l'axe perpendiculaire. Seule la composante des vitesses suivant l'axe sera modifiée. On donnera ici la solution sans démonstration. On pose donc :
et l'on a .
De même :
et l'on a .
On remarquera dans ces formules que si les sphères sont de masse égale et si les vitesses au point de rencontre sont les mêmes alors on a . On retrouve alors le calcul classique d'un vecteur réfléchi par rapport à une normale (suivant ) soit .
Recalage au point de contact▲
Pour les mêmes raisons que précédemment (voir recalage Sphère/Plan), on va chercher à recaler les deux sphères.
Dans le cas de cette collision, on va reculer les deux sphères suivant la direction de leur vitesse respective jusqu'au moment où elles ne possèdent plus qu'un seul point d'intersection : leur point de contact.
On a avec ( resp. ) pente de la vitesse de l'objet 1 ( resp. 2). De plus il faut que pour être au point exact de contact. Donc :
On a donc un système à deux équations et deux inconnues que l'on peut résoudre aisément par les méthodes classiques. On arrive alors à :
Il faudra donc reculer la sphère 1 de et la sphère 2 de .
Suite à la présentation orale du projet, une question nous a permis de voir une limite dans cette méthode. En effet, la variable « b », posée ainsi, suppose que les vitesses sont coplanaires ; ce qui n'est pas forcément vrai.
Il faudrait donc trouver la démonstration dans le cas général, en distinguant les variables et .
Leçon 3 : Gestion d'une box - Partie 1/2▲
Dans un second temps, une fois l'architecture du moteur établie et la gestion des sphères implémentée, nous avons décidé de nous intéresser à la gestion d'un objet qui paraît simple, mais dont la dynamique est assez complexe : le cube.
La collision Boite/Plan▲
La détection de la collision▲
Soit une boite , de centre et de dimensions suivant les axes de son repère local et un plan, de centre et de normale .
On calcule tout d'abord la distance du centre de la boite au plan. En projetant sur la normale, on a .
Ensuite, on va chercher la contribution de chaque côté du cube suivant la normale. Pour cela, on projette chaque axe du repère local sur la normale que l'on multiplie par les dimensions de la boite :
Ou encore,
Il n'y a plus qu'à calculer la différence entre la distance séparant les deux centres et la demi-hauteur du cube.
On vérifie donc le signe de l'expression .
Gestion de la collision▲
Les choses commencent à se compliquer ici. En effet, pour la gestion des collisions des sphères, seule la vitesse linéaire était à gérer. En faisant intervenir les masses, on calculait la vitesse réfléchie.
Avec les boites, un nouveau paramètre rentre en compte : la vitesse angulaire. Dès lors, en plus de la vitesse linéaire, il faut calculer la réponse agissant sur la vitesse angulaire. Nous avons utilisé la théorie de l'impulsion qui est applicable à tout type de collision.
Pour la collision de deux corps rigides, on suppose que le processus de déformation microscopique consiste en deux phases : la phase de compression et la période de restitution. La phase de compression s'étend de l'instant du contact jusqu'à l'instant où la vitesse devient nulle. La restitution commence alors et prend fin lors de la séparation des corps. La durée de contact étant supposée très courte et les forces très grandes, on considère que :
- le processus de collision est instantané et le changement de vitesse est discontinu ;
- il n'y a pas de déplacement pendant l'impulsion ;
- les forces qui interagissent sont des impulsions et toutes les autres forces finies sont négligeables.
Théorie de l'impulsion▲
Considérons deux objets et qui viennent tout juste de collisionner en un point P. Lorsque les deux corps entrent en collision, une impulsion normale et une impulsion tangentielle sont générées au point de contact.
Nous allons distinguer deux repères correspondant aux repères locaux de chaque objet. On considère que la probabilité d'avoir un contact de type sommet/sommet est nulle. On pose plusieurs variables :
- Soit la vitesse linéaire initiale de l'objet .
- Soit la vitesse angulaire initiale de l'objet .
Pour l'objet , on a les relations suivantes :
- l'impulsion correspond à la différence de quantité de mouvement. En considérant chaque composante, on a ;
- la seconde relation fait appel au théorème des moments d'inertie, . En appliquant cette relation à l'objet , on a : ;
- en appliquant cette relation à l'objet , on a : ;
- similairement, la vitesse du point de collision C suivant l'objet est .
On définit alors deux grandeurs :
- la vitesse de glissement : elle correspond à la composante tangentielle de la vitesse relative des points de contact ;
- la vitesse de compression : elle correspond à la composante normale de la vitesse relative des points de contact ;
- en combinant les équations précédentes, on obtient le système
en posant et .
Classification du mouvement▲
Une fois tous ces coefficients calculés, il faut classifier le mouvement pour définir le bon type d'impulsion.
La résolution de ce système se fera par la technique graphique de Routh. Cette technique permet de déterminer des modes de contact ainsi que les formules à utiliser pour chacun des modes.
On pose les coefficients suivants :
et étant le coefficient frottement du matériau.
En fonction de ces valeurs, nous allons définir cinq cas :
|
|
|
|
Glissement |
Glissement |
|
R-adhérence |
R-glissement vers l'arrière |
|
C-adhérence |
C-glissement vers l'arrière |
Méthode de Poisson▲
Nous donnons ici directement les résultats :
- Glissement
- C-adhérence
- R-adhérence
- C-glissement vers l'arrière
- R-glissement vers l'arrière
Leçon 4 : Gestion d'une box - Partie 2/2▲
Application à la collision Box/Plan▲
Une fois le point d'intersection trouvé, il suffit d'appliquer ces formules pour calculer l'impulsion en considérant que le plan n'a ni vitesse linéaire, ni vitesse angulaire. De plus on considère sa masse et son moment d'inertie comme étant infinis.
Les résultats obtenus avec ce calcul de l'impulsion sont très satisfaisants. Nous avions commencé cette implémentation pour la collision Box/Plan, mais comme ce calcul est totalement générique, nous l'avons appliqué pour tous les autres types de collision. Cependant, à cause d'un manque de temps, nous n'avons pas modifié les méthodes de gestion d'intersection que nous avions déjà implémentées.
Recalage au point de collision▲
Pour le cas de la collision boite/Plan, nous allons devoir « remonter dans le temps » pour retrouver le moment où la boite avait exactement un seul point de contact avec le plan. Une difficulté supplémentaire apparaît alors : non seulement la boite s'est translatée, mais elle a également tourné en même temps.
Mise en équation du problème▲
On appelle « d » la distance du centre de la boite au plan, d0 est la distance initiale.
- représente les coordonnées du point de contact dans le repère local de la boite.
- ?0 représente l'angle initial entre le point de contact et la normale et ? mesure la variation de cet angle au cours du temps.
On a dans le triangle colorié en bleu : .
Plus généralement, lorsqu'on « remonte dans le temps », on a : .
Or et ?=?.?t avec ? vitesse angulaire de la boite. Donc :
On cherche alors à trouver le ?t.
Méthodes de résolution▲
Notre équation nous ramène donc à chercher le point d'intersection entre un cosinus et une droite. En effet, notre équation peut se mettre sous la forme cos( ?.?t +?0 )=a?t +b avec a,b, ? et ?0 positifs.
Pour résoudre cette équation, nous avons pensé à deux possibilités.
- Développement limité du cosinus
En réalisant un développement limité du cosinus, nous nous ramerons à une équation du second degré et nous pourrons ainsi en tirer une expression analytique pour ?t :
Cependant le développement limité n'est valable qu'au voisinage de 0. On risque alors d'avoir une imprécision sur ?t dès que l'angle formé par ?+?0 devient grand.
- Dichotomie
C'est la méthode que nous avons choisi d'implémenter. Nous avons remarqué que l'angle ?+?0 est compris entre 0 et pi/2. On a donc une première indication sur un intervalle dans lequel nous pourrons trouver ?t : 0 < ?t < (pi/2-?0)/?. Ceci constituera notre intervalle de départ pour la dichotomie. On peut donc en déduire que le cosinus de ?+?0 sera décroissant sur l'intervalle considéré et sera compris entre 0 et cos(?0).
Or a et b sont positifs, donc la droite est croissante. De plus, en ?t=0 le membre de gauche vaut cos(?0) et le membre de droite vaut b.
Or et avec donc .
Il y a donc bien une solution et une seule à notre problème.
On va alors pouvoir procéder à la recherche de ?t par dichotomie en évaluant, et en rétrécissant l'intervalle par le bas si la quantité est positive et par le haut si elle est négative. On a estimé qu'en 10 itérations nous avions une bonne estimation de ?t.
Connaissant ?t par l'une ou l'autre des méthodes, on peut alors recaler notre boite sans difficulté.
La collision Box/Sphère▲
Détection de la collision▲
La détection est faite en utilisant tout ce qui a été vu précédemment. On calcule les contributions des axes du cube par projection sur l'axe liant les deux centres de gravité des objets.
Soit une boite de centre et de dimensions suivant les axes de son repère local et une sphère , de centre et de rayon .
Une étape supplémentaire est nécessaire ici pour se servir correctement du calcul de l'impulsion. Il s'agit de calculer la normale au point de collision. En effet, deux cas de figure sont possibles.
- La collision se produit sur la face du cube ; dans ce cas, la normale de collision est égale à la normale de la face du cube.
- La collision a lieu sur un sommet du cube : la normale de collision est égale au vecteur normalisé.
On pose, mais on a toujours . La condition de collision est alors :
Gestion de la collision▲
Nous calculons l'impulsion en considérant que la sphère n'a pas de vitesse angulaire et que le moment d'inertie est infini.
Collision Boite/Boite▲
Détection de la collision Boite/Boite▲
Pour détecter une collision entre deux boites, on s'appuie sur le théorème de l'axe séparateur. Si deux boites ne sont pas en contact alors il existe un axe séparateur , où et sont des vecteurs disjoints choisis parmi les 6 axes des boites.
Un axe est dit séparateur s'il existe un plan orthogonal à celui-ci qui sépare les deux boites et que cet axe soit orthogonal à la face d'une des deux boites ou orthogonal à deux côtés de chaque boite.
Ceci conduit à tester les 15 axes suivants.
Collision face avec un sommet
- Normale face1 objet 1
- Normale face2 objet 1
- Normale face3 objet 1
- Normale face1 objet 2
- Normale face2 objet 2
- Normale face3 objet 2
Collision arrête avec une autre arrête
- Normale face1 objet1 ^ Normale face1 objet2
- Normale face1 objet1 ^ Normale face2 objet2
- Normale face1 objet1 ^ Normale face3 objet2
- Normale face2 objet1 ^ Normale face1 objet2
- Normale face2 objet1 ^ Normale face2 objet2
- Normale face2 objet1 ^ Normale face3 objet2
- Normale face3 objet1 ^ Normale face1 objet2
- Normale face3 objet1 ^ Normale face2 objet2
- Normale face3 objet1 ^ Normale face3 objet2
Le test s'effectue simplement par projection des boites sur les axes :
Ainsi on peut montrer que L est un axe séparateur s'il satisfait la condition suivante : avec et les dimensions des cubes.
L'algorithme s'arrête dès la détection du premier axe, il n'y a alors pas de collision. Si pour aucun des 15 axes cette condition n'est pas vérifiée alors il y a collision.
Gestion de la collision boite/boite▲
Nous utilisons la technique décrite dans le chapitre Gestion de la collision boite/Plan généralisée à deux objets.
La normale de la collision est alors définie comme étant l'axe séparateur trouvé précédemment.
Pour trouver les coordonnées du point de contact, nous séparons les cas.
- Collision entre un sommet et une face.
- Collision entre deux arrêtes.
Collision sommet/face
On cherche le sommet de la boite en collision. Pour cela, on se base sur le produit scalaire entre les axes de cette boite et la normale :
Implémentation collision sommet/face |
---|
avec orienté vers la boite dont le sommet est en collision. |
Collision arrête/arrête
De la même manière, on va chercher le point de contact dans le repère local d'une des boites puis le convertir en coordonnées globales. Par définition, la normale est orthogonale à un des axes de la boite. Pour les deux autres axes, on procédera de la même manière.
Implémentation collision arrête/arrête |
---|
If( == 0 ) |
Architecture▲
Dans cette partie, nous allons rapidement détailler les classes et leurs relations. L'affichage des objets se fait via l'API OpenGL.
La classe Objet
La classe objet est la classe mère de toutes les primitives graphiques. Elle possède les paramètres communs à tous les objets.
- Masse
- Position, Vitesses, Accélération
- Matériau
- Nombre de collisions
Concernant les méthodes, cette classe possède principalement des accesseurs. Cependant, la méthode d'affichage est une méthode virtuelle pure, ce qui rend cette classe abstraite.
La classe Sphère
Cette classe hérite de la classe objet. Elle définit les paramètres propres à la sphère et elle surcharge la méthode d'affichage. on remarquera ici la méthode pour texturer une sphère.
glPushMatrix
(
);
GLUquadric*
params =
gluNewQuadric
(
); //création d'une quadrique
gluQuadricTexture
(
params,GL_TRUE); //activation des coordonnées de texture
glTranslatef
(
m_vPos.x, m_vPos.y, m_vPos.z);
gluSphere
(
params, m_fRayon, 30
, 30
);
glPopMatrix
(
);
gluDeleteQuadric
(
params); //je supprime la quadrique
En effet, il ne faut pas passer par la fonction GLUT, mais plutôt par la création d'une quadrique.
La classe Plan
À partir des trois points du plan fournis au constructeur, on calcule le dernier point et la méthode d'affichage affiche un simple quadrilatère texturé.
La classe Box
Une box est une boite qui possède son propre repère local. Ainsi, il suffit de modifier les axes pour changer l'orientation de la boite. On peut alors se passer de toutes fonctions de transformation d'OpenGl.
La méthode d'affichage se résume à afficher 6 quadrilatères texturés.
Le fichier PhysicEngine.cpp
Il s'agit du point d'entrée du programme. Les méthodes OpenGl y sont définies ainsi que la scène et la caméra.
La boucle principale permet de passer le temps écoulé depuis la dernière frame à la scène. De plus, le parseur de scène se trouve ici et est exécuté lors de l'initialisation d'OpenGl. Au niveau des textures, elles sont chargées à ce moment-là et l'index de la texture est stocké dans le matériau.
La classe Scene
Il s'agit du cœur du moteur. Elle contient trois objets du type list de la Standard Template Library :
- la première contient tous les objets ;
- la seconde tous les matériaux ;
- la dernière répertorie toutes les intersections de la frame courante.
Dans cette classe sont définies les méthodes d'intersection (détection) et de calcul de la réponse (gestion). De plus, à chaque frame, la scène met à jour la dynamique des objets.
La classe Image
Cette classe associée au fichier tga.cpp permet de lire et de charger les textures de format *.tga via l'objet Image_Manager.
La classe Materiau
Elle conserve l'index de la texture chargé par OpenGL. Les coefficients de frottements et de glissement permettent de modifier la réponse de l'objet.
Conclusion▲
Voici les quelques améliorations que nous pourrions apporter au projet.
- Amélioration des techniques de recalage. En effet, nous n'avons pas eu le temps nécessaire pour trouver un algorithme du recalage lors d'une collision entre une sphère et une boite et entre une boite et une boite. De plus l'implémentation du recalage lors d'un contact boite/plan est à améliorer. En effet, quelques problèmes surviennent parfois, notamment lorsque la vitesse linéaire devient trop tangentielle au plan.
- Amélioration du traitement des collisions arrête/arrête entre deux boites. En effet, nous avons remarqué que parfois le calcul du point de contact paraît erroné. De plus, on ne trouve pas le même point si l'on considère l'une ou l'autre boite.
- Nous pourrions également modifier la classe Sphere afin d'ajouter un mouvement de rotation aux sphères. En effet, dans l'état les sphères ne font que se translater et ne tournent pas.
- Ajouter une force de réaction dans le cas de collision entre une boite et une sphère ou entre deux boites lorsque les deux objets sont à l'arrêt. En effet, sans cela, si on pose un objet sur un autre sans vitesse, l'impulsion calculée va être nulle et l'objet du dessus va « entrer » dans l'objet du dessous. Il faudrait alors à ce moment appliquer une force de réaction.
- Enfin, une optimisation du code source nous permettrait de gagner du temps et ainsi de pouvoir traiter des scènes plus importantes.
Bibliographie▲
- http://roso.epfl.ch/dm/pdf/CHAP3.PDF
- http://fr.wikipedia.org/wiki/Moment_(mécanique)
- http://www.yov408.com/tutorials/gdmphys3.pdf
- http://www.jdotec.net/s3i/Mecanique/Cinematique/Cinematique_du_contact_ponctuel.php
- http://www.jdotec.net/s3i/Mecanique/ActionsMeca/Lois_du_frottement.php
- http://www.sciences-indus-cpge.apinc.org/Matrice-d-inertie-des-solides
- http://graphics.stanford.edu/courses/cs448-01-spring/papers/moore.pdf
- http://www.euclideanspace.com/physics/dynamics/collision/index.htm
- http://www-evasion.imag.fr/Membres/Francois.Faure/ascollisions/divers/dea-romain-rodriguez.pdf
- http://mustapha.bismi.free.fr/articles/obb.pdf
- http://www.librecours.org/cgi-bin/domain?callback=info&elt=78
- http://www.sciences.univ-nantes.fr/physique/perso/blanquet/synophys/13mesol/13mesol.htm
- http://perso.orange.fr/physique.chimie/TS_Physique/Physique_12_CHUTE_VERTICALE_D_UN_SOLIDE.htm
- https://hal.inria.fr/inria-00070602/file/RR-5401.pdf