dxf2gl/ 777 0 0 0 6105270604 5177 5dxf2gl/dispgl.cpp 666 0 0 10656 6051525452 7221 // Microsoft Windows/NT openGL include files #include "glos.h" #include #include #include // local object include files #include "faccess.h" #include "globj.h" #include "glface.h" #define DEBUG 0 static FaceList *CurObj; void SetObj( FaceList *obj ) { CurObj = obj; } // // Get the view values (e.g., the min and max values for the X, Y and Z // axies. // typedef struct { float min; float max; } AxisMinMax; static AxisMinMax Axis; void init_minmax( GL_object &GL_Obj ) { Axis.min = GL_Obj.PointRange.GetMin(); Axis.max = GL_Obj.PointRange.GetMax(); Axis.min = (float)((int)Axis.min + 1); Axis.max = (float)((int)Axis.max + 1); } void print_minmax(void) { printf("axis range = %2.2f to %2.2f\n", Axis.min, Axis.max ); } // // Feed the point list to openGL as a polygon // void disp_gl_face(FaceList::face *face_ptr ) { int NumPts = face_ptr->point_cnt; int i; glBegin( GL_POLYGON ); for (i = 0; i < NumPts; i++) { glVertex3fv(face_ptr->f[i].v); } glEnd(); } // disp_gl_face static int SpinAngle = 0; // spin angle, in degrees // // The glRotatef function takes four arguments, the angle of rotation, // and a 3-D point. The axis of rotation defined by the line from (0,0,0) // to the 3-D point. So to rotate on the X-axis, the point would be // (1, 0, 0), to rotate on the Y-axis (0, 1, 0) and to rotate on the // Z-axis (0, 0, 1). // const int On = 1; const int Off = 0; // Rotate first on the X-axis static int AxisPoint[ 3 ] = {On, Off, Off}; static int AxisIx = 0; // // Display the wire frame described by the face list pointed to by // CurObj. // void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT); if (CurObj != NULL) { glPushMatrix(); glRotatef((float)SpinAngle, (float)AxisPoint[0], (float)AxisPoint[1], (float)AxisPoint[2]); FaceList::ListHandle FaceList = CurObj->GetListStart(); while (FaceList != NULL) { disp_gl_face( CurObj->GetFace(FaceList) ); FaceList = CurObj->GetNextFace( FaceList ); } // while glPopMatrix(); glFlush(); auxSwapBuffers(); } // CurObj != NULL } void CALLBACK spinDisplay(void) { SpinAngle = SpinAngle + 2; if (SpinAngle > 360) { AxisPoint[ AxisIx ] = Off; AxisIx = (AxisIx + 1) % 3; AxisPoint[ AxisIx ] = On; SpinAngle = SpinAngle - 360; } display(); } void CALLBACK myReshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glMatrixMode (GL_PROJECTION); glLoadIdentity(); if (w <= h) { float AdjY = Axis.max * (GLfloat)h / (GLfloat)w; glOrtho(-Axis.max, Axis.max, // x-axis -AdjY, AdjY, // y-axis -Axis.max, Axis.max); // z-axis } else { float AdjX = Axis.max * (GLfloat)h / (GLfloat)w; glOrtho(-AdjX, AdjX, // x-axis -Axis.max, Axis.max, // y-axis -Axis.max, Axis.max); // z-axis } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void myinit (void) { // clear background to black glClearColor (0.0, 0.0, 0.0, 0.0); // draw all lines in white, on the black background glColor3f(1.0, 1.0, 1.0); // Set polygon mode to line glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // "cull" invisible polygons glCullFace(GL_BACK); // turn on culling glEnable(GL_CULL_FACE); } // myinit /* Read a DXF file and display the object using openGL */ void display_gl_obj(char *ProgName, char *FileName) { FileAccess FileObj( FileName ); if (FileObj.FileOK()) { GL_object GL_Obj( &FileObj ); FaceList *CurObj = GL_Obj.GL_GetFaceList(); // Get the DXF object SetObj( CurObj ); init_minmax( GL_Obj ); // save the min and the max axis values #if DEBUG print_minmax(); CurObj->print(); #endif // GL display stuff auxInitDisplayMode (AUX_DOUBLE | AUX_RGBA ); auxInitPosition (0, 0, 500, 500); auxInitWindow (ProgName); myinit(); auxReshapeFunc(myReshape); auxIdleFunc(spinDisplay); auxMainLoop(display); delete CurObj; } } // display_gl_obj void main(int argc, char *argv[]) { char *FileName; if (argc == 2) { FileName = argv[ 1 ]; display_gl_obj(argv[0], FileName); } else { printf("usage: %s \n", argv[0] ); } } dxf2gl/dxfvals.h 666 0 0 2236 6074400134 7020 typedef enum { DXF_start = 0, DXF_textval = 1, DXF_name = 2, DXF_othername1 = 3, DXF_othername2 = 4, DXF_entity_handle = 5, DXF_line_type = 6, DXF_text_style = 7, DXF_layer_name = 8, DXF_var_name = 9, DXF_primary_X = 10, DXF_other_X_1 = 11, DXF_primary_Y = 20, DXF_other_Y_1 = 21, DXF_other_Z = 31, DXF_elevation = 38, DXF_thickness = 39, DXF_floatvals = 40, DXF_repeat = 49, DXF_angle1 = 50, DXF_angle2 = 51, DXF_angle3 = 52, DXF_angle4 = 53, DXF_angle5 = 54, DXF_angle6 = 55, DXF_angle7 = 56, DXF_angle8 = 57, DXF_angle9 = 58, DXF_colornum = 62, DXF_entities_flg = 66, DXF_ent_ident = 67, DXF_SeventyFlag = 70, DXF_SeventyOneFlag= 71, DXF_SeventyTwoFlag= 72, DXF_view_state = 69, DXF_comment = 999 } DXF_values; dxf2gl/faccess.cpp 666 0 0 4035 6076531124 7320 /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ /* File access routines. FileAccess constructor - open the file FileAccess destructor - close the file get_line - return a line from the file as a null terminated string */ #include #include #include "ianstd.h" #include "faccess.h" FileAccess::FileAccess(const char *FileName ) { FilePtr = fopen(FileName, "r"); // open file for reading FileOpenOK = FALSE; if (FilePtr != NULL) FileOpenOK = TRUE; else perror(FileName); // print system error message } // FileAccess constructor FileAccess::~FileAccess(void) { if (FileOpenOK) fclose(FilePtr); } // FileAccess destructor void FileAccess::file_error(const char *msg ) { printf("%s\n", msg ); } // // Get a line from the file pointed to by the class variable FilePtr. // When fgets reads the line, it includes the cariage return character. // This function overwrites this with a null (like the gets() function). // BOOLEAN FileAccess::get_line(char *LineBuf, const int BufSize) { BOOLEAN result; result = FALSE; LineBuf[0] = '\0'; if (fgets(LineBuf, BufSize, FilePtr)) { int len = strlen(LineBuf); if (LineBuf[len-1] = '\n') LineBuf[len-1] = '\0'; result = TRUE; } else { if (feof(FilePtr)) file_error("Unexpected end of file"); else perror("File error:"); } return result; } dxf2gl/faccess.h 666 0 0 3407 6076531546 6777 #ifndef FACCESS_H #define FACCESS_H /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ /* FileAccess - a class for opening and reading ASCII files. Public functions: FileAccess constructor - The argument to this constructor is the file name. The constructor will open the file and set the variable FileOpenOK (which can be accessed via FileOK). FileAccess destructor - Close the file get_line - get a line for the file and return it as a null terminated string. */ #include #include "ianstd.h" class FileAccess { // Variables private: FILE *FilePtr; BOOLEAN FileOpenOK; protected: public: // Class Functions private: OpenFile(char *FileName); void file_error(const char *msg); protected: public: FileAccess(const char *FileName = "" ); ~FileAccess(void); BOOLEAN FileOK(void) { return FileOpenOK; } BOOLEAN get_line(char *LineBuf, const int BufSize); }; // FileAccess #endif dxf2gl/globj.cpp 666 0 0 43275 6076613612 7042 /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ #include #include "globj.h" #include "glscan.h" #include "gltoken.h" #include "dxfvals.h" static void print_token(gl_token token, GL_scanner &GL_scan); /* The GL_object class supplies the class functions to read a DXF file consisting of 3DFACE and POLYLINE "entities". These "entities" describe the polygon faces that make up a 3D object. The GL_object class was written to support the display of DXF files using openGL under windows NT. DXF files are text files that describe 3D models built with AutoCAD, a program from AutoDesk. Since AutoCAD was one of the first modelers that ran on PC, the DXF file format that it used became a defacto standard among the programs that later compeated with AutoDesk. Also, many models are provided in DXF format. The DXF file format has all the hallmarks of something designed by a bunch of Fortran programmers. The format is complicated and only partially documented. A DXF file consists of a number of sections, not all of which may be used by a given application. For example, many DXF files contain color information, but GL_object does not use it. Since a given application is likely to ignore at least some of the information that may be present in a DXF file, a DXF reader must be written so that it skips over sections that it does not need. This design is followed by GL_object too. The structure of a DXF file is defined by text strings (which this program turns into enumeration "tokens") and numeric values. For example, all sections start with a zero (a DXF_start, below) and the token "SECTION". There may also be names. For example, each object or object section has a name (e.g., "Cube3" or "ENGINE"). GL_object reads the file and breaks it up into "tokens", which are special words in the DXF file, and special integers (for example, DXF_name). Points are described by single precision "float" values. A copy of the enumeration describing the "special integer values" is included for reference below (this is from dxfvals.h). typedef enum { DXF_start = 0, DXF_textval = 1, DXF_name = 2, DXF_othername1 = 3, DXF_othername2 = 4, DXF_entity_handle = 5, DXF_line_type = 6, DXF_text_style = 7, DXF_layer_name = 8, DXF_var_name = 9, DXF_primary_X = 10, DXF_other_X_1 = 11, DXF_primary_Y = 20, DXF_other_Y_1 = 21, DXF_primary_Z = 30, DXF_other_Z = 31, DXF_elevation = 38, DXF_thickness = 39, DXF_floatvals = 40, DXF_repeat = 49, DXF_angle1 = 50, DXF_angle1 = 51, DXF_angle1 = 52, DXF_angle1 = 53, DXF_angle1 = 54, DXF_angle1 = 55, DXF_angle1 = 56, DXF_angle1 = 57, DXF_angle1 = 58, DXF_colornum = 62, DXF_entities_flg = 66, DXF_ent_ident = 67, DXF_view_state = 69, DXF_SeventyFlag = 70, // I guess I have a horror of literal DXF_SeventyOneFlag= 71, // constants. DXF_SeventyTwoFlag= 72, DXF_comment = 999 } DXF_values; */ // // GL_GetFaceList is called to process the DXF file and return a pointer // to a FaceList object. // // The DXF file format was not designed so that it could be easily // described as a grammer and/or a finite state machine. In fact, one // almost suspects that the format is kept purposely obscure, in an // attemp to stifle any competition for AutoDesk. An attempt is made // below to describe the DXF file format in terms of a grammer. Truth // to tell, it seems rather dicey. John Walker and his colleagues may // have been geniuses, but they also had clay feet. Below is an attempt // at describing the file format in grammerical form. As anyone who has // read the DXF file format description can see, this is only a fraction // of the sections that can be in a DXF file. Since some DXF file // information is application dependent and is not needed by all // applications, unneeded sections are simply skipped. // // Notes: Words that are in capitols are tokens (see tokens.h), // that is, values returned by the scanner. // Words that start with "DXF_" are DXF integer values // with special meanings. Curley braces ("{" and "}") // mean "one or more occurances". // // DXF_Section = DXF_start SECTION DXF_name SecName SecData SecEnd // SecName = HEADER | TABLES | ENTITIES // SecData = DXF_start SecStuff // SecEnd = DXF_start ENDSEC // SecStuff = TableSec | EntitiesSec // TableSec = TABLE TableGroup DXF_start ENDTAB // TableGroup = LayerGroup | OtherGroup // OtherGroup = DXF_name GroupName GroupData // LayerGroup = DXF_name LAYER DXF_SeventyFlag MaxItems {LayerDesc} // LayerDesc = DXF_start LAYER DXF_name LayerName // DXF_SeventyFlag FlagVals DXF_colornum // ColorNum DXF_line_type LineType // LineType = CONTINUOUS // EntitiesSec = {DXF_start EntType DXF_layer_name EntName EntData} // EntTyp = THREE_D_FACE // EntData = ThreeD_data // ThreeD_data = {Face} // Face = Set1 Set2 Set3 Set4 EndSet // EndSet = 62 0 // // FaceList *GL_object::GL_GetFaceList(void) { FaceList *CurObj; gl_token token; CurObj = NULL; token = GL_scan->get_next_token(); while (token != end_of_file) { switch (token) { case header: // Skip the header section SkipSection(); break; case tables: // This program skips the table section. Some of the // grammar for tables is outlined in the comment above. while (IsTable()) { if (IsName()) { // Following the DXF_name token there will be the // table name. Currently all table information is // skipped by reading tokens until the ENDTAB token // is encounterd. // Get the table name token = GL_scan->get_next_token(); while (token != endtab && token != end_of_file) { token = GL_scan->get_next_token(); } if (token == end_of_file) { printf("GL_GetFaceList: unexpected end of file\n"); } } // IsName } // while table break; case blocks: // terminated by an endblk case block: case entities: { // ended by an endsec token = GL_scan->get_next_token(); while (token != endsec && token != endblk && token != end_of_file) { switch (token) { case three_d_face: Get3DFACE( CurObj ); break; case polyline: GetPolyLine( CurObj ); break; } // switch if (token != end_of_file) token = GL_scan->get_next_token(); } // while } // case blocks && entities } // end switch if (token != end_of_file) token = GL_scan->get_next_token(); } // while return CurObj; } // GL_GetFaceList /* GetPolyLine Process a DXF file POLYLINE section and enter the points in the polygon face list. An attempt at explaining the POLYLINE format is shown below: PolyLineHeader PolyVert MeshVals PolyLineHeader = DXF_start POLYLINE DXF_name EntName PolyVert = DXF_entities_flg PolyElev PolyElev = 10 0 20 0 30 Elevation MeshVals = 70 0 71 PolygonCount 72 PointCount EntName = string The code below skips the POLYLINE header and the POLYLINE vertices section. It looks for the "72" marker, which indicates the number of points per polygon. Or at least that is what I think it means and what this object uses it for. Following the 71 and 72 groups is a sequence of VERTEX objects, where each VERTEX describes one 3D point. It is these points that are entered into the polygon face list. I have not been able to get POLYLINE objects to display properly, so there is clearly something wrong with my interpretation of the DXF file format spec. */ void GL_object::GetPolyLine(FaceList *&CurObj) { gl_token token; int polypoint = 3; if (CurObj == NULL) CurObj = new FaceList; token = GL_scan->get_next_token(); // skip down to the first vertex in the poly line while (token != vertex && token != seqend && token != end_of_file) { token = GL_scan->get_next_token(); // Look for the 72 marker - the number of points in the polygon // If this is not found, then the default is three if (token == integer && GL_scan->get_gl_int() == DXF_SeventyTwoFlag) { token = GL_scan->get_next_token(); if (token == integer) { polypoint = GL_scan->get_gl_int(); } else { printf("GetPolyLine: int value expected after '72' polycount mark\n"); } } } if (token == vertex) { // allocate storage for one polygon in the polyline object CurObj->get_new_poly_face(polypoint); while (token != seqend && token != end_of_file) { token = GL_scan->get_next_token(); // get the token following the vertex if (GL_scan->get_gl_int() == DXF_layer_name) { token = GL_scan->get_next_token(); // read the layer name token = GL_scan->get_next_token(); // try for colornum if (GL_scan->get_gl_int() == DXF_colornum) { token = GL_scan->get_next_token(); // read the color value } else // it not the layer name, so put it back in the stack. undo(token); } else { // it not the layer name, but it the start of a point list, // push it back on the stack if (GL_scan->get_gl_int() == 10) undo(token); } // We should now be at the start of the point description get_poly_point( CurObj); // get points {10, 20, 30} token = GL_scan->get_next_token(); // get the token following point desc. while (token != seqend && token != end_of_file && GL_scan->get_gl_int() != DXF_start) { token = GL_scan->get_next_token(); } if (token != seqend && token != end_of_file) token = GL_scan->get_next_token(); // should be either vertex or seqend } // while } // if } // GetPolyLine /* Get3DFACE Process a DXF file 3DFACE section and enter the face into the face list. A 3DFACE section consists of either three or four 3D points. Each "face" is read in and added to the face list for the object. DXF files that consist entirely of 3DFACE "entities" will be interpreted properly and will display properly using openGL. */ void GL_object::Get3DFACE(FaceList *&CurObj) { gl_token token; // The last token fetched should be 3DFACE. This is followed by some // optional information about the face (which this program ignores), // followed by the point descriptions. // // The points are preceeded by the integers {10, 20, 30}, {11, 21, 31}, // {12, 22, 32}, {13, 23, 33}. There will always be four points. // if the polygon is a triangle, the third and fourth points will be // the same. // // Skip down to the start of the first set: // token = GL_scan->get_next_token(); while (token != integer || (token == integer && GL_scan->get_gl_int() != 10)) token = GL_scan->get_next_token(); // push the "10" back into the stack GL_scan->put_token_in_stack( integer, GL_scan->get_gl_int() ); // We should not be at the start of the point list if (CurObj == NULL) CurObj = new FaceList; CurObj->get_new_3DFACE(); // allocate storage for a new face get_3DFACE_point( CurObj ); // get points {10, 20, 30} get_3DFACE_point( CurObj ); // get points {11, 21, 31} get_3DFACE_point( CurObj ); // get points {12, 22, 32} get_3DFACE_point( CurObj ); // get points {13, 23, 33} } // Get3DFACE /* GetCoord Read in a 3D point coordinate. Each coordiniate is a "float" and will be preceeded by an integer value. For example, the X coordinate for the first point will be preceeded by a 10, the Y coordinate by a 20, and the Z coordinate by a 30. */ float GL_object::GetCoord(void) { gl_token token; token = GL_scan->get_next_token(); if (token != integer) printf("GL_object::GetCoord: integer point marker expected\n"); token = GL_scan->get_next_token(); if (token != real) printf("GL_object::GetCoord: real expected\n"); return GL_scan->get_gl_float(); } /* get_3DFACE_point Read in the three coordinates that make up a 3D point. The object keeps track of the min and max dimensions so that the object can be properly displated by openGL. */ void GL_object::get_3DFACE_point(FaceList *FaceObjPtr) { float x, y, z; x = GetCoord(); y = GetCoord(); z = GetCoord(); FaceObjPtr->add_3DFACE_point(x, y, z ); PointRange.SetMinMax( x ); PointRange.SetMinMax( y ); PointRange.SetMinMax( z ); } /* get_poly_point Read in a 3D pont form a POLYLINE object. */ void GL_object::get_poly_point(FaceList *FaceObjPtr) { float x, y, z; x = GetCoord(); y = GetCoord(); z = GetCoord(); FaceObjPtr->add_poly_point(x, y, z); PointRange.SetMinMax( x ); PointRange.SetMinMax( y ); PointRange.SetMinMax( z ); } /* --------------------------------------------------------- The functions below are used by the DXF file scanner to recognize various parts of the DXF file. An input token stack is used so that the scanner can be "backed up", when an item is not found and a try can be made for another item. --------------------------------------------------------- */ BOOLEAN GL_object::IsEndSet(void) { gl_token token; BOOLEAN retval = FALSE; token = GL_scan->get_next_token(); if (token == integer && GL_scan->get_gl_int() == 62) { if (IsStart()) retval = TRUE; } else printf("IsEndSet: value 62 expected\n"); return retval; } BOOLEAN GL_object::IsEndSec(void) { gl_token token; token = GL_scan->get_next_token(); if (token == endsec) return TRUE; else { printf("ENDSEC token expected\n"); return FALSE; } } void GL_object::undo(gl_token token) { if (token == integer) GL_scan->put_token_in_stack( integer, GL_scan->get_gl_int()); else GL_scan->put_token_in_stack( token ); } BOOLEAN GL_object::Is3DFace(void) { gl_token token; int retval = FALSE; token = GL_scan->get_next_token(); if (token == integer && GL_scan->get_gl_int() == DXF_start) { token = GL_scan->get_next_token(); if (token == three_d_face) { retval = TRUE; } else { GL_scan->put_token_in_stack( token ); GL_scan->put_token_in_stack( integer, DXF_start ); } } else { undo(token); } return retval; } BOOLEAN GL_object::IsTable(void) { gl_token token; int retval = FALSE; token = GL_scan->get_next_token(); if (token == integer && GL_scan->get_gl_int() == DXF_start) { token = GL_scan->get_next_token(); if (token == table) { retval = TRUE; } else { GL_scan->put_token_in_stack( token ); GL_scan->put_token_in_stack( integer, DXF_start ); } } else { undo(token); } return retval; } BOOLEAN GL_object::IsLayerName(void) { gl_token token; token = GL_scan->get_next_token(); if (token == integer && GL_scan->get_gl_int() == DXF_layer_name) return TRUE; else { printf("DXF_layer_name expected\n"); return FALSE; } } BOOLEAN GL_object::IsStart(void) { gl_token token; token = GL_scan->get_next_token(); if (token == integer && GL_scan->get_gl_int() == DXF_start) return TRUE; else { printf("DXF_start expected\n"); return FALSE; } } BOOLEAN GL_object::IsName(void) { gl_token token; token = GL_scan->get_next_token(); if (token == integer && GL_scan->get_gl_int() == DXF_name) return TRUE; else { printf("DXF_name expected\n"); return FALSE; } } // // SkipSection // // Not all DXF sections are relevant to a given application and some // sections are AutoDesk application specific. This function will skip // a section. The function reads tokens until it finds the end of section // sequence. It then backs up, leaving the end of section sequence in place. // If the EOF marker is found first, an error is printed. // void GL_object::SkipSection(void) { gl_token token; token = GL_scan->get_next_token(); while (token != endsec && token != end_of_file) { token = GL_scan->get_next_token(); } // put the end section marker back in the stack if (token == end_of_file) { printf("GL_object::SkipSection: unexpected end of file\n"); exit(1); } } // SkipSection static void print_token(gl_token token, GL_scanner &GL_scan) { GL_scan.print_token( token ); if (token == integer) printf(" %d", GL_scan.get_gl_int()); else if (token == real) printf(" %f", GL_scan.get_gl_float()); else if (token == name) printf(" %s", GL_scan.get_gl_name()); printf("\n"); } dxf2gl/globj.h 666 0 0 4307 6076614234 6461 #ifndef GLOBJ_H #define GLOBJ_H /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ /* This file contains the parser object that processes the DXF file. The class function GL_GetFaceList returns the Face list for the 3D DXF object. */ #include "faccess.h" #include "glscan.h" #include "glface.h" class MinMax { private: float min; float max; public: typedef enum {MAXVAL = 1024*1000} bogus; // The initial values of max and min should be way beyond any reasonable // range. MinMax(void) { min = (float)MAXVAL; max = (float)(-(MAXVAL)); } void SetMinMax( float val ) { if (val < min) min = val; if (val > max) max = val; } float GetMin(void) { return min; } float GetMax(void) { return max; } }; class GL_object { // variables private: GL_scanner *GL_scan; protected: public: MinMax PointRange; // class functions private: void set_min_max(); void undo(gl_token token); BOOLEAN IsEndSec(void); BOOLEAN IsStart(void); BOOLEAN IsName(void); BOOLEAN IsTable(void); BOOLEAN IsLayerName(void); BOOLEAN Is3DFace(void); BOOLEAN IsEndSet(void); float GetCoord(void); void get_3DFACE_point(FaceList *FaceObjPtr); void get_poly_point(FaceList *FaceObjPtr); void SkipSection(void); void Get3DFACE(FaceList *&CurObj); void GetPolyLine(FaceList *&CurObj); protected: public: GL_object(FileAccess *FileObj ) { GL_scan = new GL_scanner( FileObj ); }; ~GL_object(void) { delete GL_scan; } FaceList *GL_GetFaceList(void); }; // GL_object #endif dxf2gl/glos.h 666 0 0 374 6027204172 6300 // // GLOS.H - Microsoft specific file header // #include // disable data conversion warnings #pragma warning(disable : 4244) // MIPS #pragma warning(disable : 4136) // X86 #pragma warning(disable : 4051) // ALPHA dxf2gl/glscan.cpp 666 0 0 21064 6100336046 7173 /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ // // This file contains the GL_scanner class functions for the DXF file scanner. // These functions are: // // print_token print the associated text string for a token // gl_name_lookup check if the word is a DXF reserved word // scan_word pick out words from the input line and catagorized them // can_numer scan words starting with numeric characters, integers // and reals. // get_token_from_stack pop a token and possibly its value from the token // stack // put_token_in_stack push the current token and possibly its value // into the token stack. // get_next_token The main scanner routine, called to return the // next token from the input stream. #include #include #include #include "ianstd.h" #include "gltstack.h" #include "glscan.h" // // There is a "hole" in C++. You are not allowed to // initialize a static variable inside of a class definition, // even though at static class member is truely static - // that is, there is only one copy, for all instances of // that class. So the variable is included here. // typedef struct { char *GLname; gl_token token; } table_rec; static table_rec res_word_table[] = { {"bad_gl_token", bad_gl_token}, {"SECTION", section}, {"HEADER", header }, {"ENDSEC", endsec }, {"SEQEND", seqend }, {"BLOCKS", blocks }, {"BLOCK", block }, {"ENDBLK", endblk }, {"VERTEX", vertex }, {"TABLES", tables }, {"TABLE", table }, {"LAYER", layer }, {"CONTINUOUS", contin }, {"ENDTAB", endtab }, {"ENTITIES", entities}, {"3DFACE", three_d_face}, {"EOF", end_of_file }, {"POLYLINE", polyline }, {"integer", integer}, {"real", real}, {"name", name}, { NULL, bad_gl_token }}; // // print_token // // Print the token name, as a character string. // void GL_scanner::print_token(const gl_token token) { char *str = "unknown"; if (token < last_gl_token) str = res_word_table[token].GLname; printf("%s", str ); } // print_token // // gl_name_lookup // // gl_name_lookup looks up a word in the reserved word table. If the // word is found in the table, the associated enumeration value is // returned. Otherwise the function returns "name", meaning that // the word is an identifier. // gl_token GL_scanner::gl_name_lookup(void) { int ix = 0; BOOLEAN found = FALSE; gl_token return_token; return_token = name; while (res_word_table[ix].GLname != NULL && !found) { if (strcmp(WordBuf, res_word_table[ix].GLname) == 0) { return_token = res_word_table[ix].token; found = TRUE; } else ix++; } return return_token; } // gl_name_lookup // // scan_word // // Find a word (e.g., a set of alpha-numeric characters bounded by spaces). // The function is only called if the first character is an alphabetic char. // The word will either be a reserved word (e.g., header or layer) or // an identifier. This function returns either "name" for an identifier // or the associated enumeration value for a reserved word. // gl_token GL_scanner::scan_word(char *cptr) { char *WordBufPtr = WordBuf; gl_token return_token; while (isalnum(*cptr)) *WordBufPtr++ = *cptr++; *WordBufPtr = '\0'; return_token = gl_name_lookup(); return return_token; } // scan_word // // scan_number // // DXF files may contain reserved words (or perhaps identifiers) that // start with integer values. For example, the reserved word 3DFACE. // This function scans the word and returns either "name" or the // associated enumeration for an identifier that starts with a number. // The function returns integer or real for numeric values and bad_gl_token // if there is an error. // // The token is either a name or reserved word begining with a number // (e.g., like the reserved word 3DFACE) or its an integer or a float. // The grammar is: // // {digit}alpha ==> name or reserved word // {digit}(space|null) ==> integer // [+|-]{digit}.{digit} ==> float // gl_token GL_scanner::scan_number(char *cptr) { char *WordBufPtr = WordBuf; gl_token return_token = bad_gl_token; if (*cptr == '+') cptr++; if (*cptr == '-') { *WordBufPtr++ = *cptr++; } while (isdigit(*cptr)) *WordBufPtr++ = *cptr++; if (isalpha(*cptr)) { // its a reserved word or a name while (isalnum(*cptr)) *WordBufPtr++ = *cptr++; *WordBufPtr = '\0'; return_token = gl_name_lookup(); } else { if (*cptr == '.') { return_token = real; *WordBufPtr++ = *cptr++; // put the '.' into the string while (isdigit(*cptr)) *WordBufPtr++ = *cptr++; *WordBufPtr = '\0'; sscanf(WordBuf, "%f", &gl_float); } else { // its and integer return_token = integer; *WordBufPtr = '\0'; sscanf(WordBuf, "%d", &gl_int); } } return return_token; } // scan_number // // get_token_from_stack // // The scanner uses two token look ahead when checking for things like // the EOF token sequence. If EOF is not found then the tokens are // pushed back into the token stack. This function pops a token and // possibly an integer or real value from the token stack and puts the // values in the scanner object. This allows the rest of the scanner // to behave as if the token were fetched from the input stream. // gl_token GL_scanner::get_token_from_stack() { gl_token token; token = bad_gl_token; if (token_in_stack()) { token_stack::token_stack_type t; t = stack.pop_token(); token = t.token; if (token == integer) gl_int = t.val.intval; else if (token == real) gl_float = t.val.realval; } else printf("Error: get_token_from_stack called on empty stack\n"); return token; } // // put_token_in_stack // // This function pushs the current token into the token stack. This is // needed to support scanner look ahead and back the token stream up // (just as ungetc() does in UNIX). The push_token function is // overloaded to support either a token, a token and an integer or a // token and a real. // void GL_scanner::put_token_in_stack(const gl_token token) { if (token == integer) stack.push_token(token, gl_int); else if (token == real) stack.push_token(token, gl_float); else stack.push_token(token); } // // get_next_token // // Scan the DXF file for tokens. This function assume that there is one // DXF token per line. This is the main scanner routine which is called // to return the next token. // // The functions that call the scanner need a way to check for the // end of file token sequence and, if the token sequence is not the end // of file sequence to push the tokens back into the input stream, // so that they will be gotten the next time get_next_token is called. // This is supported by the token stack object. // gl_token GL_scanner::get_next_token(void) { const int LineSize = 80; char line[LineSize]; gl_token return_token; return_token = bad_gl_token; gl_int = -1; if (token_in_stack()) { return_token = get_token_from_stack(); } else { if (MyFileObj->get_line( line, sizeof(line) )) { char *cptr = line; while (isspace(*cptr)) cptr++; // if its an alphabetic character, then it is either a DXF "reserved // word" (e.g., a DXF token) or it a name. if (isalpha(*cptr)) return_token = scan_word(cptr); else { // Its either a token or name starting with a number or its a // floating point or an integer. return_token = scan_number(cptr); } } } return return_token; } dxf2gl/glscan.h 666 0 0 5206 6100335706 6622 #ifndef GLSCAN_H /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ /* This file contains the scanner object that tokenizes the input stream. The scanner either returns a reserved word (e.g., section or three_d_face), "name" (an identifier, such as a layer name or face name), integer or real. The various DXF markers (e.g., the 70 marker or 0 for start) are returned as integers. This scanner is designed as a front end for a program that reads a DXF file and displays it as a 3D wire frame, using openGL (hense then "GL" naming). Scanning and parsing a DXF file is difficult, because the DXF file format seems to have grown over time in an ad hoc manner. Further, the documentation is obscure and/or incomplete. While parsing the file, it is sometimes necessary to "back up". To support this, a stack is maintained. Input tokens and values can be "pushed" onto this stack and re-read. The token_stack class supports this feature. */ #define GLSCAN_H #include "faccess.h" #include "gltoken.h" #include "gltstack.h" #include "ianstd.h" class GL_scanner { // variables private: token_stack stack; float gl_float; int gl_int; FileAccess *MyFileObj; typedef enum {WordBufSize = 40} bogus2; char WordBuf[ WordBufSize ]; protected: public: // class functions private: gl_token scan_number(char *cptr); gl_token scan_word(char *cptr); gl_token gl_name_lookup(void); protected: public: GL_scanner( FileAccess *FileObj ) { MyFileObj = FileObj; } float get_gl_float() { return gl_float; } int get_gl_int() { return gl_int; } char *get_gl_name() { return WordBuf; } gl_token get_next_token(void); BOOLEAN token_in_stack(void) { return stack.StackHasItems(); } gl_token get_token_from_stack(); void put_token_in_stack(const gl_token token); void put_token_in_stack(const gl_token token, int DX_val) { stack.push_token(token, DX_val); } void print_token(const gl_token token); }; #endif dxf2gl/gltoken.h 666 0 0 1374 6100336164 7017 #ifndef GLTOKEN_H #define GLTOKEN_H // // The gl_token enumeration defines the tokens that are returned by the // scanner and are used by the parser in attempting to recognize the // components of a DXF file. // typedef enum { bad_gl_token, section, header, endsec, seqend, blocks, block, endblk, vertex, tables, table, layer, contin, endtab, entities, three_d_face, end_of_file, polyline, integer, real, name, last_gl_token } gl_token; #endif dxf2gl/gltstack.cpp 666 0 0 1723 6100336710 7516 #include #include "gltstack.h" // // push_token : integer version // void token_stack::push_token( gl_token token, int intval ) { if (token_sp > 0) { token_sp--; token_stack_buf[ token_sp ].token = token; token_stack_buf[ token_sp ].val.intval = intval; } else printf("push_token: stack overflow\n"); } // // push_token : float version // void token_stack::push_token( gl_token token, float realval ) { if (token_sp > 0) { token_sp--; token_stack_buf[ token_sp ].token = token; token_stack_buf[ token_sp ].val.realval = realval; } else printf("push_token: stack overflow\n"); } // // pop_token // token_stack::token_stack_type token_stack::pop_token(void) { token_stack_type t; t.token = bad_gl_token; t.val.intval = 0; if (token_sp < MaxTokens) return token_stack_buf[ token_sp++ ]; else { printf("pop_token: stack underflow\n"); return t; } } dxf2gl/gltstack.h 666 0 0 3712 6100336646 7173 #ifndef GLTSTACK_H #define GLTSTACK_H /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ /* This file contains the stack object definition. The scanner requires two token look ahead to resolve things like the EOF token sequence. If this sequence is checked for, but not found, it is necessary to "back up" the input stream. This is done via the token stack. Note that a DXF file may contain both integer and float values. Two versions of "push_token" are implemented, one with an integer value and one with a float value. The integer version may be used with just a token value, in which case the default value will be used for the integer. */ #include "gltoken.h" #include "ianstd.h" class token_stack { public: typedef union { int intval; float realval; } token_union; typedef struct { gl_token token; token_union val; } token_stack_type; private: typedef enum {MaxTokens = 10} bogus1; token_stack_type token_stack_buf[ MaxTokens ]; int token_sp; public: token_stack(void) { token_sp = MaxTokens; } BOOLEAN StackHasItems(void) { return token_sp < MaxTokens; } void push_token( gl_token token, int intval = 0 ); void push_token( gl_token token, float realval ); token_stack_type pop_token(void); }; #endif dxf2gl/ianstd.h 666 0 0 760 6027213636 6622 #ifndef IANSTD_H #define IANSTD_H // These rather convoluted ifndef's are required because both FALSE, TRUE // and BOOLEAN are defined by various windows and windows/nt headers. When // these headers are included, a redefine error results without these ifndefs. // typedef enum { #ifndef FALSE FALSE = 0, #endif #ifndef TRUE TRUE = 1, #endif BOGUS} BoolVals; #ifndef _WINNT_ typedef int BOOLEAN; #endif #endif dxf2gl/pagepool.cpp 666 0 0 14207 6100035520 7524 /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ #include #include #include "pagepool.h" // // Get the system page size by calling the Windows NT function GetSystemInfo. // This function is system dependant and must be rewritten for a non-Win32 // platform, like UNIX (live free or die). // // This function is used to initialize the static class variable page_size. // unsigned int page_pool::GetSysPageSize( void ) { SYSTEM_INFO sys_info; // system info structure, defined in windows.h GetSystemInfo( &sys_info ); return sys_info.dwPageSize; } // page_pool::GetSysPageSize unsigned int page_pool::page_size = page_pool::GetSysPageSize(); // // page_pool object constructor. Set up the page list pointers and allocate // an initial page of memory. // page_pool::page_pool(void) { page_chain *new_link; new_link = new_block( page_size ); page_list_head = new_link; current_page = new_link; } // page_pool constructor // // page_pool destructor // // This function moves through the link list of memory pages and // deallocates them. // page_pool::~page_pool(void) { page_chain *tmp; while (page_list_head != NULL) { free( page_list_head->block ); tmp = page_list_head; page_list_head = page_list_head->next_page; free( tmp ); } } // // virtual function add_to_list // // User defined ordered list function. This function is optional. // If the memory allocater built on top of the page_pool object supports // allocation, deallocation and reallocation, a free list can be added // to reduce fragementation in the memory allocated by the page_pool // allocator. // void page_pool::add_to_list(void *addr, unsigned int size) { // Don't do anything... } // add_to_free_list // // new_block // // The new_block function is the "root" memory allocator for the // page_pool object. The amount of memory allocated is rounded up // to the next "page_size" boundary. // page_pool::page_chain *page_pool::new_block( unsigned int block_size ) { page_chain *new_link = NULL; int alloc_amt; // round to the nearest page size alloc_amt = ((block_size + (page_size-1)) / page_size) * page_size; if (alloc_amt <= max_block_size) { new_link = (page_chain *)malloc( sizeof( page_chain ) ); if (new_link != NULL) { new_link->block = (void *)malloc( alloc_amt ); new_link->bytes_used = 0; new_link->block_size = alloc_amt; new_link->next_page = NULL; } else { printf("page_pool::page_chain: malloc memory allocation error\n"); } } else { printf("page_pool::new_block: allocation request too large\n"); } return new_link; } // page_chain::new_block // // add_block // // This function is called when the amount of memory requested by page_alloc // will not fit in the current block. If the amount of free memory in // the current block is larger than a minimum allocation value // (min_block_size) this free memory is place in the free list // by calling add_to_list, which is a virtual function. // void *page_pool::add_block( unsigned int block_size ) { page_chain *new_page = NULL; page_chain *last_page; int bytes_free; last_page = current_page; new_page = new_block( block_size ); current_page->next_page = new_page; current_page = new_page; bytes_free = last_page->block_size - last_page->bytes_used; // if there is unused memory in the block and it is larger than the minimum // allocation block, put it in the free list, to avoid fragmentation. if (bytes_free >= min_block_size) { void *addr; addr = (void *)((unsigned int)last_page->block + last_page->bytes_used); last_page->bytes_used += bytes_free; add_to_list(addr, bytes_free); // Add to the ordered free list } return (void *)new_page; } // page_chain::add_block // // page_alloc // // This function is called to allocate memory from the page_pool object // memory pool. If there is enough free memory in the current block to // satisify the memory request, memory is allocated from the current // block and the amount of free memory is updated. If the current block // does not have enough memory, add_block is called to allocate a new memory // block which will be large enough. // void *page_pool::page_alloc( unsigned int num_bytes ) { void *addr = NULL; unsigned int amt_free = current_page->block_size - current_page->bytes_used; if (num_bytes > amt_free) { if (add_block( num_bytes ) != NULL) { amt_free = current_page->block_size; } } if (amt_free >= num_bytes) { addr = (void *)((unsigned int)current_page->block + current_page->bytes_used); current_page->bytes_used += num_bytes; } else { printf("page_pool::page_alloc: allocation error\n"); exit(1); } return addr; } // page_pool::page_alloc // // print_page_pool_info // // Print information about the page pool // void page_pool::print_page_pool_info(void) { int total_allocated = 0; int total_unused = 0; page_chain *ptr = page_list_head; printf("[block size, bytes_used]\n"); while (ptr != NULL) { printf("[%4d, %4d]", ptr->block_size, ptr->bytes_used); total_allocated += ptr->bytes_used; total_unused += (ptr->block_size - ptr->bytes_used); if (ptr->next_page != NULL) { printf(", "); } else { printf("\n"); } ptr = ptr->next_page; } // while printf("Total allocated = %5d, total unused = %3d\n", total_allocated, total_unused ); } dxf2gl/pagepool.h 666 0 0 5413 6105272404 7161 #ifndef PAGEPOOL_H #define PAGEPOOL_H /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ /* The page_pool object is designed to support rapid memory allocation and deallocation of all allocated memory, once the object is no longer needed. By using a block allocation scheme, the overhead of memory allocation is greatly reduced, compared to "malloc" (or new). Deallocation of large blocks of memory is also much faster than calling free for every allocated block of memory. The page_pool allocator allocates blocks of memory in "page_size" increments. The page_size variable is set at start-up and contains the system virtual memory page size. The page_pool object contains the virtual function "add_to_list" which can be implemented by the inherited function ordered_list. Ordered list is a class that supports ordered list insertion and deletion. In this case, this is used to support an ordered list of free memory blocks. The ordered list is only needed if the page_pool is used as the base for a memory allocater that can allocate from a free list. */ class page_pool { private: // typedefs and variables typedef struct page_chain_struct { void *block; unsigned int bytes_used; unsigned int block_size; page_chain_struct *next_page; } page_chain; // The min_block_size is the smallest block that will be returned by the // page_pool allocater. The max_block_size is the largest memory block // that can be requested. Ideally, this should be a multiple of the page // size. typedef enum { min_block_size = 96, max_block_size = 1024 * 8 } bogus; page_chain *page_list_head; page_chain *current_page; static unsigned int page_size; // system page size, shared by all instances private: // class functions static unsigned int GetSysPageSize(void); page_chain *new_block( unsigned int block_size ); void *add_block( unsigned int block_size ); public: // class functions page_pool(void); ~page_pool(void); void *page_alloc( unsigned int block_size ); void print_page_pool_info(void); virtual void add_to_list(void *addr, unsigned int size); }; // class page_pool #endif dxf2gl/glface.cpp 666 0 0 17523 6105273426 7161 /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ #include #include "glface.h" /* A 3D graphic object can be described by a list of polygon faces. Each face is itself a list of 3D points (e.g., x, y, z coordinates). This class supports the construction of polygon faces for a 3D object that is read from a DXF file. Two DXF polygon types are supported: - 3DFACE - POLYLINE A 3DFACE polygon is composed of either three points (e.g., its a triangle) or four points (its a rectangle). A POLYLINE object is composed of one or more polygons (what AutoDesk calls a polygon mesh). These may have a variable number of points, although the number of points per polygon may be specified in the POLYLINE definition. */ // add_point // // Add a point to a polygon. If the point being added is the same // as the last point (which can occur in 3DFACE polygons), skip it. // void FaceList::add_point(face *cur_face, float x, float y, float z) { int PointCnt = cur_face->point_cnt; float *points = cur_face->f[PointCnt].v; float *LastPts = cur_face->f[ PointCnt-1 ].v; // If the point being added is not the same as the last point, // then add it to the point list. if (cur_face->point_cnt == 0 || (LastPts[Xcoord] != x || LastPts[Ycoord] != y || LastPts[Zcoord] != z)) { points[Xcoord] = x; points[Ycoord] = y; points[Zcoord] = z; cur_face->point_cnt++; } } // add_point // // add_3DFACE_point // // This function adds a 3D point to a 3DFACE polygon. The number of // points in a 3DFACE object is defined when the polygon face is allocated // and is fixed at no more than four. // void FaceList::add_3DFACE_point(float x, float y, float z ) { if (ListTail != NULL) { face *cur_face = &ListTail->cur_face; int PointCnt = cur_face->point_cnt; if (PointCnt >= cur_face->point_max) { printf("FaceList::add_3DFACE_point: Attempted to add too many points\n"); } else { add_point(cur_face, x, y, z); } } else printf("FaceList::add_3DFACE_point: Can't add point to unalloced list\n"); } // add_3DFACE_point /* add_poly_point A DXF POLYLINE object is composed of a "polygon mesh", which contains one or more polygons. These polygons may have a variable number of points. According to the spec, the "71" marker following the POLYLINE marker gives the number of polygons and the "72" marker gives the number of points. But the spec also says that these numbers are not required to be correct (got to love it). Apparently the DXF reader is supposed to figure it out. How this is done, is not stated (at least so that I could understand). So the code below depends on the "72" marker being correct for the "point maximum" of an object. This value set when the polygon face is allocated. A POLYLINE object consists of a sequence of VERTEXs. When "point_max" VERTEXs are read, a new POLYLINE face is allocated (get_new_poly_face). */ void FaceList::add_poly_point(float x, float y, float z ) { if (ListTail != NULL) { face *cur_face = &ListTail->cur_face; int PointCnt = cur_face->point_cnt; // Hit the end of the current polygon, start a new one if (cur_face->point_cnt >= cur_face->point_max) { get_new_poly_face( cur_face->point_max ); cur_face = &ListTail->cur_face; } add_point(cur_face, x, y, z); } else printf("FaceList::add_poly_point: Can't add point to unalloced list\n"); } // add_poly_point // // get_new_3DFACE // // Allocate storage for a new 3DFACE (e.g., a polygon face consisting // of three or four points). // void FaceList::get_new_3DFACE(void) { FaceElem *tmp; vect *VectPtr; tmp = (FaceElem *)mem.page_alloc( sizeof( FaceElem ) ); VectPtr = (vect *)mem.page_alloc( sizeof( vect ) * MinSize ); tmp->next_face = NULL; tmp->cur_face.point_cnt = 0; tmp->cur_face.f = VectPtr; tmp->cur_face.point_max = MinSize; if (ListHead == NULL) { ListHead = tmp; ListTail = tmp; } else { ListTail->next_face = tmp; ListTail = tmp; } } // // get_new_poly_face // // Allocate memory for a polygon face from a POLYLINE object. The // number of points is given by the polypoint argument. // void FaceList::get_new_poly_face(int polypoint) { FaceElem *tmp; vect *VectPtr; tmp = (FaceElem *)mem.page_alloc( sizeof( FaceElem ) ); VectPtr = (vect *)mem.page_alloc( sizeof( vect ) * polypoint ); tmp->next_face = NULL; tmp->cur_face.point_cnt = 0; tmp->cur_face.f = VectPtr; tmp->cur_face.point_max = polypoint; if (ListHead == NULL) { ListHead = tmp; ListTail = tmp; } else { ListTail->next_face = tmp; ListTail = tmp; } } #ifdef DYNAMIC_ALLOC /* GrowFace GrowFace was originally written so that the number of points in a POLYLINE object could be dynamically increased. This is necessary because the number of VERTEXs (e.g., 3D points) that follow the POLYLINE header varies. However, the number of points per POLYLINE polygon are supposed to be specified in the header. So, assuming that this number is correct, storage for the polygon can be allocated once. This avoids the complicated memory allocation, deallocation and reallocation of freed memory that is supported by this function. As a result, this function is currently unused. It is included in this object in case it is necessary to support dynamically growable polygon faces. This function calls mem.mem_alloc, from the memory allocation object. If this function is used, the point vector should have been allocated with mem_alloc, instead of page_alloc. This will allow the old memory to be deallocated and recovered for later allocation. */ void FaceList::GrowFace( face *cur_face ) { const int MaxSize = 1024 * 4; int new_size; if (cur_face->point_cnt < cur_face->point_max) printf("FaceList::GrowFace called too soon\n"); else { new_size = cur_face->point_max * 2; if (new_size > MaxSize) { printf("FaceList::GrowFace: too many points allocated\n"); exit(1); } else { vect *VectPtr, *tmp; int i; VectPtr = (vect *)mem.mem_alloc( sizeof(vect) * new_size ); for (i = 0; i < cur_face->point_cnt; i++) { VectPtr[i] = cur_face->f[i]; } tmp = cur_face->f; // Free the old memory mem.mem_free( tmp ); cur_face->f = VectPtr; cur_face->point_max = new_size; } } } // GrowFace #endif // // print // // Print out the face list for a 3D object. This function is supplied for // debugging. // void FaceList::print(void) { FaceElem *cur_elem = ListHead; while (cur_elem != NULL) { int i, j; face *cur_face = &(cur_elem->cur_face); printf("{ "); for (j = 0; j < cur_face->point_cnt; j++) { if (j > 0) printf(" "); printf("["); for (i = Xcoord; i <= Zcoord; i++) { printf("%f", cur_face->f[j].v[i] ); if (i < Zcoord) printf(", "); } printf("]"); if (j < cur_face->point_cnt-1) printf("\n"); } // j printf("}\n"); cur_elem = cur_elem->next_face; } } dxf2gl/glface.h 666 0 0 7014 6105273472 6601 #ifndef GLFACE_H #define GLFACE_H /*==================================================================== This software was written by Ian L. Kaplan, Chief Fat Bear, Bear Products International. Use of this software, for any purpose, is granted on two conditions: 1. This copyright notice must be included with the software or any software derived from it. 2. The risk of using this software is accepted by the user. No warranty as to its usefulness or functionality is provided or implied. The author and Bear Products International provides no support. ====================================================================*/ #include #include "pagepool.h" /* A 3D graphic object can be described as a list of polygons. Each of these polygons consists of three or more points in 3D space (e.g., x, y, z coordinates). The FaceList object will construct a list of polygon faces read from a DXF file. Two DXF file polygon formats are supported: - 3DFACE - POLYLINE The "face" structure member "f" is a pointer to an array of points. This point array is dynamically allocated. The minimum number of points that can be allocated for a polygon is four (a 3DFACE polygon may only consist of three points, in which case the last point is unused). Although during creating there is a distinction made between DXF 3DFACE objects and POLYLINE objects, the class represents both as polygon faces and no such distinction exists when the polygon list is read. The object supplies the following public functions for creating a polygon list: add_3DFACE_point - Add a 3D point to a 3DFACE polygon add_poly_point - Add a 3D point to a POLYLINE polygon get_new_3DFACE - Create a new 3DFACE polygon get_new_poly_face - Create a new POLYLINE polygon Once the polygon list is created, it can be read using the following functions: GetListStart - Return a handle for the start of the polygon face list GetFace - Get a polygon face, given a list handle GetNextFace - Get the next polygon face in the list */ class FaceList { public: typedef enum {MinSize = 4} bogus; // minimum number of points typedef enum {Xcoord, Ycoord, Zcoord} bogus2; typedef struct { float v[3]; } vect; // a point in the 3D plane typedef struct { vect *f; // an array of 3D points int point_cnt; // number of points currently alloc'ed int point_max; // max points } face; typedef void *ListHandle; private: typedef struct FaceListStruct { face cur_face; struct FaceListStruct *next_face; } FaceElem; page_pool mem; FaceElem *ListHead; FaceElem *ListTail; private: void add_point(face *cur_face, float x, float y, float z); // void GrowFace( face *cur_face ); public: FaceList(void) { ListHead = NULL; ListTail = NULL; } void add_3DFACE_point(float x, float y, float z ); void add_poly_point(float x, float y, float z); void get_new_3DFACE(void); void get_new_poly_face(int polypont); ListHandle GetListStart(void) { return (ListHandle)ListHead; } face *GetFace( ListHandle handle) { return &((FaceElem *)handle)->cur_face; } ListHandle GetNextFace( ListHandle handle ) { return (ListHandle)((FaceElem *)handle)->next_face; } void print(void); }; #endif dxf2gl/dxf2gl.mak 666 0 0 23465 6105275120 7107 # Microsoft Developer Studio Generated NMAKE File, Format Version 4.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 !IF "$(CFG)" == "" CFG=dxf2gl - Win32 Debug !MESSAGE No configuration specified. Defaulting to dxf2gl - Win32 Debug. !ENDIF !IF "$(CFG)" != "dxf2gl - Win32 Release" && "$(CFG)" != "dxf2gl - Win32 Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE on this makefile !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "dxf2gl.mak" CFG="dxf2gl - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "dxf2gl - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "dxf2gl - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF ################################################################################ # Begin Project # PROP Target_Last_Scanned "dxf2gl - Win32 Debug" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "dxf2gl - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" OUTDIR=.\Release INTDIR=.\Release ALL : "$(OUTDIR)\dxf2gl.exe" CLEAN : -@erase ".\Release\dxf2gl.exe" -@erase ".\Release\faccess.obj" -@erase ".\Release\gltstack.obj" -@erase ".\Release\glscan.obj" -@erase ".\Release\dispgl.obj" -@erase ".\Release\pagepool.obj" -@erase ".\Release\glface.obj" -@erase ".\Release\globj.obj" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ /Fp"$(INTDIR)/dxf2gl.pch" /YX /Fo"$(INTDIR)/" /c CPP_OBJS=.\Release/ CPP_SBRS= # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo BSC32_FLAGS=/nologo /o"$(OUTDIR)/dxf2gl.bsc" BSC32_SBRS= LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 glaux.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 LINK32_FLAGS=glaux.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib\ winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib\ uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no\ /pdb:"$(OUTDIR)/dxf2gl.pdb" /machine:I386 /out:"$(OUTDIR)/dxf2gl.exe" LINK32_OBJS= \ "$(INTDIR)/faccess.obj" \ "$(INTDIR)/gltstack.obj" \ "$(INTDIR)/glscan.obj" \ "$(INTDIR)/dispgl.obj" \ "$(INTDIR)/pagepool.obj" \ "$(INTDIR)/glface.obj" \ "$(INTDIR)/globj.obj" "$(OUTDIR)\dxf2gl.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << !ELSEIF "$(CFG)" == "dxf2gl - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" OUTDIR=.\Debug INTDIR=.\Debug ALL : "$(OUTDIR)\dxf2gl.exe" CLEAN : -@erase ".\Debug\vc40.pdb" -@erase ".\Debug\vc40.idb" -@erase ".\Debug\dxf2gl.exe" -@erase ".\Debug\dispgl.obj" -@erase ".\Debug\pagepool.obj" -@erase ".\Debug\glface.obj" -@erase ".\Debug\glscan.obj" -@erase ".\Debug\faccess.obj" -@erase ".\Debug\gltstack.obj" -@erase ".\Debug\globj.obj" -@erase ".\Debug\dxf2gl.ilk" -@erase ".\Debug\dxf2gl.pdb" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c # ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ /Fp"$(INTDIR)/dxf2gl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c CPP_OBJS=.\Debug/ CPP_SBRS= # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo BSC32_FLAGS=/nologo /o"$(OUTDIR)/dxf2gl.bsc" BSC32_SBRS= LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 # ADD LINK32 glaux.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 LINK32_FLAGS=glaux.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib\ winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib\ uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes\ /pdb:"$(OUTDIR)/dxf2gl.pdb" /debug /machine:I386 /out:"$(OUTDIR)/dxf2gl.exe" LINK32_OBJS= \ "$(INTDIR)/dispgl.obj" \ "$(INTDIR)/pagepool.obj" \ "$(INTDIR)/glface.obj" \ "$(INTDIR)/glscan.obj" \ "$(INTDIR)/faccess.obj" \ "$(INTDIR)/gltstack.obj" \ "$(INTDIR)/globj.obj" "$(OUTDIR)\dxf2gl.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << !ENDIF .c{$(CPP_OBJS)}.obj: $(CPP) $(CPP_PROJ) $< .cpp{$(CPP_OBJS)}.obj: $(CPP) $(CPP_PROJ) $< .cxx{$(CPP_OBJS)}.obj: $(CPP) $(CPP_PROJ) $< .c{$(CPP_SBRS)}.sbr: $(CPP) $(CPP_PROJ) $< .cpp{$(CPP_SBRS)}.sbr: $(CPP) $(CPP_PROJ) $< .cxx{$(CPP_SBRS)}.sbr: $(CPP) $(CPP_PROJ) $< ################################################################################ # Begin Target # Name "dxf2gl - Win32 Release" # Name "dxf2gl - Win32 Debug" !IF "$(CFG)" == "dxf2gl - Win32 Release" !ELSEIF "$(CFG)" == "dxf2gl - Win32 Debug" !ENDIF ################################################################################ # Begin Source File SOURCE=.\pagepool.cpp !IF "$(CFG)" == "dxf2gl - Win32 Release" DEP_CPP_PAGEP=\ ".\pagepool.h"\ NODEP_CPP_PAGEP=\ ".\ordlist.h"\ "$(INTDIR)\pagepool.obj" : $(SOURCE) $(DEP_CPP_PAGEP) "$(INTDIR)" !ELSEIF "$(CFG)" == "dxf2gl - Win32 Debug" DEP_CPP_PAGEP=\ ".\pagepool.h"\ "$(INTDIR)\pagepool.obj" : $(SOURCE) $(DEP_CPP_PAGEP) "$(INTDIR)" !ENDIF # End Source File ################################################################################ # Begin Source File SOURCE=.\gltstack.cpp DEP_CPP_GLTST=\ ".\gltstack.h"\ ".\gltoken.h"\ ".\ianstd.h"\ "$(INTDIR)\gltstack.obj" : $(SOURCE) $(DEP_CPP_GLTST) "$(INTDIR)" # End Source File ################################################################################ # Begin Source File SOURCE=.\glscan.cpp DEP_CPP_GLSCA=\ ".\ianstd.h"\ ".\gltstack.h"\ ".\glscan.h"\ ".\gltoken.h"\ ".\faccess.h"\ "$(INTDIR)\glscan.obj" : $(SOURCE) $(DEP_CPP_GLSCA) "$(INTDIR)" # End Source File ################################################################################ # Begin Source File SOURCE=.\globj.cpp !IF "$(CFG)" == "dxf2gl - Win32 Release" DEP_CPP_GLOBJ=\ ".\globj.h"\ ".\glscan.h"\ ".\gltoken.h"\ ".\dxfvals.h"\ ".\faccess.h"\ ".\glface.h"\ ".\ianstd.h"\ ".\pagepool.h"\ ".\gltstack.h"\ "$(INTDIR)\globj.obj" : $(SOURCE) $(DEP_CPP_GLOBJ) "$(INTDIR)" !ELSEIF "$(CFG)" == "dxf2gl - Win32 Debug" DEP_CPP_GLOBJ=\ ".\globj.h"\ ".\glscan.h"\ ".\gltoken.h"\ ".\dxfvals.h"\ ".\faccess.h"\ ".\glface.h"\ ".\gltstack.h"\ ".\ianstd.h"\ ".\pagepool.h"\ "$(INTDIR)\globj.obj" : $(SOURCE) $(DEP_CPP_GLOBJ) "$(INTDIR)" !ENDIF # End Source File ################################################################################ # Begin Source File SOURCE=.\glface.cpp DEP_CPP_GLFAC=\ ".\glface.h"\ ".\pagepool.h"\ "$(INTDIR)\glface.obj" : $(SOURCE) $(DEP_CPP_GLFAC) "$(INTDIR)" # End Source File ################################################################################ # Begin Source File SOURCE=.\faccess.cpp DEP_CPP_FACCE=\ ".\ianstd.h"\ ".\faccess.h"\ "$(INTDIR)\faccess.obj" : $(SOURCE) $(DEP_CPP_FACCE) "$(INTDIR)" # End Source File ################################################################################ # Begin Source File SOURCE=.\dispgl.cpp !IF "$(CFG)" == "dxf2gl - Win32 Release" DEP_CPP_DISPG=\ ".\glos.h"\ {$(INCLUDE)}"\gl\GL.H"\ {$(INCLUDE)}"\gl\GLU.H"\ {$(INCLUDE)}"\gl\GLAUX.H"\ ".\faccess.h"\ ".\globj.h"\ ".\glface.h"\ ".\ianstd.h"\ ".\glscan.h"\ ".\gltoken.h"\ ".\gltstack.h"\ ".\pagepool.h"\ "$(INTDIR)\dispgl.obj" : $(SOURCE) $(DEP_CPP_DISPG) "$(INTDIR)" !ELSEIF "$(CFG)" == "dxf2gl - Win32 Debug" DEP_CPP_DISPG=\ ".\glos.h"\ {$(INCLUDE)}"\gl\GL.H"\ {$(INCLUDE)}"\gl\GLU.H"\ {$(INCLUDE)}"\gl\GLAUX.H"\ ".\faccess.h"\ ".\globj.h"\ ".\glface.h"\ ".\ianstd.h"\ ".\glscan.h"\ ".\pagepool.h"\ ".\gltoken.h"\ ".\gltstack.h"\ "$(INTDIR)\dispgl.obj" : $(SOURCE) $(DEP_CPP_DISPG) "$(INTDIR)" !ENDIF # End Source File # End Target # End Project ################################################################################