Nous allons continuer à utiliser le framebuffer pour
dessiner diverses figures. En fait il s’agit d’utiliser la zone mémoire
résultant du mapping pour renseigner les octets nécessaires avec la couleur
désirée, le reste restant inchangée par rapport aux programmes précédents. Mais
nous n’utiliserons que la résolution en 32 bits (soit 4 octets soit un
registre) pour l’affichage.
Donc dans ce programme, nous modifierons la routine dessin
pour afficher les différentes figures.
Mais tout d’abord nous préparons deux sous routines : la
première codeRGB pour concaténer les 3 couleurs rouge, vert et bleu dans le
même registre de 32 bits, le 4ième octet sera ici mis toujours à
zéro. La deuxième aff_pixel_codeRGB32 placera le code couleur calculé par la
précédente sur les 4 octets de la mémoire du mapping à la position X,Y
correspondante de l’écran. Il faut donc multiplier la position y par le nombre
de pixels contenus dans la largeur de l’écran et ajouter le nombre de pixel X puis
multiplier le tour par 4 pour obtenir la correspondance en mémoire. En fait
pour cette dernière opération il suffit d’utiliser l’instruction str
r3,[r9,r0,lsl #2]. Vous remarquerez que je ne respecte pas de norme dans
l’utilisation des registres puisqu’ici j’utilise le registre r9 dans toutes les
sous procédures pour véhiculer l’adresse de début du mapping. Mais cela n’a pas
beaucoup d’importance puisque toutes ces routines sont internes au programme.
Ensuite, nous écrivons toutes les routines de dessin en
essayant de passer les mêmes données dans les mêmes registres (r0, r1 pour la
position x,y, r2 pour la largeur de l’écran (mais que j’ai appelé malencontreusement
longueur de la ligne), r3 pour le code couleur).
Voyons une des plus simples : traçage d’une ligne
horizontale : traceDroiteH. En argument, nous passons les positions X de
début et de fin de la droite puis la
longueur de la ligne (largeur de l’écran) la couleur et la position Y. Dans la
routine, nous vérifions que la position X de fin est supérieure à la position
de début puis nous effectuons une boucle qui va faire varier la position x du
début à la fin et appeler la fonction d’affichage du pixel précédente. Nous faisons la même chose pour
tracer une ligne verticale sauf que nous faisons varier la position y du début
à la fin.
Pour tracer une ligne quelconque, j’ai adapté et converti un
algorithme de Bresenham trouvé sur internet. Vous trouverez sur Wikipédia,
l’analyse complète de cet algorithme.
Pour tracer un polygone, nous créons en mémoire une série de
positions X,Y de chaque sommet et dans
la routine, il nous suffira de tracer les droites qui relient ces points sans
oublier de fermer le polygone. Pour le remplir, j’ai écrit une procédure au
plus vite qui n’est certainement pas la bonne solution. En effet elle utilise
une zone mémoire équivalent à la taille de la zone du mapping pour détecter les
points se trouvant au même niveau horizontal sur les bords du polygone puis
tracer des droites horizontales pour relier ces 2 points. Hélas elle fonctionne
très mal pour un polygone convexe (voir le résultat du polygone vert) que l’on
peut rattraper en remplissant des triangles (voir le résultat en bleu).
Pour tracer un cercle, j’ai aussi adapté et converti un
algorithme trouvé sur internet. Celui çi calcule et trace les positions X,Y
d’un octant (1/8 de cercle) puis par symétrie, affiche toutes les autres
positions. Ces 2 derniers algorithmes minimisent les opérations arithmétiques
couteuses mais je n’ai pas optimisé ces routines en assembleur ARM
(pistes : meilleure utilisation des registres, réduction des push et pop,
etc).
Je vais me pencher sur l’écriture d’une petite animation
pour voir si ces routines sont efficaces.
En écrivant ce post et en balayant ce programme, je me suis
rendu compte que j’avais codé de nombreuses incohérences : fatigue des
fêtes !!! Ce code sera certainement à reprendre pour amélioration !!!
Aucun commentaire:
Enregistrer un commentaire