three_d/renderer/geometry/
instanced_mesh.rs1use crate::core::*;
2use crate::renderer::*;
3use std::sync::RwLock;
4
5use super::BaseMesh;
6
7pub struct InstancedMesh {
11 context: Context,
12 base_mesh: BaseMesh,
13 transform: RwLock<(
14 InstanceBuffer<Vec4>,
15 InstanceBuffer<Vec4>,
16 InstanceBuffer<Vec4>,
17 )>,
18 indices: RwLock<Vec<usize>>,
19 tex_transform: RwLock<Option<(InstanceBuffer<Vec3>, InstanceBuffer<Vec3>)>>,
20 instance_color: RwLock<Option<InstanceBuffer<Vec4>>>,
21 last_camera_position: RwLock<Option<Vec3>>,
22 aabb: AxisAlignedBoundingBox, transformation: Mat4,
24 current_transformation: Mat4,
25 animation: Option<Box<dyn Fn(f32) -> Mat4 + Send + Sync>>,
26 instances: Instances,
27}
28
29impl InstancedMesh {
30 pub fn new(context: &Context, instances: &Instances, cpu_mesh: &CpuMesh) -> Self {
36 #[cfg(debug_assertions)]
37 instances.validate().expect("invalid instances");
38
39 let aabb = cpu_mesh.compute_aabb();
40 let instanced_mesh = Self {
41 context: context.clone(),
42 base_mesh: BaseMesh::new(context, cpu_mesh),
43 transform: RwLock::new((
44 InstanceBuffer::<Vec4>::new(context),
45 InstanceBuffer::<Vec4>::new(context),
46 InstanceBuffer::<Vec4>::new(context),
47 )),
48 tex_transform: RwLock::new(None),
49 instance_color: RwLock::new(None),
50 last_camera_position: RwLock::new(None),
51 indices: RwLock::new((0..instances.transformations.len()).collect::<Vec<usize>>()),
52 aabb,
53 transformation: Mat4::identity(),
54 current_transformation: Mat4::identity(),
55 animation: None,
56 instances: instances.clone(),
57 };
58 instanced_mesh.update_instance_buffers();
59 instanced_mesh
60 }
61
62 pub fn transformation(&self) -> Mat4 {
66 self.transformation
67 }
68
69 pub fn set_transformation(&mut self, transformation: Mat4) {
74 self.transformation = transformation;
75 self.current_transformation = transformation;
76 *self.last_camera_position.write().unwrap() = None;
77 }
78
79 pub fn set_animation(&mut self, animation: impl Fn(f32) -> Mat4 + Send + Sync + 'static) {
85 self.animation = Some(Box::new(animation));
86 }
87
88 pub fn instance_count(&self) -> u32 {
90 self.instances.count()
91 }
92
93 pub fn set_instances(&mut self, instances: &Instances) {
97 #[cfg(debug_assertions)]
98 instances.validate().expect("invalid instances");
99 self.instances = instances.clone();
100 *self.indices.write().unwrap() =
101 (0..instances.transformations.len()).collect::<Vec<usize>>();
102 *self.last_camera_position.write().unwrap() = None;
103
104 self.update_instance_buffers();
105 }
106
107 fn update_instance_buffers(&self) {
111 let indices = self.indices.read().unwrap();
112 let mut row1 = Vec::new();
113 let mut row2 = Vec::new();
114 let mut row3 = Vec::new();
115 for transformation in indices.iter().map(|i| self.instances.transformations[*i]) {
116 row1.push(transformation.row(0));
117 row2.push(transformation.row(1));
118 row3.push(transformation.row(2));
119 }
120
121 *self.transform.write().unwrap() = (
122 InstanceBuffer::new_with_data(&self.context, &row1),
123 InstanceBuffer::new_with_data(&self.context, &row2),
124 InstanceBuffer::new_with_data(&self.context, &row3),
125 );
126
127 *self.tex_transform.write().unwrap() =
128 self.instances
129 .texture_transformations
130 .as_ref()
131 .map(|texture_transforms| {
132 let mut instance_tex_transform1 = Vec::new();
133 let mut instance_tex_transform2 = Vec::new();
134 for texture_transform in indices.iter().map(|i| texture_transforms[*i]) {
135 instance_tex_transform1.push(vec3(
136 texture_transform.x.x,
137 texture_transform.y.x,
138 texture_transform.z.x,
139 ));
140 instance_tex_transform2.push(vec3(
141 texture_transform.x.y,
142 texture_transform.y.y,
143 texture_transform.z.y,
144 ));
145 }
146 (
147 InstanceBuffer::new_with_data(&self.context, &instance_tex_transform1),
148 InstanceBuffer::new_with_data(&self.context, &instance_tex_transform2),
149 )
150 });
151 *self.instance_color.write().unwrap() =
152 self.instances.colors.as_ref().map(|instance_colors| {
153 let ordered_instance_colors = indices
154 .iter()
155 .map(|i| instance_colors[*i].to_linear_srgb())
156 .collect::<Vec<_>>();
157 InstanceBuffer::new_with_data(&self.context, &ordered_instance_colors)
158 });
159 }
160}
161
162impl<'a> IntoIterator for &'a InstancedMesh {
163 type Item = &'a dyn Geometry;
164 type IntoIter = std::iter::Once<&'a dyn Geometry>;
165
166 fn into_iter(self) -> Self::IntoIter {
167 std::iter::once(self)
168 }
169}
170
171impl Geometry for InstancedMesh {
172 fn draw(&self, viewer: &dyn Viewer, program: &Program, render_states: RenderStates) {
173 if render_states.blend != Blend::Disabled
175 && self
176 .last_camera_position
177 .read()
178 .unwrap()
179 .map(|p| p.distance2(viewer.position()) > 0.001)
180 .unwrap_or(true)
181 {
182 *self.last_camera_position.write().unwrap() = Some(viewer.position());
183 let distances = self
184 .instances
185 .transformations
186 .iter()
187 .map(|m| {
188 (m * self.current_transformation)
189 .w
190 .truncate()
191 .distance2(viewer.position())
192 })
193 .collect::<Vec<_>>();
194 self.indices.write().unwrap().sort_by(|a, b| {
195 distances[*b]
196 .partial_cmp(&distances[*a])
197 .unwrap_or(std::cmp::Ordering::Equal)
198 });
199 self.update_instance_buffers();
200 }
201
202 program.use_uniform("viewProjection", viewer.projection() * viewer.view());
203 program.use_uniform("modelMatrix", self.current_transformation);
204
205 let (row1, row2, row3) = &*self.transform.read().unwrap();
206 program.use_instance_attribute("row1", row1);
207 program.use_instance_attribute("row2", row2);
208 program.use_instance_attribute("row3", row3);
209
210 if program.requires_attribute("tex_transform_row1") {
211 if let Some((row1, row2)) = &*self.tex_transform.read().unwrap() {
212 program.use_instance_attribute("tex_transform_row1", row1);
213 program.use_instance_attribute("tex_transform_row2", row2);
214 }
215 }
216
217 if program.requires_attribute("instance_color") {
218 if let Some(color) = &*self.instance_color.read().unwrap() {
219 program.use_instance_attribute("instance_color", color);
220 }
221 }
222
223 self.base_mesh
224 .draw_instanced(program, render_states, viewer, self.instance_count());
225 }
226
227 fn vertex_shader_source(&self) -> String {
228 format!(
229 "#define USE_INSTANCE_TRANSFORMS\n{}{}{}",
230 if self.instance_color.read().unwrap().is_some() {
231 "#define USE_INSTANCE_COLORS\n"
232 } else {
233 ""
234 },
235 if self.tex_transform.read().unwrap().is_some() {
236 "#define USE_INSTANCE_TEXTURE_TRANSFORMATION\n"
237 } else {
238 ""
239 },
240 self.base_mesh.vertex_shader_source()
241 )
242 }
243
244 fn id(&self) -> GeometryId {
245 GeometryId::InstancedMesh(
246 self.base_mesh.normals.is_some(),
247 self.base_mesh.tangents.is_some(),
248 self.base_mesh.uvs.is_some(),
249 self.base_mesh.colors.is_some(),
250 self.instance_color.read().unwrap().is_some(),
251 self.tex_transform.read().unwrap().is_some(),
252 )
253 }
254
255 fn aabb(&self) -> AxisAlignedBoundingBox {
256 let mut aabb = AxisAlignedBoundingBox::EMPTY;
257 let local_aabb = self.aabb.transformed(self.current_transformation);
258 for transformation in &self.instances.transformations {
259 aabb.expand_with_aabb(local_aabb.transformed(*transformation));
260 }
261 aabb
262 }
263
264 fn animate(&mut self, time: f32) {
265 if let Some(animation) = &self.animation {
266 self.current_transformation = self.transformation * animation(time);
267 *self.last_camera_position.write().unwrap() = None;
268 }
269 }
270
271 fn render_with_material(
272 &self,
273 material: &dyn Material,
274 viewer: &dyn Viewer,
275 lights: &[&dyn Light],
276 ) {
277 render_with_material(&self.context, viewer, self, material, lights)
278 }
279
280 fn render_with_effect(
281 &self,
282 material: &dyn Effect,
283 viewer: &dyn Viewer,
284 lights: &[&dyn Light],
285 color_texture: Option<ColorTexture>,
286 depth_texture: Option<DepthTexture>,
287 ) {
288 render_with_effect(
289 &self.context,
290 viewer,
291 self,
292 material,
293 lights,
294 color_texture,
295 depth_texture,
296 )
297 }
298}
299
300#[derive(Clone, Debug, Default)]
308pub struct Instances {
309 pub transformations: Vec<Mat4>,
311 pub texture_transformations: Option<Vec<Mat3>>,
313 pub colors: Option<Vec<Srgba>>,
315}
316
317impl Instances {
318 pub fn validate(&self) -> Result<(), RendererError> {
322 let instance_count = self.count();
323 let buffer_check = |length: Option<usize>, name: &str| -> Result<(), RendererError> {
324 if let Some(length) = length {
325 if length < instance_count as usize {
326 Err(RendererError::InvalidBufferLength(
327 name.to_string(),
328 instance_count as usize,
329 length,
330 ))?;
331 }
332 }
333 Ok(())
334 };
335
336 buffer_check(
337 self.texture_transformations.as_ref().map(|b| b.len()),
338 "texture transformations",
339 )?;
340 buffer_check(Some(self.transformations.len()), "transformations")?;
341 buffer_check(self.colors.as_ref().map(|b| b.len()), "colors")?;
342
343 Ok(())
344 }
345
346 pub fn count(&self) -> u32 {
348 self.transformations.len() as u32
349 }
350}
351
352impl From<PointCloud> for Instances {
353 fn from(points: PointCloud) -> Self {
354 Self {
355 transformations: points
356 .positions
357 .to_f32()
358 .into_iter()
359 .map(Mat4::from_translation)
360 .collect(),
361 colors: points.colors,
362 ..Default::default()
363 }
364 }
365}