| 19 | |
| 20 | template<typename T> |
| 21 | MeshIntersectionResult meshRayIntersect_( const MeshPart& meshPart, const Line3<T>& line, |
| 22 | T rayStart, T rayEnd, const IntersectionPrecomputes<T>& prec, bool closestIntersect, const FacePredicate & validFaces ) |
| 23 | { |
| 24 | const auto& m = meshPart.mesh; |
| 25 | const auto& tree = m.getAABBTree(); |
| 26 | MeshIntersectionResult res; |
| 27 | if( tree.nodes().empty() ) |
| 28 | return res; |
| 29 | |
| 30 | RayOrigin<T> rayOrigin{ line.p }; |
| 31 | T s = rayStart, e = rayEnd; |
| 32 | if( !rayBoxIntersect( Box3<T>{ tree[tree.rootNodeId()].box }, rayOrigin, s, e, prec ) ) |
| 33 | return res; |
| 34 | |
| 35 | constexpr int maxTreeDepth = 32; |
| 36 | std::pair< NodeId,T> nodesStack[maxTreeDepth]; |
| 37 | int currentNode = 0; |
| 38 | nodesStack[0] = { tree.rootNodeId(), rayStart }; |
| 39 | |
| 40 | TriPointf triP; |
| 41 | while( currentNode >= 0 && ( closestIntersect || !res.proj.face ) ) |
| 42 | { |
| 43 | if( currentNode >= maxTreeDepth ) // max depth exceeded |
| 44 | { |
| 45 | spdlog::critical( "Maximal AABBTree depth reached!" ); |
| 46 | assert( false ); |
| 47 | break; |
| 48 | } |
| 49 | |
| 50 | const auto& node = tree[nodesStack[currentNode].first]; |
| 51 | if( nodesStack[currentNode--].second < rayEnd ) |
| 52 | { |
| 53 | if( node.leaf() ) |
| 54 | { |
| 55 | auto face = node.leafId(); |
| 56 | if( ( !meshPart.region || meshPart.region->test( face ) ) && ( !validFaces || validFaces( face ) ) ) |
| 57 | { |
| 58 | VertId a, b, c; |
| 59 | m.topology.getTriVerts( face, a, b, c ); |
| 60 | |
| 61 | const Vector3<T> vA = Vector3<T>( m.points[a] ) - line.p; |
| 62 | const Vector3<T> vB = Vector3<T>( m.points[b] ) - line.p; |
| 63 | const Vector3<T> vC = Vector3<T>( m.points[c] ) - line.p; |
| 64 | if ( auto triIsect = rayTriangleIntersect( vA, vB, vC, prec ) ) |
| 65 | { |
| 66 | const T t( triIsect->t ); |
| 67 | if ( t < rayEnd && t > rayStart ) |
| 68 | { |
| 69 | res.distanceAlongLine = triIsect->t; |
| 70 | res.proj.face = face; |
| 71 | triP = triIsect->bary; |
| 72 | if ( t == 0 ) |
| 73 | { |
| 74 | rayStart = rayEnd = 0; |
| 75 | break; // intersection exactly at ray origin |
| 76 | } |
| 77 | if ( t < 0 ) |
| 78 | { |
no test coverage detected