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