Calculating vector from barycentric coordinate and vertex normals

I am prototyping a hover ship game and the goal is to have the ship smoothly adjust its orientation as it moves across terrain. Currently the C++ code uses quaternions to accurately snap the ship’s normal to the surface normal of the static mesh under the ship.

To achieve smooth orientation changes I am cast a ray downward to get the impact face, and then fetch vertex coordinates and vertex normals, and calculate the barycentric coordinate. However, I am having trouble using this information to calculate a vector to orient the ship to. I believe the vector should be a weighted sum of the vertex normals but my calculation at the end does not give the correct result.

Can you provide suggestions on how to calculate this vector? Here is a code snippet.

FStaticMeshVertexBuffers* VertexBuffers = &StaticMesh->GetRenderData()->LODResources[0].VertexBuffers;
FStaticMeshVertexBuffer* StaticMeshVertexBuffer = &VertexBuffers->StaticMeshVertexBuffer;
FPositionVertexBuffer* PositionVertexBuffer = &VertexBuffers->PositionVertexBuffer;

FIndexArrayView IndexBuffer = StaticMesh->GetRenderData()->LODResources[0].IndexBuffer.GetArrayView();

// Storage for the triangle vertices
FVector VertexPositions[3];
FVector VertexNormals[3];

for (int i = 0; i < 3; i++) {

    // Get vertex index
    uint32 index = IndexBuffer[FaceIndex * 3 + i];


    // Get vertex position and normal
    VertexPositions[i] = FVector(PositionVertexBuffer->VertexPosition(index));
    VertexNormals[i] = FVector(StaticMeshVertexBuffer->VertexTangentZ(index));

    // Transform position and normal into world space
    VertexPositions[i] = ComponentTransform.TransformPosition(VertexPositions[i]);
    VertexNormals[i] = ComponentTransform.TransformVector(VertexNormals[i]);

}

// Get barycentric coordinates at raycast impact point
FVector b = FMath::ComputeBaryCentric2D(ImpactPoint, VertexPositions[0], VertexPositions[1], VertexPositions[2]);

// Vector that will use to orient ship
FVector BaryNormal;

// This code attempts to build the BaryNormal vector but it does not give the desired result
BaryNormal.X = b.X * VertexNormals[0].X + b.Y * VertexNormals[1].X + b.Z * VertexNormals[2].X;
BaryNormal.Y = b.X * VertexNormals[0].Y + b.Y * VertexNormals[1].Y + b.Z * VertexNormals[2].Y;
BaryNormal.Z = b.X * VertexNormals[0].Z + b.Y * VertexNormals[1].Z + b.Z * VertexNormals[2].Z;

BaryNormal.Normalize();

You can also use a linetrace built into the engine to retrieve the hit normal in an FHitResult struct.

World->LineTraceSingleByChannel(OutHit, Start, End, CollisionChannel, Params)

This library shows how it is done:

  • “\UE_4.27\Engine\Source\Runtime\Engine\Private\KismetSystemLibrary.cpp”
    UKismetSystemLibrary::LineTraceSingle

Thanks @Roy_Wierer.Seda145 but I’m already using LineTraceSingleByChannel to get the hit result and the impact normal. The impact normal works fine to orient the ship but it will not give smooth transitions between surfaces. Using barycentric coordinates with the vertex normals is a way to get smooth movement and is the subject of my question.

1 Like

hey, im trying to figure out the same thing you are. did you ever figure it out? how do you access the information from the triangle? how do you caculate an interpolated normal from the barycentric coordinate?