Forums d'entraide informatique - Astuces - Conseils

Des experts à votre écoute pour tous vos dysfonctionnements

Vous n'êtes pas identifié.


#1 13-08-2008 17:35:30

Admin
Administrateur
Date d'inscription: 30-07-2008
Messages: 683

Représentation d'un objet en 3D

Représentation d'un objet en 3D


1/ Le monde en 3 dimensions

Modéliser un objet de la réalité revient a considérer ses coordonnées spatiales. Aussi, dessiner un objet en 3D peut ne pas paraître simple au premier abord. Selon le problème, les structures utilisées peuvent différer. Nous allons donc nous limiter à une seule représentation, la plus intuitive et très certainement la plus simple à mettre en oeuvre, qui est une représentation hiérarchique.

Nous allons travailler dans le repère cartésien (O,X,Y,Z) qui sera notre espace image. Un objet 3D est caractérisé par sa forme et sa position. La forme d'un objet est définie par un ensemble de facettes planes, et une face est logiquement définie par les coordonnées de ses sommets. En général, les coordonnées sont exprimées par rapport au centre de l'objet. Ce centre est utilisé comme centre de rotation de l'objet.

Ainsi, la position d'un objet dans notre espace image est définie d'une part par les coordonnées de son centre, et d'autre part par son orientation dans l'espace. Ceci nous mène donc naturellement à utiliser un vecteur de translation (Xoff,Yoff,Zoff) et trois angles de rotation distincts (un pour chaque axe).

Pour déterminer la position d'un objet, nous devons connaître les coordonnées de chacun des sommets qui composent ses faces. En pratique, un même sommet est commun à plusieurs faces. C'est pourquoi, afin de ne pas recalculer plusieurs fois les mêmes coordonnées, nous ne travaillons qu'avec des points. Au lieu d'avoir une liste de coordonnées (x,y,z) pour représenter nos faces, nous n'aurons qu'une simple liste de numéros référençant les points de l'objet.

2/ Un exemple simple

Avant d'aller plus loin, prenons un des objets le plus élémentaire en 3D : le Cube. Pour un cube de coté 200 centré sur l'origine, nous pouvons définir ses sommets de la manière suivante :

Point #
   
X
   
Y
   
Z
0
   
-100
   
-100
   
-100
1
   
100
   
-100
   
-100
2
   
100
   
100
   
-100
3
   
-100
   
100
   
-100
4
   
100
   
-100
   
100
5
   
-100
   
-100
   
100
6
   
-100
   
100
   
100
7
   
100
   
100
   
100
Pour les faces, nous pouvons utiliser la structure suivante :

Nb de sommets     Liste des points
4
   
0,1,2,3
4
   
1,4,7,2
4
   
4,5,6,7
4
   
5,0,3,6
4
   
5,4,1,0
4
   
3,2,7,6
L'objet est définit comme ci-dessous :
le cube en 3D

Vous pouvez dès à présent remarquer que les numéros des sommets sont donnés de manière à décrire chaque face dans un sens précis. Dans notre exemple, lorsqu'on regarde une face, ses sommets sont numérotés dans le sens trigonométrique.

3/ Un premier programme

Bien. Tout cela est bien joli, mais en pratique qu'est-ce que ça donne ? Pour ce faire, nous utilisons une projection, qui est le seul moyen de représenter un objet 3D en 2D. Le principe sera expliqué dans le chapitre suivant.

Avant toute chose, il faut définir les sommets du cube. On peut réaliser cette opération de plusieurs manières, soit statiquement, soit dynamiquement. La structure utilisée est des plus simples :

typedef struct
{
  double x,y,z;
} Point;

Pour les sommets, nous pouvons les définir de la manière suivante :

Point cube1[8];

puis faire appel à une fonction qui affectera une valeur a chacun de points :

void Initialiser(void)
{
  cube1[0].x = -100;  cube1[0].y = -100;  cube1[0].z = -100;
  cube1[1].x =  100;  cube1[1].y = -100;  cube1[1].z = -100;
  cube1[2].x =  100;  cube1[2].y =  100;  cube1[2].z = -100;
  cube1[3].x = -100;  cube1[3].y =  100;  cube1[3].z = -100;
  cube1[4].x =  100;  cube1[4].y = -100;  cube1[4].z =  100;
  cube1[5].x = -100;  cube1[5].y = -100;  cube1[5].z =  100;
  cube1[6].x = -100;  cube1[6].y =  100;  cube1[6].z =  100;
  cube1[7].x =  100;  cube1[7].y =  100;  cube1[7].z =  100;
}

Nous pouvons également initialiser les valeurs de chacune des coordonnées lors de la déclaration du vecteur des sommets :

Point cube2[8]= { -100,-100,-100,
                   100,-100,-100,
                   100, 100,-100,
                  -100, 100,-100,
                   100,-100, 100,
                  -100,-100, 100,
                  -100, 100, 100,
                   100, 100, 100 };

Pour afficher tous les sommets de notre cube, nous devons transformer leurs coordonnées 3D en coordonnées 2D, ce qui revient à faire une projection. Le principe en est simple : il suffit de diviser les valeurs X et Y de chaque point par la troisième valeur Z.. Nous avons alors une projection perspective. Voici un petit schéma simple qui va vous éclairer l'esprit sur ce principe fondamental en 3D :

Vous constatez qu'il est simple de calculer la valeur de Y'. Il en est de même pour X'. Si vous ne comprenez pas ce principe, reprenez vos cours de math de 4ème, c'est au programme !

En pratique, il est avantageux de choisir pour valeur de d une puissance de 2 : cela permet de remplacer une multiplication par un simple décalage arithmétique, beaucoup moins coûteux en temps machine (même si cette tendance disparaît peu à peu). Voici une procédure C qui affiche chacun des points du cube en blanc :

void Sommet1(void)
{
  int i;

  _setcolor(15);

  for (i=0;i<8;i++)
  {
    _setpixel((cube1[i].x*256)/(cube1[i].z+Zoff)+Xoff,
              (cube1[i].y*256)/(cube1[i].z+Zoff)+Yoff);
  }
}

Si vous utilisez un autre compilateur que le Watcom C, vous devrez bien sur remplacer les instructions _setcolor et _setpixel par les fonctions similaires disponibles, ou bien encore par votre propres fonctions, comme nous le verrons plus tard.

Une manière bien plus visuelle d'afficher notre cube serait de le dessiner en fil de fer. Rien de plus simple : il suffit de tracer les arêtes entre les sommets projetés sur le plan de l'écran. En reprenant le schéma de notre cube, cela devient un jeu d'enfant :

void FilDeFer(void)
{
_setcolor(15);

/* On affiche la face avant */
ligne(0,1); ligne(1,2); ligne(2,3); ligne(3,0);

/* Puis la face arriere */
ligne(4,5); ligne(5,6); ligne(6,7); ligne(7,4);

/* Et enfin les aretes restantes */
ligne(0,5);
ligne(1,4);
ligne(2,7);
ligne(3,6);
}

Voilà pour notre premier programme consistant à afficher un objet 3D.

Les transformations géométriques 

La programmation en 3D est rarement limitée à des objets immobiles, en particulier dans le domaine des démos. Tout mouvement peut se décomposer en une translation et une rotation, et dans le cas échéant on peut inclure le changement d'échelle. Les objets subissent donc un certain nombre de transformations géométriques, afin de donner une illusion de mouvement. Ces transformations ne sont pas très compliquées d'un point de vue mathématiques, et elles sont de plus en plus câblées sur de nombreux processeurs (par exemple sur les Silicon Graphics) mais il est tout de même bon de les présenter clairement, car vous serez très certainement amené à les programmer.

1/ La translation

On appelle translation un déplacement simple dans une direction fixe. Elle est matérialisée par une addition vectorielle, tout simplement. Par exemple, pour déplacer un point P(x,y) de dx unités selon l'axe des x et de dy unités par rapport à l'axe des y il suffit de faire :

x' = x + dx y' = y + dy

Le point P'(x',y') sera donc le point obtenu par la translation de vecteur T(dx,dy). En 3D, il suffit d'ajouter une dimension : le fonctionnement est strictement identique. En résumé, la translation peut s'écrire sous la forme :

P' = P + T

Pour déplacer un objet par une translation, il suffit d'appliquer la même transformation à tous ses points.

2/ Le changement d'échelle

On peut effectuer aussi facilement un changement d'échelle sur un objet, ce qui permet de le "grossir" ou au contraire de le "rétrécir". Dans ce cas, il faut faire une multiplication de la forme :

x' = sx * x y' = sy * y

Le point P'(x',y') sera le point obtenu par la multiplication du point P et de la matrice S(sx,sy). On écrira donc P'= S . P, où S est une matrice du type :

3/ La rotation

Contrairement aux idées reçues, les calculs de rotations ne sont pas très compliqués, pour peu que l'on ait des vagues souvenirs de trigonométrie et que l'on sache manipuler les matrices.

Plaçons-nous dans le plan avec l'exemple suivant :

rotation.gif

Nous avons ici une rotation d'angle a autour de l'origine. En supposant que les points A et B soient sur le cercle trigonométrique (pour ceux qui aurait oublié : A(1,0) et B(0,1)), nous avons clairement :

xA' = cos(a)   et   xB' = -sin(a)

yA' = sin(a)   et    yB' =  cos(a)

Cette opération n'est autre qu'un calcul matriciel, et vous devez certainement savoir comment l'effectuer. La rotation matrice de la rotation R d'angle a est donc :



On peut maintenant généraliser le problème à tous les points du plan en utilisant cette matrice R. La rotation d'un point P autour de l'origine devient alors :

    *

      x'  =  x.cos(a)  -  y.sin(a)
    *

      y'  =  x.sin(a)  +  y.cos(a)

Pour passer en 3D, rien de plus facile : il suffit d'ajouter une dimension à notre matrice. Dans une rotation, il est important de distinguer les axes concernés ; aussi nous allons voir la matrice associée à la rotation autour de chaque axe. Commençons par la rotation autour de l'axe des X : il est clair que nous pouvons déduire la matrice à partir de celle que nous venons de voir. Il suffit pour cela d'observer que la rotation autour de l'axe des X ne modifiera pas les composantes X des coordonnées du point considéré (où de l'objet).

Voici l'allure qu'auront nos matrices pour une rotation respectivement autour des des axes X,Y et Z :

    x' = x

y' = y*cos(a) - z*sin(a)

z' = y*sin(a) + z*cos(a)
    x' = x*cos(a) + z*sin(a)

y' = y

z' = -x*sin(a) + z*cos(a)
    x' = x*cos(a) + y*sin(a)

y' = -x*sin(a) + y*cos(a)

z' = z

Voilà pour nos rotations. Mais, me direz-vous, pourquoi se promener avec 3 matrices, et non pas une seule ? En fait, le problème est un petit peu plus compliqué que ça, et l'on en reparlera un peu plus tard lorsque nous verrons les matrices homogènes. On peut en effet n'avoir qu'une seule matrice : il suffit de les combiner entre elles. Il s'agit encore une fois d'un simple produit matriciel, mais je ne vous donnerez pas la formule, elle est trop longue pour tenir sur une seule ligne yikes) Si vous etes courageux je vous laisse le soin de la trouver.

A ce niveau, vous pouvez déjà réaliser toutes les animations que vous voulez, puisque nous avons abordé toutes les bases mathématiques nécessaires. Mais il nous reste encore un problème à résoudre : comment afficher une objet représenté en 3D sur un petit écran tout plat qui ne compte lui que 2 dimensions ? Rassurez-vous, la solution est relativement simple, et si vous avez suivit jusque-là cela ne vous causera en principe pas de problème particulier.

4/ La projection

Pour passer d'une dimension 3 à une dimension 2, il faut projeter les coordonnées des sommets qui composent la scène à visualiser. Il existe plusieurs types de projection : la projection parallèle et la projection perspective. La première est utilisée en architecture, alors que le seconde est utilisée pour le rendu réaliste, car elle rend compte des distances et donne véritablement une impression de profondeur à la scène. C'est celle que nous avons vue dans le chapitre précédent, et que nous allons utiliser par la suite.

Dans ce cas de figure, le principe consiste à projeter les points sur un plan situé devant le point d'observation. Reprenons notre petit schéma :

Vous constatez qu'il est simple de calculer la valeur de Y'. Il en est de même pour X'. Il s'agit ici d'une formule simplifiée pour nos besoins, et qui va s'avérer très rapide et efficace, mais qui risque de nous limiter. Donc si jamais vous avez besoin un jour des vraies formules de projection perspective, vous avez de la chance les voici :

X' = Xo + Zo * (X-Xo) / (Zo-Z)

Y' = Yo + Zo * (Y-Yo) / (Zo-Z)

Ces formules tiennent compte de la position de l'observateur, qui est situé au point O(Xo,Yo,Zo). En supposant que l'on ait Xo=Yo=0, on a l'oeil qui est situé quelque par sur l'axe des Z, et l'on retombe sur les formules précédentes. C'est une petite optimisation qui simplifie la vie des débutants, mais qui n'est pas valable dans le cas général.

Comme vous l'avez certainement constaté, le dessin en 2D n'est pas réellement mon domaine de prédilection. Je ne vais donc pas vous faire de petit dessin pour illustrer mes formules, d'autant qu'elles sont compréhensibles.

5/ Les coordonnées homogènes

Les coordonnées homogènes sont utilisées en synthèse d'image afin d'unifier le traitement des transformations géométriques d'une scène et de les regrouper dans une seule matrice. En effet, si l'on utilise une matrice 2*2 pour les scènes bidimensionnelles et une matrice 3*3 pour les scènes tridimensionnelles, ces matrices ne peuvent exprimer que des rotations.

Pour exprimer aussi les translations, les changements d'échelle et les projections, on va utiliser des matrices 4*4 pour les scènes tridimensionnelles.

Ainsi, si (x,y,z) sont les coordonnées d'un point de la scène à transformer et MH la matrice 4*4 de coordonnées homogènes, on effectuera la multiplication :

MH * [ x y z 1 ]

ce qui donnera comme résultat [ X Y Z H ].

Les coordonnées du point transformé seront alors (X/H , Y/H , Z/H).

La matrice 4*4 des coordonnées homogènes peut être considérée comme étant composée de 4 sous-matrices, chacune d'elle étant associée à un type de transformation.


Cordialement

L'équipe Parisdepannage.fr

Hors ligne

 

Pied de page des forums


Copyright Parisdepannage.fr


Fermer la fenètre