L'algorithme de remplissage de trianglesVoici l'algorithme en language C. C'est ce que je préfère, ça permet une traduction vers tous les autres langages je trouve.
Pour fonctionner, il est nécessaire que les couples de coordonnées soient triées du y le plus petit au y le plus grand.
- Code:
-
void FillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color) {
int dx1 = x3 - x1;
int dy1 = y3 - y1;
int sgn1 = Sign(dx1);
dx1 = Abs(dx1);
int err1 = 0;
int dx2 = x2 - x1;
int dy2 = y2 - y1;
int sgn2 = Sign(dx2);
dx2 = Abs(dx2);
int err2 = 0;
int xl = x1;
int xr = x1;
if (y1 == y2)
xr = x2;
for (int y = y1; y < y3; y++) {
DrawLine(xl, y, xr, y, color);
err1 += dx1;
while (err1 > dy1) {
xl += sgn1;
err1 -= dy1;
}
if (y == y2) { // On passe au tracé du second "demi-triangle"
dx2 = x3 - x2;
dy2 = y3 - y2;
sgn2 = Sign(dx2);
dx2 = Abs(dx2);
err2 = 0;
}
err2 += dx2;
while (err2 > dy2) {
xr += sgn2;
err2 -= dy2;
}
}
}
Nous verrons plus tard qu'il est facilement transciptable en assembleur Z80.
Avec cet algorithme, on peut maintenant tracer des triangles remplis avec une couleur déterminée.
Pour pouvoir tracer des objets un peu plus complexe, il suffira de tracer tous les triangles définissant ces objets.
Ensuite, seconde partie: animer un objet.
Pour cela, j'ai ajouté une option à Make3DFrame qui me permet de générer une suite de coordonnées de triangles,
pour définir un objet, et ce pour chaque image (que je nomerai "frame" par la suite).
Ensuite s'est posé un problème:
pour animer un objet, il faut donc créer une suite d'images définissant la position et/ou la forme de cet objet.
Ce pour quoi Make3DFrame est prévu, jusque là pas de problème.
Mais côté CPC, il faudra ensuite:
- Afficher la frame 0,
- Effacer la frame 0,
- Afficher la frame 1,
- Effacer la frame 1,
- Afficher la frame 2,
- Effacer la frame 2...
Et ainsi de suite jusqu'à la dernière frame, puis reboucler sur la première.
Dans l'idéal, On pourrait dire que l'algorithme d'animation est le suivant:
- Effacer frame n-1
- Afficher frame n
- Incrémenter n
- Si n > dernière frame, alors n=0 (pour rebouclage)
Ce qui nous fait en gros une boucle.
Sur CPC, on ajouterai même un "wait vbl" au début de la boucle, pour synchroniser notre animation avec le balayage écran.
Oui mais voilà, si la routine d'effacement + d'affichage dépasse le temps d'affichage d'une image (environ 20 milli secondes sur CPC),
on obtient un clignottement très désagréable...
La routine de tracé de triangle est rapide, mais malheureusement pas assez pour permettre ce genre de chose.
Il a donc fallu utiliser une "astuce" : le double buffering.
Cette technique consiste en gros à utiliser 2 pages écran, à dessiner dans une page pendant que l'autre est affichée, puis faire un "échange" de
la page affichée.
Ceci fonctionne très bien sur CPC, grace au CRTC, qui permet de définir justement l'adresse de la page écran (qui par défaut est en #C000).
Ensuite, plutôt que d'effacer "bêtement" tout l'écran, il suffit d'effacer que ce qui a été dessiné.
Pour cela j'ai donc utilisé au début la même routine de tracé de triangles, simplement en lui passant en paramètre une couleur égale à zéro.
Ceci semble logique, vu que je connais les coordonnées des triangles à effacer (ils sont dans la liste).
Mais la routine de tracé de triangles utilise pas mal le processeur, et je me suis dit qu'il serait plus rapide d'effacer un "rectangle"
dans lequel serait contenus tous les triangles affichés.
Facile également, vu que l'on connait les coordonnées de tous les triangles de la "frame".
Il n'y a qu'à déterminer les bornes xmin, ymin et xmax, ymax de la frame en parcourant les coordonnées de tous les triangles.