Hi yes, my solution works okay. It doesn’t give 100% uniform results, but it helps.
Declaration:
UFUNCTION(BlueprintPure)
static float ExpFadeOutSineWave(float time, float exponent, float frequency, float startValue, float amplitude);
Definition:
bool UCustomBlueprintFunctionLibrary::FindCollisionUVFromHit(const struct FHitResult& Hit, FVector2f& UV, int32 UVChannel, float& stretch)
{
USkeletalMeshComponent* Mesh = Cast<USkeletalMeshComponent>(Hit.Component);
if (Mesh) {
FSkeletalMeshRenderData* RenderData = Mesh->GetSkeletalMeshRenderData();
FSkeletalMeshLODRenderData& LODData = RenderData->LODRenderData[0];
FRawStaticIndexBuffer16or32Interface* Indices = RenderData->LODRenderData[0].MultiSizeIndexContainer.GetIndexBuffer();
if (Hit.FaceIndex * 3 + 2 > Indices->Num()) return false;
const int32 Index0 = Indices->Get(Hit.FaceIndex * 3 + 0);
const int32 Index1 = Indices->Get(Hit.FaceIndex * 3 + 1);
const int32 Index2 = Indices->Get(Hit.FaceIndex * 3 + 2);
const FVector3f Pos0 = Mesh->GetSkinnedVertexPosition(Mesh, Index0, LODData, RenderData->LODRenderData[0].SkinWeightVertexBuffer);
const FVector3f Pos1 = Mesh->GetSkinnedVertexPosition(Mesh, Index1, LODData, RenderData->LODRenderData[0].SkinWeightVertexBuffer);
const FVector3f Pos2 = Mesh->GetSkinnedVertexPosition(Mesh, Index2, LODData, RenderData->LODRenderData[0].SkinWeightVertexBuffer);
FVector tPos0;
FVector tPos1;
FVector tPos2;
tPos0.X = Pos0.X;
tPos0.Y = Pos0.Y;
tPos0.Z = Pos0.Z;
tPos1.X = Pos1.X;
tPos1.Y = Pos1.Y;
tPos1.Z = Pos1.Z;
tPos2.X = Pos2.X;
tPos2.Y = Pos2.Y;
tPos2.Z = Pos2.Z;
const FVector2D UV0 = Mesh->GetVertexUV(Index0, UVChannel);
const FVector2D UV1 = Mesh->GetVertexUV(Index1, UVChannel);
const FVector2D UV2 = Mesh->GetVertexUV(Index2, UVChannel);
/*Calculate the UV stretch*/
//Calculate area of 3D triangle
// Calculate two vectors forming the sides of the triangle
FVector3f side1_3d = Pos1 - Pos0;
FVector3f side2_3d = Pos2 - Pos0;
// Calculate the cross product of the two vectors
FVector3f crossProduct_3d = FVector3f::CrossProduct(side1_3d, side2_3d);
// Calculate the magnitude of the cross product
float area3D = 0.5f * crossProduct_3d.Size();
//Calculate area of 2D triangle
// Calculate two vectors forming the sides of the triangle
FVector2D side1_2d = UV1 - UV0;
FVector2D side2_2d = UV2 - UV0;
// Calculate the cross product (which results in a scalar in 2D)
float crossProduct_2d = FVector2D::CrossProduct(side1_2d, side2_2d);
// Calculate the absolute value of the cross product and divide by 2 to get the area
float area2D = FMath::Abs(crossProduct_2d) * 0.5f;
// Calculate stretch
stretch = sqrt(area2D) / sqrt(area3D);
const FVector LocalHitPos = Mesh->GetComponentToWorld().InverseTransformPosition(Hit.Location);
const FVector BaryCoords = FMath::ComputeBaryCentric2D(LocalHitPos, tPos0, tPos1, tPos2);
FVector2D tUV = (BaryCoords.X * UV0) + (BaryCoords.Y * UV1) + (BaryCoords.Z * UV2);
UV.X = tUV.X;
UV.Y = tUV.Y;
return true;
}
else {
return false;
}
}```