/* * PVVMUD a 3D MUD * Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include "globals.h" #include "writebog.h" #include "geometry.H" #include "namedb.H" void countElements(TreeNode_t * node, WORD * numV, WORD * numN, WORD * numTC, WORD * numP){ if (node == NULL) return; switch (node->nodeKind){ case GeometryK: countElements(node->child[1],numV,numN,numTC,numP); break; case ObjectK: countElements(node->child[1],numV,numN,numTC,numP); countElements(node->sibling,numV,numN,numTC,numP); break; case VertexK: (*numV)++; countElements(node->sibling,numV,numN,numTC,numP); break; case UVMappingK: (*numTC)++; countElements(node->sibling,numV,numN,numTC,numP); break; case FaceK: (*numN)++; countElements(node->sibling,numV,numN,numTC,numP); break; case MaterialK: case SmoothingK: countElements(node->sibling,numV,numN,numTC,numP); break; case TriMeshK: (*numP)++; countElements(node->child[1],numV,numN,numTC,numP); countElements(node->child[2],numV,numN,numTC,numP); countElements(node->sibling,numV,numN,numTC,numP); break; } } void CalcNorm(CGeometry * geo,float * xx, float * yy,float * zz, int v1, int v2, int v3){ double dx1,dy1,dz1,dx2,dy2,dz2; double v1x,v1y,v1z,v2x,v2y,v2z,v3x,v3y,v3z; double x,y,z,l; geo->getVertex(v1,&v1x,&v1y,&v1z); geo->getVertex(v2,&v2x,&v2y,&v2z); geo->getVertex(v3,&v3x,&v3y,&v3z); dx1 = v1x - v2x; dy1 = v1y - v2y; dz1 = v1z - v2z; dx2 = v2x - v3x; dy2 = v2y - v3y; dz2 = v2z - v3z; x = dy1*dz2 - dy2*dz1; y = dx2*dz1 - dx1*dz2; z = dx1*dy2 - dx2*dy1; l = sqrt(x*x+y*y+z*z); *xx = x/l; *yy = y/l; *zz = z/l; } int * vertexIndexMap; CPolygon * poly; int normalIndex; int * normalIndexMap; int * texCoordIndexMap; int texCoordIndex; CNameDB * nameDB; void buildGeo(CGeometry * geo, TreeNode_t * node){ int ii,index,v1,v2,v3; int numVertices,numFaces,numTexCoords; float xx,yy,zz; if (node == NULL) return; switch (node->nodeKind){ case GeometryK: vertexIndexMap = NULL; normalIndex = 0; buildGeo(geo,node->child[1]); break; case ObjectK: buildGeo(geo,node->child[1]); buildGeo(geo,node->sibling); break; case TriMeshK: buildGeo(geo,node->child[0]); buildGeo(geo,node->child[1]); buildGeo(geo,node->child[2]); geo->addPolygon(poly); break; case TriMeshHeadK: if (vertexIndexMap != NULL) free(vertexIndexMap); if (texCoordIndexMap != NULL) free(texCoordIndexMap); numVertices = node->child[0]->attr.num; numFaces = node->child[1]->attr.num; numTexCoords = (node->attr.mapped ? numFaces*3 : 0 ); vertexIndexMap = (int *)malloc( numVertices * sizeof(int) ); if (numTexCoords != 0){ texCoordIndexMap = (int *)malloc( numTexCoords * sizeof(int) ); } else texCoordIndexMap = NULL; poly = new CPolygon( PT_Triangles , 0, numFaces*3, numFaces, numTexCoords ); break; case VertexK: index = node->child[0]->attr.num; xx = node->child[1]->attr.value; yy = node->child[2]->attr.value; zz = node->child[3]->attr.value; vertexIndexMap[index] = geo->addVertex(xx,yy,zz); texCoordIndex = index; buildGeo(geo,node->sibling); break; case FaceK: v1 = node->child[1]->attr.num; v2 = node->child[2]->attr.num; v3 = node->child[3]->attr.num; poly->addVertexIndex(vertexIndexMap[v1]); poly->addVertexIndex(vertexIndexMap[v2]); poly->addVertexIndex(vertexIndexMap[v3]); if (texCoordIndexMap != NULL){ poly->addTexCoordIndex(texCoordIndexMap[v1]); poly->addTexCoordIndex(texCoordIndexMap[v2]); poly->addTexCoordIndex(texCoordIndexMap[v3]); } /* Calculate Normal vector to Face */ CalcNorm(geo,&xx,&yy,&zz,vertexIndexMap[v1], vertexIndexMap[v2],vertexIndexMap[v3]); normalIndexMap[normalIndex] = geo->addNormal(xx,yy,zz); poly->addNormalIndex(normalIndexMap[normalIndex]); normalIndex++; buildGeo(geo,node->sibling); break; case MaterialK: poly->setMaterial(nameDB->insert(node->attr.name)); buildGeo(geo,node->sibling); break; case SmoothingK: buildGeo(geo,node->sibling); break; case UVMappingK: xx = node->child[0]->attr.value; yy = node->child[1]->attr.value; if (texCoordIndexMap != NULL){ texCoordIndexMap[texCoordIndex] = geo->addTexCoord(xx,yy); } buildGeo(geo,node->sibling); break; } } void writebogfile(TreeNode_t * node, FILE * bogfile, FILE * ndbfile ){ WORD numVertices,numNormals,numTexCoords,numPolygons; CGeometry * geo; numVertices = 0; numNormals = 0; numTexCoords = 0; numPolygons = 0; countElements(node,&numVertices,&numNormals,&numTexCoords,&numPolygons); geo = new CGeometry(0,numVertices,numNormals, numTexCoords,numPolygons); normalIndexMap = (int *)malloc( numNormals * sizeof(int) ); nameDB = new CNameDB(); buildGeo(geo,node); geo->writeBOG(bogfile); nameDB->writeNDB(ndbfile); delete geo; delete nameDB; }