From 799e1de13654669e577501076d2146abeb8392d2 Mon Sep 17 00:00:00 2001 From: Rtch90 Date: Sun, 8 Apr 2018 18:25:42 +0100 Subject: [PATCH] [Fix] Made the linear component of collisions with static bodies work. --- src/collider/Makefile.am | 2 +- src/collider/collider.h | 11 +---- src/collider/collision_contact.h | 14 ++++++ src/collider/collision_space.cpp | 19 ++++++--- src/collider/collision_space.h | 2 +- src/collider/geom.cpp | 61 +++++++++++++------------- src/collider/geom.h | 8 ++-- src/dynamic_body.cpp | 4 ++ src/space.cpp | 73 +++++++++++++------------------- 9 files changed, 97 insertions(+), 97 deletions(-) create mode 100644 src/collider/collision_contact.h diff --git a/src/collider/Makefile.am b/src/collider/Makefile.am index 9475b79..ccb9dc3 100644 --- a/src/collider/Makefile.am +++ b/src/collider/Makefile.am @@ -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 diff --git a/src/collider/collider.h b/src/collider/collider.h index e983e41..64c59df 100644 --- a/src/collider/collider.h +++ b/src/collider/collider.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" diff --git a/src/collider/collision_contact.h b/src/collider/collision_contact.h new file mode 100644 index 0000000..f22cb11 --- /dev/null +++ b/src/collider/collision_contact.h @@ -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; + } +}; + diff --git a/src/collider/collision_space.cpp b/src/collider/collision_space.cpp index dac128e..1fa0dcb 100644 --- a/src/collider/collision_space.cpp +++ b/src/collider/collision_space.cpp @@ -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::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::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); + } + } } } diff --git a/src/collider/collision_space.h b/src/collider/collision_space.h index a9203d7..ed91d29 100644 --- a/src/collider/collision_space.h +++ b/src/collider/collision_space.h @@ -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 m_geoms; diff --git a/src/collider/geom.cpp b/src/collider/geom.cpp index 10a34da..28bd544 100644 --- a/src/collider/geom.cpp +++ b/src/collider/geom.cpp @@ -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); + } } } } diff --git a/src/collider/geom.h b/src/collider/geom.h index c4893ef..4616e5a 100644 --- a/src/collider/geom.h +++ b/src/collider/geom.h @@ -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; diff --git a/src/dynamic_body.cpp b/src/dynamic_body.cpp index b1d402e..063609e 100644 --- a/src/dynamic_body.cpp +++ b/src/dynamic_body.cpp @@ -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); diff --git a/src/space.cpp b/src/space.cpp index a1407fb..8d479b4 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -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(c->userData1); Object* po2 = static_cast(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(po1)->m_body; - if(po2->IsType(Object::DYNAMICBODY)) b2 = static_cast(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(po1); + else mover = static_cast(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. */