bool UGameplayStatics::FindCollisionUV(const struct FHitResult& Hit, int32 UVChannel, FVector2D& UV)
{
bool bSuccess = false;
if (!UPhysicsSettings::Get()->bSupportUVFromHitResults)
{
FMessageLog("PIE").Warning(LOCTEXT("CollisionUVNoSupport", "Calling FindCollisionUV but 'Support UV From Hit Results' is not enabled in project settings. This is required for finding UV for collision results."));
}
else
{
UPrimitiveComponent* HitPrimComp = Hit.Component.Get();
if (HitPrimComp)
{
UBodySetup* BodySetup = HitPrimComp->GetBodySetup();
if (BodySetup)
{
const FVector LocalHitPos = HitPrimComp->GetComponentToWorld().InverseTransformPosition(Hit.Location);
bSuccess = BodySetup->CalcUVAtLocation(LocalHitPos, Hit.FaceIndex, UVChannel, UV);
}
}
}
return bSuccess;
}
bool UBodySetup::CalcUVAtLocation(const FVector& BodySpaceLocation, int32 FaceIndex, int32 UVChannel, FVector2D& UV) const
{
bool bSuccess = false;
if (UVInfo.VertUVs.IsValidIndex(UVChannel) && UVInfo.IndexBuffer.IsValidIndex(FaceIndex * 3 + 2))
{
int32 Index0 = UVInfo.IndexBuffer[FaceIndex * 3 + 0];
int32 Index1 = UVInfo.IndexBuffer[FaceIndex * 3 + 1];
int32 Index2 = UVInfo.IndexBuffer[FaceIndex * 3 + 2];
FVector Pos0 = UVInfo.VertPositions[Index0];
FVector Pos1 = UVInfo.VertPositions[Index1];
FVector Pos2 = UVInfo.VertPositions[Index2];
FVector2D UV0 = UVInfo.VertUVs[UVChannel][Index0];
FVector2D UV1 = UVInfo.VertUVs[UVChannel][Index1];
FVector2D UV2 = UVInfo.VertUVs[UVChannel][Index2];
// Transform hit location from world to local space.
// Find barycentric coords
FVector BaryCoords = FMath::ComputeBaryCentric2D(BodySpaceLocation, Pos0, Pos1, Pos2);
// Use to blend UVs
UV = (BaryCoords.X * UV0) + (BaryCoords.Y * UV1) + (BaryCoords.Z * UV2);
bSuccess = true;
}
return bSuccess;
}