nphysics3d/material/
material.rs1use downcast_rs::Downcast;
2use na::{self, RealField};
3use std::ops::Deref;
4use std::sync::Arc;
5
6use ncollide::query::TrackedContact;
7use ncollide::shape::Shape;
8
9use crate::material::MaterialsCoefficientsTable;
10use crate::math::{Isometry, Vector};
11
12#[derive(Copy, Clone)]
14pub struct MaterialContext<'a, N: RealField + Copy> {
15 pub shape: &'a dyn Shape<N>,
17 pub position: &'a Isometry<N>,
19 pub contact: &'a TrackedContact<N>,
21 pub is_first: bool,
26}
27
28impl<'a, N: RealField + Copy> MaterialContext<'a, N> {
29 pub(crate) fn new(
30 shape: &'a dyn Shape<N>,
31 position: &'a Isometry<N>,
32 contact: &'a TrackedContact<N>,
33 is_first: bool,
34 ) -> Self {
35 MaterialContext {
36 shape,
37 position,
38 contact,
39 is_first,
40 }
41 }
42}
43
44#[derive(Copy, Clone, Debug)]
46pub enum MaterialCombineMode {
47 Average,
49 Min,
53 Multiply,
57 Max,
61 Lookup, }
65
66impl MaterialCombineMode {
67 #[inline]
72 pub fn combine<N: RealField + Copy>(a: (N, Self), b: (N, Self)) -> (N, MaterialCombineMode) {
73 match (a.1, b.1) {
74 (MaterialCombineMode::Max, _) | (_, MaterialCombineMode::Max) => {
75 (a.0.max(b.0), MaterialCombineMode::Max)
76 }
77 (MaterialCombineMode::Multiply, _) | (_, MaterialCombineMode::Multiply) => {
78 (a.0 * b.0, MaterialCombineMode::Multiply)
79 }
80 (MaterialCombineMode::Min, _) | (_, MaterialCombineMode::Min) => {
81 (a.0.min(b.0), MaterialCombineMode::Min)
82 }
83 _ => ((a.0 + b.0) * na::convert(0.5), MaterialCombineMode::Average),
85 }
86 }
87}
88
89pub struct LocalMaterialProperties<N: RealField + Copy> {
91 pub id: Option<MaterialId>,
93 pub friction: (N, MaterialCombineMode),
95 pub restitution: (N, MaterialCombineMode),
97 pub surface_velocity: Vector<N>,
99}
100
101pub trait MaterialClone<N: RealField + Copy> {
103 fn clone_box(&self) -> Box<dyn Material<N>> {
105 unimplemented!()
106 }
107}
108
109pub type MaterialId = u32;
111
112impl<N: RealField + Copy, T: 'static + Material<N> + Clone> MaterialClone<N> for T {
113 fn clone_box(&self) -> Box<dyn Material<N>> {
114 Box::new(self.clone())
115 }
116}
117
118pub trait Material<N: RealField + Copy>: Downcast + Send + Sync + MaterialClone<N> {
120 fn local_properties(&self, context: MaterialContext<N>) -> LocalMaterialProperties<N>;
122}
123
124impl_downcast!(Material<N> where N: RealField + Copy);
125
126impl<N: RealField + Copy> Clone for Box<dyn Material<N>> {
127 fn clone(&self) -> Box<dyn Material<N>> {
128 self.clone_box()
129 }
130}
131
132impl<N: RealField + Copy> dyn Material<N> {
133 pub fn combine<M1, M2>(
135 table: &MaterialsCoefficientsTable<N>,
136 material1: &M1,
137 context1: MaterialContext<N>,
138 material2: &M2,
139 context2: MaterialContext<N>,
140 ) -> LocalMaterialProperties<N>
141 where
142 M1: ?Sized + Material<N>,
143 M2: ?Sized + Material<N>,
144 {
145 let props1 = material1.local_properties(context1);
146 let props2 = material2.local_properties(context2);
147 let restitution;
148 let friction;
149
150 match (props1.id, props2.id) {
151 (Some(id1), Some(id2)) => {
152 restitution = table
153 .restitution_coefficient(id1, id2)
154 .map(|coeff| (coeff, MaterialCombineMode::Lookup))
155 .unwrap_or_else(|| {
156 MaterialCombineMode::combine(props1.restitution, props2.restitution)
157 });
158 friction = table
159 .friction_coefficient(id1, id2)
160 .map(|coeff| (coeff, MaterialCombineMode::Lookup))
161 .unwrap_or_else(|| {
162 MaterialCombineMode::combine(props1.friction, props2.friction)
163 });
164 }
165 _ => {
166 restitution = MaterialCombineMode::combine(props1.restitution, props2.restitution);
167 friction = MaterialCombineMode::combine(props1.friction, props2.friction);
168 }
169 }
170
171 LocalMaterialProperties {
172 id: None,
173 friction,
174 restitution,
175 surface_velocity: props1.surface_velocity - props2.surface_velocity,
176 }
177 }
178}
179
180#[derive(Clone)]
184pub struct MaterialHandle<N: RealField + Copy>(Arc<Box<dyn Material<N>>>);
185
186impl<N: RealField + Copy> MaterialHandle<N> {
187 #[inline]
189 pub fn new<S: Material<N> + Clone>(material: S) -> MaterialHandle<N> {
190 MaterialHandle(Arc::new(Box::new(material)))
191 }
192
193 pub(crate) fn make_mut(&mut self) -> &mut dyn Material<N> {
194 &mut **Arc::make_mut(&mut self.0)
195 }
196}
197
198impl<N: RealField + Copy> AsRef<dyn Material<N>> for MaterialHandle<N> {
199 #[inline]
200 fn as_ref(&self) -> &dyn Material<N> {
201 &*self.deref()
202 }
203}
204
205impl<N: RealField + Copy> Deref for MaterialHandle<N> {
206 type Target = dyn Material<N>;
207
208 #[inline]
209 fn deref(&self) -> &dyn Material<N> {
210 &**self.0.deref()
211 }
212}