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

File: [Development] / performer / src / lib / libpfdb / libpfbpoly / pfbpoly.c (download)

Revision 1.1, Tue Nov 21 21:39:32 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 1994, 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
 */

/*
 * pfbpoly.c: $Revision: 1.1 $ $Date: 2000/11/21 21:39:32 $
 */

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

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

#ifndef P_32_SWAP
#define	P_32_SWAP(a) {							\
	uint _tmp = *(uint *)a;				\
	((char *)a)[0] = ((char *)&_tmp)[3];				\
	((char *)a)[1] = ((char *)&_tmp)[2];				\
	((char *)a)[2] = ((char *)&_tmp)[1];				\
	((char *)a)[3] = ((char *)&_tmp)[0];				\
}
#endif  /* P_32_SWAP */

#ifndef P_16_SWAP
#define	P_16_SWAP(a) {							\
	ushort _tmp = *(ushort *)a;				\
	((char *)a)[0] = ((char *)&_tmp)[1];				\
	((char *)a)[1] = ((char *)&_tmp)[0];				\
}
#endif  /* P_16_SWAP */


size_t swapped_fread32(void *ptr, size_t size, size_t nitems, FILE *stream)
{
        unsigned char *p = ptr;
        int i, n;

		if((size != 4) && (nitems > 1))
		{
			n = (size * nitems)/4;
		}
		else if((size != 4) && nitems == 1)
		{
			n = size/4;
		}
		else
		{
			n = nitems;
		}

        /* do 32bit swap */
        nitems = fread(ptr, 4, n, stream);
        for(i=0; i<n; ++i)
        {
            P_32_SWAP(p);
            p += 4;
        }
        return nitems;
}

size_t swapped_fread16(void *ptr, size_t size, size_t nitems, FILE *stream)
{
        unsigned char *p = ptr;
        int i;

        /* do 16bit swap */
        nitems = fread(ptr, 2, nitems, stream);
        for(i=0; i<nitems; ++i)
        {
            P_16_SWAP(p);
            p += 2;
        }
        return nitems;
}

size_t pfb_fread(void *ptr, size_t size, size_t nitems, FILE *stream)
{
#ifdef __i386__
		if(size == 1)
		{
			/* normal fread */
			nitems = fread(ptr, size, nitems, stream);
			return nitems;
		}
		else if(size == 2)
		{
			/* swapped_fread16 */
			nitems = swapped_fread16(ptr, size, nitems, stream);
			return nitems;
		}
		else if((size == 4) || (size%4 == 0))
		{
			/* swapped_fread32 */
			nitems = swapped_fread32(ptr, size, nitems, stream);
			return nitems;
		}
#else
			/* normal fread */
			nitems = fread(ptr, size, nitems, stream);
			return nitems;
#endif
}


#define OLD_BPOLY_MAGIC	0x62706F6C      /* "bpol" */
#define NEW_BPOLY_MAGIC	0x62706F32      /* "bpo2" */

#define VERTEX_COLOR	0x1
#define VERTEX_TEXTURE	0x4
#define VERTEX_NORMAL	0x8
#define POLYGON_COLOR	0x2

typedef struct polyVertex 
{
    pfVec3	xyz;
    pfVec4	rgba;
    pfVec3	norm;
    pfVec2	st;
} polyVertex;

/*
 * pfdLoadFile_bpoly -- Load Prisims ".bpoly" files into IRIS Performer
 */

extern pfNode *
pfdLoadFile_bpoly (char *fileName)
{
    FILE	*bpolyFIle	= NULL;
    pfdGeom	*geom		= NULL;
    pfNode	*node		= NULL;
    polyVertex	*v		= NULL; 
    int		 geomSize	= 256;
    int		 i		= 0;
    int		 j		= 0;
    int		 magic		= 0;
    int		 bpolyPoints	= 0;
    int		 bpolyPolys	= 0;
    int		 numTris	= 0;
    short	 flag		= 0;
    pfMaterial  *m      	= NULL;
    double	 startTime	= pfGetTime();
    int		 t		= 0;

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

    /* open Prisims ".bpoly" file file */
    if ((bpolyFIle = pfdOpenFile(fileName)) == NULL)
	return NULL;

    /* allocate a new primitive geom */
    geom = pfdNewGeom(geomSize);

#define	RANDOM_COLOR
#ifdef	RANDOM_COLOR
    /* pick a random not-too-dark color */
    pfuRandomize(*(int *)&startTime);
    pfuRandomColor(geom->colors[0], 0.2f, 0.7f);
#endif

    /* establish material definition for model */
    m = (pfMaterial*)pfdGetTemplateObject(pfGetMtlClassType());
    pfMtlColor(m, PFMTL_AMBIENT,  0.2f, 0.2f, 0.2f);
    pfMtlColor(m, PFMTL_DIFFUSE,  0.8f, 0.8f, 0.8f);
    pfMtlColor(m, PFMTL_SPECULAR, 1.0f, 1.0f, 1.0f);
    pfMtlShininess(m, 30.0f);
    pfMtlColorMode(m, PFMTL_FRONT, PFMTL_CMODE_AD);
    pfdBldrStateAttr(PFSTATE_FRONTMTL, m);
    pfdBldrStateMode(PFSTATE_CULLFACE, PFCF_BACK);
    pfdBldrStateMode(PFSTATE_ENLIGHTING, PF_ON);

    /* read "header" definition from ".bpoly" file */
    if (fread(&magic, sizeof(magic), 1, bpolyFIle) != 1)
    {
	fclose(bpolyFIle);
	return NULL;
    }

    /* magic number determines size of vertex indices */
    if (magic != OLD_BPOLY_MAGIC && magic != NEW_BPOLY_MAGIC)
    {
	pfdDelGeom(geom);
	fclose(bpolyFIle);
	return NULL;
    }

    /* read counts from file */
    if (magic == OLD_BPOLY_MAGIC)
    {
	short	shortPoints	= 0;
	short	shortPolys	= 0;

	if ((fread(&shortPoints, sizeof(shortPoints), 1, bpolyFIle) != 1) ||
	    (fread(&shortPolys,  sizeof(shortPolys ), 1, bpolyFIle) != 1))
	{
	    pfdDelGeom(geom);
	    fclose(bpolyFIle);
	    return NULL;
	}

	bpolyPoints = shortPoints;
	bpolyPolys  = shortPolys;
    }
    else
    {
	if ((fread(&bpolyPoints, sizeof(bpolyPoints), 1, bpolyFIle) != 1) ||
	    (fread(&bpolyPolys,  sizeof(bpolyPolys ), 1, bpolyFIle) != 1))
	{
	    pfdDelGeom(geom);
	    fclose(bpolyFIle);
	    return NULL;
	}
    }

    /* read vertex-type flag */
    if (fread(&flag, sizeof(flag), 1, bpolyFIle) != 1)
    {
	pfdDelGeom(geom);
	fclose(bpolyFIle);
	return NULL;
    }

    /* read "POINTS" definition from ".bpoly" file */
    v = (polyVertex *)pfMalloc(bpolyPoints*sizeof(polyVertex), NULL);

    for (i = 0; i < bpolyPoints; i++)
    {
	if ((                           fread(v[i].xyz,  sizeof(float), 3, bpolyFIle) != 3) ||
	    ((flag & VERTEX_COLOR  ) && fread(v[i].rgba, sizeof(float), 3, bpolyFIle) != 3) ||
	    ((flag & VERTEX_TEXTURE) && fread(v[i].st,   sizeof(float), 2, bpolyFIle) != 2) ||
	    ((flag & VERTEX_NORMAL ) && fread(v[i].norm, sizeof(float), 3, bpolyFIle) != 3))
	{
	    pfFree(v);
	    pfdDelGeom(geom);
	    fclose(bpolyFIle);
	    return NULL;
	}

	/* set alpha-component to fully opaque */
	v[i].rgba[3] = 1.0f;

#ifdef	DEBUG
	pfNotify(PFNFY_DEBUG, PFNFY_MORE,  "vertex %d", i);
	    pfNotify(PFNFY_DEBUG, PFNFY_MORE,  "   xyz: %g %g %g", 
		v[i].xyz[0],  
		v[i].xyz[1],  
		v[i].xyz[2]);
	if (flag & VERTEX_COLOR)
	    pfNotify(PFNFY_DEBUG, PFNFY_MORE,  "  rgba: %g %g %g %g", 
		v[i].rgba[0], 
		v[i].rgba[1], 
		v[i].rgba[2], 
		v[i].rgba[3]);
	if (flag & VERTEX_NORMAL)
	    pfNotify(PFNFY_DEBUG, PFNFY_MORE,  "  norm: %g %g %g", 
		v[i].norm[0], 
		v[i].norm[1], 
		v[i].norm[2]);
	if (flag & VERTEX_TEXTURE)
	    pfNotify(PFNFY_DEBUG, PFNFY_MORE,  "    st: %g %g", 
		v[i].st[0], 
		v[i].st[1]);
#endif
    }

    /* read "POLYS" definition from ".bpoly" file */
    for (j = 0; j < bpolyPolys; j++)
    {
	char	closed	= 0;
	int	vCount	= 0;
	pfVec4	rgba;

	if (fread(&closed, sizeof(closed), 1, bpolyFIle) != 1) 
	{
	    pfFree(v);
	    pfdDelGeom(geom);
	    fclose(bpolyFIle);
	    return NULL;
	}

	/* color specified at polygon level */
	if (flag & POLYGON_COLOR) 
	{
	    if (fread(rgba, sizeof(float), 3, bpolyFIle) != 3)
	    {
		pfFree(v);
		pfdDelGeom(geom);
		fclose(bpolyFIle);
		return NULL;
	    }

	    /* set alpha-component to fully opaque */
	    rgba[3] = 1.0f;
	}

	/* number of vertices in polygon */
	if (magic == OLD_BPOLY_MAGIC)
	{
	    short	shortCount	= 0;

	    if (fread(&shortCount, sizeof(shortCount), 1, bpolyFIle) != 1)
	    {
		pfFree(v);
		pfdDelGeom(geom);
		fclose(bpolyFIle);
		return NULL;
	    }

	    vCount = shortCount;
	}
	else
	{
	    if (fread(&vCount, sizeof(vCount), 1, bpolyFIle) != 1)
	    {
		pfFree(v);
		pfdDelGeom(geom);
		fclose(bpolyFIle);
		return NULL;
	    }
	}

	/* resize geometry geom if necessary */
	if (geomSize < vCount)
	    pfdResizeGeom(geom, geomSize = vCount);

	/* read vertex indices from file */
	for (i = 0; i < vCount; i++)
	{
	    int		index	= 0;

	    if (magic == OLD_BPOLY_MAGIC)
	    {
		unsigned short	shortIndex	= 0;

		if (fread(&shortIndex, sizeof(shortIndex), 1, bpolyFIle) != 1)
		{
		    pfFree(v);
		    pfdDelGeom(geom);
		    pfdResetBldrGeometry();
		    fclose(bpolyFIle);
		    return NULL;
		}

		index = shortIndex;
	    }
	    else
	    {
		if (fread(&index, sizeof(index), 1, bpolyFIle) != 1)
		{
		    pfFree(v);
		    pfdDelGeom(geom);
		    pfdResetBldrGeometry();
		    fclose(bpolyFIle);
		    return NULL;
		}
	    }

	    /* index is 1-based in file, 0-based in array */
	    --index;

	    if (index < 0 || index >= bpolyPoints)
	    {
		pfNotify(PFNFY_WARN, PFNFY_PRINT, 
		    "pfdLoadFile_bpoly: index %d out of range [0 .. %d]", 
		    index, bpolyPoints);
		pfFree(v);
		pfdDelGeom(geom);
		pfdResetBldrGeometry();
		fclose(bpolyFIle);
		return NULL;
	    }

	    /* copy valid vertex attributes to builder */
	    pfCopyVec3(geom->coords[i], v[index].xyz);

	    if (flag & VERTEX_COLOR)
		pfCopyVec4(geom->colors[i], v[index].rgba);

	    if (flag & VERTEX_NORMAL)
		pfCopyVec3(geom->norms[i], v[index].norm);

	    if (flag & VERTEX_TEXTURE)
		pfCopyVec2(geom->texCoords[i], v[index].st);
	}

	/* add polygon to builder */
	if (i >= 3)
	{
	    geom->numVerts = i;
	    geom->primtype = PFGS_POLYS;
	    geom->cbind = (flag & VERTEX_COLOR)   ? PFGS_PER_VERTEX : 
#ifdef  RANDOM_COLOR
                                                    PFGS_PER_PRIM;
#else
			  (flag & POLYGON_COLOR)  ? PFGS_PER_PRIM   : 
			                            PFGS_OFF;
#endif
	    geom->nbind = (flag & VERTEX_NORMAL)  ? PFGS_PER_VERTEX : PFGS_OFF;
	    geom->tbind[0] = (flag & VERTEX_TEXTURE) ? PFGS_PER_VERTEX : PFGS_OFF;
	    for (t = 1 ; t < PF_MAX_TEXTURES ; t ++)
		geom->tbind[t] = PFGS_OFF;

#ifdef  POLYGONS_ARE_IN_CW_ORDER
	    /* poly files seem to have CW polygon orientation so reverse */
	    pfdReverseGeom(buffer);
#endif

	    pfdAddBldrGeom(geom, 1);
	    numTris += geom->numVerts - 2;
	}
    }

    /* close ".bpoly" file */
    fclose(bpolyFIle);

    /* release dynamically allocated vertex data */
    pfFree(v);

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

    /* release memory and reset builder */
    pfdDelGeom(geom);
    pfdResetBldrGeometry();

    /* print statistics */
    pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "pfdLoadFile_bpoly: %s", fileName);
    pfNotify(PFNFY_INFO,   PFNFY_MORE,  "  Input Data:");
    pfNotify(PFNFY_INFO,   PFNFY_MORE,  "    Input vertices:     %8ld", 
	bpolyPoints);
    pfNotify(PFNFY_INFO,   PFNFY_MORE,  "    Input polygons:     %8ld", 
	bpolyPolys);

    /* return pointer to in-memory scene-graph */
    return node;
}