Cedric Gautier (gce++at++scl.syseca.fr)
Tue, 23 Aug 94 12:01:35 +0200
Answer is:
try this version of the pfiv.c loader ...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "pf.h"
#include "pfsgi.h"
#include "pfutil.h"
/* case insensitive string equality test */
#define SAME(_a, _b) (strcasecmp(_a,_b) == 0)
/* program capacity constants */
#define MAX_MATERIALS 512
#define MAX_TEXTURES 20000
#define MAX_STRING 1024
#define MAX_VERTICES 20000
#define MAX_NORMALS 20000
#define MAX_INDICES 20000
/* token types returned from parser */
#define T_END 0
#define T_KEYWORD 1
#define T_NUMBER 2
#define T_COMPLETE 3
/* attribute and mode definition */
typedef struct Style
{
pfGeoState *geostate;
pfMaterial *material;
pfTexture *texture;
pfTexEnv *environment;
long culling;
} Style;
/* function type and argument declarations */
static FILE *openFile(const char *fileName);
static pfGeoState* defaultGeoState(void);
static void processPolygons(pfGeode *geode, pfuBuilder *builder, Style *style);
static int getToken (FILE *fp, char *token);
static float ar = 0.5, ag = 0.5, ab = 0.5;
static float dr = 0.5, dg = 0.5, db = 0.5;
static float sr = 0.5, sg = 0.5, sb = 0.5;
static float er = 0.5, eg = 0.5, eb = 0.5;
static float shin= 0.0;
extern pfNode *
LoadIv (char *fileName, pfGeoState *geostate)
{
FILE *ivFile;
pfuPoly polygon;
pfuBuilder *builder = NULL;
int tokenType = NULL;
char token[256];
char verToken[256];
char texPath[256];
pfGeode *geode = NULL;
pfNode *node = NULL;
pfNode *hierarchy = NULL;
int width = 0;
int i;
int j;
long pending = 0;
long numV = 0;
long numT = 0;
long numVI = 0;
long numTI = 0;
long numN = 0;
long numNI = 0;
long numTris = 0;
long numSkip = 0;
long numOther = 0;
float alpha = 1.0f;
float sx = 1.0f;
float sy = 1.0f;
float sz = 1.0f;
double startTime = pfGetTime();
double elapsedTime = 0.0;
static void *sharedArena = NULL;
pfVec3 v[MAX_VERTICES];
pfVec3 n[MAX_NORMALS];
pfVec2 t[MAX_TEXTURES];
int vi[MAX_INDICES];
int ni[MAX_INDICES];
int f[MAX_INDICES];
int vCount = 0;
int tCount = 0;
int viCount = 0;
int nCount = 0;
int niCount = 0;
int fCount = 0;
Style style;
strcpy(verToken, "point");
/* get pointer to IRIS Performer shared memory arena */
if (sharedArena == NULL)
sharedArena = pfGetSharedArena();
/* open ".iv" file */
if ((ivFile = openFile(fileName)) == NULL)
return NULL;
/* give object a default geostate if nothing is passed in */
if (geostate == NULL)
geostate = defaultGeoState();
/* the style structure contains the current modes and attributes */
style.geostate = geostate;
style.material = NULL;
style.culling = PFCF_BACK;
/* give object a default texture environment */
style.texture = pfNewTex(sharedArena);
style.environment = pfNewTEnv(sharedArena);
pfTEnvMode(style.environment, PFTE_MODULATE);
/* initialize utility library triangle/geoset builder */
builder = pfuNewBuilder();
/* read ".iv" file */
tokenType = getToken(ivFile, token);
while (tokenType != T_END)
{
if (SAME(token, "ambientColor"))
{
getToken(ivFile, token); sscanf(token, "%f", &ar);
getToken(ivFile, token); sscanf(token, "%f", &ag);
getToken(ivFile, token); sscanf(token, "%f", &ab);
tokenType = getToken(ivFile, token);
}
else
if (SAME(token, "diffuseColor"))
{
getToken(ivFile, token); sscanf(token, "%f", &dr);
getToken(ivFile, token); sscanf(token, "%f", &dg);
getToken(ivFile, token); sscanf(token, "%f", &db);
tokenType = getToken(ivFile, token);
pfSetVec4(polygon.colors[0], dr, dg, db, alpha);
}
else
if (SAME(token, "specularColor"))
{
getToken(ivFile, token); sscanf(token, "%f", &sr);
getToken(ivFile, token); sscanf(token, "%f", &sg);
getToken(ivFile, token); sscanf(token, "%f", &sb);
tokenType = getToken(ivFile, token);
}
else
if (SAME(token, "emissiveColor"))
{
getToken(ivFile, token); sscanf(token, "%f", &er);
getToken(ivFile, token); sscanf(token, "%f", &eg);
getToken(ivFile, token); sscanf(token, "%f", &eb);
tokenType = getToken(ivFile, token);
}
else
if (SAME(token, "shininess"))
{
getToken(ivFile, token); sscanf(token, "%f", &shin);
tokenType = getToken(ivFile, token);
}
else
if (SAME(token, verToken))
{
for (vCount = 0; (tokenType=getToken(ivFile, token)) == T_NUMBER;
vCount++)
{
if (vCount >= MAX_VERTICES)
vCount = MAX_VERTICES - 1;
sscanf(token, "%f", &v[vCount][0]);
getToken(ivFile, token); sscanf(token, "%f", &v[vCount][1]);
getToken(ivFile, token); sscanf(token, "%f", &v[vCount][2]);
v[vCount][0] *= sx;
v[vCount][1] *= sy;
v[vCount][2] *= sz;
}
numV += vCount;
strcpy(verToken, "voint");
}
else
if (SAME(token, "vector"))
{
for (nCount = 0; (tokenType=getToken(ivFile, token)) == T_NUMBER;
nCount++)
{
if (nCount >= MAX_NORMALS)
nCount = MAX_NORMALS - 1;
sscanf(token, "%f", &n[nCount][0]);
getToken(ivFile, token); sscanf(token, "%f", &n[nCount][1]);
getToken(ivFile, token); sscanf(token, "%f", &n[nCount][2]);
}
numN += nCount;
}
else
if (SAME(token, "filename"))
{
getToken(ivFile, token);
sscanf(token, "%s", texPath);
fprintf(stderr, "Texture Name: %s\n", texPath);
pfLoadTexFile(style.texture, texPath);
}
else
if (SAME(token, "point"))
{
for (tCount = 0; (tokenType=getToken(ivFile, token)) == T_NUMBER;
tCount++)
{
if (tCount >= MAX_TEXTURES)
tCount = MAX_TEXTURES - 1;
sscanf(token, "%f", &t[tCount][0]);
getToken(ivFile, token); sscanf(token, "%f", &t[tCount][1]);
}
numT += tCount;
fprintf(stderr, "Texture Coordinates: %d\n", tCount);
}
else
if (SAME(token, "numVertices"))
{
for (fCount = 0; (tokenType=getToken(ivFile, token)) == T_NUMBER;
fCount++)
{
if (fCount >= MAX_INDICES)
fCount = MAX_INDICES - 1;
sscanf(token, "%d", &f[fCount]);
}
for (i = 0, j = 0; i < fCount; i++)
{
for (polygon.numVerts = 0; polygon.numVerts < f[i];
polygon.numVerts++)
{
pfCopyVec3(polygon.coords[polygon.numVerts], v[j]);
if (nCount >= vCount)
pfCopyVec3(polygon.norms [polygon.numVerts], n[j]);
if (tCount >= vCount)
pfCopyVec2(polygon.texCoords [polygon.numVerts], t[j]);
j++;
}
if (polygon.numVerts > 2)
{
polygon.cbind = PFGS_PER_PRIM;
polygon.nbind =
(nCount >= vCount) ? PFGS_PER_VERTEX : PFGS_OFF;
polygon.tbind =
(tCount >= vCount) ? PFGS_PER_VERTEX : PFGS_OFF;
numTris += polygon.numVerts - 2;
pfuAddPoly(builder, &polygon);
polygon.numVerts = 0;
}
}
nCount = 0;
vCount = 0;
tCount = 0;
pending = 0;
}
else
if (tokenType == T_COMPLETE && pending)
{
if (viCount > 2)
{
for (i = 0, polygon.numVerts = 0; i < viCount; i++)
{
if (vi[i] >= 0 && vi[i] < MAX_INDICES)
{
pfCopyVec3(polygon.coords[polygon.numVerts], v[vi[i]]);
if (nCount == vCount)
pfCopyVec3(polygon.norms [polygon.numVerts], n[vi[i]]);
polygon.numVerts++;
}
else
if (polygon.numVerts > 2)
{
polygon.cbind = PFGS_PER_PRIM;
polygon.nbind =
(nCount == vCount) ? PFGS_PER_VERTEX : PFGS_OFF;
polygon.tbind = PFGS_OFF;
numTris += polygon.numVerts - 2;
pfuAddPoly(builder, &polygon);
polygon.numVerts = 0;
}
}
}
nCount = 0;
vCount = 0;
pending = 0;
}
else
{
/*
* fprintf(stderr, " unrecognized: %s\n", token);
*/
tokenType = getToken(ivFile, token);
++numOther;
}
}
/* close ".iv" file */
fclose(ivFile);
/* construct geode */
if (numTris > 0)
{
geode = pfNewGeode();
node = (pfNode *)geode;
processPolygons(geode, builder, &style);
}
/* delete builder */
pfuDelBuilder(builder);
/* print statistics */
if(pfGetNotifyLevel() >= PFNFY_INFO)
{
elapsedTime = pfGetTime() - startTime;
fprintf(stderr, "LoadIv:\n");
fprintf(stderr, " file name = %s\n", fileName);
fprintf(stderr, " commands skipped = %8ld\n", numSkip);
fprintf(stderr, " commands unknown = %8ld\n", numOther);
fprintf(stderr, " vertices (indices) = %8ld (%8ld)\n", numV, numVI);
fprintf(stderr, " normals (indices) = %8ld (%8ld)\n", numN, numNI);
fprintf(stderr, " textures (indices) = %8ld (%8ld)\n", numT, numTI);
fprintf(stderr, " triangles = %8ld\n", numTris);
if (elapsedTime > 0.0)
{
fprintf(stderr, " loading time = %12.3f sec\n",
elapsedTime);
fprintf(stderr, " loading rate = %12.3f tri/sec\n",
numTris/elapsedTime);
}
}
/* print statistics */
if (pfGetNotifyLevel() >= PFNFY_INFO)
fprintf(stderr, "\n");
return node;
}
static FILE *
openFile (const char *fileName)
{
FILE *file = NULL;
char filePath[MAX_STRING];
/* 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;
}
/*
* 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_DIFFUSE, 0.5, 0.5, 0.5);
pfMtlColor(material, PFMTL_AMBIENT, 0.5, 0.5, 0.5);
pfMtlColorMode(material, PFMTL_FRONT, LMC_AD);
geostate = pfNewGState(arena);
pfGStateAttr(geostate, PFSTATE_FRONTMTL, material);
}
return geostate;
}
/*
* add builder polygons to a geode
*/
static void
processPolygons (pfGeode *geode, pfuBuilder *builder, Style *style)
{
int i;
int numGeoSets = 0;
pfList *geoSetList = NULL;
pfGeoSet *geoset = NULL;
pfGeoState *specific = NULL;
pfMaterial *material = NULL;
static void *sharedArena = NULL;
if (geode == NULL || builder == NULL || style == NULL)
return;
if (sharedArena == NULL)
sharedArena = pfGetSharedArena();
/* convert current face list into one or more geosets */
geoSetList = pfuMakeGSets(builder);
numGeoSets = pfGetNum(geoSetList);
/* make a specific geostate for this collection of polygons */
if (style->geostate != NULL)
{
specific = pfNewGState(sharedArena);
pfCopy(specific, style->geostate);
}
/* set face culling mode to other-than-default */
if (style->culling == PFCF_OFF)
pfGStateMode(specific, PFSTATE_CULLFACE, style->culling);
/* set material to other-than-default */
material = pfNewMtl(sharedArena);
pfMtlColor(material, PFMTL_AMBIENT, ar, ag, ab);
pfMtlColor(material, PFMTL_DIFFUSE, dr, dg, db);
pfMtlColor(material, PFMTL_SPECULAR, sr, sg, sb);
pfMtlColor(material, PFMTL_EMISSION, er, eg, eb);
pfMtlShininess(material, shin * 128.);
pfMtlColorMode(material, PFMTL_FRONT, LMC_AD);
pfGStateAttr(specific, PFSTATE_FRONTMTL, material);
/* set texture to other-than-default */
if (style->texture != NULL)
{
pfGStateAttr(specific, PFSTATE_TEXTURE, style->texture);
pfGStateAttr(specific, PFSTATE_TEXENV, style->environment);
}
/* bind specific geostate to each geoset and each geoset to the geode */
for (i = 0; i < numGeoSets; i++)
{
geoset = (pfGeoSet*)pfGet(geoSetList, i);
pfGSetGState(geoset, specific);
pfAddGSet(geode, geoset);
}
}
/*
* get next token from input
*/
static int
getToken (FILE *fp, char *token)
{
int i;
int c;
/* find next token */
for (;;)
{
/* comsume space characters */
while ((c = getc(fp)) != EOF && isspace(c))
/* EMPTY */ {};
/* stop if end of file */
if (c == EOF)
return T_END;
/* consume comments */
if (c == '#' || c == '/')
{
while ((c = getc(fp)) != EOF && c != '\n')
/* EMPTY */ {};
continue;
}
/* consume quoted strings */
if (c == '"')
{
i= 0;
while ((c = getc(fp)) != EOF && c != '"')
{
token[i]= c;
i++;
};
token[i]= '\0';
return T_KEYWORD;
}
/* skip important grouping tokens */
if (c == '{' || c == ',' || c == '[' || c == ']' || c == '(' ||
c == ')' || c == '|' || c == '~' || c == '_' )
continue;
/* extract keyword token */
if (c == '}')
{
token[0] = c;
token[1] = '\0';
return T_COMPLETE;
}
if (c != EOF && isalpha(c))
{
for (i = 0; c != EOF && (isalnum(c) || c == '_'); i++)
{
token[i] = c;
c = getc(fp);
}
token[i] = '\0';
ungetc(c, fp);
return T_KEYWORD;
}
else
if (c != EOF && isdigit(c)||c=='.'||c=='+'||c=='-'||c=='e'||c=='E')
{
for (i=0; c!=EOF &&
(isdigit(c)||c=='.'||c=='+'||c=='-'||c=='e'||c=='E'); i++)
{
token[i] = c;
c = getc(fp);
}
token[i] = '\0';
ungetc(c, fp);
return T_NUMBER;
}
else
fprintf(stderr, "<< %c >>\n", c);
}
}
...
Cedric
Cedric from Dahouet harbor on Armor coast in France - email: gce++at++syseca.fr
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:50:30 PDT