1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! Components for use by entities.

use {std, cgmath, enumflags};

use {force, geometry};

pub const MATERIAL_WOOD : Material  = Material {
  restitution: 0.6, friction: 0.4
};
pub const MATERIAL_STONE : Material = Material {
  restitution: 0.8, friction: 0.6
};

/// A point in 3D space
#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
#[derive(Clone,Debug,PartialEq)]
pub struct Position (pub cgmath::Point3 <f64>);

/// First (velocity) and second (acceleration) time derivatives of position
#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
#[derive(Clone,Debug,PartialEq)]
pub struct Derivatives {
  /// First time derivative of position
  pub velocity     : cgmath::Vector3 <f64>,
  /// Second time derivative of position
  pub acceleration : cgmath::Vector3 <f64>,
  /// First time derivative of momentum.
  ///
  /// This vector is intended to be cleared and then accumulated each step.
  pub force        : cgmath::Vector3 <f64>,
  pub force_flags  : enumflags::BitFlags <force::Flag>
}

/// A bounding volume
#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
#[derive(Clone,Debug,PartialEq)]
pub struct Bound (pub geometry::shape::Variant <f64>);

/// A point mass; does *not* currently enforce that mass is nonzero or positive
#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
#[derive(Clone,Debug,PartialEq)]
pub struct Mass {
  mass            : f64,
  mass_reciprocal : f64
}

/// Surface material properties
#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
#[derive(Clone,Debug,PartialEq)]
pub struct Material {
  /// A generic restitution is in [0.0,1.0] with 1.0 being perfectly elastic and
  /// 0.0 perfectly inelastic.
  ///
  /// When a pair of material objects collide, their respective restitution
  /// coefficients are multiplied to give the restitution coefficient for that
  /// collision.
  pub restitution : f64,
  /// A generic friction coefficient is in [0.0,\infty] with 0.0 being perfectly
  /// frictionless and 1.0 being about equivalent to concrete on rubber.
  ///
  /// When a pair of material objects have contact, the average of their
  /// respective friction coefficients is computed to give the friction
  /// coefficient for that contact.
  pub friction    : f64
}

impl Position {
  #[inline]
  pub fn origin() -> Self {
    Position ([0.0, 0.0, 0.0].into())
  }
}

impl Mass {
  #[inline]
  pub fn new (mass : f64) -> Self {
    let mass_reciprocal = 1.0 / mass;
    Self { mass, mass_reciprocal }
  }
  #[inline]
  pub fn mass (&self) -> f64 {
    self.mass
  }
  #[inline]
  pub fn mass_reciprocal (&self) -> f64 {
    self.mass_reciprocal
  }
  #[inline]
  pub fn set_mass (&mut self, mass : f64) {
    self.mass = mass;
    self.mass_reciprocal = 1.0 / self.mass;
  }
}
impl std::ops::Add <Self> for Mass {
  type Output = Self;
  fn add (self, rhs : Self) -> Self {
    let mass = self.mass + rhs.mass;
    let mass_reciprocal = 1.0 / mass;
    Mass { mass, mass_reciprocal }
  }
}

impl Derivatives {
  #[inline]
  pub fn zero() -> Self {
    use cgmath::Zero;
    let velocity     = cgmath::Vector3::zero();
    let acceleration = cgmath::Vector3::zero();
    let force        = cgmath::Vector3::zero();
    let force_flags  = enumflags::BitFlags::all();
    Derivatives { velocity, acceleration, force, force_flags }
  }
}