rhusics_core/
body_pose.rs1use cgmath::{BaseFloat, EuclideanSpace, InnerSpace, One, Rotation, Transform, VectorSpace};
2use collision::{Interpolate, TranslationInterpolate};
3
4use Pose;
5
6#[derive(Clone, Debug, PartialEq)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub struct BodyPose<P, R> {
10 dirty: bool,
11 position: P,
12 rotation: R,
13 inverse_rotation: R,
14}
15
16impl<P, R> Pose<P, R> for BodyPose<P, R>
17where
18 P: EuclideanSpace,
19 P::Scalar: BaseFloat,
20 R: Rotation<P>,
21{
22 fn new(position: P, rotation: R) -> Self {
25 Self {
26 dirty: true,
27 position,
28 inverse_rotation: rotation.invert(),
29 rotation,
30 }
31 }
32
33 fn set_rotation(&mut self, rotation: R) {
35 self.rotation = rotation;
36 self.inverse_rotation = self.rotation.invert();
37 self.dirty = true;
38 }
39
40 fn set_position(&mut self, position: P) {
42 self.position = position;
43 self.dirty = true;
44 }
45
46 fn rotation(&self) -> R {
48 self.rotation
49 }
50
51 fn position(&self) -> P {
53 self.position
54 }
55}
56
57impl<P, R> BodyPose<P, R>
58where
59 P: EuclideanSpace,
60 P::Scalar: BaseFloat,
61 R: Rotation<P>,
62{
63 pub fn clear(&mut self) {
65 self.dirty = false;
66 }
67}
68
69impl<P, R> Transform<P> for BodyPose<P, R>
70where
71 P: EuclideanSpace,
72 P::Scalar: BaseFloat,
73 R: Rotation<P>,
74{
75 fn one() -> Self {
76 Self::new(P::origin(), R::one())
77 }
78
79 fn look_at(eye: P, center: P, up: P::Diff) -> Self {
80 let rot = R::look_at(center - eye, up);
81 let disp = rot.rotate_vector(P::origin() - eye);
82 Self::new(P::from_vec(disp), rot)
83 }
84
85 fn transform_vector(&self, vec: P::Diff) -> P::Diff {
86 self.rotation.rotate_vector(vec)
87 }
88
89 fn inverse_transform_vector(&self, vec: P::Diff) -> Option<P::Diff> {
90 Some(self.inverse_rotation.rotate_vector(vec))
91 }
92
93 fn transform_point(&self, point: P) -> P {
94 self.rotation.rotate_point(point) + self.position.to_vec()
95 }
96
97 fn concat(&self, other: &Self) -> Self {
98 Self::new(
99 self.position + self.rotation.rotate_point(other.position).to_vec(),
100 self.rotation * other.rotation,
101 )
102 }
103
104 fn inverse_transform(&self) -> Option<Self> {
105 Some(Self::new(
106 self.rotation.rotate_point(self.position) * -P::Scalar::one(),
107 self.inverse_rotation,
108 ))
109 }
110}
111
112impl<P, R> TranslationInterpolate<P::Scalar> for BodyPose<P, R>
113where
114 P: EuclideanSpace,
115 P::Scalar: BaseFloat,
116 P::Diff: VectorSpace + InnerSpace,
117 R: Rotation<P> + Clone,
118{
119 fn translation_interpolate(&self, other: &Self, amount: P::Scalar) -> Self {
120 BodyPose::new(
121 P::from_vec(self.position.to_vec().lerp(other.position.to_vec(), amount)),
122 other.rotation,
123 )
124 }
125}
126
127impl<P, R> Interpolate<P::Scalar> for BodyPose<P, R>
128where
129 P: EuclideanSpace,
130 P::Scalar: BaseFloat,
131 P::Diff: VectorSpace + InnerSpace,
132 R: Rotation<P> + Interpolate<P::Scalar>,
133{
134 fn interpolate(&self, other: &Self, amount: P::Scalar) -> Self {
135 BodyPose::new(
136 P::from_vec(self.position.to_vec().lerp(other.position.to_vec(), amount)),
137 self.rotation.interpolate(&other.rotation, amount),
138 )
139 }
140}