[Change] Laser hit uses new collision detection.

This commit is contained in:
Rtch90 2018-04-13 22:24:56 +01:00
parent 75613f2237
commit 04fa6c2843
8 changed files with 69 additions and 130 deletions

View File

@ -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<Geom*>::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();

View File

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

View File

@ -5,7 +5,6 @@
#include <SDL.h>
#include <SDL_opengl.h>
#include <SDL_image.h>
#include <ode/ode.h>
#include <float.h>
#include <limits>
#include <time.h>

View File

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

View File

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

View File

@ -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<Object*>(&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<Body*>(c.userData1);
printf("Hit %s\n", hit->GetLabel().c_str());
} else {
printf("Hit nothing..\n");
}
}
if(m_wheelTransition != 0.0f) {

View File

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

View File

@ -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<Object*>(o1, o2);
std::swap<dGeomID>(g1, g2);
}
Ship::LaserObj* lobj = static_cast<Ship::LaserObj*>(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<ModelBody::GeomBit*>(o1)->parent;
flags |= static_cast<ModelBody::GeomBit*>(o1)->flags;
} else pb1 = static_cast<Body*>(o1);
if(o2->IsType(Object::GEOM)) {
pb2 = static_cast<ModelBody::GeomBit*>(o2)->parent;
flags |= static_cast<ModelBody::GeomBit*>(o2)->flags;
} else pb2 = static_cast<Body*>(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<ModelBody::GeomBit*>(o1)->parent;
flags |= static_cast<ModelBody::GeomBit*>(o1)->flags;
} else pb1 = static_cast<Body*>(o1);
if(o2->IsType(Object::GEOM)) {
pb2 = static_cast<ModelBody::GeomBit*>(o2)->parent;
flags |= static_cast<ModelBody::GeomBit*>(o2)->flags;
} else pb2 = static_cast<Body*>(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<Body*>(o1);
Body* pb2 = static_cast<Body*>(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<Object*>(c->userData1);
Object* po2 = static_cast<Object*>(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<Object*>(dGeomGetData(oO));
Object* po2 = static_cast<Object*>(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<Frame*>::iterator i = f->m_children.begin(); i != f->m_children.end(); ++i) {
CollideFrame(*i);
}