@@ -264,11 +264,11 @@ public final class Geometry: Hashable {
264264 case var . path( path) :
265265 ( path, material) = path. vertexColorsToMaterial ( material: material)
266266 type = . path( path)
267- case let . mesh( mesh) :
268- material = mesh. polygons . first? . material as? Material ?? material
267+ case let . mesh( mesh) where !mesh . isEmpty :
268+ material = mesh. materials . first as? Material ?? . default
269269 case . hull, . minkowski:
270270 useMaterialForCache = true
271- case . union, . xor, . difference, . intersection, . stencil:
271+ case . union, . xor, . difference, . intersection, . stencil, . mesh :
272272 material = children. first? . material ?? . default
273273 case . group:
274274 if debug {
@@ -447,22 +447,30 @@ public extension Geometry {
447447 )
448448 }
449449
450- /// Builds the meshes for the receiver and all its children
450+ /// Builds the meshes for the receiver and all its descendents
451451 /// Built meshes will be stored in the cache. Already-cached meshes will be re-used if available
452452 /// - Returns: false if cancelled or true when completed
453453 func build( _ callback: @escaping LegacyCallback ) -> Bool {
454454 buildLeaves ( callback) && buildPreview ( callback) && buildFinal ( callback)
455455 }
456456
457- /// Returns the union mesh of the receiver and all its children
457+ /// Returns the union mesh of the receiver and all its descendents
458+ /// The cache is neither checked nor updated. Only already-built meshes are returned.
458459 /// - Note: Includes both material and transform
459460 func flattened( _ callback: @escaping LegacyCallback = { true } ) -> Mesh {
460461 flattened ( with: material, callback)
461462 }
462463
463- /// Returns the combined mesh of the receiver and all its children
464+ /// Returns the meshes of the receiver and all its descendents
465+ /// The cache is neither checked nor updated. Only already-built meshes are returned
466+ /// - Note: Includes both material and transform
467+ func meshes( _ callback: @escaping LegacyCallback = { true } ) -> [ Mesh ] {
468+ meshes ( with: material, callback)
469+ }
470+
471+ /// Returns the combined mesh of the receiver and all its descendents
464472 /// The cache is neither checked nor updated. Only already-built meshes are returned
465- /// - Note: Result is does *not* include the material or transform for the receiver
473+ /// - Note: Includes both material and transform
466474 func merged( _ callback: @escaping LegacyCallback = { true } ) -> Mesh {
467475 var result = mesh ?? . empty
468476 if type. isLeafGeometry {
@@ -501,7 +509,7 @@ private extension Collection<Geometry> {
501509
502510 /// Returns a merged mesh for all of the geometries in the collection and all their descendents
503511 /// The cache is neither checked nor updated. Only already-built meshes are returned
504- /// - Note: Does not include the material or transform of the top-level geometries in the collection
512+ /// - Note: Results include both material and transform
505513 func merged( _ callback: @escaping LegacyCallback ) -> Mesh {
506514 var result = Mesh . empty
507515 for child in self where callback ( ) {
@@ -514,28 +522,28 @@ private extension Collection<Geometry> {
514522private extension Geometry {
515523 /// Computes the union of the meshes of the descendents of the receiver
516524 /// The cache is neither checked nor updated. Only already-built meshes are included in the union result
517- /// - Note: Includes both material (if specified) and transform
525+ /// - Note: Includes the receiver's material but not its transform
518526 func flattenedChildren( _ callback: @escaping LegacyCallback ) -> [ Mesh ] {
519527 children. flattened ( with: material, callback)
520528 }
521529
522530 /// Returns a merged mesh for all of the descendents of the receiver
523531 /// The cache is neither checked nor updated. Only already-built meshes are returned
524- /// - Note: Does not include the material or transform of the top-level geometries in the collection
532+ /// - Note: Does not include the material or transform of the receiver
525533 func mergedChildren( _ callback: @escaping LegacyCallback ) -> Mesh {
526534 children. merged ( callback)
527535 }
528536
529537 /// Computes the union of the meshes of the first child of the receiver
530538 /// The cache is neither checked nor updated. Only already-built meshes are included in the union result
531- /// - Note: Includes both material (if specified) and transform
539+ /// - Note: Includes the receiver's material but not its transform
532540 func flattenedFirstChild( _ callback: @escaping LegacyCallback ) -> Mesh {
533541 children. first. map { $0. flattened ( with: self . material, callback) } ?? . empty
534542 }
535543
536- /// Returns the meshes of the receiver and all its descendents
544+ /// Returns the meshes of the receivers children and their descendents
537545 /// The cache is neither checked nor updated. Only already-built meshes are returned
538- /// - Note: Includes both the material and transform
546+ /// - Note: Includes the receiver's material but not its transform
539547 func childMeshes( _ callback: @escaping ( ) -> Bool ) -> [ Mesh ] {
540548 children. meshes ( with: material, callback)
541549 }
@@ -547,28 +555,24 @@ private extension Geometry {
547555 . union( meshes ( with: material, callback) , isCancelled: { !callback( ) } )
548556 }
549557
550- /// Returns the meshes of the receiver and all its children
551- /// The cache is neither checked nor updated. Only already-built meshes are returned.
558+ /// Returns the meshes of the receiver and all its descendents
559+ /// The cache is neither checked nor updated. Only already-built meshes are returned
552560 /// - Note: Includes both material (if specified) and transform
553561 func meshes( with material: Material ? , _ callback: @escaping LegacyCallback ) -> [ Mesh ] {
554562 var meshes = [ Mesh] ( )
555- if var mesh, mesh != . empty {
556- mesh = mesh. transformed ( by: transform)
557- if material != self . material {
558- mesh = mesh. replacing ( nil , with: self . material)
559- }
563+ if let mesh, mesh != . empty {
560564 meshes. append ( mesh)
561565 }
562566 if type. isLeafGeometry {
563- meshes += childMeshes ( callback) . map {
564- let mesh = $0 . transformed ( by : transform )
565- if material != self . material {
566- return mesh . replacing ( nil , with : self . material )
567- }
568- return mesh
567+ meshes += childMeshes ( callback)
568+ }
569+ return meshes . map {
570+ let mesh = $0 . transformed ( by : transform )
571+ if material != self . material {
572+ return mesh. replacing ( nil , with : self . material )
569573 }
574+ return mesh
570575 }
571- return meshes
572576 }
573577
574578 /// Build all geometries that don't have dependencies
@@ -1056,13 +1060,7 @@ public extension Geometry {
10561060 /// Builds the mesh (if needed) and returns the triangle count
10571061 /// Built meshes will be stored in the cache. Already-cached meshes will be re-used if available
10581062 func triangles( _ isCancelled: @escaping CancellationHandler ) -> [ Polygon ] {
1059- switch type {
1060- case . group:
1061- return children. reduce ( into: [ ] ) { $0 += $1. triangles ( isCancelled) }
1062- default :
1063- _ = build { !isCancelled( ) }
1064- return mesh? . triangulate ( ) . polygons ?? [ ]
1065- }
1063+ polygons ( isCancelled) . flatMap { $0. triangulate ( ) }
10661064 }
10671065
10681066 /// Returns if the geometry is watertight
@@ -1072,7 +1070,7 @@ public extension Geometry {
10721070 case . cone, . cylinder, . sphere, . cube:
10731071 return true
10741072 case . group:
1075- return children. reduce ( true ) { $0 && $1 . isWatertight ( isCancelled) }
1073+ return children. allSatisfy { $0. isWatertight ( isCancelled) }
10761074 default :
10771075 _ = build { !isCancelled( ) }
10781076 return mesh? . isWatertight ?? true
0 commit comments