Example #1
0
 public GeneratedChunk(Chunk chunk, ThreeDimensionalBlockArray blocks, Vector3[] vertices, Vector2[] uvs, int[] triangles)
 {
     this.chunk     = chunk;
     this.blocks    = blocks;
     this.vertices  = vertices;
     this.uvs       = uvs;
     this.triangles = triangles;
 }
Example #2
0
    void GenerateMeshThreaded(ThreeDimensionalBlockArray Blocks, Chunk chunk)
    {
        var refreshed = GenerateMesh(Blocks, chunk);

        refreshed.ApplyBlocks = false;

        generatedChunks.Enqueue(refreshed);
    }
Example #3
0
    int GetHeight(ThreeDimensionalBlockArray Blocks, int x, int z)
    {
        for (int y = (int)size.y - 1; y >= 0; y--)
        {
            if (Blocks[x, y, z].BlockID != BlockType.Air)
            {
                return(y);
            }
        }

        return(0);
    }
Example #4
0
    bool BlockExists(int x, int y, int z, BlockFace blockFace, ThreeDimensionalBlockArray currentBlocks, ThreeDimensionalBlockArray neighourBlocks)
    {
        if (neighourBlocks != null)
        {
            //Debug.Log("Neighbour is not null");
            // if at the edge of the array, we need to check neighbours
            if (x == 0 || x >= ((int)Chunk.ChunkSize.x - 1) || z == 0 || z >= ((int)Chunk.ChunkSize.z - 1))
            {
                switch (blockFace)
                {
                case BlockFace.Top:
                case BlockFace.Bottom:
                    break;

                case BlockFace.Left:
                    if (x != 0)
                    {
                        break;
                    }

                    return(neighourBlocks.BlockExists((int)Chunk.ChunkSize.x, y, z));

                case BlockFace.Right:
                    if (x != (int)Chunk.ChunkSize.x - 1)
                    {
                        break;
                    }

                    return(neighourBlocks.BlockExists(0, y, z));

                case BlockFace.Forward:
                    if (z != (int)Chunk.ChunkSize.z - 1)
                    {
                        break;
                    }

                    return(neighourBlocks.BlockExists(x, y, 0));

                case BlockFace.Back:
                    if (z != 0)
                    {
                        break;
                    }

                    return(neighourBlocks.BlockExists(x, y, (int)Chunk.ChunkSize.z - 1));
                }
            }
        }
        return(currentBlocks.BlockExists(x, y, z, blockFace));
    }
Example #5
0
 void FillArea(ThreeDimensionalBlockArray Blocks, int xStart, int yStart, int zStart, int xEnd, int yEnd, int zEnd, BlockType blockType)
 {
     for (int y = yStart; y <= yEnd; y++)
     {
         for (int x = xStart; x <= xEnd; x++)
         {
             for (int z = zStart; z <= zEnd; z++)
             {
                 if (Blocks.ElementExists(x, y, z))
                 {
                     Block block = Blocks.Get(x, y, z);
                     if (block.BlockID == BlockType.Air)
                     {
                         block.BlockID = blockType;
                     }
                 }
             }
         }
     }
 }
Example #6
0
    void GenerateTree(ThreeDimensionalBlockArray Blocks, Vector3 pos, TreeType treeType, System.Random random)
    {
        //System.Random random = new System.Random();

        int yStart = (int)pos.y + 1;
        int yEnd   = yStart + random.Next(3, 7);
        int y      = yStart;

        for (; y < yEnd; y++)
        {
            Blocks[(int)pos.x, y, (int)pos.z].BlockID = BlockType.OakLog;
        }
        Blocks[(int)pos.x, y, (int)pos.z].BlockID = BlockType.OakLeaf;

        // one leaf forward, back, left and right from the top leaf
        Vector3 current = new Vector3(pos.x, y, pos.z);
        Vector3 forward, back, left, right;

        forward = current + Vector3.forward;
        back    = current + Vector3.back;
        left    = current + Vector3.left;
        right   = current + Vector3.right;

        if (Blocks.ElementExists(forward))
        {
            if (Blocks.Get(forward).BlockID == BlockType.Air)
            {
                Blocks.Get(forward).BlockID = BlockType.OakLeaf;
            }
        }
        if (Blocks.ElementExists(back))
        {
            if (Blocks.Get(back).BlockID == BlockType.Air)
            {
                Blocks.Get(back).BlockID = BlockType.OakLeaf;
            }
        }
        if (Blocks.ElementExists(left))
        {
            if (Blocks.Get(left).BlockID == BlockType.Air)
            {
                Blocks.Get(left).BlockID = BlockType.OakLeaf;
            }
        }
        if (Blocks.ElementExists(right))
        {
            if (Blocks.Get(right).BlockID == BlockType.Air)
            {
                Blocks.Get(right).BlockID = BlockType.OakLeaf;
            }
        }

        // one layer down, an entire ring
        current = new Vector3(pos.x, y - 1, pos.z);

        // 3x1x3 ring
        FillArea(Blocks, (int)current.x - 1, (int)current.y, (int)current.z - 1, (int)current.x + 1, (int)current.y, (int)current.z + 1, BlockType.OakLeaf);

        // 5x2x5 ring

        FillArea(Blocks, (int)current.x - 2, (int)current.y - 2, (int)current.z - 2, (int)current.x + 2, (int)current.y - 1, (int)current.z + 2, BlockType.OakLeaf);
    }
Example #7
0
    GeneratedChunk GenerateMesh(ThreeDimensionalBlockArray Blocks, Chunk chunk)
    {
        List <Vector3> vertices  = new List <Vector3>();
        List <Vector2> uvs       = new List <Vector2>();
        List <int>     triangles = new List <int>();

        int VerticesIndex;

        float blockSize = 1;

        ThreeDimensionalBlockArray leftBlocks, rightBlocks, backBlocks, frontBlocks;

        leftBlocks = rightBlocks = backBlocks = frontBlocks = null;
        ChunkIndex chunkIndex = chunk.ChunkIndex;
        ChunkIndex leftIndex, rightIndex, backIndex, frontIndex;

        leftIndex  = new ChunkIndex(chunkIndex.ChunkX - 1, chunkIndex.ChunkZ);
        rightIndex = new ChunkIndex(chunkIndex.ChunkX + 1, chunkIndex.ChunkZ);
        backIndex  = new ChunkIndex(chunkIndex.ChunkX, chunkIndex.ChunkZ - 1);
        frontIndex = new ChunkIndex(chunkIndex.ChunkX, chunkIndex.ChunkZ + 1);


        lock (Chunk.WorldChunks)
        {
            if (Chunk.WorldChunks.TryGetValue(leftIndex, out Chunk left))
            {
                leftBlocks = left.ChunkBlocks;
            }
            if (Chunk.WorldChunks.TryGetValue(rightIndex, out Chunk right))
            {
                rightBlocks = right.ChunkBlocks;
            }
            if (Chunk.WorldChunks.TryGetValue(backIndex, out Chunk back))
            {
                backBlocks = back.ChunkBlocks;
            }
            if (Chunk.WorldChunks.TryGetValue(frontIndex, out Chunk front))
            {
                frontBlocks = front.ChunkBlocks;
            }
        }

        for (int y = 0; y < size.y; y++)
        {
            for (int x = 0; x < size.x; x++)
            {
                for (int z = 0; z < size.z; z++)
                {
                    if (Blocks[x, y, z].BlockID != BlockType.Air)
                    {
                        BlockType          blockType = Blocks[x, y, z].BlockID;
                        BlockFaceDirection direction = BlockFaceDirection.Side;


                        if (!BlockExists(x, y, z, BlockFace.Top, Blocks, null))
                        {
                            direction = BlockFaceDirection.Top;

                            VerticesIndex = vertices.Count;

                            vertices.Add(new Vector3(x, y + blockSize, z));
                            vertices.Add(new Vector3(x, y + blockSize, z + blockSize));
                            vertices.Add(new Vector3(x + blockSize, y + blockSize, z + blockSize));
                            vertices.Add(new Vector3(x + blockSize, y + blockSize, z));

                            UpdateChunkUV(blockType, direction);
                        }

                        if (!BlockExists(x, y, z, BlockFace.Bottom, Blocks, null))
                        {
                            if (y == 0)
                            {
                                continue;
                            }
                            direction = BlockFaceDirection.Bottom;

                            VerticesIndex = vertices.Count;

                            vertices.Add(new Vector3(x, y, z));
                            vertices.Add(new Vector3(x + blockSize, y, z));
                            vertices.Add(new Vector3(x + blockSize, y, z + blockSize));
                            vertices.Add(new Vector3(x, y, z + blockSize));

                            UpdateChunkUV(blockType, direction);
                        }

                        if (!BlockExists(x, y, z, BlockFace.Left, Blocks, leftBlocks))
                        {
                            direction = BlockFaceDirection.Side;

                            VerticesIndex = vertices.Count;

                            vertices.Add(new Vector3(x, y, z + blockSize));
                            vertices.Add(new Vector3(x, y + blockSize, z + blockSize));
                            vertices.Add(new Vector3(x, y + blockSize, z));
                            vertices.Add(new Vector3(x, y, z));

                            UpdateChunkUV(blockType, direction);
                        }

                        if (!BlockExists(x, y, z, BlockFace.Right, Blocks, rightBlocks))
                        {
                            direction = BlockFaceDirection.Side;

                            VerticesIndex = vertices.Count;

                            vertices.Add(new Vector3(x + blockSize, y, z));
                            vertices.Add(new Vector3(x + blockSize, y + blockSize, z));
                            vertices.Add(new Vector3(x + blockSize, y + blockSize, z + blockSize));
                            vertices.Add(new Vector3(x + blockSize, y, z + blockSize));

                            UpdateChunkUV(blockType, direction);
                        }

                        if (!BlockExists(x, y, z, BlockFace.Back, Blocks, backBlocks))
                        {
                            direction = BlockFaceDirection.Side;

                            VerticesIndex = vertices.Count;

                            vertices.Add(new Vector3(x, y, z));
                            vertices.Add(new Vector3(x, y + blockSize, z));
                            vertices.Add(new Vector3(x + blockSize, y + blockSize, z));
                            vertices.Add(new Vector3(x + blockSize, y, z));

                            UpdateChunkUV(blockType, direction);
                        }

                        if (!BlockExists(x, y, z, BlockFace.Forward, Blocks, frontBlocks))
                        {
                            direction = BlockFaceDirection.Side;

                            VerticesIndex = vertices.Count;

                            vertices.Add(new Vector3(x + blockSize, y, z + blockSize));
                            vertices.Add(new Vector3(x + blockSize, y + blockSize, z + blockSize));
                            vertices.Add(new Vector3(x, y + blockSize, z + blockSize));
                            vertices.Add(new Vector3(x, y, z + blockSize));


                            UpdateChunkUV(blockType, direction);
                        }
                    }
                }
            }
        }

        return(new GeneratedChunk(chunk, Blocks, vertices.ToArray(), uvs.ToArray(), triangles.ToArray()));

        void UpdateChunkUV(BlockType blockType, BlockFaceDirection direction)
        {
            triangles.Add(VerticesIndex);
            triangles.Add(VerticesIndex + 1);
            triangles.Add(VerticesIndex + 2);

            triangles.Add(VerticesIndex + 2);
            triangles.Add(VerticesIndex + 3);
            triangles.Add(VerticesIndex);

            Vector2 textureInterval = TextureManager.TextureInterval;

            int textureIndex = 0;

            switch (direction)
            {
            case BlockFaceDirection.Top:
                textureIndex = TextureManager.TextureMap[blockType].TopIndex;
                break;

            case BlockFaceDirection.Side:
                textureIndex = TextureManager.TextureMap[blockType].SideIndex;
                break;

            case BlockFaceDirection.Bottom:
                textureIndex = TextureManager.TextureMap[blockType].BottomIndex;
                break;
            }

            Vector2 textureId = new Vector2(textureInterval.x * (textureIndex % TextureManager.AtlasSize.x), textureInterval.y * Mathf.FloorToInt(textureIndex / TextureManager.AtlasSize.y));


            uvs.Add(new Vector2(textureId.x + textureInterval.x, textureId.y - textureInterval.y));
            uvs.Add(new Vector2(textureId.x + textureInterval.x, textureId.y));
            uvs.Add(new Vector2(textureId.x, textureId.y));
            uvs.Add(new Vector2(textureId.x, textureId.y - textureInterval.y));
        }
    }
Example #8
0
    /// <summary>
    /// General method that returns a completed chunk
    /// </summary>
    /// <returns>The chunk.</returns>
    /// <param name="chunk">Chunk.</param>
    /// <param name="chunkIndex">Chunk index.</param>
    /// <param name="noiseSettings">Noise settings.</param>
    GeneratedChunk GenerateChunk(Chunk chunk, ChunkIndex chunkIndex, NoiseSettings noiseSettings, bool perlin)
    {
        // Create our blocks. This is not the mesh
        ThreeDimensionalBlockArray Blocks = new ThreeDimensionalBlockArray((int)size.x, (int)size.y, (int)size.z);

        // Heightmap
        float[,] noiseMap = null;

        if (perlin)
        {
            noiseMap = NoiseGenerator.Generate2D(chunkIndex.ChunkX, chunkIndex.ChunkZ, (int)size.x, (int)size.z, noiseSettings.Octaves, noiseSettings.Amplitude, noiseSettings.Smoothness, noiseSettings.GroundHeight, noiseSettings.Roughness);
        }
        else
        {
            noiseMap = NoiseGenerator.Generate2DSimplex(chunkIndex.ChunkX, chunkIndex.ChunkZ, (int)size.x, (int)size.z, noiseSettings.Octaves, noiseSettings.Amplitude, noiseSettings.Smoothness, noiseSettings.GroundHeight, noiseSettings.Roughness);
        }

        List <Vector3> trees = new List <Vector3>();

        // can't use unity due to threading
        System.Random random = new System.Random();

        for (int x = 0; x < size.x; x++)
        {
            for (int z = 0; z < size.z; z++)
            {
                int h = Mathf.RoundToInt(noiseMap[x, z]);
                for (int y = 0; y < size.y; y++)
                {
                    BlockType blockType = BlockType.Air;

                    if (y < h)
                    {
                        // Top block
                        if (y + 1 == h)
                        {
                            // TODO: Get top block
                            blockType = BlockType.Grass;

                            if (random.Next(0, 100 - noiseSettings.TreeFrequency) == 5)
                            {
                                trees.Add(new Vector3(x, y, z));
                            }
                            //if ((0, noiseSettings.TreeFrequency + 1) == 5)
                            //{
                            //    trees.Add(new Vector3(x, y, z));
                            //}
                        }
                        // Dirt
                        else if (y + 1 > h - 3)
                        {
                            blockType = BlockType.Dirt;
                        }
                        // Below
                        else
                        {
                            blockType = BlockType.Stone;
                        }
                    }

                    Blocks[x, y, z] = new Block(x, y, z, blockType);
                }
            }
        }

        //foreach (Vector3 pos in trees)
        //{
        //    GenerateTree(pos, TreeType.Oak);
        //}

        return(GenerateMesh(Blocks, chunk));
    }
Example #9
0
    GeneratedChunk GenerateNew(Chunk chunk, ChunkIndex chunkIndex, NoiseSettings noiseSettings)
    {
        System.Random random = new System.Random();

        ThreeDimensionalBlockArray Blocks = new ThreeDimensionalBlockArray((int)size.x, (int)size.y, (int)size.z);

        noiseSettings.SetWeights();

        // Loop through all blocks and get solid or air value
        for (int x = 0; x < size.x; x++)
        {
            for (int y = 0; y < size.y; y++)
            {
                for (int z = 0; z < size.z; z++)
                {
                    if (y == 0 || y == 1 || y == 2)
                    {
                        Blocks[x, y, z] = new Block(x, y, z, BlockType.Stone);
                        continue;
                    }

                    float groundNoise = 0;
                    float caveNoise1  = 0;
                    float caveNoise2  = 0;

                    caveNoise1  = NoiseGenerator.GetPixelRidged(chunkIndex, x, y, z, noiseSettings.CaveOne);
                    groundNoise = NoiseGenerator.GetPixel(chunk.ChunkIndex, x, y, z, noiseSettings);
                    caveNoise2  = NoiseGenerator.GetPixelRidged(chunkIndex, x, y, z, noiseSettings.CaveTwo);

                    float groundSolid = 1;
                    int   caveOpen1   = -1;
                    int   caveOpen2   = -1;

                    groundSolid = OneMinusOne(groundNoise, ChunkYGradient[y]);

                    caveOpen1 = OneZero(caveNoise1, ChunkYGradient[y]);
                    caveOpen2 = OneZero(caveNoise2, ChunkYGradient[y]);

                    bool isSolid;

                    float finalOpen = groundSolid * Flip(caveOpen1 * caveOpen2);

                    isSolid = finalOpen >= 1;

                    //isSolid = caveOpen1 >= 1;
                    Blocks[x, y, z] = new Block(x, y, z, isSolid ? BlockType.Grass : BlockType.Air);
                }
            }
        }

        // Loop through all blocks and get grass, dirt or stone value
        for (int x = 0; x < size.x; x++)
        {
            for (int z = 0; z < size.z; z++)
            {
                float topBlockHeight = -1;   // the height we first found a block at

                for (int y = (int)size.y - 1; y >= 0; y--)
                {
                    // if we found the first solid block and are not below ground
                    if (Blocks[x, y, z].BlockID != BlockType.Air)
                    {
                        if (topBlockHeight < 0)
                        {
                            topBlockHeight = y;
                        }

                        if (y < topBlockHeight && y >= topBlockHeight - 3)
                        {
                            Blocks[x, y, z].BlockID = BlockType.Dirt;
                        }
                        else if (y < topBlockHeight)
                        {
                            Blocks[x, y, z].BlockID = BlockType.Stone;
                        }
                    }
                }
            }
        }

        //List<Vector3> trees = new List<Vector3>();

        //// Loop through 4x4 grids and place trees
        //for (int x = 0; x < size.x; x += 4)
        //{
        //    for (int z = 0; z < size.z; z += 4)
        //    {
        //        // to get delta height we index the array diagonally and min max the heights
        //        // there's no point going through each block
        //        int one, two, three, four;
        //        one = GetHeight(Blocks, x, z);
        //        two = GetHeight(Blocks, x + 1, z + 1);
        //        three = GetHeight(Blocks, x + 2, z + 2);
        //        four = GetHeight(Blocks, x + 3, z + 3);

        //        int min = int.MaxValue;
        //        int max = int.MinValue;

        //        if (one > max)
        //            one = max;
        //        if (two > max)
        //            two = max;
        //        if (three > max)
        //            three = max;
        //        if (four > max)
        //            four = max;

        //        if (one < min)
        //            one = min;
        //        if (two < min)
        //            two = min;
        //        if (three < min)
        //            three = min;
        //        if (four < min)
        //            four = min;

        //        int delta = max - min;
        //        if (delta < 5)  // only do trees if the ground is relatively flat
        //        {
        //            if (random.Next(0, 100 - noiseSettings.TreeFrequency) == 5)
        //            {
        //                trees.Add(new Vector3(x, one, z));
        //            }
        //        }
        //    }
        //}

        //foreach (Vector3 vector in trees)
        //{
        //    GenerateTree(Blocks, vector, TreeType.Oak, random);
        //}


        return(GenerateMesh(Blocks, chunk));
    }
Example #10
0
 /// <summary>
 /// Sets the blocks of this chunk
 /// </summary>
 /// <param name="blocks">Blocks.</param>
 public void ApplyBlocks(ThreeDimensionalBlockArray blocks)
 {
     ChunkBlocks = blocks;
 }