PDA

Voir la version complète : [GBA][Aide] Problème de gestion de la mémoire et des variables (débutant)


bhelial
24/05/2007, 01h03
Boujour,

J'essaie de coder un moteur3D assez simplifié sur GBA.

Pour l'instant j'arrive à partir d'un tableau qui contient les coordonnées en 3d d'un cube à calculer ses coordonnées en 2D,à l'afficher en fil de fer et à faire fonctioner la rotation de mon cube.

Le problème survient au niveau du remplissage des polygones. Je crée un tableau contenant pour chaque polygone les coordonnées x de départ et de fin pour chaque ligne puis je génère l'affichage de ces lignes. Lorsque j'initialise mon tableau pour mon polygone, le tableau contenant mes coordonnées en 2D renvoie des données compètement illogiques alors que si je me contente d'afficher mon cube en fil de fer, tout va bien. En résumé dès que je fais une opération après l'affichage, mes variables sont corrompues

Je me demande si je ne depasse pas la taille de la mémoire (pourtant avec seulement 8 points, celà me semble pas énorme). Je suis également relativement débutant en C et en C++ et je me demande si l'allocation de mes variables est correcte...

Dans tous les cas, un peu d'aide serait la bienvenue.
Merci par avance.:)

Voici mon code. Je développe sous Visual Ham :


#include <mygba.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define REG_DISPCNT *(volatile unsigned long*)0x4000000
#define RGB(r,g,b) ((r)+((g)<<5)+((b)<<10))

MULTIBOOT

//************************************************** **************************************

u8 vbl_count = 0;
int xa,ya,za = 0;

typedef struct Coordonnees Coordonnees;
struct Coordonnees
{
long x;
long y;
};

typedef struct point3D point3D;
struct point3D
{
int x,y,z;
};


typedef struct point2D point2D;
struct point2D
{
int x,y;
};


typedef struct polygones polygones;
struct polygones
{
int a,b,c;
};

typedef struct fillpolygones fillpolygones;
struct fillpolygones
{
int y, startx, endx;
};


point3D Sommet[8]; /* les sommets du cube */
point3D Point3D[8]; /* les sommets apres rotation */
point2D Point2D[8]; /* les sommets apres projection */


polygones Poly[12]; /* les polygones à remplir à partir des coordonnées des points*/

fillpolygones fillpoly[200];

int Nb_points = 8;

// position par rapport à l'écran
int Xoff = 0;//160
int Yoff = 0;//100
int Zoff = -145;//-125 //600


static float Sin[360],Cos[360]; /* Tableaux precalcules de sinus et cosinus */
static float matrice[3][3]; /* Matrice de rotation 3*3 */


/************************************************** **************************/
/* Init_Sinus() : precalcul les tables de sinus et cosinus */
/************************************************** **************************/
float** Init_Sinus(float *Sin, float *Cos)
{
int i;

for(i=0;i<360;i++)
{
Sin[i]=sin(i * 3.1415927 / 180);
Cos[i]=cos(i * 3.1415927 / 180);
}
return (float**)Sin;
return (float**)Cos;
}

/************************************************** **************************/
/* Initialiser() : initialise les coordonnees des sommets du cube */
/* ainsi que les polygones à remplir */
/************************************************** **************************/
point3D** Initialiser(point3D *Sommet)
{
Sommet[0].x = -25; Sommet[0].y = -25; Sommet[0].z = -25;
Sommet[1].x = 25; Sommet[1].y = -25; Sommet[1].z = -25;
Sommet[2].x = 25; Sommet[2].y = 25; Sommet[2].z = -25;
Sommet[3].x = -25; Sommet[3].y = 25; Sommet[3].z = -25;
Sommet[4].x = 25; Sommet[4].y = -25; Sommet[4].z = 25;
Sommet[5].x = -25; Sommet[5].y = -25; Sommet[5].z = 25;
Sommet[6].x = -25; Sommet[6].y = 25; Sommet[6].z = 25;
Sommet[7].x = 25; Sommet[7].y = 25; Sommet[7].z = 25;

return (point3D**)Sommet;
}

polygones** Initialiser2(polygones *Poly)
{
Poly[0].a = 5; Poly[0].b = 6; Poly[0].c = 7;
Poly[1].a = 5; Poly[1].b = 4; Poly[1].c = 7;

Poly[2].a = 0; Poly[2].b = 1; Poly[2].c = 2;
Poly[3].a = 0; Poly[3].b = 2; Poly[3].c = 3;

Poly[4].a = 5; Poly[4].b = 0; Poly[4].c = 1;
Poly[5].a = 5; Poly[5].b = 4; Poly[5].c = 1;

Poly[6].a = 6; Poly[6].b = 3; Poly[6].c = 2;
Poly[7].a = 6; Poly[7].b = 7; Poly[7].c = 2;

Poly[8].a = 6; Poly[8].b = 5; Poly[8].c = 0;
Poly[9].a = 6; Poly[9].b = 3; Poly[9].c = 0;

Poly[10].a = 7; Poly[10].b = 4; Poly[10].c = 1;
Poly[11].a = 7; Poly[11].b = 2; Poly[11].c = 1;

return (polygones**)Poly;
}

/************************************************** **************************/
/* Rotation() : effectue la rotation des points Sommet -> Point3D */
/************************************************** **************************/
point3D** Rotation(point3D *Point3D, int Xa, int Ya, int Za)
{
int i;

/* Calcul de la matrice de rotation 3*3 */
matrice[0][0] = Cos[Za]*Cos[Ya];
matrice[1][0] = Sin[Za]*Cos[Ya];
matrice[2][0] = -Sin[Ya];

matrice[0][1] = Cos[Za]*Sin[Ya]*Sin[Xa] - Sin[Za]*Cos[Xa];
matrice[1][1] = Sin[Za]*Sin[Ya]*Sin[Xa] + Cos[Xa]*Cos[Za];
matrice[2][1] = Sin[Xa]*Cos[Ya];

matrice[0][2] = Cos[Za]*Sin[Ya]*Cos[Xa] + Sin[Za]*Sin[Xa];
matrice[1][2] = Sin[Za]*Sin[Ya]*Cos[Xa] - Cos[Za]*Sin[Xa];
matrice[2][2] = Cos[Xa]*Cos[Ya];


/* Rotation des sommets de l'objet */
for(i=0; i<Nb_points; i++)
{
Point3D[i].x = (int) (matrice[0][0]*Sommet[i].x
+ matrice[1][0]*Sommet[i].y
+ matrice[2][0]*Sommet[i].z);

Point3D[i].y = (int) (matrice[0][1]*Sommet[i].x
+ matrice[1][1]*Sommet[i].y
+ matrice[2][1]*Sommet[i].z);

Point3D[i].z = (int) (matrice[0][2]*Sommet[i].x
+ matrice[1][2]*Sommet[i].y
+ matrice[2][2]*Sommet[i].z);
}
return (point3D**)Point3D;
}

/************************************************** **************************/
/* Projection() : convertit les points 3D en 2D après la rotation */
/************************************************** **************************/
point2D** Projection(point2D *Point2D)
{
int i;

float fx;
float fy;
int x, y;

for(i=0;i<Nb_points;i++)
{
fx = (Point3D[i].x * 256 ) / (Point3D[i].z + Zoff) + Xoff ;
fy = (Point3D[i].y * 256 ) / (Point3D[i].z + Zoff) + Yoff ;

// partie entière des coordonnées
x = (int) floor(fx);
y = (int) floor(fy);

// génération du tableau 2D
Point2D[i].x = x;
Point2D[i].y = y;

}
return (point2D**)Point2D;
}

/************************************************** **************************/
/* translation() : fait en sorte que le point (0,0) soit au centre de */
/* l'écran */
/************************************************** **************************/

void translation(int x, int y) {
unsigned short *VideoBuffer = (unsigned short *) 0x6000000;
// Passer en mode 3:
REG_DISPCNT= (0x3 | 0x400);

x = x + 120;
y = 80 - y;

VideoBuffer[y * 240 + x] = RGB(20,20,20);
}

/************************************************** **************************/
/* axex() : génération des axes après translation */
/************************************************** **************************/
void axes(void) {
int x2;
int y2;

for (x2= -120; x2< 120; x2= x2+1) {
translation(x2,0);
}

for (y2=-80; y2<160; y2++) {
translation(0,y2);
}
}

/************************************************** **************************/
/* Afficher() : dessine la scene a l'ecran */
/************************************************** **************************/

void Afficher(int couleur)
{
int i;

for (i=0;i<8;i++)
{
translation(Point2D[i].x,Point2D[i].y);
}
}

/************************************************** **************************/
/* Line() : trace une ligne entre deux points */
/************************************************** **************************/

void Line(int x1,int y1, int x2,int y2)
{
int xx,yy;
int Dx,Dy;
int xincr,yincr;
int erreur;
int i;

/* On initialise les variables */
Dx = abs(x2-x1);
Dy = abs(y2-y1);

/* On détermine dans quel sens varie la droite */
if(x1<x2)
xincr = 1;
else
xincr = -1;

if(y1<y2)
yincr = 1;
else
yincr = -1;

/* Trace de ligne */
xx = x1;
yy = y1;

if(Dx>Dy)
{
erreur = Dx/2;
for(i=0;i<Dx;i++)
{
xx += xincr;
erreur += Dy;
if(erreur>Dx)
{
erreur -= Dx;
yy += yincr;
}
translation(xx,yy);
}
}
else
{
erreur = Dy/2;
for(i=0;i<Dy;i++)
{
yy += yincr;
erreur += Dx;
if(erreur>Dy)
{
erreur -= Dy;
xx += xincr;
}
translation(xx,yy);
}
}
}

/************************************************** **************************/
/* Afficher() : dessine la scene a l'ecran */
/************************************************** **************************/
void fildefer(point2D *Point2D) {

for (int aze =0; aze<12; aze++) {
Line (Point2D[Poly[aze].a].x, Point2D[Poly[aze].a].y, Point2D[Poly[aze].b].x, Point2D[Poly[aze].b].y);
Line (Point2D[Poly[aze].a].x, Point2D[Poly[aze].a].y, Point2D[Poly[aze].c].x, Point2D[Poly[aze].c].y);
Line (Point2D[Poly[aze].b].x, Point2D[Poly[aze].b].y, Point2D[Poly[aze].c].x, Point2D[Poly[aze].c].y);
}
}


/************************************************** ************************************************** ************************************************** *****/
/************************************************** ************************************************** ************************************************** *****/
fillpolygones** Initialiserfillpoly(fillpolygones *fillpoly)
{
//fillpolygones fillpoly[200];

for (signed int i=-100; i<100;i++) {
fillpoly[i].y = i;
fillpoly[i].startx = -16000;
fillpoly[i].endx = -16000;
}
return (fillpolygones**)fillpoly;
}


void InitSegment(int x1, int y1, int x2,int y2)
{
int temp,y;
long x,pas;

if(y2!=y1)
{
if(y2<y1)
{
temp=y1;
y1=y2;
y2=temp;

temp=x1;
x1=x2;
x2=temp;
}

x = x1<<8;
pas= ((x2-x1)<<8)/(y2-y1);

x+=pas;
y1++;

//if(y1<miny) miny=y1;
//if(y2>maxy) maxy=y2;

for(y=y1;y<=y2;y++)
{
if (y>= -80) {
//if((y>=-80) /*&& (y<Ymax)*/) l'axe des ordonnées va de -80 à 80
if(fillpoly[y].startx == -16000) {
fillpoly[y].startx = x>>8;
} else {
fillpoly[y].endx = x>>8;
}
}
x+=pas;
}

}
}


void Hline()
{
int x1, x2;

//unsigned short *VideoBuffer = (unsigned short *) 0x6000000;
// Passer en mode 3:
//REG_DISPCNT= (0x3 | 0x400);

for (int i=-100; i<100; i++) {
if (fillpoly[i].startx != -16000 && fillpoly[i].endx != -16000) {
if (fillpoly[i].startx < fillpoly[i].endx) {
x1 = fillpoly[i].startx;
x2 = fillpoly[i].endx;
}
else
{
x1 = fillpoly[i].endx;
x2 = fillpoly[i].startx;
}

for (int ii=x1; ii<=x2; ii++)
{
//VideoBuffer[y * 240 + x] = RGB(20,20,20);
translation(ii,fillpoly[i].y);
}
}
}
}

/************************************************** ************************************************** ************************************************** *****/
/************************************************** ************************************************** ************************************************** *****/

void fildefer2(point2D *Point2D) {

for (int aze =0; aze<12; aze++) {
Line (Point2D[Poly[aze].a].x, Point2D[Poly[aze].a].y, Point2D[Poly[aze].b].x, Point2D[Poly[aze].b].y);
Line (Point2D[Poly[aze].a].x, Point2D[Poly[aze].a].y, Point2D[Poly[aze].c].x, Point2D[Poly[aze].c].y);
Line (Point2D[Poly[aze].b].x, Point2D[Poly[aze].b].y, Point2D[Poly[aze].c].x, Point2D[Poly[aze].c].y);
}
}



/************************************************** **************************/
/* reset_screen() : efface l'écran */
/************************************************** **************************/
void reset_screen() {
unsigned short *VideoBuffer = (unsigned short *) 0x6000000;
// Passer en mode 3:
REG_DISPCNT= (0x3 | 0x400);

int xx = 0;
int yy = 0;

for (yy=0; yy <160; yy++) {
for (xx=0; xx<240; xx++) {
VideoBuffer[yy * 240 + xx] = RGB(90,90,90);
}
}

}



/************************************************** **************************/
/*** MAIN ***/
/************************************************** **************************/
int main(void)
{
//ham_Init();
unsigned short *VideoBuffer = (unsigned short *) 0x6000000;
//Passer en mode 3:
REG_DISPCNT= (0x3 | 0x400);

while(true)
{
int xa,ya,za;
axes();
bool bouton_presse = 0;

// Initialisations
Initialiserfillpoly(fillpoly);
Init_Sinus(Sin, Cos);
Initialiser(Sommet);
Initialiser2(Poly);
xa=ya=za=0;

Rotation(Point3D,0,0,0);
delete[] Sommet;
Projection(Point2D);
delete[] Point3D;

Afficher(100);
fildefer(Point2D);

int aze = 0;
Initialiserfillpoly(fillpoly);
InitSegment (Point2D[Poly[aze].a].x, Point2D[Poly[aze].a].y, Point2D[Poly[aze].b].x, Point2D[Poly[aze].b].y);
InitSegment (Point2D[Poly[aze].a].x, Point2D[Poly[aze].a].y, Point2D[Poly[aze].c].x, Point2D[Poly[aze].c].y);
InitSegment (Point2D[Poly[aze].b].x, Point2D[Poly[aze].b].y, Point2D[Poly[aze].c].x, Point2D[Poly[aze].c].y);
Hline();

//Afficher(100);
//fildefer(Point2D);
/*
Initialiserfillpoly();
InitSegment (-53, -53, 53, -53);
InitSegment (-53, -53, -53, 53);
InitSegment (53, -53, -53, 53);
Hline();
*/



while (bouton_presse == 0) {
if (F_CTRLINPUT_UP_PRESSED)
{
bouton_presse = 1;
reset_screen();
axes();
ya = ya + 10;

if (ya >= 360) {
ya = 0;
}

Rotation(Point3D,xa,ya,za);
Projection(Point2D);
Afficher(100);
fildefer(Point2D);
bouton_presse = 0;
}

if (F_CTRLINPUT_DOWN_PRESSED)
{
reset_screen();
axes();
ya = ya - 10;

if (ya <= 0) {
ya = 360;
}

Rotation(Point3D,xa,ya,za);
Projection(Point2D);
Afficher(100);
fildefer(Point2D);
}

if (F_CTRLINPUT_LEFT_PRESSED)
{
reset_screen();
axes();
za = za - 10;

if (za <= 0) {
za = 360;
}

Rotation(Point3D,xa,ya,za);
Projection(Point2D);
Afficher(100);
fildefer(Point2D);
}

if (F_CTRLINPUT_RIGHT_PRESSED) // Pour la droite
{
reset_screen();
axes();
za = za + 10;

if (za >= 360) {
za = 0;
}

Rotation(Point3D,xa,ya,za);
Projection(Point2D);
Afficher(100);
fildefer(Point2D);
}

} // while

while (bouton_presse == 1) {
if ( F_CTRLINPUT_UP_PRESSED
|| F_CTRLINPUT_DOWN_PRESSED
|| F_CTRLINPUT_LEFT_PRESSED
|| F_CTRLINPUT_RIGHT_PRESSED)
{
axes();
bouton_presse = 0;
}
} // while



}
return 0;
}

/* END OF FILE */

Dr.Vince
24/05/2007, 01h36
arf....... je suis pas assez bon techniquement pour te répondre (et surtout comprendre ton code) mais une chose est sûr, c'est que sur GBA les float sont à proscrire sauf si le but est de tué le processeur de ta GBA :)

en plus tu mixe ça à des sin, cos et des divisions !!!

le mieux c'est d'utiliser des LUT pour les tables des sin et des cos

themouton
24/05/2007, 11h53
Salut,
en regardant vite fait ton code, le truc qui je trouve bizarre :

for (signed int i=-100; i<100;i++) {
fillpoly[i].y = i;
...

ça marche ça en C ? Donner une valeur négative à un tableau au niveau de l'index, je sais pas trop quel résultat cela donne. Car si le C transforme le i en entier non signé, ça va faire un tres grand nombre... Car le signe d'un nombre vient du dernier bit.
Tu peux trouver des infos sur le net qu'il explique le fonctionnement du signe en C.
Il faut mieux utiliser des nombres positifs et non signé pour les index d'un tableau.

Nesgba
24/05/2007, 18h04
yo,

j'arrive pas a comprendre qu'un mec qui sais passer en paramettre de fonction des doubles pointeurs arrive
a produire du si mauvais code.

a mon sens il est impossible qu'une meme personne qui sais utiliser des algos dediés a afficher de la vraie 3D
polygonale (avec la projection, et meme une fonction de filling) ai reussi a produire un code aussi fouilli et mal pensé.

tu as du reprendre un code existant et tu as fait la convertion a l'arrache pour le porter sur gba,
mais c'est une mauvaise idée, deja 95% des codes et algo que tu trouvera sur le net ne sont pas super optimisés,
(et encore.. la je parle des codes des demomaker pro-mode 13h d'antan, alors j'imagine meme pas le code d'un pro-directX qui veut se la faire "soft engine powaa")

juste en regardant le code, je mise sur 12 fps pour un cube en flat ayant une sherebox de 120 pixels de diametre ;).
sans exagerer, avec quelques optimisations tu pourrais faire tourner ton programme disons 15 à 20 fois plus vite.

d'ailleur puisqu'on y est, voici quelques optimisations que je te propose de faire
(je m'engage sur le bien fait de ces optimisations que sur les plateformes gba et nds, je reste ouvert a toute discution ou contestation)
1: virer les float
3: pas de divisions
2: pas de tableaux 2D (qui plus est sur organe ultra critique comme la matrice 3x3)
4: changer le format de stockage des données
5: arreter de faire des operations inutiles (pourquoi passer en float pour la projection ? le n*256 est la justement pour eviter d'utiliser des float)
6: ne pas utiliser les pointeurs tel quel (1:lire valeur pointeur, 2:faire operation sur valeur, 3: mettre valeur dans pointeur)
7: eviter de renvoyer des structures par fonctions
8: ne pas relire 30 fois la meme valeur sur un tableau stocké en ewram (voir point 6)
9: la Hline est justement la pour permettre de ne pas plotter 1 par 1
10: utiliser une table de sin/cos puissance de 2
11: mettre les fonctions critiques dans la pile IWRAM
12: passer en mode 4 (ca te permettra de plotter 4 par 4)
13: enlever le mode MULTIBOOT
14: l'instruction de comparaison "if" est a utiliser que losque qu'il est impossible de faire autrement
15: deboucler les algo qui ne comportent pas d'instruction de comparaison ou de branchement pour faire jouer le pipeline sur 3 niveau de l'arm7tdmi
16: virer les faces dont la normale ne pointe pas vers la camera

bon on va rester puissance de 2 pour les optim proposés ^^ (ok je sort ->)

ca fait toujours plaisir de voir un gars se mettre a la 3D (particulierement sur ma chere gba :')),
mais faut pas faire des trucs comme ca :(. ne perd surtout pas espoir parcque je te dit ca,
mieu vaut que tu commence lentement mais que tu y aille surrement. ;)

a+



ça marche ça en C ? Donner une valeur négative à un tableau au niveau de l'index,

j'avais essayé de faire des operations de ce genre, mais je n'ai pas encore reussi a pointer correctement (faudrai voir comment gcc stoque 2 tableau successifs en rom) je m'y attarderai un de ces jours ;)

je dit ca car (ca peut sembler invraisemblable a un codeur habitué au C,C++) c'est tout a fait fesable en asm (et meme recommandée pour optimiser certains acces).

mais je ne pense pas que das ce cas ci il l'ai fait expres, ce sont des tricks vraiment osés pour de la prog C ^^

ps: ah si on pouvai pointer sur un label ca serai le reve absolu ... :'}

bhelial
24/05/2007, 21h44
Merci pour vos réponses.

Pour commencer, j'aurai pas la prétention de dire que le code est intégralement de moi. Quand j'ai débuté ce prog, j'ai comencé par chercher comment fonctionne un moteur 3D et j'ai regardé différents algorythmes et tutoriaux afin d'avoir une idée de ce que je devais coder. Mathématiquement parlant, j'ai beaucoup adapté des algorythmes déjà existant tout en essayant de les simplifier pour ne pas dire que certains sont pratiquement repompés...

Concernant le code pas du tout optimisé, j'en suis parfaitment conscient. Avant de faire un programme optimal, j'ai commencé par essayer de faire fonctionner mes algos. Même si je me débrouille pas trop mal en J2EE, j'ai jamais fait de C ou de C++ n'y encore moins de dev sur console (qui est vraiment problématique au niveau du debuggage). Maintenant que j'ai resolu ce problème, je vais essayé de l'optimiser (au passage merci pour tous les conseils, j'aurai certainement pas vu autant de choses à améliorer bien que la gestion des faces cachées était la prochaine étape...).


Concernant mon problème, celui-ci venait bien de l'intialisation de mon tableau avec un index négatif (je sais pas comment j'ai fait pour avoir l'idée de faire ça et pour pas le voir... ::snif2: ).

Pour l'explication, d'après ce que j'ai compris <A HREF="http://www.ann.jussieu.fr/courscpp/Sections/Sect03-B2.html" >ici</A>, en appelant les éléménts du tableau indéxés avec une référence négative,
j'accédais aux données stockées avant mon tableau et de fait, je modifiais complétement mes autres tableaux stockés précédement en mémoire.

Je sais que c'est pas le but de ce sujet mais je poste quand même le code corrigé (mais comme viens de le dire Nesgba pas du tout optimisé) si jamais quelqu'un passe par là et est intéréssé par mon horreur :p :


#include <mygba.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define REG_DISPCNT *(volatile unsigned long*)0x4000000
#define RGB(r,g,b) ((r)+((g)<<5)+((b)<<10))

MULTIBOOT

//************************************************** **************************************

u8 vbl_count = 0;
int xa,ya,za = 0;

typedef struct Coordonnees Coordonnees;
struct Coordonnees
{
long x;
long y;
};

typedef struct point3D point3D;
struct point3D
{
int x,y,z;
};


typedef struct point2D point2D;
struct point2D
{
int x,y;
};


typedef struct polygones polygones;
struct polygones
{
int a,b,c;
};

typedef struct fillpolygones fillpolygones;
struct fillpolygones
{
int y, startx, endx;
};


point3D Sommet[8]; /* les sommets du cube */
point3D Point3D[8]; /* les sommets apres rotation */
point2D Point2D[8]; /* les sommets apres projection */


polygones Poly[12]; /* les polygones à remplir à partir des coordonnées des points*/

fillpolygones fillpoly[200];

int Nb_points = 8;

// position par rapport à l'écran
int Xoff = 0; //160
int Yoff = 0; //100
int Zoff = -145; //-125 //600


static float Sin[360],Cos[360]; /* Tableaux precalcules de sinus et cosinus */
static float matrice[3][3]; /* Matrice de rotation 3*3 */


/************************************************** **************************/
/* Init_Sinus() : precalcul les tables de sinus et cosinus */
/************************************************** **************************/
float** Init_Sinus(float *Sin, float *Cos)
{
int i;

for(i=0;i<360;i++)
{
Sin[i]=sin(i * 3.1415927 / 180);
Cos[i]=cos(i * 3.1415927 / 180);
}
return (float**)Sin;
return (float**)Cos;
}

/************************************************** **************************/
/* Initialiser() : initialise les coordonnees des sommets du cube */
/* Initialiser2() : intialise les polygones à remplir */
/************************************************** **************************/
point3D** Initialiser(point3D *Sommet)
{
Sommet[0].x = -25; Sommet[0].y = -25; Sommet[0].z = -25;
Sommet[1].x = 25; Sommet[1].y = -25; Sommet[1].z = -25;
Sommet[2].x = 25; Sommet[2].y = 25; Sommet[2].z = -25;
Sommet[3].x = -25; Sommet[3].y = 25; Sommet[3].z = -25;
Sommet[4].x = 25; Sommet[4].y = -25; Sommet[4].z = 25;
Sommet[5].x = -25; Sommet[5].y = -25; Sommet[5].z = 25;
Sommet[6].x = -25; Sommet[6].y = 25; Sommet[6].z = 25;
Sommet[7].x = 25; Sommet[7].y = 25; Sommet[7].z = 25;

return (point3D**)Sommet;
}

polygones** Initialiser2(polygones *Poly)
{
Poly[0].a = 5; Poly[0].b = 6; Poly[0].c = 7;
Poly[1].a = 5; Poly[1].b = 4; Poly[1].c = 7;

Poly[2].a = 0; Poly[2].b = 1; Poly[2].c = 2;
Poly[3].a = 0; Poly[3].b = 2; Poly[3].c = 3;

Poly[4].a = 5; Poly[4].b = 0; Poly[4].c = 1;
Poly[5].a = 5; Poly[5].b = 4; Poly[5].c = 1;

Poly[6].a = 6; Poly[6].b = 3; Poly[6].c = 2;
Poly[7].a = 6; Poly[7].b = 7; Poly[7].c = 2;

Poly[8].a = 6; Poly[8].b = 5; Poly[8].c = 0;
Poly[9].a = 6; Poly[9].b = 3; Poly[9].c = 0;

Poly[10].a = 7; Poly[10].b = 4; Poly[10].c = 1;
Poly[11].a = 7; Poly[11].b = 2; Poly[11].c = 1;

return (polygones**)Poly;
}

/************************************************** **************************/
/* Initialiserfillpoly() : initialise le tableau de remplissage du polygone */
/* avec une valeur impossbile à obtenir dans la réalité */
/************************************************** **************************/
fillpolygones** Initialiserfillpoly(fillpolygones *fillpoly)
{
/* l'index du tableau ne pouvant être négatif, fillpoly[0] designe le point d'abscisse y = -100 */
for (int i=0; i<200;i++) {
fillpoly[i].y = i-100;
fillpoly[i].startx = -16000;
fillpoly[i].endx = -16000;
}
return (fillpolygones**)fillpoly;
}

/************************************************** **************************/
/* Rotation() : effectue la rotation des points Sommet -> Point3D */
/************************************************** **************************/
point3D** Rotation(point3D *Point3D, int Xa, int Ya, int Za)
{
int i;

/* Calcul de la matrice de rotation 3*3 */
matrice[0][0] = Cos[Za]*Cos[Ya];
matrice[1][0] = Sin[Za]*Cos[Ya];
matrice[2][0] = -Sin[Ya];

matrice[0][1] = Cos[Za]*Sin[Ya]*Sin[Xa] - Sin[Za]*Cos[Xa];
matrice[1][1] = Sin[Za]*Sin[Ya]*Sin[Xa] + Cos[Xa]*Cos[Za];
matrice[2][1] = Sin[Xa]*Cos[Ya];

matrice[0][2] = Cos[Za]*Sin[Ya]*Cos[Xa] + Sin[Za]*Sin[Xa];
matrice[1][2] = Sin[Za]*Sin[Ya]*Cos[Xa] - Cos[Za]*Sin[Xa];
matrice[2][2] = Cos[Xa]*Cos[Ya];


/* Rotation des sommets de l'objet */
for(i=0; i<Nb_points; i++)
{
Point3D[i].x = (int) (matrice[0][0]*Sommet[i].x
+ matrice[1][0]*Sommet[i].y
+ matrice[2][0]*Sommet[i].z);

Point3D[i].y = (int) (matrice[0][1]*Sommet[i].x
+ matrice[1][1]*Sommet[i].y
+ matrice[2][1]*Sommet[i].z);

Point3D[i].z = (int) (matrice[0][2]*Sommet[i].x
+ matrice[1][2]*Sommet[i].y
+ matrice[2][2]*Sommet[i].z);
}
return (point3D**)Point3D;
}

/************************************************** **************************/
/* Projection() : convertit les points 3D en 2D après la rotation */
/************************************************** **************************/
point2D** Projection(point2D *Point2D)
{
int i;

float fx;
float fy;
int x, y;

for(i=0;i<Nb_points;i++)
{
fx = (Point3D[i].x * 256 ) / (Point3D[i].z + Zoff) + Xoff ;
fy = (Point3D[i].y * 256 ) / (Point3D[i].z + Zoff) + Yoff ;

// partie entière des coordonnées
x = (int) floor(fx);
y = (int) floor(fy);

// génération du tableau 2D
Point2D[i].x = x;
Point2D[i].y = y;

}
return (point2D**)Point2D;
}

/************************************************** **************************/
/* translation() : fait en sorte que le point (0,0) soit au centre de */
/* l'écran */
/************************************************** **************************/

void translation(int x, int y, int R, int G, int B) {
unsigned short *VideoBuffer = (unsigned short *) 0x6000000;
// Passer en mode 3:
REG_DISPCNT= (0x3 | 0x400);

x = x + 120;
y = 80 - y;

VideoBuffer[y * 240 + x] = RGB(R, G, B);
}

/************************************************** **************************/
/* axes() : génération des axes après translation */
/************************************************** **************************/
void axes(void) {
int x2;
int y2;

for (x2= -120; x2< 120; x2= x2+1) {
translation(x2,0, 20, 20, 20);
}

for (y2=-80; y2<160; y2++) {
translation(0,y2, 20, 20, 20);
}
}

/************************************************** **************************/
/* Afficher() : dessine la scene a l'ecran */
/************************************************** **************************/

void Afficher(int couleur)
{
int i;

for (i=0;i<8;i++)
{
translation(Point2D[i].x,Point2D[i].y, 20, 20, 20);
}
}

/************************************************** **************************/
/* Line() : trace une ligne entre deux points */
/************************************************** **************************/

void Line(int x1,int y1, int x2,int y2)
{
int xx,yy;
int Dx,Dy;
int xincr,yincr;
int erreur;
int i;

/* On initialise les variables */
Dx = abs(x2-x1);
Dy = abs(y2-y1);

/* On détermine dans quel sens varie la droite */
if(x1<x2)
xincr = 1;
else
xincr = -1;

if(y1<y2)
yincr = 1;
else
yincr = -1;

/* Trace de ligne */
xx = x1;
yy = y1;

if(Dx>Dy)
{
erreur = Dx/2;
for(i=0;i<Dx;i++)
{
xx += xincr;
erreur += Dy;
if(erreur>Dx)
{
erreur -= Dx;
yy += yincr;
}
translation(xx,yy, 0, 0, 0);
}
}
else
{
erreur = Dy/2;
for(i=0;i<Dy;i++)
{
yy += yincr;
erreur += Dx;
if(erreur>Dy)
{
erreur -= Dy;
xx += xincr;
}
translation(xx,yy, 0, 0, 0);
}
}
}

/************************************************** **************************/
/* Afficher() : dessine la scene a l'ecran */
/************************************************** **************************/
void fildefer(point2D *Point2D) {

for (int i =0; i<12; i++) {
Line (Point2D[Poly[i].a].x, Point2D[Poly[i].a].y, Point2D[Poly[i].b].x, Point2D[Poly[i].b].y);
Line (Point2D[Poly[i].a].x, Point2D[Poly[i].a].y, Point2D[Poly[i].c].x, Point2D[Poly[i].c].y);
Line (Point2D[Poly[i].b].x, Point2D[Poly[i].b].y, Point2D[Poly[i].c].x, Point2D[Poly[i].c].y);
}
}

/************************************************** **************************/
/* InitSegment() : calcule les coordonnées x de départ et d'arrivée pour */
/* chaque ligne horizontale du polygone */
/************************************************** **************************/
void InitSegment(int x1, int y1, int x2,int y2)
{
int temp,y;
long x,pas;

if(y2!=y1)
{
if(y2<y1)
{
temp=y1;
y1=y2;
y2=temp;

temp=x1;
x1=x2;
x2=temp;
}

x = x1<<8;
pas= ((x2-x1)<<8)/(y2-y1);

x+=pas;
y1++;

for(y=y1;y<=y2;y++)
{
if (y>= -80) {
//if(y>=-80) l'axe des ordonnées va de -80 à 80

/* y + 100 : dans fillpoly[], l'index 0 renvoie le point d'abscisse -100
pour modifier le point d'abscisse y, on cherche l'index y+100
*/
if(fillpoly[y+100].startx == -16000) {
fillpoly[y+100].startx = x>>8;
} else {
fillpoly[y+100].endx = x>>8;
}
}
x+=pas;
}

}
}

/************************************************** **************************/
/* Hline() : s'occupe de remplir le polygone */
/************************************************** **************************/
void Hline()
{
int x1, x2;

for (int i=-0; i<200; i++) {
if (fillpoly[i].startx != -16000 && fillpoly[i].endx != -16000) {
if (fillpoly[i].startx < fillpoly[i].endx) {
x1 = fillpoly[i].startx;
x2 = fillpoly[i].endx;
}
else
{
x1 = fillpoly[i].endx;
x2 = fillpoly[i].startx;
}

for (int ii=x1; ii<=x2; ii++)
{
//VideoBuffer[y * 240 + x] = RGB(20,20,20);
translation(ii,fillpoly[i].y, 20, 20, 20);
}
}
}
}

/************************************************** **************************/
/* fillpoly() :remplissage de touts les polygones de la figure */
/************************************************** **************************/

void Drawpolygones (point2D *Point2D, polygones *Poly) {

for (int i =0; i<12; i++) {
Initialiserfillpoly(fillpoly);
InitSegment (Point2D[Poly[i].a].x, Point2D[Poly[i].a].y, Point2D[Poly[i].b].x, Point2D[Poly[i].b].y);
InitSegment (Point2D[Poly[i].a].x, Point2D[Poly[i].a].y, Point2D[Poly[i].c].x, Point2D[Poly[i].c].y);
InitSegment (Point2D[Poly[i].b].x, Point2D[Poly[i].b].y, Point2D[Poly[i].c].x, Point2D[Poly[i].c].y);
Hline();
}
}


/************************************************** **************************/
/* reset_screen() : efface l'écran */
/************************************************** **************************/
void reset_screen() {
unsigned short *VideoBuffer = (unsigned short *) 0x6000000;
// Passer en mode 3:
REG_DISPCNT= (0x3 | 0x400);

int xx = 0;
int yy = 0;

for (yy=0; yy <160; yy++) {
for (xx=0; xx<240; xx++) {
VideoBuffer[yy * 240 + xx] = RGB(90,90,90);
}
}

}

/************************************************** ************************************************** ************************************************** *****/
/************************************************** ************************************************** ************************************************** *****/


/************************************************** **************************/
/*** MAIN */
/************************************************** **************************/
int main(void)
{
//ham_Init();
unsigned short *VideoBuffer = (unsigned short *) 0x6000000;
//Passer en mode 3:
REG_DISPCNT= (0x3 | 0x400);

while(true)
{
int xa,ya,za;
axes();
bool bouton_presse = 0;

// Initialisations
Init_Sinus(Sin, Cos);
Initialiser(Sommet);
Initialiser2(Poly);

xa=ya=za=0;

Rotation(Point3D,0,0,0);
Projection(Point2D);

Afficher(100);

Drawpolygones(Point2D, Poly);
fildefer(Point2D);



while (bouton_presse == 0) {
if (F_CTRLINPUT_UP_PRESSED)
{
bouton_presse = 1;
reset_screen();
axes();
ya = ya + 10;

if (ya >= 360) {
ya = 0;
}

Rotation(Point3D,xa,ya,za);
Projection(Point2D);
Afficher(100);
Drawpolygones(Point2D, Poly);
fildefer(Point2D);

bouton_presse = 0;
}

if (F_CTRLINPUT_DOWN_PRESSED)
{
reset_screen();
axes();
ya = ya - 10;

if (ya <= 0) {
ya = 350;
}

Rotation(Point3D,xa,ya,za);
Projection(Point2D);
Afficher(100);
Drawpolygones(Point2D, Poly);
fildefer(Point2D);

}

if (F_CTRLINPUT_LEFT_PRESSED)
{
reset_screen();
axes();
za = za - 10;

if (za <= 0) {
za = 350;
}

Rotation(Point3D,xa,ya,za);
Projection(Point2D);
Afficher(100);
Drawpolygones(Point2D, Poly);
fildefer(Point2D);

}

if (F_CTRLINPUT_RIGHT_PRESSED) // Pour la droite
{
reset_screen();
axes();
za = za + 10;

if (za >= 360) {
za = 0;
}

Rotation(Point3D,xa,ya,za);
Projection(Point2D);
Afficher(100);
Drawpolygones(Point2D, Poly);
fildefer(Point2D);

}

} // while

while (bouton_presse == 1) {
if ( F_CTRLINPUT_UP_PRESSED
|| F_CTRLINPUT_DOWN_PRESSED
|| F_CTRLINPUT_LEFT_PRESSED
|| F_CTRLINPUT_RIGHT_PRESSED)
{
axes();
bouton_presse = 0;
}
} // while



}
return 0;
}

/* END OF FILE */

kinski
25/05/2007, 10h56
Merci pour vos réponses.
...Je sais que c'est pas le but de ce sujet mais je poste quand même le code corrigé (mais comme viens de le dire Nesgba pas du tout optimisé) si jamais quelqu'un passe par là et est intéréssé par mon horreur :p :

Super initiative, merci ! Tout mon soutien pour ton projet.

Arcadia
25/05/2007, 11h19
Pareil que kinski ! Merci pour la communauté. Et ton code, qu'il soit beau ou non optimisé, au moins il a le mérite d'exister ;)...