sphere box test
This commit is contained in:
parent
1f70062750
commit
78f5b85d24
1 changed files with 23 additions and 36 deletions
|
|
@ -194,44 +194,31 @@ namespace Crafter {
|
|||
}
|
||||
|
||||
export template<typename T>
|
||||
constexpr bool IntersectionTestSphereOrientatedBox(Vector<T, 3, 0> spherePos, T sphereRadius, Vector<T, 3, 0> boxSize, MatrixRowMajor<T, 4, 3, 1> boxMat) {
|
||||
Vector<T, 3, 0> d = spherePos - Vector<T, 3, 0>(boxMat.m[0][3], boxMat.m[1][3], boxMat.m[2][3]);
|
||||
constexpr bool IntersectionTestSphereOrientedBox(Vector<T, 3, 0> sphereCenter, T sphereRadius, Vector<T, 3, 0> boxSize, MatrixRowMajor<T, 4, 3, 1> boxMatrix) {
|
||||
// Extract the OBB's axes (columns of the rotation matrix)
|
||||
Vector<T, 3, 0> xAxis(boxMatrix.m[0][0], boxMatrix.m[0][1], boxMatrix.m[0][2]);
|
||||
Vector<T, 3, 0> yAxis(boxMatrix.m[1][0], boxMatrix.m[1][1], boxMatrix.m[1][2]);
|
||||
Vector<T, 3, 0> zAxis(boxMatrix.m[2][0], boxMatrix.m[2][1], boxMatrix.m[2][2]);
|
||||
|
||||
T distSq = T(0);
|
||||
// Translate the sphere center into the OBB's local space
|
||||
Vector<T, 3, 0> localCenter = Vector<T, 3, 0>(
|
||||
Vector<T, 3, 0>::Dot(sphereCenter - Vector<T, 3, 0>(boxMatrix.m[3][0], boxMatrix.m[3][1], boxMatrix.m[3][2]), xAxis),
|
||||
Vector<T, 3, 0>::Dot(sphereCenter - Vector<T, 3, 0>(boxMatrix.m[3][0], boxMatrix.m[3][1], boxMatrix.m[3][2]), yAxis),
|
||||
Vector<T, 3, 0>::Dot(sphereCenter - Vector<T, 3, 0>(boxMatrix.m[3][0], boxMatrix.m[3][1], boxMatrix.m[3][2]), zAxis)
|
||||
);
|
||||
|
||||
for (std::uint32_t i = 0; i < 3; ++i)
|
||||
{
|
||||
Vector<T, 3, 0> axis(boxMat.m[0][i], boxMat.m[1][i], boxMat.m[2][i]);
|
||||
T dist = Vector<T, 3, 0>::Dot(d, axis);
|
||||
T excess = std::fabs(dist) - boxSize.v[i];
|
||||
excess = std::max(excess, T(0));
|
||||
distSq += excess * excess;
|
||||
}
|
||||
// Clamp the local center to the OBB's extents
|
||||
Vector<T, 3, 0> closestPoint = Vector<T, 3, 0>(
|
||||
std::max(-boxSize.x, std::min(localCenter.x, boxSize.x)),
|
||||
std::max(-boxSize.y, std::min(localCenter.y, boxSize.y)),
|
||||
std::max(-boxSize.z, std::min(localCenter.z, boxSize.z))
|
||||
);
|
||||
|
||||
// Check sphere axes (world axes)
|
||||
for (std::uint32_t i = 0; i < 3; ++i) {
|
||||
Vector<T, 3, 0> axis = Vector<T, 3, 0>(0,0,0);
|
||||
axis.v[i] = T(1);
|
||||
T dist = Vector<T, 3, 0>::Dot(d, axis);
|
||||
T excess = std::abs(dist) - sphereRadius;
|
||||
excess = std::max(excess, T(0));
|
||||
distSq += excess * excess;
|
||||
}
|
||||
// Calculate the distance between the closest point and the local center
|
||||
Vector<T, 3, 0> delta = localCenter - closestPoint;
|
||||
T distanceSquared = Vector<T, 3, 0>::Dot(delta, delta);
|
||||
|
||||
// Check cross product axes
|
||||
for (std::uint32_t i = 0; i < 3; ++i) {
|
||||
for (std::uint32_t j = 0; j < 3; ++j) {
|
||||
Vector<T, 3, 0> boxAxis(boxMat.m[0][i], boxMat.m[1][i], boxMat.m[2][i]);
|
||||
Vector<T, 3, 0> sphereAxis = Vector<T, 3, 0>(0,0,0);
|
||||
sphereAxis.v[j] = T(1);
|
||||
Vector<T, 3, 0> axis = Vector<T, 3, 0>::Cross(boxAxis, sphereAxis);
|
||||
T dist = Vector<T, 3, 0>::Dot(d, axis);
|
||||
T excess = std::abs(dist) - (boxSize.v[(i+1)%3] * sphereRadius + boxSize.v[(i+2)%3] * sphereRadius);
|
||||
excess = std::max(excess, T(0));
|
||||
distSq += excess * excess;
|
||||
}
|
||||
}
|
||||
|
||||
return distSq <= sphereRadius * sphereRadius;
|
||||
// Check if the distance is less than or equal to the sphere's radius squared
|
||||
return distanceSquared <= (sphereRadius * sphereRadius);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue