home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / IRIT / POLY3DS.ZIP / XVIEWOBJ.C < prev   
Encoding:
C/C++ Source or Header  |  1990-05-05  |  16.9 KB  |  495 lines

  1. /*****************************************************************************
  2. * Module to handle viewing of objects in the ViewWindow.             *
  3. *                                         *
  4. * Written by:  Gershon Elber            Unix - X11 Ver 0.1, Mar. 1990    *
  5. *****************************************************************************/
  6.  
  7. #ifndef __MSDOS__
  8.  
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <setjmp.h>
  12. #include <math.h>
  13. #include "program.h"
  14. #include "postscrp.h"
  15. #include "viewobjl.h"
  16. #include "viewobjg.h"
  17. #include "graphgng.h"
  18.  
  19. #include "xgraphic.h"
  20.  
  21. /* Save the current displayed object information in local variables. */
  22. static FileDescription **LocalFD;
  23. static int LocalNumOfObjects;
  24. static char **LocalObjects;
  25.  
  26. static jmp_buf LongJumpBuffer;                    /* Used in breaking. */
  27.  
  28. /*****************************************************************************
  29. *  Routine to interactively display geometric object(s) PObjList on the View *
  30. * window enable rotating/translating/scaling it using the Input Device.      *
  31. *****************************************************************************/
  32. void InteractGeomObject(FileDescription **FD, int NumOfObjects,    char **Objects)
  33. {
  34.     /* Get data from input device, interpret it, and display interactively:  */
  35.     InteractHandleInput(FD, NumOfObjects, Objects);
  36. }
  37.  
  38. /*****************************************************************************
  39. *  Routine to handle data from the input device (keyboard, mouse etc.) -     *
  40. * clip it against the sub windows of the interactive menu and perform the    *
  41. * required transfomation, by updating the global view matrix object VIEW_MAT *
  42. *  The input data in the Rotation/Translation/Scaling sub windows is used    *
  43. * (horizontal distance from sub window center) to set amount of change.         *
  44. *****************************************************************************/
  45. static void InteractHandleInput(FileDescription **FD, int NumOfObj,
  46.                             char **Objects)
  47. {
  48.     int i, UpdateView, QuitView = FALSE;
  49.     char *ToggleStr;
  50.     RealType x, y, ChangeFactor;
  51.     MatrixType Mat, OrigViewMat, OrigPerspMat;
  52.  
  53.     /* Save copy of original matrix, so we can recover if reset is required. */
  54.     GEN_COPY(OrigViewMat,  GlblViewMat,  sizeof(MatrixType));
  55.     GEN_COPY(OrigPerspMat, GlblPerspMat, sizeof(MatrixType));
  56.  
  57.     switch (GlblViewMode) {             /* Update the current view. */
  58.     case VIEW_ORTHOGRAPHIC:
  59.         GEN_COPY(CrntViewMat, GlblViewMat, sizeof(MatrixType));
  60.         break;
  61.     case VIEW_PERSPECTIVE:
  62.         MultTwo4by4(CrntViewMat, GlblViewMat, GlblPerspMat);
  63.         break;
  64.     }
  65.  
  66.     LocalFD = FD;
  67.     LocalNumOfObjects = NumOfObj;
  68.     LocalObjects = Objects;
  69.  
  70.     GGMySetLineStyle(FULL_LINE_STYLE);
  71.  
  72.     GGClearAllScreen();                  /* Clear the view window. */
  73.     ViewGeomObjectList(FD, NumOfObj, Objects);/* Display it for first time. */
  74.  
  75.     while (TRUE) {
  76.     QuitView = FALSE;
  77.  
  78.     UpdateView = TRUE;
  79.     GenUnitMat(Mat);            /* No transformation by default! */
  80.  
  81.     switch (GetGraphicEvent(&ChangeFactor, &ToggleStr)) {
  82.         case EVENT_SCR_OBJ_TGL:    /* Its Coordinate system - toggle it. */
  83.         GlblTransformMode = *ToggleStr == 'S' ?
  84.                     TRANS_SCREEN :
  85.                     TRANS_OBJECT;
  86.         UpdateView = FALSE;
  87.         break;
  88.         case EVENT_PERS_ORTHO_TGL:           /* Its View mode - toggle it. */
  89.         GlblViewMode = *ToggleStr == 'P' ?
  90.                        VIEW_PERSPECTIVE :
  91.                    VIEW_ORTHOGRAPHIC;
  92.         break;
  93.         case EVENT_PERS_ORTHO_Z: /* Its Perspective Z focal point modif. */
  94.         if (GlblViewMode != VIEW_PERSPECTIVE) {
  95.             GGTone(1000, 100);               /* Do some noise! */
  96.             UpdateView = FALSE;
  97.             break;
  98.         }
  99.         /* Make it between 0.5 and 1.5: */
  100.         ChangeFactor = ChangeFactor / 2.0 + 1.0;
  101.         GlblPerspMat[2][2] *= ChangeFactor;
  102.         GlblPerspMat[2][3] *= ChangeFactor;
  103.         GlblPerspMat[3][2] *= ChangeFactor;
  104.         break;
  105.         case EVENT_ROTATE_X:       /* Its rotation along the X axis. */
  106.         GenMatRotX1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
  107.         break;
  108.         case EVENT_ROTATE_Y:       /* Its rotation along the Y axis. */
  109.         GenMatRotY1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
  110.         break;
  111.         case EVENT_ROTATE_Z:       /* Its rotation along the Z axis. */
  112.         GenMatRotZ1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
  113.         break;
  114.         case EVENT_TRANSLATE_X:    /* Its translation along the X axis. */
  115.         GenMatTrans(ChangeFactor * MAX_TRANSLATE_FACTOR, 0.0, 0.0,
  116.                                     Mat);
  117.         break;
  118.         case EVENT_TRANSLATE_Y:    /* Its translation along the Y axis. */
  119.         GenMatTrans(0.0, ChangeFactor * MAX_TRANSLATE_FACTOR, 0.0,
  120.                                     Mat);
  121.         break;
  122.         case EVENT_TRANSLATE_Z:    /* Its translation along the Z axis. */
  123.         GenMatTrans(0.0, 0.0, ChangeFactor * MAX_TRANSLATE_FACTOR,
  124.                                     Mat);
  125.         break;
  126.         case EVENT_SCALE:              /* Its scaling along all axes. */
  127.         if (ChangeFactor > 0.0)              /* Make it around 1... */
  128.              ChangeFactor = ChangeFactor * MAX_SCALE_FACTOR + 1.0;
  129.         else ChangeFactor = 1.0 /
  130.             (-ChangeFactor * MAX_SCALE_FACTOR + 1.0);
  131.         GenMatScale(ChangeFactor, ChangeFactor, ChangeFactor, Mat);
  132.         break;
  133.         case EVENT_DEPTH_CUE:
  134.         GlblDepthCue = *ToggleStr == 'D';
  135.         if (!GlblDepthCue) GGMySetLineStyle(FULL_LINE_STYLE);
  136.         break;
  137.         case EVENT_SAVE_PS:
  138.         SavePostScript(FD, NumOfObj, Objects);
  139.         UpdateView = FALSE;
  140.         break;
  141.         case EVENT_SAVE_MATRIX:
  142.         SaveCurrentMat();
  143.         UpdateView = FALSE;
  144.         break;
  145.         case EVENT_RESET_MATRIX:
  146.         GEN_COPY(GlblViewMat,  OrigViewMat,  sizeof(MatrixType));
  147.         GEN_COPY(GlblPerspMat, OrigPerspMat, sizeof(MatrixType));
  148.         break;
  149.         case EVENT_QUIT:
  150.         LocalFD = NULL;
  151.         LocalNumOfObjects = 0;
  152.         LocalObjects = NULL;
  153.         return;                        /* Its Quit. */
  154.         default:
  155.         GGTone(1000, 100);               /* Do some noise! */
  156.         UpdateView = FALSE;
  157.     }
  158.     if (UpdateView) {
  159.         GGClearAllScreen();               /* Clear the view window. */
  160.  
  161.         switch (GlblTransformMode) {/* Udpate the global viewing matrix. */
  162.         case TRANS_SCREEN:
  163.             MultTwo4by4(GlblViewMat, GlblViewMat, Mat);
  164.             break;
  165.         case TRANS_OBJECT:
  166.             MultTwo4by4(GlblViewMat, Mat, GlblViewMat);
  167.             break;
  168.         }
  169.  
  170.         switch (GlblViewMode) {         /* Update the current view. */
  171.         case VIEW_ORTHOGRAPHIC:
  172.             GEN_COPY(CrntViewMat, GlblViewMat, sizeof(MatrixType));
  173.             break;
  174.         case VIEW_PERSPECTIVE:
  175.             MultTwo4by4(CrntViewMat, GlblViewMat, GlblPerspMat);
  176.             break;
  177.         }
  178.  
  179.         ViewGeomObjectList(FD, NumOfObj, Objects);    /* And display it... */
  180.     }
  181.     }
  182. }
  183.  
  184. /*****************************************************************************
  185. *  Routine to update the viewing screen. On unix systems this routine may    *
  186. * be invoked when X sends expose event to this program (see xgrphgen.c).     *
  187. * In MSDOS this routine is static and been called from InteractHandleInput   *
  188. * above routine only.                                 *
  189. *****************************************************************************/
  190. void UpdateInteractHandleInput(void)
  191. {
  192.     GGClearAllScreen();
  193.     if (LocalFD)
  194.     ViewGeomObjectList(LocalFD, LocalNumOfObjects, LocalObjects);
  195. }
  196.  
  197. /*****************************************************************************
  198. *  Routine to display the geometric objects in PObjList, by simply calling   *
  199. * ViewGeomObject on all of them. PObjList must be of type OBJ_LIST_OBJ.         *
  200. *****************************************************************************/
  201. static void ViewGeomObjectList(FileDescription **FD, int NumOfObjects,
  202.                                 char **Objects)
  203. {
  204.     int    i;
  205.     ObjectStruct *PObject;
  206.  
  207.     GGMySetColor(RED);                    /* Make default color - RED. */
  208.  
  209.     if (setjmp(LongJumpBuffer) == 0)          /* Its the setjmp itself call! */
  210.     if (NumOfObjects > 0)       /* There was something on command line... */
  211.         for (i=0; i<NumOfObjects; i++) {
  212.         if ((PObject = SearchObject(FD, *Objects)) ==
  213.                             (ObjectStruct *) NULL)
  214.             fprintf(stderr,
  215.                 "Given Object %s not found in data files\n",
  216.                 *Objects);
  217.         else ViewOneObject(PObject);
  218.         Objects++;
  219.         }
  220.     else {
  221.         /* Draw all objects not in other object by scanning object trees.*/
  222.         DrawAllObjects(FD);        /* and drawing ones with Reference == 0. */
  223.     }
  224. }
  225.  
  226. /*****************************************************************************
  227. * Routine to save the current view trans. GlblViewMat to a generic mat file  *
  228. *****************************************************************************/
  229. static void SaveCurrentMat(void)
  230. {
  231.     int    i, j;
  232.     FILE *f;
  233.     char *p, FileName[FILE_NAME_LEN];
  234.     static char FileCount = '0';
  235.  
  236.     strcpy(FileName, GENERIC_MAT_FILE);
  237.     if ((p = strchr(FileName, '#')) != NULL) {
  238.     *p = FileCount;
  239.     if (FileCount++ == '9') FileCount = '0';
  240.     }
  241.     if ((f = fopen(FileName, "wt")) == NULL) {
  242.     GGTone(700, 200);
  243.     return;
  244.     }
  245.  
  246.     for    (i=0; i<4; i++)    {
  247.     for (j=0; j<4; j++) fprintf(f, "%12lf ", GlblViewMat[i][j]);
  248.     fprintf(f, "\n");
  249.     }
  250.  
  251.     if (GlblViewMode == VIEW_PERSPECTIVE) {
  252.     fprintf(f, "\n");
  253.     for (i=0; i<4; i++) {
  254.         for (j=0; j<4; j++) fprintf(f, "%12lf ", GlblPerspMat[i][j]);
  255.         fprintf(f, "\n");
  256.     }
  257.     }
  258.  
  259.     fclose(f);
  260. }
  261.  
  262. /*****************************************************************************
  263. * Routine to search for    an object in the File descriptions FD. Note that if  *
  264. * an object exists more    than once only the first will be returned. If none   *
  265. * is found then    NULL is    returned, else a pointer to that object    struct.         *
  266. *****************************************************************************/
  267. static ObjectStruct *SearchObject(FileDescription **FD, char *Object)
  268. {
  269.      BinTree *PBinTree;
  270.  
  271.      while (*FD) {
  272.       if ((PBinTree    = GetBinTree(Object, (*FD++) -> ObjectPointer)) !=
  273.                          (BinTree *) NULL)
  274.       return PBinTree -> Data.PObject;
  275.      }
  276.      return (ObjectStruct *) NULL;
  277. }
  278.  
  279. /*****************************************************************************
  280. * Routine to draw all the objects not in other objects...             *
  281. * by scanning all the object trees and drawing the objects with    Reference==0 *
  282. * meaning nobody referred to them yet...                     *
  283. *****************************************************************************/
  284. static void DrawAllObjects(FileDescription **FD)
  285. {
  286.     while (*FD)    VisitObjectTree((*FD++) -> ObjectPointer);
  287. }
  288.  
  289. /*****************************************************************************
  290. * Routine to draw all the objects not in other objects...             *
  291. * by scanning all the object in    tree PBinTree and drawing the objects with   *
  292. * Reference==0,    meaning    nobody referred    to them    yet...                 *
  293. *****************************************************************************/
  294. static void VisitObjectTree(BinTree *PBinTree)
  295. {
  296.     if (PBinTree == (BinTree *)    NULL) return;
  297.  
  298.     VisitObjectTree(PBinTree -> right);
  299.  
  300.     if (MoreFlag == 1)
  301.     printf("Drawing object %s\n", PBinTree -> Name);
  302.     ViewOneObject(PBinTree -> Data.PObject);
  303.  
  304.     VisitObjectTree(PBinTree -> left);
  305. }
  306.  
  307. /*****************************************************************************
  308. * Routine to draw one object Object, using the Matrix transform    Mat.         *
  309. *****************************************************************************/
  310. static void ViewOneObject(ObjectStruct *PObject)
  311. {
  312.     PolygonStruct *PList = PObject -> PPolygon;
  313.  
  314.     SetDrawColor(PObject -> Color);           /* Default color for object. */
  315.  
  316.     while (PList) {
  317.     ViewOnePolygon(PList);
  318.     PList =    PList -> Pnext;
  319.     }
  320. }
  321.  
  322. /*****************************************************************************
  323. * Routine to draw one polygon, using the Matrix    transform Mat.             *
  324. * Note this is the routine that    makes the real drawing...             *
  325. *****************************************************************************/
  326. static void ViewOnePolygon(PolygonStruct *PPolygon)
  327. {
  328.     int    i, Count, DrawNextEdge, NumOfVertices;
  329.     float MappedNormal[3], PolyNormal[3];
  330.     VertexStruct *PList = PPolygon -> PVertex;
  331.  
  332.     TestQuitView();
  333.  
  334.     Count = NumEdges;
  335.  
  336.     if (PList == NULL) return;
  337.  
  338.     switch (PPolygon -> PolyType) {
  339.     case POINTLIST:
  340.         while (PList) {
  341.         MyMoveTo(PList -> Coord);
  342.         MyDrawTo(PList -> Coord);
  343.         PList = PList -> Pnext;
  344.         }
  345.         break;
  346.     case POLYLINE:
  347.         MyMoveTo(PList -> Coord);
  348.         DrawNextEdge = !PList -> Internal;
  349.         PList = PList -> Pnext;
  350.  
  351.         while (PList) {
  352.         MyDrawTo(PList -> Coord);
  353.  
  354.         PList = PList -> Pnext;
  355.         }
  356.         break;
  357.     case POLYGON:
  358.         if (DrawPNormalsFlag && PPolygon->HasPlane)
  359.         {
  360.         for (i=0; i<3; i++) PolyNormal[i] = PList -> Coord[i];
  361.         NumOfVertices = 1;
  362.         }
  363.  
  364.         MyMoveTo(PList -> Coord);
  365.         DrawNextEdge = !PList -> Internal;
  366.         PList = PList -> Pnext;
  367.  
  368.         while (PList) {
  369.         if (DrawNextEdge || InterFlag)
  370.             MyDrawTo(PList -> Coord);
  371.         else MyMoveTo(PList -> Coord);
  372.  
  373.         if (DrawVNormalsFlag && PList -> HasNormal) {
  374.             for (i=0; i<3; i++) MappedNormal[i] =
  375.                     PList -> Coord[i] + PList -> Normal[i];
  376.             i = ClosedObject;
  377.             ClosedObject = FALSE;
  378.             MyDrawTo(MappedNormal);
  379.             MyMoveTo(PList -> Coord);
  380.             ClosedObject = i;
  381.         }
  382.  
  383.         if (DrawPNormalsFlag && PPolygon->HasPlane)
  384.         {
  385.             for (i=0; i<3; i++) PolyNormal[i] += PList -> Coord[i];
  386.             NumOfVertices++;
  387.         }
  388.         /* If -e option specified #Edges to draw. */
  389.         if (!(--Count)) return;
  390.         DrawNextEdge = !PList -> Internal;
  391.         PList = PList -> Pnext;
  392.         }
  393.  
  394.         /* Close polygon by drawing a line to first vertex. */
  395.         if (DrawNextEdge || InterFlag)
  396.         MyDrawTo(PPolygon -> PVertex -> Coord);
  397.  
  398.         if (DrawPNormalsFlag && PPolygon->HasPlane)
  399.         {
  400.         for (i=0; i<3; i++) PolyNormal[i] /= NumOfVertices;
  401.         MyMoveTo(PolyNormal);
  402.         for (i=0; i<3; i++) PolyNormal[i] += PPolygon->Plane[i];
  403.         i = ClosedObject;
  404.         ClosedObject = FALSE;
  405.         MyDrawTo(PolyNormal);
  406.         ClosedObject = i;
  407.         }
  408.         break;
  409.     }
  410. }
  411.  
  412. static double LastCoord[3];    /* Used to store last point we moved/draw to. */
  413.  
  414. /*****************************************************************************
  415. * Routine to mave to 3D    point given as Coord[3], using Mat transform.         *
  416. *****************************************************************************/
  417. static void MyMoveTo(float Coord[3])
  418. {
  419.     MultVecby4by4(LastCoord, Coord, CrntViewMat);   /* Set last point coord. */
  420. }
  421.  
  422. /*****************************************************************************
  423. * Routine to draw to 3D    point given as Coord[3], using Mat transform, from   *
  424. * the last point we moved to.                             *
  425. *****************************************************************************/
  426. static void MyDrawTo(float Coord[3])
  427. {
  428.     double NewCoord[3], MiddleCoord[3], t;
  429.  
  430.     MultVecby4by4(NewCoord, Coord, CrntViewMat);    /* Set last point coord. */
  431.     if (ClosedObject && NewCoord[2] < LastCoord[2]) {
  432.     GEN_COPY(LastCoord, NewCoord, 3 * sizeof(double));
  433.     return;
  434.     }
  435.  
  436.     /* Implementation of simple depth cue - if line is >Z or <Z ... */
  437.     if (LastCoord[2] <= 0.0 && NewCoord[2] <= 0.0) {
  438.     if (GlblDepthCue) GGMySetLineStyle(DOTTED_LINE_STYLE);
  439.     GGMyMove(LastCoord[0], LastCoord[1]);
  440.     GGMyDraw(NewCoord[0], NewCoord[1]);                /* DRAW! */
  441.     }
  442.     else
  443.     if (LastCoord[2] >= 0.0 && NewCoord[2] >= 0.0 ||
  444.     ABS(LastCoord[2] - NewCoord[2]) < EPSILON) {
  445.     if (GlblDepthCue) GGMySetLineStyle(FULL_LINE_STYLE);
  446.     GGMyMove(LastCoord[0], LastCoord[1]);
  447.     GGMyDraw(NewCoord[0], NewCoord[1]);                /* DRAW! */
  448.     }
  449.     else {                      /* Line intersect Z = 0 plane. */
  450.     t = LastCoord[2] / (LastCoord[2] - NewCoord[2]);
  451.     MiddleCoord[0] = LastCoord[0] * (1.0 - t) + NewCoord[0] * t;
  452.     MiddleCoord[1] = LastCoord[1] * (1.0 - t) + NewCoord[1] * t;
  453.     if (GlblDepthCue) GGMySetLineStyle(FULL_LINE_STYLE);
  454.     if (LastCoord[2] > 0.0) {
  455.         GGMyMove(LastCoord[0], LastCoord[1]);
  456.         GGMyDraw(MiddleCoord[0], MiddleCoord[1]);            /* DRAW! */
  457.     }
  458.     else {
  459.         GGMyMove(MiddleCoord[0], MiddleCoord[1]);
  460.         GGMyDraw(NewCoord[0], NewCoord[1]);                /* DRAW! */
  461.     }
  462.     if (GlblDepthCue) GGMySetLineStyle(DOTTED_LINE_STYLE);
  463.     if (LastCoord[2] < 0.0) {
  464.         GGMyMove(LastCoord[0], LastCoord[1]);
  465.         GGMyDraw(MiddleCoord[0], MiddleCoord[1]);            /* DRAW! */
  466.     }
  467.     else {
  468.         GGMyMove(MiddleCoord[0], MiddleCoord[1]);
  469.         GGMyDraw(NewCoord[0], NewCoord[1]);                /* DRAW! */
  470.     }
  471.     }
  472.  
  473.     GEN_COPY(LastCoord, NewCoord, 3 * sizeof(double)); /* Set current point. */
  474. }
  475.  
  476. /*****************************************************************************
  477. * Routine to set current drawing color to given    RGB values:             *
  478. * Currently only 8 colors are supported:                     *
  479. *****************************************************************************/
  480. static void SetDrawColor(int Color)
  481. {
  482.     GGMySetColor(Color);
  483. }
  484.  
  485. /*****************************************************************************
  486. *  Routine to test if quit display event - occured - SPACE was hit on         *
  487. * keyboard or right button was clicked on mouse.                 *
  488. *****************************************************************************/
  489. static void TestQuitView(void)
  490. {
  491.     if (IsAbortKeyPressed()) longjmp(LongJumpBuffer, 1);       /* Jump to... */
  492. }
  493.  
  494. #endif /* __MSDOS__ */
  495.