1

J'ai réalisé un petit "moteur 3D", grâce notament au tuto de Christophe Heulin.
Pour l'instnant il faut tourner un cube et quatre autres lignes grâce aux trois formules de projections 3D (j'utilise une fonction pour chaque et j n'utilise pas encore les matrices de roations).
Pour l'instant avec l'objet que j'ai à l'écran ça tourne à plus de 110 fps sur Ti 89 Hw2 avec un cube (plus les quatres autres lignes) de taille moyenne.

Avant j'utilisais cette formule qui marche très très bien ! :

Pixel[t].x = Xset + (Transform[t].x<<8) / (Transform[t].z+Offset);
Pixel[t].y = Yset + (Transform[t].y<<8) / (Transform[t].z+Offset);

Transform[t] est la liste des coordonnées des vertex transformés. Comme cette liste est multiplié par des angles allant de -128 à 128 je me servait de Offset pour que le cube puisse rentrer dans l'écran et en même temps le fait de décaler Transform[t] de 8 et de le diviser bpar Offset corrigeait très bien la perspective.
En plus avec Xset (80) et Yset(50) je pouvais centrer le cube.
Et puius avec Offset on peut facilment faire un zoom sans déformer l'objet.

Et puis après j'ai trouver une autre formule de projection qui permet de prendre en compte celui qui regarde la scène (je l'ai trouvé dans le tuto de Heulin):

X' = Xo + Zo * (X-Xo) / (Zo-Z)
Y' = Yo + Zo * (Y-Yo) / (Zo-Z)

Et dans mon programme ça donne ça:

Pixel[t].x = Xset+ (Zset * (Transform[t].x/128-Xset) / ((Zset-Transform[t].z/128)));
Pixel[t].y = Yset+ (Zset * (Transform[t].y/128-Yset) / ((Zset-Transform[t].z/128)));

Déjà comme il n'y a plus de Offset je suis obligé de diviser Transform[t] par 128 à chauqe fois.
En plus il faut faire une translation de tout les vecteurs après la transformation et avant la projection.
Et ensuite il y a de très gros problème de perspective. J'ai essayé de faire quelque chose comme ça:

Pixel[t].x = Xset+ 200*(Zset * (Transform[t].x/128-Xset) / ((Zset-Transform[t].z/128+5000)));
Pixel[t].y = Yset+ 200*(Zset * (Transform[t].y/128-Yset) / ((Zset-Transform[t].z/128+5000)))

Ca corrige un peu la perspective mais je doute que ce soit un réglage parfait et la formule est un peu trop couteuse.
Quand je déplace le cube vers la gauche ou vers la droite il y a bien une mofification de l'angle vu et le cube ne se déforme pas trop mais c'es(t quand même pas aussi bien que le réglage que j'avais fait pour la première formule


Es-ce que quelqi(un pourrait m'aider à corriger cette formule de projection ou alors m'en expliquer une qui pourrait marcher en partant du fait que mon programme tourne avec des angles précalculer dans des tables qui vont de -128 à 128 (vu que quand j'ai fait cette table j'ai multipilé les sin et les cos de chaque angle (de 0 à 360) par 128.

J'ai fait tout les moteur de recherche pour essayer de trouver une formule de projection correcte mais toutte celle que jai trouvé ne marchait pas ou pas aussi bien que celle de Heulin (celle qui ne prend pas en compte celui qui regarde la scène).
Et comme je sais que beaucoup d'entre vous sur ce forum ont réalisé (ou sont toujours entrain de réaliser un moteur 3D) sur TI89/TI92/V2000 je compte sur votre expérience pour m'apporter des solutions.

Merci d'avance à tout ceux qui pourront m'aider. smile





www.wikio.fr/user1921&info=comments

2

[cowboy]
Bravo ! top
[/cowboy]
le TI-BASIC est d'la merde !

3

Il y a personne qui connait des formules de projections 3D ?!
www.wikio.fr/user1921&info=comments

4

Il y a une infinité de matrice de projection... regarde un cours de sup, il y a tout un chapitre dessus.
XLib v1.00 Powerrrrrrrrrrrrrrrrrrrr!

5

Tu ne connais pas des liens sur Internet par ex ?
Parce-que j'ai déjà chrerché longtemps mais je n'ai rien trouvé d'intéressant ou de bien précis.
www.wikio.fr/user1921&info=comments

6

7

Ok, merci ! Je vais aller voir.
www.wikio.fr/user1921&info=comments

8

Y a pas grand chose, en fait.
Mais une formule de projection, ce n'est pas très compliqué.
Il suffit d'utiliser Thalès comme le conseille Mr Heulin, si je me souviens bien.
Moi, ce que je fais pour avoir une vue subjective, c'est simplement de projeter les coordonnées des polygones dans un nouveau repère dont l'origine est définie par la position de l'utilisateur, et l'axe Z la direction dans laquelle il regarde. Ensuite, j'applique la projection des coordonnées des points (exprimés dans le nouveau repère) sur l'écran et c'est tout.

9

En fait il faut que je trouve le meilleur réglage pour ma dernière formule.
Parce-qu'utiliser le théorème de Thalès et faire une projection en fonction de l'observateur c'est très facile mais ce qui l'est moins c'est d'avoir une formule qui projète les polygone sans déformation et avec une perspective qui donne l'impression que c'est de la 3D !
Parce-qu'en bidouillant des formules foireuse ça mène pas à grand chose.

Et ta formule, elle marche bien ?

Sur le forum il y a des screens de moteur 3D dont la projection à l'air d'être parfaite tandis qu'il y a des programmes avec un cube 3D qui tourne ou la perspective est complètement déformé et en plus elle pas prend en compte la position de l'observateur.
Donc il y a bien des réglage à effectuer.

Dans ce cas là ça ça pourrait très bien faire puisqu'on utilise le théorème de Thalès:
//Pixel[t].x = Xset + (Transform[t].x) / (Transform[t].z);
//Pixel[t].y = Yset + (Transform[t].y) / (Transform[t].z);

mais le projection est vraiment nul.

avec cela c'est parfait :
//Pixel[t].x = Xset + (Transform[t].x<<8) / (Transform[t].z+Offset);
//Pixel[t].y = Yset + (Transform[t].y<<8) / (Transform[t].z+Offset);

ou

X=80+(Vertex.x*256)/(Vertex.z+500)
Y=50+(Vertex.y*256)/(Vertex.z+500)


En gros je recherche la même chose mais avec une formule qui prenne en compte l'observateur et qui puisse projeter des polygones sur l'écran d'une Ti 89 avec une perspective correcte.








www.wikio.fr/user1921&info=comments

10

Ma formule est similaire à la tienne, c'est un truc du genre : x_ecran=x_espace*dist_focale/z_espace
Pour chaque polygone.
Pour ce qui est de la déformation de ton polygone, ça dépend de la distance focale je crois, en gros de la distance de l'observateur à l'écran. Il faut que cette distance soit de la largeur de l'écran divisée par deux (80 pour une TI-89, 120 pour une TI-92+) pour avoir une perspective correcte (FOV=90°).
Mais tu peux prendre une valeur proche qui est une puissance de 2, ça ne changera pas énormément (Moi, je prends 64 sur 89 et 128 sur 92+).


Pour prendre en compte la position de l'utilisateur, moi, ce que je fais, c'est ce que j'ai dit plus haut : j'exprime les coordonnées dans un autre repère définit par la position et l'orientation de l'utilisateur et je projete ces coordonées là. En plus, ça permet de simplifier la gestion du clipping.

11

J'ai à peu près compris mais j'arrive pas appilquer cela au programme que j'ai fait:

Voici les vertex que j'utilise:

Vertex[0].x=-10; Vertex[0].y=-10; Vertex[0].z=-10;
Vertex[1].x=10; Vertex[1].y=-10; Vertex[1].z=-10;
Vertex[2].x=10; Vertex[2].y=10; Vertex[2].z=-10;
Vertex[3].x=-10; Vertex[3].y=10; Vertex[3].z=-10;
Vertex[4].x=10; Vertex[4].y=-10; Vertex[4].z=10;
Vertex[5].x=-10; Vertex[5].y=-10; Vertex[5].z=10;
Vertex[6].x=-10; Vertex[6].y=10; Vertex[6].z=10;
Vertex[7].x=10; Vertex[7].y=10; Vertex[7].z=10;
Vertex[8].x=0; Vertex[8].y=0; Vertex[8].z=0;

Ensuite voici la table des angles que j'utilise:
static short Cos[361]={128,128,128,128,128,128,127,127,127,126,126,126,125,125,124,124,123,122,122,121,120,119,119,118,117,116,115,114,113,112,111,110,109,107,106,105,104,102,100,99,98,97,95,94,92,91,89,87,86,84,82,81,79,77,75,73,72,70,68,66,64,62,60,58,56,54,52,50,48,46,44,42,40,37,35,33,31,29,27,24,22,20,18,16,13,11,9,7,4,2,0,-2,-4,-7,-9,-11,-13,-16,-18,-20,-22,-24,-27,-29,-31,-33,-35,-37,-40,-42,-44,-46,-48,-50,-52,-54,-56,-58,-60,-62,-64,-66,-68,-70,-72,-73,-75,-77,-79,-81,-82,-84,-86,-87,-89,-91,-92,-94,-95,-97,-98,-99,-101,-102,-104,-105,-106,-107,-109,-110,-111,-112,-113,-114,-115,-116,-117,-118,-119,-119,-120,-121,-122,-122,-123,-124,-124,-125,-125,-126,-126,-126,-127,-127,-127,-128,-128,-128,-128,-128,-128,-128,-128,-128,-128,-128,-127,-127,-127,-126,-126,-126,-125,-125,-124,-124,-123,-122,-122,-121,-120,-119,-119,-118,-117,-116,-115,-114,-113,-112,-111,-110,-109,-107,-106,-105,-104,-102,-100,-99,-98,-97,-95,-94,-92,-91,-89,-87,-86,-84,-82,-81,-79,-77,-75,-73,-72,-70,-68,-66,-64,-62,-60,-58,-56,-54,-52,-50,-48,-46,-44,-42,-40,-37,-35,-33,-31,-29,-27,-24,-22,-20,-18,-16,-13,-11,-9,-7,-4,-2,0,2,4,7,9,11,13,16,18,20,22,24,27,29,31,33,35,37,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,73,75,77,79,81,82,84,86,87,89,91,92,94,95,97,98,99,101,102,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,119,120,121,122,122,123,124,124,125,125,126,126,126,127,127,127,128,128,128,128,128,128};
static short Sin[361]={0,2,4,7,9,11,13,16,18,20,22,24,27,29,31,33,35,37,40,42,44,46,48

Voila mes formule de rotation:

inline void RotationY(void)
{
Transform[t].x = Vertex[t].x*Cos[i] + Vertex[t].z*Sin[i];
Transform[t].y = Vertex[t].y*128;
Transform[t].z = (-Vertex[t].x)*Sin[i] + Vertex[t].z*Cos[i];
}

inline void RotationX(void)
{
Transform[t].x = Vertex[t].x*128;
Transform[t].y = Vertex[t].y*Cos[i] - Vertex[t].z*Sin[i];
Transform[t].z = Vertex[t].y*Sin[i] + Vertex[t].z*Cos[i];
}

inline void RotationZ(void)
{
Transform[t].x = Vertex[t].x*Cos[i] + Vertex[t].y*Sin[i];
Transform[t].y = (-Vertex[t].x)*Sin[i] + Vertex[t].y*Cos[i];
Transform[t].z = Vertex[t].z*128;
}

i correspond à l'angle (qui va de 0 à 360).

Je stocke donc mes Vertex multiplié par des angles entiers allant de -128 à 128 dans le tableau Transform[t], t étant la variable qui correspond un un des 9 vertex.

Ensuite sans aucune translation j'applique la formule de projection:

Pixel[t].x = 80 + (Transform[t].x<<8) / (Transform[t].z+16000);
Pixel[t].y = 50 + (Transform[t].y<<8) / (Transform[t].z+16000);

Comme je n'ai fait aucune translation 80 et 50 permette de centrer le cube dans l'écran.
Transform[t].<<8 je crois que ça correspond à la distance focale dont tu me parlais ?
16000 me permet d'avoir des Z positifs vu qu'il y a des vertex z qui sont égaux à -10 et en même temps il m'arrange bien parce-qu'il permet d'avoir un grand nombre Z pour pouvoir diviser suffisament le produit des vertex par les grands angles entiers pour que l'objet rentre dans l'écran.
Sinon il faudrait que je divise Transform[t].x,Transform[t].y,Transform[t].z par 128.

Au passage tu te sers bien de table comme moi pour tes angles ? Si c'est le cas tu fait comment pour les diviser par le nombre par lequel tu les à multiplié ?

Pixel[t].x et Pixel[t].y contiennent les coordonnées 2D qui vont être afficher à l'écran.
Il me reste plus qu'a afficher directement les lignes:

DrawFastLine(buffer,Pixel[0].x,Pixel[0].y,Pixel[1].x,Pixel[1].y);
DrawFastLine(buffer,Pixel[1].x,Pixel[1].y,Pixel[2].x,Pixel[2].y);
DrawFastLine(buffer,Pixel[2].x,Pixel[2].y,Pixel[3].x,Pixel[3].y);
DrawFastLine(buffer,Pixel[0].x,Pixel[0].y,Pixel[3].x,Pixel[3].y);
DrawFastLine(buffer,Pixel[4].x,Pixel[4].y,Pixel[5].x,Pixel[5].y);
DrawFastLine(buffer,Pixel[5].x,Pixel[5].y,Pixel[6].x,Pixel[6].y);
DrawFastLine(buffer,Pixel[6].x,Pixel[6].y,Pixel[7].x,Pixel[7].y);
DrawFastLine(buffer,Pixel[4].x,Pixel[4].y,Pixel[7].x,Pixel[7].y);
DrawFastLine(buffer,Pixel[0].x,Pixel[0].y,Pixel[5].x,Pixel[5].y);
DrawFastLine(buffer,Pixel[1].x,Pixel[1].y,Pixel[4].x,Pixel[4].y);
DrawFastLine(buffer,Pixel[2].x,Pixel[2].y,Pixel[7].x,Pixel[7].y);
DrawFastLine(buffer,Pixel[3].x,Pixel[3].y,Pixel[6].x,Pixel[6].y);

DrawFastLine(buffer,Pixel[0].x,Pixel[0].y,Pixel[8].x,Pixel[8].y);
DrawFastLine(buffer,Pixel[1].x,Pixel[1].y,Pixel[8].x,Pixel[8].y);
DrawFastLine(buffer,Pixel[2].x,Pixel[2].y,Pixel[8].x,Pixel[8].y);
DrawFastLine(buffer,Pixel[3].x,Pixel[3].y,Pixel[8].x,Pixel[8].y);

FastCopyScreen(buffer,LCD_MEM);
memset(buffer, 0, 3840);



Donc concrètement si je veux projetter les coordonnées dans un autre repère du plan pour prendre en compte l'observateur il faut que je fasse comment ?
www.wikio.fr/user1921&info=comments

12

Il y a eu un petit pb: la table des sin est pas passé entièrement. Mais bon c pareil que la tables des sin sauf que c l'inverse.

Et puis DrawFastLine c la routine du tracé des lignes d'extgraph que j'ai optimiser pour ce programme (elle dessine que en A_REPLACE) mais je ne l'ai pas encore modifié pour qu'elle trace des lignes clippés.
J'ai pas trouver d'autre nom ! grin
www.wikio.fr/user1921&info=comments

13

Pour DrawFastLine, c'est un très bon choix, car c'est une fonction extrêmement rapide.

Ensuite, pour mes angles, j'utilise effectivement des tables précalculées (sinon c'est très lent). J'utilise donc des tables de 360 char qui contiennent les cosinus/sinus de l'angle multiplié par 32 (décalé de 5 bits vers la gauche), je trouve que la précision est suffisante. Au passage, ce n'est pas normal que ta table contienne 361 valeurs, elle devrait en contenir 360. Pour obtenir la vraie valeur de mon cosinus/sinus, je divise par 32 (logique), ce qui correspond à un décalage de 5 bits vers la droite. Mais normalement, TIGCC optimise ça tout seul.

Sinon pour projeter mes polygones dans un autre repère, j'utilise le produit scalaire.
Si tu as vu le produit scalaire en classe, tu pourras p-ê trouver tout seul comment faire, sinon, je t'expliquerai, mais c'est compliqué, il faudrait que je fasse des shémas et tout et tout.
Sinon, tu n'es pas obligé de projeter tes polygones dans un nouveau repère puis de les projeter à l'écran. Tu peux réaliser ces 2 opérations en une seule fois, mais moi, je trouve que ça simplifie après pour calculer le clipping.
Mais moi aussi, je débute vraiment, donc je passe p-ê à côté de bon nombre d'optimisations en faisant ça...