Obligement - L'Amiga au maximum

Mercredi 26 septembre 2018 - 07:41  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles en d'autres langues


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : C - Graphismes 3D en C (animation)
(Article écrit par Pascal Amiable et extrait d'Amiga News Tech - septembre 1990)


Ce mois-ci, je vous propose de la 3D animée. En effet, maintenant que nous avons tous les outils nécessaires à l'affichage d'un objet 3D sur l'écran de notre Amiga, nous allons étudier les moyens efficaces nous permettant de l'animer. Vous vous êtes sans doute rendu compte que l'animation proposée le mois dernier était lente et peu satisfaisante du point de vue visuel. Il y a deux raisons à cela. Le recalcul systématique de la matrice de projection en double précision est inutile et très coûteux en temps de calcul. Le tracé et l'effacement sur un écran standard Intuition est visible. Nous allons essayer de résoudre ces deux problèmes.

Affichage sur écran avec double tampon mémoire

Au niveau de l'affichage, nous devons créer un écran accessible rapidement aux routines de tracé et où l'on puisse afficher et effacer un objet non pas ligne par ligne (ce qui crée un phénomène de scintillement disgracieux) mais en une seule fois. La solution est simple. On crée un écran avec deux zones de tracé, et l'on écrit dans une des zones pendant que l'on affiche l'autre. On permute ensuite les deux zones et le tour est joué ! C'est ce que l'on appelle un écran "double buffer" (double tampon mémoire).

Pour créer un écran à double tampon mémoire, plus question d'utiliser Intuition dont la structure ralentit notablement les routines de tracé. Nous allons créer notre écran directement à l'aide des fonctions de la bibliothèque graphic.library.

L'Amiga crée un écran à partir des instructions que vous lui donnez. Ces instructions doivent être organisées sous la forme d'une structure dénommée "View". A un "View" on associe une ou plusieurs zones d'affichage dénommées "ViewPort". Il est à noter que plusieurs ViewPort de résolutions et de types différents peuvent cohabiter sur le même View. Chaque ViewPort est défini par sa taille, sa position sur le View, son mode de visualisation, sa table de couleurs et un pointeur sur une première structure "RasInfo".

Chaque structure RasInfo contient des informations concernant une des "BitMaps" (zone de traçage) liée au ViewPort (position par rapport au View et pointeur sur la BitMap). Une BitMap est, quant à elle, définie par sa taille (horizontale et verticale) et le nombre de "bitplanes" qu'elle contient. Les structures RasInfos étant comme les ViewPorts chaînées entre elles.

A partir de cette brève description de principe, comment allons-nous définir notre écran à double tampon mémoire. Nous allons commencer par déclarer un View et ViewPort soit :

struct View view;
struct ViewPort viewport;

Comme nous avons besoin de deux zones de traçage (deux tampons mémoire), il faut déclarer deux structures RasInfo et deux BitMap :

struct RasInfo rasinfos[2];
struct BitMap bitmaps[2];

Maintenant, il ne nous reste plus qu'à initialiser tout cela (voir la fonction void ouvrecran()). Donc, on initialise le View grâce à InitView(&view) et le ViewPort avec InitVPort(&viewport). 0n associe le ViewPort au View : view.viewport = &viewport et on sélectionne le mode associé au View : view.Modes = MODE.

On initialise les deux BitMap à l'aide de la fonction InitBitMap(&bitmap[i],profondeur,largeur,hauteur). On initialise les deux structures RasInfo (Cf. listing) et on remplit la structure ViewPort (c'est très simple). Pour la table des couleurs, on commence par réserver une zone pour cette table.

viewport.ColorMap = (struct ColorMap*)GetColorMap(COLOR);

...et ensuite on charge cette table dans le ViewPort grâce à :

Load RGB4(&viewport,&colortable[0],COLOR);

Il nous reste à réserver les zones mémoire nécessaires aux deux bitMap et à remplir ces zones avec zéro. On alloue chaque plan de la BitMap à l'aide de la fonction AllocRaster(largeur,hauteur) et on les met à zéro à l'aide du Blitter avec :

BltClear((UBYTE*)bitmap[i].Planes[i],RASSIZE(largeur,hauteur),0);

Bien, maintenant que nous manque-t-il pour créer notre écran ? Déjà nous n'avons pas de crayons pour écrire dans nos bitmaps. Pour combler ce manque, il nous faut définir deux structures "RastPort" (une par BitMap) qui servent à écrire dans la mémoire. Pour chaque RastPort on appelle InitRastPort(&rastport) et on associe au RastPort une BitMap : rastport[i]BitMap = &bitmap[i].

Ensuite, il faut préparer le double tampon mémoire pour l'affichage, c'est-à-dire qu'il va falloir créer deux listes Copper différentes, une associée à chaque tampon mémoire. La séquence est la suivante :

MakeVPort(&view,&viewport);
MrgCop(&view);

...génère la première liste Copper dont on va stocker les pointeurs dans LOF[DB1] et SHF[DB1]. On change dans le ViewPort le pointeur sur la structure RasInfo. C'est-à-dire que l'on pointe sur la structure 2, viewport.RasInfo = &rasinfo[DB2]; et rasinfo[DB2].Next = &rasinfo[DB1]; (on réalise le chaînage).

On remet NULL les deux morceaux de liste Copper afin de les faire régénérer par l'Amiga.

view.LofCprList = NULL
view.SFCprlist = NULL
MakeVPort(&view,&viewport);
MrgCop(&view);

...génère la deuxième liste Copper, dont on stockera également les pointeurs dans LOF[DB2] et SHF[DB2].

Le programme principal

C'est presque terminé. Maintenant, il ne nous reste plus qu'à regarder le programme principal.
  • 1. On appelle Init() qui ouvre la bibliothèque graphique graphic.library et sauvegarde l'écran courant.
  • 2. On charge l'objet courant à l'aide des fonctions chargepoint() et chargeligne().
  • 3. On stocke dans deux tableaux les valeurs des sinus et cosinus par degré afin d'éviter de les recalculer à chaque passage.
  • 4. On appelle la fonction ouvrecran() qui initialise notre View;.
  • 5. On calcule une première fois l'objet (rotations() et affiche()).
  • 6. Dans la boucle principale (que l'on interrompt en appuyant sur le bouton de gauche de la souris).
  • 6a. On définit le RastPort que l'on va utiliser (on écrit dans la zone mémoire qui n'est pas affichée).
  • 6b. On incrémente les deux angles de rotation.
  • 6c. On fait tourner l'objet et on l'affiche.
  • 6d. On affiche l'écran qui vient d'être dessiné et on recommence en changeant de Rastport.
  • 7. Une fois sorti de la boucle, on recharge l'ancien écran : (LoadView(écran-sauvegardé)); et on libère tout ce que l'on a alloué (libère()).
Avec cette méthode, l'animation devient fluide, il ne nous reste plus qu'à accélérer le calcul de la fonction rotation().

Nouvelle fonction rotation()

Pour diminuer les temps de calcul, l'idée est simple, éviter le recalcul des sinus et cosinus à chaque fois. Pour ce faire, on stocke dans deux tables sinus[360] et cosinus[360] les valeurs des sinus et cosinus tous les degrés et on les stocke sous forme de "float". Ensuite, on multiplie dans la fonction rotation() les coordonnées par les valeurs associées de ces tables et on gagne du temps.

Sous Lattice v5.00

Une autre méthode que j'utilise avec le Lattice v5.00 pour accélérer le calcul est d'utiliser la bibliothèque de fonctions mathffp.library. Cette bibliothèque utilise le format de calcul Fast Floatingpoint de Motorola qui permet un gain de temps au dépens de la précision (qui n'est nullement importante ici). On compile donc le programme anim.c avec lc.ff.lcf anim.c et le tour est joué.

Je ne sais si cela se fait automatiquement à la compilation sous les versions antérieures du Lattice ou sous Manx. Il vous reste toutefois la possibilité de les utiliser en appelant directement les fonctions de la bibliothèque. A noter qu'il est nécessaire d'avoir dans le tiroir Libs: la bibliothèque mathffp.library pour que le programme fonctionne.

Les fichiers objet

Les fonctions chargeligne() et chargepoint() ayant été modifiées les tableaux de points et de lignes ont été également modifiés. Un exemple valant mieux qu'un grand discours, voici l'exemple d'une pyramide à base carrée.

C

Conclusion

Le programme est disponible en source et exécutable sur 3615 Comrev et enfin, si vous voulez en savoir plus sur la programmation des écrans à l'aide de la graphic.library, je vous conseille deux ouvrages : le ROM Kernel Manual en anglais qui est la référence de Commodore pour le programmeur et l'excellent livre de Micro Application : Graphisme sur Amiga, où vous trouverez dans la partie consacrée au langage C de nombreuses explications avec des exemples très didactiques sur ce sujet.

Programme d'animation d'un objet dans l'espace

C
C
C
C
C
C


[Retour en haut] / [Retour aux articles] [Article précédent] / [Article suivant]