Ejemplo n.º 1
0
    private void AddMesh()
    {
        Vector3[] vertices = new Vector3[] {
            new Vector3(-5f, 0f, -5f),
            new Vector3(5f, 0f, -5f),
            new Vector3(5f, 0f, 5f),
            new Vector3(-5f, 0f, 5f)
        };
        Vector3[] normals = new Vector3[] {
            Vector3.Up,
            Vector3.Up,
            Vector3.Up,
            Vector3.Up
        };
        int[] indices = new int[] { 0, 1, 2, 0, 2, 3 };

        Godot.Collections.Array meshData = new Godot.Collections.Array();
        meshData.Resize((int)Mesh.ArrayType.Max);
        meshData[(int)Mesh.ArrayType.Vertex] = vertices;
        meshData[(int)Mesh.ArrayType.Normal] = normals;
        meshData[(int)Mesh.ArrayType.Index]  = indices;

        _mesh = VisualServer.MeshCreate();
        VisualServer.MeshAddSurfaceFromArrays(_mesh, VisualServer.PrimitiveType.Triangles, meshData);

        _instance = VisualServer.InstanceCreate();
        VisualServer.InstanceSetBase(_instance, _mesh);

        RID scenario = GetWorld().Scenario;

        VisualServer.InstanceSetScenario(_instance, scenario);
    }
Ejemplo n.º 2
0
    private ArrayMesh draw_hex_tri(Vector3[] base_verts, ref ArrayMesh local_array_mesh)
    {
        Mesh a = new ArrayMesh();

        Godot.Collections.Array mesh_arrays = new Godot.Collections.Array();

        int[] indices = new int[] { 0, 1, 2, 0, 2, 3 };
        mesh_arrays.Resize((int)Mesh.ArrayType.Max);

        for (int i = 0; i < 3; i++)
        {
            List <Vector3> verts = new List <Vector3>();
            for (int i2 = 0; i2 < base_verts.Length; i2++)
            {
                verts.Add(point_rotation(base_verts[i2], base_verts[2], 120f * i));
            }

            //mesh_arrays[Godot.Mesh] = verts;
            mesh_arrays[(int)ArrayMesh.ArrayType.Vertex] = verts.ToArray();
            mesh_arrays[(int)ArrayMesh.ArrayType.Index]  = indices;
        }

        local_array_mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, mesh_arrays);
        return(local_array_mesh);
    }
Ejemplo n.º 3
0
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
        StreamReader textReader = new StreamReader(@"./UMA/Content/UMA_Core/HumanMale/Slots/Body/UMA_Human_Male_Legs_Slot.asset");

        textReader.ReadLine();
        textReader.ReadLine();
        textReader.ReadLine();
        var deserializer = new DeserializerBuilder()
                           .WithNamingConvention(new CamelCaseNamingConvention())
                           .Build();

        var slotData = deserializer.Deserialize <SlotYaml>(textReader);

        GD.Print(slotData.MonoBehaviour.MName);

        var verticeOrder = decodeUnitysCompressionSubMesh(slotData.MonoBehaviour.MeshData.Submeshes[0].Triangles);
        var surfaceArray = new Godot.Collections.Array();

        surfaceArray.Resize(ARRAY_MAX);
        surfaceArray[ARRAY_VERTEX]   = slotData.MonoBehaviour.MeshData.Vertices;
        surfaceArray[ARRAY_NORMAL]   = slotData.MonoBehaviour.MeshData.Normals;
        surfaceArray[ARRAY_TANGENTS] = CreateTangents(slotData.MonoBehaviour.MeshData.Tangents);
        surfaceArray[ARRAY_TEX_UV]   = slotData.MonoBehaviour.MeshData.Uv;
        surfaceArray[ARRAY_INDEX]    = verticeOrder;

        ArrayMesh legMesh = new ArrayMesh();

        legMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, surfaceArray, null, ARRAY_FORMAT_VERTEX + ARRAY_FORMAT_NORMAL + ARRAY_FORMAT_TANGENT + ARRAY_FORMAT_TANGENT);
        var legMaterial = (SpatialMaterial)GD.Load("res://skin.material");

        GD.Print("Surface Count" + legMesh.GetSurfaceCount());
        var node = (MeshInstance)FindNode("UmaMeshNode");


        GD.Print(node.GetType());
        GD.Print(node.Mesh.ToString());
        legMesh.SurfaceSetMaterial(0, legMaterial);
        node.SetMesh(legMesh);
        GD.Print(node.Mesh.ToString());

        /*
         * DynamicCharacterAvatar characterAvatar= new DynamicCharacterAvatar();
         *
         * DynamicAssetLoader.Instance = new DynamicAssetLoader();
         *
         * UMA.UMAContext.Instance = new UMA.UMAContext();
         * characterAvatar.context = UMA.UMAContext.Instance;
         * UMA.UMAContext.Instance.raceLibrary = new DynamicRaceLibrary();
         *
         * UMATextRecipe textRecipe = new UMATextRecipe();
         * textRecipe.recipeString = @"{""version"":3,""packedSlotDataList"":[],""slotsV2"":[],""slotsV3"":[{""id"":""MaleEyes"",""scale"":100,""copyIdx"":-1,""overlays"":[{""id"":""EyeOverlay"",""colorIdx"":3,""rect"":[0,0,0,0]},{""id"":""Default Eye Adjust"",""colorIdx"":2,""rect"":[0,0,0,0]}]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":""MaleInnerMouth"",""scale"":100,""copyIdx"":-1,""overlays"":[{""id"":""InnerMouth"",""colorIdx"":4,""rect"":[0,0,0,0]}]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":""MaleTorso"",""scale"":100,""copyIdx"":-1,""overlays"":[{""id"":""M_BodOverlay 1"",""colorIdx"":0,""rect"":[0,0,0,0]}]},{""id"":""MaleFeet"",""scale"":100,""copyIdx"":16,""overlays"":[]},{""id"":""MaleHands"",""scale"":100,""copyIdx"":16,""overlays"":[]},{""id"":""MaleLegs"",""scale"":100,""copyIdx"":16,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":""M_Highpoly Head"",""scale"":100,""copyIdx"":-1,""overlays"":[{""id"":""M_Face"",""colorIdx"":0,""rect"":[0,0,0,0]}]}],""colors"":[],""fColors"":[{""name"":""Skin"",""colors"":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{""name"":""Hair"",""colors"":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{""name"":""Eyes"",""colors"":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{""name"":""-"",""colors"":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{""name"":""-"",""colors"":[234,234,234,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]}],""sharedColorCount"":3,""race"":""HumanMale"",""packedDna"":[{""dnaType"":""DynamicUMADna"",""dnaTypeHash"":815443803,""packedDna"":""{\""bDnaAsset\"":{\""instanceID\"":12024},\""bDnaAssetName\"":\""HumanMaleDynamicDnaAsset\"",\""bDnaSettings\"":[{\""name\"":\""skinGreenness\"",\""value\"":128},{\""name\"":\""skinBlueness\"",\""value\"":128},{\""name\"":\""skinRedness\"",\""value\"":128},{\""name\"":\""height\"",\""value\"":128},{\""name\"":\""headSize\"",\""value\"":128},{\""name\"":\""headWidth\"",\""value\"":128},{\""name\"":\""neckThickness\"",\""value\"":128},{\""name\"":\""armLength\"",\""value\"":128},{\""name\"":\""forearmLength\"",\""value\"":128},{\""name\"":\""armWidth\"",\""value\"":128},{\""name\"":\""forearmWidth\"",\""value\"":128},{\""name\"":\""handsSize\"",\""value\"":128},{\""name\"":\""feetSize\"",\""value\"":128},{\""name\"":\""legSeparation\"",\""value\"":128},{\""name\"":\""upperMuscle\"",\""value\"":128},{\""name\"":\""lowerMuscle\"",\""value\"":128},{\""name\"":\""upperWeight\"",\""value\"":128},{\""name\"":\""lowerWeight\"",\""value\"":128},{\""name\"":\""legsSize\"",\""value\"":128},{\""name\"":\""belly\"",\""value\"":128},{\""name\"":\""waist\"",\""value\"":128},{\""name\"":\""gluteusSize\"",\""value\"":128},{\""name\"":\""earsSize\"",\""value\"":128},{\""name\"":\""earsPosition\"",\""value\"":128},{\""name\"":\""earsRotation\"",\""value\"":128},{\""name\"":\""noseSize\"",\""value\"":128},{\""name\"":\""noseCurve\"",\""value\"":128},{\""name\"":\""noseWidth\"",\""value\"":128},{\""name\"":\""noseInclination\"",\""value\"":128},{\""name\"":\""nosePosition\"",\""value\"":128},{\""name\"":\""nosePronounced\"",\""value\"":128},{\""name\"":\""noseFlatten\"",\""value\"":128},{\""name\"":\""chinSize\"",\""value\"":128},{\""name\"":\""chinPronounced\"",\""value\"":128},{\""name\"":\""chinPosition\"",\""value\"":128},{\""name\"":\""mandibleSize\"",\""value\"":128},{\""name\"":\""jawsSize\"",\""value\"":128},{\""name\"":\""jawsPosition\"",\""value\"":128},{\""name\"":\""cheekSize\"",\""value\"":128},{\""name\"":\""cheekPosition\"",\""value\"":128},{\""name\"":\""lowCheekPronounced\"",\""value\"":128},{\""name\"":\""lowCheekPosition\"",\""value\"":128},{\""name\"":\""foreheadSize\"",\""value\"":128},{\""name\"":\""foreheadPosition\"",\""value\"":128},{\""name\"":\""lipsSize\"",\""value\"":128},{\""name\"":\""mouthSize\"",\""value\"":128},{\""name\"":\""eyeRotation\"",\""value\"":128},{\""name\"":\""eyeSize\"",\""value\"":128},{\""name\"":\""breastSize\"",\""value\"":128},{\""name\"":\""eyeSpacing\"",\""value\"":128}]}""}],""wardrobeSet"":[],""packedRecipeType"":""Standard""}";
         * GD.Print(textRecipe.recipeString);
         * characterAvatar.umaRecipe = textRecipe;
         *
         * UMAGenerator generator = new UMAGenerator();
         * characterAvatar.umaGenerator = generator;
         *
         * characterAvatar.Start();
         * GD.Print("It actually made it to the end of the Start routine!");*/
    }
    public static ArrayMesh GenerateMesh(float[,] noiseMap, float heightMultiplier, Curve heightCurve, int lod)
    {
        int width  = noiseMap.GetLength(0);
        int height = noiseMap.GetLength(1);

        Vector3[] vertices = new Vector3[width * height];
        Vector3[] normals  = new Vector3[width * height];
        Vector2[] uvs      = new Vector2[width * height];
        int[]     indices  = new int[(width - 1) * (height - 1) * 6];

        float topLeftX = (width - 1) / -2f;
        float topLeftZ = (height - 1) / -2f;

        int simplificationFactor = lod == 0 ? 1 : lod * 2;
        int verticesPerLine      = (width - 1) / simplificationFactor + 1;

        int vertices_idx = 0;

        for (int y = 0; y < height; y += simplificationFactor)
        {
            for (int x = 0; x < width; x += simplificationFactor)
            {
                vertices[vertices_idx] = new Vector3(topLeftX + x, heightCurve.Interpolate(noiseMap[x, y]) * heightMultiplier, topLeftZ + y);
                uvs[vertices_idx]      = new Vector2(x / (float)width, y / (float)height);
                ++vertices_idx;
            }
        }

        int indices_idx = 0;

        vertices_idx = 0;
        for (int y = 0; y < height; y += simplificationFactor)
        {
            for (int x = 0; x < width; x += simplificationFactor)
            {
                if (x < width - 1 && y < height - 1)
                {
                    AddTriangle(vertices, indices, normals, vertices_idx, vertices_idx + verticesPerLine + 1, vertices_idx + verticesPerLine, indices_idx);
                    AddTriangle(vertices, indices, normals, vertices_idx, vertices_idx + 1, vertices_idx + verticesPerLine + 1, indices_idx + 3);
                    indices_idx += 6;
                }
                ++vertices_idx;
            }
        }

        var meshArrays = new Godot.Collections.Array();

        meshArrays.Resize((int)ArrayMesh.ArrayType.Max);
        meshArrays[(int)ArrayMesh.ArrayType.Vertex] = vertices;
        meshArrays[(int)ArrayMesh.ArrayType.TexUv]  = uvs;
        meshArrays[(int)ArrayMesh.ArrayType.Index]  = indices;
        meshArrays[(int)ArrayMesh.ArrayType.Normal] = normals;

        ArrayMesh mesh = new ArrayMesh();

        mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, meshArrays);
        return(mesh);
    }
Ejemplo n.º 5
0
    void CombinaQuads()
    {
        MeshInstance cube = new MeshInstance
        {
            Name = "Chunk"
        };

        ArrayMesh cubeArray = new ArrayMesh();

        Godot.Collections.Array kids = chunk.GetChildren();
        Material[] materiais         = new Material[kids.Count];

        int contador = 0;

        foreach (MeshInstance meshI in kids)
        {
            Vector3[] vertLocal  = (Vector3[])meshI.Mesh.SurfaceGetArrays(0)[(int)ArrayMesh.ArrayType.Vertex];
            Vector3[] vertGlobal = new Vector3[vertLocal.Length];

            //convertendo as coordenads de locais para globais dos quads
            for (int i = 0; i < vertLocal.Length; i++)
            {
                vertGlobal[i].x = vertLocal[i].x + meshI.Translation.x;
                vertGlobal[i].y = vertLocal[i].y + meshI.Translation.y;
                vertGlobal[i].z = vertLocal[i].z + meshI.Translation.z;
            }

            ArrayMesh combineArray = new ArrayMesh();
            var       arrays       = new Godot.Collections.Array();
            arrays.Resize((int)ArrayMesh.ArrayType.Max);
            arrays[(int)ArrayMesh.ArrayType.Vertex] = vertGlobal;
            arrays[(int)ArrayMesh.ArrayType.Normal] = meshI.Mesh.SurfaceGetArrays(0)[(int)ArrayMesh.ArrayType.Normal];
            arrays[(int)ArrayMesh.ArrayType.TexUv]  = meshI.Mesh.SurfaceGetArrays(0)[(int)ArrayMesh.ArrayType.TexUv];
            arrays[(int)ArrayMesh.ArrayType.Index]  = meshI.Mesh.SurfaceGetArrays(0)[(int)ArrayMesh.ArrayType.Index];

            cubeArray.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);
            materiais[contador] = meshI.GetSurfaceMaterial(0);

            meshI.QueueFree();
            contador++;
        }

        cube.Mesh = cubeArray;
        for (int i = 0; i < materiais.Length; i++)
        {
            cube.SetSurfaceMaterial(i, materiais[i]);
        }

        chunk.AddChild(cube);
    }
Ejemplo n.º 6
0
    public void CreateQuad(Vector3 vertex0, Vector3 vertex1, Vector3 vertex2, Vector3 vertex3)
    {
        // Generate quad mesh (2 triangles)

        Vector3[] vertices = { vertex0,   //top-left
                               vertex1,   //top-right
                               vertex2,   //bottom-left
                               vertex3 }; //bottom-right

        int[] index = new int[6] {
            0, 1, 2, 3, 2, 1
        };

        // UVs
        Vector2[] uvs = { new Vector2(0f, 1f),   //top-left
                          new Vector2(1f, 1f),   //top-right
                          new Vector2(0f, 0f),   //bottom-left
                          new Vector2(1f, 0f) }; //bottom-right

        // Normals
        Vector3[] normals = new Vector3[4]
        {
            Vector3.Up, Vector3.Up, Vector3.Up, Vector3.Up
        };

        Godot.Collections.Array arrays = new Godot.Collections.Array();
        arrays.Resize(9);
        // see
        arrays[0] = vertices;
        arrays[1] = normals;
        arrays[4] = uvs;
        arrays[8] = index;

        // Create the Mesh.

        // Initialize the ArrayMesh.
        ArrayMesh arr_mesh = new ArrayMesh();

        arr_mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);
        MeshInstance quad = new MeshInstance();

        quad.Mesh = arr_mesh;

        quad.MaterialOverride = cubeMaterial; // apply texture - rock, dirt, grass, etc.
        quad.MaterialOverride = cubeMaterial; // apply texture - rock, dirt, grass, etc.

        cube.AddChild(quad);                  // add quad to the cube node
    }
Ejemplo n.º 7
0
    /// <summary>
    ///   Creates the actual mesh object. Call InitializeMesh instead of this directly
    /// </summary>
    private void BuildMesh()
    {
        // This is actually a triangle list, but the index buffer is used to build
        // the indices (to emulate a triangle fan)
        var bufferSize = vertices2D.Count + 2;
        var indexSize  = vertices2D.Count * 3;

        var arrays = new Godot.Collections.Array();

        arrays.Resize((int)Mesh.ArrayType.Max);

        // Build vertex, index, and uv lists

        // Index mapping to build all triangles
        var indices            = new int[indexSize];
        int currentVertexIndex = 1;

        for (int i = 0; i < indexSize; i += 3)
        {
            indices[i]     = 0;
            indices[i + 1] = currentVertexIndex + 1;
            indices[i + 2] = currentVertexIndex;

            ++currentVertexIndex;
        }

        // Write mesh data //
        var vertices = new Vector3[bufferSize];
        var uvs      = new Vector2[bufferSize];

        int writeIndex = 0;

        writeIndex = InitializeCorrectMembrane(writeIndex, vertices, uvs);

        if (writeIndex != bufferSize)
        {
            throw new Exception("Membrane buffer write ended up at wrong index");
        }

        // Godot might do this automatically
        // // Set the bounds to get frustum culling and LOD to work correctly.
        // // TODO: make this more accurate by calculating the actual extents
        // m_mesh->_setBounds(Ogre::Aabb(Float3::ZERO, Float3::UNIT_SCALE * 50)
        //     /*, false*/);
        // m_mesh->_setBoundingSphereRadius(50);

        arrays[(int)Mesh.ArrayType.Vertex] = vertices;
        arrays[(int)Mesh.ArrayType.Index]  = indices;
        arrays[(int)Mesh.ArrayType.TexUv]  = uvs;

        // Create the mesh
        var generatedMesh = new ArrayMesh();

        var surfaceIndex = generatedMesh.GetSurfaceCount();

        generatedMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);

        // Apply the mesh to us
        Mesh = generatedMesh;
        SetSurfaceMaterial(surfaceIndex, MaterialToEdit);
    }
Ejemplo n.º 8
0
    void CriaQuad(LadoDoCubo lado)
    {
        ArrayMesh    quadArray;
        MeshInstance quad = new MeshInstance
        {
            Name = "Quad"
        };

        //Criando os Arrays
        Vector3[] normalArray = new Vector3[4];
        Vector2[] uvArray     = new Vector2[4];
        Vector3[] vertexArray = new Vector3[4];
        int[]     indexArray  = new int[6];

        //calculando UVs no atlas
        Vector2 uv00;
        Vector2 uv10;
        Vector2 uv01;
        Vector2 uv11;

        if (tBloco == TipoDeBloco.GRASS && lado == LadoDoCubo.TOP)
        {
            uv00 = blocosUVs[0, 0];
            uv10 = blocosUVs[0, 1];
            uv01 = blocosUVs[0, 2];
            uv11 = blocosUVs[0, 3];
        }
        else if (tBloco == TipoDeBloco.GRASS && lado == LadoDoCubo.BOTTOM)
        {
            uv00 = blocosUVs[(int)(TipoDeBloco.DIRT + 1), 0];
            uv10 = blocosUVs[(int)(TipoDeBloco.DIRT + 1), 1];
            uv01 = blocosUVs[(int)(TipoDeBloco.DIRT + 1), 2];
            uv11 = blocosUVs[(int)(TipoDeBloco.DIRT + 1), 3];
        }
        else
        {
            uv00 = blocosUVs[(int)(tBloco + 1), 0];
            uv10 = blocosUVs[(int)(tBloco + 1), 1];
            uv01 = blocosUVs[(int)(tBloco + 1), 2];
            uv11 = blocosUVs[(int)(tBloco + 1), 3];
        }


        //Todos os Vertices Possiveis
        Vector3 p0 = new Vector3(-0.5f, -0.5f, 0.5f);
        Vector3 p1 = new Vector3(0.5f, -0.5f, 0.5f);
        Vector3 p2 = new Vector3(0.5f, -0.5f, -0.5f);
        Vector3 p3 = new Vector3(-0.5f, -0.5f, -0.5f);
        Vector3 p4 = new Vector3(-0.5f, 0.5f, 0.5f);
        Vector3 p5 = new Vector3(0.5f, 0.5f, 0.5f);
        Vector3 p6 = new Vector3(0.5f, 0.5f, -0.5f);
        Vector3 p7 = new Vector3(-0.5f, 0.5f, -0.5f);

        switch (lado)
        {
        case LadoDoCubo.BOTTOM:
            vertexArray = new Vector3[] { p0, p1, p2, p3 };
            normalArray = new Vector3[] { Vector3.Down, Vector3.Down, Vector3.Down, Vector3.Down };
            break;

        case LadoDoCubo.TOP:
            vertexArray = new Vector3[] { p7, p6, p5, p4 };
            normalArray = new Vector3[] { Vector3.Up, Vector3.Up, Vector3.Up, Vector3.Up };
            break;

        case LadoDoCubo.LEFT:
            vertexArray = new Vector3[] { p7, p4, p0, p3 };
            normalArray = new Vector3[] { Vector3.Left, Vector3.Left, Vector3.Left, Vector3.Left };
            break;

        case LadoDoCubo.RIGHT:
            vertexArray = new Vector3[] { p5, p6, p2, p1 };
            normalArray = new Vector3[] { Vector3.Right, Vector3.Right, Vector3.Right, Vector3.Right };
            break;

        case LadoDoCubo.FRONT:
            vertexArray = new Vector3[] { p4, p5, p1, p0 };
            normalArray = new Vector3[] { Vector3.Forward, Vector3.Forward, Vector3.Forward, Vector3.Forward };
            break;

        case LadoDoCubo.BACK:
            vertexArray = new Vector3[] { p6, p7, p3, p2 };
            normalArray = new Vector3[] { Vector3.Back, Vector3.Back, Vector3.Back, Vector3.Back };
            break;
        }

        uvArray    = new Vector2[] { uv11, uv01, uv00, uv10 };
        indexArray = new int[] { 0, 1, 2, 0, 2, 3 };

        quadArray = new ArrayMesh();
        var arrays = new Godot.Collections.Array();

        arrays.Resize((int)ArrayMesh.ArrayType.Max);
        arrays[(int)ArrayMesh.ArrayType.Vertex] = vertexArray;
        arrays[(int)ArrayMesh.ArrayType.Normal] = normalArray;
        arrays[(int)ArrayMesh.ArrayType.TexUv]  = uvArray;
        arrays[(int)ArrayMesh.ArrayType.Index]  = indexArray;

        quadArray.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);

        quad.Mesh = quadArray;
        quad.SetSurfaceMaterial(0, material);

        quad.Translation = position;

        parent.AddChild(quad);
    }
Ejemplo n.º 9
0
    private static void RenderDrawData(ImDrawDataPtr drawData, RID parent)
    {
        // allocate and clear out our CanvasItem pool as needed
        int neededNodes = 0;

        for (int i = 0; i < drawData.CmdListsCount; i++)
        {
            neededNodes += drawData.CmdListsRange[i].CmdBuffer.Size;
        }

        while (_children.Count < neededNodes)
        {
            RID newChild = VisualServer.CanvasItemCreate();
            VisualServer.CanvasItemSetParent(newChild, parent);
            VisualServer.CanvasItemSetDrawIndex(newChild, _children.Count);
            _children.Add(newChild);
            _meshes.Add(new ArrayMesh());
        }

        // trim unused nodes to reduce draw calls
        while (_children.Count > neededNodes)
        {
            int idx = _children.Count - 1;
            VisualServer.FreeRid(_children[idx]);
            _children.RemoveAt(idx);
            _meshes.RemoveAt(idx);
        }

        // render
        drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale);
        int nodeN = 0;

        for (int n = 0; n < drawData.CmdListsCount; n++)
        {
            ImDrawListPtr cmdList   = drawData.CmdListsRange[n];
            int           idxOffset = 0;

            int nVert = cmdList.VtxBuffer.Size;

            Godot.Vector2[] vertices = new Godot.Vector2[nVert];
            Godot.Color[]   colors   = new Godot.Color[nVert];
            Godot.Vector2[] uvs      = new Godot.Vector2[nVert];

            for (int i = 0; i < cmdList.VtxBuffer.Size; i++)
            {
                var v = cmdList.VtxBuffer[i];
                vertices[i] = new Godot.Vector2(v.pos.X, v.pos.Y);
                // need to reverse the color bytes
                byte[] col = BitConverter.GetBytes(v.col);
                colors[i] = Godot.Color.Color8(col[0], col[1], col[2], col[3]);
                uvs[i]    = new Godot.Vector2(v.uv.X, v.uv.Y);
            }

            for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++, nodeN++)
            {
                ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi];

                int[] indices = new int[drawCmd.ElemCount];
                for (int i = idxOffset, j = 0; i < idxOffset + drawCmd.ElemCount; i++, j++)
                {
                    indices[j] = cmdList.IdxBuffer[i];
                }

                var arrays = new Godot.Collections.Array();
                arrays.Resize((int)ArrayMesh.ArrayType.Max);
                arrays[(int)ArrayMesh.ArrayType.Vertex] = vertices;
                arrays[(int)ArrayMesh.ArrayType.Color]  = colors;
                arrays[(int)ArrayMesh.ArrayType.TexUv]  = uvs;
                arrays[(int)ArrayMesh.ArrayType.Index]  = indices;

                var mesh = _meshes[nodeN];
                while (mesh.GetSurfaceCount() > 0)
                {
                    mesh.SurfaceRemove(0);
                }
                mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);

                RID child = _children[nodeN];

                Texture tex = GetTexture(drawCmd.TextureId);
                VisualServer.CanvasItemClear(child);
                VisualServer.CanvasItemSetClip(child, true);
                VisualServer.CanvasItemSetCustomRect(child, true, new Godot.Rect2(
                                                         drawCmd.ClipRect.X,
                                                         drawCmd.ClipRect.Y,
                                                         drawCmd.ClipRect.Z - drawCmd.ClipRect.X,
                                                         drawCmd.ClipRect.W - drawCmd.ClipRect.Y)
                                                     );
                VisualServer.CanvasItemAddMesh(child, mesh.GetRid(), null, null, tex.GetRid(), new RID(null));

                // why doesn't this quite work?
                // VisualServer.CanvasItemAddTriangleArray(child, indices, vertices, colors, uvs, null, null, tex.GetRid(), -1, new RID(null));

                idxOffset += (int)drawCmd.ElemCount;
            }
        }
    }
Ejemplo n.º 10
0
    // Creates a cube using an array.
    public static ArrayMesh Render(SubChunk chunk)
    {
        var arrayMesh = new ArrayMesh();

        // Array containing other arrays.
        // OpenGL array buffer.
        var arrays = new Godot.Collections.Array();

        arrays.Resize((int)ArrayMesh.ArrayType.Max);


        // Reset data.
        Vertices = new Vector3[9999];
        Normals  = new Vector3[9999];
        Colors   = new Color[9999];

        vertexIdx = 0;

        if (chunk.isEmpty())
        {
            return(null);
        }


        // If sub-chunk is completely surrounded. dont render.
        if (!chunk.RenderBottom && !chunk.RenderTop &&
            !chunk.RenderLeft && !chunk.RenderRight &&
            !chunk.RenderFront && !chunk.RenderBack)
        {
            return(null);
        }

        // 16 x 16 x 16 = 4096 blocks.
        for (int x = 0; x < Chunk.CHUNK_SIZE; x++)
        {
            for (int z = 0; z < Chunk.CHUNK_SIZE; z++)
            {
                for (int y = 0; y < Chunk.CHUNK_SIZE; y++)
                {
                    // No cube if not active.
                    if (chunk.GetBlock(x, y, z) == -1)
                    {
                        continue;
                    }

                    // Create cube.
                    CreateBlock(new Vector3(x, y, z), chunk);
                }
            }
        }

        System.Array.Resize(ref Vertices, vertexIdx);
        System.Array.Resize(ref Normals, vertexIdx);
        System.Array.Resize(ref Colors, vertexIdx);

        // Fill the array with the others arrays.
        arrays[0] = Vertices;
        arrays[1] = Normals;
        arrays[3] = Colors;

        if (Vertices.Length == 0)
        {
            return(null);
        }

        // Create surface from arrays.
        arrayMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);

        ApplyMaterial(arrayMesh);

        // Done.
        return(arrayMesh);
    }
Ejemplo n.º 11
0
    private bool CreateMesh()
    {
        var verts   = new List <Vector3>();
        var normals = new List <Vector3>();
        var indices = new List <int>();

        Dictionary <Vector3, int> index_lookup = new Dictionary <Vector3, int>();

        ArrayMesh marching_cube_mesh = new ArrayMesh();

        float cell_dimensions = mesh_dimensions.x / (float)mesh_subdivisions;//  10.0F;
        int   splitting       = mesh_subdivisions / 2;
        int   index_counter   = 0;

        for (int i = -splitting; i < splitting; i++)
        {
            for (int j = -splitting; j < splitting; j++)
            {
                for (int k = -splitting; k < splitting; k++)
                {
                    Vector3  cell_origin = mesh_offset + new Vector3(i * cell_dimensions, j * cell_dimensions, k * cell_dimensions);
                    GridCell grid_cell   = new GridCell();
                    grid_cell.p    = new Vector3[8];
                    grid_cell.val  = new float[8];
                    grid_cell.p[0] = cell_origin + 0.5F * new Vector3(-cell_dimensions, -cell_dimensions, -cell_dimensions);
                    grid_cell.p[1] = cell_origin + 0.5F * new Vector3(+cell_dimensions, -cell_dimensions, -cell_dimensions);
                    grid_cell.p[2] = cell_origin + 0.5F * new Vector3(+cell_dimensions, +cell_dimensions, -cell_dimensions);
                    grid_cell.p[3] = cell_origin + 0.5F * new Vector3(-cell_dimensions, +cell_dimensions, -cell_dimensions);
                    grid_cell.p[4] = cell_origin + 0.5F * new Vector3(-cell_dimensions, -cell_dimensions, +cell_dimensions);
                    grid_cell.p[5] = cell_origin + 0.5F * new Vector3(+cell_dimensions, -cell_dimensions, +cell_dimensions);
                    grid_cell.p[6] = cell_origin + 0.5F * new Vector3(+cell_dimensions, +cell_dimensions, +cell_dimensions);
                    grid_cell.p[7] = cell_origin + 0.5F * new Vector3(-cell_dimensions, +cell_dimensions, +cell_dimensions);

                    for (int l = 0; l < 8; l++)
                    {
                        grid_cell.val[l] = GetDensity(grid_cell.p[l]);
                    }

                    Triangle[] triangles     = new Triangle[5];
                    int        num_triangles = Polygonise(ref grid_cell, 0.5F, ref triangles);
                    for (int l = 0; l < num_triangles; l++)
                    {
                        // for (int m = 0; m < 3; m++)
                        // {
                        //     if (index_lookup.ContainsKey(triangles[l].p[m]))
                        //     {
                        //         indices.Add(index_lookup[triangles[l].p[m]]);
                        //         // GD.Print("collision: " + triangles[l].p[m] + "\t" + index_lookup[triangles[l].p[0]] + "\t" + index_counter);
                        //     }
                        //     else
                        //     {
                        //         index_lookup[triangles[l].p[m]] = index_counter;
                        //         indices.Add(index_counter);
                        //         verts.Add(triangles[l].p[m]);
                        //         ++index_counter;
                        //     }
                        // }
                        index_lookup[triangles[l].p[1]] = index_counter;
                        indices.Add(index_counter);
                        verts.Add(triangles[l].p[1]);
                        ++index_counter;

                        index_lookup[triangles[l].p[0]] = index_counter;
                        indices.Add(index_counter);
                        verts.Add(triangles[l].p[0]);
                        ++index_counter;

                        index_lookup[triangles[l].p[2]] = index_counter;
                        indices.Add(index_counter);
                        verts.Add(triangles[l].p[2]);
                        ++index_counter;
                    }
                }
            }
        }

        Stopwatch stopwatch = new Stopwatch();

        stopwatch.Start();
        foreach (var vertex in verts)
        {
            normals.Add(GetDensityNormal(vertex));
        }
        stopwatch.Stop();
        // GD.Print("normals took ", stopwatch.Elapsed);

        if (index_counter == 0)
        {
            return(false);
        }
        // GD.Print("index: " + index_counter);
        // GD.Print("verts: " + verts.Count);
        // Calculate vertex normals, face-by-face.
        // for (int i = 0; i < mdt.GetFaceCount(); i++)
        // {
        //     // Get the index in the vertex array.
        //     int a = mdt.GetFaceVertex(i, 0);
        //     int b = mdt.GetFaceVertex(i, 1);
        //     int c = mdt.GetFaceVertex(i, 2);
        //     // Get vertex position using vertex index.
        //     Vector3 ap = mdt.GetVertex(a);
        //     Vector3 bp = mdt.GetVertex(b);
        //     Vector3 cp = mdt.GetVertex(c);
        //     // Calculate face normal.
        //     Vector3 n = (bp - cp).Cross(ap - bp).Normalized();
        //     // Add face normal to current vertex normal.
        //     // This will not result in perfect normals, but it will be close.
        //     mdt.SetVertexNormal(a, n + mdt.GetVertexNormal(a));
        //     mdt.SetVertexNormal(b, n + mdt.GetVertexNormal(b));
        //     mdt.SetVertexNormal(c, n + mdt.GetVertexNormal(c));
        // }

        // Run through vertices one last time to normalize normals and
        // set color to normal.
        // foreach (int i in Enumerable.Range(0,mdt.GetVertexCount()))
        // {
        //     var v = mdt.GetVertexNormal(i).Normalized();
        //     mdt.SetVertexNormal(i, v);
        //     mdt.SetVertexColor(i, new Color(v.x, v.y, v.z));
        // }

        var arr = new Godot.Collections.Array();

        arr.Resize((int)Mesh.ArrayType.Max);
        arr[(int)Mesh.ArrayType.Vertex] = verts.ToArray();
        arr[(int)Mesh.ArrayType.Normal] = normals.ToArray();
        arr[(int)Mesh.ArrayType.Index]  = indices.ToArray();

        marching_cube_mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arr);
        this.Mesh = marching_cube_mesh;
        return(true);
    }
Ejemplo n.º 12
0
    private RawChunk Meshing(Chunk chunk, RawChunk rawChunk, ArrayPool <Position> pool)
    {
        Position[]           values = MeshingUtils.NaiveGreedyMeshing(chunk, pool);
        Queue <Position>[][] stacks = new Queue <Position> [6][];
        int[] size = new int[chunk.Materials - 1];

        for (int side = 0; side < 6; side++)
        {
            stacks[side] = new Queue <Position> [chunk.Materials - 1];
            for (int t = 0; t < chunk.Materials - 1; t++)
            {
                stacks[side][t] = new Queue <Position> (Constants.CHUNK_SIZE3D);
            }

            MeshingUtils.GreedyMeshing(values, side, stacks[side]);
            for (int t = 0; t < chunk.Materials - 1; t++)
            {
                size[t] += stacks[side][t].Count;
            }
        }

        pool.Return(values);

        for (int t = 0; t < chunk.Materials - 1; t++)
        {
            SpatialMaterial material      = reg.SelectByID(t + 1).material;
            Vector3[]       vertice       = new Vector3[size[t]];
            int[]           indices       = new int[size[t] + (size[t] / 2)];
            Vector3[]       normals       = new Vector3[size[t]];
            Vector2[]       uvs           = new Vector2[size[t]];
            float           textureWidth  = 2048f / material.AlbedoTexture.GetWidth();
            float           textureHeight = 2048f / material.AlbedoTexture.GetHeight();

            if (size[t] > 0)
            {
                int index = 0;
                int i     = 0;
                for (int side = 0; side < 6; side++)
                {
                    for (; i < size[t]; i += 4)
                    {
                        if (stacks[side][t].Count > 0)
                        {
                            indices[index]     = i;
                            indices[index + 1] = i + 1;
                            indices[index + 2] = i + 2;
                            indices[index + 3] = i + 2;
                            indices[index + 4] = i + 3;
                            indices[index + 5] = i;
                            index += 6;

                            for (int s = 0; s < 4; s++)
                            {
                                Position position = stacks[side][t].Dequeue();

                                Vector3 vector = new Vector3();
                                vector.x       = position.x * Constants.VOXEL_SIZE;
                                vector.y       = position.y * Constants.VOXEL_SIZE;
                                vector.z       = position.z * Constants.VOXEL_SIZE;
                                vertice[i + s] = vector;

                                Vector2 uv     = new Vector2();
                                Vector3 normal = new Vector3();
                                switch (side)
                                {
                                case 0:
                                    //Front
                                    normal.x       = 0f;
                                    normal.y       = 0f;
                                    normal.z       = -1f;
                                    normals[i + s] = normal;

                                    uv.x       = vector.x * textureWidth;
                                    uv.y       = vector.y * textureHeight;
                                    uvs[i + s] = uv;
                                    break;

                                case 1:
                                    //Back
                                    normal.x       = 0f;
                                    normal.y       = 0f;
                                    normal.z       = 1f;
                                    normals[i + s] = normal;

                                    uv.x       = vector.x * textureWidth;
                                    uv.y       = vector.y * textureHeight;
                                    uvs[i + s] = uv;

                                    break;

                                case 2:
                                    //Right
                                    normal.x       = -1f;
                                    normal.y       = 0f;
                                    normal.z       = 0f;
                                    normals[i + s] = normal;

                                    uv.x       = vector.z * textureWidth;
                                    uv.y       = vector.y * textureHeight;
                                    uvs[i + s] = uv;
                                    break;

                                case 3:
                                    //Left
                                    normal.x       = 1f;
                                    normal.y       = 0f;
                                    normal.z       = 0f;
                                    normals[i + s] = normal;

                                    uv.x       = vector.z * textureWidth;
                                    uv.y       = vector.y * textureHeight;
                                    uvs[i + s] = uv;
                                    break;

                                case 4:
                                    //Top
                                    normal.x       = 0f;
                                    normal.y       = 1f;
                                    normal.z       = 0f;
                                    normals[i + s] = normal;

                                    uv.x       = vector.x * textureWidth;
                                    uv.y       = vector.z * textureHeight;
                                    uvs[i + s] = uv;
                                    break;

                                case 5:
                                    //Bottom
                                    normal.x       = 0f;
                                    normal.y       = 0f;
                                    normal.z       = 0f;
                                    normals[i + s] = normal;

                                    uv.x       = vector.x * textureWidth;
                                    uv.y       = vector.z * textureHeight;
                                    uvs[i + s] = uv;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            Godot.Collections.Array godotArray = new Godot.Collections.Array();
            if (vertice.Length > 0)
            {
                godotArray.Resize(9);

                godotArray[0] = vertice;
                godotArray[1] = normals;
                godotArray[4] = uvs;
                godotArray[8] = indices;
            }
            rawChunk.arrays[t]    = godotArray;
            rawChunk.materials[t] = material;
        }
        return(rawChunk);
    }
Ejemplo n.º 13
0
    public RawChunk FastGodotCube(Chunk chunk, RawChunk rawChunk)
    {
        Godot.Collections.Array godotArray = new Godot.Collections.Array();
        godotArray.Resize(9);
        rawChunk.arrays        = new Godot.Collections.Array[1];
        rawChunk.materials     = new SpatialMaterial[1];
        rawChunk.colliderFaces = new Vector3[1][];

        int objectID = chunk.Voxels[0].value;

        SpatialMaterial material = reg.SelectByID(objectID).material;

        float textureWidth  = 2048f / material.AlbedoTexture.GetWidth();
        float textureHeight = 2048f / material.AlbedoTexture.GetHeight();

        Vector3[] vertice = new Vector3[24];
        Vector3[] normals = new Vector3[24];
        Vector2[] uvs     = new Vector2[24];

        //FRONT
        vertice[0] = new Vector3(0, 0, 0);
        vertice[1] = new Vector3(Constants.CHUNK_LENGHT, 0, 0);
        vertice[2] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, 0);
        vertice[3] = new Vector3(0, Constants.CHUNK_LENGHT, 0);

        for (int i = 0; i < 4; i++)
        {
            normals[i] = new Vector3(0, 0, -1);
            uvs[i].x   = vertice[i].x * textureWidth;
            uvs[i].y   = vertice[i].y * textureHeight;
        }

        //BACK
        vertice[4] = new Vector3(Constants.CHUNK_LENGHT, 0, Constants.CHUNK_LENGHT);
        vertice[5] = new Vector3(0, 0, Constants.CHUNK_LENGHT);
        vertice[6] = new Vector3(0, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT);
        vertice[7] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT);

        for (int i = 4; i < 8; i++)
        {
            normals[i] = new Vector3(0, 0, 1);
            uvs[i].x   = vertice[i].x * textureWidth;
            uvs[i].y   = vertice[i].y * textureHeight;
        }

        //LEFT
        vertice[8]  = new Vector3(0, 0, Constants.CHUNK_LENGHT);
        vertice[9]  = new Vector3(0, 0, 0);
        vertice[10] = new Vector3(0, Constants.CHUNK_LENGHT, 0);
        vertice[11] = new Vector3(0, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT);

        for (int i = 8; i < 12; i++)
        {
            normals[i] = new Vector3(1, 0, 0);
            uvs[i].x   = vertice[i].z * textureWidth;
            uvs[i].y   = vertice[i].y * textureHeight;
        }

        //RIGHT
        vertice[12] = new Vector3(Constants.CHUNK_LENGHT, 0, 0);
        vertice[13] = new Vector3(Constants.CHUNK_LENGHT, 0, Constants.CHUNK_LENGHT);
        vertice[14] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT);
        vertice[15] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, 0);

        for (int i = 12; i < 16; i++)
        {
            normals[i] = new Vector3(-1, 0, 0);
            uvs[i].x   = vertice[i].z * textureWidth;
            uvs[i].y   = vertice[i].y * textureHeight;
        }

        // TOP
        vertice[16] = new Vector3(0, Constants.CHUNK_LENGHT, 0);
        vertice[17] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, 0);
        vertice[18] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT);
        vertice[19] = new Vector3(0, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT);

        for (int i = 16; i < 20; i++)
        {
            normals[i] = new Vector3(0, 1, 0);
            uvs[i].x   = vertice[i].x * textureWidth;
            uvs[i].y   = vertice[i].z * textureHeight;
        }

        //BOTTOM
        vertice[20] = new Vector3(0, 0, Constants.CHUNK_LENGHT);
        vertice[21] = new Vector3(Constants.CHUNK_LENGHT, 0, Constants.CHUNK_LENGHT);
        vertice[22] = new Vector3(Constants.CHUNK_LENGHT, 0, 0);
        vertice[23] = new Vector3(0, 0, 0);

        for (int i = 20; i < 24; i++)
        {
            normals[i] = new Vector3(0, -1, 0);
            uvs[i].x   = vertice[i].x * textureWidth;
            uvs[i].y   = vertice[i].z * textureHeight;
        }

        godotArray[0] = vertice;
        godotArray[1] = normals;
        godotArray[4] = uvs;
        int index = 0;

        int[] indice = new int[36];

        for (int i = 0; i < 36; i += 6)
        {
            indice[i]     = index;
            indice[i + 1] = index + 1;
            indice[i + 2] = index + 2;
            indice[i + 3] = index + 2;
            indice[i + 4] = index + 3;
            indice[i + 5] = index;

            index += 4;
        }

        godotArray[8] = indice;

        rawChunk.arrays[0]        = godotArray;
        rawChunk.materials[0]     = material;
        rawChunk.colliderFaces[0] = vertice;

        return(rawChunk);
    }
Ejemplo n.º 14
0
    static void BuildSection(File file, int xPos, int yPos, float heightScale, Vector2 textureScale, ref ArrayMesh mesh)
    {
        var vertices = new Vector3[VERTEX_CHUNK * VERTEX_CHUNK];
        var normals  = new Vector3[VERTEX_CHUNK * VERTEX_CHUNK];
        var uv       = new Vector2[VERTEX_CHUNK * VERTEX_CHUNK];
        var cutout   = new bool[VERTEX_CHUNK * VERTEX_CHUNK];
        var colour   = new Color[VERTEX_CHUNK * VERTEX_CHUNK];      //I'm using the colour info for texture mix info.

        for (int sz = 0; sz < VERTEX_CHUNK; sz++)
        {
            for (int sx = 0; sx < VERTEX_CHUNK; sx++)
            {
                var index = sz * VERTEX_CHUNK + sx;
                vertices[index] = new Vector3(
                    xPos + sx - CHUNK_WIDTH * NUM_CHUNKS / 2,
                    file.Get16() * heightScale,
                    yPos + sz - CHUNK_WIDTH * NUM_CHUNKS / 2);
                normals[index] = new Vector3((sbyte)file.Get8(), (sbyte)file.Get8(), (sbyte)file.Get8()).Normalized();
                uv[index]      = new Vector2(
                    (float)(xPos + sx) / CHUNK_WIDTH,
                    (float)(yPos + sz) / CHUNK_WIDTH)
                                 * textureScale;

                cutout[index] = (file.Get8() & 0b10000000) == 0b10000000;

                var mixRatios = file.Get16();
                colour[index] = new Color(
                    MixRatioHelper(mixRatios, 0x000f),
                    MixRatioHelper(mixRatios, 0x00f0),
                    MixRatioHelper(mixRatios, 0x0f00),
                    MixRatioHelper(mixRatios, 0xf000)
                    );
            }
        }

        var indices = new int[CHUNK_WIDTH * CHUNK_WIDTH * 6];

        for (var z = 0; z < CHUNK_WIDTH; z++)
        {
            for (var x = 0; x < CHUNK_WIDTH; x++)
            {
                var index       = (z * CHUNK_WIDTH + x) * 6;
                var base_vertex = (z * VERTEX_CHUNK + x);

                if (!cutout[base_vertex + 1 + VERTEX_CHUNK])
                {
                    if (z % 2 == 0)
                    {
                        indices[index]     = base_vertex;
                        indices[index + 1] = base_vertex + 1;
                        indices[index + 2] = base_vertex + VERTEX_CHUNK;
                        indices[index + 3] = base_vertex + VERTEX_CHUNK;
                        indices[index + 4] = base_vertex + 1;
                        indices[index + 5] = base_vertex + 1 + VERTEX_CHUNK;
                    }
                    else
                    {
                        indices[index]     = base_vertex;
                        indices[index + 1] = base_vertex + 1;
                        indices[index + 2] = base_vertex + 1 + VERTEX_CHUNK;
                        indices[index + 3] = base_vertex;
                        indices[index + 4] = base_vertex + 1 + VERTEX_CHUNK;
                        indices[index + 5] = base_vertex + VERTEX_CHUNK;
                    }
                }
            }
        }

        var array = new Godot.Collections.Array();

        array.Resize((int)ArrayMesh.ArrayType.Max);
        array[(int)ArrayMesh.ArrayType.Vertex] = vertices;
        array[(int)ArrayMesh.ArrayType.Normal] = normals;
        array[(int)ArrayMesh.ArrayType.Color]  = colour;
        array[(int)ArrayMesh.ArrayType.TexUv]  = uv;
        array[(int)ArrayMesh.ArrayType.Index]  = indices;
        mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, array);
    }