public TerrainChunk(GraphicsDevice graphicsDevice, HeightProvider heightProvider, Vector2 gridCoordinates, NoiseProvider decorNoiseProvider)
        {
            _gridTriangles = new List <GridTriangle>();

            GridCoordinates = gridCoordinates;

            CalculateContents(graphicsDevice, heightProvider, decorNoiseProvider);
        }
Example #2
0
        public World(GraphicsDevice graphicsDevice, HeightProvider heightProvider, DirectionLight light, NoiseProvider decorNoiseProvider)
        {
            _graphicsDevice = graphicsDevice;

            _heightProvider = heightProvider;

            _decorNoiseProvider = decorNoiseProvider;

            _newTerrainChunks = new List <TerrainChunk>();

            TerrainChunks = new List <TerrainChunk>();
            Light         = light;
        }
        private void CalculateContents(GraphicsDevice graphicsDevice, HeightProvider heightProvider, NoiseProvider decorNoiseProvider)
        {
            float centreXWorld = GridCoordinates.X * EdgeLength;
            float centreZWorld = GridCoordinates.Y * EdgeLength;

            Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);

            List <TerrainVertex> resultVertices = new List <TerrainVertex>();

            for (int z = 0; z < VerticesPerEdge; z++)
            {
                for (int x = 0; x < VerticesPerEdge; x++)
                {
                    float positionXLocal = x * VertexSpacing - HalfEdgeLength;
                    float positionZLocal = z * VertexSpacing - HalfEdgeLength;

                    float positionXWorld = positionXLocal + centreXWorld;
                    float positionZWorld = positionZLocal + centreZWorld;

                    Vector3 position = new Vector3(positionXWorld, heightProvider.GetHeight(positionXWorld, positionZWorld), positionZWorld);
                    Vector3 normal   = heightProvider.GetNormalFromFiniteOffset(positionXWorld, positionZWorld);

                    Vector2 textureCoordinates       = new Vector2(positionXLocal, positionZLocal) / HalfEdgeLength;
                    Vector2 textureCoordinatesDetail = new Vector2(positionXLocal, positionZLocal) * 2 / HalfEdgeLength;

                    TerrainVertex vertex = new TerrainVertex(position, normal, textureCoordinates, textureCoordinatesDetail);
                    resultVertices.Add(vertex);

                    min = Vector3.Min(min, position);
                    max = Vector3.Max(max, position);
                }
            }

            TerrainVertex[] resultVerticesData = resultVertices.ToArray();

            VertexBuffer = new VertexBuffer(graphicsDevice, TerrainVertex.VertexDeclaration, resultVerticesData.Length, BufferUsage.WriteOnly);
            VertexBuffer.SetData(resultVerticesData);

            // Populate grid triangles
            _gridTriangles.Clear();

            for (int z = 0; z < VerticesPerEdge - 1; z++)
            {
                for (int x = 0; x < VerticesPerEdge - 1; x++)
                {
                    int baseIndexPosition = (x + z * (VerticesPerEdge - 1)) * 6;
                    _gridTriangles.Add(new GridTriangle(resultVerticesData[Indices[baseIndexPosition]].Position, resultVerticesData[Indices[baseIndexPosition + 1]].Position, resultVerticesData[Indices[baseIndexPosition + 2]].Position));
                    _gridTriangles.Add(new GridTriangle(resultVerticesData[Indices[baseIndexPosition + 3]].Position, resultVerticesData[Indices[baseIndexPosition + 4]].Position, resultVerticesData[Indices[baseIndexPosition + 5]].Position));
                }
            }

            // Include water tile vertices in bounding box
            for (int z = -1; z <= 1; z += 2)
            {
                for (int x = -1; x <= 1; x += 2)
                {
                    Vector3 waterTileVertexPosition = new Vector3(centreXWorld + x * HalfEdgeLength, 0, centreZWorld + z * HalfEdgeLength);

                    min = Vector3.Min(min, waterTileVertexPosition);
                    max = Vector3.Max(max, waterTileVertexPosition);
                }
            }

            BoundingBox = new BoundingBox(min, max);

            // Fill decor according to procedural inputs
            _decorRandom = new Random(GridCoordinates.GetHashCode());

            DecorItems = new List <DecorItem>();
            for (int z = 0; z < DecorGridSize; z++)
            {
                for (int x = 0; x < DecorGridSize; x++)
                {
                    float decorCentreXWorld = centreXWorld - HalfEdgeLength + HalfDecorTileEdgeLength + x * DecorTileEdgeLength + (float)(2 * _decorRandom.NextDouble() - 1) * HalfDecorTileEdgeLength;
                    float decorCentreZWorld = centreZWorld - HalfEdgeLength + HalfDecorTileEdgeLength + z * DecorTileEdgeLength + (float)(2 * _decorRandom.NextDouble() - 1) * HalfDecorTileEdgeLength;

                    float?decorHeight = GetGridHeight(new Vector3(decorCentreXWorld, 0, decorCentreZWorld));
                    if (decorHeight.HasValue && decorHeight.Value > 5)
                    {
                        if (decorNoiseProvider.GetValue(decorCentreXWorld, decorCentreZWorld) > 0.9f)
                        {
                            DecorItems.Add(new DecorItem(new Vector3(decorCentreXWorld, decorHeight.Value, decorCentreZWorld), (float)(_decorRandom.NextDouble() * 2 * Math.PI)));
                        }
                    }
                }
            }
        }