Blog de Grégory GHEZ

Pour chaque [ingénieur logiciel] qui affirme : "Personne ne s'embêtera à faire çà", vous trouverez un gamin en Finlande qui s'embêtera à le faire.  - Alex Mayfield

  Home :: Contact :: Syndication  :: Login
  37 Posts :: 4 Stories :: 3 Comments :: 0 Trackbacks

Article Categories

Archives

Message Categories

Liens

Pour comprendre l'exemple qui va accompagné cette présentation, je vous conseille vivement de revoir vos mathématiques, notament en ce qui concerne la manipulation de matrices.

La base de la programmation en 3-Dimensions (x, y et z) est consituée des élements suivants:

  • Définition du point (x,y,z)
  • Transformation de point dans l'espace (translation, rotation, dillatation)
  • Définition d'un objet 3D constitué d'une collection de points

Nous n'aborderons pas dans cet article les fonctionnalités avancées de la 3D actuelle telles que l'éclairage et les ombres, mais sachez que tout est faisable, le tout est de savoir gérer les limitations de GDI+ dans ce domaine.
GDI+ en effet, n'a pas été conçu pour effectuer des rendus 3D fluides.

Commençons par la structure la plus simple, le point:

Il se représente dans un repère à 3 axes: x, y et z respectivement l'abscisse, l'ordonnée et la profondeur.

Ces deux représentation sont correctes, et il n'y a pas de règle qui impose le choix de l'un ou de l'autre pour effectuer le rendu de vos objets dans une scène 3D.

En .NET malheureusement pour l'instant il n'existe pas de structure permettant de représenter cette entité. Point et PointF représentent tous deux des points dans un repère x,y donc 2D à la nuance près que PointF traite avec des float plutôt que des int pour Point.

Voici l'implémentation d'un point 3D que je vous propose:

public class Point3D
{
   private double
m_x;
   private double
m_y;
   private double
m_z;

   public
Point3D()
   {
      m_x = 0.0;
      m_y = 0.0;
      m_z = 0.0;
   }

   public Point3D(double x, double y, double
z)
   {
      m_x = x;
      m_y = y;
      m_z = z;
   }

   public
PointF Point2D
   {
      get { return new PointF((float)m_x, (float
)m_y); }
   }

}

Jusque là pas de soucis, maintenant venons aux éléments les plus interessant utilisés pour faire des animations en 3D: les transformations.
La première transformation que nous allons voir est la translation, cette transformation revient à déplacer le point selon une ligne droite dans son repère.
Par exemple, pour un déplacement horizontal:

   Point3D pt = new Point3D();
  
pt.X += 10;

On peut également effectuer une translation sur les axes y et z pour créer une translation globale déplaçant le point sur les axes x,y et z simultanément.
Nous verrons plus loin lorsque nous aurons étudier les matrices de transformation que la translation peut être effectuer d'une autre manière en appliquant une matrice de transformation au point.

La rotation est l'opération de transformation la plus complexe, et nous allons donc commencer à étudier les matrices permettant d'effectuer les rotations x, y et z.
Les matrices de transformation que je vais utiliser sont de taille 4x4 afin de modéliser un point représenté par (x,y,z,w) ou w est le facteur d'échelle, c'est à dire que pour passer de cette représentation à (X,Y,Z) on effectue (x/w, y/w, z/w).

La matrice permettant d'effectuer la rotation d'un point autour de l'axe x est la suivante:

En C#, on peut la représenter comme suit:

public struct Matrix3D
{
   public double
A11;
   public double
A12;
   public double
A13;
   public double
A14;
   public double
A21;
   public double
A22;
   public double
A23;
   public double
A24;
   public double
A31;
   public double
A32;
   public double
A33;
   public double
A34;
   public double
A41;
   public double
A42;
   public double
A43;
   public double
A44;

   public static Matrix3D GetRotateX(double
teta)
   {
      Matrix3D m =
new
Matrix3D();

      m.A22 = Math.Cos(teta);
      m.A23 = -Math.Sin(teta);
      m.A32 = Math.Sin(teta);
      m.A33 = Math.Cos(teta);
      m.A11 = 1.0;
      m.A44 = 1.0;

      return
m;
   }
}

Sur ce modèle on peut représenter également les matrices de zoom et de translation qui sont les suivantes:

Ainsi nous pouvons rajouter au code de notre classe Point3D les méthodes suivantes:

public void ApplyMatrix(Matrix3D m)
{
   double
w = 0.0;
   Point3D pt =
new
Point3D();

   w = m.A41 * m_x + m.A42 * m_y + m.A43 * m_z + m.A44;
   pt.m_x = m.A11 * m_x + m.A12 * m_y + m.A13 * m_z + m.A14;
   pt.m_y = m.A21 * m_x + m.A22 * m_y + m.A23 * m_z + m.A24;
   pt.m_z = m.A31 * m_x + m.A32 * m_y + m.A33 * m_z + m.A34;

   if
(w != 0.0)
   {
      pt.m_x /= w;
      pt.m_y /= w;
      pt.m_z /= w;
   }

   m_x = pt.m_x;
   m_y = pt.m_y;
   m_z = pt.m_z;
}

public void Rotate(double tetaX, double tetaY, double
tetaZ)
{
   ApplyMatrix(Matrix3D.GetRotateX(tetaX));
   ApplyMatrix(Matrix3D.GetRotateY(tetaY));
   ApplyMatrix(Matrix3D.GetRotateZ(tetaZ));
}

public void Offset(double dx, double dy, double
dz)
{
   ApplyMatrix(Matrix3D.GetTranslation(dx, dy, dz));
}

public void Zoom(double
factor)
{
   ApplyMatrix(Matrix3D.GetZoom(factor));
}


Il ne nous reste plus qu'à définir l'objet 3D par la classe C# suivante:

public class Object3D
{
   private string
m_name;
   private
Point3DCollection m_points;

   public string
Name
   {
      get { return
m_name; }
      set { m_name = value
; }
   }

   public
Point3DCollection Points
   {
      get { return
m_points; }
   }

   public Object3D(): this(null
) {}

   public Object3D(string
name)
   {
      m_points =
new
Point3DCollection();
      m_name = name;
   }

   public void Rotate(double tetaX, double tetaY, double
tetaZ)
   {
      foreach (Point3D pt in
m_points)
      {
         pt.Rotate(tetaX, tetaY, tetaZ);
      }
   }

   public void Offset(double dx, double dy, double
dz)
   {
      foreach (Point3D pt in
m_points)
      {
         pt.Offset(dx, dy, dz);
      }
   }

   public void Zoom(double
factor)
   {
      foreach (Point3D pt in
m_points)
      {
         pt.Zoom(factor);
      }
   }

}

Comme vous l'aurez compris, effectuer une transformation sur un objet 3D revient à effectuer la dite transformation sur l'ensemble des points qui le compose.

Pour ceux qui seraient interessé par une librairie contenant toutes les belles choses que nous venons de voir et plus encore, je vous invite à télécharger la solution en cours de développement qui se trouve ici.

posted on jeudi 25 août 2005 00:10

Feedback

# Programmation 3D avec GDI 25/08/2005 01:16 Blog de Gr


# re: La base de la programmation 3D en GDI+ .NET 25/08/2005 10:06 Etienne
Excellent !

C'est quand que tu nous fais un Quake en GDI+ ? :)

# re: La base de la programmation 3D en GDI+ .NET 25/08/2005 21:10 gg00xiv
C'est déjà fait.



Non je rigole ;) mais j'ai pas le temps pour la conception d'un jeu entier je préfère travailler sur les bases et plus précisement sur un moteur en GDI+, mais pour cela il y a encore plein de points de la 3D à intégrer.

# re: La base de la programmation 3D en GDI+ .NET 16/08/2007 16:04 akon ringtones
really nice

# re: La base de la programmation 3D en GDI+ .NET 16/08/2007 16:05 free lg ringtones
cool site

Post Feedback

Title:
Name:
Url:
Comments: 
Enter the code you see: