|
9 | 9 | #include "MRMeshCollidePrecise.h" |
10 | 10 | #include "MRBox.h" |
11 | 11 | #include "MRParallelFor.h" |
| 12 | +#include "MRMeshComponents.h" |
| 13 | +#include "MRBitSetParallelFor.h" |
12 | 14 | #include <random> |
13 | 15 |
|
14 | 16 | namespace MR |
@@ -347,4 +349,56 @@ Expected<Mesh> uniteManyMeshes( |
347 | 349 | return reducer.resultMesh; |
348 | 350 | } |
349 | 351 |
|
| 352 | +Expected<Mesh> uniteComponents( const Mesh& mesh, const UniteComponentsParams& params ) |
| 353 | +{ |
| 354 | + MR_TIMER; |
| 355 | + if ( !mesh.topology.isClosed() ) |
| 356 | + { |
| 357 | + assert( !"uniteComponents: require closed mesh" ); |
| 358 | + return unexpected( "Mesh is not closed." ); |
| 359 | + } |
| 360 | + auto mapAndNum = MeshComponents::getAllComponentsMap( mesh ); |
| 361 | + if ( !reportProgress( params.baseParams.progressCb, 0.1f ) ) |
| 362 | + return unexpectedOperationCanceled(); |
| 363 | + std::vector<Mesh> components( mapAndNum.second ); |
| 364 | + std::vector<const Mesh*> meshPtrs( mapAndNum.second ); |
| 365 | + auto keepGoing = ParallelFor( components, [&] ( size_t i ) |
| 366 | + { |
| 367 | + FaceBitSet compBs( mesh.topology.faceSize() ); |
| 368 | + BitSetParallelFor( mesh.topology.getValidFaces(), [&] ( FaceId f ) |
| 369 | + { |
| 370 | + if ( RegionId( i ) == mapAndNum.first[f] ) |
| 371 | + compBs.set( f ); |
| 372 | + } ); |
| 373 | + components[i].addMeshPart( MeshPart( mesh, &compBs ) ); |
| 374 | + |
| 375 | + if ( params.trySelfBoolean ) |
| 376 | + { |
| 377 | + auto sbRes = selfBoolean( components[i] ); |
| 378 | + if ( sbRes.has_value() ) |
| 379 | + { |
| 380 | + sbRes->deleteFaces( sbRes->topology.getValidFaces() - MeshComponents::getLargestComponent( *sbRes ) ); |
| 381 | + components[i] = std::move( *sbRes ); |
| 382 | + } |
| 383 | + } |
| 384 | + if ( params.flipInverted && components[i].volume() < 0.0f ) |
| 385 | + components[i].topology.flipOrientation(); |
| 386 | + |
| 387 | + meshPtrs[i] = &components[i]; |
| 388 | + |
| 389 | + compBs = {}; // reduce peek memory |
| 390 | + |
| 391 | + if ( params.expansionRatio != 0.0f ) |
| 392 | + { |
| 393 | + auto center = components[i].findCenterFromFaces(); |
| 394 | + components[i].transform( AffineXf3f::xfAround( Matrix3f::scale( 1.0f + params.expansionRatio ), center ) ); |
| 395 | + } |
| 396 | + }, subprogress( params.baseParams.progressCb, 0.1f, 0.4f ) ); |
| 397 | + if ( !keepGoing ) |
| 398 | + return unexpectedOperationCanceled(); |
| 399 | + UniteManyMeshesParams ump = params.baseParams; |
| 400 | + ump.progressCb = subprogress( params.baseParams.progressCb, 0.4f, 1.0f ); |
| 401 | + return uniteManyMeshes( meshPtrs, ump ); |
| 402 | +} |
| 403 | + |
350 | 404 | } |
0 commit comments