Download

Procedural Mesh Performance Issues

Hey, I am building a procedurally generated sphere.

It is being built up from a cube by getting the 6 plane vertices, then calculating triangles and then building the mesh in 6 sections.
I am having ridiculous performance issues, however. The cubes have a “density”, which is how many vertices are on each section, so a density of 3 will have 6 * (3*3) vertices for example.
Anything above 10-12 vertices takes ages to load after property change and increases the ram memory usage of the editor by a large amount.
About a density of 20 takes up 4 gigs of ram. Furthermore, deleting the object does not return the memory for some reason.
I tried looking at the profiler and it mainly said the CPU is waiting a ton of time.

Are there any known issues that can cause this or is just my code performing horribly ?
I can post the code but it is a fairly large chunk, so it does not matter much before specifics.

Hello,

Based on my experience, runtime generating a procedural mesh with a few thousand vertices is almost unnoticeable, and only generating tens of thousands of vertices causes minor FPS drops, although I have never made measurements, and I have always worked with a single mesh section and flat planes.
If I understand you correctly, you experience performance issues after 10-12 vertices, which seems extreme, so it might be useful to share your code.

Hey, Sorry for the late reply @Kontur I set everything back with the virus and all.

I switched to the RuntimeMeshComponent and got a fairly nice optimization.
However when I use its native code I can freely generate a mesh up to 2k vertices without any noticeable lag and even then it lags just a bit.
I don’t have access from there to the actual data to add noise to it so I made my own implementation.
Unfortunately that performs at a tenth of the performance. It lags as soon as 200 vertices are reached.
I copied the original implementation and the same thing happens so the issue is not the formula of generation I believe.
This is the generation code :


void ProceduralPlanetData::Initialize()
{
    //Clear Previous Data and Set New Size for Arrays
    int32 NewSize = Resolution * Resolution * 6;
    MeshData.Normals.Reset(NewSize);
    MeshData.UV0.Reset(NewSize);
    MeshData.Positions.Reset(NewSize);
    MeshData.Tangents.Reset(NewSize);
    MeshData.VertexColors.Reset(NewSize);
    MeshData.Triangles.Reset((NewSize - 2*Resolution + 1)*6);

    //Build the 6 planes
    MakePlaneData(FRotator(0.f, 0.f, 0.f));
    MakePlaneData(FRotator(90.f, 0.f, 0.f));
    MakePlaneData(FRotator(180.f, 0.f, 0.f));
    MakePlaneData(FRotator(-90.f, 0.f, 0.f));
    MakePlaneData(FRotator(90.f, 0.f, 90.f));
    MakePlaneData(FRotator(90.f, 0.f, -90.f));
}

void ProceduralPlanetData::MakePlaneData(FRotator Rotation)
{
    //Baked triangle order to save some calculations
    uint32 TrisOrder[6] = { 0, 1, Resolution, 1, Resolution + 1, Resolution };
    for (uint32 XIndex = 0; XIndex < Resolution; XIndex++)
    {
        for (uint32 YIndex = 0; YIndex < Resolution; YIndex++)
        {
            FVector Position;
            Position.X = (XIndex / ((float)Resolution - 1) - 0.5f) * 2.f;
            Position.Y = (YIndex / ((float)Resolution - 1) - 0.5f) * 2.f;
            Position.Z = 1.f;
            //Unit Sphere position
            Position.Normalize();
            //Add plane rotation
            Position = Rotation.RotateVector(Position);
            //Normals
            MeshData.Normals.Add(Position);
            //UV0
            MeshData.UV0.Add(FVector2D(Position.X,Position.Y));
            //Position
            Position *= Radius;
            MeshData.Positions.Add(Position);

            //Calculate triangles
            if (XIndex != Resolution - 1 && YIndex != Resolution - 1)
            {
                uint32 TrisNumber = MeshData.Positions.Num()-1;
                for (int32 TrisIndex = 0; TrisIndex < 6; TrisIndex++)
                {
                    MeshData.Triangles.Add(TrisOrder[TrisIndex] + TrisNumber);
                }
            }
        }
    }
}


Then I call it from my actor class OnConstruction and PostEditChangeProperty.
I am getting a large memory overhead thought when I increase the vertices and it doesnt go down when I lower them or delete the object. Not sure why that happens but it might be the solution there.