From d5cd91e02bb4442ddfd42feb2bf3ade0026e00ca Mon Sep 17 00:00:00 2001 From: Rtch90 Date: Sun, 19 Nov 2017 19:50:06 +0000 Subject: [PATCH] [Change] Get the collision geom flags through to the collision detection.. --- src/Makefile.am | 4 +- src/model_coll_mesh_data.cpp | 102 +++++++++++++++++++++++++++++++++++ src/model_coll_mesh_data.h | 24 +++++++++ src/object.h | 2 +- src/sbre/models.cpp | 8 +-- src/ship.cpp | 5 +- src/space.cpp | 19 +++++-- src/space_station.cpp | 4 +- src/static_rigid_body.cpp | 79 ++++++++++++++------------- src/static_rigid_body.h | 17 ++++-- 10 files changed, 207 insertions(+), 57 deletions(-) create mode 100644 src/model_coll_mesh_data.cpp create mode 100644 src/model_coll_mesh_data.h diff --git a/src/Makefile.am b/src/Makefile.am index 797898d..cec8087 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ Lephisto3D_SOURCES = main.cpp gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cp gui_image_radio_button.cpp gui_multi_state_image_button.cpp ship_cpanel.cpp gui_widget.cpp sector_view.cpp \ mtrand.cpp world_view.cpp system_view.cpp star_system.cpp sector.cpp system_info_view.cpp generic_system_view.cpp \ gui_container.cpp date.cpp space_station.cpp space_station_view.cpp static_rigid_body.cpp ship_type.cpp \ - info_view.cpp + info_view.cpp model_coll_mesh_data.cpp Lephisto3D_LDADD = sbre/libsbre.a include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h gui_container.h gui_events.h gui_fixed.h \ @@ -16,5 +16,5 @@ include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h gui_radio_group.h gui_screen.h gui_toggle_button.h gui_widget.h libs.h matrix4x4.h mtrand.h objimport.h l3d.h \ planet.h player.h rigid_body.h sector.h sector_view.h ship_cpanel.h ship.h space.h star.h star_system.h system_info_view.h \ system_view.h vector3.h view.h world_view.h date.h space_station.h space_station_view.h static_rigid_body.h gui_iselectable.h \ - ship_type.h object.h info_view.h + ship_type.h object.h info_view.h model_coll_mesh_data.h diff --git a/src/model_coll_mesh_data.cpp b/src/model_coll_mesh_data.cpp new file mode 100644 index 0000000..9e91084 --- /dev/null +++ b/src/model_coll_mesh_data.cpp @@ -0,0 +1,102 @@ +#include +#include +#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 { + bool operator()(coltri_t a, coltri_t b) { return a.flags < b.flags; } +}; + +static ObjParams params = { + { 0.5, 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); + meshParts = new dTriMeshDataID[numMeshParts]; + meshFlags = new int[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)); + meshFlags[midx] = flag; + meshParts[midx++] = triMeshDataID; + tidx += len; + } while(tidx < sbreCollMesh->ni/3); +} + +CollMeshSet::CollMeshSet(int sbreModel) { + 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]; + } + + 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; +} + diff --git a/src/model_coll_mesh_data.h b/src/model_coll_mesh_data.h new file mode 100644 index 0000000..889a909 --- /dev/null +++ b/src/model_coll_mesh_data.h @@ -0,0 +1,24 @@ +#pragma once +#include "libs.h" +#include "sbre/sbre.h" + +struct coltri_t { + int v1, v2, v3, flags; +}; + +class CollMeshSet { +public: + CollMesh* sbreCollMesh; + coltri_t* triIndices; + dTriMeshDataID* meshParts; + int* meshFlags; + int numMeshParts; + + CollMeshSet(int sbreModel); +private: + void GetMeshParts(void); +}; + +CollMeshSet* GetModelCollMeshSet(int sbreModel); +CollMesh* GetModelSBRECollMesh(int sbreModel); + diff --git a/src/object.h b/src/object.h index b1874f3..925393e 100644 --- a/src/object.h +++ b/src/object.h @@ -2,7 +2,7 @@ class Object { public: - enum Type { NONE, BODY, SHIP, SPACESTATION, LASER }; + enum Type { NONE, BODY, SHIP, SPACESTATION, LASER, GEOM }; virtual Type GetType(void) = 0; }; diff --git a/src/sbre/models.cpp b/src/sbre/models.cpp index 3923db6..24a9d21 100644 --- a/src/sbre/models.cpp +++ b/src/sbre/models.cpp @@ -672,10 +672,10 @@ static PlainVertex station1vtx1[] = { { VTYPE_PLAIN, { 0.0f, 0.0f, 25.0f } }, /* 34, ring start, end. */ { VTYPE_PLAIN, { 0.0f, 0.0f, -25.0f } }, - { VTYPE_PLAIN, { -10.0f, 5.0f, 10.0f } }, - { VTYPE_PLAIN, { 10.0f, 5.0f, 10.0f } }, /* 36, inlet middle (for docking). */ - { VTYPE_PLAIN, { 10.0f, -5.0f, 10.0f } }, - { VTYPE_PLAIN, { -10.0f, -5.0f, 10.0f } }, + { VTYPE_PLAIN, { -9.0f, 4.5f, 10.0f } }, + { VTYPE_PLAIN, { 9.0f, 4.5f, 10.0f } }, /* 36, inlet middle (for docking). */ + { VTYPE_PLAIN, { 9.0f, -4.5f, 10.0f } }, + { VTYPE_PLAIN, { -9.0f, -4.5f, 10.0f } }, #if 0 { VTYPE_PLAIN, { 0.0f, 120.0f, 15.0f } }, /* 34, ring top. */ diff --git a/src/ship.cpp b/src/ship.cpp index 2169ed6..fd5a080 100644 --- a/src/ship.cpp +++ b/src/ship.cpp @@ -4,6 +4,7 @@ #include "l3d.h" #include "world_view.h" #include "space.h" +#include "model_coll_mesh_data.h" static ObjParams params = { { 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, @@ -38,8 +39,8 @@ Ship::Ship(ShipType::Type shipType) : RigidBody() { memset(m_thrusters, 0, sizeof(m_thrusters)); const ShipType& stype = GetShipType(); SetGeomFromSBREModel(stype.sbreModel, ¶ms); - SetMassDistributionFromCollMesh(sbreCollMesh); - dGeomSetBody(m_geom, m_body); + SetMassDistributionFromCollMesh(GetModelSBRECollMesh(stype.sbreModel)); + GeomsSetBody(m_body); UpdateMass(); } diff --git a/src/space.cpp b/src/space.cpp index 06f9ba9..88d275e 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -132,7 +132,9 @@ static bool _OnCollision(dGeomID g1, dGeomID g2, Object* o1, Object* o2, } Ship::LaserObj* lobj = static_cast(o2); if(o1 == lobj->owner) return false; - printf("%s was shot by %s\n", ((Body*)o1)->GetLabel().c_str(), lobj->owner->GetLabel().c_str()); + printf("%s (geom flag %x) was shot by %s\n", ((StaticRigidBody::Geom*)o1)->parent->GetLabel().c_str(), + ((StaticRigidBody::Geom*)o1)->flags, lobj->owner->GetLabel().c_str()); + if(o1->GetType() == Object::SHIP) { RigidBody* rb = (RigidBody*)o1; dVector3 start, dir; @@ -147,8 +149,19 @@ static bool _OnCollision(dGeomID g1, dGeomID g2, Object* o1, Object* o2, } return false; } else { - Body* pb1 = static_cast(o1); - Body* pb2 = static_cast(o2); + Body* pb1, *pb2; + int flags = 0; + /* Geom bodies point to their parents. */ + if(o1->GetType() == Object::GEOM) { + pb1 = static_cast(o1)->parent; + flags |= static_cast(o1)->flags; + } else pb1 = static_cast(o1); + if(o2->GetType() == Object::GEOM) { + pb2 = static_cast(o2)->parent; + flags |= static_cast(o2)->flags; + } else pb2 = static_cast(o2); + + printf("Collision flags %x\n", flags); if((pb1 && !pb1->OnCollision(pb2)) || (pb2 && !pb2->OnCollision(pb1))) return false; } return true; diff --git a/src/space_station.cpp b/src/space_station.cpp index 15eb553..5279ced 100644 --- a/src/space_station.cpp +++ b/src/space_station.cpp @@ -25,8 +25,8 @@ SpaceStation::SpaceStation(void) : StaticRigidBody() { matrix4x4d m = matrix4x4d::RotateYMatrix(-M_PI/4); dMatrix3 _m; m.SaveToOdeMatrix(_m); - dGeomSetRotation(m_geom, _m); - dGeomSetBody(m_geom, 0); + //dGeomSetRotation(m_geom, _m); + //dGeomSetBody(m_geom, 0); } SpaceStation::~SpaceStation(void) { diff --git a/src/static_rigid_body.cpp b/src/static_rigid_body.cpp index 4a6e9a5..c8a1bea 100644 --- a/src/static_rigid_body.cpp +++ b/src/static_rigid_body.cpp @@ -5,51 +5,44 @@ #include "frame.h" #include "l3d.h" #include "world_view.h" +#include "model_coll_mesh_data.h" StaticRigidBody::StaticRigidBody(void): Body() { - m_geom = 0; - sbreCollMesh = 0; triMeshLastMatrixIndex = 0; } StaticRigidBody::~StaticRigidBody(void) { - if(sbreCollMesh) { - free(sbreCollMesh->pVertex); - free(sbreCollMesh->pIndex); - free(sbreCollMesh->pFlag); - free(sbreCollMesh); - } SetFrame(0); /* Will remove geom from frame if necessary. */ - dGeomDestroy(m_geom); + for(unsigned int i = 0; i < geoms.size(); i++) { + dGeomDestroy(geoms[i]); + } } -void StaticRigidBody::SetGeomSphere(double radius) { - assert(!m_geom); - m_geom = dCreateSphere(0, radius); +void StaticRigidBody::GeomsSetBody(dBodyID body) { + for(unsigned int i = 0; i < geoms.size(); i++) { + dGeomSetBody(geoms[i], body); + } } void StaticRigidBody::SetGeomFromSBREModel(int sbreModel, ObjParams* params) { - assert(!m_geom); - assert(sbreCollMesh == 0); - 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]; - } - dTriMeshDataID triMeshDataID = dGeomTriMeshDataCreate(); - dGeomTriMeshDataBuildSingle(triMeshDataID, (void*)sbreCollMesh->pVertex, - 3*sizeof(float), sbreCollMesh->nv, (void*)sbreCollMesh->pIndex, - sbreCollMesh->ni, 3*sizeof(int)); + assert(geoms.size() == 0); + CollMeshSet* mset = GetModelCollMeshSet(sbreModel); - /* TODO: Leaking StaticRigidBody m_geom. */ - m_geom = dCreateTriMesh(0, triMeshDataID, NULL, NULL, NULL); - dGeomSetData(m_geom, static_cast(this)); + geomColl.resize(mset->numMeshParts); + geoms.resize(mset->numMeshParts); + + for(unsigned int i = 0; i < mset->numMeshParts; i++) { + geoms[i] = dCreateTriMesh(0, mset->meshParts[i], NULL, NULL, NULL); + geomColl[i].parent = this; + geomColl[i].flags = mset->meshFlags[i]; + dGeomSetData(geoms[i], static_cast(&geomColl[i])); + } } void StaticRigidBody::SetPosition(vector3d p) { - dGeomSetPosition(m_geom, p.x, p.y, p.z); + for(unsigned int i = 0; i < geoms.size(); i++) { + dGeomSetPosition(geoms[i], p.x, p.y, p.z); + } } void StaticRigidBody::SetVelocity(vector3d v) { @@ -57,12 +50,12 @@ void StaticRigidBody::SetVelocity(vector3d v) { } vector3d StaticRigidBody::GetPosition(void) { - const dReal* pos = dGeomGetPosition(m_geom); + const dReal* pos = dGeomGetPosition(geoms[0]); return vector3d(pos[0], pos[1], pos[2]); } void StaticRigidBody::GetRotMatrix(matrix4x4d& m) { - m.LoadFromOdeMatrix(dGeomGetRotation(m_geom)); + m.LoadFromOdeMatrix(dGeomGetRotation(geoms[0])); } void StaticRigidBody::ViewingRotation(void) { @@ -73,7 +66,7 @@ void StaticRigidBody::ViewingRotation(void) { } void StaticRigidBody::TransformCameraTo(void) { - const dReal* p = dGeomGetPosition(m_geom); + const dReal* p = dGeomGetPosition(geoms[0]); matrix4x4d m; GetRotMatrix(m); m = m.InverseOf(); @@ -84,7 +77,7 @@ void StaticRigidBody::TransformCameraTo(void) { void StaticRigidBody::TransformToModelCoords(const Frame* camFrame) { vector3d fpos = GetPositionRelTo(camFrame); - const dReal* r = dGeomGetRotation(m_geom); + const dReal* r = dGeomGetRotation(geoms[0]); matrix4x4d m; m[ 0] = r[ 0]; m[ 1] = r[ 4]; m[ 2] = r[ 8]; m[ 3] = 0; m[ 4] = r[ 1]; m[ 5] = r[ 5]; m[ 6] = r[ 9]; m[ 7] = 0; @@ -94,14 +87,22 @@ void StaticRigidBody::TransformToModelCoords(const Frame* camFrame) { } void StaticRigidBody::SetFrame(Frame* f) { - if(GetFrame()) GetFrame()->RemoveGeom(m_geom); + if(GetFrame()) { + for(unsigned int i = 0; i < geoms.size(); i++) { + GetFrame()->RemoveGeom(geoms[i]); + } + } Body::SetFrame(f); - if(f) f->AddGeom(m_geom); + if(f) { + for(unsigned int i = 0; i < geoms.size(); i++) { + f->AddGeom(geoms[i]); + } + } } void StaticRigidBody::TriMeshUpdateLastPos(void) { /* ODE tri mesh likes to know our old position. */ - const dReal* r = dGeomGetRotation(m_geom); + const dReal* r = dGeomGetRotation(geoms[0]); vector3d pos = GetPosition(); dReal* t = triMeshTrans + 16*triMeshLastMatrixIndex; t[ 0] = r[0]; t[1] = r[1]; t[ 2] = r[ 2]; t[ 3] = 0; @@ -109,7 +110,9 @@ void StaticRigidBody::TriMeshUpdateLastPos(void) { t[ 8] = r[8]; t[9] = r[9]; t[10] = r[10]; t[11] = 0; t[12] = pos.x; t[13] = pos.y; t[14] = pos.z; t[15] = 1; triMeshLastMatrixIndex = !triMeshLastMatrixIndex; - dGeomTriMeshSetLastTransform(m_geom, *(dMatrix4*)(triMeshTrans + 16*triMeshLastMatrixIndex)); + for(unsigned int i = 0; i < geoms.size(); i++) { + dGeomTriMeshSetLastTransform(geoms[i], *(dMatrix4*)(triMeshTrans + 16*triMeshLastMatrixIndex)); + } } void StaticRigidBody::RenderSbreModel(const Frame* camFrame, int model, ObjParams* params) { @@ -145,7 +148,7 @@ void StaticRigidBody::RenderSbreModel(const Frame* camFrame, int model, ObjParam pos = L3D::world_view->viewingRotation*pos; Vector p; p.x = pos.x; p.y = pos.y; p.z = -pos.z; matrix4x4d rot; - rot.LoadFromOdeMatrix(dGeomGetRotation(m_geom)); + rot.LoadFromOdeMatrix(dGeomGetRotation(geoms[0])); rot = L3D::world_view->viewingRotation * rot; Matrix m; m.x1 = rot[0]; m.x2 = rot[4]; m.x3 = -rot[8]; diff --git a/src/static_rigid_body.h b/src/static_rigid_body.h index 3e16343..321160b 100644 --- a/src/static_rigid_body.h +++ b/src/static_rigid_body.h @@ -1,4 +1,5 @@ #pragma once +#include #include "body.h" #include "vector3.h" #include "matrix4x4.h" @@ -21,16 +22,22 @@ public: void ViewingRotation(void); void GetRotMatrix(matrix4x4d& m); virtual void SetFrame(Frame* f); + void GeomsSetBody(dBodyID body); void TriMeshUpdateLastPos(void); void SetGeomFromSBREModel(int sbreModel, ObjParams* params); - void SetGeomSphere(double radius); void RenderSbreModel(const Frame* camFrame, int model, ObjParams* params); -protected: - dGeomID m_geom; - CollMesh* sbreCollMesh; - float* meshNormals; + + class Geom : public Object { + public: + virtual Type GetType(void) { return Object::GEOM; } + Body* parent; + int flags; + }; +private: + std::vector geomColl; + std::vector geoms; dReal triMeshTrans[32]; int triMeshLastMatrixIndex; };