Skip to content

Commit

Permalink
Better organize physics system logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Speykious committed Jan 8, 2024
1 parent cc16db7 commit 60db181
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 89 deletions.
60 changes: 9 additions & 51 deletions inox2d/src/physics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,79 +6,37 @@ use crate::nodes::node_data::InoxData;
use crate::params::ParamUuid;
use crate::puppet::Puppet;

use glam::{vec2, Vec2};
use glam::Vec2;

use self::pendulum::rigid::RigidPendulum;
use self::pendulum::spring::SpringPendulum;
use self::runge_kutta::PhysicsState;
use self::pendulum::rigid::RigidPendulumSystem;
use self::pendulum::spring::SpringPendulumSystem;

/// Physics model to use for simple physics
#[derive(Debug, Clone)]
pub enum SimplePhysicsSystem {
/// Rigid pendulum
RigidPendulum {
bob: Vec2,
state: PhysicsState<2, RigidPendulum>,
},
RigidPendulum(RigidPendulumSystem),

// Springy pendulum
SpringPendulum {
bob: Vec2,
state: PhysicsState<4, SpringPendulum>,
},
SpringPendulum(SpringPendulumSystem),
}

impl SimplePhysicsSystem {
pub fn new_rigid_pendulum() -> Self {
Self::RigidPendulum {
bob: Vec2::ZERO,
state: PhysicsState::default(),
}
Self::RigidPendulum(RigidPendulumSystem::default())
}

pub fn new_spring_pendulum() -> Self {
Self::SpringPendulum {
bob: Vec2::ZERO,
state: PhysicsState::default(),
}
Self::SpringPendulum(SpringPendulumSystem::default())
}

fn tick(&mut self, anchor: Vec2, props: &SimplePhysicsProps, dt: f32) -> Vec2 {
// enum dispatch, fill the branches once other systems are implemented
// as for inox2d, users are not expected to bring their own physics system,
// no need to do dynamic dispatch with something like Box<dyn SimplePhysicsSystem>
match self {
SimplePhysicsSystem::RigidPendulum {
ref mut bob,
ref mut state,
} => {
// Compute the angle against the updated anchor position
let d_bob = *bob - anchor;
state.setv_angle(f32::atan2(-d_bob.x, d_bob.y));

// Run the pendulum simulation in terms of angle
runge_kutta::tick(&pendulum::rigid::eval, state, props, anchor, dt);

// Update the bob position at the new angle
let angle = state.getv_angle();
let d_bob = vec2(-angle.sin(), angle.cos());
*bob = anchor + d_bob * props.length;

*bob
}
SimplePhysicsSystem::SpringPendulum {
ref mut bob,
ref mut state,
} => {
state.setv_bob(*bob);

// Run the spring pendulum simulation
runge_kutta::tick(&pendulum::spring::eval, state, props, anchor, dt);

*bob = state.getv_bob();

*bob
}
SimplePhysicsSystem::RigidPendulum(system) => system.tick(anchor, props, dt),
SimplePhysicsSystem::SpringPendulum(system) => system.tick(anchor, props, dt),
}
}
}
Expand Down
57 changes: 42 additions & 15 deletions inox2d/src/physics/pendulum/rigid.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use glam::Vec2;
use glam::{Vec2, vec2};

use crate::physics::runge_kutta::PhysicsState;
use crate::physics::runge_kutta::{PhysicsState, self};
use crate::physics::SimplePhysicsProps;

pub struct RigidPendulum;
/// Marker type for a rigid pendulum physics state
struct RigidPendulum;

impl PhysicsState<2, RigidPendulum> {
type RigidPendulumState = PhysicsState<2, RigidPendulum>;

impl RigidPendulumState {
// angle

pub fn getv_angle(&self) -> f32 {
Expand All @@ -16,9 +19,9 @@ impl PhysicsState<2, RigidPendulum> {
self.vars[0] = angle;
}

pub fn getd_angle(&self) -> f32 {
self.derivatives[0]
}
// pub fn getd_angle(&self) -> f32 {
// self.derivatives[0]
// }

pub fn setd_angle(&mut self, angle: f32) {
self.derivatives[0] = angle;
Expand All @@ -30,21 +33,21 @@ impl PhysicsState<2, RigidPendulum> {
self.vars[1]
}

pub fn setv_dangle(&mut self, dangle: f32) {
self.vars[1] = dangle;
}
// pub fn setv_dangle(&mut self, dangle: f32) {
// self.vars[1] = dangle;
// }

pub fn getd_dangle(&self) -> f32 {
self.derivatives[1]
}
// pub fn getd_dangle(&self) -> f32 {
// self.derivatives[1]
// }

pub fn setd_dangle(&mut self, dangle: f32) {
self.derivatives[1] = dangle;
}
}

pub fn eval(
state: &mut PhysicsState<2, RigidPendulum>,
fn eval(
state: &mut RigidPendulumState,
physics_props: &SimplePhysicsProps,
_anchor: Vec2,
_t: f32,
Expand All @@ -60,3 +63,27 @@ pub fn eval(

state.setd_dangle(dd);
}

#[derive(Debug, Clone, Default)]
pub struct RigidPendulumSystem {
pub bob: Vec2,
state: RigidPendulumState,
}

impl RigidPendulumSystem {
pub fn tick(&mut self, anchor: Vec2, props: &SimplePhysicsProps, dt: f32) -> Vec2 {
// Compute the angle against the updated anchor position
let d_bob = self.bob - anchor;
self.state.setv_angle(f32::atan2(-d_bob.x, d_bob.y));

// Run the pendulum simulation in terms of angle
runge_kutta::tick(&eval, &mut self.state, props, anchor, dt);

// Update the bob position at the new angle
let angle = self.state.getv_angle();
let d_bob = vec2(-angle.sin(), angle.cos());
self.bob = anchor + d_bob * props.length;

self.bob
}
}
56 changes: 36 additions & 20 deletions inox2d/src/physics/pendulum/spring.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::physics::runge_kutta::PhysicsState;
use crate::physics::runge_kutta::{PhysicsState, self};
use crate::physics::SimplePhysicsProps;
use glam::{vec2, Vec2};
use std::f32::consts::PI;

#[derive(Debug, Clone)]
pub struct SpringPendulum;
/// Marker type for a spring pendulum physics state
struct SpringPendulum;

impl PhysicsState<4, SpringPendulum> {
type SpringPendulumState = PhysicsState<4, SpringPendulum>;

impl SpringPendulumState {
// bob

pub fn getv_bob(&self) -> Vec2 {
Expand All @@ -18,9 +20,9 @@ impl PhysicsState<4, SpringPendulum> {
self.vars[1] = bob.y;
}

pub fn getd_bob(&self) -> Vec2 {
vec2(self.derivatives[0], self.derivatives[1])
}
// pub fn getd_bob(&self) -> Vec2 {
// vec2(self.derivatives[0], self.derivatives[1])
// }

pub fn setd_bob(&mut self, bob: Vec2) {
self.derivatives[0] = bob.x;
Expand All @@ -33,27 +35,22 @@ impl PhysicsState<4, SpringPendulum> {
vec2(self.vars[2], self.vars[3])
}

pub fn setv_dbob(&mut self, dbob: Vec2) {
self.vars[2] = dbob.x;
self.vars[3] = dbob.y;
}
// pub fn setv_dbob(&mut self, dbob: Vec2) {
// self.vars[2] = dbob.x;
// self.vars[3] = dbob.y;
// }

pub fn getd_dbob(&self) -> Vec2 {
vec2(self.derivatives[2], self.derivatives[3])
}
// pub fn getd_dbob(&self) -> Vec2 {
// vec2(self.derivatives[2], self.derivatives[3])
// }

pub fn setd_dbob(&mut self, dbob: Vec2) {
self.derivatives[2] = dbob.x;
self.derivatives[3] = dbob.y;
}
}

pub fn eval(
state: &mut PhysicsState<4, SpringPendulum>,
props: &SimplePhysicsProps,
anchor: Vec2,
_t: f32,
) {
fn eval(state: &mut SpringPendulumState, props: &SimplePhysicsProps, anchor: Vec2, _t: f32) {
state.setd_bob(state.getv_dbob());

// These are normalized vs. mass
Expand Down Expand Up @@ -93,3 +90,22 @@ pub fn eval(

state.setd_dbob(dd_bob);
}

#[derive(Debug, Clone, Default)]
pub struct SpringPendulumSystem {
pub bob: Vec2,
state: SpringPendulumState,
}

impl SpringPendulumSystem {
pub fn tick(&mut self, anchor: Vec2, props: &SimplePhysicsProps, dt: f32) -> Vec2 {
self.state.setv_bob(self.bob);

// Run the spring pendulum simulation
runge_kutta::tick(&eval, &mut self.state, props, anchor, dt);

self.bob = self.state.getv_bob();

self.bob
}
}
6 changes: 3 additions & 3 deletions inox2d/src/physics/simple_physics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ impl SimplePhysics {
}

pub fn update_anchor(&mut self) {
let new_bob = self.anchor + vec2(0.0, self.final_length());
let bob = self.anchor + vec2(0.0, self.final_length());

match &mut self.system {
SimplePhysicsSystem::RigidPendulum { ref mut bob, .. } => *bob = new_bob,
SimplePhysicsSystem::SpringPendulum { ref mut bob, .. } => *bob = new_bob,
SimplePhysicsSystem::RigidPendulum(system) => system.bob = bob,
SimplePhysicsSystem::SpringPendulum(system) => system.bob = bob,
}
}

Expand Down

0 comments on commit 60db181

Please sign in to comment.