#include #include #include "libs.h" #include "model_coll_mesh_data.h" #include "sbre/sbre.h" #include "collider/collider.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 { 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 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); 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++; meshInfo[midx].flags = flag; meshInfo[midx].triStart = tidx; meshInfo[midx].numTris = len; midx++; 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, ¶ms); /* 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]; } } m_geomTree = new GeomTree(sbreCollMesh->nv, sbreCollMesh->ni/3, sbreCollMesh->pVertex, sbreCollMesh->pIndex, sbreCollMesh->pFlag); 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::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; }