sphere box test

This commit is contained in:
Jorijn van der Graaf 2026-03-07 20:26:53 +01:00
commit 78f5b85d24

View file

@ -194,44 +194,31 @@ namespace Crafter {
} }
export template<typename T> 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) { constexpr bool IntersectionTestSphereOrientedBox(Vector<T, 3, 0> sphereCenter, T sphereRadius, Vector<T, 3, 0> boxSize, MatrixRowMajor<T, 4, 3, 1> boxMatrix) {
Vector<T, 3, 0> d = spherePos - Vector<T, 3, 0>(boxMat.m[0][3], boxMat.m[1][3], boxMat.m[2][3]); // 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) // Clamp the local center to the OBB's extents
{ Vector<T, 3, 0> closestPoint = Vector<T, 3, 0>(
Vector<T, 3, 0> axis(boxMat.m[0][i], boxMat.m[1][i], boxMat.m[2][i]); std::max(-boxSize.x, std::min(localCenter.x, boxSize.x)),
T dist = Vector<T, 3, 0>::Dot(d, axis); std::max(-boxSize.y, std::min(localCenter.y, boxSize.y)),
T excess = std::fabs(dist) - boxSize.v[i]; std::max(-boxSize.z, std::min(localCenter.z, boxSize.z))
excess = std::max(excess, T(0)); );
distSq += excess * excess;
}
// Check sphere axes (world axes) // Calculate the distance between the closest point and the local center
for (std::uint32_t i = 0; i < 3; ++i) { Vector<T, 3, 0> delta = localCenter - closestPoint;
Vector<T, 3, 0> axis = Vector<T, 3, 0>(0,0,0); T distanceSquared = Vector<T, 3, 0>::Dot(delta, delta);
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;
}
// Check cross product axes // Check if the distance is less than or equal to the sphere's radius squared
for (std::uint32_t i = 0; i < 3; ++i) { return distanceSquared <= (sphereRadius * sphereRadius);
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;
} }
} }