/* Programme test de tracé 3D affichant un polygone qui effectue une rotation en Mode X. L'espace de visualisation est congru à l'espace monde. Le point de vue est fixé à l'origine (0,0,0) de l'espace monde, en regardant dans la direction des Z négatifs croissants. Un système de coordonnées main-droite est utilisé. Testé avec Borland C++ 4.02 en modèle small par Jim Mischel 12/16/94 */ #include #include #include #include #include "polygon.h" void main(void); /* Offset de base de la page dans laquelle afficher */ unsigned int CurrentPageBase = 0; /* Rectangle de clipping; clip l'écran */ int ClipMinX=0, ClipMinY=0; int ClipMaxX=SCREEN_WIDTH, ClipMaxY=SCREEN_HEIGHT; /* Rectangle spécifiant la superficie à effacer dans chaque page */ struct Rect EraseRect[2] = { {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}, {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT} }; /* Transformation de l'espace objet d'un polygone à l'espace monde. Configuré initialement pour n'effectuer aucune rotation et pour déplacer le polygone dans l'espace monde à -140 unités de l'origine vers l'axe Z . A partir du point de vue, -140 vers l'axe Z signifie 140 unités dans le sens de l'observateur. Le programme change dynamiquement la rotation et la translation */ static double PolyWorldXform[4][4] = { {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, -140.0}, {0.0, 0.0, 0.0, 1.0} }; /* Transformation de l'espace monde à l'espace de visualisation. Dans ce programme, le point de vue est fixé à l'origine de l'espace monde, en regardant vers le bas de l'axe Z dans le sens des Z négatifs croissant, donc l'espace de visualisation est identique à l'espace monde ; c'est la matrice identité. */ static double WorldViewXform[4][4] = { {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0} }; static unsigned int PageStartOffsets[2] = {PAGE0_START_OFFSET,PAGE1_START_OFFSET}; int DisplayedPage, NonDisplayedPage; void main() { int Done = 0; double WorkingXform[4][4]; static struct Point3 TestPoly[] = {{-30,-15,0,1},{0,15,0,1},{10,-5,0,1}}; #define TEST_POLY_LENGTH (sizeof(TestPoly)/sizeof(struct Point3)) double Rotation = M_PI / 60.0; /* rotation initiale = 3 degrés */ union REGS regset; Set320x240Mode(); ShowPage(PageStartOffsets[DisplayedPage = 0]); /* Continue d'effectuer la rotation du polygone, le traçant dans la page offscreen , et permutant à la page pour l'afficher */ do { CurrentPageBase = /* sélectionne l'autre page pour y tracer */ PageStartOffsets[NonDisplayedPage = DisplayedPage ^ 1]; /* Modifie la matrice de transformation de l'espace objet en espace monde pour la rotation courante autour de l'axe Y */ PolyWorldXform[0][0] = PolyWorldXform[2][2] = cos(Rotation); PolyWorldXform[2][0] = -(PolyWorldXform[0][2] = sin(Rotation)); /* Concatène les transformations objet/monde et monde/visualisation pour réaliser une matrice de transformation qui convertit les points de l'espace objet en ponts de l'espace de visualisation avec une seule opération */ ConcatXforms(WorldViewXform, PolyWorldXform, WorkingXform); /* Vide la partie de la page offscreen dans laquelle on a tracé la dernière fois, puis réinitialise la superficie effacée */ FillRectangleX(EraseRect[NonDisplayedPage].Left, EraseRect[NonDisplayedPage].Top, EraseRect[NonDisplayedPage].Right, EraseRect[NonDisplayedPage].Bottom, CurrentPageBase, 0); EraseRect[NonDisplayedPage].Left = EraseRect[NonDisplayedPage].Top = 0x7FFF; EraseRect[NonDisplayedPage].Right = EraseRect[NonDisplayedPage].Bottom = 0; /* Transforme le polygone, le projette sur l'écran et l'affiche */ XformAndProjectPoly(WorkingXform, TestPoly, TEST_POLY_LENGTH,9); /* Permute pour afficher la page dans laquelle nous venons de tracer */ ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]); /* Effectue une rotation de 6 degrés autour de l'axe Y */ if ((Rotation += (M_PI/30.0)) >= (M_PI*2)) Rotation -= M_PI*2; if (kbhit()) { switch (getch()) { case 0x1B: /* Esc pour quitter */ Done = 1; break; case 'A': case 'a': PolyWorldXform[2][3] -= 3.0; break; case 'T': case 't': if (PolyWorldXform[2][3] < -40.0) PolyWorldXform[2][3] += 3.0; break; case 0: /* code étendu */ switch (getch()) { case 0x4B: /* gauche (-X) */ PolyWorldXform[0][3] -= 3.0; break; case 0x4D: /* droite (+X) */ PolyWorldXform[0][3] += 3.0; break; case 0x48: /* haut (+Y) */ PolyWorldXform[1][3] += 3.0; break; case 0x50: /* bas (-Y) */ PolyWorldXform[1][3] -= 3.0; break; default: break; } break; default: /*pause avec les autres touches clavier */ getch(); break; } } } while (!Done); /* Revient en mode texte et quitte */ regset.x.ax = 0x0003; /* AL = 3 sélectionne le mode texte 80x25 */ int86(0x10, ®set, ®set); }