Files
pvvmud/util/asc2bog/writebog.c
2025-03-05 08:37:43 +01:00

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;
}