Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (c) 1993 Lightscape Graphics Software, Ltd.
- *
- * 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 Lightscape Graphics Software may not be
- * used in any advertising or publicity relating to the software
- * without the specific, prior written permission of
- * Lightscape Graphics Software.
- *
- * 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 LIGHTSCAPE GRAPHICS SOFTWARE 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.
- *
- */
- /*
- * pflsb.c:
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
- #include <limits.h>
- #ifndef __linux__
- #ifdef _POSIX_SOURCE
- extern char *strdup (const char *s1);
- #endif
- #endif
- #include <Performer/pf.h>
- #include <Performer/pfdu.h>
- #include <Performer/pfdb/pflsb.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 */
- void swapLSBpatchVertex(LSBpatchVertex *data)
- {
- #ifdef __i386__
- int i;
- for(i=0; i<3; i++)
- P_32_SWAP(&data->color[i]);
- #endif
- }
- void swapLSBtopPatchVertexTextured(LSBtopPatchVertexTextured *data)
- {
- #ifdef __i386__
- int i;
- for(i=0; i<3; i++)
- P_32_SWAP(&data->coord[i]);
- for(i=0; i<3; i++)
- P_32_SWAP(&data->color[i]);
- for(i=0; i<2; i++)
- P_32_SWAP(&data->uv[i]);
- #endif
- }
- void swapLSBpatchLeaf(LSBpatchLeaf *data)
- {
- #ifdef __i386__
- int i;
- for(i=0; i<4; i++)
- P_16_SWAP(&data->vertices[i]);
- for(i=0; i<4; i++)
- P_16_SWAP(&data->midVertices[i]);
- #endif
- }
- void swapLSBpatchClusterLong(LSBpatchClusterLong *data)
- {
- #ifdef __i386__
- int i;
- for(i=0; i<4; i++)
- P_32_SWAP(&data->plane[i]);
- P_32_SWAP(&data->materialId);
- P_32_SWAP(&data->layerId);
- P_32_SWAP(&data->textureId);
- P_32_SWAP(&data->numTopNodes);
- P_32_SWAP(&data->numNodes);
- P_32_SWAP(&data->numTopVertices);
- P_32_SWAP(&data->numVertices);
- #endif
- }
- void swapLSBpatchCluster(LSBpatchCluster *data)
- {
- #ifdef __i386__
- int i;
- for(i=0; i<4; i++)
- P_32_SWAP(&data->plane[i]);
- P_32_SWAP(&data->materialId);
- P_32_SWAP(&data->layerId);
- P_32_SWAP(&data->textureId);
- P_16_SWAP(&data->numTopNodes);
- P_16_SWAP(&data->numNodes);
- P_16_SWAP(&data->numTopVertices);
- P_16_SWAP(&data->numVertices);
- #endif
- }
- void swapLSBheader(LSBheader *data)
- {
- #ifdef __i386__
- int i;
- P_16_SWAP(&data->LSBversion);
- P_16_SWAP(&data->fileFlags);
- P_32_SWAP(&data->numPatchClusters);
- P_32_SWAP(&data->numTopNodes);
- P_32_SWAP(&data->numNodes);
- P_32_SWAP(&data->numTopPatchVertices);
- P_32_SWAP(&data->numPatchVertices);
- P_32_SWAP(&data->numMaterials);
- P_32_SWAP(&data->numLayers);
- P_32_SWAP(&data->numTextures);
- #endif
- }
- void swapLSBtopPatchVertex(LSBtopPatchVertex *data)
- {
- #ifdef __i386__
- int i;
- for(i=0; i<3; i++)
- P_32_SWAP(&data->coord[i]);
- for(i=0; i<3; i++)
- P_32_SWAP(&data->color[i]);
- #endif
- }
- /* global data used by loader */
- static int numTris = 0;
- static int numQuads = 0;
- static pfdGeom *geom = NULL;
- static int geomSize = 256;
- static int clustersPerGeode = 0;
- static pfGroup *groupNode = NULL;
- static float spatialSize = 0.0f;
- static int spatialCount = 0;
- static char *defaultLayerName = "default";
- static int useLongData = 0;
- #define TRI(_a, _b, _c) {\
- geom->primtype = PFGS_POLYS;\
- geom->numVerts = 3;\
- pfCopyVec4(geom->colors[0], colors[(_a)]);\
- pfCopyVec4(geom->colors[1], colors[(_b)]);\
- pfCopyVec4(geom->colors[2], colors[(_c)]);\
- pfCopyVec3(geom->coords[0], coords[(_a)]);\
- pfCopyVec3(geom->coords[1], coords[(_b)]);\
- pfCopyVec3(geom->coords[2], coords[(_c)]);\
- if (geom->tbind[0] == PFGS_PER_VERTEX) \
- {\
- pfCopyVec2(geom->texCoords[0][0], texCoords[(_a)]);\
- pfCopyVec2(geom->texCoords[0][1], texCoords[(_b)]);\
- pfCopyVec2(geom->texCoords[0][2], texCoords[(_c)]);\
- }\
- pfdAddBldrGeom(geom, 1);\
- numTris++;\
- }
- #define QUAD(_a, _b, _c, _d) {\
- geom->primtype = PFGS_POLYS;\
- geom->numVerts = 4;\
- pfCopyVec4(geom->colors[0], colors[(_a)]);\
- pfCopyVec4(geom->colors[1], colors[(_b)]);\
- pfCopyVec4(geom->colors[2], colors[(_c)]);\
- pfCopyVec4(geom->colors[3], colors[(_d)]);\
- pfCopyVec3(geom->coords[0], coords[(_a)]);\
- pfCopyVec3(geom->coords[1], coords[(_b)]);\
- pfCopyVec3(geom->coords[2], coords[(_c)]);\
- pfCopyVec3(geom->coords[3], coords[(_d)]);\
- if (geom->tbind[0] == PFGS_PER_VERTEX) \
- {\
- pfCopyVec2(geom->texCoords[0][0], texCoords[(_a)]);\
- pfCopyVec2(geom->texCoords[0][1], texCoords[(_b)]);\
- pfCopyVec2(geom->texCoords[0][2], texCoords[(_c)]);\
- pfCopyVec2(geom->texCoords[0][3], texCoords[(_d)]);\
- }\
- pfdAddBldrGeom(geom, 1);\
- numQuads++;\
- }
- #define VI(_n) (node->vertices[_n]->index)
- #define CI(_n) (((LSpatchVertex *)(node->children[_n]))->index)
- static void
- makeTri(
- LSpatchNode *node,
- pfVec4 *colors,
- pfVec3 *coords,
- pfVec2 *texCoords)
- {
- unsigned int mask, leafType;
- LSpatchNode **child;
- int t;
- geom->cbind = PFGS_PER_VERTEX;
- geom->nbind = PFGS_OFF;
- geom->tbind[0] = (texCoords == NULL) ? PFGS_OFF : PFGS_PER_VERTEX;
- for(t = 1; t < 4; t++)
- geom->tbind[t] = PFGS_OFF;
- if (node->isLeaf)
- {
- leafType = 0;
- child = node->children;
- mask = 1; if (*child++ != NULL) leafType |= mask;
- mask <<= 1; if (*child++ != NULL) leafType |= mask;
- mask <<= 1; if (*child != NULL) leafType |= mask;
- switch (leafType)
- {
- case 0:
- TRI(VI(0), VI(1), VI(2));
- break;
- case 1:
- TRI(VI(0), CI(0), VI(2));
- TRI(CI(0), VI(1), VI(2));
- break;
- case 2:
- TRI(VI(1), CI(1), VI(0));
- TRI(CI(1), VI(2), VI(0));
- break;
- case 3:
- TRI(VI(0), CI(0), CI(1));
- TRI(CI(0), VI(1), CI(1));
- TRI(CI(1), VI(2), VI(0));
- break;
- case 4:
- TRI(VI(2), CI(2), VI(1));
- TRI(CI(2), VI(0), VI(1));
- break;
- case 5:
- TRI(VI(2), CI(2), CI(0));
- TRI(CI(2), VI(0), CI(0));
- TRI(CI(0), VI(1), VI(2));
- break;
- case 6:
- TRI(VI(1), CI(1), CI(2));
- TRI(CI(1), VI(2), CI(2));
- TRI(CI(2), VI(0), VI(1));
- break;
- case 7:
- TRI(VI(0), CI(0), CI(2));
- TRI(CI(0), VI(1), CI(1));
- TRI(CI(1), VI(2), CI(2));
- TRI(CI(0), CI(1), CI(2));
- break;
- }
- }
- else
- {
- /* just emit this node without recursion */
- TRI(VI(0), VI(1), VI(2));
- }
- }
- static void
- makeQuad(
- LSpatchNode *node,
- pfVec4 *colors,
- pfVec3 *coords,
- pfVec2 *texCoords)
- {
- unsigned int mask, leafType;
- LSpatchNode **child;
- geom->cbind = PFGS_PER_VERTEX;
- geom->nbind = PFGS_OFF;
- geom->tbind[0] = (texCoords == NULL) ? PFGS_OFF : PFGS_PER_VERTEX;
- if (node->isLeaf)
- {
- leafType = 0;
- child = node->children;
- mask = 1; if (*child++ != NULL) leafType |= mask;
- mask <<= 1; if (*child++ != NULL) leafType |= mask;
- mask <<= 1; if (*child++ != NULL) leafType |= mask;
- mask <<= 1; if (*child != NULL) leafType |= mask;
- switch (leafType)
- {
- case 0:
- QUAD(VI(0), VI(1), VI(2), VI(3));
- break;
- case 1:
- QUAD(VI(0), CI(0), VI(2), VI(3));
- TRI(CI(0), VI(1), VI(2));
- break;
- case 2:
- QUAD(VI(1), CI(1), VI(3), VI(0));
- TRI(CI(1), VI(2), VI(3));
- break;
- case 3:
- TRI(VI(0), CI(0), VI(3));
- TRI(CI(0), VI(1), CI(1));
- QUAD(CI(0), CI(1), VI(2), VI(3));
- break;
- case 4:
- QUAD(VI(2), CI(2), VI(0), VI(1));
- TRI(CI(2), VI(3), VI(0));
- break;
- case 5:
- QUAD(VI(0), CI(0), CI(2), VI(3));
- QUAD(CI(0), VI(1), VI(2), CI(2));
- break;
- case 6:
- TRI(VI(1), CI(1), VI(0));
- TRI(CI(1), VI(2), CI(2));
- QUAD(CI(1), CI(2), VI(3), VI(0));
- break;
- case 7:
- QUAD(VI(0), CI(0), CI(2), VI(3));
- QUAD(CI(0), CI(1), VI(2), CI(2));
- TRI(CI(0), VI(1), CI(1));
- break;
- case 8:
- QUAD(VI(3), CI(3), VI(1), VI(2));
- TRI(CI(3), VI(0), VI(1));
- break;
- case 9:
- TRI(VI(3), CI(3), VI(2));
- TRI(CI(3), VI(0), CI(0));
- QUAD(CI(3), CI(0), VI(1), VI(2));
- break;
- case 10:
- QUAD(VI(1), CI(1), CI(3), VI(0));
- QUAD(CI(1), VI(2), VI(3), CI(3));
- break;
- case 11:
- QUAD(VI(3), CI(3), CI(1), VI(2));
- QUAD(CI(3), CI(0), VI(1), CI(1));
- TRI(CI(3), VI(0), CI(0));
- break;
- case 12:
- TRI(VI(2), CI(2), VI(1));
- TRI(CI(2), VI(3), CI(3));
- QUAD(CI(2), CI(3), VI(0), VI(1));
- break;
- case 13:
- QUAD(VI(2), CI(2), CI(0), VI(1));
- QUAD(CI(2), CI(3), VI(0), CI(0));
- TRI(CI(2), VI(3), CI(3));
- break;
- case 14:
- QUAD(VI(1), CI(1), CI(3), VI(0));
- QUAD(CI(1), CI(2), VI(3), CI(3));
- TRI(CI(1), VI(2), CI(2));
- break;
- case 15:
- QUAD(VI(0), CI(0), CI(2), CI(3));
- TRI(CI(2), VI(3), CI(3));
- QUAD(VI(1), CI(1), CI(2), CI(0));
- TRI(CI(1), VI(2), CI(2));
- break;
- }
- }
- else
- {
- /* just emit this node without recursion */
- TRI(VI(0), VI(1), VI(3));
- TRI(VI(1), VI(2), VI(3));
- }
- }
- static void
- buildPolygons(
- int recursionDepth,
- int recursionLimit,
- LSpatchNode *node,
- pfVec4 *colors,
- pfVec3 *coords,
- pfVec2 *texCoords)
- {
- if (node->isLeaf || recursionDepth >= recursionLimit)
- {
- if (NODE_IS_TRIANGLE(node))
- makeTri( node, colors, coords, texCoords);
- else
- makeQuad(node, colors, coords, texCoords);
- }
- else
- {
- int i;
- for (i = 0; i < 4; i++)
- buildPolygons(recursionDepth+1, recursionLimit,
- node->children[i], colors, coords, texCoords);
- }
- }
- static int
- loadPatchVertex(
- FILE *fp,
- pfVec4 *color)
- {
- LSBpatchVertex lsbPatchVertex;
- if (fread((void *)(&lsbPatchVertex),
- sizeof(LSBpatchVertex), 1, fp) <= 0)
- return 0;
- swapLSBpatchVertex(&lsbPatchVertex);
- pfCopyVec3(*color, lsbPatchVertex.color);
- (*color)[3] = 1.0f;
- return 1;
- }
- static int
- loadTopPatchVertex(
- FILE *fp,
- pfVec4 *color,
- pfVec3 *coord,
- pfVec2 *texCoord)
- {
- if (texCoord != NULL)
- {
- LSBtopPatchVertexTextured lsbPatchVertexTextured;
- if (fread((void *)(&lsbPatchVertexTextured),
- sizeof(LSBtopPatchVertexTextured), 1, fp) <= 0)
- return 0;
- swapLSBtopPatchVertexTextured(&lsbPatchVertexTextured);
- pfCopyVec3(*coord, lsbPatchVertexTextured.coord);
- pfCopyVec3(*color, lsbPatchVertexTextured.color);
- (*color)[3] = 1.0f;
- pfCopyVec2(*texCoord, lsbPatchVertexTextured.uv);
- }
- else
- {
- LSBtopPatchVertex lsbPatchVertex;
- if (fread((void *)(&lsbPatchVertex),
- sizeof(LSBtopPatchVertex), 1, fp) <= 0)
- return 0;
- swapLSBtopPatchVertex(&lsbPatchVertex);
- pfCopyVec3(*coord, lsbPatchVertex.coord);
- pfCopyVec3(*color, lsbPatchVertex.color);
- (*color)[3] = 1.0f;
- }
- return 1;
- }
- static int
- readPatchLeaf(
- FILE *fp,
- unsigned int *verts,
- unsigned int *midVerts)
- {
- LSBpatchLeaf lsbPatchLeaf;
- LSBpatchLeaf lsbPatchLeafLong;
- if (useLongData)
- {
- if (fread((void *)(&lsbPatchLeaf),
- sizeof(LSBpatchLeaf), 1, fp) <= 0)
- return 0;
- swapLSBpatchLeaf(&lsbPatchLeaf);
- verts[0] = lsbPatchLeafLong.vertices[0];
- verts[1] = lsbPatchLeafLong.vertices[1];
- verts[2] = lsbPatchLeafLong.vertices[2];
- verts[3] = lsbPatchLeafLong.vertices[3];
- midVerts[0] = lsbPatchLeafLong.midVertices[0];
- midVerts[1] = lsbPatchLeafLong.midVertices[1];
- midVerts[2] = lsbPatchLeafLong.midVertices[2];
- midVerts[3] = lsbPatchLeafLong.midVertices[3];
- }
- else
- {
- if (fread((void *)(&lsbPatchLeaf),
- sizeof(LSBpatchLeaf), 1, fp) <= 0)
- return 0;
- swapLSBpatchLeaf(&lsbPatchLeaf);
- verts[0] = lsbPatchLeaf.vertices[0];
- verts[1] = lsbPatchLeaf.vertices[1];
- verts[2] = lsbPatchLeaf.vertices[2];
- verts[3] = lsbPatchLeaf.vertices[3];
- midVerts[0] = lsbPatchLeaf.midVertices[0];
- midVerts[1] = lsbPatchLeaf.midVertices[1];
- midVerts[2] = lsbPatchLeaf.midVertices[2];
- midVerts[3] = lsbPatchLeaf.midVertices[3];
- }
- return 1;
- }
- static LSpatchNode *
- loadPatchNodes(
- FILE *fp,
- LSpatchNode *root,
- LSpatchNode **nodes,
- LSpatchVertex *vertices)
- {
- int i, n;
- LSpatchNode *node;
- unsigned int verts[4], midVerts[4];
- switch (getc(fp))
- {
- case 'i':
- if (root != NULL)
- node = root;
- else
- {
- node = *nodes;
- (*nodes)++;
- }
- for (i = 0; i < 4; i++)
- {
- node->children[i] = loadPatchNodes(fp, NULL, nodes, vertices);
- if (node->children[i] == NULL)
- {
- node = NULL;
- break;
- }
- }
- if (node != NULL)
- {
- node->isLeaf = 0;
- if (NODE_IS_TRIANGLE(node->children[0]))
- {
- for (i = 0; i < 3; i++)
- node->vertices[i] = node->children[i]->vertices[i];
- node->vertices[3] = NULL;
- }
- else
- for (i = 0; i < 4; i++)
- node->vertices[i] = node->children[i]->vertices[i];
- }
- break;
- case 'l' :
- if (!readPatchLeaf(fp, verts, midVerts))
- return NULL;
- if (root != NULL)
- node = root;
- else
- {
- node = *nodes;
- (*nodes)++;
- }
- node->isLeaf = 1;
- node->children[3] = NULL;
- node->vertices[3] = NULL;
- n = ((verts[3] == 0) ? 3 : 4);
- for (i = 0; i < n; i++)
- {
- node->vertices[i] = &(vertices[verts[i] - 1]);
- node->children[i] = (midVerts[i] == 0)
- ? NULL
- : (LSpatchNode *)(&(vertices[midVerts[i] - 1]));
- }
- break;
- default :
- node = NULL;
- break;
- }
- return node;
- }
- static int
- readPatchCluster(FILE *fp,
- unsigned short *flags,
- pfVec4 *plane,
- unsigned int *materialId,
- unsigned int *layerId,
- unsigned int *textureId,
- unsigned int *numTopNodes,
- unsigned int *numNodes,
- unsigned int *numTopVerts,
- unsigned int *numVertices)
- {
- unsigned short clustFlags;
- unsigned short junk;
- if (fread((void *)(&clustFlags), sizeof(unsigned short), 1, fp) <= 0)
- return(0);
- if (fread((void *)(&junk), sizeof(unsigned short), 1, fp) <= 0)
- return(0);
- #ifdef __i386__
- P_16_SWAP(&clustFlags);
- P_16_SWAP(&junk);
- #endif
- if (clustFlags & LSB_BIG_CLUSTER)
- {
- LSBpatchClusterLong lsbLongCluster;
- useLongData = 1;
- if(fread((void *)(&lsbLongCluster.plane),
- (long)(sizeof(LSBpatchClusterLong))-4, 1, fp) <= 0)
- return 0;
- swapLSBpatchClusterLong(&lsbLongCluster);
- *flags = clustFlags;
- pfSetVec4(*plane,
- lsbLongCluster.plane[0],
- lsbLongCluster.plane[1],
- lsbLongCluster.plane[2],
- lsbLongCluster.plane[3]);
- *materialId = lsbLongCluster.materialId;
- *layerId = lsbLongCluster.layerId;
- *textureId = lsbLongCluster.textureId;
- *numTopNodes = lsbLongCluster.numTopNodes;
- *numNodes = lsbLongCluster.numNodes;
- *numTopVerts = lsbLongCluster.numTopVertices;
- *numVertices = lsbLongCluster.numVertices;
- }
- else
- {
- LSBpatchCluster lsbPatchCluster;
- useLongData = 0;
- if (fread((void *)(&lsbPatchCluster.plane),
- (long)(sizeof(LSBpatchCluster))-4, 1, fp) <= 0)
- return(0);
- swapLSBpatchCluster(&lsbPatchCluster);
- *flags = clustFlags;
- pfSetVec4(*plane,
- lsbPatchCluster.plane[0],
- lsbPatchCluster.plane[1],
- lsbPatchCluster.plane[2],
- lsbPatchCluster.plane[3]);
- *materialId = lsbPatchCluster.materialId;
- *layerId = lsbPatchCluster.layerId;
- *textureId = lsbPatchCluster.textureId;
- *numTopNodes = lsbPatchCluster.numTopNodes;
- *numNodes = lsbPatchCluster.numNodes;
- *numTopVerts = lsbPatchCluster.numTopVertices;
- *numVertices = lsbPatchCluster.numVertices;
- }
- return 1;
- }
- static void
- initPatchNodes(
- LSpatchNode *node,
- pfVec3 *coords,
- pfVec2 *texCoords)
- {
- unsigned int i, j, n;
- LSpatchVertex *v;
- if (!node->isLeaf)
- {
- n = NUM_NODE_VERTICES(node);
- for (i = 0; i < n; i++)
- {
- j = (i + 1) % n;
- v = node->children[i]->vertices[j];
- if (v->flags)
- {
- v->flags = 0;
- pfCombineVec3(coords[v->index],
- 0.5, coords[node->vertices[i]->index],
- 0.5, coords[node->vertices[j]->index]);
- if (texCoords != NULL)
- pfCombineVec2(texCoords[v->index],
- 0.5, texCoords[node->vertices[i]->index],
- 0.5, texCoords[node->vertices[j]->index]);
- }
- }
- if (NODE_IS_RECT(node))
- {
- v = node->children[2]->vertices[0];
- v->flags = 0;
- pfCombineVec3(coords[v->index],
- 0.5, coords[node->children[0]->vertices[1]->index],
- 0.5, coords[node->children[2]->vertices[3]->index]);
- if (texCoords != NULL)
- {
- pfCombineVec2(texCoords[v->index],
- 0.5, texCoords[node->children[0]->vertices[1]->index],
- 0.5, texCoords[node->children[2]->vertices[3]->index]);
- }
- }
- for (i = 0; i < 4; i++)
- initPatchNodes(node->children[i], coords, texCoords);
- }
- }
- static int
- readClusters(
- FILE *fp,
- LSBheader *lsbHeader,
- LSmaterial *materials,
- LSlayer *layers,
- LStexture *textures,
- int recursionLimit
- )
- {
- unsigned short flags;
- unsigned int i, j, k;
- unsigned int materialId, layerId, textureId;
- unsigned int numOtherVertices, numTopVerts, numVerts, numTopNodes, numNodes;
- pfVec4 plane, *curColor;
- pfVec3 *curCoord;
- pfVec2 *curTexCoord;
- LSpatchVertex *curVertex;
- LSpatchNode *curTopNode, *curNode;
- LSpatchCluster thisPatchCluster;
- LSpatchCluster *curCluster = &thisPatchCluster;
- int nodeCount = 256;
- int vertexCount = 256;
- LSpatchNode *nodes = pfCalloc(nodeCount, sizeof(LSpatchNode), NULL);
- LSpatchVertex
- *vertices = pfCalloc(vertexCount, sizeof(LSpatchVertex), NULL);
- pfVec4 *pfColors = pfCalloc(vertexCount, sizeof(pfVec4), NULL);
- pfVec3 *pfCoords = pfCalloc(vertexCount, sizeof(pfVec3), NULL);
- pfVec2 *pfTexCoords = pfCalloc(vertexCount, sizeof(pfVec2), NULL);
- for (i = 0; i < lsbHeader->numPatchClusters; i++)
- {
- if (!readPatchCluster(fp, &flags, &plane, &materialId, &layerId,
- &textureId, &numTopNodes, &numNodes, &numTopVerts, &numVerts))
- {
- if (nodes != NULL) pfFree(nodes);
- if (vertices != NULL) pfFree(vertices);
- if (pfColors != NULL) pfFree(pfColors);
- if (pfCoords != NULL) pfFree(pfCoords);
- if (pfTexCoords != NULL) pfFree(pfTexCoords);
- return 0;
- }
- curCluster->flags = flags;
- pfCopyVec4(curCluster->plane, plane);
- if (materialId == 0)
- curCluster->material = NULL;
- else
- curCluster->material = &(materials[materialId - 1]);
- /* specify layer for this cluster */
- #ifdef BUILD_LAYERS_INDEPENDENTLY
- if (layerId == 0)
- {
- curCluster->layer = NULL;
- pfdSelectBldrName(defaultLayerName);
- }
- else
- {
- curCluster->layer = &(layers[layerId - 1]);
- pfdSelectBldrName(curCluster->layer->name);
- }
- #endif
- /* specify texture for this cluster */
- if (textureId == 0)
- {
- curCluster->texture = NULL;
- pfdBldrStateAttr(PFSTATE_TEXTURE, NULL);
- pfdBldrStateMode(PFSTATE_ENTEXTURE, PFTR_OFF);
- }
- else
- {
- pfTexture *tex = (pfTexture *)
- pfdGetTemplateObject(pfGetTexClassType());
- curCluster->texture = &(textures[textureId - 1]);
- pfTexName(tex, curCluster->texture->name);
- pfdBldrStateAttr(PFSTATE_TEXTURE, tex);
- pfdBldrStateMode(PFSTATE_ENTEXTURE, PFTR_ON);
- }
- /* update vertex-count array sizes and pointers */
- if (vertexCount < numVerts)
- {
- vertexCount = numVerts;
- pfColors = pfRealloc(pfColors, vertexCount*sizeof(pfVec4));
- if (pfColors == NULL)
- return 0;
- pfCoords = pfRealloc(pfCoords, vertexCount*sizeof(pfVec3));
- if (pfCoords == NULL)
- return 0;
- pfTexCoords = pfRealloc(pfTexCoords, vertexCount*sizeof(pfVec2));
- if (pfTexCoords == NULL)
- return 0;
- vertices = pfRealloc(vertices, numVerts*sizeof(LSpatchVertex));
- if (vertices == NULL)
- return 0;
- }
- curColor = pfColors;
- curCoord = pfCoords;
- curVertex = vertices;
- curTexCoord = (curCluster->flags & LSB_TEXTURED) ? pfTexCoords : NULL;
- /* update node-count array sizes and pointers */
- if (nodeCount < numNodes)
- {
- nodeCount = numNodes;
- nodes = pfRealloc(nodes, numNodes*sizeof(LSpatchNode));
- if (nodes == NULL)
- return 0;
- }
- curTopNode = nodes;
- numOtherVertices = numVerts - numTopVerts;
- for (j = 0; j < numOtherVertices; j++, curColor++, curCoord++, curVertex++)
- {
- if (!loadPatchVertex(fp, curColor))
- return 0;
- curVertex->flags = 1; /* means that geometry needs to be initialized */
- curVertex->index = j;
- if (curCluster->flags & LSB_TEXTURED)
- curTexCoord++;
- }
- for (j = 0; j < numTopVerts; j++, curColor++, curCoord++, curVertex++)
- {
- if (!loadTopPatchVertex(fp, curColor, curCoord, curTexCoord))
- return 0;
- curVertex->flags = 0;
- curVertex->index = numOtherVertices + j;
- if (curCluster->flags & LSB_TEXTURED)
- curTexCoord++;
- }
- /* temporary node info */
- curNode = nodes + numTopNodes;
- for (j = 0; j < numTopNodes; j++, curTopNode++)
- if (!loadPatchNodes(fp, curTopNode, &curNode, vertices))
- return 0;
- /* initialize geometry */
- for (j = 0, curTopNode = nodes; j < numTopNodes; j++, curTopNode++)
- initPatchNodes(curTopNode, pfCoords, pfTexCoords);
- /* create geometry */
- if (curCluster->flags & LSB_TEXTURED)
- for (k = 0, curTopNode = nodes; k < numTopNodes; k++, curTopNode++)
- buildPolygons(0, recursionLimit, curTopNode, pfColors, pfCoords, pfTexCoords);
- else
- for (k = 0, curTopNode = nodes; k < numTopNodes; k++, curTopNode++)
- buildPolygons(0, recursionLimit, curTopNode, pfColors, pfCoords, NULL);
- /* go ahead and build this cluster's geometry */
- if ((clustersPerGeode > 0) &&
- ( ((clustersPerGeode == 1) || ((i > 0) && (i % clustersPerGeode) == 0)) ||
- (i == lsbHeader->numPatchClusters - 1)) )
- pfAddChild(groupNode, pfdBuild());
- }
- if (nodes != NULL) pfFree(nodes);
- if (vertices != NULL) pfFree(vertices);
- if (pfColors != NULL) pfFree(pfColors);
- if (pfCoords != NULL) pfFree(pfCoords);
- if (pfTexCoords != NULL) pfFree(pfTexCoords);
- return 1;
- }
- static int
- readSignature(FILE *fp)
- {
- char line[256];
- static char *signature = LSB_SIGNATURE;
- /* read LSB signature */
- if (fgets(line, 256, fp) == NULL)
- return 0;
- if (strncmp(signature, line, strlen(signature)) != 0)
- return 0;
- /* scan past signature data */
- do
- {
- if (fgets(line, 256, fp) == NULL)
- return 0;
- }
- while (line[0] != LSB_BEGIN_CHAR);
- /* indicate success */
- return 1;
- }
- static int
- readHeader(FILE *fp, LSBheader *header)
- {
- if (fread((void *)header, sizeof(LSBheader), 1, fp) <= 0)
- return 0;
- swapLSBheader(header);
- /* indicate success */
- return 1;
- }
- static int
- readMaterials(FILE *fp, void *arena, unsigned int nmaterials,
- LSmaterial **materials)
- {
- unsigned int i;
- char line[256];
- /* check input arguments */
- if (nmaterials < 1 || materials == NULL)
- return 1;
- /* allocate an array of LSmaterial structures */
- *materials = (LSmaterial *)
- pfCalloc(nmaterials, sizeof(LSmaterial), arena);
- if (*materials == NULL)
- return 0;
- /* read material information */
- pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "Materials");
- for (i = 0; i < nmaterials; i++)
- {
- if (fgets(line, 256, fp) == NULL)
- return 0;
- line[strlen(line) - 1] = '\0';
- (*materials)[i].name = strdup(line);
- pfNotify(PFNFY_DEBUG, PFNFY_PRINT, " %2d: %s", i, line);
- }
- /* indicate success */
- return 1;
- }
- static int
- deallocateMaterials(unsigned int nmaterials, LSmaterial **materials)
- {
- unsigned int i;
- /* no materials means nothing to deallocate */
- if (nmaterials < 1 || materials == NULL || *materials == NULL)
- return 1;
- /* delete each material's data */
- for (i = 0; i < nmaterials; i++)
- if ((*materials)[i].name != NULL)
- free((*materials)[i].name);
- /* reset material array pointer */
- pfFree(*materials);
- *materials = NULL;
- /* indicate success */
- return 1;
- }
- static int
- readLayers(FILE *fp, void *arena, unsigned int nlayers, LSlayer **layers)
- {
- unsigned int i;
- char line[256];
- /* check input arguments */
- if (nlayers < 1 || layers == NULL)
- return 1;
- /* allocate an array of LSlayer structures */
- *layers = (LSlayer *)pfCalloc(nlayers, sizeof(LSlayer), arena);
- if (*layers == NULL)
- return 0;
- /* read layer information */
- pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "Layers");
- for (i = 0; i < nlayers; i++)
- {
- if (fgets(line, 256, fp) == NULL)
- return 0;
- line[strlen(line) - 1] = '\0';
- (*layers)[i].name = strdup(line);
- pfNotify(PFNFY_DEBUG, PFNFY_PRINT, " %2d: %s", i, line);
- }
- /* indicate success */
- return 1;
- }
- static int
- deallocateLayers(unsigned int nlayers, LSlayer **layers)
- {
- unsigned int i;
- /* no layers means nothing to deallocate */
- if (layers == NULL || *layers == NULL)
- return 1;
- /* delete each layer's data */
- for (i = 0; i < nlayers; i++)
- if ((*layers)[i].name != NULL)
- free((*layers)[i].name);
- /* reset layer array pointer */
- pfFree(*layers);
- *layers = NULL;
- /* indicate success */
- return 1;
- }
- static int
- readTextures(FILE *fp, void *arena, unsigned int ntextures,
- LStexture **textures)
- {
- unsigned int i;
- char line[256];
- /* check input arguments */
- if (ntextures < 1 || textures == NULL)
- return 1;
- /* allocate an array of LStexture structures */
- *textures = (LStexture *)pfCalloc(ntextures, sizeof(LStexture), arena);
- if (*textures == NULL)
- return 0;
- /* read texture information */
- pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "Textures");
- for (i = 0; i < ntextures; i++)
- {
- if (fgets(line, 256, fp) == NULL)
- return 0;
- line[strlen(line) - 1] = '\0';
- (*textures)[i].name = strdup(line);
- pfNotify(PFNFY_DEBUG, PFNFY_PRINT, " %2d: %s", i, line);
- }
- /* indicate success */
- return 1;
- }
- static int
- deallocateTextures(unsigned int ntextures, LStexture **textures)
- {
- unsigned int i;
- /* no textures means nothing to deallocate */
- if (textures == NULL || *textures == NULL)
- return 1;
- /* delete each textures's data */
- for (i = 0; i < ntextures; i++)
- if ((*textures)[i].name != NULL)
- free((*textures)[i].name);
- /* reset texture array pointer */
- pfFree(*textures);
- *textures = NULL;
- /* indicate success */
- return 1;
- }
- /*
- * pfdLoadFile_lsb -- Load Lightscape ".lsb" files into IRIS Performer
- */
- extern pfNode *
- pfdLoadFile_lsb (char *fileName)
- {
- FILE *lsbFile = NULL;
- pfNode *node = NULL;
- LSmaterial *materials = NULL;
- LSlayer *layers = NULL;
- LStexture *textures = NULL;
- LSpatchCluster *clusters = NULL;
- LSBheader lsbHeader;
- int recursionLimit = 0;
- char *ep = NULL;
- double startTime = pfGetTime();
- double elapsedTime = 0.0;
- /* restore builder to initial state */
- pfdResetBldrGeometry();
- pfdResetBldrState();
- /* open ".lsb" file */
- if ((lsbFile = pfdOpenFile(fileName)) == NULL)
- {
- pfNotify(PFNFY_WARN, PFNFY_RESOURCE,
- "pfdLoadFile_lsb: error opening file \"%s\"", fileName);
- return NULL;
- }
- /* read ".lsb" file "signature" section */
- if (!readSignature(lsbFile))
- {
- pfNotify(PFNFY_WARN, PFNFY_RESOURCE,
- "pfdLoadFile_lsb: error reading signature from \"%s\"", fileName);
- fclose(lsbFile);
- return NULL;
- }
- /* read ".lsb" file "header" section */
- if (!readHeader(lsbFile, &lsbHeader))
- {
- pfNotify(PFNFY_WARN, PFNFY_RESOURCE,
- "pfdLoadFile_lsb: error reading header from \"%s\"", fileName);
- fclose(lsbFile);
- return NULL;
- }
- /* update recursion limit from environment variable */
- if ((ep = getenv("LS_RECURSION_LIMIT")) != NULL)
- sscanf(ep, "%d", &recursionLimit);
- /* update clusters-per-geode from environment variable */
- if ((ep = getenv("LS_CLUSTERS_PER_GEODE")) != NULL)
- sscanf(ep, "%d", &clustersPerGeode);
- /* update spatial size from environment variable */
- if ((ep = getenv("LS_SPATIAL_SIZE")) != NULL)
- sscanf(ep, "%f", &spatialSize);
- /* update spatial count from environment variable */
- if ((ep = getenv("LS_SPATIAL_COUNT")) != NULL)
- sscanf(ep, "%d", &spatialCount);
- /* update file search path from environment variable */
- if ((ep = getenv("LS_TEXTURE_PATH")) != NULL)
- {
- const char *op = pfGetFilePath();
- char *np = NULL;
- if (op == NULL)
- op = "";
- np = (char *)pfMalloc(strlen(op) + 1 + strlen(ep) + 1, NULL);
- strcpy(np, ep);
- strcat(np, ":");
- strcat(np, op);
- pfFilePath(np);
- pfFree(np);
- }
- /* disable lighting (that's what radiosity is all about ;-) */
- pfdBldrStateMode(PFSTATE_ENLIGHTING, PF_OFF);
- pfdBldrStateMode(PFSTATE_CULLFACE, PFCF_BACK);
- /* disable undesired automatic builder actions */
- pfdBldrMode(PFDBLDR_AUTO_NORMALS, PF_OFF);
- pfdBldrMode(PFDBLDR_AUTO_ORIENT, PF_OFF);
- /* parent group for "build-clumps-of-clusters" mode */
- if (clustersPerGeode > 0)
- groupNode = pfNewGroup();
- /* reset global geometry counters */
- numTris = 0;
- numQuads = 0;
- /* allocate geometry buffer structure */
- geom = pfdNewGeom(geomSize = 256);
- /* read ".lsb" file materials, layers, textures, and clusters */
- if (readMaterials(lsbFile, NULL, lsbHeader.numMaterials, &materials) &&
- readLayers (lsbFile, NULL, lsbHeader.numLayers, &layers) &&
- readTextures (lsbFile, NULL, lsbHeader.numTextures, &textures) &&
- readClusters (lsbFile, &lsbHeader, materials, layers, textures, recursionLimit))
- {
- /* build scene graph of file's primitives unless it's already built */
- if (clustersPerGeode > 0)
- node = (pfNode *)groupNode;
- else
- node = pfdBuild();
- /* construct spatial octree hierarchy from geosets in scene graph */
- if (spatialSize != 0.0f || spatialCount != 0)
- {
- pfGroup *group = pfNewGroup();
- pfAddChild(group, node);
- node = (pfNode *)pfdSpatialize(group, spatialSize, spatialCount);
- }
- /* use file name name for top-level pfNode */
- if (node != NULL)
- pfNodeName(node, fileName);
- /* print statistics */
- pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "pfdLoadFile_lsb: %s", fileName);
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Configuration Data:");
- if (ep != NULL)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Texture path: %s", ep);
- if (recursionLimit > 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Recursion limit: %8ld",
- recursionLimit);
- if (clustersPerGeode > 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Clusters per geode: %8ld",
- clustersPerGeode);
- if (lsbHeader.numMaterials != 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Input materials: %8ld",
- lsbHeader.numMaterials);
- if (lsbHeader.numLayers != 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Input layers: %8ld",
- lsbHeader.numLayers);
- if (lsbHeader.numTextures != 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Input textures: %8ld",
- lsbHeader.numTextures);
- if (lsbHeader.numPatchClusters != 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Input clusters: %8ld",
- lsbHeader.numPatchClusters);
- if (numTris != 0 || numQuads != 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Input Data:");
- if (numTris != 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Input triangles: %8ld",
- numTris);
- if (numQuads != 0)
- pfNotify(PFNFY_INFO, PFNFY_MORE, " Input quads: %8ld",
- numQuads);
- }
- /* close input file */
- fclose(lsbFile);
- /* release allocated storage */
- deallocateMaterials(lsbHeader.numMaterials, &materials);
- deallocateLayers (lsbHeader.numLayers, &layers);
- deallocateTextures (lsbHeader.numTextures, &textures);
- /* release storage allocated for geometric primitives */
- pfdDelGeom(geom);
- /* release storage allocated by the builder */
- pfdResetBldrGeometry();
- /* return root node to caller */
- return node;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement