[Fix] Made the linear component of collisions with static bodies work.
This commit is contained in:
parent
40f6d6dc37
commit
799e1de136
@ -1,5 +1,5 @@
|
||||
noinst_LIBRARIES = libcollider.a
|
||||
libcollider_a_SOURCES = geom_tree.cpp geom.cpp collision_space.cpp
|
||||
|
||||
include_HEADERS = geom_tree.h geom.h collision_space.h collider.h
|
||||
include_HEADERS = geom_tree.h geom.h collision_space.h collider.h collision_contact.h
|
||||
|
||||
|
@ -4,14 +4,5 @@
|
||||
#include "collision_space.h"
|
||||
#include "geom.h"
|
||||
|
||||
class Geom;
|
||||
|
||||
struct CollisionContact {
|
||||
vector3d pos;
|
||||
vector3d normal;
|
||||
double depth;
|
||||
int triIdx;
|
||||
void* userData1, *userData2;
|
||||
int geomFlag;
|
||||
};
|
||||
#include "collision_contact.h"
|
||||
|
||||
|
14
src/collider/collision_contact.h
Normal file
14
src/collider/collision_contact.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
struct CollisionContact {
|
||||
vector3d pos;
|
||||
vector3d normal;
|
||||
double depth;
|
||||
int triIdx;
|
||||
void* userData1, *userData2;
|
||||
int geomFlag;
|
||||
CollisionContact(void) {
|
||||
depth = 0; triIdx = -1; userData1 = userData2 = 0;
|
||||
}
|
||||
};
|
||||
|
@ -58,7 +58,7 @@ void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir, isect_
|
||||
CollideRaySphere(start, dir, isect);
|
||||
}
|
||||
|
||||
void CollisionSpace::CollideGeoms(Geom* a, void (*callback)(CollisionContact*)) {
|
||||
void CollisionSpace::CollideGeoms(Geom* a) {
|
||||
/* Our big Aabb. */
|
||||
vector3d pos = a->GetPosition();
|
||||
Aabb bigAabb;
|
||||
@ -68,7 +68,7 @@ void CollisionSpace::CollideGeoms(Geom* a, void (*callback)(CollisionContact*))
|
||||
|
||||
/* First test this reested sh*t against the planet sphere thing. */
|
||||
if(sphere.radius != 0) {
|
||||
a->CollideSphere(sphere, callback);
|
||||
a->CollideSphere(sphere);
|
||||
}
|
||||
|
||||
for(std::list<Geom*>::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) {
|
||||
@ -79,17 +79,24 @@ void CollisionSpace::CollideGeoms(Geom* a, void (*callback)(CollisionContact*))
|
||||
bigAabb2.min += pos2;
|
||||
bigAabb2.max += pos2;
|
||||
if(bigAabb.Intersects(bigAabb2)) {
|
||||
a->Collide(*i, callback);
|
||||
if(!(*i)->HasMoved()) (*i)->Collide(a, callback);
|
||||
a->Collide(*i);
|
||||
if(!(*i)->HasMoved()) (*i)->Collide(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionSpace::Collide(void (*callback)(CollisionContact*)) {
|
||||
/* For now, do a totally stupid intersection of every body on every other. */
|
||||
for(std::list<Geom*>::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) {
|
||||
if((*i)->HasMoved()) CollideGeoms(*i, callback);
|
||||
(*i)->contact = CollisionContact();
|
||||
if((*i)->HasMoved()) {
|
||||
CollideGeoms(*i);
|
||||
if((*i)->HasMoved()) {
|
||||
CollideGeoms(*i);
|
||||
if((*i)->contact.triIdx != -1)
|
||||
(*callback)(&(*i)->contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void CollideGeoms(Geom* a, void (*callback)(CollisionContact*));
|
||||
void CollideGeoms(Geom* a);
|
||||
void CollideRaySphere(const vector3d& start, const vector3d& dir, isect_t* isect);
|
||||
std::list<Geom*> m_geoms;
|
||||
|
||||
|
@ -42,7 +42,7 @@ vector3d Geom::GetPosition(void) const {
|
||||
m_orient[m_orientIdx][14]);
|
||||
}
|
||||
|
||||
void Geom::CollideSphere(Sphere& sphere, void(*callback)(CollisionContact*)) {
|
||||
void Geom::CollideSphere(Sphere& sphere) {
|
||||
/*
|
||||
* If the geom is actually within the sphere, create a contact so
|
||||
* that we can't fall into spheres forever and ever and ever..
|
||||
@ -50,15 +50,13 @@ void Geom::CollideSphere(Sphere& sphere, void(*callback)(CollisionContact*)) {
|
||||
vector3d v = GetPosition() - sphere.pos;
|
||||
const double len = v.Length();
|
||||
if(len < sphere.radius) {
|
||||
CollisionContact c;
|
||||
c.pos = GetPosition();
|
||||
c.normal = (1.0/len)*v;
|
||||
c.depth = sphere.radius - len;
|
||||
c.triIdx = 0;
|
||||
c.userData1 = this->m_data;
|
||||
c.userData2 = sphere.userData;
|
||||
c.geomFlag = 0;
|
||||
(*callback)(&c);
|
||||
contact.pos = GetPosition();
|
||||
contact.normal = (1.0/len)*v;
|
||||
contact.depth = sphere.radius - len;
|
||||
contact.triIdx = 0;
|
||||
contact.userData1 = this->m_data;
|
||||
contact.userData2 = sphere.userData;
|
||||
contact.geomFlag = 0;
|
||||
return;
|
||||
}
|
||||
for(int i = 0; i < m_geomtree->m_numVertices; i++) {
|
||||
@ -80,15 +78,13 @@ void Geom::CollideSphere(Sphere& sphere, void(*callback)(CollisionContact*)) {
|
||||
if(i2 > 0) {
|
||||
if(i1 > 0) {
|
||||
if(i1 < len) {
|
||||
CollisionContact c;
|
||||
c.pos = from + dir*i1;
|
||||
c.normal = vector3d::Normalize(v);
|
||||
c.depth = len - i1;
|
||||
c.triIdx = 0;
|
||||
c.userData1 = this->m_data;
|
||||
c.userData2 = sphere.userData;
|
||||
c.geomFlag = 0;
|
||||
(*callback)(&c);
|
||||
contact.pos = from + dir*i1;
|
||||
contact.normal = vector3d::Normalize(v);
|
||||
contact.depth = len - i1;
|
||||
contact.triIdx = 0;
|
||||
contact.userData1 = this->m_data;
|
||||
contact.userData2 = sphere.userData;
|
||||
contact.geomFlag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,7 +92,7 @@ void Geom::CollideSphere(Sphere& sphere, void(*callback)(CollisionContact*)) {
|
||||
}
|
||||
}
|
||||
|
||||
void Geom::Collide(Geom* b, void(*callback)(CollisionContact*)) {
|
||||
void Geom::Collide(Geom* b) {
|
||||
m_moved = false;
|
||||
for(int i = 0; i < m_geomtree->m_numVertices; i++) {
|
||||
vector3d v(&m_geomtree->m_vertices[3*i]);
|
||||
@ -116,19 +112,20 @@ void Geom::Collide(Geom* b, void(*callback)(CollisionContact*)) {
|
||||
isect.triIdx = -1;
|
||||
b->m_geomtree->TraceRay(_from, _dir, &isect);
|
||||
if(isect.triIdx != -1) {
|
||||
CollisionContact c;
|
||||
/* In world coords. */
|
||||
c.pos = b->GetTransform() * (from + dir*isect.dist);
|
||||
vector3f n = b->m_geomtree->GetTriNormal(isect.triIdx);
|
||||
c.normal = vector3d(n.x, n.y, n.z);
|
||||
c.normal = b->GetTransform().ApplyRotationOnly(c.normal);
|
||||
const double depth = len - isect.dist;
|
||||
if(depth > contact.depth) {
|
||||
/* In world coords. */
|
||||
contact.pos = b->GetTransform() * (from + dir*isect.dist);
|
||||
vector3f n = b->m_geomtree->GetTriNormal(isect.triIdx);
|
||||
contact.normal = vector3d(n.x, n.y, n.z);
|
||||
contact.normal = b->GetTransform().ApplyRotationOnly(contact.normal);
|
||||
|
||||
c.depth = len - isect.dist;
|
||||
c.triIdx = isect.triIdx;
|
||||
c.userData1 = m_data;
|
||||
c.userData2 = b->m_data;
|
||||
c.geomFlag = b->m_geomtree->GetTriFlag(isect.triIdx);
|
||||
(*callback)(&c);
|
||||
contact.depth = len - isect.dist;
|
||||
contact.triIdx = isect.triIdx;
|
||||
contact.userData1 = m_data;
|
||||
contact.userData2 = b->m_data;
|
||||
contact.geomFlag = b->m_geomtree->GetTriFlag(isect.triIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
#include "../matrix4x4.h"
|
||||
#include "../vector3.h"
|
||||
#include "collision_contact.h"
|
||||
|
||||
class GeomTree;
|
||||
class isect_t;
|
||||
class CollisionContact;
|
||||
class Sphere;
|
||||
|
||||
class Geom {
|
||||
@ -21,10 +21,12 @@ public:
|
||||
bool IsEnabled(void) { return m_active; }
|
||||
bool HasMoved(void) { return m_moved; }
|
||||
GeomTree* GetGeomTree(void) { return m_geomtree; }
|
||||
void Collide(Geom* b, void(*callback)(CollisionContact*));
|
||||
void CollideSphere(Sphere& sphere, void (*callback)(CollisionContact*));
|
||||
void Collide(Geom* b);
|
||||
void CollideSphere(Sphere& sphere);
|
||||
void SetUserData(void* d) { m_data = d; }
|
||||
void* GetUserData(void) { return m_data; }
|
||||
|
||||
CollisionContact contact;
|
||||
private:
|
||||
/* double-buffer position so we can keep previous position. */
|
||||
matrix4x4d m_orient[2], m_invOrient;
|
||||
|
@ -93,6 +93,10 @@ vector3d DynamicBody::GetPosition(void) const {
|
||||
}
|
||||
|
||||
void DynamicBody::TimeStepUpdate(const float timeStep) {
|
||||
/*
|
||||
* XXX Remember this is used to step back also in the collision code.
|
||||
* very silly btw.
|
||||
*/
|
||||
if(m_enabled) {
|
||||
m_vel += timeStep * m_force * (1.0/m_mass);
|
||||
m_angVel += timeStep * m_torque * (1.0 / m_angInertia);
|
||||
|
@ -271,6 +271,7 @@ 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))) {
|
||||
@ -305,14 +306,7 @@ static bool _OnCollision(dGeomID g1, dGeomID g2, Object* o1, Object* o2,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dump_contact(const dContact* c) {
|
||||
printf("pos %f,%f,%f\n", c->geom.pos[0], c->geom.pos[1], c->geom.pos[2]);
|
||||
printf("normal %f,%f,%f\n", c->geom.normal[0], c->geom.normal[1], c->geom.normal[2]);
|
||||
printf("depth %f\n", c->geom.depth);
|
||||
printf("side1:side2 %d:%d\n", c->geom.side1, c->geom.side2);
|
||||
printf("fdir1 %f,%f,%f\n", c->fdir1[0], c->fdir1[1], c->fdir1[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool _OnCollision2(Object* o1, Object* o2, CollisionContact* c) {
|
||||
Body* pb1, *pb2;
|
||||
@ -332,50 +326,42 @@ static bool _OnCollision2(Object* o1, Object* o2, CollisionContact* c) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define MAX_CONTACTS 1
|
||||
/* XXX SO REESTED!! 1 CONTACT PER PHYSICS TICK?! WTH?! */
|
||||
static int contact_num;
|
||||
static void hitCallback(CollisionContact* c) {
|
||||
if(contact_num++ >= MAX_CONTACTS) return;
|
||||
printf("AUCH!! %x (depth %f)\n", SDL_GetTicks(), c->depth);
|
||||
#if 0
|
||||
dContact contact;
|
||||
|
||||
contact.surface.mode = dContactBounce;
|
||||
contact.surface.mu = 0.8;
|
||||
contact.surface.mu2 = 0;
|
||||
contact.surface.bounce = 0.1;
|
||||
contact.surface.bounce_vel = 0.1;
|
||||
|
||||
contact.geom.pos[0] = c->pos.x;
|
||||
contact.geom.pos[1] = c->pos.y;
|
||||
contact.geom.pos[2] = c->pos.z;
|
||||
contact.geom.pos[3] = 1;
|
||||
contact.geom.normal[0] = c->normal.x;
|
||||
contact.geom.normal[1] = c->normal.y;
|
||||
contact.geom.normal[2] = c->normal.z;
|
||||
contact.geom.normal[3] = 1;
|
||||
contact.geom.depth = c->depth;
|
||||
contact.geom.g1 = 0;
|
||||
contact.geom.g2 = 0;
|
||||
contact.fdir1[0] = 0;
|
||||
contact.fdir1[1] = 0;
|
||||
contact.fdir1[2] = 0;
|
||||
|
||||
Object* po1 = static_cast<Object*>(c->userData1);
|
||||
Object* po2 = static_cast<Object*>(c->userData2);
|
||||
|
||||
if(!_OnCollision2(po1, po2, c)) return;
|
||||
|
||||
dBodyID b1 = 0;
|
||||
dBodyID b2 = 0;
|
||||
/* Get the dynamics body for each geom. */
|
||||
if(po1->IsType(Object::DYNAMICBODY)) b1 = static_cast<DynamicBody*>(po1)->m_body;
|
||||
if(po2->IsType(Object::DYNAMICBODY)) b2 = static_cast<DynamicBody*>(po2)->m_body;
|
||||
const bool po1_isDynBody = po1->IsType(Object::DYNAMICBODY);
|
||||
const bool po2_isDynBody = po2->IsType(Object::DYNAMICBODY);
|
||||
/* Collision response. */
|
||||
assert(po1_isDynBody || po2_isDynBody);
|
||||
|
||||
dJointID j = dJointCreateContact(Space::world, _contactgroup, &contact);
|
||||
dJointAttach(j, b1, b2);
|
||||
#endif
|
||||
if(po1_isDynBody && po2_isDynBody) {
|
||||
|
||||
} else {
|
||||
/* One body is static. */
|
||||
vector3d hitNormal;
|
||||
if(po2_isDynBody) hitNormal = -c->normal;
|
||||
else hitNormal = c->normal;
|
||||
printf("Hi! %f,%f,%f\n", hitNormal.x, hitNormal.y, hitNormal.z);
|
||||
|
||||
DynamicBody* mover;
|
||||
if(po1_isDynBody) mover = static_cast<DynamicBody*>(po1);
|
||||
else mover = static_cast<DynamicBody*>(po2);
|
||||
|
||||
const vector3d vel = mover->GetVelocity();
|
||||
vector3d reflect = vel - (hitNormal * vector3d::Dot(vel, hitNormal) * 2.0f);
|
||||
/* Dampen a little. */
|
||||
reflect = reflect * 0.5;
|
||||
|
||||
/* Step back. */
|
||||
mover->TimeStepUpdate(-L3D::GetTimeStep());
|
||||
/* and set altered velocity. */
|
||||
mover->SetVelocity(reflect);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -464,7 +450,6 @@ void Space::ApplyGravity(void) {
|
||||
void Space::TimeStep(float step) {
|
||||
ApplyGravity();
|
||||
|
||||
contact_num = 0;
|
||||
CollideFrame(rootFrame);
|
||||
|
||||
/* TODO: Does not need to be done this often. */
|
||||
|
Loading…
Reference in New Issue
Block a user