Michael Jones (mtj++at++babar)
Mon, 4 Apr 1994 14:06:40 -0700
Here's the simple loader from 1.2 -- you'll want the new pfuBuilder()
from 1.2 to compile this.
Hint: upgrade to SC4-PERF-1.2 (the 1..2 release) right away! If you
have support, ask when you'll get your upgrade.
/*
* Copyright (c) 1993 Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that (i) the above copyright notices and this
* permission notice appear in all copies of the software and related
* documentation, and (ii) the name of Silicon Graphics may not be
* used in any advertising or publicity relating to the software
* without the specific, prior written permission of Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
* INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY
* THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE
* OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/*
* pfdxf.c: $Revision: 1.24 $ $Date: 1994/03/16 11:56:18 $
*/
#include <Performer/pf.h>
#include "pfsgi.h"
#include "pfutil.h"
/*
* This AutoCAD reader was created almost verbatim from the
* AutoCAD DXF file to DKB data file converter written and
* placed in the public domain 8/13/90 by Aaron A. Collins.
*
* It parses a limited, but useful, subset of the AutoCAD
* DXF file format. No effort has been made to handle the
* complete range of possible DXF opcodes and commands.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 2048
static int groupcode;
static char linbuf[BUFFER_SIZE];
static char curobj[80];
static int curcolor;
static float curr;
static float curg;
static float curb;
static float xcoords[BUFFER_SIZE];
static float ycoords[BUFFER_SIZE];
static float zcoords[BUFFER_SIZE];
static float floats[10];
static float angles[10];
static int ints[10];
static long numTris;
static long numVoid;
/* function type and argument declarations */
static FILE *openFile(char *fileName);
static pfGeoState* defaultGeoState(void);
static int getLine(FILE *fp);
static void addGeometry(pfuBuilder *);
static void getColor(int ndx, float *red, float *green, float *blue);
static int isDegenerate(int a, int b, int c);
static int findEntity(FILE *fp);
static int readEntity(FILE *fp, pfuBuilder *builder);
/*
* LoadDxf -- load DXF format ".dxf" files into IRIS Performer
*/
extern pfNode *
LoadDxf (char *fileName, pfGeoState *geostate)
{
int i;
FILE *dxfFile;
pfuBuilder *builder = NULL;
pfList *gsetList = NULL;
pfGeode *geode = NULL;
pfNode *node = NULL;
pfNode *hierarchy = NULL;
double startTime = pfGetTime();
double elapsedTime = 0.0;
/* open DXF file file */
if ((dxfFile = openFile(fileName)) == NULL)
return NULL;
/* give object a default geostate if nothing is passed in */
if (geostate == NULL)
geostate = defaultGeoState();
/* initialize utility library triangle/geoset builder */
builder = pfuNewBuilder();
/* initialize current object */
numTris = 0;
numVoid = 0;
curobj[0] = '\0';
curcolor = 7;
getColor(curcolor, &curr, &curg, &curb);
/* read DXF file */
while (findEntity(dxfFile))
readEntity(dxfFile, builder);
/* close DXF file */
fclose(dxfFile);
/* signal failure if no geometry loaded */
if (numTris == 0)
{
pfuDelBuilder(builder);
return NULL;
}
/* construct geode */
geode = pfNewGeode();
node = (pfNode *)geode;
/* convert current face list into one or more geosets */
gsetList = pfuMakeGSets(builder);
for (i = 0; i < pfGetNum(gsetList); i++)
{
pfGeoSet *geoset = (pfGeoSet*)pfGet(gsetList, i);
pfGSetGState(geoset, geostate);
pfAddGSet(geode, geoset);
}
pfuDelBuilder(builder);
/* print statistics */
if(pfGetNotifyLevel() >= PFNFY_INFO)
{
elapsedTime = pfGetTime() - startTime;
fprintf(stderr, "LoadDxf:\n");
fprintf(stderr, " file name = %s\n", fileName);
fprintf(stderr, " triangles = %8ld\n", numTris);
fprintf(stderr, " numVoid = %8ld\n", numVoid);
if (elapsedTime > 0.0)
{
fprintf(stderr, " loading time = %12.3f sec\n",
elapsedTime);
fprintf(stderr, " loading rate = %12.3f tri/sec\n",
numTris/elapsedTime);
}
}
/* #define BREAKUP_GEODE */
#ifdef BREAKUP_GEODE
/* convert geode to recursive spatial hierarchy */
startTime = pfGetTime();
hierarchy = pfuBreakup(geode, 10.0f, 24, 8);
elapsedTime = pfGetTime() - startTime;
/* replace monolithic geode with recursive spatial hierarchy */
if (hierarchy != NULL)
{
node = hierarchy;
pfDelete(geode);
}
/* print statistics */
if (pfGetNotifyLevel() >= PFNFY_INFO && elapsedTime > 0.0)
{
fprintf(stderr, " breakup time = %12.3f sec\n",
elapsedTime);
fprintf(stderr, " breakup rate = %12.3f tri/sec\n",
numTris/elapsedTime);
}
#endif
/* print statistics */
if (pfGetNotifyLevel() >= PFNFY_INFO)
fprintf(stderr, "\n");
return node;
}
static FILE *
openFile (char *fileName)
{
FILE *file = NULL;
char filePath[BUFFER_SIZE];
/* check argument */
if (fileName == NULL || *fileName == '\0')
return NULL;
/* find file in IRIS Performer directory-search path */
if (!pfFindFile(fileName, filePath, R_OK))
{
pfNotify(PFNFY_WARN, PFNFY_RESOURCE,
"openFile: Could not find file \"%s\"", fileName);
return NULL;
}
/* open file */
if ((file = fopen(filePath, "r")) == NULL)
{
pfNotify(PFNFY_WARN, PFNFY_RESOURCE,
"openFile: Could not open file \"%s\"", filePath);
return NULL;
}
return file;
}
/*
* read a group code and the next line from dxfFile
*/
static int
getLine(FILE *fp)
{
/* get a line from DXF file */
fgets(linbuf, BUFFER_SIZE, fp);
if (feof(fp))
return 1;
/* scan out group code */
sscanf(linbuf, "%3d", &groupcode);
/* get a line from DXF file */
fgets(linbuf, BUFFER_SIZE, fp);
if (feof(fp))
return 1;
return 0;
}
/*
* dump out current object we should have all info on
*/
static void
addGeometry(pfuBuilder *builder)
{
static pfuPoly polygon;
static int state=0;
static int nb_points;
static int nb_cotes;
static int indice_point;
/* 2 back-to-back triangles */
if (strstr(curobj, "TRACE"))
{
if (isDegenerate(0, 1, 2))
{
numVoid++;
return;
}
polygon.numVerts = 3;
polygon.tbind = PFGS_OFF;
polygon.nbind = PFGS_OFF;
polygon.cbind = PFGS_OVERALL;
pfSetVec3(polygon.coords[0], xcoords[0], ycoords[0], zcoords[0]);
pfSetVec3(polygon.coords[1], xcoords[1], ycoords[1], zcoords[1]);
pfSetVec3(polygon.coords[2], xcoords[2], ycoords[2], zcoords[2]);
pfSetVec3(polygon.colors[0], curr, curg, curb);
pfuAddPoly(builder, &polygon);
numTris += polygon.numVerts - 2;
if (isDegenerate(0, 3, 2))
{
numVoid++;
return;
}
polygon.numVerts = 3;
polygon.tbind = PFGS_OFF;
polygon.nbind = PFGS_OFF;
polygon.cbind = PFGS_OVERALL;
pfSetVec3(polygon.coords[0], xcoords[0], ycoords[0], zcoords[0]);
pfSetVec3(polygon.coords[1], xcoords[2], ycoords[2], zcoords[2]);
pfSetVec3(polygon.coords[2], xcoords[3], ycoords[3], zcoords[3]);
pfSetVec3(polygon.colors[0], curr, curg, curb);
pfuAddPoly(builder, &polygon);
numTris += polygon.numVerts - 2;
return;
}
/* 1 or 2 triangles */
else if (strstr(curobj, "SOLID"))
{
if (isDegenerate(0, 1, 2))
{
numVoid++;
return;
}
polygon.numVerts = 3;
polygon.tbind = PFGS_OFF;
polygon.nbind = PFGS_OFF;
polygon.cbind = PFGS_OVERALL;
pfSetVec3(polygon.coords[0], xcoords[0], ycoords[0], zcoords[0]);
pfSetVec3(polygon.coords[1], xcoords[1], ycoords[1], zcoords[1]);
pfSetVec3(polygon.coords[2], xcoords[2], ycoords[2], zcoords[2]);
pfSetVec3(polygon.colors[0], curr, curg, curb);
pfuAddPoly(builder, &polygon);
numTris += polygon.numVerts - 2;
/* is one triangle enough... */
if (xcoords[2] == xcoords[3] &&
ycoords[2] == ycoords[3] &&
zcoords[2] == zcoords[3])
return;
if (isDegenerate(0, 3, 2))
{
numVoid++;
return;
}
polygon.numVerts = 3;
polygon.tbind = PFGS_OFF;
polygon.nbind = PFGS_OFF;
polygon.cbind = PFGS_OVERALL;
pfSetVec3(polygon.coords[0], xcoords[0], ycoords[0], zcoords[0]);
pfSetVec3(polygon.coords[1], xcoords[2], ycoords[2], zcoords[2]);
pfSetVec3(polygon.coords[2], xcoords[3], ycoords[3], zcoords[3]);
pfSetVec3(polygon.colors[0], curr, curg, curb);
pfuAddPoly(builder, &polygon);
numTris += polygon.numVerts - 2;
return;
}
/* 1 or 2 triangles */
else if (strstr(curobj, "3DFACE"))
{
if (isDegenerate(0, 1, 2))
{
numVoid++;
return;
}
polygon.numVerts = 3;
polygon.tbind = PFGS_OFF;
polygon.nbind = PFGS_OFF;
polygon.cbind = PFGS_OVERALL;
pfSetVec3(polygon.coords[0], xcoords[0], ycoords[0], zcoords[0]);
pfSetVec3(polygon.coords[1], xcoords[1], ycoords[1], zcoords[1]);
pfSetVec3(polygon.coords[2], xcoords[2], ycoords[2], zcoords[2]);
pfSetVec3(polygon.colors[0], curr, curg, curb);
pfuAddPoly(builder, &polygon);
numTris += polygon.numVerts - 2;
/* is one triangle enough... */
if (xcoords[2] == xcoords[3] &&
ycoords[2] == ycoords[3] &&
zcoords[2] == zcoords[3])
return;
if (isDegenerate(0, 3, 2))
{
numVoid++;
return;
}
polygon.numVerts = 3;
polygon.tbind = PFGS_OFF;
polygon.nbind = PFGS_OFF;
polygon.cbind = PFGS_OVERALL;
pfSetVec3(polygon.coords[0], xcoords[0], ycoords[0], zcoords[0]);
pfSetVec3(polygon.coords[1], xcoords[2], ycoords[2], zcoords[2]);
pfSetVec3(polygon.coords[2], xcoords[3], ycoords[3], zcoords[3]);
pfSetVec3(polygon.colors[0], curr, curg, curb);
pfuAddPoly(builder, &polygon);
numTris += polygon.numVerts - 2;
return;
}
else if (strstr(curobj, "SEQEND"))
{
if (state == 1 && polygon.numVerts > 2)
{
pfSetVec3(polygon.colors[0], curr, curg, curb);
pfuAddPoly(builder, &polygon);
numTris += polygon.numVerts - 2;
}
state = 0; /* end of something */
}
else if (strstr(curobj, "POLYLINE"))
{
state = 1; /* begin of a polyline */
indice_point = 1;
nb_points = ints[1];
nb_cotes = ints[2];
if (nb_points >= (BUFFER_SIZE-1))
{
state = 0;
return;
}
polygon.numVerts = 0;
polygon.tbind = PFGS_OFF;
polygon.nbind = PFGS_OFF;
polygon.cbind = PFGS_OVERALL;
}
/* a new vertex in a polyline */
else if (strstr(curobj, "VERTEX") && state == 1)
{
/* is it a new vertex ? */
if (indice_point <= nb_points)
{
/* copying point */
xcoords[indice_point] = xcoords[0];
ycoords[indice_point] = ycoords[0];
zcoords[indice_point] = zcoords[0];
indice_point++;
}
else
/* creating edges */
if (nb_cotes > 0)
{
/* closing an older polygon */
if ((ints[1] > 0) && (polygon.numVerts > 2))
{
pfSetVec3(polygon.colors[0], curr, curg, curb);
pfuAddPoly(builder, &polygon);
numTris += polygon.numVerts - 2;
}
/* creating a new polygon */
if (ints[1] > 0)
{
polygon.numVerts = 0;
pfSetVec3(polygon.coords[polygon.numVerts++],
xcoords[ints[1]], ycoords[ints[1]], zcoords[ints[1]]);
}
if (ints[2] > 0)
{
pfSetVec3(polygon.coords[polygon.numVerts++],
xcoords[ints[2]], ycoords[ints[2]], zcoords[ints[2]]);
}
if (ints[3] > 0)
{
pfSetVec3(polygon.coords[polygon.numVerts++],
xcoords[ints[3]], ycoords[ints[3]], zcoords[ints[3]]);
}
}
}
/* not implemented */
else if (
strstr(curobj, "LINE") || strstr(curobj, "POINT") ||
strstr(curobj, "CIRCLE") || strstr(curobj, "ARC") ||
strstr(curobj, "TEXT") || strstr(curobj, "SHAPE") ||
strstr(curobj, "BLOCK") || strstr(curobj, "ENDBLK") ||
strstr(curobj, "INSERT") || strstr(curobj, "ATTDEF") ||
strstr(curobj, "ATTRIB") || strstr(curobj, "3DLINE") ||
strstr(curobj, "DIMENSION"))
{
return;
}
/* no current object defined */
else
return;
}
/*
* colors defined by basic AutoCAD color table
*/
static void
getColor (int ndx, float *red, float *green, float *blue)
{
/* AutoCAD color table */
static float colors[][3] =
{
{0.0f, 0.0f, 0.0f}, /* 0 == black */
{1.0f, 0.0f, 0.0f}, /* 1 == red */
{1.0f, 1.0f, 0.0f}, /* 2 == yellow */
{0.0f, 1.0f, 0.0f}, /* 3 == green */
{0.0f, 1.0f, 1.0f}, /* 4 == cyan */
{0.0f, 0.0f, 1.0f}, /* 5 == blue */
{1.0f, 0.0f, 1.0f}, /* 6 == magenta */
{1.0f, 1.0f, 1.0f}, /* 7 == white */
{0.5f, 0.5f, 0.5f}, /* 8 == dk grey */
{0.75f, 0.75f, 0.75f} /* 9 == lt grey */
};
/* use white (color 7) as default color */
if (ndx < 0 || ndx > 9)
ndx = 7;
/* set colors in reference arguments */
*red = colors[ndx][0];
*green = colors[ndx][1];
*blue = colors[ndx][2];
return;
}
/*
* check for degenerate triangle structure
*/
static int
isDegenerate(int a, int b, int c)
{
if ((xcoords[a] == xcoords[b] &&
ycoords[a] == ycoords[b] &&
zcoords[a] == zcoords[b]) ||
(xcoords[b] == xcoords[c] &&
ycoords[b] == ycoords[c] &&
zcoords[b] == zcoords[c]) ||
(xcoords[a] == xcoords[c] &&
ycoords[a] == ycoords[c] &&
zcoords[a] == zcoords[c]))
return 1;
else
return 0;
}
/*
* move forward to ENTITIES section
*/
static int
findEntity(FILE *fp)
{
while (1)
{
/* is there more to read */
if (feof(fp))
return 0;
/* get a group code and a line */
if (getLine(fp))
return 0;
/* file section mark */
if (groupcode == 0)
{
if (strstr(linbuf, "EOF"))
return 0;
if (strstr(linbuf, "SECTION"))
{
if (getLine(fp))
return 0;
if (groupcode != 2)
continue;
if (strstr(linbuf, "ENTITIES"))
break;
}
}
}
return 1;
}
/*
* read objects from ENTITIES section
*/
static int
readEntity(FILE *fp, pfuBuilder *builder)
{
while (1)
{
/* is there more to read */
if (feof(fp))
break;
/* get a group code and a line */
if (getLine(fp))
break;
/* cardinal group codes */
if (groupcode < 10)
{
switch(groupcode)
{
/* start of entity, table, file sep */
case 0:
/* add object's polygons to builder */
addGeometry(builder);
if (strstr(linbuf, "EOF"))
return 0;
if (strstr(linbuf, "ENDSEC"))
continue;
/* reset object */
curobj[0] = '\0';
curcolor = 7;
getColor(curcolor, &curr, &curg, &curb);
/* get new */
strcpy(curobj, linbuf);
break;
/* primary text value for entity (?) */
case 1:
break;
/* block name, attribute tag, etc */
case 2:
case 3:
case 4:
break;
/* entity handle (hex string) */
case 5:
break;
/* line type name */
case 6:
break;
/* text style name */
case 7:
break;
/* layer name */
case 8:
break;
/* variable name ID (only in header) */
case 9:
break;
}
}
/* some X coord */
else if (groupcode >= 10 && groupcode < 19)
sscanf(linbuf, "%f", &(xcoords[groupcode-10]));
/* some Y coord */
else if (groupcode >= 20 && groupcode < 29)
sscanf(linbuf, "%f", &(ycoords[groupcode-20]));
/* some Z coord */
else if (groupcode >= 30 && groupcode < 38)
sscanf(linbuf, "%f", &(zcoords[groupcode-30]));
/* entity elevation if nonzero */
else if (groupcode == 38)
{
}
/* entity thickness if nonzero */
else if (groupcode == 39)
{
}
/* misc floats */
else if (groupcode >= 40 && groupcode < 49)
sscanf(linbuf, "%f", &(floats[groupcode-40]));
/* repeated value groups */
else if (groupcode == 49)
{
}
/* misc angles */
else if (groupcode >= 50 && groupcode < 59)
sscanf(linbuf, "%f", &(angles[groupcode-50]));
/* color number */
else if (groupcode == 62)
{
sscanf(linbuf, "%6d", &curcolor);
getColor(curcolor, &curr, &curg, &curb);
}
/* "entities follow" flag */
else if (groupcode == 66)
{
}
/* misc ints */
else if (groupcode >= 70 && groupcode < 79)
sscanf(linbuf, "%d", &(ints[groupcode-70]));
/* X, Y, Z components of extrusion direction */
else if (groupcode == 210 || groupcode == 220 || groupcode == 230)
{
}
}
return 0;
}
/*
* make a reasonable default geostate
*/
static pfGeoState*
defaultGeoState (void)
{
static void *arena = NULL;
static pfMaterial *material = NULL;
static pfGeoState *geostate = NULL;
if (geostate == NULL)
{
arena = pfGetSharedArena();
material = pfNewMtl(arena);
pfMtlColor(material, PFMTL_AMBIENT, 0.1, 0.1, 0.1);
pfMtlColor(material, PFMTL_SPECULAR, 0.8, 0.8, 0.8);
pfMtlShininess(material, 10.0);
pfMtlColorMode(material, PFMTL_FRONT, LMC_AD);
geostate = pfNewGState(arena);
pfGStateAttr(geostate, PFSTATE_FRONTMTL, material);
}
return geostate;
}
--Be seeing you, mtj++at++sgi.com 415.390.1455 M/S 7L-590 Michael Jones Silicon Graphics, Advanced Graphics Division 2011 N. Shoreline Blvd., Mtn. View, CA 94039-7311
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:50:14 PDT