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