inox2d/physics/
simple_physics.rs1use std::f32::consts::PI;
2
3use glam::{vec2, vec4, Vec2};
4
5use super::{ParamMapMode, SimplePhysics, SimplePhysicsSystem};
6use crate::puppet::PuppetPhysics;
7use crate::render::NodeRenderCtx;
8
9impl SimplePhysics {
10 fn update_inputs(&mut self, node_render_ctx: &NodeRenderCtx) {
11 let anchor_pos = match self.local_only {
12 true => node_render_ctx.trans_offset.translation.extend(1.0),
13 false => node_render_ctx.trans * vec4(0.0, 0.0, 0.0, 1.0),
14 };
15
16 self.anchor = vec2(anchor_pos.x, anchor_pos.y);
17 }
18
19 fn calc_outputs(&self, node_render_ctx: &NodeRenderCtx) -> Vec2 {
20 let oscale = self.final_output_scale();
21
22 let local_pos4 = match self.local_only {
28 true => vec4(self.output.x, self.output.y, 0.0, 1.0),
29 false => node_render_ctx.trans.inverse() * vec4(self.output.x, self.output.y, 0.0, 1.0),
30 };
31
32 let local_angle = vec2(local_pos4.x, local_pos4.y).normalize();
33
34 let relative_length = self.output.distance(self.anchor) / self.final_length();
36
37 let param_value = match self.map_mode {
38 ParamMapMode::XY => {
39 let local_pos_norm = local_angle * relative_length;
40 let mut result = local_pos_norm - Vec2::Y;
41 result.y = -result.y; result
43 }
44 ParamMapMode::AngleLength => {
45 let a = f32::atan2(-local_angle.x, local_angle.y) / PI;
46 vec2(a, relative_length)
47 }
48 };
49
50 param_value * oscale
51 }
52
53 pub fn update(&mut self, dt: f32, puppet_physics: PuppetPhysics, node_render_ctx: &NodeRenderCtx) -> Vec2 {
54 let mut h = dt.min(10.);
57
58 self.update_inputs(node_render_ctx);
59
60 while h > 0.01 {
62 self.tick(0.01, puppet_physics);
63 h -= 0.01;
64 }
65
66 self.tick(h, puppet_physics);
67
68 self.calc_outputs(node_render_ctx)
69 }
70
71 pub fn update_anchor(&mut self) {
72 let bob = self.anchor + vec2(0.0, self.final_length());
73
74 match &mut self.system {
75 SimplePhysicsSystem::RigidPendulum(system) => system.bob = bob,
76 SimplePhysicsSystem::SpringPendulum(system) => system.bob = bob,
77 }
78 }
79
80 pub fn final_gravity(&self, puppet_physics: &PuppetPhysics) -> f32 {
81 (self.props.gravity * self.offset_props.gravity) * puppet_physics.gravity * puppet_physics.pixels_per_meter
82 }
83
84 pub fn final_length(&self) -> f32 {
85 self.props.length * self.offset_props.length
86 }
87
88 pub fn final_frequency(&self) -> f32 {
89 self.props.frequency * self.offset_props.frequency
90 }
91
92 pub fn final_angle_damping(&self) -> f32 {
93 self.props.angle_damping * self.offset_props.angle_damping
94 }
95
96 pub fn final_length_damping(&self) -> f32 {
97 self.props.length_damping * self.offset_props.length_damping
98 }
99
100 pub fn final_output_scale(&self) -> Vec2 {
101 self.props.output_scale * self.offset_props.output_scale
102 }
103}