--- /dev/null
+#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
#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;
+
};
}
namespace gong {
namespace physics {
+struct Contact;
struct Derivative;
struct Object;
struct State;
private:
std::vector<Object *> objects;
+ std::vector<Contact> contacts;
glm::vec3 gravity;
};
--- /dev/null
+#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
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);
+ }
};
}
--- /dev/null
+#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);
+ }
+}
+
+}
+}
+#include "Contact.hpp"
#include "Derivative.hpp"
#include "Object.hpp"
#include "Simulation.hpp"
#include "State.hpp"
+#include "../geometry/primitive.hpp"
+
namespace gong {
namespace physics {
}
+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
}