Inventor loader ...

New Message Reply Date view Thread view Subject view Author view

Cedric Gautier (gce++at++scl.syseca.fr)
Tue, 23 Aug 94 12:01:35 +0200


   Hello,
   I am new to Performer - so I have a pretty simple question.
I have been trying to get Inventor .iv files to load into
perfly. I've tried both 1.0 and 2.0 iv files and usually - though
not always, perfly tells me it can't load them (after finding and
loading the textures declared therein). Can anyone tell me how
it is discriminating?
                                 Mark Lasersohn
                                 Bailey Controls Company
                                 laser++at++bailey.com

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
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:50:30 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.