| 17 | { |
| 18 | |
| 19 | std::vector<FaceFace> findCollidingTriangles( const MeshPart & a, const MeshPart & b, const AffineXf3f * rigidB2A, bool firstIntersectionOnly ) |
| 20 | { |
| 21 | MR_TIMER; |
| 22 | |
| 23 | std::vector<FaceFace> res; |
| 24 | const AABBTree & aTree = a.mesh.getAABBTree(); |
| 25 | const AABBTree & bTree = b.mesh.getAABBTree(); |
| 26 | if ( aTree.nodes().empty() || bTree.nodes().empty() ) |
| 27 | return res; |
| 28 | |
| 29 | NodeBitSet aNodes, bNodes; |
| 30 | NodeBitSet* aNodesPtr{nullptr}, * bNodesPtr{nullptr}; |
| 31 | if ( a.region ) |
| 32 | { |
| 33 | aNodes = aTree.getNodesFromLeaves( *a.region ); |
| 34 | aNodesPtr = &aNodes; |
| 35 | } |
| 36 | if ( b.region ) |
| 37 | { |
| 38 | bNodes = bTree.getNodesFromLeaves( *b.region ); |
| 39 | bNodesPtr = &bNodes; |
| 40 | } |
| 41 | |
| 42 | std::vector<NodeNode> subtasks{ { NodeId{ 0 }, NodeId{ 0 } } }; |
| 43 | |
| 44 | while( !subtasks.empty() ) |
| 45 | { |
| 46 | const auto s = subtasks.back(); |
| 47 | subtasks.pop_back(); |
| 48 | |
| 49 | if ( aNodesPtr && !aNodes.test( s.aNode ) ) |
| 50 | continue; |
| 51 | if ( bNodesPtr && !bNodes.test( s.bNode ) ) |
| 52 | continue; |
| 53 | |
| 54 | const auto & aNode = aTree[s.aNode]; |
| 55 | const auto & bNode = bTree[s.bNode]; |
| 56 | |
| 57 | const auto overlap = aNode.box.intersection( transformed( bNode.box, rigidB2A ) ); |
| 58 | if ( !overlap.valid() ) |
| 59 | continue; |
| 60 | |
| 61 | if ( aNode.leaf() && bNode.leaf() ) |
| 62 | { |
| 63 | const auto aFace = aNode.leafId(); |
| 64 | const auto bFace = bNode.leafId(); |
| 65 | res.emplace_back( aFace, bFace ); |
| 66 | continue; |
| 67 | } |
| 68 | |
| 69 | if ( !aNode.leaf() && ( bNode.leaf() || aNode.box.volume() >= bNode.box.volume() ) ) |
| 70 | { |
| 71 | // split aNode |
| 72 | subtasks.push_back( { aNode.l, s.bNode } ); |
| 73 | subtasks.push_back( { aNode.r, s.bNode } ); |
| 74 | } |
| 75 | else |
| 76 | { |
no test coverage detected