>>NEW<< La librairie G3D

Pour les plus motivés, nous proposons des projets 3D.

../_images/demo2.gif

Le repère 3D

Axes et origine

Par convention, la caméra est centrée sur l’origine du monde. L’axe des abscisses et des ordonnées sont orientés comme dans le plan c’est à dire vers la droite et vers le haut. Le repère est direct, ainsi, la direction du 3ème vecteur doit correspondre au produit vectoriel i^j. Ainsi l’axe de la profondeur est orienté vers la caméra (vers vous) :

../_images/repere.png

Attention cependant, comme l’axe des z est orienté vers la caméra et que la caméra est centrée sur le milieu de l’écran, l’axe des z est visuellement réduit à un point. Par convention, on dessine l’axe des x, y et z en rouge, vert et bleu. Voici la vue depuis l’application :

../_images/ecran.png

La perspective

La mise en place d’une caméra produit un effet de perspective 3D. Par conséquent, des objets éloignés peuvent avoir la même taille que des objets plus petits mais plus proches de la caméra.

../_images/pers.png

Initialisation

Ouvrez le fichier EleveDemo3D.cpp. Dans la fonction demo3DRender, vous trouvez l’activation du mode 3D - perspective :

GX::select3DMode(Color::Gray,G.Cam,1200,700);

qui permet d’initialiser :

  • La couleur de fond

  • La position de la caméra

  • La taille de la fenêtre : 1200x700

Avertissement

Veillez à ce que la première opération effectuée par la fonction demo3DRender soit : select3DMode.

Plus loin, vous trouverez ce code :

GX::ActivateUImode();

GX::drawStringFontMono(V3(50, 10, 0), "ZS to move - AEQD to rotate", 60, 3, Color::Black);

Il désactive la 3D et repasse la fenêtre en mode 2D. On peut ainsi dessiner les éléments d’interface affichés sur l’écran, comme le score, la vie… Vous pouvez utiliser ici les fonctions de G2D.

Avertissement

Veillez à ne plus dessiner d’éléments 3D après avoir activé le mode UI.

Camera

La position de la caméra est décrite dans une structure Camera qui contient :

  • pos : sa position dans la scène

  • yaw : sa rotation par rapport à l’axe vertical - rotation gauche droite du joueur

  • pitch : sa rotation par rapport à l’axe horizontal - lever/baisser la tête

Vous pouvez déplacer la caméra/ le joueur dans la scène :

// rotations
float turnSpeed = 80;
if (GX::isKeyPressed(Key::Q)) G.Cam.yaw -= turnSpeed * dT;
if (GX::isKeyPressed(Key::D)) G.Cam.yaw += turnSpeed * dT;


// walk

float walkSpeed = 100;
float rad = G.Cam.yaw * PI / 180.0f;
V3 forward( sin(rad), 0,  -cos(rad)  );


if (GX::isKeyPressed(Key::Z)) G.Cam.pos = G.Cam.pos + walkSpeed *dT * forward;
if (GX::isKeyPressed(Key::S)) G.Cam.pos = G.Cam.pos - walkSpeed *dT * forward;

L’appui sur les touches Q/D fait tourner la tête à gauche et à droite par simple modification de l’angle de yaw. L’appui sur les touches Z/S fait avancer/reculer le joueur/caméra. Mais c’est un peu plus subtil. En effet, il faut calculer le vecteur correspondant à la direction où regarde la caméra :

  • pour yaw = 0 : forward = (0,0,-1) ce qui correspond à un vecteur orienté vers le fond de la scène, donc notre joueur avance

  • pour yaw = 90: forward = (1,0,0) ce qui correspond à la droite

Ainsi, on remarque que l’angle de rotation est dans le sens horaire, en augmentant l’angle yaw on tourne vers la droite.

../_images/deplacement.gif

Hiérarchie de repères

Pour organiser une scène 3D, on peut donner les coordonnées absolues de tous les objets, c’est à dire par rapport au repère d’origine. Cependant, cela devient vite difficile lorsque l’on commence à déplacer ou à tourner des objets. Il est alors plus simple d’utiliser un système de repères et de sous-repères.

La logique est la suivante :

  • GX::BeginLocalFrame() : crée un sous-repère, les transformations effectuées dans ce sous-repère n’influent que les objets créés dans ce sous-repère

  • GX::EndLocalFrame() : quitte le sous-repère pour revenir au repère courant. Les transformations effectuées dans le sous-repère sont oubliées

Les fonctions permettant de gérer les transformations sont :

  • GX::Rotate(float angleDeg, V3 axis) : déclenche une rotation autour de l’axe donné en paramètre.

  • GX::Translate(V3 v) : applique une translation d’un vecteur v.

  • GX::Scale(V3 zoom) : déclenche un changement d’échelle sur chaque direction, un coefficient par direction x/y/z.

../_images/rot.gif
  • Un premier repère, dans lequel se trouvent les trois sphères, est créé et effecue des mouvements de bas en haut

  • Chaque sphère dispose de son propre repère local dans lequel on applique une rotation

  • Les rotations sont indépendantes les unes des autres

La fonction GX::DrawAxes() dessine un repère local, elle peut être utile pour vérifier l’orientation exacte d’un sous-repère.

Object3D

Des primitives géométriques sont déjà programmées dans la classe Object3D :

Object3D CreateSphere(float R = 100.0f, float stepDeg = 10.0f, Color c= Color::Red);
Object3D CreateCube(float size = 100.0f, Color c = Color::Red);
Object3D CreateParallelogram(V3 A, V3 B, V3 C, Color c, bool flipNormal); // AB-AC

Ces fonctions peuvent être appelées n’importe où dans le code, sans qu’un premier objet3D ait été créé. On appelle cela des fonctions de classe (et non d’instance). Syntaxe :

Object3D::CreateSphere(...)

La fonction :

Object3D LoadFromPLYInAssetFolder(const std::string& filename);

permet d’importer un objet 3D au format PLY.

Avertissement

Veillez à mettre les fichiers PLY dans le répertoire assets du projet.

Pour dessiner un objet, il suffit d’appeler sa méthode draw() disposant de trois paramètres :

  • bool flat : dessine les faces en mode flat - couleur unie sur toute la face

  • bool mesh : dessiner les bords des faces, si flat = false, cela produit un rendu en fil de fer

  • bool Normals : dessine les normales - option de Debug

../_images/normal.png

Note

Un objet 3D peut être utilisé plusieurs fois dans une scène. Ainsi, une fois la sphère rouge créée, vous pouvez la dessiner à plusieurs endroits dans la scène. Dans la même logique d’optimisation, la voiture peut être chargée une seule fois dans la fonction Init() du projet et ensuite réutiliser plusieurs fois durant l’affichage. Rappelez vous GTA5, il était d’usage à un instant t de ne croiser que 5 types de véhicules différents dans les rues.