示例#1
0
 /// <summary>
 /// This is highly dependent on TerrainChunk internal details. (See "GetDirectionsToLook" method.)
 /// A TerrainChunk stores some blocks of adjacent chunks in order to simplify mesh generation.
 /// Therefore, when we change a block type, we have to update the block type in adjacent chunks as well.
 /// This method gathers the adjacent chunks that need to be updated.
 /// </summary>
 private IEnumerable <TerrainChunk> GetAdjacentChunksThatShareBlock(TerrainChunk chunk, Index3D blockLocalIndex)
 {
     foreach (var d in GetDirectionsToLook(chunk, blockLocalIndex))
     {
         yield return(chunkGenerator.GetOrGenerateEmpty(chunk.Index.Step(d), chunksParent));
     }
 }
示例#2
0
 private void SetTypeOfSameBlockInAdjacentChunks(TerrainChunk chunk, Index3D blockLocalIndex, Vector3 pointOnTerrainMesh, TerrainBlock.Type blockNewType)
 {
     foreach (var adjacentChunk in GetAdjacentChunksThatShareBlock(chunk, blockLocalIndex))
     {
         SetBlockTypeAt(adjacentChunk, adjacentChunk.GetBlockLocalIndexAt(pointOnTerrainMesh), blockNewType);
     }
 }
            public Mesh BuildMesh(TerrainChunk chunk)
            {
                chunk.ForEachGroundBlock(block =>
                {
                    if (block.LocalIndex.Y < config.WaterLevelInBlocks)
                    {
                        var x = block.LocalIndex.X * config.BlockSize - config.HalfBlockSize;
                        var z = block.LocalIndex.Z * config.BlockSize - config.HalfBlockSize;

                        triangles.Add(vertices.Count);
                        triangles.Add(vertices.Count + 1);
                        triangles.Add(vertices.Count + 2);
                        triangles.Add(vertices.Count);
                        triangles.Add(vertices.Count + 2);
                        triangles.Add(vertices.Count + 3);

                        vertices.Add(new Vector3(x, 0, z));
                        vertices.Add(new Vector3(x, 0, z + config.BlockSize));
                        vertices.Add(new Vector3(x + config.BlockSize, 0, z + config.BlockSize));
                        vertices.Add(new Vector3(x + config.BlockSize, 0, z));

                        uvs.AddRange(new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0) });
                    }
                });

                return(BuildMesh());
            }
        public TerrainTreesGenerator(TerrainConfig config, TerrainChunk chunk)
        {
            this.config = config;
            this.chunk  = chunk;

            rand = new System.Random(chunk.Index.X * 10000 + chunk.Index.Z);
        }
示例#5
0
        private TerrainBlock.Type SetBlockTypeAt(TerrainChunk chunk, Index3D blockLocalIndex, TerrainBlock.Type blockNewType)
        {
            var blockType = chunk.GetBlock(blockLocalIndex).BlockType;

            chunk.SetBlockType(blockLocalIndex, blockNewType);
            chunkGenerator.BuildMeshFor(chunk);
            return(blockType);
        }
示例#6
0
        private TerrainBlock GetBlockAt(Vector3 pointInWorld, out TerrainChunk chunk)
        {
            var chunkIndex = config.GetChunkIndexAt(pointInWorld);

            chunk = chunkGenerator.GetOrGenerateEmpty(chunkIndex, chunksParent);
            var blockLocalIndex = chunk.GetBlockLocalIndexAt(pointInWorld);

            return(chunk.GetBlock(blockLocalIndex));
        }
示例#7
0
 public void GenerateEmptyBlocksFor(TerrainChunk chunk, float blocksSize)
 {
     chunk.ForEachBlockIndex(
         (localIndex, globalIndex) =>
     {
         var block = new TerrainBlock(TerrainBlock.Type.None, localIndex, globalIndex, blocksSize);
         chunk.SetBlock(localIndex, block);
     }
         );
 }
示例#8
0
        public void GenerateBlocksFor(TerrainChunk chunk, float blocksSize)
        {
            chunk.ForEachBlockIndex(
                (localIndex, globalIndex) =>
            {
                var blockType = CalculateBlockType(globalIndex);
                var block     = new TerrainBlock(blockType, localIndex, globalIndex, blocksSize);
                chunk.SetBlock(localIndex, block);
            }
                );

            new TerrainTreesGenerator(config, chunk).Generate(noise);
        }
示例#9
0
        public Mesh BuildMesh(TerrainChunk chunk)
        {
            chunk.ForEachNonEmptyVisibleBlock(block =>
            {
                var blockLocalIndex = block.LocalIndex;

                var blockMinVertex = new Vector3(
                    blockLocalIndex.X * config.BlockSize - config.HalfBlockSize,
                    blockLocalIndex.Y * config.BlockSize - config.HalfBlockSize,
                    blockLocalIndex.Z * config.BlockSize - config.HalfBlockSize
                    );

                var blockUVs = TerrainBlockUVs.Create(block.BlockType);

                if (chunk.IsBlockEmpty(blockLocalIndex.StepUp()))
                {
                    AddBlockFace_up(blockMinVertex, blockUVs);
                }

                if (chunk.IsBlockEmpty(blockLocalIndex.StepDown()))
                {
                    AddBlockFace_down(blockMinVertex, blockUVs);
                }

                if (chunk.IsBlockEmpty(blockLocalIndex.StepForward()))
                {
                    AddBlockFace_forward(blockMinVertex, blockUVs);
                }

                if (chunk.IsBlockEmpty(blockLocalIndex.StepRight()))
                {
                    AddBlockFace_right(blockMinVertex, blockUVs);
                }

                if (chunk.IsBlockEmpty(blockLocalIndex.StepBack()))
                {
                    AddBlockFace_back(blockMinVertex, blockUVs);
                }

                if (chunk.IsBlockEmpty(blockLocalIndex.StepLeft()))
                {
                    AddBlockFace_left(blockMinVertex, blockUVs);
                }
            });

            return(BuildMesh());
        }
示例#10
0
        private IEnumerable <Vector3> GetDirectionsToLook(TerrainChunk chunk, Index3D blockLocalIndex)
        {
            var directionsToUpdate = new List <Vector3>();

            if (blockLocalIndex.X <= chunk.MinBlockIndex.X)
            {
                directionsToUpdate.Add(Vector3.left);
            }
            else if (blockLocalIndex.X >= chunk.MaxBlockIndex.X)
            {
                directionsToUpdate.Add(Vector3.right);
            }

            if (blockLocalIndex.Y <= chunk.MinBlockIndex.Y)
            {
                directionsToUpdate.Add(Vector3.down);
            }
            else if (blockLocalIndex.Y >= chunk.MaxBlockIndex.Y)
            {
                directionsToUpdate.Add(Vector3.up);
            }

            if (blockLocalIndex.Z <= chunk.MinBlockIndex.Z)
            {
                directionsToUpdate.Add(Vector3.back);
            }
            else if (blockLocalIndex.Z >= chunk.MaxBlockIndex.Z)
            {
                directionsToUpdate.Add(Vector3.forward);
            }

            var numberOfDirections = directionsToUpdate.Count;

            for (var i = 0; i < Mathf.CeilToInt(numberOfDirections / 2.0f); ++i)
            {
                for (var j = i + 1; j < numberOfDirections; ++j)
                {
                    directionsToUpdate.Add(directionsToUpdate[i] + directionsToUpdate[j]);
                }
            }

            return(directionsToUpdate);
        }
        public void BuildMeshFor(TerrainChunk chunk)
        {
            var meshBuilder = new TerrainChunkMeshBuilder(config);
            var mesh        = meshBuilder.BuildMesh(chunk);

            var chunkObject = chunk.gameObject;

            chunkObject.GetComponent <MeshFilter>().mesh         = mesh;
            chunkObject.GetComponent <MeshCollider>().sharedMesh = mesh;

            chunkObject.transform.position = chunk.FirstVisibleBlockGlobalIndex.AsVector3() * config.BlockSize;

            if (chunk.Index.Y == 0) // generates water only for chunks at the ground level
            {
                var waterMesh = new WaterMeshBuilder(config).BuildMesh(chunk);

                if (waterMesh != null)
                {
                    var waterObject = chunkObject.transform.GetChild(0);
                    waterObject.transform.localPosition          = new Vector3(0, config.WaterLevelInBlocks * config.BlockSize - config.HalfBlockSize * 1.3f, 0);
                    waterObject.GetComponent <MeshFilter>().mesh = waterMesh;
                }
            }
        }