linear_sim/
component.rs

1//! Components for use by entities.
2
3use {std, enumflags2};
4use derive_more::From;
5#[cfg(feature = "derive_serdes")]
6use serde::{Deserialize, Serialize};
7
8use crate::{force, geometry, math};
9
10#[allow(clippy::excessive_precision)]
11pub const MATERIAL_WOOD    : Material  = Material {
12  restitution: 0.6, friction: 0.63245553203367586639
13  //restitution: 0.6, friction: 0.4
14};
15#[allow(clippy::excessive_precision)]
16pub const MATERIAL_STONE   : Material = Material {
17  restitution: 0.8, friction: 0.77459666924148337703
18  //restitution: 0.8, friction: 0.6
19};
20#[allow(clippy::excessive_precision)]
21pub const MATERIAL_COPPER  : Material = Material {
22  restitution: 0.6, friction: 0.63245553203367586639
23  //restitution: 0.15, friction: 0.4
24};
25#[allow(clippy::excessive_precision)]
26pub const MATERIAL_BRONZE  : Material = Material {
27  restitution: 0.6, friction: 0.54772255750516611345
28  //restitution: 0.6, friction: 0.3
29};
30pub const MATERIAL_LEATHER : Material = Material {
31  restitution: 0.1, friction: std::f64::consts::FRAC_1_SQRT_2
32  //restitution: 0.1, friction: 0.5
33};
34
35/// A point in 3D space
36#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
37#[derive(Clone, Debug, PartialEq, From)]
38pub struct Position (pub math::Point3 <f64>);
39
40/// First (velocity) and second (acceleration) time derivatives of position
41#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
42#[derive(Clone, Debug, PartialEq)]
43pub struct Derivatives {
44  /// First time derivative of position
45  pub velocity     : math::Vector3 <f64>,
46  /// Second time derivative of position
47  pub acceleration : math::Vector3 <f64>,
48  /// First time derivative of momentum.
49  ///
50  /// This vector is intended to be cleared and then accumulated each step.
51  pub force        : math::Vector3 <f64>,
52  pub force_flags  : enumflags2::BitFlags <force::Flag>
53}
54
55/// A drag coefficient for dynamic objects
56#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
57#[derive(Clone, Debug, PartialEq)]
58pub struct Drag (pub f64);
59
60/// A bounding volume
61#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
62#[derive(Clone, Debug, PartialEq, From)]
63pub struct Bound (pub geometry::shape::Variant <f64>);
64
65/// A point mass; does *not* currently enforce that mass is nonzero or positive
66#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
67#[derive(Clone, Debug, PartialEq)]
68pub struct Mass {
69  mass            : f64,
70  mass_reciprocal : f64
71}
72
73/// Surface material properties
74#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
75#[derive(Clone, Debug, PartialEq)]
76pub struct Material {
77  /// A generic restitution is in [0.0,1.0] with 1.0 being perfectly elastic and
78  /// 0.0 perfectly inelastic.
79  ///
80  /// When a pair of material objects collide, their respective restitution
81  /// coefficients are multiplied to give the restitution coefficient for that
82  /// collision.
83  pub restitution : f64,
84  /// A generic friction coefficient is in [0.0,\infty] with 0.0 being perfectly
85  /// frictionless and 1.0 being about equivalent to concrete on rubber.
86  ///
87  /// When a pair of material objects have contact, the average of their
88  /// respective friction coefficients is computed to give the friction
89  /// coefficient for that contact.
90  pub friction    : f64
91}
92
93impl Position {
94  #[inline]
95  pub fn origin() -> Self {
96    Position ([0.0, 0.0, 0.0].into())
97  }
98}
99
100impl Mass {
101  #[inline]
102  pub fn new (mass : f64) -> Self {
103    let mass_reciprocal = 1.0 / mass;
104    Self { mass, mass_reciprocal }
105  }
106  #[inline]
107  pub fn mass (&self) -> f64 {
108    self.mass
109  }
110  #[inline]
111  pub fn mass_reciprocal (&self) -> f64 {
112    self.mass_reciprocal
113  }
114  #[inline]
115  pub fn set_mass (&mut self, mass : f64) {
116    self.mass = mass;
117    self.mass_reciprocal = 1.0 / self.mass;
118  }
119}
120impl std::ops::Add <Self> for Mass {
121  type Output = Self;
122  fn add (self, rhs : Self) -> Self {
123    let mass = self.mass + rhs.mass;
124    let mass_reciprocal = 1.0 / mass;
125    Mass { mass, mass_reciprocal }
126  }
127}
128
129impl Derivatives {
130  #[inline]
131  pub fn zero() -> Self {
132    let velocity     = math::Vector3::zero();
133    let acceleration = math::Vector3::zero();
134    let force        = math::Vector3::zero();
135    let force_flags  = enumflags2::BitFlags::all();
136    Derivatives { velocity, acceleration, force, force_flags }
137  }
138}
139
140impl Drag {
141  #[inline]
142  pub fn zero() -> Self {
143    Drag (0.0)
144  }
145}