three_d/renderer/object/
instanced_model.rs1use crate::renderer::*;
2
3pub struct InstancedModelPart<M: Material> {
7 gm: Gm<InstancedMesh, M>,
8 animations: Vec<KeyFrameAnimation>,
9}
10
11impl<M: Material> InstancedModelPart<M> {
12 pub fn animations(&self) -> Vec<Option<String>> {
16 self.animations
17 .iter()
18 .map(|animation| animation.name.clone())
19 .collect()
20 }
21
22 pub fn choose_animation(&mut self, animation_name: Option<&str>) {
26 if let Some(animation) = self
27 .animations
28 .iter()
29 .find(|a| animation_name == a.name.as_deref())
30 .cloned()
31 {
32 self.set_animation(move |time| animation.transformation(time));
33 }
34 }
35}
36
37impl<'a, M: Material> IntoIterator for &'a InstancedModelPart<M> {
38 type Item = &'a dyn Object;
39 type IntoIter = std::iter::Once<&'a dyn Object>;
40
41 fn into_iter(self) -> Self::IntoIter {
42 self.gm.into_iter()
43 }
44}
45
46use std::ops::Deref;
47impl<M: Material> Deref for InstancedModelPart<M> {
48 type Target = Gm<InstancedMesh, M>;
49 fn deref(&self) -> &Self::Target {
50 &self.gm
51 }
52}
53
54impl<M: Material> std::ops::DerefMut for InstancedModelPart<M> {
55 fn deref_mut(&mut self) -> &mut Self::Target {
56 &mut self.gm
57 }
58}
59
60impl<M: Material> Geometry for InstancedModelPart<M> {
61 impl_geometry_body!(deref);
62
63 fn animate(&mut self, time: f32) {
64 self.gm.animate(time)
65 }
66}
67
68impl<M: Material> Object for InstancedModelPart<M> {
69 impl_object_body!(deref);
70}
71
72pub struct InstancedModel<M: Material>(Vec<InstancedModelPart<M>>);
76
77impl<'a, M: Material> IntoIterator for &'a InstancedModel<M> {
78 type Item = &'a dyn Object;
79 type IntoIter = std::vec::IntoIter<&'a dyn Object>;
80
81 fn into_iter(self) -> Self::IntoIter {
82 self.iter()
83 .map(|m| m as &dyn Object)
84 .collect::<Vec<_>>()
85 .into_iter()
86 }
87}
88
89impl<M: Material + FromCpuMaterial + Clone + Default> InstancedModel<M> {
90 pub fn new(
95 context: &Context,
96 instances: &Instances,
97 cpu_model: &CpuModel,
98 ) -> Result<Self, RendererError> {
99 let materials = cpu_model
100 .materials
101 .iter()
102 .map(|m| M::from_cpu_material(context, m))
103 .collect::<Vec<_>>();
104 let mut gms = Vec::new();
105 for primitive in cpu_model.geometries.iter() {
106 if let CpuGeometry::Triangles(geometry) = &primitive.geometry {
107 let material = if let Some(material_index) = primitive.material_index {
108 materials
109 .get(material_index)
110 .ok_or_else(|| {
111 RendererError::MissingMaterial(
112 material_index.to_string(),
113 primitive.name.clone(),
114 )
115 })?
116 .clone()
117 } else {
118 M::default()
119 };
120 let mut gm = Gm {
121 geometry: InstancedMesh::new(context, instances, geometry),
122 material,
123 };
124 gm.set_transformation(primitive.transformation);
125 gms.push(InstancedModelPart {
126 gm,
127 animations: primitive.animations.clone(),
128 });
129 }
130 }
131 let mut model = Self(gms);
132 if let Some(animation_name) = model.animations().first().cloned() {
133 model.choose_animation(animation_name.as_deref());
134 }
135 Ok(model)
136 }
137
138 pub fn animations(&self) -> Vec<Option<String>> {
142 let mut set = std::collections::HashSet::new();
143 for model_part in self.0.iter() {
144 set.extend(model_part.animations());
145 }
146 set.into_iter().collect()
147 }
148
149 pub fn choose_animation(&mut self, animation_name: Option<&str>) {
153 for part in self.0.iter_mut() {
154 part.choose_animation(animation_name);
155 }
156 }
157
158 pub fn animate(&mut self, time: f32) {
162 self.iter_mut().for_each(|m| m.animate(time));
163 }
164}
165
166impl<M: Material> std::ops::Deref for InstancedModel<M> {
167 type Target = Vec<InstancedModelPart<M>>;
168 fn deref(&self) -> &Self::Target {
169 &self.0
170 }
171}
172
173impl<M: Material> std::ops::DerefMut for InstancedModel<M> {
174 fn deref_mut(&mut self) -> &mut Self::Target {
175 &mut self.0
176 }
177}