Code source d'un moteur trois dimensions - les bases

Soyez le premier à donner votre avis sur cette source.

Vue 6 621 fois - Téléchargée 457 fois

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

Ajouter un commentaire Commentaires
Messages postés
220
Date d'inscription
dimanche 7 septembre 2003
Statut
Membre
Dernière intervention
7 avril 2007

Jcd l'erreur était bien plus bête que ça, et elle ne résidait même pas de surcroît dans la formule.
Messages postés
12
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
30 août 2005

Excuse moi en, mais est-ce que tu pourrais par exemple réecrire juste la première formule du TRUC_POINT dans Truc_Tourner() ?
Messages postés
12
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
30 août 2005

Je comprends...mais je pense suivre la forme générale :
a * (t->matrice [i] [j] - t->posA) + b * (t->matrice [i] [k] - t->posB)+ t->posC ;

comment modifier cette formule pour que ce soit ça ?
Messages postés
1138
Date d'inscription
mardi 10 juin 2003
Statut
Membre
Dernière intervention
25 janvier 2009
4
dans TrucTourner()
si C est le centre de rotation alors Y =R.(X-C) + C
avec R la matrice de rotation de centre O, et justement tu oublies la composante en z du " + C"
Messages postés
12
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
30 août 2005

Où donc ?
Afficher les 6 commentaires

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.