From 04fa6c284330996c8739138b91425631bb7a9ae6 Mon Sep 17 00:00:00 2001 From: Rtch90 Date: Fri, 13 Apr 2018 22:24:56 +0100 Subject: [PATCH] [Change] Laser hit uses new collision detection. --- src/collider/collision_space.cpp | 46 +++++++++++++ src/collider/collision_space.h | 1 + src/libs.h | 1 - src/model_body.h | 7 +- src/object.h | 2 +- src/ship.cpp | 26 ++++---- src/ship.h | 8 --- src/space.cpp | 108 ++----------------------------- 8 files changed, 69 insertions(+), 130 deletions(-) diff --git a/src/collider/collision_space.cpp b/src/collider/collision_space.cpp index 1fa0dcb..d682435 100644 --- a/src/collider/collision_space.cpp +++ b/src/collider/collision_space.cpp @@ -58,6 +58,52 @@ void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir, isect_ CollideRaySphere(start, dir, isect); } +void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir, + float len, CollisionContact*c, Geom* ignore) { + double dist = len; + for(std::list::iterator i = m_geoms.begin(); i!= m_geoms.end(); ++i) { + if((*i) == ignore) continue; + if((*i)->IsEnabled()) { + const matrix4x4d& invTrans = (*i)->GetInvTransform(); + vector3d ms = invTrans * start; + vector3d md = invTrans.ApplyRotationOnly(dir); + vector3f modelStart = vector3f(ms.x, ms.y, ms.z); + vector3f modelDir = vector3f(md.x, md.y, md.z); + + isect_t isect; + isect.dist = dist; + isect.triIdx = -1; + (*i)->GetGeomTree()->TraceRay(modelStart, modelDir, &isect); + if(isect.triIdx != -1) { + c->pos = start + dir*isect.dist; + c->normal = vector3d(0.0); + c->depth = len - isect.dist; + c->triIdx = isect.triIdx; + c->userData1 = (*i)->GetUserData(); + c->userData2 = 0; + c->geomFlag = (*i)->GetGeomTree()->GetTriFlag(isect.triIdx); + dist = isect.dist; + } + } + } + + { + isect_t isect; + isect.dist = dist; + isect.triIdx = -1; + CollideRaySphere(start, dir, &isect); + if(isect.triIdx != -1) { + c->pos = start + dir*isect.dist; + c->normal = vector3d(0.0); + c->depth = len - isect.dist; + c->triIdx = -1; + c->userData1 = sphere.userData; + c->userData2 = 0; + c->geomFlag = 0; + } + } +} + void CollisionSpace::CollideGeoms(Geom* a) { /* Our big Aabb. */ vector3d pos = a->GetPosition(); diff --git a/src/collider/collision_space.h b/src/collider/collision_space.h index ed91d29..eba75d3 100644 --- a/src/collider/collision_space.h +++ b/src/collider/collision_space.h @@ -20,6 +20,7 @@ public: void AddGeom(Geom*); void RemoveGeom(Geom*); void TraceRay(const vector3d& start, const vector3d& dir, isect_t* isect); + void TraceRay(const vector3d& start, const vector3d& dir, float len, CollisionContact* c, Geom* ignore = 0); void Collide(void (*callback)(CollisionContact*)); void SetSphere(const vector3d& pos, double radius, void* user_data) { sphere.pos = pos; sphere.radius = radius; sphere.userData = user_data; diff --git a/src/libs.h b/src/libs.h index 36dc3f0..3891cf3 100644 --- a/src/libs.h +++ b/src/libs.h @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include diff --git a/src/model_body.h b/src/model_body.h index 0f3e853..b1a46ac 100644 --- a/src/model_body.h +++ b/src/model_body.h @@ -25,18 +25,13 @@ public: virtual void Disable(void); virtual void Enable(void); void GetAabb(Aabb& aabb); + Geom* GetGeom(void) { return m_geom; } void TriMeshUpdateLastPos(const matrix4x4d& currentTransform); void SetModel(int sbreModel); void RenderSbreModel(const Frame* camFrame, int model, ObjParams* params); - class GeomBit : public Object { - public: - OBJDEF(GeomBit, Object, GEOM); - Body* parent; - int flags; - }; protected: virtual void Save(void); virtual void Load(void); diff --git a/src/object.h b/src/object.h index 01af994..fb45f35 100644 --- a/src/object.h +++ b/src/object.h @@ -2,7 +2,7 @@ class Object { public: - enum Type { OBJECT, BODY, MODELBODY, DYNAMICBODY, SHIP, PLAYER, SPACESTATION, LASER, GEOM, PLANET, STAR }; + enum Type { OBJECT, BODY, MODELBODY, DYNAMICBODY, SHIP, PLAYER, SPACESTATION, PLANET, STAR }; virtual Type GetType(void) { return OBJECT; } virtual bool IsType(Type c) { return GetType() == c; } }; diff --git a/src/ship.cpp b/src/ship.cpp index e4c2819..f9c989f 100644 --- a/src/ship.cpp +++ b/src/ship.cpp @@ -6,6 +6,7 @@ #include "model_coll_mesh_data.h" #include "space_station.h" #include "serializer.h" +#include "collider/collider.h" static ObjParams params = { { 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, @@ -63,7 +64,6 @@ void Ship::Load(void) { m_flightState = (FlightState) rd_int(); for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { m_gunState[i] = rd_int(); - m_tempLaserGeom[i] = 0; } m_shipType = (ShipType::Type)rd_int(); m_dockedWithPort = rd_int(); @@ -99,10 +99,8 @@ Ship::Ship(ShipType::Type shipType) : DynamicBody() { m_combatTarget = 0; m_shipType = shipType; m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0; - m_laserCollisionObj.owner = this; m_equipment = EquipSet(shipType); for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { - m_tempLaserGeom[i] = 0; m_gunState[i] = 0; } memset(m_thrusters, 0, sizeof(m_thrusters)); @@ -298,20 +296,26 @@ void Ship::TimeStepUpdate(const float timeStep) { /* LASERZ!! */ for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { - /* Free old temp laser geoms. */ - /*if(m_tempLaserGeom[i]) dGeomDestroy(m_tempLaserGeom[i]); - m_tempLaserGeom[i] = 0; if(!m_gunState[i]) continue; - dGeomID ray = dCreateRay(GetFrame()->GetSpaceID(), 10000); - const vector3d pos = GetPosition(); const vector3f _dir = stype.gunMount[i].dir; vector3d dir = vector3d(_dir.x, _dir.y, _dir.z); + const vector3f _pos = stype.gunMount[i].pos; + vector3d pos = vector3d(_pos.x, _pos.y, _pos.z); + matrix4x4d m; GetRotMatrix(m); dir = m.ApplyRotationOnly(dir); - dGeomRaySet(ray, pos.x, pos.y, pos.z, dir.x, dir.y, dir.z); - dGeomSetData(ray, static_cast(&m_laserCollisionObj)); - m_tempLaserGeom[i] = ray; */ + pos = m.ApplyRotationOnly(pos); + pos += GetPosition(); + + CollisionContact c; + GetFrame()->GetCollisionSpace()->TraceRay(pos, dir, 10000.0, &c, GetGeom()); + if(c.userData1) { + Body* hit = static_cast(c.userData1); + printf("Hit %s\n", hit->GetLabel().c_str()); + } else { + printf("Hit nothing..\n"); + } } if(m_wheelTransition != 0.0f) { diff --git a/src/ship.h b/src/ship.h index 4f3b730..168b8df 100644 --- a/src/ship.h +++ b/src/ship.h @@ -45,12 +45,6 @@ public: FlightState GetFlightState(void) const { return m_flightState; } float GetWheelState(void) const { return m_wheelState; } - class LaserObj : public Object { - public: - OBJDEF(LaserObj, Object, LASER); - Ship* owner; - }; - EquipSet m_equipment; virtual void PostLoadFixup(void); @@ -77,9 +71,7 @@ private: float m_thrusters[ShipType::THRUSTER_MAX]; float m_angThrusters[3]; float m_dockingTimer; - dGeomID m_tempLaserGeom[ShipType::GUNMOUNT_MAX]; - LaserObj m_laserCollisionObj; Body* m_navTarget; Body* m_combatTarget; shipstats_t m_stats; diff --git a/src/space.cpp b/src/space.cpp index 0d7212c..61dbffc 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -271,58 +271,10 @@ void Space::UpdateFramesOfReference(void) { } } -#if 0 -static bool _OnCollision(dGeomID g1, dGeomID g2, Object* o1, Object* o2, - int numContacts, dContact contacts[]) { - if((o1->IsType(Object::LASER)) || (o2->IsType(Object::LASER))) { - if(o1->IsType(Object::LASER)) { - std::swap(o1, o2); - std::swap(g1, g2); - } - Ship::LaserObj* lobj = static_cast(o2); - if(o1 == lobj->owner) return false; - if(o1->IsType(Object::SHIP)) { - DynamicBody* rb = (DynamicBody*)o1; - dVector3 start, dir; - dGeomRayGet(g2, start, dir); - rb->AddForceAtPos(vector3d(dir[0], dir[1], dir[2])*100, - vector3d(contacts[0].geom.pos[0], contacts[0].geom.pos[1], contacts[0].geom.pos[2])); - } - return false; - } else { - Body* pb1, *pb2; - int flags = 0; - /* Geom bodies point to their parents. */ - if(o1->IsType(Object::GEOM)) { - pb1 = static_cast(o1)->parent; - flags |= static_cast(o1)->flags; - } else pb1 = static_cast(o1); - if(o2->IsType(Object::GEOM)) { - pb2 = static_cast(o2)->parent; - flags |= static_cast(o2)->flags; - } else pb2 = static_cast(o2); - - if((pb1 && !pb1->OnCollision(pb2, flags)) || (pb2 && !pb2->OnCollision(pb1, flags))) return false; - } - return true; -} -#endif - -static bool _OnCollision2(Object* o1, Object* o2, CollisionContact* c) { - Body* pb1, *pb2; - int flags = c->geomFlag; - //printf("Collision flags %x (triIdx %d)\n", flags, c->triIdx); - /* Geom bodies point to their parents. */ - if(o1->IsType(Object::GEOM)) { - pb1 = static_cast(o1)->parent; - flags |= static_cast(o1)->flags; - } else pb1 = static_cast(o1); - if(o2->IsType(Object::GEOM)) { - pb2 = static_cast(o2)->parent; - flags |= static_cast(o2)->flags; - } else pb2 = static_cast(o2); - - if((pb1 && !pb1->OnCollision(pb2, flags)) || (pb2 && !pb2->OnCollision(pb1, flags))) return false; +static bool OnCollision(Object* o1, Object* o2, CollisionContact* c) { + Body* pb1 = static_cast(o1); + Body* pb2 = static_cast(o2); + if((pb1 && !pb1->OnCollision(pb2, c->geomFlag)) || (pb2 && !pb2->OnCollision(pb1, c->geomFlag))) return false; return true; } @@ -332,7 +284,7 @@ static void hitCallback(CollisionContact* c) { Object* po1 = static_cast(c->userData1); Object* po2 = static_cast(c->userData2); - if(!_OnCollision2(po1, po2, c)) return; + if(!OnCollision(po1, po2, c)) return; const bool po1_isDynBody = po1->IsType(Object::DYNAMICBODY); const bool po2_isDynBody = po2->IsType(Object::DYNAMICBODY); @@ -401,58 +353,8 @@ static void hitCallback(CollisionContact* c) { } } -#if 0 -static void nearCallback(void* data, dGeomID oO, dGeomID o1) { - /* Create an array of dContact objects to hold the contact joints. */ - static const int MAX_CONTACTS = 100; - dContact contact[MAX_CONTACTS]; - - for(int i = 0; i < MAX_CONTACTS; i++) { - contact[i].surface.mode = dContactBounce; - contact[i].surface.mu = 0.8; - contact[i].surface.mu2 = 0; - contact[i].surface.bounce = 0.1; - contact[i].surface.bounce_vel = 0.1; - } - if(int numc = dCollide(oO, o1, MAX_CONTACTS, &contact[0].geom, sizeof(dContact))) { - Object* po1 = static_cast(dGeomGetData(oO)); - Object* po2 = static_cast(dGeomGetData(o1)); - if(!_OnCollision(oO, o1, po1, po2, numc, contact)) return; - /* Get the dynamics body for each geom. */ - dBodyID b1 = dGeomGetBody(oO); - dBodyID b2 = dGeomGetBody(o1); - /* - * To add contact point found to our joint group we call dJointCreateContact - * which is just one of the many different types available. - */ - for(int i = 0; i < numc; i++) { - printf("\nODE collision:\n); - dump_contact(contact+i); - /* - * dJointCreateContact needs to know which world and joint group to work - * with as well as the dContact object itself. - * It returns a new dJointID which we then use with dJointAttach to - * finally create the temp contact joint between the two geom bodies. - */ - //dJointID c = dJointCreateContact(Space::world, _contactgroup, contact + i); -#if 0 - struct dContactGeom { - dVector3 pos; /* Constact position. */ - dVector3 normal; /* Normal vector. */ - dReal depth; /* Penetration depth. */ - dGeomId g1, g2; /* The colliding geoms. */ - }; -#endif - - //dJointAttach(c, b1, b2); - } - } -} -#endif - void Space::CollideFrame(Frame* f) { f->GetCollisionSpace()->Collide(&hitCallback); - //dSpaceCollide(f->GetSpaceID(), NULL, &nearCallback); for(std::list::iterator i = f->m_children.begin(); i != f->m_children.end(); ++i) { CollideFrame(*i); }