home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * Program to draw 3D object as solid objects in GIF image file format. *
- * *
- * Options: *
- * 1. -m : More flag, to print more imformation on input/errors. *
- * 2. -a ambient : Ratio of the ambient color. *
- * 3. -c n : Number of bit ber pixel (2^n is number of colors possible). *
- * 4. -l x y z : Light source direction vector. *
- * 5. -s x y : Specify new dimensions to generate the resulting image. *
- * 6. -g : Use gouraud shading. *
- * 7. -b : Delete Back facing polygons. *
- * 8. -M Mask : Create boolean Mask (coverage) image as well. *
- * 9. -o Objects : List of objects to be displayed from the input data files. *
- * This option should not be last and Object list terminates with *
- * next option (- as first char). ALL objects are displayed otherwise.*
- * 10. -v ViewFile : Optional view to start with. *
- * 11. -z : Print current version, and some helpfull data. *
- * 12. -2 : Force 2 light sources at opposite direction of light vectors. *
- * *
- * Note some of those options may be permanently set to a different default *
- * using the configuration file "Poly3D-R.cfg" *
- * *
- * Usage: poly3d-r [-a Ambient] [-c N] [-l X Y Z] [-2] [-m] [-s Xsize Ysize] *
- * [-S SubSample] [-g] [-b] [-M Mask] [-o Objects...] [-v ViewFile] [-z] *
- * DFiles *
- * *
- * Written by: Gershon Elber Ver 2.0, Mar 1990 *
- *****************************************************************************/
-
- #ifdef __MSDOS__
- #include <stdlib.h>
- #include <conio.h>
- #include <io.h>
- #include <dos.h>
- #include <alloc.h>
- #endif /* __MSDOS__ */
-
- #include <stdio.h>
- #include <math.h>
- #include <time.h>
- #include "program.h"
- #include "getarg.h"
- #include "genmat.h"
- #include "parser.h"
- #include "config.h"
- #include "ctrl-brk.h"
-
- #ifdef __MSDOS__
- /* This huge stack is mainly from second phase - the segment intersections */
- /* which may cause recursive calls - a lot... */
- extern unsigned int _stklen = 32766;
- #endif /* __MSDOS__ */
-
- #ifdef SYSV
- static char *VersionStr =
- "Poly3D-R version 2.0, Gershon Elber,\n\
- (C) Copyright 1989 Gershon Elber, Non commercial use only.";
- #else
- static char *VersionStr = "Poly3D-R version 2.0, Gershon Elber, "
- __DATE__ ", " __TIME__ "\n"
- "(C) Copyright 1989 Gershon Elber, Non commercial use only.";
- #endif /* SYSV */
-
- static char *CtrlStr =
- "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";
-
-
- static long SaveTotalTime;
- static int ViewFlag = FALSE;
- static GifColorType MaskColorMap[2] = { /* Boolean mask GIF file color map. */
- { 0, 0, 0 },
- { 255, 255, 255 }
- };
-
- int NumOfPolygons = 0; /* Total number of polygons scan converted. */
- int NumOfVertices = 0; /* Total number of vertices. */
- MatrixType GlblViewMat; /* Current view of object. */
-
- /* Amount scene was scaled up from normalized [-1..1] size on both X & Y: */
- float ScaleUpFactor = 0.0;
-
- /* The following are setable variables (via configuration file poly3d-h.cfg).*/
- int MoreFlag = FALSE, GouraudFlag = FALSE, BackFacingFlag = FALSE,
- ScreenXSize = DEFAULT_SCREEN_XSIZE, ScreenYSize = DEFAULT_SCREEN_YSIZE;
- double NormalAvgDegree = DEFAULT_NORMAL_AVG_DEGREE;
- struct ShadingInfoStruct ShadingInfo = {
- 1,
- DEFAULT_BITS_PER_PIXEL,
- 0,
- DEFAULT_COLOR,
- DEFAULT_BACK_GROUND_COLOR,
- FALSE,
- NULL, /* No color map yet */
- NULL,
- DEFAULT_LIGHT_SOURCE,
- DEFAULT_AMBIENT,
- };
-
- static ConfigStruct SetUp[] =
- { { "AvgDegree", (VoidPtr) &NormalAvgDegree, SU_REAL_TYPE },
- { "Ambient", (VoidPtr) &ShadingInfo.Ambient, SU_REAL_TYPE },
- { "SubSample", (VoidPtr) &ShadingInfo.SubSamplePixel, SU_INTEGER_TYPE },
- { "BitsPerPixel", (VoidPtr) &ShadingInfo.BitsPerPixel, SU_INTEGER_TYPE },
- { "LightSrcX", (VoidPtr) &ShadingInfo.LightSource[0], SU_REAL_TYPE },
- { "LightSrcY", (VoidPtr) &ShadingInfo.LightSource[1], SU_REAL_TYPE },
- { "LightSrcZ", (VoidPtr) &ShadingInfo.LightSource[2], SU_REAL_TYPE },
- { "TwoSources", (VoidPtr) &ShadingInfo.TwoSources, SU_BOOLEAN_TYPE },
- { "Xsize", (VoidPtr) &ScreenXSize, SU_INTEGER_TYPE },
- { "Ysize", (VoidPtr) &ScreenYSize, SU_INTEGER_TYPE },
- { "Color", (VoidPtr) &ShadingInfo.DefaultColor, SU_INTEGER_TYPE },
- { "BackGroundColor", (VoidPtr) &ShadingInfo.BackGroundColor, SU_INTEGER_TYPE },
- { "More", (VoidPtr) &MoreFlag, SU_BOOLEAN_TYPE } };
- #define NUM_SET_UP (sizeof(SetUp) / sizeof(ConfigStruct))
-
- /* All polygons to be scan convert will be inserted into this hash table */
- /* during the preprocessing (PrepareXXXX functions). */
- struct PolygonStruct **PolyHashTable;
-
-
- static void MainGetViewFile(char *ViewFileName);
- static FileDescription **MainGetDataFiles(char **DataFileNames,
- int NumOfDataFiles);
- static void FreeBinTree(struct BinTree *Pbin);
-
- /*****************************************************************************
- * Main routine - Read Parameter line and do what you need... *
- *****************************************************************************/
- void main(int argc, char **argv)
- {
- int AmbientFlag = FALSE, ColorFlag = FALSE, LightSrcFlag = FALSE,
- TwoSourcesFlag = FALSE, GifMaskFlag = FALSE, ObjFlag = FALSE,
- NumObjs = 0, RealNumObjs, VerFlag = FALSE, NumFiles = 0,
- ImageSizeFlag = FALSE, SubSampleFlag = FALSE, Error;
- char **Objects = NULL, *ViewName = NULL, **FileNames = NULL, *GifMaskName;
- double Size;
- FileDescription **FD;
- GifFileType *GifFile, *GifMask = NULL;
-
- SaveTotalTime = time(NULL); /* Save starting time. */
- #ifdef __MSDOS__
- ctrlbrk((int (*)()) MyExit); /* Kill this program if ^C... */
- #endif /* __MSDOS__ */
- SetUpHardErr(); /* Set up hardware error trap routine (int 24h). */
-
- Config("poly3d-r", SetUp, NUM_SET_UP); /* Read config. file if exists. */
-
- if ((Error = GAGetArgs (argc, argv, CtrlStr,
- &AmbientFlag, &ShadingInfo.Ambient,
- &ColorFlag, &ShadingInfo.BitsPerPixel,
- &LightSrcFlag, &ShadingInfo.LightSource[0],
- &ShadingInfo.LightSource[1],
- &ShadingInfo.LightSource[2],
- &TwoSourcesFlag,
- &MoreFlag, &ImageSizeFlag, &ScreenXSize, &ScreenYSize,
- &SubSampleFlag, &ShadingInfo.SubSamplePixel,
- &GouraudFlag, &BackFacingFlag, &GifMaskFlag, &GifMaskName,
- &ObjFlag, &NumObjs, &Objects,
- &ViewFlag, &ViewName, &VerFlag, &NumFiles, &FileNames)) != 0) {
- GAPrintErrMsg(Error);
- GAPrintHowTo(CtrlStr);
- MyExit(1);
- }
-
- if (TwoSourcesFlag) ShadingInfo.TwoSources = TRUE;
-
- if (ShadingInfo.Ambient < 0.0 || ShadingInfo.Ambient > 1.0) {
- fprintf(stderr, "Ambient light specified not in [0.0..1.0] range, %lf selected instead\n",
- DEFAULT_AMBIENT);
- ShadingInfo.Ambient = DEFAULT_AMBIENT;
- }
- if (ShadingInfo.BitsPerPixel < 1 || ShadingInfo.BitsPerPixel > 8) {
- fprintf(stderr, "PitsPerPixel not in [1..8] range, %d selected instead\n",
- DEFAULT_BITS_PER_PIXEL);
- ShadingInfo.BitsPerPixel = DEFAULT_BITS_PER_PIXEL;
- }
-
- Size = sqrt(SQR(ShadingInfo.LightSource[0]) +
- SQR(ShadingInfo.LightSource[1]) +
- SQR(ShadingInfo.LightSource[2]));
- if (ABS(Size) < EPSILON) {
- fprintf(stderr, "Light source vector is zero, Z axis selected instead\n");
- ShadingInfo.LightSource[0] =
- ShadingInfo.LightSource[1] = 0.0;
- ShadingInfo.LightSource[2] = 1.0;
- }
- else {
- ShadingInfo.LightSource[0] /= Size;
- ShadingInfo.LightSource[1] /= Size;
- ShadingInfo.LightSource[2] /= Size;
- }
-
- if (VerFlag) {
- fprintf(stderr, "\n%s\n\n", VersionStr);
- GAPrintHowTo(CtrlStr);
- ConfigPrint(SetUp, NUM_SET_UP);
- MyExit(0);
- }
-
- if (!NumFiles) {
- fprintf(stderr, "No data file names were given, exit\n");
- GAPrintHowTo(CtrlStr);
- MyExit(1);
- }
-
- if (SubSampleFlag) {
- if (ShadingInfo.SubSamplePixel < 1 || ShadingInfo.SubSamplePixel > 4) {
- fprintf(stderr, "Sub sampling can be 1 to 4 only (1x1 to 4x4)\n");
- GAPrintHowTo(CtrlStr);
- MyExit(1);
- }
- }
-
- MainGetViewFile(ViewName);
-
- /* Get the data files: */
- FD = MainGetDataFiles(FileNames, NumFiles);
-
- /* Prepare data structures of objects themselves: */
- RealNumObjs = NumObjs;
- PrepareViewData(FD, &RealNumObjs, Objects);
- if (NumObjs != 0) RealNumObjs = NumObjs;
-
- /* Into shadingInfo global structure: */
- PrepareColorTable(FD, NumObjs, RealNumObjs, Objects);
-
- EvalVrtxColors(FD, NumObjs, Objects);
-
- #ifndef DEBUG_NO_GIF
-
- /* Open stdout for the GIF image file: */
- if ((GifFile = EGifOpenFileHandle(1)) == NULL ||
- EGifPutScreenDesc(GifFile,
- ScreenXSize, ScreenYSize, ShadingInfo.BitsPerPixel, 0,
- ShadingInfo.BitsPerPixel, ShadingInfo.PColorMap) == ERROR ||
- EGifPutImageDesc(GifFile,
- 0, 0, ScreenXSize, ScreenYSize, FALSE,
- ShadingInfo.BitsPerPixel, NULL) == ERROR)
- QuitGifError();
- /* Open special mask file if required: */
- if (GifMaskFlag &&
- ((GifMask = EGifOpenFileName(GifMaskName, FALSE)) == NULL ||
- EGifPutScreenDesc(GifMask,
- ScreenXSize, ScreenYSize, 1, 0, 1, MaskColorMap) == ERROR ||
- EGifPutImageDesc(GifMask,
- 0, 0, ScreenXSize, ScreenYSize, FALSE, 1, NULL) == ERROR))
- QuitGifError();
-
- #endif DEBUG_NO_GIF
-
- ScanConvertData(GifFile, GifMask); /* Do the real interesting stuff... */
-
- #ifndef DEBUG_NO_GIF
-
- EGifCloseFile(GifFile);
- if (GifMask) EGifCloseFile(GifMask);
-
- #endif DEBUG_NO_GIF
-
- MyExit(0);
- }
-
- /*****************************************************************************
- * Main routine to read the view description file, into GlblViewMat: *
- *****************************************************************************/
- static void MainGetViewFile(char *ViewFileName)
- {
- double Scale;
- MatrixType Mat;
- FILE *f;
-
- if (ViewFlag && (f = fopen(ViewFileName, "rt")) == NULL) {
- fprintf(stderr, "Can't open view file %s\n", ViewFileName);
- MyExit(1);
- }
-
- /* Get view data if ViewFlag, otherwise set default view (isometric): */
- GetViewFile(f, ViewFlag);
-
- /* Now its time to scale the normalized image (+/-1 on both X & Y) to */
- /* size specified by the image dimensions. We scale up to the SMALLER */
- /* dimension, and put the center at the image center. */
- /* Also, as the GIF image starts at the top, we must flip the image */
- /* along Y axis. */
- ScaleUpFactor = Scale = MIN(ScreenXSize * ShadingInfo.SubSamplePixel,
- ScreenYSize * ShadingInfo.SubSamplePixel) / 2.0;
- GenMatScale(Scale, -Scale, Scale, Mat);
- MultTwo4by4(GlblViewMat, GlblViewMat, Mat);
- GenMatTrans(ScreenXSize * ShadingInfo.SubSamplePixel / 2.0,
- ScreenYSize * ShadingInfo.SubSamplePixel / 2.0, 0.0, Mat);
- MultTwo4by4(GlblViewMat, GlblViewMat, Mat);
-
- if (ViewFlag) fclose(f); /* Close the file. */
- }
-
- /*****************************************************************************
- * Main routine to read the data description files: *
- * Returns pointer to pointers on FileDescription structures (one per file). *
- *****************************************************************************/
- static FileDescription **MainGetDataFiles(char **DataFileNames,
- int NumOfDataFiles)
- {
- int i;
- long SaveTime = time(NULL);
- FILE *f;
- FileDescription **FDbase, **FDinc; /* Used to save memory pointers loc. */
-
- NumOfPolygons = 0;
- fprintf(stderr, "\nPass 1, Polys = ");
-
- FDbase = FDinc = (FileDescription **) /* Allocate the pointers block. */
- MyMalloc((unsigned) sizeof(FileDescription *) * (NumOfDataFiles + 1));
-
- for (i=0; i<NumOfDataFiles; i++) {
- if (MoreFlag) {
- fprintf(stderr, "\rReading data file %s", *DataFileNames);
- fprintf(stderr, "\nPass 1, Polys = ");
- }
- f = fopen(*DataFileNames, "rt"); /* Open the file. */
- if (!f)
- {
- fprintf(stderr, "Can't open data file %s\n", *DataFileNames);
- MyExit(1);
- }
-
- *FDinc = GetDataFile(f); /* Get the data file. */
- FreeBinTree((*FDinc) -> VertexPointer); /* We dont need these trees. */
- FreeBinTree((*FDinc) -> PolygonPointer); /* objects are all loaded. */
- (*FDinc) -> VertexPointer = (*FDinc) -> PolygonPointer = NULL;
- fprintf(stderr, " \b"); /* Erase the FreeBinTree marker... */
- *FDinc++;
-
- fclose(f); /* Close the file. */
-
- DataFileNames++; /* Skip to next file name. */
- }
-
- *FDinc = NULL;
-
- fprintf(stderr, ", %ld seconds.", time(NULL) - SaveTime);
-
- return FDbase;
- }
-
- /*****************************************************************************
- * My Routine to allocate dynamic memory. All program requests must call *
- * this routine (no direct call to malloc). Dies if no memory. *
- *****************************************************************************/
- char *MyMalloc(unsigned size)
- {
- char *p;
-
- if ((p = malloc(size)) != NULL) return p;
-
- fprintf(stderr, "\nNot enough memory, exit\n");
- MyExit(2);
-
- return NULL; /* Makes warning silent. */
- }
-
- /*****************************************************************************
- * Routine to free a binary tree, which is not needed any more: *
- *****************************************************************************/
- static void FreeBinTree(BinTree *Pbin)
- {
- static Flip = FALSE;
-
- if (Flip) {
- Flip = FALSE;
- fprintf(stderr, "m\b");
- }
- else {
- Flip = TRUE;
- fprintf(stderr, "M\b");
- }
-
- if (Pbin) {
- FreeBinTree(Pbin -> right);
- FreeBinTree(Pbin -> left);
- free((char *) Pbin);
- }
- }
-
- /*****************************************************************************
- * MyExit routine. Note it might call to CloseGraph without calling *
- * InitGraph(), or call MouseClose() without MouseInit(), or call *
- * RestoreCtrlBrk() without SetUpCtrlBrk() and it is the responsibility *
- * of the individual modules to do nothing in these cases. *
- *****************************************************************************/
- void MyExit(int ExitCode)
- {
- #ifdef __MSDOS__
- fprintf(stderr,
- "\nPoly3D-R: Total RealTime %ld seconds, Core left %ldk.\n",
- time(NULL) - SaveTotalTime, coreleft() / 1024);
- #else
- fprintf(stderr,
- "\nPoly3D-R: Total RealTime %ld seconds.\n",
- time(NULL) - SaveTotalTime);
- #endif /* __MSDOS__ */
-
- exit(ExitCode);
- }
-
- /******************************************************************************
- * Close output file (if open), and exit. *
- ******************************************************************************/
- void QuitGifError(void)
- {
- PrintGifError();
- MyExit('G');
- }
-