Visual Scripting – Generating Normals

I got rather carried away with actually developing this next feature so this post covers 2 weeks of development . I have since completed more work which i’ll cover in the next post.

Generating Normals

The task for the next feature was to start adding trees to my landscape but only where the slope of the landscape below was suitable, this requires knowing the normals of the mesh so i started here.

My plan was to look at all of the points adjacent to another and use the cross product with 2 adjacent points at a time and then average them. In the first week my attempt was very problem filled, at one point the compiler had decided that the entire function had no purpose and optimised all of it away, making debugging the problem rather difficult. I also had a problem where the normals that were returned to me were just incorrect.

What did not help was that I had decided to use a complicated method to get the normals with the hope that it would run fast. This was a mistake and i should have started with a simpler approach and optimised it later if needed. I do this often and in future i’ll be assuring i don’t do it. KISS: Keep It Simple, Stupid.

My second approach worked immediately, further hammering down theĀ KISS “methodology”. First i initialise my blank array of normals to face along the z axis, this is so that all of the edge cases are handled. Then for each point that is not on an edge i calculate the normal for the positions above and right, then the positions below and left giving me two normals, then i can average these out. I only need to work out the two opposing normals as all four adjacent positions are factored into the calculation.

TArray<FVector> UMyFunctionLibrary::GenerateNormals(const TArray<FVector> positions)
    // Output array
    TArray<FVector> Normals;

    // Set every vector to point up
    for (size_t i = 0; i < positions.Num(); i++)
        Normals.Add(FVector(0.f, 0.0f, 1.0f));

    size_t size = sqrt(positions.Num());

    // For each point that is not on the edge
    for (size_t y = 1; y < size - 1; y++)
        for (size_t x = 1; x < size - 1; x++)

            FVector thisPos = positions[y * size + x];

            // Up and Right
            FVector up = thisPos - positions[(y + 1) * size + x];
            FVector right = thisPos - positions[y * size + (x + 1)];

            FVector normalA = FVector::CrossProduct(up, right);

            // Down and Left
            FVector down = thisPos - positions[(y - 1) * size + x];
            FVector left = thisPos - positions[y * size + (x - 1)];

            FVector normalB = FVector::CrossProduct(down, left);

            // Mean of both normals
            FVector normalAvg = (normalA + normalB) / 2;

            // Set ths normal in the array
            // Negated because Unreal uses an inverted y axis
            Normals[y * size + x] = -normalAvg;

    return Normals;

Here’s some renders using the line renderer to visualise the normals.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s