Ejemplo n.º 1
0
        /// <summary>
        /// Populates this chunk's terrain data.
        /// </summary>
        private void PopulateTerrain()
        {
            Profiler.Start( "Chunk Population" );

            lock ( _data )
            {
                var terrain = Terrain.Instance;
                terrain.SetCurrentChunk( this );

                // go through for each terrain block
                for ( int x = 0; x < ChunkData.SizeXZ; ++x )
                {
                    for ( int z = 0; z < ChunkData.SizeXZ; ++z )
                    {
                        var lightingLevel = Block.MaximumLighting;

                        for ( int y = ChunkData.SizeY - 1; y >= 0; --y )
                        {
                            var isAboveEmpty = ( terrain.Query( x, y + 1, z ) == BlockType.Air );

                            // ensure we need to create face data for this block
                            _data[ x, y, z ] = new Block( terrain.Query( x, y, z ), this, lightingLevel );
                            var block = _data[ x, y, z ];
                            if ( block.TypeInfo.IsEmpty )
                            {
                                continue;
                            }

                            // if the block's type is dirt and there's nothing on top, then the block should be grass
                            if ( block.Type == BlockType.Dirt && isAboveEmpty )
                            {
                                _data[ x, y, z ] = new Block( BlockType.Grass, this, lightingLevel );
                                block = _data[ x, y, z ];
                            }

                            lightingLevel = Block.MinimumLighting;
                        }
                    }
                }

                // build the voxel buffer
                BuildVoxelBufferNoLockData( false );
            }

            Profiler.Stop( "Chunk Population" );
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Builds the voxel buffer without locking the chunk data.
        /// </summary>
        /// <param name="needToSetCurrentChunk">True if we need to set this chunk as the current chunk for the terrain, false if not.</param>
        private void BuildVoxelBufferNoLockData( bool needToSetCurrentChunk )
        {
            Profiler.Start( "Voxel Buffer Building" );

            lock ( _chunkBuilder )
            {
                _chunkBuilder.Reset();

                // get the terrain
                var terrain = Terrain.Instance;
                if ( needToSetCurrentChunk )
                {
                    terrain.SetCurrentChunk( this );
                }

                // go through for each terrain block
                var temp = new Block();
                var tempBounds = new BoundingBox();
                var blockCenter = new Vector3();
                var useSmoothLighting = Game.Instance.Settings.SmoothLighting;
                for ( int x = 0; x < ChunkData.SizeXZ; ++x )
                {
                    for ( int z = 0; z < ChunkData.SizeXZ; ++z )
                    {
                        var lighting = new BlockFaceLighting( Block.MaximumLighting );

                        for ( int y = ChunkData.SizeY - 1; y >= 0; --y )
                        {
                            // get block info
                            var block = _data[ x, y, z ];
                            var exposed = false;
                            if ( block.TypeInfo.IsEmpty )
                            {
                                continue;
                            }

                            // get the block's and center
                            Position.LocalToWorld( _data.Index, x, y, z, out blockCenter );

                            // get surrounding block light level
                            // TODO : We don't need to get a lot of these if smooth lighting is disabled
                            var right            = GetLightFromBlock( terrain, x + 1, y,     z     );
                            var rightTop         = GetLightFromBlock( terrain, x + 1, y + 1, z     );
                            var rightBottom      = GetLightFromBlock( terrain, x + 1, y - 1, z     );
                            var left             = GetLightFromBlock( terrain, x - 1, y,     z     );
                            var leftTop          = GetLightFromBlock( terrain, x - 1, y + 1, z     );
                            var leftBottom       = GetLightFromBlock( terrain, x - 1, y - 1, z     );
                            var back             = GetLightFromBlock( terrain, x,     y,     z + 1 );
                            var backLeft         = GetLightFromBlock( terrain, x - 1, y,     z + 1 );
                            var backRight        = GetLightFromBlock( terrain, x + 1, y,     z + 1 );
                            var backTop          = GetLightFromBlock( terrain, x,     y + 1, z + 1 );
                            var backTopLeft      = GetLightFromBlock( terrain, x - 1, y + 1, z + 1 );
                            var backTopRight     = GetLightFromBlock( terrain, x + 1, y + 1, z + 1 );
                            var backBottom       = GetLightFromBlock( terrain, x,     y - 1, z + 1 );
                            var backBottomLeft   = GetLightFromBlock( terrain, x - 1, y - 1, z + 1 );
                            var backBottomRight  = GetLightFromBlock( terrain, x + 1, y - 1, z + 1 );
                            var front            = GetLightFromBlock( terrain, x,     y,     z - 1 );
                            var frontLeft        = GetLightFromBlock( terrain, x - 1, y,     z - 1 );
                            var frontRight       = GetLightFromBlock( terrain, x + 1, y,     z - 1 );
                            var frontTop         = GetLightFromBlock( terrain, x,     y + 1, z - 1 );
                            var frontTopLeft     = GetLightFromBlock( terrain, x - 1, y + 1, z - 1 );
                            var frontTopRight    = GetLightFromBlock( terrain, x + 1, y + 1, z - 1 );
                            var frontBottom      = GetLightFromBlock( terrain, x,     y - 1, z - 1 );
                            var frontBottomLeft  = GetLightFromBlock( terrain, x - 1, y - 1, z - 1 );
                            var frontBottomRight = GetLightFromBlock( terrain, x + 1, y - 1, z - 1 );
                            var top              = GetLightFromBlock( terrain, x,     y + 1, z     );
                            var bottom           = GetLightFromBlock( terrain, x,     y - 1, z     );

                            // check to the right
                            temp.Type = terrain.Query( x + 1, y, z );
                            if ( temp.TypeInfo.IsEmpty )
                            {
                                lighting = new BlockFaceLighting( right );

                                // calculate smooth lighting
                                if ( useSmoothLighting )
                                {
                                    lighting.LowerLeft  = 0.25f * ( right + rightBottom + frontBottomRight + frontRight );
                                    lighting.LowerRight = 0.25f * ( right + rightBottom + backBottomRight  + backRight  );
                                    lighting.UpperRight = 0.25f * ( right + rightTop    + backTopRight     + backRight  );
                                    lighting.UpperLeft  = 0.25f * ( right + rightTop    + frontTopRight    + frontRight );
                                }

                                _chunkBuilder.AddFaceData( blockCenter, BlockFace.Right, block.Type, lighting );
                                exposed = true;
                            }

                            // check to the left
                            temp.Type = terrain.Query( x - 1, y, z );
                            if ( temp.TypeInfo.IsEmpty )
                            {
                                lighting = new BlockFaceLighting( left );

                                // calculate smooth lighting
                                if ( useSmoothLighting )
                                {
                                    lighting.LowerLeft  = 0.25f * ( left + leftBottom + backBottomLeft  + backLeft  );
                                    lighting.LowerRight = 0.25f * ( left + leftBottom + frontBottomLeft + frontLeft );
                                    lighting.UpperRight = 0.25f * ( left + leftTop    + frontTopLeft    + frontLeft );
                                    lighting.UpperLeft  = 0.25f * ( left + leftTop    + backTopLeft     + backLeft  );
                                }

                                _chunkBuilder.AddFaceData( blockCenter, BlockFace.Left, block.Type, lighting );
                                exposed = true;
                            }

                            // check in back
                            temp.Type = terrain.Query( x, y, z + 1 );
                            if ( temp.TypeInfo.IsEmpty )
                            {
                                lighting = new BlockFaceLighting( back );

                                // calculate smooth lighting
                                if ( useSmoothLighting )
                                {
                                    lighting.LowerLeft  = 0.25f * ( back + backBottom + backBottomRight + backRight );
                                    lighting.LowerRight = 0.25f * ( back + backBottom + backBottomLeft  + backLeft  );
                                    lighting.UpperRight = 0.25f * ( back + backTop    + backTopLeft     + backLeft  );
                                    lighting.UpperLeft  = 0.25f * ( back + backTop    + backTopRight    + backRight );
                                }

                                _chunkBuilder.AddFaceData( blockCenter, BlockFace.Back, block.Type, lighting );
                                exposed = true;
                            }

                            // check in front
                            temp.Type = terrain.Query( x, y, z - 1 );
                            if ( temp.TypeInfo.IsEmpty )
                            {
                                lighting = new BlockFaceLighting( front );

                                // calculate smooth lighting
                                if ( useSmoothLighting )
                                {
                                    lighting.LowerLeft  = 0.25f * ( front + frontBottom + frontBottomLeft  + frontLeft  );
                                    lighting.LowerRight = 0.25f * ( front + frontBottom + frontBottomRight + frontRight );
                                    lighting.UpperRight = 0.25f * ( front + frontTop    + frontTopRight    + frontRight );
                                    lighting.UpperLeft  = 0.25f * ( front + frontTop    + frontTopLeft     + frontLeft  );
                                }

                                _chunkBuilder.AddFaceData( blockCenter, BlockFace.Front, block.Type, lighting );
                                exposed = true;
                            }

                            // check above
                            temp.Type = terrain.Query( x, y + 1, z );
                            if ( temp.TypeInfo.IsEmpty )
                            {
                                lighting = new BlockFaceLighting( top );

                                // calculate smooth lighting
                                if ( useSmoothLighting )
                                {
                                    lighting.LowerLeft  = 0.25f * ( top + frontTop + frontTopLeft  + leftTop  );
                                    lighting.LowerRight = 0.25f * ( top + frontTop + frontTopRight + rightTop );
                                    lighting.UpperRight = 0.25f * ( top + backTop  + backTopRight  + rightTop );
                                    lighting.UpperLeft  = 0.25f * ( top + backTop  + backTopLeft   + leftTop  );
                                }

                                _chunkBuilder.AddFaceData( blockCenter, BlockFace.Top, block.Type, lighting );
                                exposed = true;
                            }

                            // check below
                            temp.Type = terrain.Query( x, y - 1, z );
                            if ( temp.TypeInfo.IsEmpty )
                            {
                                lighting = new BlockFaceLighting( bottom );

                                // calculate smooth lighting
                                if ( useSmoothLighting )
                                {
                                    lighting.LowerLeft  = 0.25f * ( bottom + backBottom  + backBottomLeft   + leftBottom  );
                                    lighting.LowerRight = 0.25f * ( bottom + backBottom  + backBottomRight  + rightBottom );
                                    lighting.UpperRight = 0.25f * ( bottom + frontBottom + frontBottomRight + rightBottom );
                                    lighting.UpperLeft  = 0.25f * ( bottom + frontBottom + frontBottomLeft  + leftBottom  );
                                }

                                _chunkBuilder.AddFaceData( blockCenter, BlockFace.Bottom, block.Type, lighting );
                                exposed = true;
                            }

                            // add the block's bounds to the octree if it's exposed
                            if ( exposed )
                            {
                                CreateBlockBounds( x, y, z, ref tempBounds );
                                _octree.Add( tempBounds );
                            }
                        }
                    }
                }

                // now build the terrain
                lock ( _terrain )
                {
                    _chunkBuilder.PopulateBuffer( _terrain );
                }
            }

            Profiler.Stop( "Voxel Buffer Building" );
        }