Code source d'un moteur trois dimensions - les bases

Description

Cette source n'a d'intérêt que de ses algorithmes et non du rendu, contrairement aux autres sources que j'envoie.
Elle ne présente que les bases en création de moteur trois dimensions.

Je suis comme certains, je débute, je n'ai jamais fait de trois dimensions en dehors de l'utilisation de librairies graphiques "grand public".

Et j'espère aider certains qui souhaitent débuter un grand projet en trois dimensions (comme un jeu de voiture, un jeu de rôle).

Ce moteur n'a que peu de possibilités : créer un espace, un point, une ligne, un rectangle, se déplacer et tourner sur les trois axes.

Source / Exemple :


/* Truc est un nom générique donc à remplacer par ce que vous voulez si c'est pour une exploitation plus ambitieuse. */

/*******************************/
/* Fichier truc.h  (à découper)*/
/*******************************/

#ifndef TRUC_H

#define TRUC_H

#include <windows.h>

#include <math.h>

#define NBCHAMPS       7

#define TRUC_POINT     0

#define TRUC_LIGNE     1

#define TRUC_RECTANGLE 2

#define TRUC_ABSOLU    0

#define TRUC_RELATIF   1

#define TRUC_AXE_X     0

#define TRUC_AXE_Y     1

#define TRUC_AXE_Z     2

typedef double TRUCNB    ; 
typedef double TRUCANGLE ; 
typedef long int TRUCINT ; 

typedef TRUCNB** TRUCMAT ; 
typedef struct{
  TRUCMAT matrice ; 
  TRUCNB posx, posy, posz ; 
  TRUCINT nbvec ; 
  HWND hwnd ; 
  HDC hdc ; 
  RECT rect ; 
}HTRUC ; 

typedef struct{
        TRUCNB x, y, z ; 
}TRUCPOINT ; 

void TrucCreerEspace  (HWND hwnd, HTRUC* t, RECT rect) ; 
void TrucGenPoint     (HTRUC *t, TRUCNB x, TRUCNB y, TRUCNB z) ; 
void TrucGenLigne     (HTRUC *t, TRUCNB xs, TRUCNB ys, TRUCNB zs, TRUCNB xf, TRUCNB yf, TRUCNB zf) ; 
void TrucGenRectangle (HTRUC *t, TRUCNB xs, TRUCNB ys, TRUCNB zs, TRUCNB xf, TRUCNB yf, TRUCNB zf) ; 
void TrucGenPolygone  (HTRUC* t, TRUCPOINT* lppt, TRUCINT nb) ; 
void TrucAfficher     (HTRUC t) ; 
void TrucDeplacer     (HTRUC *t, TRUCNB x, TRUCNB y, TRUCNB z, TRUCINT mode) ; 
void TrucTourner      (HTRUC* t, TRUCINT axe, TRUCANGLE angle) ; 

#endif

/******************************/
/* Fichier truc.c (à découper)*/
/******************************/
#include "truc.h"

/* Formule magique de conversion de coordonnées en trois dimensions pour qu'elles puissent s'afficher sur un écran en deux dimensions */

#define FORM(a,b) (t.matrice [a] [b + b / 2 + 2] - (b % 2 == 0 ? t.posx : t.posy)) * (1.0 + (b % 2 == 0 ? (t.rect.right - t.rect.left) : (t.rect.bottom - t.rect.top)) / (t.matrice [a] [(b / 2 + 1) * 3 + 1] - t.posz > 0 ? t.matrice [a] [(b / 2 + 1) * 3 + 1] - t.posz : 1)) + (b % 2 == 0 ? (t.rect.right - t.rect.left) : (t.rect.bottom - t.rect.top)) / 2

void TrucCreerEspace (HWND hwnd, HTRUC* t, RECT rect) /* Créer un espace du point de vue structure de données */
{
  t->matrice     = (TRUCNB**)malloc (sizeof (TRUCNB*)) ; 

  • (t->matrice) = (TRUCNB*)malloc (sizeof (TRUCNB)) ;
t->nbvec = 1 ; t->posx = 0 ; t->posy = 0 ; t->posz = 0 ; t->rect.top = rect.top ; t->rect.bottom = rect.bottom ; t->rect.left = rect.left ; t->rect.right = rect.right ; t->hwnd = hwnd ; t->hdc = GetDC (hwnd) ; } void TrucGenPoint (HTRUC* t, TRUCNB x, TRUCNB y, TRUCNB z) /* Génerer un point dans la matrice */ { t->nbvec = t->nbvec + 1 ; t->matrice = (TRUCNB**)realloc (t->matrice, t->nbvec * sizeof (TRUCNB*)) ; t->matrice [t->nbvec - 1] = (TRUCNB*)malloc (NBCHAMPS * sizeof (TRUCNB)) ; t->matrice [t->nbvec - 1] [0] = TRUC_POINT ; t->matrice [t->nbvec - 1] [1] = x ; t->matrice [t->nbvec - 1] [2] = y ; t->matrice [t->nbvec - 1] [3] = z ; } void TrucGenLigne (HTRUC* t, TRUCNB xs, TRUCNB ys, TRUCNB zs, TRUCNB xf, TRUCNB yf, TRUCNB zf) /* Génerer une ligne dans la matrice */ { t->nbvec = t->nbvec + 1 ; t->matrice = (TRUCNB**)realloc (t->matrice, t->nbvec * sizeof (TRUCNB*)) ; t->matrice [t->nbvec - 1] = (TRUCNB*)malloc (NBCHAMPS * sizeof (TRUCNB)) ; t->matrice [t->nbvec - 1] [0] = TRUC_LIGNE ; t->matrice [t->nbvec - 1] [1] = xs ; t->matrice [t->nbvec - 1] [2] = ys ; t->matrice [t->nbvec - 1] [3] = zs ; t->matrice [t->nbvec - 1] [4] = xf ; t->matrice [t->nbvec - 1] [5] = yf ; t->matrice [t->nbvec - 1] [6] = zf ; } void TrucGenRectangle (HTRUC* t, TRUCNB xs, TRUCNB ys, TRUCNB zs, TRUCNB xf, TRUCNB yf, TRUCNB zf) /* Génerer un rectangle dans la matrice */ { t->nbvec = t->nbvec + 1 ; t->matrice = (TRUCNB**)realloc (t->matrice, t->nbvec * sizeof (TRUCNB*)) ; t->matrice [t->nbvec - 1] = (TRUCNB*)malloc (NBCHAMPS * sizeof (TRUCNB)) ; t->matrice [t->nbvec - 1] [0] = TRUC_RECTANGLE ; t->matrice [t->nbvec - 1] [1] = xs ; t->matrice [t->nbvec - 1] [2] = ys ; t->matrice [t->nbvec - 1] [3] = zs ; t->matrice [t->nbvec - 1] [4] = xf ; t->matrice [t->nbvec - 1] [5] = yf ; t->matrice [t->nbvec - 1] [6] = zf ; } void TrucGenPolygone (HTRUC* t, TRUCPOINT* lppt, TRUCINT nb) /* Génerer un polygone dans la matrice */ { TRUCINT i; t->nbvec = t->nbvec + 1 ; t->matrice = (TRUCNB**)realloc (t->matrice, t->nbvec * sizeof (TRUCNB*)) ; t->matrice [t->nbvec - 1] = (TRUCNB*)malloc ((3 * nb + 4) * sizeof (TRUCNB)) ; t->matrice [t->nbvec - 1] [0] = TRUC_POLYGONE ; t->matrice [t->nbvec - 1] [1] = 1.0 * nb ; for (i = 0 ; i < nb ; i++) { t->matrice [t->nbvec - 1] [3 * i + 2] = lppt [i].x ; t->matrice [t->nbvec - 1] [3 * i + 3] = lppt [i].y ; t->matrice [t->nbvec - 1] [3 * i + 4] = lppt [i].z ; } } /* La il serait possible de faire une fonction TrucGenBoule. */ void TrucAfficher (HTRUC t) /* Afficher tous les objets génerés avec la formule magique (differenciation selon les objets) */ { TRUCINT i = 0 ; for (i = 1 ; i < t.nbvec ; i++) { POINT lp [2] ; if (t.matrice [i] [0] == TRUC_POINT && t.matrice [i] [3] - t.posz > 0 && t.matrice [i] [3] - t.posz < 40) { lp [0].x = FORM(i, 0) ; lp [0].y = FORM(i, 1) ; lp [1].x = FORM(i, 0) + 1 ; lp [1].y = FORM(i, 1) + 1 ; Polyline (t.hdc, lp, 2) ; } if (t.matrice [i] [0] == TRUC_LIGNE) { lp [0].x = FORM(i, 0) ; lp [0].y = FORM(i, 1) ; lp [1].x = FORM(i, 2) ; lp [1].y = FORM(i, 3) ; if (t.matrice [i] [3] - t.posz >= 0 || t.matrice [i] [6] - t.posz >= 0) Polyline (t.hdc, lp, 2) ; } if (t.matrice [i] [0] == TRUC_RECTANGLE && t.matrice [i] [6] - t.posz > 0 && t.matrice [i] [3] - t.posz > 0) { POINT lp2 [4] ; lp2 [0].x = FORM(i, 0) ; lp2 [0].y = FORM(i, 1) ; lp2 [1].x = FORM(i, 2) ; lp2 [1].y = lp2 [0].y ; lp2 [2].x = lp2 [1].x ; lp2 [2].y = FORM(i, 3) ; lp2 [3].x = lp2 [0].x ; lp2 [3].y = lp2 [2].y ; Polygon (t.hdc, lp2, 4) ; } if (t.matrice [i] [0] == TRUC_POLYGONE) { TRUCINT j,k; for (j = 0 ; j < t.matrice [i] [1] - 1; j++) { POINT lp2 [2] ; k = 2 * j; lp2 [0].x = FORM(i, k) ; k++ ; lp2 [0].y = FORM(i, k) ; k++ ; lp2 [1].x = FORM(i, k) ; k++ ; lp2 [1].y = FORM(i, k) ; k++ ; if (t.matrice [i] [4 + 3 * j] - t.posz >= 0 || t.matrice [i] [7 + 3 * j] - t.posz >= 0) Polyline (t.hdc, lp2, 2) ; } } } } void TrucDeplacer (HTRUC* t, TRUCNB x, TRUCNB y, TRUCNB z, TRUCINT mode) /* Fonction de déplacement de l'oeil (trivial) */ { if (mode == TRUC_ABSOLU) { t->posx = x ; t->posy = y ; t->posz = z ; }else{ t->posx += x ; t->posy += y ; t->posz += z ; } InvalidateRect (t->hwnd, &(t->rect), TRUE) ; } void TrucTourner (HTRUC* t, TRUCINT axe, TRUCANGLE angle) /* Fonction de rotation de l'oeil (voir matrices de rotation sur un moteur de recherche) */ { TRUCINT i ; for (i = 1 ; i < t->nbvec ; i++) { if (t->matrice [i] [0] == TRUC_POINT) { if (axe == TRUC_AXE_X) { TRUCNB a = t->matrice [i] [2], b = t->matrice [i] [3] ; t->matrice [i] [2] = sin (angle) * (b - t->posz) + cos (angle) * (a - t->posy) + t->posy ; t->matrice [i] [3] = - sin (angle) * (a - t->posy) + cos (angle) * (b - t->posz) + t->posz ; } if (axe == TRUC_AXE_Y) { TRUCNB a = t->matrice [i] [1], b = t->matrice [i] [3] ; t->matrice [i] [1] = - sin (angle) * (b - t->posz) + cos (angle) * (a - t->posx) + t->posx ; t->matrice [i] [3] = sin (angle) * (a - t->posx) + cos (angle) * (b - t->posz) + t->posz ; } if (axe == TRUC_AXE_Z) { TRUCNB a = t->matrice [i] [1], b = t->matrice [i] [2] ; t->matrice [i] [1] = sin (angle) * (b - t->posy) + cos (angle) * (a - t->posx) + t->posx ; t->matrice [i] [2] = - sin (angle) * (a - t->posx) + cos (angle) * (b - t->posy) + t->posy ; } } if (t->matrice [i] [0] == TRUC_LIGNE || t->matrice [i] [0] == TRUC_RECTANGLE) { if (axe == TRUC_AXE_X) { TRUCNB a = t->matrice [i] [2], b = t->matrice [i] [3], c = t->matrice [i] [5], d = t->matrice [i] [6]; t->matrice [i] [2] = sin (angle) * (b - t->posz) + cos (angle) * (a - t->posy) + t->posy ; t->matrice [i] [3] = - sin (angle) * (a - t->posy) + cos (angle) * (b - t->posz) + t->posz ; t->matrice [i] [5] = sin (angle) * (d - t->posz) + cos (angle) * (c - t->posy) + t->posy ; t->matrice [i] [6] = - sin (angle) * (c - t->posy) + cos (angle) * (d - t->posz) + t->posz ; } if (axe == TRUC_AXE_Y) { TRUCNB a = t->matrice [i] [1], b = t->matrice [i] [3], c = t->matrice [i] [4], d = t->matrice [i] [6]; t->matrice [i] [1] = - sin (angle) * (b - t->posz) + cos (angle) * (a - t->posx) + t->posx ; t->matrice [i] [3] = sin (angle) * (a - t->posx) + cos (angle) * (b - t->posz) + t->posz ; t->matrice [i] [4] = - sin (angle) * (d - t->posz) + cos (angle) * (c - t->posx) + t->posx ; t->matrice [i] [6] = sin (angle) * (c - t->posx) + cos (angle) * (d - t->posz) + t->posz ; } if (axe == TRUC_AXE_Z) { TRUCNB a = t->matrice [i] [1], b = t->matrice [i] [2], c = t->matrice [i] [4], d = t->matrice [i] [5]; t->matrice [i] [1] = sin (angle) * (b - t->posy) + cos (angle) * (a - t->posx) + t->posx ; t->matrice [i] [2] = - sin (angle) * (a - t->posx) + cos (angle) * (b - t->posy) + t->posy ; t->matrice [i] [4] = sin (angle) * (d - t->posy) + cos (angle) * (c - t->posx) + t->posx ; t->matrice [i] [5] = - sin (angle) * (c - t->posx) + cos (angle) * (d - t->posy) + t->posy ; } } if (t->matrice [i] [0] == TRUC_POLYGONE) { TRUCINT j; for (j = 0 ; j < t->matrice [i] [1] ; j++) { if (axe == TRUC_AXE_X) { TRUCNB a = t->matrice [i] [3 * j + 3], b = t->matrice [i] [3 * j + 4] ; t->matrice [i] [3 * j + 3] = sin (angle) * (b - t->posz) + cos (angle) * (a - t->posy) + t->posy ; t->matrice [i] [3 * j + 4] = - sin (angle) * (a - t->posy) + cos (angle) * (b - t->posz) + t->posz ; } if (axe == TRUC_AXE_Y) { TRUCNB a = t->matrice [i] [3 * j + 2], b = t->matrice [i] [3 * j + 4] ; t->matrice [i] [3 * j + 2] = - sin (angle) * (b - t->posz) + cos (angle) * (a - t->posx) + t->posx ; t->matrice [i] [3 * j + 4] = sin (angle) * (a - t->posx) + cos (angle) * (b - t->posz) + t->posz ; } if (axe == TRUC_AXE_Z) { TRUCNB a = t->matrice [i] [3 * j + 2], b = t->matrice [i] [3 * j + 3] ; t->matrice [i] [3 * j + 2] = sin (angle) * (b - t->posy) + cos (angle) * (a - t->posx) + t->posx ; t->matrice [i] [3 * j + 3] = - sin (angle) * (a - t->posx) + cos (angle) * (b - t->posy) + t->posy ; } } } } InvalidateRect (t->hwnd, &(t->rect), TRUE) ; }

Conclusion :


J'ai besoin d'aide car je bloque sur plusieurs problèmes :
- Comment se programme l'affichage d'une boule ?
- Comment s'écrit l'algorithme d'élimination des faces cachées ?
- (Pourquoi ma fonction de rotation redimensionne-t-elle les objets ?) corrigé avec cette mise à jour

Je n'ai jamais programmé dans ce domaine donc à défaut, la source est classée en débutant.

J'ai inclus un "faire.bat" pour une compilation plus simple, même si la logique aurait voulu que je constitue un "makefile".

Dans l'exemple, voici les assignations des touches :
- Flèches directionnelles : se déplacer selon les axes x et z
- F1 et F2 : se déplacer selon l'axe y
Sur le pavé numérique :
- 8 et 2 : tourner par rapport à l'axe des x
- 9 et 7 : tourner par rapport à l'axe des y
- 4 et 6 : tourner par rapport à l'axe des z

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.