| 211 | } |
| 212 | |
| 213 | MeshMeshSignedDistanceResult findSignedDistance( const MeshPart & a, const MeshPart & b, const AffineXf3f* rigidB2A, float upDistLimitSq ) |
| 214 | { |
| 215 | MR_TIMER; |
| 216 | auto res = findDistance( a, b, rigidB2A, upDistLimitSq > 0.0f ? upDistLimitSq : FLT_TRUE_MIN ); |
| 217 | if ( res.distSq == FLT_TRUE_MIN ) |
| 218 | res.distSq = 0.0f; |
| 219 | if ( !res.a || !res.b ) |
| 220 | { // findDistance returns the limit sentinel when nothing closer was found |
| 221 | assert( res.distSq == upDistLimitSq ); |
| 222 | return { res.a, res.b, MeshMeshCollisionStatus::NotColliding, std::sqrt( res.distSq ) }; |
| 223 | } |
| 224 | assert( res.distSq == 0.0f || res.distSq < upDistLimitSq ); |
| 225 | std::vector<FaceFace> collisions; |
| 226 | auto status = findCollisionStatus( a, b, res, rigidB2A, &collisions ); |
| 227 | if ( status == MeshMeshCollisionStatus::Touching ) |
| 228 | return { res.a, res.b,status, 0 }; // two meshes touch one another but do not intersect |
| 229 | if ( status != MeshMeshCollisionStatus::Colliding ) |
| 230 | { |
| 231 | auto dist = status == MeshMeshCollisionStatus::BothOutside ? std::sqrt( res.distSq ) : -std::sqrt( res.distSq ); |
| 232 | return { res.a, res.b,status, dist }; |
| 233 | } |
| 234 | |
| 235 | // colliding |
| 236 | |
| 237 | auto zoneAndDistancesAB = findSignedDistanceOneWay( a, b, collisions, false, rigidB2A ); |
| 238 | auto zoneAndDistancesBA = findSignedDistanceOneWay( a, b, collisions, true, rigidB2A ); |
| 239 | |
| 240 | MeshMeshSignedDistanceResult signedRes; |
| 241 | signedRes.status = status; |
| 242 | signedRes.signedDist = FLT_MAX; |
| 243 | |
| 244 | auto getTriByVert = [&]( const MeshTopology& topology, VertId id )->FaceId |
| 245 | { |
| 246 | for ( auto e : orgRing( topology, id ) ) |
| 247 | if ( auto f = topology.left( e ) ) |
| 248 | return f; |
| 249 | return FaceId{}; |
| 250 | }; |
| 251 | |
| 252 | for ( VertId id : zoneAndDistancesAB.vertBS ) |
| 253 | { |
| 254 | const auto& [proj, dist] = zoneAndDistancesAB.projectons[id]; |
| 255 | if ( proj.valid() && dist < signedRes.signedDist ) |
| 256 | { |
| 257 | signedRes.a = { getTriByVert( a.mesh.topology,id ), a.mesh.points[id] }; |
| 258 | signedRes.b = proj; |
| 259 | signedRes.signedDist = dist; |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | for ( VertId id : zoneAndDistancesBA.vertBS ) |
| 264 | { |
| 265 | const auto& [proj, dist] = zoneAndDistancesBA.projectons[id]; |
| 266 | if ( proj.valid() && dist < signedRes.signedDist ) |
| 267 | { |
| 268 | signedRes.a = proj; |
| 269 | signedRes.b = { getTriByVert( b.mesh.topology,id ), b.mesh.points[id] }; |
| 270 | signedRes.signedDist = dist; |
nothing calls this directly
no test coverage detected