Category : C Source Code
Archive   : POLY3DRS.ZIP
Filename : POLY3D-R.C

 
Output of file : POLY3D-R.C contained in archive : POLY3DRS.ZIP
/*****************************************************************************
* 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
#include
#include
#include
#include
#endif /* __MSDOS__ */

#include
#include
#include
#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 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');
}


  3 Responses to “Category : C Source Code
Archive   : POLY3DRS.ZIP
Filename : POLY3D-R.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/