Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

SQUELETTE DE MOTEUR 3D


Information sur la source

Catégorie :Maths & Algorithmes Classé sous : moteur 3d, jeu vidéo, matrice, graphisme, michel Niveau : Initié Date de création : 11/11/2007 Date de mise à jour : 11/11/2007 23:55:49 Vu / téléchargé: 3 240 / 191

Note :
7 / 10 - par 1 personne
7,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (20)
Ajouter un commentaire et/ou une note

Description

Jusque de quoi faire un moteur 3d:
    - environnement de base : 5*5*5 points, on va dire que c'est une map de démonstration
    - une base globale et une base caméra
    - reception des messages du clavier (via l'API Winodws)
    - traitement des messages => déplacement dans l'environnement

Pour les solutions techniques utilisées : juste la multiplication de matrices.
Juste un point pas évident : les matrices sont 4*4 alors que on évolue dans un environnement 3*3. Pouquoi donc ?
Parce que cela nous permet de nous situer dans un "espace homogène" (je crois que ça s'appelle comme ça). En gros, la translation, très utilisée par le moteur 3d n'est pas une application linéaire (l'image de l'origine n'est pas l'origine par exemple), donc on ne pas utliliser les matrices, qui sont pourtant très pratiques.
Mais on peut se débrouiller en rajoutant une dimention, car une application linéaire dans l'espace homogène peut se retrouver être une translation dans un espace de cet espace homogène (typiquement l'espace w=1 mais tous les espaces qui ne contiennent pas l'origine à mon avis).
Génial, non ? Sinon, il vaut mieux essayer à comprendre avec un plan, c'est plus facile.
 

Source

  • // Moteur3D - Mon moteur 3D
  • // Commandé au clavier par les touches flèchées et par les touches z, q, s, d, CapsLock, Ctrl, Insert, f.
  • // Traite les messages signalant l'appui d'une touche.
  • #include <windows.h>
  • #include <math.h>
  • /********************************* DEFINITIONS ********************************/
  • #define X 0
  • #define Y 1
  • #define Z 2
  • /***************************** VARIABLES UTILISEES ****************************/
  • HINSTANCE hInstance; // Handle du programme
  • double distance_ecran = 600; // Distance des yeux à l'écran (mm).
  • double largeur_ecran_metrique = 375; // En mm.
  • double hauteur_ecran_metrique = 300; // En mm.
  • double largeur_ecran_pixel = 1280; // En pixels.
  • double hauteur_ecran_pixel = 1024; // En pixels.
  • double matrice_globale_camera [16]= { // Matrice de changement de base : base globale -> base camera
  • 1, 0, 0, 0,
  • 0, 1, 0, 0,
  • 0, 0, 1, 0,
  • 0, 0, 0, 1}; // matrice identité
  • double coefficient_translation = 1; // Longueur de la translation élementaire (appui d'une touche) en mm
  • double coefficient_rotation = 10; // Angle d'une rotation élementaire (appui d'une touche) en 10^-3 rad
  • double grille [5*5*5*4]; // Plus tard, une grille de 5 * 5 * 5 points
  • // Callback
  • LRESULT CALLBACK WindowMainProcedure (HWND, UINT, WPARAM, LPARAM);
  • // Traitement et affichage de l'image.
  • void ImageTraitement (HWND hwnd);
  • // Translate la base caméra (pour faire une nouvelle base caméra)
  • void TranslationCamera (long axe, double longueur);
  • // Rotationne la base caméra (pour faire une nouvelle base caméra)
  • void RotationCamera (long axe, double angle);
  • // Multiplie une matrice 1*4 par une matrice 4*4.
  • void MatriceMultiplication_14_44 (double matrice_1 [4], double matrice_2 [16], double matrice_s [4]);
  • // Multiplie une matrice 4*4 par une matrice 4*4.
  • void MatriceMultiplication_44_44 (double matrice_1 [16], double matrice_2 [16], double matrice_s [16]);
  • /********************************** FONCTIONS *********************************/
  • int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
  • {
  • MSG messages;
  • WNDCLASSEX wincl;
  • HWND hwnd;
  • hInstance = hThisInstance;
  • wincl.cbSize = sizeof (WNDCLASSEX);
  • wincl.style = CS_HREDRAW | CS_VREDRAW;
  • wincl.lpfnWndProc = WindowMainProcedure;
  • wincl.cbClsExtra = 0;
  • wincl.cbWndExtra = 0;
  • wincl.hInstance = hInstance;
  • wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  • wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
  • wincl.hbrBackground = GetStockObject (BLACK_BRUSH);
  • wincl.lpszMenuName = NULL;
  • wincl.lpszClassName = "MainClass";
  • wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
  • if (!RegisterClassEx (&wincl)){
  • MessageBox (NULL, "Erreur dans l'enregistrement de la classe \"MainClass\".",
  • "Erreur", MB_OK | MB_ICONWARNING);
  • return 0;}
  • hwnd = CreateWindowEx (0, "MainClass", "Moteur 3D",
  • WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
  • 500, 300, HWND_DESKTOP, NULL, hInstance, NULL);
  • if (!hwnd){
  • MessageBox (NULL, "Erreur dans la création de la fenêtre.",
  • "Erreur", MB_OK | MB_ICONWARNING);
  • return 0;}
  • while (GetMessage (&messages, NULL, 0, 0))
  • {
  • DispatchMessage(&messages);
  • }
  • UNREFERENCED_PARAMETER(hPrevInstance);
  • UNREFERENCED_PARAMETER(lpszArgument);
  • UNREFERENCED_PARAMETER(nFunsterStil);
  • return messages.wParam;
  • }
  • LRESULT CALLBACK WindowMainProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  • {
  • switch (message) {
  • case WM_CREATE:
  • {
  • long i, j, k;
  • // Initialisation des points.
  • for (i=0; i<5; i++){
  • for (j=0; j<5; j++){
  • for (k=0; k<5; k++){
  • grille [i*5*5*4 + j*5*4 + k*4] = 5 * i;
  • grille [i*5*5*4 + j*5*4 + k*4 + 1] = 5 * j;
  • grille [i*5*5*4 + j*5*4 + k*4 + 2] = 100 + (5 * k);// Calcul des coordonnées
  • grille [i*5*5*4 + j*5*4 + k*4 + 3] = 1; // Tous ces points appatiennent à l'espace de
  • // coordonnée w=1 dans l'espace homogène (on rajoute cette 4ème dimention pour utiliser les
  • // propriétés d'une application linéaire avec la translation (application non linéaire))
  • }
  • }
  • }
  • }
  • return 0;
  • case WM_KEYDOWN:
  • {
  • BOOL modif = FALSE;
  • switch (wParam){
  • // translations avec les touche fléchées et Ctrl et Insert
  • case VK_LEFT:
  • TranslationCamera (X, lParam & 0xFFFF);
  • modif = TRUE;
  • break;
  • case VK_RIGHT:
  • TranslationCamera (X, -(lParam & 0xFFFF));
  • modif = TRUE;
  • break;
  • case VK_UP:
  • TranslationCamera (Y, -(lParam & 0xFFFF));
  • modif = TRUE;
  • break;
  • case VK_DOWN:
  • TranslationCamera (Y, lParam & 0xFFFF);
  • modif = TRUE;
  • break;
  • case VK_CONTROL:
  • TranslationCamera (Z, lParam & 0xFFFF);
  • modif = TRUE;
  • break;
  • case VK_NUMPAD0:
  • TranslationCamera (Z, -(lParam & 0xFFFF));
  • modif = TRUE;
  • break;
  • // rotations avec q, d, z, s, CapsLock et f
  • case 'Q':
  • RotationCamera (Y, lParam & 0xFFFF);
  • modif = TRUE;
  • break;
  • case 'D':
  • RotationCamera (Y, -(lParam & 0xFFFF));
  • modif = TRUE;
  • break;
  • case 'Z':
  • RotationCamera (X, lParam & 0xFFFF);
  • modif = TRUE;
  • break;
  • case 'S':
  • RotationCamera (X, -(lParam & 0xFFFF));
  • modif = TRUE;
  • break;
  • case VK_CAPITAL:
  • RotationCamera (Z, lParam & 0xFFFF);
  • modif = TRUE;
  • break;
  • case 'F':
  • RotationCamera (Z, -(lParam & 0xFFFF));
  • modif = TRUE;
  • break;
  • }
  • if (modif == TRUE){
  • // Demande à redessiner l'image.
  • InvalidateRect (hwnd, NULL, TRUE);
  • }
  • }
  • return 0;
  • case WM_PAINT:
  • ImageTraitement (hwnd);
  • return 0;
  • case WM_DESTROY:
  • PostQuitMessage (0);
  • break;
  • default:
  • return DefWindowProc (hwnd, message, wParam, lParam);
  • }
  • return 0;
  • }
  • void ImageTraitement (HWND hwnd)
  • {
  • HDC hdc;
  • PAINTSTRUCT ps;
  • RECT ClientRect;
  • long i;
  • double coord_3d [4];
  • double coord_2d [2];
  • GetClientRect (hwnd, &ClientRect);
  • hdc = BeginPaint (hwnd, &ps);
  • // Traitement des points un par un.
  • for (i=0; i<5*5*5; i++){
  • // Calcule les coordonnées du point dans la base caméra.
  • MatriceMultiplication_14_44 (grille + (i*4), matrice_globale_camera, coord_3d);
  • if (coord_3d [2] > 0){
  • // Calcule les coordonnées dans le plan vituel (en mm).
  • coord_2d [0] = distance_ecran * (coord_3d [0] / coord_3d [2]);
  • coord_2d [1] = distance_ecran * (coord_3d [1] / coord_3d [2]);
  • // Calcule les coordonnées dans le plan réel (en pixel)
  • coord_2d [0] *= largeur_ecran_pixel / largeur_ecran_metrique;
  • coord_2d [1] *= hauteur_ecran_pixel / hauteur_ecran_metrique;
  • // Centre les cordonnées
  • coord_2d [0] += ClientRect.right / 2;
  • coord_2d [1] = (ClientRect.bottom / 2) - coord_2d [1];
  • // Affiche le point
  • SetPixel (hdc, (long)(coord_2d [0]), (long)(coord_2d [1]), 0x00FFFFFF);
  • }
  • }
  • EndPaint (hwnd, &ps);
  • }
  • void TranslationCamera (long axe, double longueur)
  • {
  • double matrice_translation [16]= {
  • 1, 0, 0, 0,
  • 0, 1, 0, 0,
  • 0, 0, 1, 0,
  • 0, 0, 0, 1}; // matrice identité
  • double matrice_tampon [16];
  • long i;
  • // Calcule la matrice de translation
  • matrice_translation [(axe * 4) + 3] = longueur * coefficient_translation;
  • // Effectue la translation
  • MatriceMultiplication_44_44 (matrice_globale_camera, matrice_translation, matrice_tampon);
  • // Remplace la matrice de changement de base
  • for (i=0; i<16; i++){
  • matrice_globale_camera [i] = matrice_tampon [i];}
  • }
  • void RotationCamera (long axe, double angle)
  • {
  • double matrice_rotation [16]= {
  • 1, 0, 0, 0,
  • 0, 1, 0, 0,
  • 0, 0, 1, 0,
  • 0, 0, 0, 1}; // matrice identité
  • double matrice_tampon [16];
  • double sinus, cosinus;
  • long i;
  • // Calcule la matrice de rotation
  • sinus = sin (angle * coefficient_rotation / 1000);
  • cosinus = cos (angle * coefficient_rotation / 1000);
  • switch (axe) {
  • case X:
  • matrice_rotation [5] = matrice_rotation [10] = cosinus;
  • // i = (0; 1; 0); j = (0; 0; 1)
  • matrice_rotation [6] = -sinus;
  • matrice_rotation [9] = sinus;
  • break;
  • case Y:
  • matrice_rotation [0] = matrice_rotation [10] = cosinus;
  • // i = (0; 0; 1); j = (1; 0; 0)
  • matrice_rotation [8] = -sinus;
  • matrice_rotation [2] = sinus;
  • break;
  • case Z:
  • matrice_rotation [0] = matrice_rotation [5] = cosinus;
  • // i = (1; 0; 0); j = (0; 1; 0)
  • matrice_rotation [1] = -sinus;
  • matrice_rotation [4] = sinus;
  • break;
  • }
  • // Effectue la rotation
  • MatriceMultiplication_44_44 (matrice_globale_camera, matrice_rotation, matrice_tampon);
  • // Remplace la matrice de changement de base
  • for (i=0; i<16; i++){
  • matrice_globale_camera [i] = matrice_tampon [i];}
  • }
  • void MatriceMultiplication_14_44 (double matrice_1 [4], double matrice_2 [16], double matrice_s [4])
  • {
  • matrice_s [0] =
  • (matrice_1 [0] * matrice_2 [0]) +
  • (matrice_1 [1] * matrice_2 [1]) +
  • (matrice_1 [2] * matrice_2 [2]) +
  • (matrice_1 [3] * matrice_2 [3]);
  • matrice_s [1] =
  • (matrice_1 [0] * matrice_2 [4]) +
  • (matrice_1 [1] * matrice_2 [5]) +
  • (matrice_1 [2] * matrice_2 [6]) +
  • (matrice_1 [3] * matrice_2 [7]);
  • matrice_s [2] =
  • (matrice_1 [0] * matrice_2 [8]) +
  • (matrice_1 [1] * matrice_2 [9]) +
  • (matrice_1 [2] * matrice_2 [10]) +
  • (matrice_1 [3] * matrice_2 [11]);
  • matrice_s [3] =
  • (matrice_1 [0] * matrice_2 [12]) +
  • (matrice_1 [1] * matrice_2 [13]) +
  • (matrice_1 [2] * matrice_2 [14]) +
  • (matrice_1 [3] * matrice_2 [15]);
  • }
  • void MatriceMultiplication_44_44 (double matrice_1 [16], double matrice_2 [16], double matrice_s [16])
  • {
  • long i, j;
  • for (j=0; j<16; j+=4){
  • for (i=0; i<4; i++){
  • matrice_s [j + i] =
  • (matrice_1 [i] * matrice_2 [j]) +
  • (matrice_1 [i + 4] * matrice_2 [j + 1]) +
  • (matrice_1 [i + 8] * matrice_2 [j + 2]) +
  • (matrice_1 [i + 12] * matrice_2 [j + 3]);
  • }
  • }
  • }
// Moteur3D - Mon moteur 3D
// Commandé au clavier par les touches flèchées et par les touches z, q, s, d, CapsLock, Ctrl, Insert, f.
// Traite les messages signalant l'appui d'une touche.

#include <windows.h>
#include <math.h>

/********************************* DEFINITIONS ********************************/
#define X 0
#define Y 1
#define Z 2

/***************************** VARIABLES UTILISEES ****************************/

HINSTANCE hInstance;					// Handle du programme

double distance_ecran = 600;			// Distance des yeux à l'écran (mm).
double largeur_ecran_metrique = 375;	// En mm.
double hauteur_ecran_metrique = 300;	// En mm.
double largeur_ecran_pixel = 1280;		// En pixels.
double hauteur_ecran_pixel = 1024;		// En pixels.
double matrice_globale_camera [16]= {	// Matrice de changement de base : base globale -> base camera
	1, 0, 0, 0,
	0, 1, 0, 0,
	0, 0, 1, 0,
	0, 0, 0, 1};   // matrice identité
double coefficient_translation = 1;		// Longueur de la translation élementaire (appui d'une touche) en mm
double coefficient_rotation = 10;		// Angle d'une rotation élementaire (appui d'une touche) en 10^-3 rad
double grille [5*5*5*4];				// Plus tard, une grille de 5 * 5 * 5 points

//  Callback
LRESULT CALLBACK WindowMainProcedure (HWND, UINT, WPARAM, LPARAM);

// Traitement et affichage de l'image.
void ImageTraitement (HWND hwnd);

// Translate la base caméra (pour faire une nouvelle base caméra)
void TranslationCamera (long axe, double longueur);

// Rotationne la base caméra (pour faire une nouvelle base caméra)
void RotationCamera (long axe, double angle);

// Multiplie une matrice 1*4 par une matrice 4*4.
void MatriceMultiplication_14_44 (double matrice_1 [4], double matrice_2 [16], double matrice_s [4]);

// Multiplie une matrice 4*4 par une matrice 4*4.
void MatriceMultiplication_44_44 (double matrice_1 [16], double matrice_2 [16], double matrice_s [16]);


/********************************** FONCTIONS *********************************/

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
{
    MSG messages;
    WNDCLASSEX wincl;
    HWND hwnd;

	hInstance = hThisInstance;
	
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.style = CS_HREDRAW | CS_VREDRAW;
    wincl.lpfnWndProc = WindowMainProcedure;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hInstance = hInstance;
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.hbrBackground = GetStockObject (BLACK_BRUSH);
    wincl.lpszMenuName = NULL;
    wincl.lpszClassName = "MainClass";
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);

    if (!RegisterClassEx (&wincl)){
		MessageBox (NULL, "Erreur dans l'enregistrement de la classe \"MainClass\".", 
			"Erreur", MB_OK | MB_ICONWARNING);
        return 0;}

    hwnd = CreateWindowEx (0, "MainClass", "Moteur 3D",
		WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
		500, 300, HWND_DESKTOP, NULL, hInstance, NULL);

	if (!hwnd){
		MessageBox (NULL, "Erreur dans la création de la fenêtre.", 
			"Erreur", MB_OK | MB_ICONWARNING);
        return 0;}

    while (GetMessage (&messages, NULL, 0, 0))
    {
        DispatchMessage(&messages);
    }

	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpszArgument);
	UNREFERENCED_PARAMETER(nFunsterStil);
    return messages.wParam;
}




LRESULT CALLBACK WindowMainProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {
		case WM_CREATE:
			{
				long i, j, k;
				// Initialisation des points.
				for (i=0; i<5; i++){
					for (j=0; j<5; j++){
						for (k=0; k<5; k++){
grille [i*5*5*4 + j*5*4 + k*4] = 5 * i;
grille [i*5*5*4 + j*5*4 + k*4 + 1] = 5 * j;
grille [i*5*5*4 + j*5*4 + k*4 + 2] = 100 + (5 * k);// Calcul des coordonnées
grille [i*5*5*4 + j*5*4 + k*4 + 3] = 1;	// Tous ces points appatiennent à l'espace de
	// coordonnée w=1 dans l'espace homogène (on rajoute cette 4ème dimention pour utiliser les
	// propriétés d'une application linéaire avec la translation (application non linéaire))
						}
					}
				}
			}
			return 0;

		case WM_KEYDOWN:
		{
			BOOL modif = FALSE;
			
			switch (wParam){
				// translations avec les touche fléchées et Ctrl et Insert
				case VK_LEFT:
					TranslationCamera (X, lParam & 0xFFFF);
					modif = TRUE;
					break;

				case VK_RIGHT:
					TranslationCamera (X, -(lParam & 0xFFFF));
					modif = TRUE;
					break;

				case VK_UP:
					TranslationCamera (Y, -(lParam & 0xFFFF));
					modif = TRUE;
					break;

				case VK_DOWN:
					TranslationCamera (Y, lParam & 0xFFFF);
					modif = TRUE;
					break;

				case VK_CONTROL:
					TranslationCamera (Z, lParam & 0xFFFF);
					modif = TRUE;
					break;

				case VK_NUMPAD0:
					TranslationCamera (Z, -(lParam & 0xFFFF));
					modif = TRUE;
					break;

				// rotations avec q, d, z, s, CapsLock et f
				case 'Q':
					RotationCamera (Y, lParam & 0xFFFF);
					modif = TRUE;
					break;

				case 'D':
					RotationCamera (Y, -(lParam & 0xFFFF));
					modif = TRUE;
					break;

				case 'Z':
					RotationCamera (X, lParam & 0xFFFF);
					modif = TRUE;
					break;

				case 'S':
					RotationCamera (X, -(lParam & 0xFFFF));
					modif = TRUE;
					break;

				case VK_CAPITAL:
					RotationCamera (Z, lParam & 0xFFFF);
					modif = TRUE;
					break;

				case 'F':
					RotationCamera (Z, -(lParam & 0xFFFF));
					modif = TRUE;
					break;
			}
			
			if (modif == TRUE){
				// Demande à redessiner l'image.
				InvalidateRect (hwnd, NULL, TRUE);
			}
		}
			return 0;


		case WM_PAINT:
			ImageTraitement (hwnd);
			return 0;
			
        case WM_DESTROY:
            PostQuitMessage (0);       
            break;

        default:                   
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}




void ImageTraitement (HWND hwnd)
{
	HDC hdc;
	PAINTSTRUCT ps;
	RECT ClientRect;
	long i;
	double coord_3d [4];
	double coord_2d [2];

	GetClientRect (hwnd, &ClientRect);
	
	hdc = BeginPaint (hwnd, &ps);
	// Traitement des points un par un.
	for (i=0; i<5*5*5; i++){
		// Calcule les coordonnées du point dans la base caméra.
		MatriceMultiplication_14_44 (grille + (i*4), matrice_globale_camera, coord_3d);

		if (coord_3d [2] > 0){
			// Calcule les coordonnées dans le plan vituel (en mm).
			coord_2d [0] = distance_ecran * (coord_3d [0] / coord_3d [2]);
			coord_2d [1] = distance_ecran * (coord_3d [1] / coord_3d [2]);
			
			// Calcule les coordonnées dans le plan réel (en pixel)
			coord_2d [0] *= largeur_ecran_pixel / largeur_ecran_metrique;
			coord_2d [1] *= hauteur_ecran_pixel / hauteur_ecran_metrique;

			// Centre les cordonnées
			coord_2d [0] += ClientRect.right / 2;
			coord_2d [1] = (ClientRect.bottom / 2) - coord_2d [1];
			
			// Affiche le point
			SetPixel (hdc, (long)(coord_2d [0]), (long)(coord_2d [1]), 0x00FFFFFF);
		}
	}
	EndPaint (hwnd, &ps);
}


void TranslationCamera (long axe, double longueur)
{
	double matrice_translation [16]= {
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 1, 0,
		0, 0, 0, 1};   // matrice identité
	double matrice_tampon [16];
	long i;

	// Calcule la matrice de translation
	matrice_translation [(axe * 4) + 3] = longueur * coefficient_translation;

	// Effectue la translation
	MatriceMultiplication_44_44 (matrice_globale_camera, matrice_translation, matrice_tampon);

	// Remplace la matrice de changement de base
	for (i=0; i<16; i++){
		matrice_globale_camera [i] = matrice_tampon [i];}
}


void RotationCamera (long axe, double angle)
{
	double matrice_rotation [16]= {
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 1, 0,
		0, 0, 0, 1};   // matrice identité
	double matrice_tampon [16];
	double sinus, cosinus;
	long i;

	// Calcule la matrice de rotation
	sinus = sin (angle * coefficient_rotation / 1000);
	cosinus = cos (angle * coefficient_rotation / 1000);
	switch (axe) {
		case X:
			matrice_rotation [5] = matrice_rotation [10] = cosinus; 
				// i = (0; 1; 0); j = (0; 0; 1)
			matrice_rotation [6] = -sinus;
			matrice_rotation [9] = sinus;
			break;

		case Y:
			matrice_rotation [0] = matrice_rotation [10] = cosinus; 
				// i = (0; 0; 1); j = (1; 0; 0)
			matrice_rotation [8] = -sinus;
			matrice_rotation [2] = sinus;
			break;

		case Z:
			matrice_rotation [0] = matrice_rotation [5] = cosinus; 
				// i = (1; 0; 0); j = (0; 1; 0)
			matrice_rotation [1] = -sinus;
			matrice_rotation [4] = sinus;
			break;
	}

	// Effectue la rotation
	MatriceMultiplication_44_44 (matrice_globale_camera, matrice_rotation, matrice_tampon);

	// Remplace la matrice de changement de base
	for (i=0; i<16; i++){
		matrice_globale_camera [i] = matrice_tampon [i];}
}


void MatriceMultiplication_14_44 (double matrice_1 [4], double matrice_2 [16], double matrice_s [4])
{
	matrice_s [0] =
		(matrice_1 [0] * matrice_2 [0]) +
		(matrice_1 [1] * matrice_2 [1]) +
		(matrice_1 [2] * matrice_2 [2]) +
		(matrice_1 [3] * matrice_2 [3]);
	matrice_s [1] =
		(matrice_1 [0] * matrice_2 [4]) +
		(matrice_1 [1] * matrice_2 [5]) +
		(matrice_1 [2] * matrice_2 [6]) +
		(matrice_1 [3] * matrice_2 [7]);
	matrice_s [2] =
		(matrice_1 [0] * matrice_2 [8]) +
		(matrice_1 [1] * matrice_2 [9]) +
		(matrice_1 [2] * matrice_2 [10]) +
		(matrice_1 [3] * matrice_2 [11]);
	matrice_s [3] =
		(matrice_1 [0] * matrice_2 [12]) +
		(matrice_1 [1] * matrice_2 [13]) +
		(matrice_1 [2] * matrice_2 [14]) +
		(matrice_1 [3] * matrice_2 [15]);
}


void MatriceMultiplication_44_44 (double matrice_1 [16], double matrice_2 [16], double matrice_s [16])
{
	long i, j;
	
	for (j=0; j<16; j+=4){
		for (i=0; i<4; i++){
			matrice_s [j + i] =
				(matrice_1 [i] 		* matrice_2 [j]) 		+
				(matrice_1 [i + 4] 	* matrice_2 [j + 1])	+
				(matrice_1 [i + 8]	* matrice_2 [j + 2])	+
				(matrice_1 [i + 12]	* matrice_2 [j + 3]);
		}
	}
}

Conclusion

Si j'ai le temps, j'essairai de l'améliorer en mettant du multithreading, en utilisant la souris, ... j'attend aussi vos remarques.
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  • main.cTélécharger ce fichier [Réservé aux membres club]Voir ce fichier10 184 octets
  • Makefile.winTélécharger ce fichier [Réservé aux membres club]897 octets
  • Moteur3D.devTélécharger ce fichier [Réservé aux membres club]1 596 octets

Télécharger le zip

Historique

11 novembre 2007 23:52:18 :
Faute d'orthographe; remise en forme.
11 novembre 2007 23:55:49 :
Correction de fautes d'orthographe; remise en forme

Commentaires et avis

signaler à un administrateur
Commentaire de shenron666 le 12/11/2007 21:12:15 7/10

Waouh un moteur 3D qui tient en 10Ko de code et sur un seul fichier svp !!! impressionant
Sinon la gestion des ombres, des collisions, du son, de l'interaction bref tout ce qui fait un moteur... c'est où ?
Je me demande pourquoi tout le monde utilise le terme "moteur 3d" dès qu'ils arrivent à afficher 3 triangles à l'écran.

Trève de plaisanterie, pour le côté éducatif du calcul de matrices dans un espace homogène en 3 dimensions c'est un bon petit exemple
tu devrais te mettre à directx ou opengl, tu t'amuserais plus

signaler à un administrateur
Commentaire de _michel le 12/11/2007 21:50:50

Shenron666 : "Sinon la gestion des ombres, des collisions, du son, de l'interaction bref tout ce qui fait un moteur... c'est où ?"
Justement, mon but n'est pas de faire un moteur physique (c'est de ça que tu veux parler je crois), je préfère les maths (c'est aussi pour ça que je poste dans Maths).

Et vous parlez de librairies graphiques. Mais mon but c'est avant tout d'apprendre (quand tu parle du coté éducatif tu es en plein dedans), et laisser faire tout ce boulot par autre chose, ça m'interesse pas. En plus, si on retire tout ça, il reste quoi ? Juste le scénario et les monstres pour tirer dessus, mais ça Quake III le fait déjà très bien.

Après on peut dire que je ferais de ma vie que de réinventer la roue, mais si je m'éclate... tant que je suis pas obligé de manger avec ça.

signaler à un administrateur
Commentaire de pgl10 le 13/11/2007 10:06:13

Ce programme fonctionne bien.

Mais pourquoi indiquer : "Jusque de quoi faire un moteur 3d" ? Il ne semble pas qu'il aille jusque là !
De plus, pourquoi indiquer : "Niveau : Initié" ?

Ce programme peut servir à démontrer un emploi élémentaire des coordonnées homogènes pour ceux qui veulent examiner cela de manière pratique.

signaler à un administrateur
Commentaire de Cyberboy2054 le 13/11/2007 19:28:06

Bah la notion de matrice c'est pas non plus à la portée du premier venu je pense.
Mais bon c'est vrai que pour mettre "moteur 3d" faudrait qu'il y ait un peu plus:lignes (pas tres difficile), triangles plein, eclairage (la galere commence ici), puis ben pour du temps reel optimiser le rendu: eviter le pixel overdraw (dessiner inutilement 2 fois un meme pixel, dans le cas ou 2 triangles sont l'un derriere l'autre), trier les faces par rapport a la possibilité de vision (frustum culling, octree)
Ca y est, tu a plein de mots à googler :) Bon courage ;)

signaler à un administrateur
Commentaire de luhtor le 13/11/2007 19:55:52

Quelques lignes de plus ?

Un moteur 3D, c'est des centaines de milliers de lignes.

signaler à un administrateur
Commentaire de _michel le 13/11/2007 20:05:50

J'ai pleins de mots à googler, et j'ai pas mal de boulot pour que ça faisse un "vrai" moteur 3d. Tout à fait d'accord.

En fait si j'ai poster mon code, c'est justement parce que un moteur 3d qui sert à quelque chose ça fait des miliers de lignes. Donc, pour quelqu'un qui veut pas s'arracher les cheveux 10 ans à comprendre un moteur 3d libre, il faut mieux un exemple de 350 lignes qui se balaye rapidement... ne m'en veuillez pas si vous pouvez faire mieux.
De toute façon, un moteur 3d est théoriquement un programme qui transforme une situation 3d en une image 2d. Si ce programme ne remplie pas les conditions, proposez-moi un titre plus explicite que : Squelette de moteur 3d.

J'ai mis ça en initié, parce que je sais pas ce que ça veut dire : on parle du nombre de ligne (0-500 : débutant, 500-1500 : initié, ... auquel cas je me suis trompé) ou alors de la complexité du code (45-120mn pour comprendre le code en sa totalité, ..., la je n'en suis pas loin pour quelqu'un qui ne connait pas l'API Windows et les matrices). Je met initié, comme ça je me trompe le moins possible.

signaler à un administrateur
Commentaire de shenron666 le 13/11/2007 20:54:54

Michel, relis mon commentaire, je suis loin, très loin de parler de moteur physique. Déjà tu n'as pas la notion de ce qu'est un "moteur" en informatique. Ton bout de code est juste un exemple de "calcul de matrices dans un espace homogène en 3 dimensions". C'est même pas 1% de ce qui constitue un moteur 3d.
ps : Tu auras au moins réussi à impressionner Metanil, même si ce n'est pas un exploit en soi.

signaler à un administrateur
Commentaire de _michel le 13/11/2007 21:29:06

"Sinon la gestion des ombres, des collisions, du son, de l'interaction bref tout ce qui fait un moteur... c'est où ?"

ombres : OK, c'est du visuel.
Mais le reste (son, interactions, collisions), c'est moteur son et moteur physique.
source : Wikipedia (à moins que j'ai mal lu)

Sinon, mon "bout de code" compile et marche indépendament! Ce n'est pas un 'orteil' de moteur 3d, c'est un 'squelette' (lol).

"Déjà tu n'as pas la notion de ce qu'est un "moteur" en informatique.[...]C'est même pas 1% de ce qui constitue un moteur 3d." Je suis pas en foncièrement en désaccord, mais j'essai d'apprendre et c'est déjà une base pour continuer.

En plus, vous avez déjà vu une source simple comme la mienne? Moi, non, c'est pour ça que j'ai posté. J'espère juste que ça va servir à quelqu'un.

Metanil : et toi, tu joue à quoi?

signaler à un administrateur
Commentaire de BruNews le 14/11/2007 00:36:36 administrateur CS

POUR LE FUN... on booste ta MatriceMultiplication_14_44().

Listing compilo en full optim et SSE2:
- 50 instructions dont 16 MUL et 36 accès mémoire.

Listing dessous:
- 36 instructions dont 8 MUL et 12 accès mémoire.

void __fastcall MatriceMultipli_14_44ASM(double *m_1, double *m_2, double *m_s)
{
  __asm {
    movapd    xmm2, [ecx]
    movapd    xmm3, [ecx+16]
    mov       eax, [esp+4]
    movapd    xmm0, xmm2
    movapd    xmm1, xmm3
    mulpd     xmm0, [edx]
    mulpd     xmm1, [edx+16]
    movapd    xmm4, xmm2
    movapd    xmm5, xmm3
    addpd     xmm0, xmm1
    mulpd     xmm4, [edx+32]
    mulpd     xmm5, [edx+48]
    movapd    xmm1, xmm0
    addpd     xmm4, xmm5
    psrldq    xmm1, 8
    unpcklpd  xmm5, xmm4
    addsd     xmm1, xmm0
    addpd     xmm5, xmm4
    movapd    xmm0, xmm2
    movsd     xmm5, xmm1
    movapd    xmm4, xmm3
    mulpd     xmm0, [edx+64]
    mulpd     xmm4, [edx+80]
    movapd    [eax], xmm5
    addpd     xmm0, xmm4
    mulpd     xmm2, [edx+96]
    mulpd     xmm3, [edx+112]
    movapd    xmm4, xmm0
    addpd     xmm2, xmm3
    psrldq    xmm4, 8
    unpcklpd  xmm3, xmm2
    addsd     xmm0, xmm4
    addpd     xmm3, xmm2
    movsd     xmm3, xmm0
    movapd    [eax+16], xmm3
    ret       4
  }
}

Tu auras au moins une fonction de moteur qui a de la reprise et du couple.
Bonne nuit à tous.

signaler à un administrateur
Commentaire de Cyberboy2054 le 14/11/2007 18:56:42

Il correspond à quoi le 4 que tu renvoie ?

signaler à un administrateur
Commentaire de BruNews le 14/11/2007 19:02:52 administrateur CS

La question serait donc:
Que fait 'ret 4' ?
'ret' est l'instruction de remise dans EIP (pointeur d'instruction) de ce qui est en [esp] provoquant la suite du prog à l'adresse EIP, ce qui suit est le nbr d'octets à remonter ESP (pointeur de pile) après le POPage de EIP.

signaler à un administrateur
Commentaire de _michel le 17/11/2007 23:52:22

Merci beaucoup, c'est une amélioration conséquente (c'est sur qu'avec des boucles imbriquées et un calcul pour chaque membre de la matrice résultat ce n'est pas du tout optimisé).

Je laisse le même code ici, pour que ça reste compréhensible!

signaler à un administrateur
Commentaire de BruNews le 18/11/2007 00:23:34 administrateur CS

ATTENTION que je transfére par 128 bits en mode aligné!!! ce qui implique que les matrices doivent être correctement placées sur des adresses multiples de 16 sinon badaboum le prog. Suffit d'utiliser VirtualAlloc pour avoir un alignement correct.

signaler à un administrateur
Commentaire de _michel le 18/11/2007 20:56:15

Ok, je comprend pourquoi on dit que LocalAlloc () est démodée.

xmm = registre 128 bits, ou je n'ai rien compris.
Si je veut agir sur des long (4 octets, 32 bits) et non sur des mots de 16 octets, il n'y pas grand chose à modifier :
        utiliser mov au lieu de movadp
        utiliser les registre du coprossesseur arithmétique au lieu des registres xmm (Donc utiliser les opérations du coprossesseur)

Pour ma culture générale, XMM est bien une technologie intel ?

signaler à un administrateur
Commentaire de BruNews le 18/11/2007 21:32:35 administrateur CS

Oui, ça s'appelle SSE.

signaler à un administrateur
Commentaire de Arnaud16022 le 19/11/2007 01:03:27

michel :

je suis entièrement d'accord avec toi point de vue intérêt mathématique pur.
C'est très intéressant, j'y ai moi-même passé un certain temps.

Cependant, l'opposition qui ressort des commentaires vient de ta notion de "moteur 3D".
Un moteur 3D n'est pas "quelque chose" ( je suis volontairement flou ) qui t'affiche des polys à l'écran.
Un moteur 3D est un programme d'une complexité redoutable, qui pour simplifier à l'extrême, sélectionne les polygones que le "quelque chose" doit afficher, et qui lui dit comment le faire.

A propos du quelque chose :
Soit tu le fais en software. Tout en CPU. Ca s'appelle MESA sous Linux, ya d'autres solutions sous Win32 je crois.
Soit tu le fais en hardware. Avec ta carte graphique, que tu lui dis " affiche moi tel poly ", et il le fait à la hauteur de 3 millions de fois par secondes environ, pendant que toi tu fais autre chose.

Avis aux autres : un moteur 3D ne tient absolument pas compte d'une quelconque interaction. C'est le rôle du moteur physique, du gestionnaire d'évènements, de(des) l'AI(s), de la timeline et du scénario, etc. Et perso je trouve pas franchement que ça rentre dans le cadre de ce que l'on appelle communément un "moteur 3D".

voilà !

Et merci Brunews pour ton sens du fun :) j'aime :)

signaler à un administrateur
Commentaire de _michel le 20/11/2007 21:58:25

MESA, ... comme dans Half Life...

D'accord, je comprend mieux. Et je parie que c'est plus rapide de le faire en hardware que en soft (c'est pour ça qu'une bonne carte graphique coute le prix de 3 PC bas de gamme).

Dorénavant je vais appeler mon programme "modélisateur de points 3d", avant de m'attaquer aux surfaces (c'est bien ça qui vous manque, non?).

signaler à un administrateur
Commentaire de pgl10 le 21/11/2007 10:01:30

Il convient de préciser ici, qu'il y a tout un mouvement relativement récent, principalement universitaire, pour modéliser des objets par un simple nuage de points pris à la surface de l'objet, ce qui présente bien des avantages. Parmi de très nombreuses publications à ce sujet j'en cite seulement deux pour expliquer cette tendance :
http://homes.dsi.unimi.it/~borghese/Research/LinesResearch/Scanner/3DScanning.html
http://www-i8.informatik.rwth-aachen.de/uploads/media/points.pdf
Mais avec Google on peut en trouver beaucoup d'autres.

Donc, en remplaçant le réseau de points par la lecture d'un fichier de points puis par un traitement avant l'affichage on obtiendrait, sur la base de ce logiciel, non pas un "modélisateur de points 3d" mais un afficheur de modèles d'objets définis par des points 3d.
Quant à l'obtention des points 3d il y a de très nombreuses solutions : scanner 3d, etc. Et même le logiciel gratuit : PhotoModeler qui permet de partir d'une simple photographie.

C'est une perspective intéressante, non ?

signaler à un administrateur
Commentaire de pgl10 le 21/11/2007 10:48:28

Je complète ici mon message précédent avec les deux précisions suivantes :
1°) PhotModeler a besoin de deux photos en stéréo pour relever les 3 coordonnées d'un point. Cependant il existe  des cas particuliers où on peut donner soit l'illusion du 3d avec une seule photo : http://www.youtube.com/watch?v=VuoljANz4EA soit même un vrai modèle 3d avec une seule photo : http://www.youtube.com/watch?v=nice6NYb_WA Mais cela sort du contexte actuel.
2°) Si on passe d'un nuage de points 3d à l'affichage d'un modèle d'objet définis par des points 3d je pense que l'on peut valablement parler d'un "modeleur d'objet 3d défini par points" et pas seulement d'un afficheur.

signaler à un administrateur
Commentaire de _michel le 23/11/2007 23:23:03

"C'est une perspective intéressante, non ?"
Oui, très !
Le traitement d'image me semble aussi intéressant, mais j'ai du temps, et je vais prendre mon temps...

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

Problème pour dériver une classe [ par arc59 ] J'ai créé une classe Matrice comportant des fonctions get_ele, set_ele (toutes les 2 sont "virtual") et la redéfinition de l'opérateur +.Dans ma class fichier.h [ par bidules ] Bonjour,j'aimerais savoir s'il est possible de mettre des structures dans un fichier d'entete.Car j'ai fais l'essai mais lors de la compilation pour c PB de matrice [ par limax84 ] J'ai un probleme d'allocation dynamique de memoire pour une matrice.pour un tableau, je procede comme ceci:int * t;t = new int [30];mais pour une matr matrice carréé [ par justeroland ] j'ai besoin de l'aide au sujet de l'exercice suivant: une matrice carré est dite balancée si les sommes des elements de ses quatre triangles sont égal Besoin d'aide en C - Fonction [ par bugs2600 ] Voici mon programme quelqu'un pourrait-il m'aider je dois faire une fonction et je ne vois pas comment la faire le non de ma fonction doit etre PRODMA graphisme ms-dos en c avec dev-cpp [ par surfeurnet ] Salut,Je suis débutant en c et je voudrai faire des graphiques sous ms-dos avec dev-cpp comment puis-je faire (j'ai entendue parlez de l'utilisation d une matrice de taille quelconque [ par anaisa ] salut tt le monde saurez vous m'aidez à résoudre un petit probleme: je dois programmé la somme, produit de matrices de taille quelconque en langage C Coord 2D to 3D [ par bat67000 ] Comment optenir d'un point 2D sur l'app les coordonnees du point 3D associé avec la matrice de projection ?(je pige pas bien comment fonctionne la mat animer un graphisme [ par GreatNeo ] Je crée par exemple une ligne. Est-il possible de la déplacer ? faut-il la transformer en bitmap ? (si oui quelle est la fonction pour le faire ?)Je v Matrice constante. [ par nsoualem ] j'ai crée une classe matrice avec un constructeurdu type:matrice(int nbligne,int nbcolonne)...elle marche a merveille!!!Lors de la création d'un code,


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,874 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.