]> git.localhorst.tv Git - gong.git/commitdiff
half-{complete,assed} sphere collision detection master
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Fri, 2 Dec 2016 15:45:56 +0000 (16:45 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Fri, 2 Dec 2016 15:45:56 +0000 (16:45 +0100)
src/physics/Contact.hpp [new file with mode: 0644]
src/physics/Object.hpp
src/physics/Simulation.hpp
src/physics/Sphere.hpp [new file with mode: 0644]
src/physics/State.hpp
src/physics/objects.cpp [new file with mode: 0644]
src/physics/sim.cpp

diff --git a/src/physics/Contact.hpp b/src/physics/Contact.hpp
new file mode 100644 (file)
index 0000000..b7109b1
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef GONG_PHYSICS_CONTACT_HPP_
+#define GONG_PHYSICS_CONTACT_HPP_
+
+#include "../graphics/glm.hpp"
+
+
+namespace gong {
+namespace physics {
+
+class Object;
+
+struct Contact {
+
+       glm::vec3 point;
+       glm::vec3 normal;
+       Object *a;
+       Object *b;
+
+       Contact(const glm::vec3 &p, const glm::vec3 &n, Object *a, Object *b)
+       : point(p), normal(n), a(a), b(b) { }
+
+};
+
+}
+}
+
+#endif
index 576317c3014ae362fa9c5fb3c331cef5a38b3b31..f4f7f4ab2c6cf19f8be2b95aa438f31c60ce81f6 100644 (file)
@@ -4,15 +4,25 @@
 #include "State.hpp"
 #include "../geometry/primitive.hpp"
 
+#include <vector>
+
 
 namespace gong {
 namespace physics {
 
+struct Contact;
+class Sphere;
+
 struct Object {
 
        State state;
        geometry::AABB bounds;
 
+       void TestCollision(Object &, std::vector<Contact> &);
+
+       virtual void ReverseCollisionTest(Object &, std::vector<Contact> &) = 0;
+       virtual void ActualCollisionTest(Sphere &, std::vector<Contact> &) = 0;
+
 };
 
 }
index 9d41877365bec36753cbc75b8c021dfa370756a9..889c455f31683493b83849a5aef4519d941c31b6 100644 (file)
@@ -9,6 +9,7 @@
 namespace gong {
 namespace physics {
 
+struct Contact;
 struct Derivative;
 struct Object;
 struct State;
@@ -24,6 +25,7 @@ private:
 
 private:
        std::vector<Object *> objects;
+       std::vector<Contact> contacts;
        glm::vec3 gravity;
 
 };
diff --git a/src/physics/Sphere.hpp b/src/physics/Sphere.hpp
new file mode 100644 (file)
index 0000000..0acbc0b
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef GONG_PHYSICS_SPHERE_HPP_
+#define GONG_PHYSICS_SPHERE_HPP_
+
+#include "Object.hpp"
+#include "../geometry/primitive.hpp"
+
+
+namespace gong {
+namespace physics {
+
+class Sphere
+: public Object {
+
+public:
+       explicit Sphere(float radius);
+
+       /// Get geometric description of shape in world coordinates
+       geometry::Sphere Shape() {
+               return geometry::Sphere{ state.pos, radius };
+       }
+
+private:
+       void ReverseCollisionTest(Object &, std::vector<Contact> &) override;
+       void ActualCollisionTest(Sphere &, std::vector<Contact> &) override;
+
+private:
+       float radius;
+
+};
+
+}
+}
+
+#endif
index 76ff16cc3029c7a9b38dc9422f0cae8fce0efec5..1a643107c5470a8c180e498f2b512f33f20a5155 100644 (file)
@@ -29,6 +29,12 @@ struct State {
        float inertia;
        /// 1/inertia
        float inverse_inertia;
+
+       /// calculate velocity at given point
+       /// (same coordinate system as used by pos)
+       glm::vec3 VelAt(const glm::vec3 &p) const noexcept {
+               return (lin * inverse_mass) + glm::cross((ang * inverse_inertia), p - pos);
+       }
 };
 
 }
diff --git a/src/physics/objects.cpp b/src/physics/objects.cpp
new file mode 100644 (file)
index 0000000..e4075b3
--- /dev/null
@@ -0,0 +1,28 @@
+#include "Contact.hpp"
+#include "Sphere.hpp"
+
+
+namespace gong {
+namespace physics {
+
+Sphere::Sphere(float r)
+: radius(r) {
+       bounds.min = glm::vec3(-r);
+       bounds.max = glm::vec3(r);
+}
+
+void Sphere::ReverseCollisionTest(Object &other, std::vector<Contact> &contacts) {
+       other.ActualCollisionTest(*this, contacts);
+}
+
+void Sphere::ActualCollisionTest(Sphere &other, std::vector<Contact> &contacts) {
+       float dist;
+       glm::vec3 norm;
+       if (Intersection(Shape(), other.Shape(), dist, norm)) {
+               glm::vec3 point(state.pos + ((dist - radius) * norm));
+               contacts.emplace_back(point, norm, this, &other);
+       }
+}
+
+}
+}
index 568d28cdefb6fc1b18c037bc6efbe1135e4f3bd8..68cc3e04ebd3719b8097ef394c64a4156a65c619 100644 (file)
@@ -1,8 +1,11 @@
+#include "Contact.hpp"
 #include "Derivative.hpp"
 #include "Object.hpp"
 #include "Simulation.hpp"
 #include "State.hpp"
 
+#include "../geometry/primitive.hpp"
+
 
 namespace gong {
 namespace physics {
@@ -29,12 +32,33 @@ Derivative::Derivative(
 }
 
 
+void Object::TestCollision(Object &other, std::vector<Contact> &contacts) {
+       if (!Intersection(bounds, other.bounds)) {
+               return;
+       }
+       // TODO: actual object shape intersection test
+       ReverseCollisionTest(other, contacts);
+}
+
+
 void Simulation::Update(float dt) {
        // integrate state
        for (Object *o : objects) {
                Integrate(o->state, dt);
        }
-       // TODO: detect collisions
+
+       // detect collisions
+       contacts.clear();
+       if (objects.size() < 2) {
+               // we don't handle self-collision, so nothing to do
+               return;
+       }
+       for (std::size_t i = 0; i < objects.size() - 1; ++i) {
+               for (std::size_t j = i + 1; j < objects.size(); ++j) {
+                       objects[i]->TestCollision(*objects[j], contacts);
+               }
+       }
+
        // TODO: resolve collisions
 }