--- /dev/null
+#ifndef GONG_PHYSICS_DERIVATIVE_HPP_
+#define GONG_PHYSICS_DERIVATIVE_HPP_
+
+#include "../graphics/glm.hpp"
+
+#include <glm/gtc/quaternion.hpp>
+
+
+namespace gong {
+namespace physics {
+
+struct State;
+
+
+struct Derivative {
+
+ glm::vec3 dpos;
+ glm::vec3 dlin;
+ glm::quat dorient;
+ glm::vec3 dang;
+
+ Derivative() noexcept;
+ Derivative(
+ const glm::vec3 &,
+ const glm::vec3 &,
+ const glm::quat &,
+ const glm::vec3 &
+ ) noexcept;
+
+};
+
+
+inline Derivative operator +(const Derivative &a, const Derivative &b) noexcept {
+ return Derivative(a.dpos + b.dpos, a.dlin + b.dlin, a.dorient * b.dorient, a.dang + b.dang);
+}
+
+inline Derivative operator *(float f, const Derivative &d) noexcept {
+ return Derivative(f * d.dpos, f * d.dlin, f * d.dorient, f * d.dang);
+}
+inline Derivative operator *(const Derivative &d, float f) noexcept {
+ return f * d;
+}
+
+State &operator +=(State &s, const Derivative &d) noexcept;
+
+}
+}
+
+#endif
--- /dev/null
+#ifndef GONG_PHYSICS_OBJECT_HPP_
+#define GONG_PHYSICS_OBJECT_HPP_
+
+#include "State.hpp"
+#include "../geometry/primitive.hpp"
+
+
+namespace gong {
+namespace physics {
+
+struct Object {
+
+ State state;
+ geometry::AABB bounds;
+
+};
+
+}
+}
+
+#endif
--- /dev/null
+#ifndef GONG_PHYSICS_SIMULATION_HPP_
+#define GONG_PHYSICS_SIMULATION_HPP_
+
+#include "../graphics/glm.hpp"
+
+#include <vector>
+
+
+namespace gong {
+namespace physics {
+
+struct Derivative;
+struct Object;
+struct State;
+
+class Simulation {
+
+public:
+ void Update(float dt);
+
+private:
+ void Integrate(State &, float dt);
+ Derivative Evaluate(const State &, float dt, const Derivative &);
+
+private:
+ std::vector<Object *> objects;
+ glm::vec3 gravity;
+
+};
+
+}
+}
+
+#endif
--- /dev/null
+#ifndef GONG_PHYSICS_STATE_HPP_
+#define GONG_PHYSICS_STATE_HPP_
+
+#include "../graphics/glm.hpp"
+
+#include <glm/gtc/quaternion.hpp>
+
+
+namespace gong {
+namespace physics {
+
+struct State {
+ /// position of center of mass
+ glm::vec3 pos;
+ /// linear momentum
+ glm::vec3 lin;
+ /// orientation
+ glm::quat orient;
+ /// angular momentum
+ glm::vec3 ang;
+ /// angular velocity as quat
+ glm::quat Spin() const noexcept {
+ return 0.5f * glm::quat(0.0f, ang * inverse_inertia) * orient;
+ }
+ float mass;
+ /// 1/mass
+ float inverse_mass;
+ /// rotational inertia
+ float inertia;
+ /// 1/inertia
+ float inverse_inertia;
+};
+
+}
+}
+
+#endif
--- /dev/null
+#include "Derivative.hpp"
+#include "Object.hpp"
+#include "Simulation.hpp"
+#include "State.hpp"
+
+
+namespace gong {
+namespace physics {
+
+Derivative::Derivative() noexcept
+: dpos(0.0f)
+, dlin(0.0f)
+, dorient(1.0f, 0.0f, 0.0f, 0.0f)
+, dang(0.0f) {
+
+}
+
+Derivative::Derivative(
+ const glm::vec3 &p,
+ const glm::vec3 &l,
+ const glm::quat &o,
+ const glm::vec3 &a
+) noexcept
+: dpos(p)
+, dlin(l)
+, dorient(o)
+, dang(a) {
+
+}
+
+
+void Simulation::Update(float dt) {
+ // integrate state
+ for (Object *o : objects) {
+ Integrate(o->state, dt);
+ }
+ // TODO: detect collisions
+ // TODO: resolve collisions
+}
+
+void Simulation::Integrate(State &s, float dt) {
+ Derivative a(Evaluate(s, 0.0f, Derivative()));
+ Derivative b(Evaluate(s, dt * 0.5f, a));
+ Derivative c(Evaluate(s, dt * 0.5f, b));
+ Derivative d(Evaluate(s, dt, c));
+ constexpr float by_six = 1.0f / 6.0f;
+ Derivative f((a + (2.0f * (b + c)) + d) * by_six);
+ s += f * dt;
+}
+
+Derivative Simulation::Evaluate(const State &s, float dt, const Derivative &d) {
+ // TODO: calculate linear and torque forces from list of raw forces
+ glm::vec3 force(gravity);
+ glm::vec3 torque(0.0f);
+ return Derivative(
+ s.lin + d.dpos * dt * s.inverse_mass,
+ force,
+ glm::normalize(s.Spin() + d.dorient * dt * s.inverse_inertia),
+ torque
+ );
+}
+
+
+State &operator +=(State &s, const Derivative &d) noexcept {
+ s.pos += d.dpos;
+ s.lin += d.dlin;
+ s.orient *= d.dorient;
+ s.ang += d.dang;
+ return s;
+}
+
+}
+}