1use crate::{PhysicsAccessView, Scalar};
2use anput::{
3 entity::Entity,
4 query::TypedLookupFetch,
5 world::{Relation, World},
6};
7use serde::{Deserialize, Serialize};
8use vek::{Mat4, Quaternion, Vec3};
9
10#[derive(Clone)]
11pub struct BodyAccessInfo {
12 pub entity: Entity,
13 pub view: PhysicsAccessView,
14}
15
16impl BodyAccessInfo {
17 pub fn new(entity: Entity, view: PhysicsAccessView) -> Self {
18 Self { entity, view }
19 }
20
21 pub fn of_world(entity: Entity, world: &World) -> Self {
22 Self::new(entity, PhysicsAccessView::new(world))
23 }
24
25 pub fn particles<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING> + 'a>(
26 &'a self,
27 ) -> impl Iterator<Item = Fetch::Value> + 'a {
28 self.view
29 .entity::<LOCKING, &Relation<BodyParticleRelation>>(self.entity)
30 .map(|relations| self.view.lookup::<LOCKING, Fetch>(relations.entities()))
31 .into_iter()
32 .flatten()
33 }
34
35 pub fn world_space_particles<
36 'a,
37 const LOCKING: bool,
38 Fetch: TypedLookupFetch<'a, LOCKING> + 'a,
39 >(
40 &'a self,
41 ) -> impl Iterator<Item = (Mat4<Scalar>, Fetch::Value)> + 'a {
42 self.view
43 .entity::<LOCKING, &Relation<BodyParticleRelation>>(self.entity)
44 .map(|relations| {
45 self.view
46 .lookup::<LOCKING, (&Position, Option<&Rotation>, Fetch)>(relations.entities())
47 .map(|(position, rotation, value)| {
48 let matrix = rotation
49 .map(|rotation| Mat4::from(rotation.current))
50 .unwrap_or_default()
51 * Mat4::translation_3d(position.current);
52 (matrix, value)
53 })
54 })
55 .into_iter()
56 .flatten()
57 }
58
59 pub fn density_fields<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING> + 'a>(
60 &'a self,
61 ) -> impl Iterator<Item = Fetch::Value> + 'a {
62 self.view
63 .entity::<LOCKING, &Relation<BodyDensityFieldRelation>>(self.entity)
64 .map(|relations| self.view.lookup::<LOCKING, Fetch>(relations.entities()))
65 .into_iter()
66 .flatten()
67 }
68}
69
70pub struct PhysicsBody;
71pub struct PhysicsParticle;
72pub struct BodyParticleRelation;
73pub struct BodyDensityFieldRelation;
74pub struct ParticleConstraintRelation;
75pub struct BodyParentRelation;
76
77#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
78pub struct Mass {
79 value: Scalar,
80 inverse: Scalar,
81}
82
83impl Mass {
84 pub fn new(value: Scalar) -> Self {
85 Self {
86 value,
87 inverse: if value != 0.0 { 1.0 / value } else { 0.0 },
88 }
89 }
90
91 pub fn new_inverse(inverse: Scalar) -> Self {
92 Self {
93 value: if inverse != 0.0 { 1.0 / inverse } else { 0.0 },
94 inverse,
95 }
96 }
97
98 pub fn value(&self) -> Scalar {
99 self.value
100 }
101
102 pub fn inverse(&self) -> Scalar {
103 self.inverse
104 }
105}
106
107impl PartialEq for Mass {
108 fn eq(&self, other: &Self) -> bool {
109 self.value == other.value
110 }
111}
112
113#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
114pub struct Position {
115 pub current: Vec3<Scalar>,
116 previous: Vec3<Scalar>,
117}
118
119impl Position {
120 pub fn new(current: impl Into<Vec3<Scalar>>) -> Self {
121 let current = current.into();
122 Self {
123 current,
124 previous: current,
125 }
126 }
127
128 pub fn previous(&self) -> Vec3<Scalar> {
129 self.previous
130 }
131
132 pub fn change(&self) -> Vec3<Scalar> {
133 self.current - self.previous
134 }
135
136 pub fn cache_current_as_previous(&mut self) {
137 self.previous = self.current;
138 }
139}
140
141impl PartialEq for Position {
142 fn eq(&self, other: &Self) -> bool {
143 self.current == other.current
144 }
145}
146
147#[derive(Debug, Default, Clone, Copy, PartialEq, Serialize, Deserialize)]
148pub struct Rotation {
149 pub current: Quaternion<Scalar>,
150 previous: Quaternion<Scalar>,
151}
152
153impl Rotation {
154 pub fn new(current: impl Into<Quaternion<Scalar>>) -> Self {
155 let current = current.into();
156 Self {
157 current,
158 previous: current,
159 }
160 }
161
162 pub fn previous(&self) -> Quaternion<Scalar> {
163 self.previous
164 }
165
166 pub fn change(&self) -> Quaternion<Scalar> {
167 self.current * self.previous.conjugate()
168 }
169
170 pub fn cache_current_as_previous(&mut self) {
171 self.previous = self.current;
172 }
173}
174
175#[derive(Debug, Default, Clone, Copy, PartialEq, Serialize, Deserialize)]
176#[repr(transparent)]
177pub struct LinearVelocity {
178 pub value: Vec3<Scalar>,
179}
180
181impl LinearVelocity {
182 pub fn new(value: impl Into<Vec3<Scalar>>) -> Self {
183 Self {
184 value: value.into(),
185 }
186 }
187}
188
189#[derive(Debug, Default, Clone, Copy, PartialEq, Serialize, Deserialize)]
190#[repr(transparent)]
191pub struct AngularVelocity {
192 pub value: Vec3<Scalar>,
193}
194
195impl AngularVelocity {
196 pub fn new(value: impl Into<Vec3<Scalar>>) -> Self {
197 Self {
198 value: value.into(),
199 }
200 }
201}
202
203#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
204pub struct ExternalForces {
205 pub force: Vec3<Scalar>,
206 pub torque: Vec3<Scalar>,
207 pub linear_impulse: Vec3<Scalar>,
208 pub angular_impulse: Vec3<Scalar>,
209}
210
211impl ExternalForces {
212 pub fn accumulate_force(&mut self, force: Vec3<Scalar>) {
213 self.force += force;
214 }
215
216 pub fn accumulate_torque(&mut self, torque: Vec3<Scalar>) {
217 self.torque += torque;
218 }
219
220 pub fn accumulate_linear_impulse(&mut self, impulse: Vec3<Scalar>) {
221 self.linear_impulse += impulse;
222 }
223
224 pub fn accumulate_angular_impulse(&mut self, impulse: Vec3<Scalar>) {
225 self.angular_impulse += impulse;
226 }
227
228 pub fn clear_continuous(&mut self) {
229 self.force = Vec3::zero();
230 self.torque = Vec3::zero();
231 }
232
233 pub fn clear_instantaneous(&mut self) {
234 self.linear_impulse = Vec3::zero();
235 self.angular_impulse = Vec3::zero();
236 }
237
238 pub fn clear(&mut self) {
239 self.clear_continuous();
240 self.clear_instantaneous();
241 }
242}
243
244#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
245pub struct Gravity {
246 pub value: Vec3<Scalar>,
247}
248
249#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
250pub struct BodyMaterial {
251 pub friction: Scalar,
252 pub restitution: Scalar,
253}
254
255impl Default for BodyMaterial {
256 fn default() -> Self {
257 Self {
258 friction: 0.5,
259 restitution: 0.5,
260 }
261 }
262}
263
264#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
265pub struct ParticleMaterial {
266 pub linear_damping: Scalar,
267 pub angular_damping: Scalar,
268 pub linear_rest_threshold: Scalar,
269 pub angular_rest_threshold: Scalar,
270}
271
272impl Default for ParticleMaterial {
273 fn default() -> Self {
274 Self {
275 linear_damping: 0.9,
276 angular_damping: 0.9,
277 linear_rest_threshold: 0.05,
278 angular_rest_threshold: 0.05,
279 }
280 }
281}