@@ -95,6 +95,13 @@ impl VertexAttributeValues {
95
95
self . len ( ) == 0
96
96
}
97
97
98
+ fn as_float3 ( & self ) -> Option < & [ [ f32 ; 3 ] ] > {
99
+ match self {
100
+ VertexAttributeValues :: Float3 ( values) => Some ( values) ,
101
+ _ => None ,
102
+ }
103
+ }
104
+
98
105
// TODO: add vertex format as parameter here and perform type conversions
99
106
/// Flattens the VertexAttributeArray into a sequence of bytes. This is
100
107
/// useful for serialization and sending to the GPU.
@@ -254,6 +261,29 @@ pub enum Indices {
254
261
U32 ( Vec < u32 > ) ,
255
262
}
256
263
264
+ impl Indices {
265
+ fn iter ( & self ) -> impl Iterator < Item = usize > + ' _ {
266
+ match self {
267
+ Indices :: U16 ( vec) => IndicesIter :: U16 ( vec. iter ( ) ) ,
268
+ Indices :: U32 ( vec) => IndicesIter :: U32 ( vec. iter ( ) ) ,
269
+ }
270
+ }
271
+ }
272
+ enum IndicesIter < ' a > {
273
+ U16 ( std:: slice:: Iter < ' a , u16 > ) ,
274
+ U32 ( std:: slice:: Iter < ' a , u32 > ) ,
275
+ }
276
+ impl Iterator for IndicesIter < ' _ > {
277
+ type Item = usize ;
278
+
279
+ fn next ( & mut self ) -> Option < Self :: Item > {
280
+ match self {
281
+ IndicesIter :: U16 ( iter) => iter. next ( ) . map ( |val| * val as usize ) ,
282
+ IndicesIter :: U32 ( iter) => iter. next ( ) . map ( |val| * val as usize ) ,
283
+ }
284
+ }
285
+ }
286
+
257
287
impl From < & Indices > for IndexFormat {
258
288
fn from ( indices : & Indices ) -> Self {
259
289
match indices {
@@ -431,6 +461,88 @@ impl Mesh {
431
461
432
462
attributes_interleaved_buffer
433
463
}
464
+
465
+ /// Duplicates the vertex attributes so that no vertices are shared.
466
+ ///
467
+ /// This can dramatically increase the vertex count, so make sure this is what you want.
468
+ /// Does nothing if no [Indices] are set.
469
+ pub fn duplicate_vertices ( & mut self ) {
470
+ fn duplicate < T : Copy > ( values : & [ T ] , indices : impl Iterator < Item = usize > ) -> Vec < T > {
471
+ indices. map ( |i| values[ i] ) . collect ( )
472
+ }
473
+
474
+ assert ! (
475
+ matches!( self . primitive_topology, PrimitiveTopology :: TriangleList ) ,
476
+ "can only duplicate vertices for `TriangleList`s"
477
+ ) ;
478
+
479
+ let indices = match self . indices . take ( ) {
480
+ Some ( indices) => indices,
481
+ None => return ,
482
+ } ;
483
+ for ( _, attributes) in self . attributes . iter_mut ( ) {
484
+ let indices = indices. iter ( ) ;
485
+ match attributes {
486
+ VertexAttributeValues :: Float ( vec) => * vec = duplicate ( & vec, indices) ,
487
+ VertexAttributeValues :: Int ( vec) => * vec = duplicate ( & vec, indices) ,
488
+ VertexAttributeValues :: Uint ( vec) => * vec = duplicate ( & vec, indices) ,
489
+ VertexAttributeValues :: Float2 ( vec) => * vec = duplicate ( & vec, indices) ,
490
+ VertexAttributeValues :: Int2 ( vec) => * vec = duplicate ( & vec, indices) ,
491
+ VertexAttributeValues :: Uint2 ( vec) => * vec = duplicate ( & vec, indices) ,
492
+ VertexAttributeValues :: Float3 ( vec) => * vec = duplicate ( & vec, indices) ,
493
+ VertexAttributeValues :: Int3 ( vec) => * vec = duplicate ( & vec, indices) ,
494
+ VertexAttributeValues :: Uint3 ( vec) => * vec = duplicate ( & vec, indices) ,
495
+ VertexAttributeValues :: Int4 ( vec) => * vec = duplicate ( & vec, indices) ,
496
+ VertexAttributeValues :: Uint4 ( vec) => * vec = duplicate ( & vec, indices) ,
497
+ VertexAttributeValues :: Float4 ( vec) => * vec = duplicate ( & vec, indices) ,
498
+ VertexAttributeValues :: Short2 ( vec) => * vec = duplicate ( & vec, indices) ,
499
+ VertexAttributeValues :: Short2Norm ( vec) => * vec = duplicate ( & vec, indices) ,
500
+ VertexAttributeValues :: Ushort2 ( vec) => * vec = duplicate ( & vec, indices) ,
501
+ VertexAttributeValues :: Ushort2Norm ( vec) => * vec = duplicate ( & vec, indices) ,
502
+ VertexAttributeValues :: Short4 ( vec) => * vec = duplicate ( & vec, indices) ,
503
+ VertexAttributeValues :: Short4Norm ( vec) => * vec = duplicate ( & vec, indices) ,
504
+ VertexAttributeValues :: Ushort4 ( vec) => * vec = duplicate ( & vec, indices) ,
505
+ VertexAttributeValues :: Ushort4Norm ( vec) => * vec = duplicate ( & vec, indices) ,
506
+ VertexAttributeValues :: Char2 ( vec) => * vec = duplicate ( & vec, indices) ,
507
+ VertexAttributeValues :: Char2Norm ( vec) => * vec = duplicate ( & vec, indices) ,
508
+ VertexAttributeValues :: Uchar2 ( vec) => * vec = duplicate ( & vec, indices) ,
509
+ VertexAttributeValues :: Uchar2Norm ( vec) => * vec = duplicate ( & vec, indices) ,
510
+ VertexAttributeValues :: Char4 ( vec) => * vec = duplicate ( & vec, indices) ,
511
+ VertexAttributeValues :: Char4Norm ( vec) => * vec = duplicate ( & vec, indices) ,
512
+ VertexAttributeValues :: Uchar4 ( vec) => * vec = duplicate ( & vec, indices) ,
513
+ VertexAttributeValues :: Uchar4Norm ( vec) => * vec = duplicate ( & vec, indices) ,
514
+ }
515
+ }
516
+ }
517
+
518
+ /// Calculates the [`Mesh::ATTRIBUTE_NORMAL`] of a mesh.
519
+ ///
520
+ /// Panics if [`Indices`] are set.
521
+ /// Consider calling [Mesh::duplicate_vertices] or export your mesh with normal attributes.
522
+ pub fn compute_flat_normals ( & mut self ) {
523
+ if self . indices ( ) . is_some ( ) {
524
+ panic ! ( "`compute_flat_normals` can't work on indexed geometry. Consider calling `Mesh::duplicate_vertices`." ) ;
525
+ }
526
+
527
+ let positions = self
528
+ . attribute ( Mesh :: ATTRIBUTE_POSITION )
529
+ . unwrap ( )
530
+ . as_float3 ( )
531
+ . expect ( "`Mesh::ATTRIBUTE_POSITION` vertex attributes should be of type `float3`" ) ;
532
+
533
+ let normals: Vec < _ > = positions
534
+ . chunks_exact ( 3 )
535
+ . map ( |p| face_normal ( p[ 0 ] , p[ 1 ] , p[ 2 ] ) )
536
+ . flat_map ( |normal| std:: array:: IntoIter :: new ( [ normal, normal, normal] ) )
537
+ . collect ( ) ;
538
+
539
+ self . set_attribute ( Mesh :: ATTRIBUTE_NORMAL , normals) ;
540
+ }
541
+ }
542
+
543
+ fn face_normal ( a : [ f32 ; 3 ] , b : [ f32 ; 3 ] , c : [ f32 ; 3 ] ) -> [ f32 ; 3 ] {
544
+ let ( a, b, c) = ( Vec3 :: from ( a) , Vec3 :: from ( b) , Vec3 :: from ( c) ) ;
545
+ ( b - a) . cross ( c - a) . normalize ( ) . into ( )
434
546
}
435
547
436
548
fn remove_resource_save (
0 commit comments