1use std;
4use enumflags2;
5use derive_more::From;
6#[cfg(feature = "derive_serdes")]
7use serde::{Deserialize, Serialize};
8
9use crate::{force, geometry, math};
10
11#[expect(clippy::excessive_precision)]
12#[expect(clippy::unreadable_literal)]
13pub const MATERIAL_WOOD : Material = Material {
14 restitution: math::Normalized::noisy_f64 (0.6),
15 friction: math::NonNegative::noisy_f64 (0.63245553203367586639)
16 };
18#[expect(clippy::excessive_precision)]
19#[expect(clippy::unreadable_literal)]
20pub const MATERIAL_STONE : Material = Material {
21 restitution: math::Normalized::noisy_f64 (0.8),
22 friction: math::NonNegative::noisy_f64 (0.77459666924148337703)
23 };
25#[expect(clippy::excessive_precision)]
26#[expect(clippy::unreadable_literal)]
27pub const MATERIAL_COPPER : Material = Material {
28 restitution: math::Normalized::noisy_f64 (0.6),
29 friction: math::NonNegative::noisy_f64 (0.63245553203367586639)
30 };
32#[expect(clippy::excessive_precision)]
33#[expect(clippy::unreadable_literal)]
34pub const MATERIAL_BRONZE : Material = Material {
35 restitution: math::Normalized::noisy_f64 (0.6),
36 friction: math::NonNegative::noisy_f64 (0.54772255750516611345)
37 };
39pub const MATERIAL_LEATHER : Material = Material {
40 restitution: math::Normalized::noisy_f64 (0.1),
41 friction: math::NonNegative::noisy_f64 (std::f64::consts::FRAC_1_SQRT_2)
42 };
44
45#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
47#[derive(Clone, Copy, Debug, PartialEq, From)]
48pub struct Position (pub math::Point3 <f64>);
49
50#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
52#[derive(Clone, Copy, Debug, PartialEq)]
53pub struct Derivatives {
54 pub velocity : math::Vector3 <f64>,
56 pub acceleration : math::Vector3 <f64>,
58 pub force : math::Vector3 <f64>,
62 pub force_flags : enumflags2::BitFlags <force::Flag>
63}
64
65#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
67#[derive(Clone, Copy, Debug, PartialEq)]
68pub struct Drag (pub f64);
69
70#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
72#[derive(Clone, Debug, PartialEq, From)]
73pub struct Bound (pub geometry::shape::Variant <f64>);
74
75#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
77#[derive(Clone, Copy, Debug, PartialEq)]
78pub struct Mass {
79 mass : f64,
80 mass_reciprocal : f64
81}
82
83#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
85#[derive(Clone, Copy, Debug, PartialEq)]
86pub struct Material {
87 pub restitution : math::Normalized <f64>,
94 pub friction : math::NonNegative <f64>
101}
102
103impl Position {
104 #[inline]
105 pub fn origin() -> Self {
106 Position (math::Point::origin())
107 }
108}
109
110#[expect(non_snake_case)]
114mod bound {
115 use super::*;
116 macro impl_from_try_into {
117 ($shape:ident, $variant:ident) => {
118 impl From <geometry::shape::$shape <f64>> for Bound {
119 fn from ($shape : geometry::shape::$shape <f64>) -> Self {
120 Bound (geometry::shape::Variant::$variant ($shape.into()))
121 }
122 }
123 impl TryInto <geometry::shape::$shape <f64>> for Bound {
124 type Error = Self;
125 fn try_into (self) -> Result <geometry::shape::$shape <f64>, Self> {
126 geometry::shape::$variant::try_from (self.0).map_err (|err| Bound (err.input))
127 .and_then (|variant| geometry::shape::$shape::try_from (variant)
128 .map_err (|err| Bound (geometry::shape::Variant::$variant (err.input))))
129 }
130 }
131 }
132 }
133 impl_from_try_into!{Sphere, Bounded}
134 impl_from_try_into!{Capsule, Bounded}
135 impl_from_try_into!{Cylinder, Bounded}
136 impl_from_try_into!{Cone, Bounded}
137 impl_from_try_into!{Cube, Bounded}
138 impl_from_try_into!{Cuboid, Bounded}
139 impl_from_try_into!{Hull, Bounded}
140 impl_from_try_into!{Halfspace, Unbounded}
141 impl From <geometry::shape::Orthant> for Bound {
144 fn from (Orthant : geometry::shape::Orthant) -> Self {
145 Bound (geometry::shape::Variant::Unbounded (Orthant.into()))
146 }
147 }
148 impl TryInto <geometry::shape::Orthant> for Bound {
149 type Error = Self;
150 fn try_into (self) -> Result <geometry::shape::Orthant, Self> {
151 geometry::shape::Unbounded::try_from (self.0).map_err (|err| Bound (err.input))
152 .and_then (|variant| geometry::shape::Orthant::try_from (variant)
153 .map_err (|err| Bound (geometry::shape::Variant::Unbounded (err.input))))
154 }
155 }
156}
157
158impl Mass {
159 #[inline]
160 pub fn new (mass : f64) -> Self {
161 let mass_reciprocal = 1.0 / mass;
162 Self { mass, mass_reciprocal }
163 }
164 #[inline]
165 pub const fn mass (&self) -> f64 {
166 self.mass
167 }
168 #[inline]
169 pub const fn mass_reciprocal (&self) -> f64 {
170 self.mass_reciprocal
171 }
172 #[inline]
173 pub fn set_mass (&mut self, mass : f64) {
174 self.mass = mass;
175 self.mass_reciprocal = 1.0 / self.mass;
176 }
177}
178impl std::ops::Add <Self> for Mass {
179 type Output = Self;
180 fn add (self, rhs : Self) -> Self {
181 let mass = self.mass + rhs.mass;
182 let mass_reciprocal = 1.0 / mass;
183 Mass { mass, mass_reciprocal }
184 }
185}
186
187impl Derivatives {
188 #[inline]
189 pub fn zero() -> Self {
190 let velocity = math::Vector3::zero();
191 let acceleration = math::Vector3::zero();
192 let force = math::Vector3::zero();
193 let force_flags = enumflags2::BitFlags::all();
194 Derivatives { velocity, acceleration, force, force_flags }
195 }
196}
197
198impl Drag {
199 #[inline]
200 pub const fn zero() -> Self {
201 Drag (0.0)
202 }
203}