Lephisto/src/model_coll_mesh_data.cpp

114 lines
3.7 KiB
C++

#include <map>
#include <algorithm>
#include "libs.h"
#include "model_coll_mesh_data.h"
#include "sbre/sbre.h"
/*
* In order to do space station doors and other flagged bits of collision
* meshes, we have to make a different dTriMeshData for each.
* Vertex indices for each flagged bit of the mesh need to be contiguous,
* so we waste some time and memory making this so.
*/
struct coltri_compare : public std::binary_function<coltri_t, coltri_t, bool> {
bool operator()(coltri_t a, coltri_t b) { return a.flags < b.flags; }
};
static ObjParams params = {
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0.f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
/* pColor[3]. */
{
{ { 1.0f, 0.0f, 1.0f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
{ { 0.8f, 0.6f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
{ { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 }
},
/* pText[3][256]. */
{ "", "" },
};
/* Indexed by sbre model ID. */
static std::map<int, CollMeshSet*> modelCollStuff;
void CollMeshSet::GetMeshParts(void) {
numMeshParts = 1;
int curFlag = triIndices[0].flags;
for(int i = 0; i < sbreCollMesh->ni/3; i++) {
if(curFlag != triIndices[i].flags) numMeshParts++;
curFlag = triIndices[i].flags;
}
//printf("%d parts\n", numMeshParts);
meshParts = new dTriMeshDataID[numMeshParts];
meshInfo = new meshinfo_t[numMeshParts];
int tidx = 0;
int midx = 0;
do {
int len = 0;
int flag = triIndices[tidx].flags;
while((len < sbreCollMesh->ni/3) && (triIndices[tidx+len].flags == flag)) len++;
//printf("%d: len %d\n", tidx, len);
dTriMeshDataID triMeshDataID = dGeomTriMeshDataCreate();
dGeomTriMeshDataBuildSingle(triMeshDataID, (void*)sbreCollMesh->pVertex,
3*sizeof(float), sbreCollMesh->nv, (void*)&triIndices[tidx],
3*len, 4*sizeof(int));
meshInfo[midx].flags = flag;
meshInfo[midx].triStart = tidx;
meshInfo[midx].numTris = len;
meshParts[midx++] = triMeshDataID;
tidx += len;
} while(tidx < sbreCollMesh->ni/3);
}
CollMeshSet::CollMeshSet(int sbreModel) {
aabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
aabb.max = vector3d(-FLT_MIN, -FLT_MIN, -FLT_MIN);
sbreCollMesh = (CollMesh*)calloc(1, sizeof(CollMesh));
sbreGenCollMesh(sbreCollMesh, sbreModel, &params);
/* TODO: Flip Z & X because sbre is in magicspace. */
for(int i = 0; i < 3*sbreCollMesh->nv; i += 3) {
sbreCollMesh->pVertex[i] = -sbreCollMesh->pVertex[i];
sbreCollMesh->pVertex[i+2] = -sbreCollMesh->pVertex[i+2];
/* Make axis aligned bounding box. */
for(int a = 0; a < 3; a++) {
if(sbreCollMesh->pVertex[i+a] < aabb.min[a])
aabb.min[a] = sbreCollMesh->pVertex[i+a];
if(sbreCollMesh->pVertex[i+a] < aabb.max[a])
aabb.max[a] = sbreCollMesh->pVertex[i+a];
}
}
triIndices = new coltri_t[sbreCollMesh->ni/3];
int tidx = 0;
/* Copy the tri indices into our lovely coltri_t array. */
for(int i = 0; i < sbreCollMesh->ni; i += 3) {
triIndices[tidx].v1 = sbreCollMesh->pIndex[i];
triIndices[tidx].v2 = sbreCollMesh->pIndex[i+1];
triIndices[tidx].v3 = sbreCollMesh->pIndex[i+2];
triIndices[tidx].flags = sbreCollMesh->pFlag[i/3];
tidx++;
}
/* Sort collmesh tris by flag, ascending. */
sort(triIndices, triIndices+(sbreCollMesh->ni/3), coltri_compare());
GetMeshParts();
}
CollMeshSet* GetModelCollMeshSet(int sbreModel) {
std::map<int, CollMeshSet*>::iterator it = modelCollStuff.find(sbreModel);
if(it != modelCollStuff.end()) return (*it).second;
CollMeshSet* cstuff = new CollMeshSet(sbreModel);
modelCollStuff[sbreModel] = cstuff;
return cstuff;
}
CollMesh* GetModelSBRECollMesh(int sbreModel) {
return modelCollStuff[sbreModel]->sbreCollMesh;
}