/***************************************************************************** * Program to draw 3D object as wireframe from any ortographic view * * Options: * * 1. -c : Object is closed. If object is closed each edge is shared by two * * polygons and therefore can bedrawn only once. * * 2. -e #Edges : If the edges are order is specific way (like in DrawFn3D) * * and only the k first edges of each polygons are to be displayed * * use this option as -e k. * * 3. -i : Internal edges. IRIT solid modeller may generate edges, which one * * may not want to see (default). -i will draw all of them. * * 4. -m : More flag, to print more imformation on input/errors. * * Note all messages goes to STDOUT (not stderr!) as this program * * works in graphic mode, and we can redirect stdout to a file. * * 5. -n : Draw vertices normals if the data has them, otherwise ignore. * * 6. -M : draw surfaces Mesh and curves control polygon. * * 7. -I n : number of isolines for a given surface. * * 8. -P : generate polygon for surfaces. * * 9. -S n : log based 2 of number of samples per curve. * * 10. -f FineNess : log based 2 of the fineness control of surface to * * polygon subdivision. * * 11. -4 : force 4 polygons per flat. Otherwise two. * * 12. -z : Print current version, and some helpfull data. * * * * Note some of those options way be permanently set to a different default * * using the configuration file "Poly3D.cfg" * * * * Usage: * * Poly3D [-c] [-m] [-i] [-e #Edges] [-n] [-N] [-M] [-I n] [-P] [-S n] * * [-f FineNess] [-4] [-z] Files * * * * Written by: Gershon Elber Ver 3.0, Aug 1990 * *****************************************************************************/ #ifdef __MSDOS__ #include #include #include #include #include #endif /* __MSDOS__ */ #include #include #include #include "program.h" #include "getarg.h" #include "genmat.h" #include "interact.h" #include "graphgen.h" #include "config.h" #ifdef __TURBOC__ /* Malloc debug routine - only on TC++ 1.0 and above. */ #define __DEBUG_MALLOC__ #endif /* __TURBOC__ */ #ifdef __MSDOS__ #include "matherr.h" #endif /* __MSDOS__ */ #ifdef __MSDOS__ extern unsigned int _stklen = 32766; /* Increase default stack size. */ #endif /* __MSDOS__ */ #ifdef NO_CONCAT_STR static char *VersionStr = "Poly3D Version 3.0, Gershon Elber,\n\ (C) Copyright 1989/90/91 Gershon Elber, Non commercial use only."; #else static char *VersionStr = "Poly3D " VERSION ", Gershon Elber, " __DATE__ ", " __TIME__ "\n" "(C) Copyright 1989/90/91 Gershon Elber, Non commercial use only."; #endif /* NO_CONCAT_STR */ static char *CtrlStr = "poly3d c%- m%- i%- e%-#Edges!d n%- N%- M%- P%- I%-#IsoLines!d S%-#SampPerCrv!d f%-FineNess!d 4%- z%- DFiles!*s"; static int GlblNormalLenAux = NORMAL_DEFAULT_LENGTH, GlblFineNess = 5, GlblFourPerFlat = FALSE; /* The following are setable variables (via configuration file poly3d.cfg). */ int #if defined(__MSDOS__) || defined(DJGCC) /* Defaults for MSDOS intr_lib. */ GlblWindowFrameWidth = 8, GlblViewFrameColor = INTR_COLOR_RED, GlblViewBackColor = INTR_COLOR_BLACK, GlblTransFrameColor = INTR_COLOR_GREEN, GlblTransBackColor = INTR_COLOR_BLACK, GlblStatusFrameColor = INTR_COLOR_RED, GlblStatusBackColor = INTR_COLOR_BLACK, GlblInputFrameColor = INTR_COLOR_RED, GlblInputBackColor = INTR_COLOR_BLACK, GlblDrawHeader = FALSE, GlblSmoothTextScroll = FALSE, GlblIntrSaveMethod = INTR_SAVE_DISK, GlblMouseSensitivity = 10, /* Sensitivity control of mouse device. */ GlblJoystickExists = FALSE, #endif /*__MSDOS__ || DJGCC */ #ifdef __MSDOS__ GlblGraphDriver = DETECT, #endif /* __MSDOS__ */ GlblWasCtrlBrk = FALSE, GlblMouseExists = TRUE, GlblTransformMode = TRANS_SCREEN, /* Screen, Object trans. mode. */ GlblViewMode = VIEW_ORTHOGRAPHIC, /* Persp, Ortho etc. */ GlblDepthCue = TRUE, /* Activate depth cueing. */ GlblDrawSolid = FALSE, /* Use hardware Z buffer rendering. */ GlblInternal = FALSE, GlblDoGraphics = TRUE,/* Control if running in graphics/text mode. */ GlblMore = FALSE, GlblNumEdges = 0, GlblDrawVNormal = FALSE, GlblDrawPNormal = FALSE, GlblClosedObject = FALSE, GlblDrawSurfaceMesh = FALSE, GlblDrawSurfacePoly = FALSE, GlblNumOfIsolines = DEFAULT_NUM_OF_ISOLINES, GlblSamplesPerCurve = DEFAULT_SAMPLES_PER_CURVE; static char *BGIDriverPath = NULL, *SVGANameMode = NULL; char #ifdef __GL__ /* Preferance position and size of view and transformation windows. */ *GlblTransPrefPos = "455, 640, 520, 965", *GlblViewPrefPos = "1, 450, 520, 965", #endif /* __GL__ */ #if defined(__MSDOS__) || defined(DJGCC) /* Defaults for MSDOS intr_lib. */ *GlblViewWndwPos = "0.02, 0.02, 0.72, 0.98", *GlblTransWndwPos = "0.75, 0.02, 0.98, 0.98", *GlblStatusWndwPos = "", *GlblInputWndwPos = "", *GlblIntrSaveDisk = "d:\\", #endif /* __MSDOS__ || DJGCC */ GlblFirstDataFileName[PATH_NAME_LEN]; /* Hold name of first data file. */ static long SaveTotalTime; MatrixType CrntViewMat; /* This is the current view! */ RealType GlblNormalLen = 0.0; /* Scaler for normals if drawn. */ static ConfigStruct SetUp[] = { #if defined(__MSDOS__) || defined(DJGCC) /* Defaults for MSDOS intr_lib. */ { "Joystick", (VoidPtr) &GlblJoystickExists, SU_BOOLEAN_TYPE }, { "Mouse", (VoidPtr) &GlblMouseExists, SU_BOOLEAN_TYPE }, { "MouseSensitivity", (VoidPtr) &GlblMouseSensitivity,SU_INTEGER_TYPE }, { "WndwWidth", (VoidPtr) &GlblWindowFrameWidth,SU_INTEGER_TYPE }, { "WndwHeader", (VoidPtr) &GlblDrawHeader, SU_BOOLEAN_TYPE }, { "WndwViewClr", (VoidPtr) &GlblViewFrameColor, SU_INTEGER_TYPE }, { "WndwTransClr", (VoidPtr) &GlblTransFrameColor, SU_INTEGER_TYPE }, { "WndwViewPos", (VoidPtr) &GlblViewWndwPos, SU_STRING_TYPE }, { "WndwTransPos", (VoidPtr) &GlblStatusWndwPos, SU_STRING_TYPE }, { "WndwBackSave", (VoidPtr) &GlblIntrSaveMethod, SU_INTEGER_TYPE }, { "WndwBackSavePath", (VoidPtr) &GlblIntrSaveDisk, SU_STRING_TYPE }, #endif /* __MSDOS__ || DJGCC */ #ifdef __MSDOS__ { "SVGANameMode", (VoidPtr) &SVGANameMode, SU_STRING_TYPE }, { "BGIDriverPath", (VoidPtr) &BGIDriverPath, SU_STRING_TYPE }, { "GraphDriver", (VoidPtr) &GlblGraphDriver, SU_INTEGER_TYPE }, #endif /* __MSDOS__ */ #ifdef __GL__ { "TransPrefPos", (VoidPtr) &GlblTransPrefPos, SU_STRING_TYPE }, { "ViewPrefPos", (VoidPtr) &GlblViewPrefPos, SU_STRING_TYPE }, #endif /* __GL__ */ { "FineNess", (VoidPtr) &GlblFineNess, SU_INTEGER_TYPE }, { "FourPerFlat", (VoidPtr) &GlblFourPerFlat, SU_BOOLEAN_TYPE }, { "ViewMode", (VoidPtr) &GlblViewMode, SU_INTEGER_TYPE }, { "TransMode", (VoidPtr) &GlblTransformMode, SU_INTEGER_TYPE }, { "ClosedObject", (VoidPtr) &GlblClosedObject, SU_BOOLEAN_TYPE }, { "DepthCue", (VoidPtr) &GlblDepthCue, SU_BOOLEAN_TYPE }, { "DrawSolid", (VoidPtr) &GlblDrawSolid, SU_BOOLEAN_TYPE }, { "Internal", (VoidPtr) &GlblInternal, SU_BOOLEAN_TYPE }, { "More", (VoidPtr) &GlblMore, SU_BOOLEAN_TYPE }, { "NormalLength", (VoidPtr) &GlblNormalLenAux, SU_INTEGER_TYPE }, { "DrawVNormal", (VoidPtr) &GlblDrawVNormal, SU_BOOLEAN_TYPE }, { "DrawPNormal", (VoidPtr) &GlblDrawPNormal, SU_BOOLEAN_TYPE }, { "NumOfEdges", (VoidPtr) &GlblNumEdges, SU_INTEGER_TYPE }, { "NumOfIsolines", (VoidPtr) &GlblNumOfIsolines, SU_INTEGER_TYPE }, { "SamplesPerCurve", (VoidPtr) &GlblSamplesPerCurve, SU_INTEGER_TYPE }, { "DrawSurfaceMesh", (VoidPtr) &GlblDrawSurfaceMesh, SU_BOOLEAN_TYPE }, { "DrawSurfacePoly", (VoidPtr) &GlblDrawSurfacePoly, SU_BOOLEAN_TYPE } }; #define NUM_SET_UP (sizeof(SetUp) / sizeof(ConfigStruct)) static IPObjectStruct *MainGetDataFiles(char **DataFileNames, int NumOfDataFiles); static IPPolygonStruct *Curve2Polylines(CagdCrvStruct *Crv); static IPPolygonStruct *Surface2Polylines(CagdSrfStruct *Srf); /***************************************************************************** * Main routine - Read Parameter line and do what you need... * *****************************************************************************/ void #ifdef __MSDOS__ cdecl /* So we can use -rp in Borland 3.0 (parameters in registers.). */ #endif /* __MSDOS__ */ main(int argc, char **argv) { int Error, EdgesFlag = FALSE, VerFlag = FALSE, IsoLinesFlag = FALSE, SamplesPerCurveFlag = FALSE, NumFiles = 0, FineNessFlag = FALSE; char **FileNames = NULL; IPObjectStruct *PObjects; SaveTotalTime = time(NULL); #ifdef __MSDOS__ ctrlbrk((int cdecl (*)()) MyExit); /* Kill process if ^C. */ #endif /* __MSDOS__ */ #ifdef __MSDOS__ MathErrorSetUp(ME_KILL, NULL); /* Kill process if math error occurs! */ #endif /* __MSDOS__ */ Config("poly3d", SetUp, NUM_SET_UP); /* Read config. file if exists. */ if ((Error = GAGetArgs(argc, argv, CtrlStr, &GlblClosedObject, &GlblMore, &GlblInternal, &EdgesFlag, &GlblNumEdges, &GlblDrawVNormal, &GlblDrawPNormal, &GlblDrawSurfaceMesh, &GlblDrawSurfacePoly, &IsoLinesFlag, &GlblNumOfIsolines, &SamplesPerCurveFlag, &GlblSamplesPerCurve, &FineNessFlag, &GlblFineNess, &GlblFourPerFlat, &VerFlag, &NumFiles, &FileNames)) != 0) { GAPrintErrMsg(Error); GAPrintHowTo(CtrlStr); exit(1); } if (VerFlag) { fprintf(stderr, "\n%s\n\n", VersionStr); GAPrintHowTo(CtrlStr); ConfigPrint(SetUp, NUM_SET_UP); exit(0); } if (!NumFiles) { fprintf(stderr, "No data file names where given, exit.\n"); GAPrintHowTo(CtrlStr); exit(1); } GlblNormalLen = ((RealType) GlblNormalLenAux) / NORMAL_SCALER_LENGTH; strcpy(GlblFirstDataFileName, FileNames[0]);/* Save name of first file. */ /* Get the data files: */ IritPrsrPolyListCirc = FALSE; PObjects = MainGetDataFiles(FileNames, NumFiles); if (GlblViewMode != VIEW_PERSPECTIVE) GlblViewMode = IritPrsrWasPrspMat ? VIEW_PERSPECTIVE : VIEW_ORTHOGRAPHIC; /* If no limit on num of edges set to maximum. Else increase count by */ /* one as we count vertices and n vertices bounds n-1 edges. */ if (GlblNumEdges == 0) GlblNumEdges = 32767; else GlblNumEdges++; #ifdef __MSDOS__ GGInstallBGI(BGIDriverPath, SVGANameMode); GGInitGraph(GlblGraphDriver, TRUE); /* Initiate the graphic driver. */ #else #ifdef DJGCC GGInitGraph(0, TRUE); /* Initiate the graphic driver. */ #else GGInitGraph(argc, argv, TRUE, TRUE); /* Initiate the graphic driver. */ #endif /* DJGCC */ #endif /* __MSDOS__ */ InteractGeomObject(PObjects); MyExit(0); } /***************************************************************************** * Main routine to read the data description files: * * Returns pointer to pointers on FileDescription structures (one per file). * *****************************************************************************/ static IPObjectStruct *MainGetDataFiles(char **DataFileNames, int NumOfDataFiles) { int i; char *ErrorMsg; FILE *f; IPObjectStruct *PObj, *PObjTail, *PObjHead = NULL; for (i = 0; i < NumOfDataFiles; i++) { if (GlblMore) fprintf(stderr, "Reading data file %s\n", *DataFileNames); #if defined(__MSDOS__) || defined(DJGCC) if ((f = fopen(*DataFileNames, "rt")) == NULL) { /* Open the file. */ #else if ((f = fopen(*DataFileNames, "r")) == NULL) { /* Open the file. */ #endif /* __MSDOS__ || DJGCC */ fprintf(stderr, "Can't open data file %s\n", *DataFileNames); exit(1); } if ((PObj = IritPrsrGetObjects(f)) != NULL) { /* Get the data file. */ PObjTail = PObj; while (PObjTail -> Pnext) PObjTail = PObjTail -> Pnext; PObjTail -> Pnext = PObjHead; PObjHead = PObj; } if (GlblMore && IritPrsrParseError(&ErrorMsg)) fprintf(stderr, "File %s, %s\n", *DataFileNames, ErrorMsg); fclose(f); /* Close the file. */ DataFileNames++; /* Skip to next file name. */ } if (PObjHead == NULL) { fprintf(stderr, "No data found.\n"); exit(1); } return PObjHead; } /***************************************************************************** * Routine to convert all surfaces/curves into polylines as follows: * * Curves are converted to single polyline with SamplesPerCurve samples. * * Surface are converted into GlblNumOfIsolines curves in each axes, each * * handled as Curves above. The polylines are saved in the appropriate * * surface/curve slots. * *****************************************************************************/ IPObjectStruct *IritPrsrProcessFreeForm(IPObjectStruct *CrvObjs, IPObjectStruct *SrfObjs) { CagdCrvStruct *Crv, *Crvs; CagdSrfStruct *Srf, *Srfs; IPObjectStruct *PObj, *PPolyObj; IPPolygonStruct *PPolygon, *PPolygonTemp; if (CrvObjs == NULL && SrfObjs == NULL) return NULL; /* Make sure requested format is something reasonable. */ if (GlblNumOfIsolines < 2) { GlblNumOfIsolines = 2; if (GlblMore) fprintf(stderr, "NumOfIsolines is less than 2, 2 picked instead.\n"); } if (GlblSamplesPerCurve < 1) { GlblSamplesPerCurve = 1; if (GlblMore) fprintf(stderr, "SamplesPerCurve is less than 1, 1 picked instead.\n"); } if (GlblSamplesPerCurve > CAGD_MAX_BEZIER_CACHE_ORDER) { GlblSamplesPerCurve = CAGD_MAX_BEZIER_CACHE_ORDER; if (GlblMore) fprintf(stderr, "Log2 SamplesPerCurve is more than %d, %d picked instead.\n", CAGD_MAX_BEZIER_CACHE_ORDER, CAGD_MAX_BEZIER_CACHE_ORDER); } BzrCrvSetCache(GlblSamplesPerCurve, TRUE); /* Set up the bezier cache. */ if (CrvObjs) { for (PObj = CrvObjs; PObj != NULL; PObj = PObj -> Pnext) { Crvs = PObj -> U.PCrvs; PObj -> FFPolylines = PPolyObj = IritPrsrNewObjectStruct(); *PPolyObj = *PObj; /* Copy all its attributes. */ PPolyObj -> U.PPolygon = NULL; PPolyObj -> Type = IP_OBJ_POLY; for (Crv = Crvs; Crv != NULL; Crv = Crv -> Pnext) { PPolygon = PPolygonTemp = Curve2Polylines(Crv); while (PPolygonTemp -> Pnext) PPolygonTemp = PPolygonTemp -> Pnext; PPolygonTemp -> Pnext = PPolyObj -> U.PPolygon; PPolyObj -> U.PPolygon = PPolygon; } } } if (SrfObjs) { for (PObj = SrfObjs; PObj != NULL; PObj = PObj -> Pnext) { Srfs = PObj -> U.PSrfs; PObj -> FFPolylines = PPolyObj = IritPrsrNewObjectStruct(); *PPolyObj = *PObj; /* Copy all its attributes. */ PPolyObj -> U.PPolygon = NULL; PPolyObj -> Type = IP_OBJ_POLY; for (Srf = Srfs; Srf != NULL; Srf = Srf -> Pnext) { PPolygon = PPolygonTemp = Surface2Polylines(Srf); while (PPolygonTemp -> Pnext) PPolygonTemp = PPolygonTemp -> Pnext; PPolygonTemp -> Pnext = PPolyObj -> U.PPolygon; PPolyObj -> U.PPolygon = PPolygon; } /* IF polygons were actually created, make sure we would not */ /* create then again... */ if (GlblDrawSurfacePoly) PObj -> FFPolygons = PObj -> FFPolylines; } } if (SrfObjs == NULL) return CrvObjs; else if (CrvObjs == NULL) return SrfObjs; else { for (PObj = SrfObjs; PObj -> Pnext != NULL; PObj = PObj -> Pnext); PObj -> Pnext = CrvObjs; return SrfObjs; } } /***************************************************************************** * Routine to convert a single curve into a polyline with SamplesPerCurve * * samples, into a polyline object. * *****************************************************************************/ static IPPolygonStruct *Curve2Polylines(CagdCrvStruct *Crv) { int i, j, n; IPVertexStruct *V, *VHead = NULL, *VTail = NULL; IPPolygonStruct *P, *PHead = NULL; CagdPolylineStruct *CagdPoly, *CagdPolyHead = CagdCrv2Polyline(Crv, GlblSamplesPerCurve); if (GlblDrawSurfaceMesh) { CagdPoly = CagdCrv2CtrlPoly(Crv); CagdPoly -> Pnext = CagdPolyHead; CagdPolyHead = CagdPoly; } for (CagdPoly = CagdPolyHead; CagdPoly != NULL; CagdPoly = CagdPoly -> Pnext) { n = CagdPoly -> Length; for (i = 0, VHead = NULL; i < n; i++) { /* Convert to vertices. */ V = IritPrsrNewVertexStruct(); for (j = 0; j < 3; j++) /* Convert to our format. */ V -> Coord[j] = CagdPoly -> Polyline[i].Pt[j]; if (VHead) { VTail -> Pnext = V; VTail = V; } else VHead = VTail = V; } P = IritPrsrNewPolygonStruct(); P -> PVertex = VHead; P -> Type = IP_POLYLINE; P -> Pnext = PHead; PHead = P; } CagdPolylineFreeList(CagdPoly); return PHead; } #ifdef __GL__ /***************************************************************************** * Routine to convert a single surface into polygons with GlblFineNess as * * sample control, and GlblFourPerFlat controlling # of polys per bilinear. * *****************************************************************************/ IPPolygonStruct *Surface2Polygons(CagdSrfStruct *Srf) { int i, j; IPVertexStruct *V, *VHead, *VTail = NULL; IPPolygonStruct *P, *PHead = NULL; CagdPolygonStruct *CagdPolygon, *CagdPolygonHead = CagdSrf2Polygons(Srf, 1 << GlblFineNess, TRUE, GlblFourPerFlat); for (CagdPolygon = CagdPolygonHead, VHead = NULL; CagdPolygon != NULL; CagdPolygon = CagdPolygon -> Pnext) { /* All polygons are triangles! */ for (i = 0, VHead = NULL; i < 3; i++) { /* Convert to vertices. */ V = IritPrsrNewVertexStruct(); IP_SET_VRTX_NORMAL(V); /* This vertex has normal. */ for (j = 0; j < 3; j++) /* Convert to our format. */ V -> Coord[j] = CagdPolygon -> Polygon[i].Pt[j]; for (j = 0; j < 3; j++) V -> Normal[j] = CagdPolygon -> Normal[i].Vec[j]; if (VHead) { VTail -> Pnext = V; VTail = V; } else VHead = VTail = V; } P = IritPrsrNewPolygonStruct(); P -> PVertex = VHead; P -> Type = IP_POLYGON; P -> Pnext = PHead; PHead = P; } CagdPolygonFreeList(CagdPolygonHead); return PHead; } #endif /* __GL__ */ /***************************************************************************** * Routine to convert a single surface into a polylines with SamplesPerCurve * * samples, NumOfIsolines isolines into a polyline object list. * * If surface is to be approximated as polygons GlblFineNess and * * GlblFourPerFlat controls this approximation. * *****************************************************************************/ static IPPolygonStruct *Surface2Polylines(CagdSrfStruct *Srf) { int i, j, n; IPVertexStruct *V, *VHead = NULL, *VTail = NULL; IPPolygonStruct *P, *PHead = NULL; CagdPolylineStruct *CagdPolyline, *CagdPolylineTemp, *CagdPolylineHead = NULL; CagdPolygonStruct *CagdPolygon, *CagdPolygonHead = NULL; /* Note we compute normals in msdos only on demand. On unix we always */ /* compute them as they are also used in shading. */ if (GlblDrawSurfacePoly) CagdPolygonHead = CagdSrf2Polygons(Srf, 1 << GlblFineNess, #if defined(__MSDOS__) || defined(DJGCC) GlblDrawVNormal, GlblFourPerFlat); #else TRUE, GlblFourPerFlat); #endif /* __MSDOS__ || DJGCC */ else CagdPolylineHead = CagdSrf2Polylines(Srf, GlblNumOfIsolines, GlblSamplesPerCurve); if (GlblDrawSurfaceMesh) { CagdPolyline = CagdPolylineTemp = CagdSrf2CtrlMesh(Srf); if (CagdPolylineTemp) while (CagdPolylineTemp -> Pnext) CagdPolylineTemp = CagdPolylineTemp -> Pnext; CagdPolylineTemp -> Pnext = CagdPolylineHead; CagdPolylineHead = CagdPolyline; } for (CagdPolyline = CagdPolylineHead; CagdPolyline != NULL; CagdPolyline = CagdPolyline -> Pnext) { n = CagdPolyline -> Length; for (i = 0, VHead = NULL; i < n; i++) { /* Convert to vertices. */ V = IritPrsrNewVertexStruct(); for (j = 0; j < 3; j++) /* Convert to our format. */ V -> Coord[j] = CagdPolyline -> Polyline[i].Pt[j]; if (VHead) { VTail -> Pnext = V; VTail = V; } else VHead = VTail = V; } P = IritPrsrNewPolygonStruct(); P -> PVertex = VHead; P -> Type = IP_POLYLINE; P -> Pnext = PHead; PHead = P; } CagdPolylineFreeList(CagdPolylineHead); for (CagdPolygon = CagdPolygonHead, VHead = NULL; CagdPolygon != NULL; CagdPolygon = CagdPolygon -> Pnext) { /* All polygons are triangles! */ for (i = 0, VHead = NULL; i < 3; i++) { /* Convert to vertices. */ V = IritPrsrNewVertexStruct(); IP_SET_VRTX_NORMAL(V); /* This vertex has normal. */ for (j = 0; j < 3; j++) /* Convert to our format. */ V -> Coord[j] = CagdPolygon -> Polygon[i].Pt[j]; for (j = 0; j < 3; j++) V -> Normal[j] = CagdPolygon -> Normal[i].Vec[j] * GlblNormalLen; if (VHead) { VTail -> Pnext = V; VTail = V; } else VHead = VTail = V; } P = IritPrsrNewPolygonStruct(); P -> PVertex = VHead; P -> Type = IP_POLYGON; P -> Pnext = PHead; PHead = P; } CagdPolygonFreeList(CagdPolygonHead); return PHead; } #ifdef __DEBUG_MALLOC__ /***************************************************************************** * My Routine to allocate dynamic memory. All program requests must call this * * routine (no direct call to malloc). Dies if no memory. * *****************************************************************************/ static void AllocError(const char *Msg, VoidPtr *p) { fprintf(stderr, "%s, Ptr = %p\n", Msg, p); MyExit(3); } #endif /* __DEBUG_MALLOC__ */ /***************************************************************************** * My Routine to allocate dynamic memory. All program requests must call this * * routine (no direct call to malloc). Dies if no memory. * *****************************************************************************/ VoidPtr MyMalloc(unsigned size) { static int Count = 0; VoidPtr p; #ifdef __MSDOS__ if (Count++ == 50) { Count = 0; fprintf(stderr, "Core left: %ldk \r", coreleft() / 1024); } #endif /* __MSDOS__ */ if ((p = malloc(size)) != NULL) return p; fprintf(stderr, "Not enough memory, exit.\n"); MyExit(2); return NULL; /* Make warnings silent. */ } /***************************************************************************** * My Routine to free dynamic memory. All program requests must call this * * routine (no direct call to free). * *****************************************************************************/ void MyFree(VoidPtr p) { #ifdef __DEBUG_MALLOC__ switch (heapchecknode(p)) { case _HEAPCORRUPT: AllocError("Heap is corrupted", p); break; case _BADNODE: AllocError("Attempt to free a bogus pointer", p); break; case _FREEENTRY: AllocError("Attempt to free an already freed pointer", p); break; case _USEDENTRY: break; default: AllocError("Allocation error", p); break; } #endif /* __DEBUG_MALLOC__ */ free(p); } /***************************************************************************** * Trap Cagd_lib errors right here. * *****************************************************************************/ void CagdFatalError(CagdFatalErrorType ErrID) { char *ErrorMsg = CagdDescribeError(ErrID); GGCloseGraph(); /* Close the graphic driver. */ fprintf(stderr, "CAGD_LIB: %s", ErrorMsg); exit(-1); } /***************************************************************************** * My exit routine. * *****************************************************************************/ void MyExit(int ExitCode) { GGCloseGraph(); /* Close the graphic driver. */ #ifdef __MSDOS__ fprintf(stderr, "\nPoly3D: Total RealTime %ld seconds, Core left %ldk.\n", time(NULL) - SaveTotalTime, coreleft() / 1024); #else fprintf(stderr, "\nPoly3D: Total RealTime %ld seconds.\n", time(NULL) - SaveTotalTime); #endif /* __MSDOS__ */ exit(ExitCode); }