Author Topic: Projection 3D  (Read 4566 times)

0 Members and 1 Guest are viewing this topic.

Arsenik

  • Associate
  • Posts: 9
Projection 3D
« on: May 03, 2006, 06:23:24 PM »
Bonjours, j'ai vraiment aimé votre logiciel et comme je fais beaucoup de C++ ( d'ailleur j'apprend tout seul alors mon code doit avoir un style particulié ! :p ) j'ai decidé de faire mon moteur 3D ( c'est entre autre pour ca que j'ai pas eu le temps de te répondre JegX mais je vais t'envoyer mon log :p )

Voilà en fait, j'hésite beaucoup pour mon algo de projection des points 3D. Le rendu avec celui-çi est correct mais j'aimerai avoir ton avis JegX ( et bien sûr ceux des autres mais généralement ceux qui codent ici n'ont pas le niveau pour coder un moteur 3D ) :

( Sachant que Array2D est le tableau ou je stock la couleur de chaque point avant de faire un rendu sur le pointeur *Screen de SDL et MainArray c'est le tableau ou je stock les positions des points 3D )

Quote
void Project(){
long double XBuffer;
long double YBuffer;

   for(int i=0;i< PointCount;i++){


      XBuffer = ((int)MainArray.iX<<8)/(MainArray.iZ+Cam.iZ)+Cam.iX;
      YBuffer = ((int)MainArray.iY<<8)/(MainArray.iZ+Cam.iZ)+Cam.iY;
      YBuffer = sHeight - YBuffer;

      Array2D.iX = XBuffer;
      Array2D.iY= YBuffer;

      Array2D.iColor = MainArray.iColor;

      
      PutPx(Array2D.iX,Array2D.iY,MainArray.iColor);

   }

}


Un screen si vous voulez voir ce que ça donne :


PS : Je fais ce moteur 3D juste pour comprendre je sais que c'est pas optimisé ni rien... :p


Merci !

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2357
    • oZone3D.Net
Projection 3D
« Reply #1 on: May 03, 2006, 10:26:06 PM »
Utilise la commande [Code] et non
Quote
pour poser tes bouts de code.

Juste comme ça au passage, bien que pas mal de newbies en prog 3D fréquentent ce forum, il y a aussi des personnes largement capables de coder des moteurs 3D de bonne facture et meme plus (n'est ce pas Groove ? - au passage, tjs pour Groove, ton article sur les VBO est vraiment sympa!).

Ceci étant dit, ça fait une éternité que j'ai pas vu de moteur 3D software. Tu es fou! :shock:
Ta routine de proj à l'air ok bien que j'ai plus trop ca en tête mais tous ces cast c'est flippant. Je ne connais pas du tout la SDL mais je suppose que ta fonction PutPx prend en param des index entiers dans le buffer qui représente la mem vidéo alors pourquoi ces "long double" ?

Honnêtement si tu veux te mettre à coder ton propre moteur 3D, utilise plutot une API genre opengl ou direct3d. Car meme avec ce genre d'api, ca reste galère de mettre sur pied un engine qui tienne la route. Et crois moi, pour réaliser un moteur 3D correct il faut creuser sérieusement sous les APIs 3D avant de faire faire à ton moteur ce que tu veux. Maintenant ton intention est honnête mais je pense que très vite tu passeras à une api 3d ne serait-ce que pour exploiter ta carte 3d car avec ton moteur software, tu vas la refroidir :D

Mais continue à newser sur ton moteur software je assez curieux de voir le reste...

Arsenik

  • Associate
  • Posts: 9
Projection 3D
« Reply #2 on: May 04, 2006, 12:29:52 AM »
Avant de continuer, je voulais juste dire que ce que j'ai dit a propos des personnes capables ou pas de coder un moteur 3D n'était pas du tout méchant, c'était juste que je savais pas vraiment si c'était l'endroit pour poser ma question donc ne le prend pas ( ni toi ni les autres ) de tout comme un reproche où une offense.

Aussi, désolé j'avais pas remarqué cette commande Code :p

Bref, ne t'inquiète pas je code en Direct3D ( mais en C# ) donc je connais mais le truc c'est qu'entre ma fonction Render en C# et Sous Direct3D

Code: [Select]

void Render(){

Dev.Clear(ClearFlags.Target | ClearFlags.ZBuffer , Color.Black, 1.0f, 0);
Dev.BeginScene();

for( int i = 0 ; i < NainMat.Length ; i++){

Dev.Material = NainMat[i];
Dev.SetTexture(0, NainText[i]);

mNain.DrawSubset(i);
}

Rotation+=0.01f;
Dev.Transform.World= Matrix.RotationY(Rotation);

Dev.Transform.View = Matrix.LookAtLH(new Vector3(0, 0.7f, -3), new Vector3(0.0F, 0.7F, 0.0F), new Vector3(0.0F, 1.0F, 0.0F));
Dev.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1F, 1.0F, 100.0F);

GetFPS();

Dev.EndScene();
Dev.Present();
}

et ma fonction de rendering en C++ c'est pas du tout pareil puisque je ne comprend pas vraiment quel est le support mathématique qui agit derrière. A par le fait que je doive utiliser des matrices de transformations ( qui sont étranges puisqu'elles prennent en paramètre des Vecteurs 3D. Ca devrait donc être des matrice 3x3 alors que j'ai l'habitude d'utiliser des 4x4 bref, ne nous emballons pas surtout que je ne suis pas sûr du tout que les matrices que DX utilise sont des 3x3... :p )
Bref, je conseil a tout le monde de prendre une librairie 2D et de commencer à coder comme il peut ne serais-ce que pour comprendre tous ces trucs :p

dailleur pour les interessé :http://www.mandragor.org/tutoriels/3d/13
et  : http://membres.lycos.fr/heulin/3D/Sommaire.html

Bref, ma question était seulement en gros quel méthode dois-je utiliser ? Comment puis-je corriger les erreurs de perspective etc...

Si tu veux voir où ça en est : http://membres.lycos.fr/wpproject/Release.rar


+++ et encore une fois désolé pour ce mal entendu !:p

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2357
    • oZone3D.Net
Projection 3D
« Reply #3 on: May 04, 2006, 09:29:43 AM »
Aucun pb pour le mal entendu :lol:

Tu me rassures, je pensais vraiment que tu étais un nostalique de l'époque du msdos ou les moteurs softwares étaient la seule issue...

Si ta fonction de rendering c++ diffère de celle de direct3d c'est totalement normal car sous direct3d comme sous opengl (c'est la meme chose à part les pb right et left hand) le pipeline de transformation est beacoup plus complexe que la simple équation de projection que tu as employé (en gros xp=(x0*d)/z0).

Les matrices utilisées par d3d ou ogl sont des matrices 4x4 car en gros tu peux combiner toutes les transformations en une seule matrice ce qui est impossible avec des matrices 3x3. Tout le hardware des cartes est taillé pour y loger des mat4x4. Donc meme si une fonction prend des vec3 en entrée, ne te fait pas avoir, elle fabrique bien en interne une mat4x4.

D'ailleurs pour t'en convaincre, voilà la def d'une mat d3d:
Code: [Select]

typedef struct D3DXMATRIX {
    FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14,
    FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24,
    FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34,
    FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 );
} D3DXMATRIX



Maintenant dans ton code, pourquoi fais-tu les transformations de la camera à la fin. Suit plutot l'ordre logique: update de la matrice de vue complete (view * proj) et rend l'objet ensuite car le rendu d'un objet 3D utilise la matrice de transformation de la camera. De plus, il est inutile à chaque frame de recalculer la mat de proj, celle-ci étant généralement fixe. Mais ca fait quelques années que j'ai plus fait de d3d mais on dirait qu'il manque un truc genre d3d_device->SetTransform( D3DTS_VIEW, &matView ) sauf si c'est fait dans le Dev.Begin/EndScene()...

Moi je verrai un code comme celui la:
Code: [Select]

void Init(){

// Trucs d'init et calcul de la matrice de proj.
     D3DXMatrixPerspectiveFovLH( &matProj, fov, aspect, znear, zfar );
    d3d_device->SetTransform( D3DTS_PROJECTION, &matProj );
}


void Render(){
         
Dev.Clear(ClearFlags.Target | ClearFlags.ZBuffer , Color.Black, 1.0f, 0);
Dev.BeginScene();

// Update de la matrice de vue avec Matrix.LookAtLH par exemple
d3d_device->SetTransform( D3DTS_VIEW, &matView )

// Rendu de tonb objet 3d

Dev.Transform.World= Matrix.RotationY(Rotation);
Rotation+=0.01f;

for( int i = 0 ; i < NainMat.Length ; i++){

Dev.Material = NainMat[i];
Dev.SetTexture(0, NainText[i]);

mNain.DrawSubset(i);
}

GetFPS();

Dev.EndScene();
Dev.Present();
}


Je trouve ce fonctionnement plus logique, non?

Maintenant pour ton pb de perspective c'est peut etre que ta matrice de proj est settée bizarement: tu utilise un fov de 45 degres et un aspect de 1. Essai plutot un fov de 60 deg (1.04) et un aspect de screenWidth/screenHeight. Peut etre que ca ira mieux.
Enfin, pas évident à dire tout ca....

Allez, c'est pas tout ca mais j'ai un hyperion à sortir!

KONI

  • Associate
  • Posts: 4
Projection 3D
« Reply #4 on: May 05, 2006, 08:56:28 AM »
Bonjour,

ce qui suit peut être un peu compliqué pour les personnes qui n'ont pas fait les math derrière mais voici la théorie pour une bonne projection:

D'abord, on utilise des vecteurs de dimension 4 pour définir un point et une matrice de 4x4 pour les transformations en 3D. Ceci provient du fait que les transformations en 3D ne sont pas linéaire !
Pour résoudre ce problème, on rajoute une 4ième composante et pour trouver les vrais coordonnées, on doit faire les calculs suivants:

x = (x1, x2, x3, x4) représente le point (x1/x4, x2/x4, x3/x4)

Maintenant, voyant voir comment on réalise une bonne projection, pour cela il faut comprendre les ONZE paramètres qui influencent une caméra:

les paramètres extérieurs:

- rotation: par rapport à une world-reference (0,0,0,0), la caméra peut être tourne en 3 dimensions, donc 3 paramètres

- translation: la caméra peut se trouver quelque part dans le repère, donc de nouveau 3 paramètres pour la translation

Si on appelle R la matrice de rotation (3x3) et T la matrice de translation (1x3), alors la matrice 4x4 qui définit les transformations extérieurs est:

(R,T;0,1)

les paramètres intérieurs:

- principal point: 2 paramètres qui définissent où se trouve le principal point sur ton caméra plane

- axis skew: un paramètre qui définit le rapport entre les deux axes, d'habitude ceci est 90°.

- inhomogeneous scaling: si tes pixels ne sont pas carrés, alors ceci sont les 2 paramètres qui influencent la rapport

Ceci fait un total de 11 paramètres pour le linéar camera model et la formule de projection est trop compliqué pour l'écrire ici donc je t'invite à lire:

http://cvlab.epfl.ch/~fua/courses/vision/math/notes/Cameras.pdf

en particulier le dernier slide à la page 2 avec le titre "Full Projection Matrix".

Si tu as des questions, n'hésite pas à les demander, il se peut que tu as des problèmes comment trouver la matrice de rotation (c'est une multiplication de 3 3x3 matrices qui ont une forme spéciale (cosinus et sinus) et qui sont particulières par rapport à l'axe de rotation)

Et si maintenant tu te demandes pourquoi faire tout ce travaille alors qu'une simple formule:

x = f * X/Z
y = f * Y/Z

suffit, alors je peux de garantir que ceci est la base sur laquelle tu peux commencer à faire des choses bien, comme les transformations en OpenGL, comme les rotations, translations etc (tu dois tout simplement multiplier ta matrice de projection par la matrice de transformation avant de dessiner tes points et ils vont se trouver au bon endroit).

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2357
    • oZone3D.Net
Projection 3D
« Reply #5 on: May 05, 2006, 09:29:39 AM »
Chouette ton explication.

Ca te dirait de pondre un petit tutoriel sur le sujet pour la section Tutorials du site, à savoir comment construire une matrice de camera complète (proj + view) ?  Si jamais, prends contact avec moi: jegx_AT_ozone3d(.)net

Arsenik

  • Associate
  • Posts: 9
Projection 3D
« Reply #6 on: May 05, 2006, 02:38:19 PM »
Que d'explication, merci beaucoup ! J'attend avec impatience ton tuto ( et j'espère que tu le feras :p ) !

++ Merci encore !