home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / IRIT / POLY3DRS.ZIP / POLY3D-R.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-05  |  14.7 KB  |  412 lines

  1. /*****************************************************************************
  2. *   Program to draw 3D object as solid objects in GIF image file format.     *
  3. *                                         *
  4. * Options:                                     *
  5. * 1. -m : More flag, to print more imformation on input/errors.             *
  6. * 2. -a ambient : Ratio of the ambient color.                     *
  7. * 3. -c n : Number of bit ber pixel (2^n is number of colors possible).         *
  8. * 4. -l x y z : Light source direction vector.                     *
  9. * 5. -s x y : Specify new dimensions to generate the resulting image.         *
  10. * 6. -g : Use gouraud shading.                             *
  11. * 7. -b : Delete Back facing polygons.                         *
  12. * 8. -M Mask : Create boolean Mask (coverage) image as well.             *
  13. * 9. -o Objects : List of objects to be displayed from the input data files. *
  14. *      This option should not be last and Object list terminates with     *
  15. *      next option (- as first char). ALL objects are displayed otherwise.*
  16. * 10. -v ViewFile : Optional view to start with.                 *
  17. * 11. -z : Print current version, and some helpfull data.             *
  18. * 12. -2 : Force 2 light sources at opposite direction of light vectors.     *
  19. *                                         *
  20. * Note some of those options may be permanently set to a different default   *
  21. * using the configuration file "Poly3D-R.cfg"                     *
  22. *                                         *
  23. * Usage: poly3d-r [-a Ambient] [-c N] [-l X Y Z] [-2] [-m] [-s Xsize Ysize]  *
  24. *     [-S SubSample] [-g] [-b] [-M Mask] [-o Objects...] [-v ViewFile] [-z]  *
  25. *                                     DFiles  *
  26. *                                         *
  27. * Written by:  Gershon Elber                Ver 2.0, Mar 1990    *
  28. *****************************************************************************/
  29.  
  30. #ifdef __MSDOS__
  31. #include <stdlib.h>
  32. #include <conio.h>
  33. #include <io.h>
  34. #include <dos.h>
  35. #include <alloc.h>
  36. #endif /* __MSDOS__ */
  37.  
  38. #include <stdio.h>
  39. #include <math.h>
  40. #include <time.h>
  41. #include "program.h"
  42. #include "getarg.h"
  43. #include "genmat.h"
  44. #include "parser.h"
  45. #include "config.h"
  46. #include "ctrl-brk.h"
  47.  
  48. #ifdef __MSDOS__
  49. /* This huge stack is mainly from second phase - the segment intersections   */
  50. /* which may cause recursive calls - a lot...                     */
  51. extern unsigned int _stklen = 32766;
  52. #endif /* __MSDOS__ */
  53.  
  54. #ifdef SYSV
  55. static char *VersionStr =
  56.     "Poly3D-R    version 2.0,    Gershon Elber,\n\
  57.     (C) Copyright 1989 Gershon Elber, Non commercial use only.";
  58. #else
  59. static char *VersionStr = "Poly3D-R    version 2.0,    Gershon Elber,    "
  60.         __DATE__ ",  " __TIME__ "\n"
  61.         "(C) Copyright 1989 Gershon Elber, Non commercial use only.";
  62. #endif /* SYSV */
  63.  
  64. static char *CtrlStr =
  65.     "poly3d-r a%-Ambient!F c%-N!d l%-X|Y|Z!F!F!F 2%- m%- s%-Xsize|Ysize!d!d S%-SubSample!d g%- b%- M%-Mask!s o%-Objects!*s v%-ViewFile!s z%- DFiles!*s";
  66.  
  67.  
  68. static long SaveTotalTime;
  69. static int ViewFlag = FALSE;
  70. static GifColorType MaskColorMap[2] = {     /* Boolean mask GIF file color map. */
  71.     {   0,   0,   0 },
  72.     { 255, 255, 255 }
  73. };
  74.  
  75. int NumOfPolygons = 0;         /* Total number of polygons scan converted. */
  76. int NumOfVertices = 0;                /* Total number of vertices. */
  77. MatrixType GlblViewMat;                  /* Current view of object. */
  78.  
  79. /* Amount scene was scaled up from normalized [-1..1] size on both X & Y: */
  80. float ScaleUpFactor = 0.0;
  81.  
  82. /* The following are setable variables (via configuration file poly3d-h.cfg).*/
  83. int MoreFlag = FALSE, GouraudFlag = FALSE, BackFacingFlag = FALSE,
  84.     ScreenXSize = DEFAULT_SCREEN_XSIZE, ScreenYSize = DEFAULT_SCREEN_YSIZE;
  85. double NormalAvgDegree = DEFAULT_NORMAL_AVG_DEGREE;
  86. struct ShadingInfoStruct ShadingInfo = {
  87.     1,
  88.     DEFAULT_BITS_PER_PIXEL,
  89.     0,
  90.     DEFAULT_COLOR,
  91.     DEFAULT_BACK_GROUND_COLOR,
  92.     FALSE,
  93.     NULL,                         /* No color map yet */
  94.     NULL,
  95.     DEFAULT_LIGHT_SOURCE,
  96.     DEFAULT_AMBIENT,
  97. };
  98.  
  99. static ConfigStruct SetUp[] =
  100. { { "AvgDegree",    (VoidPtr) &NormalAvgDegree,        SU_REAL_TYPE },
  101.   { "Ambient",        (VoidPtr) &ShadingInfo.Ambient,        SU_REAL_TYPE },
  102.   { "SubSample",    (VoidPtr) &ShadingInfo.SubSamplePixel,    SU_INTEGER_TYPE },
  103.   { "BitsPerPixel",    (VoidPtr) &ShadingInfo.BitsPerPixel,    SU_INTEGER_TYPE },
  104.   { "LightSrcX",    (VoidPtr) &ShadingInfo.LightSource[0],    SU_REAL_TYPE },
  105.   { "LightSrcY",    (VoidPtr) &ShadingInfo.LightSource[1],    SU_REAL_TYPE },
  106.   { "LightSrcZ",    (VoidPtr) &ShadingInfo.LightSource[2],    SU_REAL_TYPE },
  107.   { "TwoSources",    (VoidPtr) &ShadingInfo.TwoSources,    SU_BOOLEAN_TYPE },
  108.   { "Xsize",        (VoidPtr) &ScreenXSize,            SU_INTEGER_TYPE },
  109.   { "Ysize",        (VoidPtr) &ScreenYSize,            SU_INTEGER_TYPE },
  110.   { "Color",        (VoidPtr) &ShadingInfo.DefaultColor,    SU_INTEGER_TYPE },
  111.   { "BackGroundColor",    (VoidPtr) &ShadingInfo.BackGroundColor,    SU_INTEGER_TYPE },
  112.   { "More",        (VoidPtr) &MoreFlag,            SU_BOOLEAN_TYPE } };
  113. #define NUM_SET_UP    (sizeof(SetUp) / sizeof(ConfigStruct))
  114.  
  115. /* All polygons to be scan convert will be inserted into this hash table     */
  116. /* during the preprocessing (PrepareXXXX functions).                 */
  117. struct PolygonStruct **PolyHashTable;
  118.  
  119.  
  120. static void MainGetViewFile(char *ViewFileName);
  121. static FileDescription **MainGetDataFiles(char **DataFileNames,
  122.                             int NumOfDataFiles);
  123. static void FreeBinTree(struct BinTree *Pbin);
  124.  
  125. /*****************************************************************************
  126. * Main routine - Read Parameter    line and do what you need...             *
  127. *****************************************************************************/
  128. void main(int argc, char **argv)
  129. {
  130.     int AmbientFlag = FALSE, ColorFlag = FALSE, LightSrcFlag = FALSE,
  131.     TwoSourcesFlag = FALSE, GifMaskFlag = FALSE, ObjFlag = FALSE,
  132.     NumObjs = 0, RealNumObjs, VerFlag = FALSE, NumFiles = 0,
  133.     ImageSizeFlag = FALSE, SubSampleFlag = FALSE, Error;
  134.     char **Objects = NULL, *ViewName = NULL, **FileNames = NULL, *GifMaskName;
  135.     double Size;
  136.     FileDescription **FD;
  137.     GifFileType *GifFile, *GifMask = NULL;
  138.  
  139.     SaveTotalTime = time(NULL);                  /* Save starting time. */
  140. #ifdef __MSDOS__
  141.     ctrlbrk((int (*)()) MyExit);           /* Kill this program if ^C... */
  142. #endif /* __MSDOS__ */
  143.     SetUpHardErr();        /* Set up hardware error trap routine (int 24h). */
  144.  
  145.     Config("poly3d-r", SetUp, NUM_SET_UP);   /* Read config. file if exists. */
  146.  
  147.     if ((Error = GAGetArgs (argc, argv, CtrlStr,
  148.         &AmbientFlag, &ShadingInfo.Ambient,
  149.         &ColorFlag, &ShadingInfo.BitsPerPixel,
  150.         &LightSrcFlag, &ShadingInfo.LightSource[0],
  151.                    &ShadingInfo.LightSource[1],
  152.                    &ShadingInfo.LightSource[2],
  153.         &TwoSourcesFlag,
  154.         &MoreFlag, &ImageSizeFlag, &ScreenXSize, &ScreenYSize,
  155.         &SubSampleFlag, &ShadingInfo.SubSamplePixel,
  156.         &GouraudFlag, &BackFacingFlag, &GifMaskFlag, &GifMaskName,
  157.         &ObjFlag, &NumObjs, &Objects,
  158.         &ViewFlag, &ViewName, &VerFlag, &NumFiles, &FileNames)) != 0) {
  159.     GAPrintErrMsg(Error);
  160.     GAPrintHowTo(CtrlStr);
  161.     MyExit(1);
  162.     }
  163.  
  164.     if (TwoSourcesFlag) ShadingInfo.TwoSources = TRUE;
  165.  
  166.     if (ShadingInfo.Ambient < 0.0 || ShadingInfo.Ambient > 1.0) {
  167.     fprintf(stderr, "Ambient light specified not in [0.0..1.0] range, %lf selected instead\n",
  168.         DEFAULT_AMBIENT);
  169.     ShadingInfo.Ambient = DEFAULT_AMBIENT;
  170.     }
  171.     if (ShadingInfo.BitsPerPixel < 1 || ShadingInfo.BitsPerPixel > 8) {
  172.     fprintf(stderr, "PitsPerPixel not in [1..8] range, %d selected instead\n",
  173.         DEFAULT_BITS_PER_PIXEL);
  174.     ShadingInfo.BitsPerPixel = DEFAULT_BITS_PER_PIXEL;
  175.     }
  176.  
  177.     Size = sqrt(SQR(ShadingInfo.LightSource[0]) +
  178.         SQR(ShadingInfo.LightSource[1]) +
  179.         SQR(ShadingInfo.LightSource[2]));
  180.     if (ABS(Size) < EPSILON) {
  181.     fprintf(stderr, "Light source vector is zero, Z axis selected instead\n");
  182.     ShadingInfo.LightSource[0] =
  183.     ShadingInfo.LightSource[1] = 0.0;
  184.     ShadingInfo.LightSource[2] = 1.0;
  185.     }
  186.     else {
  187.     ShadingInfo.LightSource[0] /= Size;
  188.     ShadingInfo.LightSource[1] /= Size;
  189.     ShadingInfo.LightSource[2] /= Size;
  190.     }
  191.  
  192.     if (VerFlag) {
  193.     fprintf(stderr, "\n%s\n\n", VersionStr);
  194.     GAPrintHowTo(CtrlStr);
  195.     ConfigPrint(SetUp, NUM_SET_UP);
  196.     MyExit(0);
  197.     }
  198.  
  199.     if (!NumFiles) {
  200.     fprintf(stderr, "No data file names were given, exit\n");
  201.     GAPrintHowTo(CtrlStr);
  202.     MyExit(1);
  203.     }
  204.  
  205.     if (SubSampleFlag) {
  206.     if (ShadingInfo.SubSamplePixel < 1 || ShadingInfo.SubSamplePixel > 4) {
  207.         fprintf(stderr, "Sub sampling can be 1 to 4 only (1x1 to 4x4)\n");
  208.         GAPrintHowTo(CtrlStr);
  209.         MyExit(1);
  210.     }
  211.     }
  212.  
  213.     MainGetViewFile(ViewName);
  214.  
  215.     /* Get the data files: */
  216.     FD = MainGetDataFiles(FileNames, NumFiles);
  217.  
  218.     /* Prepare data structures of objects themselves: */
  219.     RealNumObjs = NumObjs;
  220.     PrepareViewData(FD, &RealNumObjs, Objects);
  221.     if (NumObjs != 0) RealNumObjs = NumObjs;
  222.  
  223.     /* Into shadingInfo global structure: */
  224.     PrepareColorTable(FD, NumObjs, RealNumObjs, Objects);
  225.  
  226.     EvalVrtxColors(FD, NumObjs, Objects);
  227.  
  228. #ifndef DEBUG_NO_GIF
  229.  
  230.     /* Open stdout for the GIF image file: */
  231.     if ((GifFile = EGifOpenFileHandle(1)) == NULL ||
  232.     EGifPutScreenDesc(GifFile,
  233.         ScreenXSize, ScreenYSize, ShadingInfo.BitsPerPixel, 0,
  234.         ShadingInfo.BitsPerPixel, ShadingInfo.PColorMap) == ERROR ||
  235.     EGifPutImageDesc(GifFile,
  236.         0, 0, ScreenXSize, ScreenYSize, FALSE,
  237.         ShadingInfo.BitsPerPixel, NULL) == ERROR)
  238.     QuitGifError();
  239.     /* Open special mask file if required: */
  240.     if (GifMaskFlag &&
  241.     ((GifMask = EGifOpenFileName(GifMaskName, FALSE)) == NULL ||
  242.      EGifPutScreenDesc(GifMask,
  243.         ScreenXSize, ScreenYSize, 1, 0, 1, MaskColorMap) == ERROR ||
  244.      EGifPutImageDesc(GifMask,
  245.         0, 0, ScreenXSize, ScreenYSize, FALSE, 1, NULL) == ERROR))
  246.     QuitGifError();
  247.  
  248. #endif DEBUG_NO_GIF
  249.  
  250.     ScanConvertData(GifFile, GifMask);     /* Do the real interesting stuff... */
  251.  
  252. #ifndef DEBUG_NO_GIF
  253.  
  254.     EGifCloseFile(GifFile);
  255.     if (GifMask) EGifCloseFile(GifMask);
  256.  
  257. #endif DEBUG_NO_GIF
  258.  
  259.     MyExit(0);
  260. }
  261.  
  262. /*****************************************************************************
  263. * Main routine to read the view    description file, into GlblViewMat:         *
  264. *****************************************************************************/
  265. static void MainGetViewFile(char *ViewFileName)
  266. {
  267.     double Scale;
  268.     MatrixType Mat;
  269.     FILE *f;
  270.  
  271.     if (ViewFlag && (f = fopen(ViewFileName, "rt")) == NULL) {
  272.     fprintf(stderr, "Can't open view file %s\n", ViewFileName);
  273.     MyExit(1);
  274.     }
  275.  
  276.     /* Get view data if ViewFlag, otherwise set default view (isometric): */
  277.     GetViewFile(f, ViewFlag);
  278.  
  279.     /* Now its time to scale the normalized image (+/-1 on both X & Y) to    */
  280.     /* size specified by the image dimensions. We scale up to the SMALLER    */
  281.     /* dimension, and put the center at the image center.             */
  282.     /* Also, as the GIF image starts at the top, we must flip the image      */
  283.     /* along Y axis.                                 */
  284.     ScaleUpFactor = Scale = MIN(ScreenXSize * ShadingInfo.SubSamplePixel,
  285.                 ScreenYSize * ShadingInfo.SubSamplePixel) / 2.0;
  286.     GenMatScale(Scale, -Scale, Scale, Mat);
  287.     MultTwo4by4(GlblViewMat, GlblViewMat, Mat);
  288.     GenMatTrans(ScreenXSize * ShadingInfo.SubSamplePixel / 2.0,
  289.         ScreenYSize * ShadingInfo.SubSamplePixel / 2.0, 0.0, Mat);
  290.     MultTwo4by4(GlblViewMat, GlblViewMat, Mat);
  291.  
  292.     if (ViewFlag) fclose(f);                  /* Close the file. */
  293. }
  294.  
  295. /*****************************************************************************
  296. * Main routine to read the data    description files:                 *
  297. * Returns pointer to pointers on FileDescription structures (one per file).  *
  298. *****************************************************************************/
  299. static FileDescription **MainGetDataFiles(char **DataFileNames,
  300.                             int NumOfDataFiles)
  301. {
  302.     int    i;
  303.     long SaveTime = time(NULL);
  304.     FILE *f;
  305.     FileDescription **FDbase, **FDinc;  /* Used to save memory pointers loc. */
  306.  
  307.     NumOfPolygons = 0;
  308.     fprintf(stderr, "\nPass 1, Polys =      ");
  309.  
  310.     FDbase = FDinc = (FileDescription **)    /* Allocate the pointers block. */
  311.      MyMalloc((unsigned) sizeof(FileDescription *) * (NumOfDataFiles + 1));
  312.  
  313.     for    (i=0; i<NumOfDataFiles;    i++) {
  314.     if (MoreFlag) {
  315.         fprintf(stderr, "\rReading data file %s", *DataFileNames);
  316.         fprintf(stderr, "\nPass 1, Polys =      ");
  317.     }
  318.     f = fopen(*DataFileNames, "rt");           /* Open the file. */
  319.     if (!f)
  320.     {
  321.         fprintf(stderr, "Can't open data file %s\n", *DataFileNames);
  322.         MyExit(1);
  323.     }
  324.  
  325.     *FDinc = GetDataFile(f);               /* Get the data file. */
  326.     FreeBinTree((*FDinc) ->    VertexPointer); /* We dont need these trees. */
  327.     FreeBinTree((*FDinc) ->    PolygonPointer);  /* objects are all loaded. */
  328.     (*FDinc) -> VertexPointer = (*FDinc) ->    PolygonPointer = NULL;
  329.     fprintf(stderr, " \b");          /* Erase the FreeBinTree marker... */
  330.     *FDinc++;
  331.  
  332.     fclose(f);                      /* Close the file. */
  333.  
  334.     DataFileNames++;              /* Skip to next file name. */
  335.     }
  336.  
  337.     *FDinc = NULL;
  338.  
  339.     fprintf(stderr, ",  %ld seconds.", time(NULL) - SaveTime);
  340.  
  341.     return FDbase;
  342. }
  343.  
  344. /*****************************************************************************
  345. * My Routine to    allocate dynamic memory. All program requests must call         *
  346. * this routine (no direct call to malloc). Dies if no memory.             *
  347. *****************************************************************************/
  348. char *MyMalloc(unsigned size)
  349. {
  350.     char *p;
  351.  
  352.     if ((p = malloc(size)) != NULL) return p;
  353.  
  354.     fprintf(stderr, "\nNot enough memory, exit\n");
  355.     MyExit(2);
  356.  
  357.     return NULL;                    /* Makes warning silent. */
  358. }
  359.  
  360. /*****************************************************************************
  361. * Routine to free a binary tree, which is not needed any more:             *
  362. *****************************************************************************/
  363. static void FreeBinTree(BinTree *Pbin)
  364. {
  365.     static Flip = FALSE;
  366.  
  367.     if (Flip) {
  368.     Flip = FALSE;
  369.     fprintf(stderr, "m\b");
  370.     }
  371.     else {
  372.     Flip = TRUE;
  373.     fprintf(stderr, "M\b");
  374.     }
  375.  
  376.     if (Pbin) {
  377.     FreeBinTree(Pbin -> right);
  378.     FreeBinTree(Pbin -> left);
  379.     free((char *) Pbin);
  380.     }
  381. }
  382.  
  383. /*****************************************************************************
  384. * MyExit routine. Note it might call to CloseGraph without calling         *
  385. * InitGraph(), or call MouseClose() without MouseInit(), or call         *
  386. * RestoreCtrlBrk() without SetUpCtrlBrk() and it is the responsibility         *
  387. * of the individual modules to do nothing in these cases.             *
  388. *****************************************************************************/
  389. void MyExit(int ExitCode)
  390. {
  391. #ifdef __MSDOS__
  392.     fprintf(stderr,
  393.     "\nPoly3D-R: Total RealTime %ld seconds, Core left %ldk.\n",
  394.         time(NULL) - SaveTotalTime, coreleft() / 1024);
  395. #else
  396.     fprintf(stderr,
  397.     "\nPoly3D-R: Total RealTime %ld seconds.\n",
  398.         time(NULL) - SaveTotalTime);
  399. #endif /* __MSDOS__ */
  400.  
  401.     exit(ExitCode);
  402. }
  403.  
  404. /******************************************************************************
  405. * Close output file (if open), and exit.                      *
  406. ******************************************************************************/
  407. void QuitGifError(void)
  408. {
  409.     PrintGifError();
  410.     MyExit('G');
  411. }
  412.