De retour sur cette librairie .NET que je commencais à développer il y a quelques semaines concernant le traitement de scènes en 3D grâce à GDI+.
Je viens de rajouter de nouveaux aspects de la 3D que je n'avais pas abordé la dernière fois faute de temps et pour éviter surtout de perdre les plus novices dans ce domaine.
Les élèments suivants ont été rajoutés et je vais tâcher de vous les détailler:
- Polygon3D (composition de n points)
- Object3D (qui ne contient plus directement une collection de points mais une collection de polygones ce qui est plus logique).
- Chargement de .obj (format de mesh 3D réalisable avec 3DS Max) en version beta.
- Définition du moteur 3D (_3DEngine) de façon plus précise.
- Affichage des polygon visibles de l'object en premier plan.
- Traitement de la focal (effet de profondeur visible).
Polygon3D
Attributs:
- BorderColor: type Color utilisé pour le tracé des polygones
- FillColor: type Color utilisé pour le remplissage des polygones
- Points: collection de Point3D
Méthodes:
- AddPoints: permet d'étendre le polygone de ces points
- Rotate: permet d'effectuer une rotation du polygone autour des axes x, y et/ou z
- Offset: permet de déplacer dans le repère x,y,z le polygone
- Dillate: permet de dillater les coordonnées des points le composant
- Clone: permet de créer une copie du polygone (coordonées des points le composant identiques)
Le moteur 3D
Les fonctionalités d'antialiasing, gestion de la focal et de mode de tracé ont été rajoutées (propriétés Antialiasing, DrawingMode et Focal de l'objet _3DEngine). L'antialiasing s'avère quasi obligatoire dans le traitement de scènes en 3D car le nombre de polygones ainsi que leur petites tailles font de la scène un vrai brouillon s'il n'est pas activé (antialiasing = lissage des droites/évite l'effet escalier).
La focal (distance entre l'object et l'oeil) quant à elle permet de donner un effet de réalisme à la profondeur occupée par l'object. La méthode ConvertPolygonToPointFArray du moteur permet de transformer un polygone en une série de points (float, float) représentés à l'écran suite à leur transformation de profondeur. Le paramètre de transformation est la valeur de la focal.
Voici cette méthode:
private
PointF[] ConvertPolygonToPointFArray(Polygon3D poly)
{
PointF[] pts = new PointF[poly.Points.Count];
for (int i=0; i {
double factor = m_focal / (m_focal - poly.Points[i].Z);
pts[i].X = (float)(poly.Points[i].X * factor);
pts[i].Y = (float)(poly.Points[i].Y * factor);
}
return pts;
}
Il est désormais possible de définir le mode de tracé via l'énumération _3DObjectDrawingMode définit comme suit:
public
enum _3DObjectDrawingMode
{
ShowPolygons,
ShowPoints,
ShowFaces
}
ShowPolygons permet de n'afficher que les contours des polygones des objects.
ShowPoints n'affiche que les points des polygones de l'object.
ShowFaces affiche les polygones remplis d'une couleur définie par la propriété FillColor du polygone.
Concernant l'affichage des polygones de premier plan, la technique est simple: faire la moyenne des coordonnées z des chaque points des polygones de l'objet et classer ces polygones par ordre croissant de moyenne z.
Il ne reste qu'a afficher les polygones de moyenne la plus élevée en premier. J'utilise pour cette occasion une SortedList.
J'ai créé pour cela une propriété sur l'objet Object3D:
public
Polygon3DCollection SortedPolygons
{
get
{
SortedList sl = new SortedList();
foreach (Polygon3D poly in m_polygons)
{
double sumZ = 0.0;
foreach (Point3D pt in poly.Points)
sumZ += pt.Z;
double avgZ = sumZ / poly.Points.Count;
if (!sl.ContainsKey(avgZ))
sl.Add(avgZ, new Polygon3DCollection());
(sl[avgZ] as Polygon3DCollection).Add(poly);
}
Polygon3DCollection polys = new Polygon3DCollection();
foreach (double avgZ in sl.Keys)
{
foreach (Polygon3D poly in sl[avgZ] as Polygon3DCollection)
{
polys.Add(poly);
}
}
return polys;
}
}
Une forme prédéfinie a été rajoutée, il s'agit de la sphère 3D composée d'environ 650 polygones carrés.
Je vous laisse découvrir l'avancement du projet à cette adresse : 3DLib_2.zip