@@ -65,6 +65,13 @@ impl VertexAttributeValues {
65
65
self . len ( ) == 0
66
66
}
67
67
68
+ fn as_float3 ( & self ) -> Option < & [ [ f32 ; 3 ] ] > {
69
+ match self {
70
+ VertexAttributeValues :: Float3 ( values) => Some ( values) ,
71
+ _ => None ,
72
+ }
73
+ }
74
+
68
75
// TODO: add vertex format as parameter here and perform type conversions
69
76
/// Flattens the VertexAttributeArray into a sequence of bytes. This is
70
77
/// useful for serialization and sending to the GPU.
@@ -194,6 +201,29 @@ pub enum Indices {
194
201
U32 ( Vec < u32 > ) ,
195
202
}
196
203
204
+ impl Indices {
205
+ fn iter ( & self ) -> impl Iterator < Item = usize > + ' _ {
206
+ match self {
207
+ Indices :: U16 ( vec) => IndicesIter :: U16 ( vec. iter ( ) ) ,
208
+ Indices :: U32 ( vec) => IndicesIter :: U32 ( vec. iter ( ) ) ,
209
+ }
210
+ }
211
+ }
212
+ enum IndicesIter < ' a > {
213
+ U16 ( std:: slice:: Iter < ' a , u16 > ) ,
214
+ U32 ( std:: slice:: Iter < ' a , u32 > ) ,
215
+ }
216
+ impl Iterator for IndicesIter < ' _ > {
217
+ type Item = usize ;
218
+
219
+ fn next ( & mut self ) -> Option < Self :: Item > {
220
+ match self {
221
+ IndicesIter :: U16 ( iter) => iter. next ( ) . map ( |val| * val as usize ) ,
222
+ IndicesIter :: U32 ( iter) => iter. next ( ) . map ( |val| * val as usize ) ,
223
+ }
224
+ }
225
+ }
226
+
197
227
impl From < & Indices > for IndexFormat {
198
228
fn from ( indices : & Indices ) -> Self {
199
229
match indices {
@@ -369,6 +399,72 @@ impl Mesh {
369
399
370
400
attributes_interleaved_buffer
371
401
}
402
+
403
+ /// Duplicates the vertex attributes so that no vertices are shared.
404
+ ///
405
+ /// Does nothing if no [Indices] are set.
406
+ pub fn duplicate_vertices ( & mut self ) {
407
+ fn duplicate < T : Copy > ( values : & [ T ] , indices : impl Iterator < Item = usize > ) -> Vec < T > {
408
+ indices. map ( |i| values[ i] ) . collect ( )
409
+ }
410
+
411
+ assert ! (
412
+ matches!( self . primitive_topology, PrimitiveTopology :: TriangleList ) ,
413
+ "can only duplicate vertices for `TriangleList`s"
414
+ ) ;
415
+
416
+ let indices = match self . indices . take ( ) {
417
+ Some ( indices) => indices,
418
+ None => return ,
419
+ } ;
420
+ for ( _, attributes) in self . attributes . iter_mut ( ) {
421
+ let indices = indices. iter ( ) ;
422
+ match attributes {
423
+ VertexAttributeValues :: Float ( vec) => * vec = duplicate ( & vec, indices) ,
424
+ VertexAttributeValues :: Int ( vec) => * vec = duplicate ( & vec, indices) ,
425
+ VertexAttributeValues :: Uint ( vec) => * vec = duplicate ( & vec, indices) ,
426
+ VertexAttributeValues :: Float2 ( vec) => * vec = duplicate ( & vec, indices) ,
427
+ VertexAttributeValues :: Int2 ( vec) => * vec = duplicate ( & vec, indices) ,
428
+ VertexAttributeValues :: Uint2 ( vec) => * vec = duplicate ( & vec, indices) ,
429
+ VertexAttributeValues :: Float3 ( vec) => * vec = duplicate ( & vec, indices) ,
430
+ VertexAttributeValues :: Int3 ( vec) => * vec = duplicate ( & vec, indices) ,
431
+ VertexAttributeValues :: Uint3 ( vec) => * vec = duplicate ( & vec, indices) ,
432
+ VertexAttributeValues :: Int4 ( vec) => * vec = duplicate ( & vec, indices) ,
433
+ VertexAttributeValues :: Uint4 ( vec) => * vec = duplicate ( & vec, indices) ,
434
+ VertexAttributeValues :: Float4 ( vec) => * vec = duplicate ( & vec, indices) ,
435
+ VertexAttributeValues :: Uchar4Norm ( vec) => * vec = duplicate ( & vec, indices) ,
436
+ }
437
+ }
438
+ }
439
+
440
+ /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of a mesh.
441
+ /// This [duplicates the vertices](Mesh::duplicate_vertices), so any [`Indices`] will be gone if set.
442
+ pub fn compute_flat_normals ( & mut self ) {
443
+ if self . indices ( ) . is_some ( ) {
444
+ self . duplicate_vertices ( ) ;
445
+ self . compute_flat_normals ( ) ;
446
+ return ;
447
+ }
448
+
449
+ let positions = self
450
+ . attribute ( Mesh :: ATTRIBUTE_POSITION )
451
+ . unwrap ( )
452
+ . as_float3 ( )
453
+ . expect ( "`Mesh::ATTRIBUTE_POSITION` vertex attributes should be of type `float3`" ) ;
454
+
455
+ let normals: Vec < _ > = positions
456
+ . chunks_exact ( 3 )
457
+ . map ( |p| face_normal ( p[ 0 ] , p[ 1 ] , p[ 2 ] ) )
458
+ . flat_map ( |normal| std:: array:: IntoIter :: new ( [ normal, normal, normal] ) )
459
+ . collect ( ) ;
460
+
461
+ self . set_attribute ( Mesh :: ATTRIBUTE_NORMAL , normals) ;
462
+ }
463
+ }
464
+
465
+ fn face_normal ( a : [ f32 ; 3 ] , b : [ f32 ; 3 ] , c : [ f32 ; 3 ] ) -> [ f32 ; 3 ] {
466
+ let ( a, b, c) = ( Vec3 :: from ( a) , Vec3 :: from ( b) , Vec3 :: from ( c) ) ;
467
+ ( b - a) . cross ( c - a) . into ( )
372
468
}
373
469
374
470
fn remove_resource_save (
0 commit comments