When we try to sweep a sphere or a capsule toward a Sphere Primitive collision, the results are wrong when the collision has an offset from its mesh.
Hit results are incoherent, and are not located on the surface of the collision.
This also happens with Capsule Sweeps vs Sphere collision.
We came up with some code change in GeometryQueries.cpp, that I will attach to this request, that fixes the issues for Spheres and Capsules.
(Full change in attached .txt file)
Modified code is located between the following tags :
//++Tuque
//--Tuque
Do you think that this fix is legitimate ?
Thank you
FGJKSphereSingleSIMD ComputeLocalSphere(const FSphere& Sphere, const FRigidTransform3& SphereTM, const FRigidTransform3& OtherTM)
{
//++Tuque - Fix Sphere center offset not transformed during sphere sweeps
//const FVec3 SphereWorldLocation = FVec3(Sphere.GetCenterf()) + SphereTM.GetLocation();
const FVec3 SphereWorldLocation = SphereTM.TransformPositionNoScale(FVec3(Sphere.GetCenterf()));
//--Tuque
const FVec3 SphereLocation = OtherTM.InverseTransformPositionNoScale(SphereWorldLocation);
return FGJKSphereSingleSIMD(SphereLocation, Sphere.GetRadiusf());
}
//...
bool SweepSphereVsSphere(const FSphere& SweptSphere, const FRigidTransform3& SweptSphereTM, const FSphere& TestSphere, const FRigidTransform3& TestSphereTM,
const FVec3& SweepDir, const FReal Length, const FReal Thickness, const bool bComputeMTD,
FReal& OutTime, FVec3& OutPosition, FVec3& OutNormal, int32& OutFaceIndex, FVec3& OutFaceNormal)
{
const Sweeps::ESweepFlags Flags = bComputeMTD ? Sweeps::ESweepFlags::MTD : Sweeps::ESweepFlags::None;
// Transform to the test shape's local space. Note: We can skip rotation which is much faster
const FVec3 TestGeomLocalToWorld = TestSphereTM.GetLocation();
const FVec3 SweptShapeLocalToWorld = SweptSphereTM.GetLocation();
const FVec3 LocalSweepDir = SweepDir;
//++Tuque - Fix Sphere center offset not transformed during sphere sweeps
//const FVec3 LocalSweepStart = SweptSphere.GetCenterf() + SweptShapeLocalToWorld - TestGeomLocalToWorld;
const FVec3 WorldSweptSphereOffset = SweptSphereTM.TransformVectorNoScale(FVec3(SweptSphere.GetCenterf()));
const FVec3 LocalSweepStart = WorldSweptSphereOffset + SweptShapeLocalToWorld - TestGeomLocalToWorld;
//--Tuque
const FReal SweepRadius = Thickness + SweptSphere.GetRadiusf();
//++Tuque - Fix Sphere center offset not transformed during sphere sweeps
//const bool bResult = Sweeps::SweepSphereVsSphere(LocalSweepStart, LocalSweepDir, Length, SweepRadius, TestSphere.GetCenterf(), TestSphere.GetRadiusf(), Flags, OutTime, OutPosition, OutNormal);
const FVec3 WorldTestSphereOffset = TestSphereTM.TransformVectorNoScale(FVec3(TestSphere.GetCenterf()));
const bool bResult = Sweeps::SweepSphereVsSphere(LocalSweepStart, LocalSweepDir, Length, SweepRadius, WorldTestSphereOffset, TestSphere.GetRadiusf(), Flags, OutTime, OutPosition, OutNormal);
//--Tuque
TransformSweepResultsToWorld(bResult, OutTime, bComputeMTD, TestSphere, TestGeomLocalToWorld, LocalSweepDir, OutPosition, OutNormal, OutFaceIndex, OutPosition, OutNormal, OutFaceNormal);
return bResult;
}
[Attachment Removed]