229 lines
5.7 KiB
C
229 lines
5.7 KiB
C
/*
|
|
* 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 <GL/gl.h>
|
|
#include <math.h>
|
|
#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;
|
|
}
|
|
|
|
|
|
|