CODINGSDCC TUT'S PAR STEPHBB75 ★ 3D Optimisation ★

Sdcc - 19 - 3D - OptimisationCoding Sdcc Tut's Par Stephbb75

3D temps IREEL

Optimisation


Comme on a vue jusqu'ici, ce qui prend le plus de temps se sont les calcules de projection et surtout de rotation, on vas optimiser un peut cela.
On débute pas le tableau des Sinus et Cosinus, on vas les passer sur un char (soit un octets) à la place d'un float (4 octets), en plus de gagner de la place en mémoire, on vas y gagner beaucoup en temps de calcule, oui, faire un calcule sur un entier est nettement plus rapide sur un Z80 que sur des flottant.
Mais comment passer une valeur de sinus qui va de 0 à 1 sur un entier ?
Tout simplement en multiplient la valeur par 127. Mais il faut aussi quand on vas faire nos calcule diviser pas quelques choses, sinon les valeurs vont être beaucoup trop grande et cela sera incorrecte come calcule.
On vas donc diviser par 128 ... tien, mais une division par 128 revient aussi à faire un décalage de 8 vers la droite non !!.
De plus, on ne calcule plus une matrice avant de faire la rotation.

Changement dans le code...
Je repars du fichier cubef3.c précédent. On vas déjà modifier la définition des deux pointeurs sur les tableaux pour les sin et cos, cela devient char* TSIN; et char* TCOS; (j'ai changer le nom au passage, comme cela pas de confusion).
Pour la fonction de rotation, on change tout aussi, vous verrez cela dans le code, le principale c'est le calcule avec les sin et cos qui prennent la forme ( (x) * TCOS[angle] + (y) * TSIN[angle] ) >> 7, on voie bien à la fin le décalage de 7 à droite... j'en profite aussi, comme les calcules sont presque à chaque fois identique par faire 2 defines comme ceci :
#define ROT_I(a,i,j) (((i)*TCOS[a]+(j)*TSIN[a])>>RSHIFT8)
#define ROT_J(a,i,j) ((-(i)*TSIN[a]+(j)*TCOS[a])>>RSHIFT8)

Voici Le code des nouvelles fonctions :

/* Tableaux precalcules de sinus et cosinus */
char* TSIN;
char* TCOS;

#define FLOAT_MULT 127  // non utilisé ici, mais utiliser pour généré les valeurs.
#define RSHIFT8     7    // décalage de 7 à droite  (10000000)

#define DEG2RAD(a) (((a)*PI)/180.0)
#define ROT_I(a,i,j) (((i)*TCOS[a]+(j)*TSIN[a])>>RSHIFT8)
#define ROT_J(a,i,j) ((-(i)*TSIN[a]+(j)*TCOS[a])>>RSHIFT8)


void Rotation(int Xa, int Ya, int Za)
{
  int i,a,b;
  int x;

   for(i = 0; i < Nb_points; i++)
   {
      /*   rotation X */
      a = Sommet[i].y;
      b = Sommet[i].z;
      Point3D[i].x = Sommet[i].x;
      Point3D[i].y = ROT_I(Xa,a,b);
      Point3D[i].z = ROT_J(Xa,a,b);

      /*  rotation Y */
      a = Point3D[i].x;
      b = Point3D[i].z;
      Point3D[i].z = ROT_J(Ya,a,b);
      Point3D[i].x = ROT_I(Ya,a,b);

      /*  rotation Z */
      a = Point3D[i].x;
      b = Point3D[i].y;
      Point3D[i].y = ROT_J(Za,a,b);
      Point3D[i].x = ROT_I(Za,a,b);
   }
}

Vous trouverez dans le ZIP le fichier GenSC.c qui permet de générer le fichier SINCOSB.DAT qui contient les valeurs des sinus et cosinus utilisé dans le programme cubef4.c.

Voyons maintenant ce que cela donne l'anim de gauche est le code avant optimisation, à droite le code optimisé :

  
L'animation est fidèle en temps vis à vis d'un CPC

Donc, comment dire, y'a pas photo quoi !!

Je vais continuer mais la ce n'est pas vraiment de l'optimisation, je vais regrouper toutes les données du cube dans une structure, c'est plus une préparation pour la suite...
On va donc créer une structure obj3D, celle ci vas contenir les valeurs des points initiaux qui se trouvais avant dans Sommet, les points pour les calcule qui se trouvait dans Point3D et les points pour l'affichage 2D qui se trouvaient dans Point2D.
Bien sur je change aussi les fonctions pour y passer un pointeur sur la structure.
Remarque, la structure est représenté par un pointeur, celui-ci est initialiser à la suite des tableaux de sinus et cosinus, avec plusieurs objets, il faut faire attention à sa mémoire...
Au passage dans la structure point2D, on met x en unsigned int et y en unsigned char (la on vas gagner 8 octets).
On change aussi dans la structure point3D le long pas int, mais la il faut changer aussi la valeurs de chaque point du cube, on les passe de la valeur 100 à la valeur 50, il faut aussi modifier la valeur de Zoff en le passent à 300 (sinon le cube est plus petit...).
On vas aussi modifier la fonction FilDeFer, au lieux d'appeler la fonction ligne qui appel la fonction lineBresenham on appel directement la fonction lineBresenham dans la fonction FilDeFer, ce qui vas nous évité de faire 12 appel à une fonction, donc en asm 12 CALL (en plus du passage des paramètres à chaque fois), soit cela ne vas pas nous faire gagner beaucoup de temps mais quand même !
Vous trouverez tout ces changement dans le fichier cubef5.c dans le fichier ZIP qui suit.

Voila, comme d'hab, le tout se trouve dans se ZIP, une 3D qui est un peut plus rapide :-)

Nous pouvons passer à la suite ... les faces pleines...

stephbb75

ANNÉE: 2013
★ AUTEUR: Stephbb75

Page précédente : Sdcc - 18 - 3D - Fil de Fer

CPCrulez[Content Management System] v8.7-desktop/cache
Page créée en 070 millisecondes et consultée 1106 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.