Skip to main content

three_d/renderer/geometry/
mesh.rs

1use crate::core::*;
2use crate::renderer::*;
3
4use super::BaseMesh;
5
6///
7/// A triangle mesh [Geometry].
8///
9pub struct Mesh {
10    base_mesh: BaseMesh,
11    context: Context,
12    aabb: AxisAlignedBoundingBox,
13    transformation: Mat4,
14    animation_transformation: Mat4,
15    animation: Option<Box<dyn Fn(f32) -> Mat4 + Send + Sync>>,
16}
17
18impl Mesh {
19    ///
20    /// Creates a new triangle mesh from the given [CpuMesh].
21    /// All data in the [CpuMesh] is transfered to the GPU, so make sure to remove all unnecessary data from the [CpuMesh] before calling this method.
22    ///
23    pub fn new(context: &Context, cpu_mesh: &CpuMesh) -> Self {
24        let aabb = cpu_mesh.compute_aabb();
25        Self {
26            context: context.clone(),
27            base_mesh: BaseMesh::new(context, cpu_mesh),
28            aabb,
29            transformation: Mat4::identity(),
30            animation_transformation: Mat4::identity(),
31            animation: None,
32        }
33    }
34
35    pub(in crate::renderer) fn set_transformation_2d(&mut self, transformation: Mat3) {
36        self.set_transformation(Mat4::new(
37            transformation.x.x,
38            transformation.x.y,
39            0.0,
40            transformation.x.z,
41            transformation.y.x,
42            transformation.y.y,
43            0.0,
44            transformation.y.z,
45            0.0,
46            0.0,
47            1.0,
48            0.0,
49            transformation.z.x,
50            transformation.z.y,
51            0.0,
52            transformation.z.z,
53        ));
54    }
55
56    ///
57    /// Returns the local to world transformation applied to this mesh.
58    ///
59    pub fn transformation(&self) -> Mat4 {
60        self.transformation
61    }
62
63    ///
64    /// Set the local to world transformation applied to this mesh.
65    /// If any animation method is set using [Self::set_animation], the transformation from that method is applied before this transformation.
66    ///
67    pub fn set_transformation(&mut self, transformation: Mat4) {
68        self.transformation = transformation;
69    }
70
71    ///
72    /// Specifies a function which takes a time parameter as input and returns a transformation that should be applied to this mesh at the given time.
73    /// To actually animate this mesh, call [Geometry::animate] at each frame which in turn evaluates the animation function defined by this method.
74    /// This transformation is applied first, then the local to world transformation defined by [Self::set_transformation].
75    ///
76    pub fn set_animation(&mut self, animation: impl Fn(f32) -> Mat4 + Send + Sync + 'static) {
77        self.animation = Some(Box::new(animation));
78        self.animate(0.0);
79    }
80
81    ///
82    /// Returns the number of vertices in this mesh.
83    ///
84    pub fn vertex_count(&self) -> u32 {
85        self.base_mesh.indices.vertex_count()
86    }
87
88    ///
89    /// Used for editing the triangle definition in the [TriangleBuffer] for this mesh.
90    /// Note: Changing this will possibly ruin the mesh.
91    ///
92    pub fn indices_mut(&mut self) -> &mut TriangleBuffer {
93        &mut self.base_mesh.indices
94    }
95
96    ///
97    /// Update the vertex positions of the mesh.
98    /// Returns an error if the number of positions does not match the number of vertices in the mesh.
99    ///
100    pub fn set_positions(&mut self, positions: &[Vec3]) -> Result<(), RendererError> {
101        if positions.len() as u32 != self.vertex_count() {
102            Err(RendererError::InvalidBufferLength(
103                "Position".to_string(),
104                self.vertex_count() as usize,
105                positions.len(),
106            ))?;
107        }
108        self.base_mesh.positions.fill(positions);
109        self.aabb = AxisAlignedBoundingBox::new_with_positions(positions);
110        Ok(())
111    }
112
113    ///
114    /// Partially update the vertex positions of the mesh.
115    /// Returns an error if the number of positions plus the offset is larger than the number of vertices in the mesh.
116    ///
117    pub fn set_positions_partially(
118        &mut self,
119        offset: u32,
120        positions: &[Vec3],
121    ) -> Result<(), RendererError> {
122        if offset + positions.len() as u32 > self.vertex_count() {
123            Err(RendererError::InvalidBufferLength(
124                "Position".to_string(),
125                self.vertex_count() as usize,
126                offset as usize + positions.len(),
127            ))?;
128        }
129        self.base_mesh.positions.fill_subset(offset, positions);
130        self.aabb.expand(positions);
131        Ok(())
132    }
133
134    ///
135    /// Used for editing the vertex positions.
136    /// Note: Changing this will possibly ruin the mesh.
137    ///
138    #[deprecated = "use set_positions and set_positions_partially instead"]
139    pub fn positions_mut(&mut self) -> &mut VertexBuffer<Vec3> {
140        &mut self.base_mesh.positions
141    }
142
143    ///
144    /// Update the vertex normals of the mesh.
145    /// Returns an error if the number of normals does not match the number of vertices in the mesh.
146    ///
147    pub fn set_normals(&mut self, normals: &[Vec3]) -> Result<(), RendererError> {
148        if normals.len() as u32 != self.vertex_count() {
149            Err(RendererError::InvalidBufferLength(
150                "Normal".to_string(),
151                self.vertex_count() as usize,
152                normals.len(),
153            ))?;
154        }
155        if let Some(buffer) = self.base_mesh.normals.as_mut() {
156            buffer.fill(normals);
157        } else {
158            self.base_mesh.normals = Some(VertexBuffer::new_with_data(&self.context, normals));
159        }
160        Ok(())
161    }
162
163    ///
164    /// Partially update the vertex normals of the mesh.
165    /// Returns an error if the number of normals plus the offset is larger than the number of vertices in the mesh
166    /// or if the normal buffer is missing.
167    ///
168    pub fn set_normals_partially(
169        &mut self,
170        offset: u32,
171        normals: &[Vec3],
172    ) -> Result<(), RendererError> {
173        if offset + normals.len() as u32 > self.vertex_count() {
174            Err(RendererError::InvalidBufferLength(
175                "Normal".to_string(),
176                self.vertex_count() as usize,
177                offset as usize + normals.len(),
178            ))?;
179        }
180        if let Some(buffer) = self.base_mesh.normals.as_mut() {
181            buffer.fill_subset(offset, normals);
182        } else {
183            Err(RendererError::PartialUpdateFailedMissingBuffer(
184                "Normal".to_string(),
185            ))?;
186        }
187        Ok(())
188    }
189
190    ///
191    /// Used for editing the vertex normals.
192    /// Note: Changing this will possibly ruin the mesh.
193    ///
194    #[deprecated = "use set_normals and set_normals_partially instead"]
195    pub fn normals_mut(&mut self) -> &mut Option<VertexBuffer<Vec3>> {
196        &mut self.base_mesh.normals
197    }
198
199    ///
200    /// Update the vertex UVs of the mesh.
201    /// Returns an error if the number of UVs does not match the number of vertices in the mesh.
202    ///
203    pub fn set_uvs(&mut self, uvs: &[Vec2]) -> Result<(), RendererError> {
204        if uvs.len() as u32 != self.vertex_count() {
205            Err(RendererError::InvalidBufferLength(
206                "UV".to_string(),
207                self.vertex_count() as usize,
208                uvs.len(),
209            ))?;
210        }
211        if let Some(buffer) = self.base_mesh.uvs.as_mut() {
212            buffer.fill(uvs);
213        } else {
214            self.base_mesh.uvs = Some(VertexBuffer::new_with_data(&self.context, uvs));
215        }
216        Ok(())
217    }
218
219    ///
220    /// Partially update the vertex UVs of the mesh.
221    /// Returns an error if the number of UVs plus the offset is larger than the number of vertices in the mesh
222    /// or if the UV buffer is missing.
223    ///
224    pub fn set_uvs_partially(&mut self, offset: u32, uvs: &[Vec2]) -> Result<(), RendererError> {
225        if offset + uvs.len() as u32 > self.vertex_count() {
226            Err(RendererError::InvalidBufferLength(
227                "UV".to_string(),
228                self.vertex_count() as usize,
229                offset as usize + uvs.len(),
230            ))?;
231        }
232        if let Some(buffer) = self.base_mesh.uvs.as_mut() {
233            buffer.fill_subset(offset, uvs);
234        } else {
235            Err(RendererError::PartialUpdateFailedMissingBuffer(
236                "UV".to_string(),
237            ))?;
238        }
239        Ok(())
240    }
241
242    ///
243    /// Used for editing the vertex uvs.
244    /// Note: Changing this will possibly ruin the mesh.
245    ///
246    #[deprecated = "use set_uvs and set_uvs_partially instead"]
247    pub fn uvs_mut(&mut self) -> &mut Option<VertexBuffer<Vec2>> {
248        &mut self.base_mesh.uvs
249    }
250
251    ///
252    /// Update the vertex tangents of the mesh.
253    /// Returns an error if the number of tangents does not match the number of vertices in the mesh.
254    ///
255    pub fn set_tangents(&mut self, tangents: &[Vec4]) -> Result<(), RendererError> {
256        if tangents.len() as u32 != self.vertex_count() {
257            Err(RendererError::InvalidBufferLength(
258                "Tangents".to_string(),
259                self.vertex_count() as usize,
260                tangents.len(),
261            ))?;
262        }
263        if let Some(buffer) = self.base_mesh.tangents.as_mut() {
264            buffer.fill(tangents);
265        } else {
266            self.base_mesh.tangents = Some(VertexBuffer::new_with_data(&self.context, tangents));
267        }
268        Ok(())
269    }
270
271    ///
272    /// Partially update the vertex tangents of the mesh.
273    /// Returns an error if the number of tangents plus the offset is larger than the number of vertices in the mesh
274    /// or if the tangent buffer is missing.
275    ///
276    pub fn set_tangents_partially(
277        &mut self,
278        offset: u32,
279        tangents: &[Vec4],
280    ) -> Result<(), RendererError> {
281        if offset + tangents.len() as u32 > self.vertex_count() {
282            Err(RendererError::InvalidBufferLength(
283                "Tangent".to_string(),
284                self.vertex_count() as usize,
285                offset as usize + tangents.len(),
286            ))?;
287        }
288        if let Some(buffer) = self.base_mesh.tangents.as_mut() {
289            buffer.fill_subset(offset, tangents);
290        } else {
291            Err(RendererError::PartialUpdateFailedMissingBuffer(
292                "Tangent".to_string(),
293            ))?;
294        }
295        Ok(())
296    }
297
298    ///
299    /// Used for editing the vertex tangents.
300    /// Note: Changing this will possibly ruin the mesh.
301    ///
302    #[deprecated = "use set_tangents and set_tangents_partially instead"]
303    pub fn tangents_mut(&mut self) -> &mut Option<VertexBuffer<Vec4>> {
304        &mut self.base_mesh.tangents
305    }
306
307    ///
308    /// Update the vertex colors of the mesh.
309    /// Returns an error if the number of colors does not match the number of vertices in the mesh.
310    ///
311    pub fn set_colors(&mut self, colors: &[Vec4]) -> Result<(), RendererError> {
312        if colors.len() as u32 != self.vertex_count() {
313            Err(RendererError::InvalidBufferLength(
314                "Color".to_string(),
315                self.vertex_count() as usize,
316                colors.len(),
317            ))?;
318        }
319        if let Some(buffer) = self.base_mesh.colors.as_mut() {
320            buffer.fill(colors);
321        } else {
322            self.base_mesh.colors = Some(VertexBuffer::new_with_data(&self.context, colors));
323        }
324        Ok(())
325    }
326
327    ///
328    /// Partially update the vertex colors of the mesh.
329    /// Returns an error if the number of colors plus the offset is larger than the number of vertices in the mesh
330    /// or if the colors buffer is missing.
331    ///
332    pub fn set_colors_partially(
333        &mut self,
334        offset: u32,
335        colors: &[Vec4],
336    ) -> Result<(), RendererError> {
337        if offset + colors.len() as u32 > self.vertex_count() {
338            Err(RendererError::InvalidBufferLength(
339                "Color".to_string(),
340                self.vertex_count() as usize,
341                offset as usize + colors.len(),
342            ))?;
343        }
344        if let Some(buffer) = self.base_mesh.colors.as_mut() {
345            buffer.fill_subset(offset, colors);
346        } else {
347            Err(RendererError::PartialUpdateFailedMissingBuffer(
348                "Color".to_string(),
349            ))?;
350        }
351        Ok(())
352    }
353
354    ///
355    /// Used for editing the vertex colors.
356    /// Note: Changing this will possibly ruin the mesh.
357    ///
358    #[deprecated = "use set_colors and set_colors_partially instead"]
359    pub fn colors_mut(&mut self) -> &mut Option<VertexBuffer<Vec4>> {
360        &mut self.base_mesh.colors
361    }
362}
363
364impl<'a> IntoIterator for &'a Mesh {
365    type Item = &'a dyn Geometry;
366    type IntoIter = std::iter::Once<&'a dyn Geometry>;
367
368    fn into_iter(self) -> Self::IntoIter {
369        std::iter::once(self)
370    }
371}
372
373impl Geometry for Mesh {
374    fn aabb(&self) -> AxisAlignedBoundingBox {
375        self.aabb
376            .transformed(self.transformation * self.animation_transformation)
377    }
378
379    fn animate(&mut self, time: f32) {
380        if let Some(animation) = &self.animation {
381            self.animation_transformation = animation(time);
382        }
383    }
384
385    fn draw(&self, viewer: &dyn Viewer, program: &Program, render_states: RenderStates) {
386        let local2world = self.transformation * self.animation_transformation;
387        if let Some(inverse) = local2world.invert() {
388            program.use_uniform_if_required("normalMatrix", inverse.transpose());
389        } else {
390            // determinant is float zero
391            return;
392        }
393
394        program.use_uniform("viewProjection", viewer.projection() * viewer.view());
395        program.use_uniform("modelMatrix", local2world);
396
397        self.base_mesh.draw(program, render_states, viewer);
398    }
399
400    fn vertex_shader_source(&self) -> String {
401        self.base_mesh.vertex_shader_source()
402    }
403
404    fn id(&self) -> GeometryId {
405        GeometryId::Mesh(
406            self.base_mesh.normals.is_some(),
407            self.base_mesh.tangents.is_some(),
408            self.base_mesh.uvs.is_some(),
409            self.base_mesh.colors.is_some(),
410        )
411    }
412
413    fn render_with_material(
414        &self,
415        material: &dyn Material,
416        viewer: &dyn Viewer,
417        lights: &[&dyn Light],
418    ) {
419        if let Err(e) = render_with_material(&self.context, viewer, &self, material, lights) {
420            panic!("{}", e.to_string());
421        }
422    }
423
424    fn render_with_effect(
425        &self,
426        material: &dyn Effect,
427        viewer: &dyn Viewer,
428        lights: &[&dyn Light],
429        color_texture: Option<ColorTexture>,
430        depth_texture: Option<DepthTexture>,
431    ) {
432        if let Err(e) = render_with_effect(
433            &self.context,
434            viewer,
435            self,
436            material,
437            lights,
438            color_texture,
439            depth_texture,
440        ) {
441            panic!("{}", e.to_string());
442        }
443    }
444}