diff --git a/src/lib/fixed_length_list.hpp b/src/lib/fixed_length_list.hpp new file mode 100644 index 0000000..96b0d52 --- /dev/null +++ b/src/lib/fixed_length_list.hpp @@ -0,0 +1,34 @@ +template +struct fixed_length_list +{ + T values[max_length]; + int length; + + fixed_length_list() + : length(0) + {} + + void add(const T& value) + { + for (int i = 0; i < length; i++) { + if (values[i] == value) + return; + } + + values[length] = value; + length += 1; + } + + void remove(const T& value) + { + for (int i = 0; i < length; i++) { + if (values[i] == value) { + for (int k = i + 1; k < length;) { + values[i++] = values[k++]; + } + length -= 1; + break; + } + } + } +}; diff --git a/src/physics/particle.cpp b/src/physics/particle.cpp index 3b85cbb..0df3b09 100644 --- a/src/physics/particle.cpp +++ b/src/physics/particle.cpp @@ -18,6 +18,9 @@ namespace physics { // drag velocity *= damping; + + // clear forces + force_accum = vec3(0, 0, 0); } } diff --git a/src/physics/particle.hpp b/src/physics/particle.hpp index 7732d8a..9d63ce3 100644 --- a/src/physics/particle.hpp +++ b/src/physics/particle.hpp @@ -1,6 +1,7 @@ #pragma once #include "math/float_types.hpp" +#include "math/math.hpp" namespace physics { @@ -14,6 +15,16 @@ namespace physics { vec3 force_accum; void integrate(float duration); - }; + inline void add_force(const vec3& force) + { + force_accum += force; + } + + inline float get_mass() const + { + float sqrt_mass = 1.0f / sqrt(inverse_mass); + return sqrt_mass * sqrt_mass; + } + }; } diff --git a/src/physics/particle_force_generator.cpp b/src/physics/particle_force_generator.cpp new file mode 100644 index 0000000..96b5ee4 --- /dev/null +++ b/src/physics/particle_force_generator.cpp @@ -0,0 +1,32 @@ +#include "physics/particle_force_generator.hpp" + +namespace physics { + + void particle_force_registry::add(particle * particle, particle_force_generator * force_generator) + { + registrations.add({particle, force_generator}); + } + + void particle_force_registry::update_forces(float duration) + { + for (int i = 0; i < registrations.length; i++) { + const particle_force_entry& entry = registrations.values[i]; + entry.force_generator->update_force(entry.particle, duration); + } + } + + void particle_gravity::update_force(particle * particle, float duration) + { + particle->add_force(gravity * particle->get_mass()); + } + + void particle_drag::update_force(particle * particle, float duration) + { + vec3 force = particle->velocity; + + float drag_coeff = magnitude(force); + drag_coeff = k1 * drag_coeff + k2 * drag_coeff * drag_coeff; + + particle->add_force(normalize(force) * drag_coeff); + } +} diff --git a/src/physics/particle_force_generator.hpp b/src/physics/particle_force_generator.hpp new file mode 100644 index 0000000..6f2124d --- /dev/null +++ b/src/physics/particle_force_generator.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include "physics/particle.hpp" +#include "lib/fixed_length_list.hpp" + +namespace physics { + + struct particle_force_generator + { + virtual void update_force(particle * particle, float duration) = 0; + }; + + struct particle_force_entry + { + physics::particle * particle; + particle_force_generator * force_generator; + + bool operator==(const particle_force_entry&) const = default; + }; + + struct particle_force_registry + { + fixed_length_list registrations; + + void add(particle * particle, particle_force_generator * force_generator); + void update_forces(float duration); + }; + + struct particle_gravity : particle_force_generator + { + vec3 gravity; + + particle_gravity(const vec3& gravity) + : gravity(gravity) + {} + + void update_force(particle * particle, float duration) override; + }; + + struct particle_drag : particle_force_generator + { + float k1; + float k2; + + void update_force(particle * particle, float duration) override; + }; +}