[Change] Get the collision geom flags through to the collision

detection..
This commit is contained in:
Allanis 2017-11-19 19:50:06 +00:00
parent 08265741a7
commit 40f38a0f58
10 changed files with 207 additions and 57 deletions

View File

@ -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

View File

@ -0,0 +1,102 @@
#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 = {
{ 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<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];
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, &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];
}
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;
}

View File

@ -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);

View File

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

View File

@ -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. */

View File

@ -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, &params);
SetMassDistributionFromCollMesh(sbreCollMesh);
dGeomSetBody(m_geom, m_body);
SetMassDistributionFromCollMesh(GetModelSBRECollMesh(stype.sbreModel));
GeomsSetBody(m_body);
UpdateMass();
}

View File

@ -132,7 +132,9 @@ static bool _OnCollision(dGeomID g1, dGeomID g2, Object* o1, Object* o2,
}
Ship::LaserObj* lobj = static_cast<Ship::LaserObj*>(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<Body*>(o1);
Body* pb2 = static_cast<Body*>(o2);
Body* pb1, *pb2;
int flags = 0;
/* Geom bodies point to their parents. */
if(o1->GetType() == Object::GEOM) {
pb1 = static_cast<StaticRigidBody::Geom*>(o1)->parent;
flags |= static_cast<StaticRigidBody::Geom*>(o1)->flags;
} else pb1 = static_cast<Body*>(o1);
if(o2->GetType() == Object::GEOM) {
pb2 = static_cast<StaticRigidBody::Geom*>(o2)->parent;
flags |= static_cast<StaticRigidBody::Geom*>(o2)->flags;
} else pb2 = static_cast<Body*>(o2);
printf("Collision flags %x\n", flags);
if((pb1 && !pb1->OnCollision(pb2)) || (pb2 && !pb2->OnCollision(pb1))) return false;
}
return true;

View File

@ -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) {

View File

@ -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<Body*>(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<Object*>(&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];

View File

@ -1,4 +1,5 @@
#pragma once
#include <vector>
#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<Geom> geomColl;
std::vector<dGeomID> geoms;
dReal triMeshTrans[32];
int triMeshLastMatrixIndex;
};