home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / i / iritsm3s.zip / poly3d-h / poly3d-h.c < prev    next >
C/C++ Source or Header  |  1992-01-12  |  15KB  |  454 lines

  1. /*****************************************************************************
  2. *   Program to draw 3D object as wireframe after removing the hidden lines.  *
  3. * This porgram works in object space, and if redirect stdout to a file, dump *
  4. * the visible polylines into it instead of drawing them on current device.   *
  5. * This may be used to display the results on any device (a plotter !?) later.*
  6. *                                         *
  7. * Options:                                     *
  8. * 1. -b : Delete back facing polygons.                         *
  9. * 2. -e #Edges : If the edges are order is specific way (like in DrawFn3D)   *
  10. *         and only the k first edges of each polygons are to be displayed    *
  11. *      use this option as -e k.                         *
  12. * 3. -i : Internal edges. IRIT solid modeller may generate edges, which one  *
  13. *      may not want to see (default). -i will draw all of them.         *
  14. * 4. -m : More flag, to print more imformation on input/errors.             *
  15. * 5. -f FineNess : log based 2 of the fineness control of surfaces subdiv.   *
  16. * 6. -4 : Four per flat bilinear, otherwise two.                 *
  17. * 7. -z : Print current version, and some helpfull data.             *
  18. *                                         *
  19. * Note some of those options may be permanently set to a different default   *
  20. * using the configuration file "Poly3D-H.cfg"                     *
  21. *                                         *
  22. * Usage: Poly3D-H [-b] [-i] [-m] [-e #Edges] [-f FineNess] [-4] [-z] DFiles. *
  23. *                                         *
  24. * Written by:  Gershon Elber                Ver 3.0, Aug. 1990   *
  25. *****************************************************************************/
  26.  
  27. #ifdef __MSDOS__
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <conio.h>
  31. #include <io.h>
  32. #include <dos.h>
  33. #include <alloc.h>
  34. #endif /* __MSDOS__ */
  35.  
  36. #include <stdio.h>
  37. #include <math.h>
  38. #include <time.h>
  39. #include "program.h"
  40. #include "getarg.h"
  41. #include "genmat.h"
  42. #include "iritprsr.h"
  43. #include "config.h"
  44.  
  45. #ifdef __TURBOC__      /* Malloc debug routine - only on TC++ 1.0 and above. */
  46. #define __DEBUG_MALLOC__
  47. #endif /* __TURBOC__ */
  48.  
  49. #ifdef __MSDOS__
  50. /* This huge stack is mainly from second phase - the segment intersections   */
  51. /* which may cause recursive calls - a lot...                     */
  52. extern unsigned int _stklen = 32766;
  53. #endif /* __MSDOS__ */
  54.  
  55. #ifdef NO_CONCAT_STR
  56. static char *VersionStr =
  57.     "Poly3D-H    Version 3.0,    Gershon Elber,\n\
  58.     (C) Copyright 1989/90/91 Gershon Elber, Non commercial use only.";
  59. #else
  60. static char *VersionStr = "Poly3D-H    " VERSION ",    Gershon Elber,    "
  61.     __DATE__ ",  " __TIME__ "\n"
  62.     "(C) Copyright 1989/90/91 Gershon Elber, Non commercial use only.";
  63. #endif /* NO_CONCAT_STR */
  64.  
  65. static char *CtrlStr =
  66.     "poly3d-h b%- m%- i%- e%-#Edges!d f%-FineNess!d 4%- z%- DFiles!*s";
  67.  
  68. static long SaveTotalTime;
  69. static int
  70.     GlblFourPerFlat = FALSE;
  71.  
  72. int NumOfPolygons = 0;              /* Total number of polygons to handle. */
  73. MatrixType GlblViewMat;                  /* Current view of object. */
  74.  
  75. /* Data structures used by the hidden line modules: */
  76. int EdgeCount = 0;
  77. EdgeStruct *EdgeHashTable[EDGE_HASH_TABLE_SIZE];
  78. IPPolygonStruct *PolyHashTable[POLY_HASH_TABLE_SIZE];
  79.  
  80. /* The following are setable variables (via configuration file poly3d-h.cfg).*/
  81. int GlblMore = FALSE,
  82.     GlblNumEdge = 0,
  83.     GlblBackFacing = FALSE,
  84.     GlblInternal = FALSE,
  85.     GlblFineNess = DEFAULT_FINENESS;
  86.  
  87. static ConfigStruct SetUp[] =
  88. { { "Internal",        (VoidPtr) &GlblInternal,    SU_BOOLEAN_TYPE },
  89.   { "BackFacing",    (VoidPtr) &GlblBackFacing,    SU_BOOLEAN_TYPE },
  90.   { "More",        (VoidPtr) &GlblMore,        SU_BOOLEAN_TYPE },
  91.   { "FourPerFlat",    (VoidPtr) &GlblFourPerFlat,    SU_BOOLEAN_TYPE },
  92.   { "FineNess",        (VoidPtr) &GlblFineNess,    SU_INTEGER_TYPE },
  93.   { "NumOfEdges",    (VoidPtr) &GlblNumEdge,        SU_INTEGER_TYPE } };
  94.  
  95. #define NUM_SET_UP    (sizeof(SetUp) / sizeof(ConfigStruct))
  96.  
  97. static IPPolygonStruct *Curve2Polylines(CagdCrvStruct *Crv);
  98. static IPPolygonStruct *Surface2Polygons(CagdSrfStruct *Srf);
  99. static IPObjectStruct *MainGetDataFiles(char **DataFileNames, int NumOfDataFiles);
  100.  
  101. /*****************************************************************************
  102. * Main routine - Read Parameter    line and do what you need...             *
  103. *****************************************************************************/
  104. void
  105. #ifdef __MSDOS__
  106. cdecl        /* So we can use -rp in Borland 3.0 (parameters in registers.). */
  107. #endif /* __MSDOS__ */
  108. main(int argc, char **argv)
  109. {
  110.     int EdgesFlag = FALSE,
  111.     VerFlag = FALSE,
  112.     NumFiles = FALSE,
  113.     FineNessFlag = FALSE, Error;
  114.     char
  115.     **FileNames = NULL;
  116.     IPObjectStruct *PObjects;
  117.  
  118.     SaveTotalTime = time(NULL);                  /* Save starting time. */
  119. #ifdef __MSDOS__
  120.     ctrlbrk((int cdecl (*)()) MyExit);           /* Kill this program if ^C... */
  121. #endif /* __MSDOS_ */
  122.  
  123.     Config("poly3d-h", SetUp, NUM_SET_UP);   /* Read config. file if exists. */
  124.  
  125.     if ((Error = GAGetArgs (argc, argv, CtrlStr,
  126.         &GlblBackFacing, &GlblMore, &GlblInternal,
  127.         &EdgesFlag, &GlblNumEdge, &FineNessFlag, &GlblFineNess,
  128.         &GlblFourPerFlat, &VerFlag, &NumFiles, &FileNames)) != 0) {
  129.     GAPrintErrMsg(Error);
  130.     GAPrintHowTo(CtrlStr);
  131.     MyExit(1);
  132.     }
  133.  
  134.     if (VerFlag) {
  135.     fprintf(stderr, "\n%s\n\n", VersionStr);
  136.     GAPrintHowTo(CtrlStr);
  137.     ConfigPrint(SetUp, NUM_SET_UP);
  138.     MyExit(0);
  139.     }
  140.  
  141.     if (!NumFiles) {
  142.     fprintf(stderr, "No data file names were given, exit\n");
  143.     GAPrintHowTo(CtrlStr);
  144.     MyExit(1);
  145.     }
  146.  
  147.     /* Get the data files: */
  148.     IritPrsrPolyListCirc = FALSE;
  149.     PObjects = MainGetDataFiles(FileNames, NumFiles);
  150.  
  151.     /* And update the global viewing matrix: */
  152.     if (IritPrsrWasPrspMat)
  153.     MultTwo4by4(GlblViewMat, IritPrsrViewMat, IritPrsrPrspMat);
  154.     else
  155.     GEN_COPY(GlblViewMat, IritPrsrViewMat, sizeof(MatrixType));
  156.  
  157.     /* Prepare data structures to be able to decide on visibility: */
  158.     PrepareViewData(PObjects);
  159.  
  160.     OutVisibleEdges();               /* Scan all sub-edges output visible. */
  161.  
  162.     MyExit(0);
  163. }
  164.  
  165. /*****************************************************************************
  166. * Main routine to read the data    description files:                 *
  167. * Returns pointer to pointers on FileDescription structures (one per file).  *
  168. *****************************************************************************/
  169. static IPObjectStruct *MainGetDataFiles(char **DataFileNames, int NumOfDataFiles)
  170. {
  171.     int i;
  172.     char *ErrorMsg;
  173.     FILE *f;
  174.     long
  175.     SaveTime = time(NULL);
  176.     IPObjectStruct *PObj, *PObjTail,
  177.     *PObjHead = NULL;
  178.  
  179.     fprintf(stderr, "Reading data file(s).\n");
  180.  
  181.     for    (i = 0; i < NumOfDataFiles; i++) {
  182.     if (GlblMore) fprintf(stderr, "Reading %s.\n", *DataFileNames);
  183.  
  184. #ifdef __MSDOS__
  185.     if ((f = fopen(*DataFileNames, "rt")) == NULL) {   /* Open the file. */
  186. #else
  187.     if ((f = fopen(*DataFileNames, "r")) == NULL) {    /* Open the file. */
  188. #endif /* __MSDOS__ */
  189.         fprintf(stderr, "Can't open data file %s.\n", *DataFileNames);
  190.         MyExit(1);
  191.     }
  192.  
  193.     if ((PObj = IritPrsrGetObjects(f)) != NULL) {  /* Get the data file. */
  194.         PObjTail = PObj;
  195.         while (PObjTail -> Pnext) PObjTail = PObjTail -> Pnext;
  196.         PObjTail -> Pnext = PObjHead;
  197.         PObjHead = PObj;
  198.     }
  199.  
  200.     if (GlblMore && IritPrsrParseError(&ErrorMsg))
  201.         fprintf(stderr, "File %s, %s\n", *DataFileNames, ErrorMsg);
  202.  
  203.     fclose(f);                      /* Close the file. */
  204.  
  205.     DataFileNames++;              /* Skip to next file name. */
  206.     }
  207.  
  208.     if (PObjHead == NULL) {
  209.     fprintf(stderr, "No data found.\n");
  210.     MyExit(1);
  211.     }
  212.  
  213.     fprintf(stderr, "Done reading,  %ld seconds.", time(NULL) - SaveTime);
  214.  
  215.     return PObjHead;
  216. }
  217.  
  218. /*****************************************************************************
  219. * Routine to convert all surfaces/curves into polylines as follows:         *
  220. * Curves are converted to single polyline with SamplesPerCurve samples.         *
  221. * Surface are converted into GlblNumOfIsolines curves in each axes, each     *
  222. * handled as Curves above. The curves and surfaces are then deleted.         *
  223. *****************************************************************************/
  224. IPObjectStruct *IritPrsrProcessFreeForm(IPObjectStruct *CrvObjs,
  225.                     IPObjectStruct *SrfObjs)
  226. {
  227.     CagdCrvStruct *Crv, *Crvs;
  228.     CagdSrfStruct *Srf, *Srfs;
  229.     IPObjectStruct *PObj;
  230.     IPPolygonStruct *PPolygon, *PPolygonTemp;
  231.  
  232.     if (CrvObjs == NULL && SrfObjs == NULL) return NULL;
  233.  
  234.     /* Make sure requested format is something reasonable. */
  235.     if (GlblFineNess < 2) {
  236.     GlblFineNess = 2;
  237.     if (GlblMore)
  238.         fprintf(stderr, "FineNess is less than 2, 2 picked instead.\n");
  239.     }
  240.  
  241.     if (CrvObjs) {
  242.     for (PObj = CrvObjs; PObj != NULL; PObj = PObj -> Pnext) {
  243.         Crvs = PObj -> U.PCrvs;
  244.         PObj -> U.PPolygon = NULL;
  245.         for (Crv = Crvs; Crv != NULL; Crv = Crv -> Pnext) {
  246.         PPolygon = PPolygonTemp = Curve2Polylines(Crv);
  247.         while (PPolygonTemp -> Pnext)
  248.             PPolygonTemp = PPolygonTemp -> Pnext;
  249.         PPolygonTemp -> Pnext = PObj -> U.PPolygon;
  250.         PObj -> U.PPolygon = PPolygon;
  251.         }
  252.         CagdCrvFreeList(Crvs);
  253.     }
  254.     }
  255.  
  256.     if (SrfObjs) {
  257.     for (PObj = SrfObjs; PObj != NULL; PObj = PObj -> Pnext) {
  258.         Srfs = PObj -> U.PSrfs;
  259.         PObj -> U.PPolygon = NULL;
  260.         for (Srf = Srfs; Srf != NULL; Srf = Srf -> Pnext) {
  261.         PPolygon = PPolygonTemp = Surface2Polygons(Srf);
  262.         while (PPolygonTemp -> Pnext)
  263.             PPolygonTemp = PPolygonTemp -> Pnext;
  264.         PPolygonTemp -> Pnext = PObj -> U.PPolygon;
  265.         PObj -> U.PPolygon = PPolygon;
  266.         }
  267.         CagdSrfFreeList(Srfs);
  268.     }
  269.     }
  270.  
  271.     if (SrfObjs == NULL)
  272.     return CrvObjs;
  273.     else if (CrvObjs == NULL)
  274.     return SrfObjs;
  275.     else {
  276.     for (PObj = SrfObjs; PObj -> Pnext != NULL; PObj = PObj -> Pnext);
  277.     PObj -> Pnext = CrvObjs;
  278.     return SrfObjs;
  279.     }
  280. }
  281.  
  282. /*****************************************************************************
  283. * Routine to convert a single curve into a polyline with SamplesPerCurve     *
  284. * samples, into a polyline object.                         *
  285. *****************************************************************************/
  286. static IPPolygonStruct *Curve2Polylines(CagdCrvStruct *Crv)
  287. {
  288.     int i, j;
  289.     IPVertexStruct *V,
  290.     *VHead = NULL;
  291.     IPPolygonStruct *P;
  292.     CagdPolylineStruct
  293.     *CagdPoly = CagdCrv2Polyline(Crv, GlblFineNess);
  294.  
  295.     for (i = 0; i < CagdPoly -> Length; i++) {
  296.     if (VHead == NULL)
  297.         VHead = V = IritPrsrNewVertexStruct();
  298.     else {
  299.         V -> Pnext = IritPrsrNewVertexStruct();
  300.         V = V -> Pnext;
  301.         }
  302.  
  303.     for (j = 0; j < 3; j++)                  /* Convert to our format. */
  304.        V -> Coord[j] = CagdPoly -> Polyline[i].Pt[j];
  305.     }
  306.  
  307.     V -> Pnext = NULL;
  308.     P = IritPrsrNewPolygonStruct();
  309.     P -> PVertex = VHead;
  310.     P -> Type = IP_POLYLINE;
  311.  
  312.     CagdPolylineFree(CagdPoly);
  313.  
  314.     return P;
  315. }
  316.  
  317. /*****************************************************************************
  318. * Routine to convert a single surface into a polygons with 2^GlblFineNess    *
  319. * as fineness measure.                                 *
  320. *****************************************************************************/
  321. static IPPolygonStruct *Surface2Polygons(CagdSrfStruct *Srf)
  322. {
  323.     int i, j;
  324.     IPVertexStruct *V, *VHead;
  325.     IPPolygonStruct *P,
  326.     *PHead = NULL;
  327.     CagdPolygonStruct *CagdPolygon,
  328.     *CagdPolygonHead = NULL;
  329.  
  330.     CagdPolygonHead = CagdSrf2Polygons(Srf, 1 << GlblFineNess,
  331.                        FALSE, GlblFourPerFlat);
  332.  
  333.     for (CagdPolygon = CagdPolygonHead;
  334.      CagdPolygon != NULL;
  335.      CagdPolygon = CagdPolygon -> Pnext) {
  336.     /* All polygons are triangles! */
  337.     VHead = NULL;
  338.     for (i = 0; i < 3; i++) {             /* Convert to vertices. */
  339.         if (VHead == NULL)
  340.         VHead = V = IritPrsrNewVertexStruct();
  341.         else {
  342.         V -> Pnext = IritPrsrNewVertexStruct();
  343.         V = V -> Pnext;
  344.         }
  345.  
  346.         for (j = 0; j < 3; j++)           /* Convert to our format. */
  347.            V -> Coord[j] = CagdPolygon -> Polygon[i].Pt[j];
  348.     }
  349.  
  350.     V -> Pnext = NULL;
  351.     P = IritPrsrNewPolygonStruct();
  352.     P -> PVertex = VHead;
  353.     P -> Type = IP_POLYGON;
  354.     P -> Pnext = PHead;
  355.  
  356.     PHead = P;
  357.     }
  358.  
  359.     CagdPolygonFreeList(CagdPolygonHead);
  360.  
  361.     return PHead;
  362. }
  363.  
  364. #ifdef __DEBUG_MALLOC__
  365. /*****************************************************************************
  366. * My Routine to    allocate dynamic memory. All program requests must call this *
  367. * routine (no direct call to malloc). Dies if no memory.             *
  368. *****************************************************************************/
  369. static void AllocError(const char *Msg, VoidPtr *p)
  370. {
  371.     fprintf(stderr, "%s, Ptr = %p\n", Msg, p);
  372.     MyExit(3);
  373. }
  374. #endif /* __DEBUG_MALLOC__ */
  375.  
  376. /*****************************************************************************
  377. * My Routine to    allocate dynamic memory. All program requests must call this *
  378. * routine (no direct call to malloc). Dies if no memory.             *
  379. *****************************************************************************/
  380. VoidPtr MyMalloc(unsigned size)
  381. {
  382.     VoidPtr p;
  383.  
  384.     if ((p = malloc(size)) != NULL) return p;
  385.  
  386.     fprintf(stderr, "Not enough memory, exit.\n");
  387.     MyExit(2);
  388.  
  389.     return NULL;                    /* Make warnings silent. */
  390. }
  391.  
  392. /*****************************************************************************
  393. * My Routine to    free dynamic memory. All program requests must call this     *
  394. * routine (no direct call to free).                         *
  395. *****************************************************************************/
  396. void MyFree(VoidPtr p)
  397. {
  398. #ifdef __DEBUG_MALLOC__
  399.     switch (heapchecknode(p)) {
  400.     case _HEAPCORRUPT:
  401.         AllocError("Heap is corrupted", p);
  402.         break;
  403.     case _BADNODE:
  404.         AllocError("Attempt to free a bogus pointer", p);
  405.         break;
  406.     case _FREEENTRY:
  407.         AllocError("Attempt to free an already freed pointer", p);
  408.         break;
  409.     case _USEDENTRY:
  410.         break;
  411.     default:
  412.         AllocError("Allocation error", p);
  413.         break;
  414.  
  415.     }
  416. #endif /* __DEBUG_MALLOC__ */
  417.  
  418.     free(p);
  419. }
  420.  
  421. /*****************************************************************************
  422. * Trap Cagd_lib errors right here.                         *
  423. *****************************************************************************/
  424. void CagdFatalError(CagdFatalErrorType ErrID)
  425. {
  426.     char
  427.     *ErrorMsg = CagdDescribeError(ErrID);
  428.  
  429.     fprintf(stderr, "CAGD_LIB: %s", ErrorMsg);
  430.  
  431.     exit(-1);
  432. }
  433.  
  434. /*****************************************************************************
  435. * MyExit routine. Note it might call to CloseGraph without calling         *
  436. * InitGraph(), or call MouseClose() without MouseInit(), or call         *
  437. * RestoreCtrlBrk() without SetUpCtrlBrk() and it is the responsibility         *
  438. * of the individual modules to do nothing in these cases.             *
  439. *****************************************************************************/
  440. void MyExit(int ExitCode)
  441. {
  442. #ifdef __MSDOS__
  443.     fprintf(stderr,
  444.         "\nPoly3D-H: Total RealTime %ld seconds, Core left %ldk.\n",
  445.         time(NULL) - SaveTotalTime, coreleft() / 1024);
  446. #else
  447.     fprintf(stderr,
  448.         "\nPoly3D-H: Total RealTime %ld seconds.\n",
  449.         time(NULL) - SaveTotalTime);
  450. #endif /* __MSDOS__ */
  451.  
  452.     exit(ExitCode);
  453. }
  454.