Construisons un moteur graphique 3D Rastérisation des triangles et des quadruples

Bienvenue dans la cinquième partie de notre série Construisons un moteur graphique 3D! Cette fois, nous allons construire deux nouvelles classes pour le rastérisation: une pour les triangles et une pour les quadrilatères de base. Ensuite, nous allons prendre des morceaux de ces deux classes et mettre en place une dernière classe de polygones..

Pointe: Ceci fait partie d'une série, donc si vous voulez en tirer le maximum, assurez-vous de lire les autres tutoriels qui ont précédé celui-ci..


résumer

Nous avons déjà beaucoup intégré notre moteur! Voici ce que nous avons:

  • Classes Point et Vector (les blocs de construction de notre moteur).
  • Fonctions de transformation pour nos points.
  • Une classe de caméra (définit notre fenêtre d'affichage, et élimine des points en dehors de l'écran).
  • Deux classes pour la pixellisation (segments de ligne et cercles).

Voici une référence rapide pour toutes les classes que nous avons construites:

 Classe de points Variables: num tuple [3]; // (x, y, z) Opérateurs: Point AddVectorToPoint (Vector); Point SubtractVectorFromPoint (Vector); Vecteur SubtractPointFromPoint (Point); NULL SetPointToPoint (Point); Fonctions: drawPoint; // dessine un point sur son n-ucle de position Classe Vector Variables: num tuple [3]; // (x, y, z) Opérateurs: vecteur AddVectorToVector (vecteur); Vecteur SubtractVectorFromVector (vecteur); Vecteur RotateXY (degrés); Vecteur RotateYZ (degrés); Vecteur RotateXZ (degrés); Échelle vectorielle (s0, s1, s2); // reçoit un tuple de mise à l'échelle, renvoie le vecteur mis à l'échelle Camera Class Vars: int minX, maxX; int minY, maxY; int minZ, maxZ; tableau objetsInWorld; // un tableau de tous les objets existants Fonctions: null drawScene (); // dessine tous les objets nécessaires à l'écran LineSegment Class Variables: int startX, startY; // le point de départ de notre segment de droite int endX, endY; // le point d'arrivée de notre segment de droite Fonction: array returnPointsInSegment; // tous les points situés sur ce segment de droite

Nous allons fortement compter sur le Segment de ligne classe pour créer notre Triangle et Quad cours, alors assurez-vous de vous familiariser avec elle avant de passer à autre chose.


Triangles de rastérisation

Mettre en place un Triangle classe pour le moteur est assez simple, surtout depuis le Segment de ligne la classe est l’endroit où toute notre pixellisation aura lieu. Cette classe permettra de définir trois points et tracera un segment de droite entre eux pour former le triangle complété.  

Un aperçu de base de la classe pourrait ressembler à ceci:

 Triangle Class Variables: // coordonnées des trois points de nos triangles int Point1X, Point1Y; int Point2X, Point2Y; int Point3X, Point3Y; Fonction: array returnPointsInTriangle; // tous les points dans le périmètre du triangle

Pour des raisons de standard, nous allons supposer que les trois points déclarés dans notre triangle sont dans le sens des aiguilles d'une montre..  

En utilisant notre Segment de ligne classe, alors, nous pouvons configurer notre returnPointsInTriangle () fonctionne comme ceci:

 function returnPointsInTriangle () tableau PointsToReturn; // créer un tableau temporaire pour contenir les points du triangle // Créer trois segments de ligne et stocker leurs points dans le tableau PointsToReturn.push (nouveau LineSegment (this.Point1X, this.Point1Y, this.Point2X, this.Point2Y)); PointsToReturn.push (nouveau LineSegment (this.Point2X, this.Point2Y, this.Point3X, this.Point3Y)); PointsToReturn.push (nouveau LineSegment (this.Point3X, this.Point3Y, this.Point1X, this.Point1Y)); retour (PointsToReturn); 

Pas trop mal, non? Comme nous avons déjà beaucoup de travail en cours dans notre Segment de ligne classe, il suffit de continuer à les lier pour créer des formes plus complexes. Cela facilite la création de polygones toujours plus complexes à l'écran, simplement en ajoutant plus Segments de ligne (et stocker plus de points dans la classe elle-même).

Ensuite, voyons comment ajouter plus de points à ce système en créant une classe carrée..


Se débarrasser du carré

Construire une classe pour gérer les quadrilatères ne consiste qu’à ajouter quelques éléments supplémentaires à notre Triangle classe. Avec une autre série de points, notre classe de quadrilatère ressemblerait à ceci:

 Quad Class Variables: int Point1X, Point1Y; // coordonne les quatre points de notre quadrilatère int Point2X, Point2Y; int Point3X, Point3Y; int Point4X, Point4Y; Fonction: array returnPointsInQuad; // retourne tous les points du quadrilatère

Ensuite, nous ajoutons simplement le segment de ligne supplémentaire au returnPointsInQuad fonction, comme si:

 function returnPointsInQuad () tableau PointsToReturn; // crée un tableau temporaire pour contenir les points du quad // Créez quatre segments de ligne et stockez leurs points dans le tableau PointsToReturn.push (nouveau LineSegment (this.Point1X, this.Point1Y, this.Point2X, this.Point2Y)); PointsToReturn.push (nouveau LineSegment (this.Point2X, this.Point2Y, this.Point3X, this.Point3Y)); PointsToReturn.push (nouveau LineSegment (this.Point3X, this.Point3Y, this.Point4X, this.Point4Y)); PointsToReturn.push (nouveau LineSegment (this.Point4X, this.Point4Y, this.Point1X, this.Point1Y)); retour (PointsToReturn); 

Bien que la construction de nouvelles classes comme celle-ci soit assez simple, il existe un moyen beaucoup plus simple d'encapsuler tous nos polygones dans une classe. En utilisant la magie des boucles et des tableaux, nous pouvons assembler une classe de polygone qui pourrait donner la forme de la taille souhaitée!


Où sont passés tous les Polys-Gon?

Pour créer une classe de polygones en expansion constante, nous devons faire deux choses. La première consiste à déplacer tous nos points dans un tableau, ce qui nous donnerait un aperçu de classe semblable à quelque chose comme ceci:

 Polygon Class Variables: tableau Points; // contient tous les points du polygone dans un tableau Fonction: array returnPointsInPolygon; // un tableau contenant tous les points du polygone

La seconde consiste à utiliser une boucle pour permettre à un nombre non spécifié de segments de ligne de se déplacer dans notre environnement. returnPointsInPolygon () fonction, qui pourrait ressembler à ceci:

 function returnPointsInPolygon tableau PointsToReturn; // un tableau temporaire pour contenir les points du polygone // en boucle sur tous les points du polygone, en déplaçant une paire de coordonnées à la fois (par pas de deux) pour (int x = 0; x < this.Points.length; x+=2)  if(this is not the last point)  //create a line segment between this point and the next one in the array PointsToReturn.push(new LineSegment(this.Points[x], this.Points[x+1], this.Points[x+2], this.Points[x+3]));  else if(this is the last point)  //create a line segment between this point and the first point in the array PointsToReturn.push(new LineSegment(this.Points[x-2], this.Points[x-1], this.Points[0], this.Points[1]));   //return the array of points return PointsToReturn; 

Avec cette classe ajoutée à notre moteur, nous pouvons maintenant créer n'importe quoi, d'un triangle à une abomination à 39 côtés avec la même ligne de code..


Créateur de polygone

Pour jouer avec notre nouvelle classe de polygones, créons un programme qui montre l'étendue de sa portée. Notre programme va permettre à l'utilisateur d'ajouter ou de supprimer des côtés du polygone affiché en appuyant sur les touches. Bien sûr, nous devrons fixer des limites pour le nombre de côtés que notre polygone peut avoir, car avoir moins de trois côtés ne le rendra plus un polygone. Nous n'avons pas vraiment besoin de surveiller les limites supérieures de notre polygone, car elles devraient bien évoluer. Cependant, nous allons limiter les polygones à un maximum de dix côtés, car nous allons définir ses nouveaux points à partir du code..

Les spécifications de notre programme peuvent être décomposées en ces petites parties:

  • Dessine un polygone à l'écran initialement.
  • Lorsque vous appuyez sur la touche 'a', diminuez le nombre de côtés du polygone de 1..
  • Lorsque vous appuyez sur la touche 's', augmentez le nombre de côtés du polygone de 1.
  • Empêcher le nombre de côtés du polygone de tomber en dessous de 3.
  • Empêcher le nombre de côtés du polygone de dépasser 10.

Regardons à quoi notre code pourrait ressembler:

 main // configuration pour votre API graphique préférée ici // configuration pour la saisie au clavier (peut ne pas être nécessaire) ici var camera = new Camera (); // crée une instance de notre classe camera camera.objectsInWorld []; // initialise le tableau d'objets de la caméra // configure l'espace d'affichage de la caméra camera.minX = 0; camera.maxX = screenWidth; camera.minY = 0; camera.maxY = screenHeight; camera.minZ = 0; camera.maxZ = 100; // crée un tableau de points pour chaque taille de polygone var threeSides = new Array (100,100,100,50,50,50); var fourSides = new Array (points ici); var fiveSides = new Array (points ici); var sixSides = new Array (points ici); var sevenSides = new Array (points ici); var eightSides = new Array (points ici); var nineSides = new Array (points ici); var tenSides = new Array (points ici); // stocke tous les tableaux dans un autre tableau pour un accès plus facile var sidesArray = nouveau tableau (threeSides, fourSides, fiveSides, sixSides, sevenSides, eightSides, nineSides, tenSides); // suit le nombre de points du polygone actuellement var var polygonPoints = 3; // crée le polygone initial à afficher var polygon = new Polygon (sidesArray [0] [0], sidesArray [0] [1], sidesArray [0] [2], sidesArray [0] [3], sidesArray [0 ] [4], sidesArray [0] [5],); // dessine le polygone initial sur l'écran camera.drawScene (); // tant que l'utilisateur n'a pas appuyé sur la touche d'échappement si (key! = esc) if (touche enfoncée == 'a') // si le polygone ne risque pas d'être inférieur à 3 si (polygonPoints! = 3) // réduire le nombre de points polygonPoints--; // change le polygone pour avoir le nombre correct de points // redessine la scène camera.drawScene ();  else if (touche enfoncée == 's') // si le polygone ne risque pas de dépasser 10 si (polygonPoints! = 10) // augmente le nombre de points polygonPoints ++; // change le polygone pour avoir le nombre correct de points // redessine la scène camera.drawScene (); 

Notre petit programme devrait vous permettre d'ajuster un polygone à l'écran maintenant! Découvrez la démo. Si vous souhaitez renforcer un peu ce programme, vous pouvez essayer de mettre la section de modification de polygones sous forme d'algorithme pour vous faciliter la mise à l'échelle. Je ne sais pas s'il en existe déjà un, mais si c'est le cas, vous pourriez facilement avoir un polygone à l'échelle infinie sur vos mains.!


Conclusion

Notre moteur est maintenant assez rastérisé, ce qui nous permet de créer presque toutes les formes dont nous pourrions avoir besoin (même si certaines ne sont combinées que de manière combinée). La prochaine fois, nous cesserons de dessiner des formes et de parler davantage de leurs propriétés. Si vous souhaitez apporter des couleurs à votre écran, assurez-vous de consulter la partie suivante.!