Пример #1
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);
    }
Пример #2
0
    private static void CreateBlock(Vector3 position, SubChunk chunk)
    {
        // subChunk index in the Chunk itself. [0, 15]
        int subChunkId = chunk.SubChunkId;

        // Position as integer.
        int x = (int)position.x;
        int y = (int)position.y;
        int z = (int)position.z;


        // False if there is a block next to those faces.
        bool left, right, top, bottom, front, back;

        top    = y != 15 ? chunk.GetBlock(x, y + 1, z) == -1 : true;
        bottom = y != 0  ? chunk.GetBlock(x, y - 1, z) == -1 : true;
        left   = x != 0  ? chunk.GetBlock(x - 1, y, z) == -1 : true;
        right  = x != 15 ? chunk.GetBlock(x + 1, y, z) == -1 : true;
        front  = z != 15 ? chunk.GetBlock(x, y, z + 1) == -1 : true;
        back   = z != 0  ? chunk.GetBlock(x, y, z - 1) == -1 : true;

        // If the block is completly surrounded(not seen).
        if (left && right && top && bottom && front && back)
        {
            return;
        }

        // Should draw faces? except chunk borders.
        bool leftChunk  = true;
        bool rightChunk = true;
        bool backChunk  = true;
        bool frontChunk = true;

        if (x == 0)
        {
            leftChunk = chunk.Chunk.ChunkLeft.GetSubChunk(subChunkId).GetBlock(15, y, z) == -1;
        }
        if (x == 15)
        {
            rightChunk = chunk.Chunk.ChunkRight.GetSubChunk(subChunkId).GetBlock(0, y, z) == -1;
        }
        if (z == 0)
        {
            backChunk = chunk.Chunk.ChunkBack.GetSubChunk(subChunkId).GetBlock(x, y, 15) == -1;
        }
        if (z == 15)
        {
            frontChunk = chunk.Chunk.ChunkFront.GetSubChunk(subChunkId).GetBlock(x, y, 0) == -1;
        }

        // Check if there is a block in the above subchunk.
        // Dont check if the subchunk is the bottom or top one.
        bool topChunk    = true;
        bool bottomChunk = true;

        if (subChunkId != 15)
        {
            SubChunk topSubChunk = chunk.Chunk.GetSubChunk(subChunkId + 1);
            if (topSubChunk.isFull())
            {
                topChunk = true;
            }
            else
            {
                topChunk = topSubChunk.GetBlock(x, 0, z) == -1;
            }
        }
        if (subChunkId != 0)
        {
            SubChunk botSubChunk = chunk.Chunk.GetSubChunk(subChunkId - 1);
            if (botSubChunk.isFull())
            {
                bottomChunk = false;
            }
            else
            {
                bottomChunk = botSubChunk.GetBlock(x, 15, z) == -1;
            }
        }

        // False if should not render chunk border faces.
        bool topBorder    = y == 15 ? chunk.RenderTop && topChunk    : top;
        bool bottomBorder = y == 0  ? chunk.RenderBottom && bottomChunk : bottom;
        bool leftBorder   = x == 0  ? chunk.RenderLeft && leftChunk   : left;
        bool rightBorder  = x == 15 ? chunk.RenderRight && rightChunk  : right;
        bool frontBorder  = z == 15 ? chunk.RenderFront && frontChunk  : front;
        bool backBorder   = z == 0  ? chunk.RenderBack && backChunk   : back;

        // Display the chunk in green if chunk is surrounded.
        int gx = (int)(chunk.Chunk.Position.x * 16) + x;
        int gz = (int)(chunk.Chunk.Position.y * 16) + z;

        CurrentColor = BlockPalette.GetColor((BLOCK_TYPE)chunk.GetBlock(x, y, z), gx, gz);

        // Represent each faces of a cube and if it should place
        // each faces. Placed in the same order in CUBE_FACES enum.
        bool[] lutFaces =
        {
            topBorder,   bottomBorder,
            leftBorder,  rightBorder,
            frontBorder, backBorder
        };

        for (int i = 0; i < 6; i++)
        {
            if (lutFaces[i] == true)
            {
                CreateFace(i, position);
            }
        }
    }