[BACK]Return to pfsv.c CVS log [TXT][DIR] Up to [Development] / performer / src / lib / libpfdb / libpfsv

File: [Development] / performer / src / lib / libpfdb / libpfsv / pfsv.c (download)

Revision 1.1, Tue Nov 21 21:39:35 2000 UTC (16 years, 11 months ago) by flynnt
Branch: MAIN
CVS Tags: HEAD

Initial check-in based on OpenGL Performer 2.4 tree.
-flynnt

/*
 * Copyright 1993, 1995, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 *
 * This source code ("Source Code") was originally derived from a
 * code base owned by Silicon Graphics, Inc. ("SGI")
 * 
 * LICENSE: SGI grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with OpenGL Performer; and (3) the
 * names of Silicon Graphics, Inc.  and SGI may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of SGI.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 * 
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 * 
 * IN NO EVENT WILL SGI BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 * 
 * Contact information:  Silicon Graphics, Inc., 
 * 1600 Amphitheatre Pkwy, Mountain View, CA  94043, 
 * or:  http://www.sgi.com
 */

/*
 * pfsv.c: $Revision: 1.1 $ $Date: 2000/11/21 21:39:35 $
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#ifdef	_POSIX_SOURCE
extern int strcasecmp (const char *s1, const char *s2);
#endif

#include <Performer/pf.h>
#include <Performer/pfdu.h>

/* case insensitive string equality test */
#define	SAME(_a, _b)	(strcasecmp(_a,_b) == 0)

/* program capacity constants */
#define	MAX_MATERIALS	512
#define	MAX_TEXTURES	512
#define	MAX_STRING	256

/*
 * pfdLoadFile_sv -- Load i3dm ".sv" files into IRIS Performer
 */

extern pfNode *
pfdLoadFile_sv (char *fileName)
{
    FILE	*svFile		= NULL;
    pfdGeom	*buffer		= NULL;
    char	*next		= NULL;
    pfNode	*node		= NULL;
    int		 width		= 0;
    int		 i;
    int		 cullDefault	= PFCF_BACK;
    int		 numTris	= 0;
    int		 numVerts	= 0; 
    int 	 numSkip	= 0;
    int		 numOther	= 0;
    char	 input[MAX_STRING];
    char	 token[MAX_STRING];
    int		 t;

    pfMaterial	*material[MAX_MATERIALS] = {NULL};
    pfTexture	*texture[MAX_TEXTURES] = {NULL};

    /* restore builder to initial state */
    pfdResetBldrGeometry();
    pfdResetBldrState();

    /* print statistics */
    pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "pfdLoadFile_sv: %s", fileName);

    /* open ".sv" file */
    if ((svFile = pfdOpenFile(fileName)) == NULL)
	return NULL;

    /* initialize utility library triangle/geoset builder */
    buffer = pfdNewGeom(4096);

    /* read ".sv" file */
    while (fgets(input, MAX_STRING, svFile) != NULL)
    {
	/* find first non-"space" character in line */
	for (next = input; *next != '\0' && isspace(*next); next++)
	    /* EMPTY */ {};
	
	/* skip blank lines and comments */
	if (*next == '\0' || *next == '#' || *next == '/')
	    continue;
	
	/* extract token */
	sscanf(next, "%s%n", token, &width);
	next += width;

	/* 
	 * identify token 
	 */

	if (SAME(token, "model"))
	{
	    pfdBldrStateMode(PFSTATE_CULLFACE, cullDefault);
	}
	else
	if (SAME(token, "endmodel"))
	{
	}
	else
	if (SAME(token, "backface"))
	{
	    int		  cullMode;
	    char	  mode[MAX_STRING];
	    pfLightModel *lm = (pfLightModel *)
		pfdGetTemplateObject(pfGetLModelClassType());

	    /* determine new cull mode ("off" means "backfaces are off") */
	    sscanf(next, "%s", mode);

	    if (SAME(mode, "off"))
	    {
		pfLModelTwoSide(lm, PF_OFF);
		pfdBldrStateAttr(PFSTATE_LIGHTMODEL, lm);
		pfdBldrStateMode(PFSTATE_CULLFACE, PFCF_BACK);
	    }
	    else
	    {
		pfLModelTwoSide(lm, PF_ON);
		pfdBldrStateAttr(PFSTATE_LIGHTMODEL, lm);
		pfdBldrStateMode(PFSTATE_CULLFACE, PFCF_OFF);
	    }
	}
	else
	if (SAME(token, "material"))
	{
	    int		 parsed;
	    int		 index;
	    float	 ar =  0.2f, ag = 0.2f, ab = 0.2f;
	    float	 dr =  0.8f, dg = 0.8f, db = 0.8f;
	    float	 sr =  0.3f, sg = 0.3f, sb = 0.3f;
	    float	 sh = 30.0f;

	    /* read material definition from input */
	    parsed = sscanf(next, "%d %f%f%f %f%f%f %f%f%f %f", 
		&index,  &ar, &ag, &ab,  &dr, &dg, &db,  &sr, &sg, &sb,  &sh);

	    /* skip invalid material definitions */
	    if (parsed < 1 || index < 0 || index >= MAX_MATERIALS)
		continue;

	    /* define a new current material */
	    if (parsed > 1)
	    {
		/* allocate material definition */
		material[index] = pfNewMtl(pfGetSharedArena());

		/* specify values in material definition */
		pfMtlColor(material[index], PFMTL_AMBIENT,  ar, ag, ab);
		pfMtlColor(material[index], PFMTL_DIFFUSE,  dr, dg, db);
		pfMtlColor(material[index], PFMTL_SPECULAR, sr, sg, sb);
		pfMtlShininess(material[index], sh);
		pfMtlColorMode(material[index], PFMTL_FRONT, PFMTL_CMODE_OFF);
		pfMtlSide(material[index], PFMTL_FRONT);
	    }

	    /* specify updated material as builder's current material */
	    if (parsed  > 0)
	    {
		pfdBldrStateAttr(PFSTATE_FRONTMTL, material[index]);
		pfdBldrStateAttr(PFSTATE_BACKMTL,  material[index]);
	    }
	}
	else
	if (SAME(token, "texture"))
	{
	    int		parsed;
	    int		index;
	    char	textureName[MAX_STRING];
	    char	texturePath[MAX_STRING];

	    /* read texture definition from input */
	    parsed = sscanf(next, "%d %s", &index, textureName);

	    /* skip invalid texture definitions */
	    if (parsed < 1 || index < 0 || index >= MAX_TEXTURES)
		continue;
	    
	    /* define a new current texture */
	    if (parsed > 1)
	    {
		/* find texture file in file search path */
		if (pfFindFile(textureName, texturePath, R_OK) == 0)
		    continue;

		/* specify the texture */
		texture[index] = pfNewTex(pfGetSharedArena());
		pfTexName(texture[index], texturePath);
	    }

	    /* specify the texture */
	    pfdBldrStateAttr(PFSTATE_TEXTURE, texture[index]);
	    pfdBldrStateMode(PFSTATE_ENTEXTURE, PFTR_ON);
	}
	else
	if (SAME(token, "poly3dn") || SAME(token, "poly3d"))
	{
	    int		count;
	    int		parsed;
	    int		hasNormals	= 1;
	    int		hasTextures	= 1;

	    /* get number of vertices in polygon */
	    if (sscanf(next, "%d", &count) != 1)
		continue;

	    /* read vertex definitions */
	    for (i = 0; i < count; i++)
	    {
		/* get next line */
		if (fgets(input, MAX_STRING, svFile) == NULL)
		    break;

		/* read whatever values are present */
		parsed = sscanf(input, "%f%f%f %f%f%f %f%f", 
		    &buffer->coords[i][0], 
		    &buffer->coords[i][1], 
		    &buffer->coords[i][2],
		    &buffer->norms [i][0], 
		    &buffer->norms [i][1], 
		    &buffer->norms [i][2],
		    &buffer->texCoords[0][i][0], 
		    &buffer->texCoords[0][i][1]);
		
		/* lowest-common-denominator vertex determines polygon type */
		if (parsed < 8)
		    hasTextures = 0;
		if (parsed < 6)
		    hasNormals = 0;
		if (parsed < 3)
		    break;
	    }

	    /* send polygon to the builder */
	    buffer->numVerts = i;
	    buffer->primtype = PFGS_POLYS;
	    buffer->cbind = PFGS_OFF;
	    buffer->nbind = hasNormals  ? PFGS_PER_VERTEX : PFGS_OFF;
	    buffer->tbind[0] = hasTextures ? PFGS_PER_VERTEX : PFGS_OFF;
            for (t = 1 ; t < PF_MAX_TEXTURES ; t ++)
		buffer->tbind[t] = PFGS_OFF;

	    pfdAddBldrGeom(buffer, 1);

	    numTris  += buffer->numVerts - 2;
	    numVerts += buffer->numVerts;
	}
	else
	if (SAME(token, "tmeshn"))
	{
	    int		count = 0;
	    pfVec3	pArray[3];
	    pfVec3	nArray[3];
	    pfVec2	tArray[3];

	    /* get number of vertices in triangle strip */
	    if (sscanf(next, "%d", &count) != 1)
		continue;

	    /* read triangle strip definition */
	    for (i = 0; i < count; i++)
	    {
		int		n = i % 3;
		int		parsed = 0;
		int		hasNormals = 1;
		int		hasTextures = 1;

		/* get next line */
		if (fgets(input, MAX_STRING, svFile) == NULL)
		    break;

		/* read whatever values are present */
		parsed = sscanf(input, "%f%f%f %f%f%f %f%f", 
		    &pArray[n][0], &pArray[n][1], &pArray[n][2],
		    &nArray[n][0], &nArray[n][1], &nArray[n][2],
		    &tArray[n][0], &tArray[n][1]);
		
		/* lowest-common-denominator vertex determines polygon type */
		if (parsed < 8)
		    hasTextures = 0;
		if (parsed < 6)
		    hasNormals = 0;
		if (parsed < 3)
		    break;

		/* send polygon to the builder */
		if (i >= 2)
		{
		    int 	j;

		    buffer->numVerts = 3;
		    buffer->primtype = PFGS_POLYS;
		    buffer->cbind = PFGS_OFF;
		    buffer->nbind = hasNormals  ? PFGS_PER_VERTEX : PFGS_OFF;
		    for (t = 1 ; t < PF_MAX_TEXTURES ; t ++)
			buffer->tbind[t] = PFGS_OFF;
		    buffer->tbind[0] = hasTextures ? PFGS_PER_VERTEX : PFGS_OFF;

		    /* copy last three vertices (CCW or CW) */
		    if (((i - 2) & 1) == 0)
		    {
			for (j = 0; j < 3; j++)
			{
			    int		k = (n + j + 2) % 3;
			    pfCopyVec3(buffer->coords[j], pArray[k]);
			    pfCopyVec3(buffer->norms [j], nArray[k]);
			    pfCopyVec2(buffer->texCoords[0][j], tArray[k]);
			}
		    }
		    else
		    {
			for (j = 0; j < 3; j++)
			{
			    int		k = (n + 2 - j + 2) % 3;
			    pfCopyVec3(buffer->coords[j], pArray[k]);
			    pfCopyVec3(buffer->norms [j], nArray[k]);
			    pfCopyVec2(buffer->texCoords[0][j], tArray[k]);
			}
		    }

		    pfdAddBldrGeom(buffer, 1);

		    numTris  += buffer->numVerts - 2;
		    numVerts += buffer->numVerts;
		}
	    }
	}
	else
	if (SAME(token, "line3d"))
	{
	    int		count;

	    /* get number of vertices in line strip */
	    if (sscanf(next, "%d", &count) != 1)
		continue;

	    ++numSkip;

	    /* read line strip definition */
	    for (i = 0; i < count; i++)
	    {
		if (fgets(input, MAX_STRING, svFile) == NULL)
		    break;
	    }
	}
	else
	if (SAME(token, "action") || 
	    SAME(token, "background_color") || 
	    SAME(token, "backset") || 
	    SAME(token, "concave") || 
	    SAME(token, "environment_map") || 
	    SAME(token, "eye_distance") || 
	    SAME(token, "gouraud") || 
	    SAME(token, "initial") || 
	    SAME(token, "jklogo") || 
	    SAME(token, "light") || 
	    SAME(token, "origin") || 
	    SAME(token, "reference") || 
	    SAME(token, "shade") || 
	    SAME(token, "shademode") || 
	    SAME(token, "texture_env") || 
	    SAME(token, "trans_init") || 
	    SAME(token, "transparent") || 
	    SAME(token, "window"))
	    ++numSkip;
	else
	{
	    pfNotify(PFNFY_WARN, PFNFY_PRINT, "pfdLoadFile_sv: unrecognized: %s", input);
	    ++numOther;
	}
    }

    /* close ".sv" file */
    fclose(svFile);
    pfdDelGeom(buffer);

    /* get a complete scene graph representing file's polygons */
    node = pfdBuild();
    if (node != NULL)
	pfNodeName(node, fileName);

    /* print statistics */
    pfNotify(PFNFY_INFO,   PFNFY_MORE,  "  Input Data:");
    pfNotify(PFNFY_INFO,   PFNFY_MORE,  "    Commands skipped:   %8ld", numSkip);
    pfNotify(PFNFY_INFO,   PFNFY_MORE,  "    Commands unknown:   %8ld", numOther);
    pfNotify(PFNFY_INFO,   PFNFY_MORE,  "    Input vertices:     %8ld", numVerts);
    pfNotify(PFNFY_INFO,   PFNFY_MORE,  "    Input triangles:    %8ld", numTris);

    return node;
}