Skip to content

Simple algorithm of how to generate a godot mesh with C#. I use a noise algorithm for the height data, and SurfaceTool to generate Triangles, one vertex per height.

License

Notifications You must be signed in to change notification settings

barrrettt/godot3-generatedmesh-cs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Mesh Generator example. Godot3 in C#

Simple algorithm of how to generate a godot mesh with C#. I use a noise algorithm for the height data, and SurfaceTool to generate Triangles, one vertex per height.

This is the code:

using Godot;
using System;

public class GeneratedMesh : MeshInstance{

    ArrayMesh tmpMesh = new ArrayMesh();
    [Export]Material mat; 
    Random random = new Random();

    [Export] public  int terrainSize = 512;
    [Export] public int seed = -1;

    [Export] public  float minColorHeight = -1f, maxColorHeight = 10f;
    [Export] Color[] heightsColors = {
        new  Color(0.1f, 0.1f, 1f),//on inspector change colors: ocean dark blue to montain white snow
        new  Color(0.1f, 0.9f, 0.1f),
        new  Color(05f, 0.4f, 0.1f),
        new  Color(0.8f, 0.8f, 0.8f),
        new  Color(0.8f, 0.8f, 0.8f),
        new  Color(0.8f, 0.8f, 0.8f),
        new  Color(0.8f, 0.8f, 0.8f),
        new  Color(0.8f, 0.8f, 0.8f),
        new  Color(0.8f, 0.8f, 0.8f),
        new  Color(0.8f, 0.8f, 0.8f),
    };

    public override void _Ready() {

        float[,] dataTerrain = generateData();
        generateMeshAndColors(dataTerrain);

    }

    private float[,] generateData(){
        //random noise data: n x n heights
        OpenSimplexNoise noise = new OpenSimplexNoise();
        if (seed == -1) seed = random.Next();
        noise.Seed = seed;

        noise.Octaves = 8;
        noise.Period = 22;
        noise.Lacunarity = 1.5f;
        noise.Persistence = 0.02f;

        float heigthMulti = 2f;

        //1 pass low noise
        float[,] dataTerrain = new float[terrainSize,terrainSize];
        for (int i = 0; i<terrainSize; i++){
            for (int j = 0; j<terrainSize; j++){
                dataTerrain[j,i] += noise.GetNoise2d(j,i) * heigthMulti;
            }
        }

        //2 pass medium heighs
        heigthMulti = 10f;
        noise.Octaves = 8;
        noise.Period = 100;
        noise.Lacunarity = 1.5f;
        noise.Persistence = 0.02f;
        
        for (int i = 0; i<terrainSize; i++){
            for (int j = 0; j<terrainSize; j++){
                dataTerrain[j,i] += noise.GetNoise2d(j,i) * heigthMulti;
            }
        }

        //3 pass Heavy heighs
        heigthMulti = 30f;
        noise.Octaves = 8;
        noise.Period = 200;
        noise.Lacunarity = 1.5f;
        noise.Persistence = 0.02f;

        //and get min and max heights
        minColorHeight = float.MaxValue;
        maxColorHeight = float.MinValue;

        for (int i = 0; i<terrainSize; i++){
            for (int j = 0; j<terrainSize; j++){
                dataTerrain[j,i] += noise.GetNoise2d(j,i) * heigthMulti;
                //minMax
                float h =  dataTerrain[j,i];
                if (h<minColorHeight) minColorHeight = h;
                if (h>maxColorHeight) maxColorHeight = h;
            }
        }
        return dataTerrain;
    }

    public void generateMeshAndColors(float[,] dataTerrain){
        //init tool 
        SurfaceTool st = new SurfaceTool();
        st.Begin(Mesh.PrimitiveType.Triangles);
        st.SetMaterial(mat);

        //get HeightsQuats and create triangles
        int maxI = dataTerrain.GetLength(0);
        int maxJ = dataTerrain.GetLength(1);
        int quadCount = 0;

        //1º rows, 2º columns
        for (int i = 0; i < maxI-1; i++){
            for (int j = 0; j < maxJ-1; j++){
                
                Quat q = new Quat();//heights to Quat
                
                q.x = dataTerrain[i,j];       q.y = dataTerrain[i,j+1];

                q.z = dataTerrain[i+1,j];     q.w = dataTerrain[i+1,j+1];

                //to mesh
                Vector3 offset = new Vector3(j,0,i);
                createQuad(st, offset, q);

                /*//debug algoritm
                GD.Print(string.Format("•quad{0}:({1},{2}): points: \n{3} {4} {5}   {6} {7} {8}\n{9} {10} {11}   {12} {13} {14}",
                quadCount,i,j, 
                offset.x, q.x, offset.z - 1,       offset.x + 1, q.y, offset.z-1,
                offset.x, q.z, offset.z,         offset.x + 1, q.w, offset.z));
                */
                quadCount++;
            }
        }

        //finally
        st.GenerateNormals();
        st.Commit(tmpMesh);
        this.SetMesh(tmpMesh);

    }

    private SurfaceTool createQuad(SurfaceTool st, Vector3 pos, Quat q){
        
        //1Quad = 4 points = 2 triangles
        Vector3 v1 = new Vector3(0, q.x,-1) + pos;
        Vector3 v2 = new Vector3(1, q.y,-1) + pos;
        Vector3 v3 = new Vector3(1, q.w, 0) + pos;
        Vector3 v4 = new Vector3(0, q.z,0) + pos;

        //tri1
        st.AddUv(new Vector2(0,0));
        st.AddColor(heightToColor(v1.y));// active albedoVertexColors on material
        st.AddVertex(v1);
        

        st.AddUv(new Vector2(0,1));
        st.AddColor(heightToColor(v2.y));
        st.AddVertex(v2);


        st.AddUv(new Vector2(1,1));
        st.AddColor(heightToColor(v4.y));
        st.AddVertex(v4);

        //tri2
        st.AddUv(new Vector2(0,0));
        st.AddColor(heightToColor(v2.y));
        st.AddVertex(v2);

        st.AddUv(new Vector2(0,1));
        st.AddColor(heightToColor(v3.y));
        st.AddVertex(v3);

        st.AddUv(new Vector2(1,1));
        st.AddColor(heightToColor(v4.y));
        st.AddVertex(v4);

        return st;
    }

    private Color heightToColor(float height){

        //get color
        int colorsCount = heightsColors.Length;
        float value = Mathf.InverseLerp(minColorHeight,maxColorHeight,height);
        int indexColor =  Mathf.Clamp( Mathf.RoundToInt( Mathf.Lerp(0,colorsCount-1,value)), 0, colorsCount-1);
        
        return heightsColors[indexColor];
    }

}

About

Simple algorithm of how to generate a godot mesh with C#. I use a noise algorithm for the height data, and SurfaceTool to generate Triangles, one vertex per height.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published