/* proj3d-tp.c - Edouard Thiel - 02/06/2001 Compilation : cc proj3d-tp.c -o proj3d-tp `~/helium/helium-cfg --cflags --libs` -lm Exécution : proj3d-tp But du TP : - Programmer des transformations géométriques 3D en coordonnées homogènes : les rotations sur les 3 axes, et la projection conique sur un plan (c-à-d la projection perspective). - L'interface du programme est entièrement fournie. - Les fonctions à compléter sont toutes dans la partie "Algorithmes". */ #include #include He_node *princ, *canvas, *panel1, *panel2, *mess1, *fen1, *panel3, *text_aX, *text_aY, *text_aZ, *text_dD; int c_gris, c_rouge, c_vert, c_bleu, c_jaune, c_cyan, c_magenta; double angleP = 5, distP = 1.02; #define ZEDIM 4 typedef double Matr[ZEDIM][ZEDIM]; /* [ligne][colonne] */ typedef double Vec[ZEDIM]; /*--------------------------- A F F I C H A G E ------------------------------*/ void init_couleurs () { c_gris = HeAllocRgb (150, 150, 150, he_white); c_rouge = HeAllocRgb (255, 0, 0, he_black); c_vert = HeAllocRgb (0, 255, 0, he_black); c_bleu = HeAllocRgb (0, 0, 255, he_black); c_jaune = HeAllocRgb (255, 255, 0, he_black); c_cyan = HeAllocRgb (0, 255, 255, he_black); c_magenta = HeAllocRgb (255, 0, 255, he_black); } /* * Dessins de base */ void couleur (int coul) { XSetForeground (he_display, he_gc, coul); } void dessin_ligne (Window win, int x1, int y1, int x2, int y2) { XDrawLine (he_display, win, he_gc, x1, y1, x2, y2); } /*-------------------------- A L G O R I T H M E S ---------------------------*/ /* * Affiche la matrice pour la mise au point du programme */ void affi_matr (Matr m) { int i, j; for (i = 0; i < ZEDIM; i++) { for (j = 0; j < ZEDIM; j++) printf ("%2.3f ", m[i][j]); printf ("\n"); } } /* * Initialise la matrice m à la matrice unité */ void matr_unite (Matr m) { /* A COMPLETER */ } /* * Recopie la matrice m dans la matrice res */ void copie_matr (Matr m, Matr res) { /* A COMPLETER */ } /* * Multiplie la matrice m1 par la matrice m2 et place le résultat dans res */ void mult_matr_matr (Matr m1, Matr m2, Matr res) { /* A COMPLETER */ } /* * Multiplie la matrice m1 par le vecteur v2 et place le résultat dans res */ void mult_matr_vec (Matr m1, Vec v2, Vec res) { /* A COMPLETER */ } /* * Fait l'operation : m = T*m * où T est la matrice de la projection conique sur le plan XY * et de centre (0,0,-D) */ void mult_projection (Matr m, double d) { /* A COMPLETER */ } /* * Fait l'operation : m = T*m * où T est la matrice de rotation sur l'axe des X et d'angle r (en degrés) */ void mult_rot_X (Matr m, double r) { /* A COMPLETER */ } /* * Fait l'operation : m = T*m * où T est la matrice de rotation sur l'axe des Y et d'angle r (en degrés) */ void mult_rot_Y (Matr m, double r) { /* A COMPLETER */ } /* * Fait l'operation : m = T*m * où T est la matrice de rotation sur l'axe des Z et d'angle r (en degrés) */ void mult_rot_Z (Matr m, double r) { /* A COMPLETER */ } /* * Calcule la matrice m du produit des transformations simples. */ void calcul_transfo3D (Matr m, double angleX, double angleY, double angleZ, double distD) { /* A COMPLETER */ } /* * Transformation géométrique d'un sommet en coordonnées homogènes : * - on applique la matrice de transformation m au vecteur (x1, y1, z1, 1). * - on obtient un vecteur (x', y', z', t'). * - si t' != 0, le résultat est *x2=x'/t', *y2=y'/t', *z2 = z'/t'. */ void appli_transfo3D (Matr m, double x1, double y1, double z1, double *x2, double *y2, double *z2) { /* A COMPLETER */ } /* * Dessin du cube en projection perspective : * - calcule la matrice m du produit des transformations simples * - applique m aux sommets 3D du cube --> sommets 2D * - adapte les coordonnées des sommets 2D à la taille du canvas * - dessine le cube avec les arêtes Ox en rouge, Oy en vert, oZ en bleu */ void dessin_projection_cube (Window win, int larg, int haut, double angleX, double angleY, double angleZ, double distD) { /* A COMPLETER */ } /*-------------------------------- U T I L E --------------------------------*/ He_node *create_textP (He_node *panel, char *nom, He_notify_proc proc, char *val) { He_node *tmp; HeCreateMessageP (panel, nom, TRUE); tmp = HeCreateText (panel); HeSetTextVisibleLen (tmp, 8); HeSetTextValue (tmp, val); HeSetTextNotifyProc (tmp, proc); HeSetPanelLayout (panel, HE_LINE_FEED); return tmp; } void set_text_double (He_node *hn, double d) { char bla[100]; sprintf (bla, "%.2f", d); HeSetTextValue (hn, bla); } /*--------------------------- C A L L B A C K S ------------------------------*/ void princ_resize (He_node *hn, int width, int height) { HeSetWidth (panel1, width); HeSetWidth (panel2, width); HeJustify (panel2, NULL, HE_BOTTOM); HeExpand (canvas, panel2, HE_BOTTOM); HeExpand (canvas, NULL, HE_RIGHT); HeJustify (fen1, princ, HE_LEFT); } void princ_replace_proc (He_node *hn, int xb, int yb) { HeJustify (fen1, princ, HE_LEFT); HeSetY (fen1, HeGetY(princ)); } void raz_proc (He_node *hn) { HeSetTextValue (text_aX, "0"); HeSetTextValue (text_aY, "0"); HeSetTextValue (text_aZ, "0"); HeSetTextValue (text_dD, "5"); HePostRepaint (canvas); } void canvas_repaint (He_node *hn, Window win) { int larg = HeGetWidth (canvas), haut = HeGetHeight (canvas); double angleX = atof(HeGetTextValue (text_aX)), angleY = atof(HeGetTextValue (text_aY)), angleZ = atof(HeGetTextValue (text_aZ)), distD = atof(HeGetTextValue (text_dD)); HeDrawBg (canvas, he_white); dessin_projection_cube (win, larg, haut, angleX, angleY, angleZ, distD); } void canvas_event (He_node *hn, He_event *hev) { double v; int re = FALSE; switch (hev->type) { case KeyPress : { switch (hev->str[0]) { case 'X' : v = atof(HeGetTextValue(text_aX)) - angleP; if (v < 0) v += 360; set_text_double(text_aX, v); re = TRUE; break; case 'x' : v = atof(HeGetTextValue(text_aX)) + angleP; if (v >= 360) v -= 360; set_text_double(text_aX, v); re = TRUE; break; case 'Y' : v = atof(HeGetTextValue(text_aY)) - angleP; if (v < 0) v += 360; set_text_double(text_aY, v); re = TRUE; break; case 'y' : v = atof(HeGetTextValue(text_aY)) + angleP; if (v >= 360) v -= 360; set_text_double(text_aY, v); re = TRUE; break; case 'Z' : v = atof(HeGetTextValue(text_aZ)) - angleP; if (v < 0) v += 360; set_text_double(text_aZ, v); re = TRUE; break; case 'z' : v = atof(HeGetTextValue(text_aZ)) + angleP; if (v >= 360) v -= 360; set_text_double(text_aZ, v); re = TRUE; break; case 'D' : v = atof(HeGetTextValue(text_dD)) / distP; set_text_double(text_dD, v); re = TRUE; break; case 'd' : v = atof(HeGetTextValue(text_dD)) * distP; set_text_double(text_dD, v); re = TRUE; break; case 'i' : raz_proc (NULL); break; } } break; } if (re) HePostRepaint (canvas); } void appli_proc (He_node *hn) { HePostRepaint (canvas); } void fen1_proc (He_node *hn) { HeSetShow (fen1, HeGetToggleValue(hn)); } void quit_proc (He_node *hn) { HeQuit(0); } /*--------------------------------- M A I N ----------------------------------*/ int main (int argc, char **argv) { int ygap; HeInit (&argc, &argv); init_couleurs (); princ = HeCreateFrame (); HeSetFrameLabel (princ, "Projection 3D"); HeSetFrameResizeProc (princ, princ_resize); HeSetFrameReplaceProc (princ, princ_replace_proc); panel1 = HeCreatePanel (princ); HeCreateToggleLedP (panel1, "Paramètres", fen1_proc, FALSE); HeCreateButtonP (panel1, "Quit", quit_proc, NULL); HeFit (panel1); canvas = HeCreateCanvas (princ); HeSetCanvasRepaintProc (canvas, canvas_repaint); HeSetCanvasEventProc (canvas, canvas_event); HeSetWidth (canvas, 400); HeSetHeight (canvas, 400); panel2 = HeCreatePanel (princ); mess1 = HeCreateMessageP (panel2, "Touches : x, X, y, Y, z, Z, d, D, i", FALSE); HeFit (panel2); HeJustify (canvas, panel1, HE_TOP); HeJustify (panel2, canvas, HE_TOP); HeFit (princ); fen1 = HeCreateFrame (); HeSetFrameLabel (fen1, "Paramètres"); panel3 = HeCreatePanel (fen1); ygap = HeGetPanelYGap (panel3); HeSetPanelYGap (panel3, 2); text_aX = create_textP (panel3, "angle X", appli_proc, "0"); text_aY = create_textP (panel3, "angle Y", appli_proc, "0"); text_aZ = create_textP (panel3, "angle Z", appli_proc, "0"); text_dD = create_textP (panel3, " dist D", appli_proc, "5.0"); HeSetPanelYGap (panel3, ygap+5); HeCreateButtonP (panel3, "Init", raz_proc, NULL); HeFit (panel3); HeFit (fen1); return HeMainLoop (princ); }