/// <summary>
        /// Writes the mesh data to the specified stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="stream"/> is <see langword="null"/>.
        /// </exception>
        public void Save(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            var writer = new BinaryWriter(stream);

            // Version
            writer.Write(0);

            // Number of levels and cells per level.
            writer.Write(NumberOfLevels);
            writer.Write(CellsPerLevel);

            // Number of vertices
            int vertexCount = Submesh.VertexCount;

            writer.Write(vertexCount);

            // Vertices
            var vertices = new TerrainVertex[vertexCount];

            Submesh.VertexBuffer.GetData(vertices);

            for (int i = 0; i < vertices.Length; i++)
            {
                writer.Write(vertices[i].Position.PackedValue);
            }

            // Number of indices.
            int indexCount = Submesh.PrimitiveCount * 3;

            writer.Write(indexCount);

            // Indices
            if (vertexCount <= ushort.MaxValue)
            {
                var indices = new ushort[indexCount];
                Submesh.IndexBuffer.GetData(indices);

                for (int i = 0; i < indexCount; i++)
                {
                    writer.Write(indices[i]);
                }
            }
            else
            {
                var indices = new int[indexCount];
                Submesh.IndexBuffer.GetData(indices);

                for (int i = 0; i < indexCount; i++)
                {
                    writer.Write(indices[i]);
                }
            }

            writer.Flush();
        }
Example #2
0
        private static DeviceBuffer CreateVertexBuffer(
            GraphicsDevice graphicsDevice,
            HeightMap heightMap,
            Rectangle patchBounds,
            ushort[] indices,
            out BoundingBox boundingBox,
            out Triangle[] triangles)
        {
            var numVertices = patchBounds.Width * patchBounds.Height;

            var vertices = new TerrainVertex[numVertices];
            var points   = new Vector3[numVertices];

            var vertexIndex = 0;

            for (var y = patchBounds.Y; y < patchBounds.Y + patchBounds.Height; y++)
            {
                for (var x = patchBounds.X; x < patchBounds.X + patchBounds.Width; x++)
                {
                    var position = heightMap.GetPosition(x, y);
                    points[vertexIndex]     = position;
                    vertices[vertexIndex++] = new TerrainVertex
                    {
                        Position = position,
                        Normal   = heightMap.Normals[x, y],
                        UV       = new Vector2(x, y)
                    };
                }
            }

            boundingBox = BoundingBox.CreateFromPoints(points);

            triangles = new Triangle[(patchBounds.Width - 1) * (patchBounds.Height) * 2];

            var triangleIndex = 0;
            var indexIndex    = 0;

            for (var y = 0; y < patchBounds.Height - 1; y++)
            {
                for (var x = 0; x < patchBounds.Width - 1; x++)
                {
                    // Triangle 1
                    triangles[triangleIndex++] = new Triangle(
                        points[indices[indexIndex++]],
                        points[indices[indexIndex++]],
                        points[indices[indexIndex++]]);

                    // Triangle 2
                    triangles[triangleIndex++] = new Triangle(
                        points[indices[indexIndex++]],
                        points[indices[indexIndex++]],
                        points[indices[indexIndex++]]);
                }
            }

            return(graphicsDevice.CreateStaticBuffer(vertices, BufferUsage.VertexBuffer));
        }
Example #3
0
        float GainVertex(int X, int Y, int DX, int DY, int Seed = 0)
        {
            TerrainVertex v = new TerrainVertex();

            v.Position.X          = X;
            v.Position.Z          = Y;
            v.Position.Y          = 0; v.Color = Color.Red;
            v.TextureCoordinate.X = X / 4f;
            v.TextureCoordinate.Y = Y / 4f;
            //this will contain calculated height
            float H = 0;

            if (this.Map == null)
            {
                return(0);// v;
            }
            //return v;
            int MapX = X + DX * (BlockSize);
            int MapY = Y + DY * (BlockSize);
            //get lerped "rough" elevation

            float Elevation = GetBilineaer(X, Y, DX, DY, Map.ElevationData);
            //return v;
            //*
            float base1 = Simplex.CalcPixel2D(MapX + 1112, MapY + 13123, 1f / 1024f) / 1f;

            H = 80f + Elevation * base1;
            float random2 = Simplex.CalcPixel2D(MapX + 1112, MapY + 13123, 1f / 32f) / 256f;

            random2 += Simplex.CalcPixel2D(MapX + 1112, MapY + 13123, 1f / 512f) / 32f;
            H       += random2;
            //*/
            bool isRiver    = false;
            bool isMountain = false;// 90f;// H;

            //return v;
            try
            {
                v.Color    = Map.GetGrassColour(DX, DY);
                isRiver    = Map.TileData[DX, DY] == WorldMap.TileType.River;
                isMountain = Map.TileData[DX, DY] == WorldMap.TileType.Mountain;
            }
            catch (Exception)
            {
                v.Color = Color.Red;
            }
            //   if (Elevation <= 0.0f&&!isRiver)
            //     H = 70f;

            v.Position.Y = H;

            if (v.Position.Y < 80f)
            {
                v.MultiTexData.Z = 1f;
            }
            return(v.Position.Y);
        }
Example #4
0
        public TerrainVertex[] GetVertices(GraphicsDevice gd)
        {
            if (VertexBuffer == null)
            {
                RegenTerrain(gd, Bp);
            }
            var dat = new TerrainVertex[VertexBuffer.VertexCount];

            VertexBuffer.GetData <TerrainVertex>(dat);
            return(dat);
        }
Example #5
0
            public static TerrainVertex[] GetVerticesMC(uint octreeNodeHandle)
            {
                // Based on http://stackoverflow.com/a/1318929
                uint noOfVertices;

                Validate(cuGetNoOfVerticesMC(octreeNodeHandle, out noOfVertices));

                TerrainVertex[] result = new TerrainVertex[noOfVertices];
                Validate(cuGetVerticesMC(octreeNodeHandle, out result));

                return(result);
            }
Example #6
0
        public static void UpdateCellBuffers(GraphicsDevice graphics,
                                             TerrainGeometryCellsComponent geo, D3DTerrainRenderComponent render)
        {
            var vbuff = new SharpDX.Direct3D11.Buffer[geo.Cells.Length];
            var ibuff = new SharpDX.Direct3D11.Buffer[geo.Cells.Length];

            for (var cellIndex = 0; cellIndex < geo.Cells.Length; cellIndex++)
            {
                var             cell   = geo.Cells[cellIndex];
                var             pool   = ArrayPool <TerrainVertex> .Shared;
                TerrainVertex[] vertex = null;
                try {
                    //vertex = new TerrainVertex[pos.Length];
                    vertex = pool.Rent(cell.VertexCount);//
                    for (var i = 0; i < cell.VertexCount; i++)
                    {
                        var weight = new Vector4(
                            SharpDX.MathUtil.Clamp(1.0f - (float)Math.Abs(cell.Positions[i].Y - 0f) / 8.0f, 0f, 1f),
                            SharpDX.MathUtil.Clamp(1.0f - (float)Math.Abs(cell.Positions[i].Y - 10) / 6.0f, 0f, 1f),
                            SharpDX.MathUtil.Clamp(1.0f - (float)Math.Abs(cell.Positions[i].Y - 15) / 6.0f, 0f, 1f),
                            SharpDX.MathUtil.Clamp(1.0f - (float)Math.Abs(cell.Positions[i].Y - geo.MaxHeight) / 4.0f, 0f, 1f)
                            );
                        var total = weight.X + weight.Y + weight.Z + weight.W;
                        weight.X /= total;
                        weight.Y /= total;
                        weight.Z /= total;
                        weight.W /= total;

                        vertex[i] = new TerrainVertex {
                            position         = cell.Positions[i],
                            normal           = cell.Normals[i],
                            tangent          = cell.Tangents[i],
                            binormal         = cell.Binormal[i],
                            color            = cell.Colors[i],
                            texcoor          = cell.TextureCoordinates[i],
                            normapMapTexCoor = cell.NormalMapTexCoordinates[i],
                            texWeights       = weight,
                        };
                    }

                    vbuff[cellIndex] = graphics.CreateBuffer(BindFlags.VertexBuffer, vertex);
                    ibuff[cellIndex] = graphics.CreateBuffer(BindFlags.IndexBuffer, cell.Indices);
                } finally {
                    pool.Return(vertex);
                }
            }
            render.VertexBuffers.Set(vbuff);
            render.IndexBuffers.Set(ibuff);
        }
Example #7
0
        public void RegenTerrain(GraphicsDevice device, WorldState world, Blueprint blueprint)
        {
            if (GrassState == null)
            {
                TerrainDirty = true; //yikes! try again to see if we have it next frame
                return;
            }
            TerrainDirty = false;
            if (VertexBuffer != null)
            {
                IndexBuffer.Dispose();
                BladeIndexBuffer.Dispose();
                VertexBuffer.Dispose();
                GridIndexBuffer?.Dispose();
                TGridIndexBuffer?.Dispose();
            }

            /** Convert rectangle to world units **/
            var quads = Size.Width;

            var quadWidth  = WorldSpace.GetWorldFromTile((float)Size.Width / (float)quads);
            var quadHeight = WorldSpace.GetWorldFromTile((float)Size.Height / (float)quads);
            var numQuads   = quads * quads;
            var archSize   = quads;

            TerrainVertex[] Geom         = new TerrainVertex[numQuads * 4];
            int[]           Indexes      = new int[numQuads * 6];
            int[]           BladeIndexes = new int[numQuads * 6];
            NumPrimitives = (numQuads * 2);

            int geomOffset   = 0;
            int indexOffset  = 0;
            int bindexOffset = 0;

            var offsetX = WorldSpace.GetWorldFromTile(Size.X);
            var offsetY = WorldSpace.GetWorldFromTile(Size.Y);

            for (var y = 0; y < quads; y++)
            {
                for (var x = 0; x < quads; x++)
                {
                    var tl = new Vector3(offsetX + (x * quadWidth), 0.0f, offsetY + (y * quadHeight));
                    var tr = new Vector3(tl.X + quadWidth, 0.0f, tl.Z);
                    var bl = new Vector3(tl.X, 0.0f, tl.Z + quadHeight);
                    var br = new Vector3(tl.X + quadWidth, 0.0f, tl.Z + quadHeight);

                    tl.Y = GetElevationPoint(x, y);
                    tr.Y = GetElevationPoint(x + 1, y);
                    bl.Y = GetElevationPoint(x, y + 1);
                    br.Y = GetElevationPoint(x + 1, y + 1);

                    Indexes[indexOffset++] = geomOffset;
                    Indexes[indexOffset++] = (geomOffset + 1);
                    Indexes[indexOffset++] = (geomOffset + 2);

                    Indexes[indexOffset++] = (geomOffset + 2);
                    Indexes[indexOffset++] = (geomOffset + 3);
                    Indexes[indexOffset++] = geomOffset;

                    short tx = (short)x, ty = (short)y;

                    if (blueprint.GetFloor(tx, ty, 1).Pattern == 0 &&
                        (blueprint.GetWall(tx, ty, 1).Segments & (WallSegments.HorizontalDiag | WallSegments.VerticalDiag)) == 0)
                    {
                        BladeIndexes[bindexOffset++] = geomOffset;
                        BladeIndexes[bindexOffset++] = (geomOffset + 1);
                        BladeIndexes[bindexOffset++] = (geomOffset + 2);

                        BladeIndexes[bindexOffset++] = (geomOffset + 2);
                        BladeIndexes[bindexOffset++] = (geomOffset + 3);
                        BladeIndexes[bindexOffset++] = geomOffset;
                    }

                    Color tlCol = Color.Lerp(LightGreen, LightBrown, GetGrassState(x, y));
                    Color trCol = Color.Lerp(LightGreen, LightBrown, GetGrassState(x + 1, y));
                    Color blCol = Color.Lerp(LightGreen, LightBrown, GetGrassState(x, y + 1));
                    Color brCol = Color.Lerp(LightGreen, LightBrown, GetGrassState(x + 1, y + 1));

                    Geom[geomOffset++] = new TerrainVertex(tl, tlCol.ToVector4(), new Vector2(((x - y) + 1) * 0.5f, (x + y) * 0.5f), GetGrassState(x, y), GetNormalAt(x, y));
                    Geom[geomOffset++] = new TerrainVertex(tr, trCol.ToVector4(), new Vector2(((x - y) + 2) * 0.5f, (x + 1 + y) * 0.5f), GetGrassState(x + 1, y), GetNormalAt(x + 1, y));
                    Geom[geomOffset++] = new TerrainVertex(br, brCol.ToVector4(), new Vector2(((x - y) + 1) * 0.5f, (x + y + 2) * 0.5f), GetGrassState(x + 1, y + 1), GetNormalAt(x + 1, y + 1));
                    Geom[geomOffset++] = new TerrainVertex(bl, blCol.ToVector4(), new Vector2((x - y) * 0.5f, (x + y + 1) * 0.5f), GetGrassState(x, y + 1), GetNormalAt(x, y + 1));
                }
            }

            var GridIndices  = GetGridIndicesForArea(Bp.BuildableArea, quads);
            var TGridIndices = GetGridIndicesForArea(Bp.TargetBuildableArea, quads);

            VertexBuffer = new VertexBuffer(device, typeof(TerrainVertex), Geom.Length, BufferUsage.None);
            VertexBuffer.SetData(Geom);

            IndexBuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits, sizeof(int) * Indexes.Length, BufferUsage.None);
            IndexBuffer.SetData(Indexes);

            BladePrimitives = (bindexOffset / 3);

            BladeIndexBuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits, sizeof(int) * Indexes.Length, BufferUsage.None);
            BladeIndexBuffer.SetData(BladeIndexes);
            GeomLength = Geom.Length;

            if (GridIndices.Length > 0)
            {
                GridIndexBuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits, sizeof(int) * GridIndices.Length, BufferUsage.None);
                GridIndexBuffer.SetData(GridIndices);
                GridPrimitives = GridIndices.Length / 2;
            }

            if (TGridIndices.Length > 0)
            {
                TGridIndexBuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits, sizeof(int) * TGridIndices.Length, BufferUsage.None);
                TGridIndexBuffer.SetData(TGridIndices);
                TGridPrimitives = TGridIndices.Length / 2;
            }
        }
Example #8
0
		/// <summary>
		/// Creates the vertex buffer for the bottom right interior trim
		/// </summary>
		/// <param name="pGraphicsDevice"></param>
		private void PopulateVerticesBottomRight(TerrainVertex.Shared[] pVertices)
		{
			int nCounter = 0;

			// bottom segment
			for (short y = Settings.BLOCK_SIZE_M_MINUS_ONE; y < Settings.BLOCK_SIZE_M + 1; y++)
			{
				for (short x = Settings.BLOCK_SIZE_M_MINUS_ONE; x < Settings.GRID_SIZE_N - Settings.BLOCK_SIZE_M_MINUS_ONE; x++)
				{
					// write shared data
					pVertices[nCounter++] = new TerrainVertex.Shared(x, y);
				}
			}

			// right segment
			for (short y = Settings.BLOCK_SIZE_M; y < (3 * Settings.BLOCK_SIZE_M); y++)
			{
				for (short x = Settings.GRID_SIZE_N - Settings.BLOCK_SIZE_M - 1; x < Settings.GRID_SIZE_N - Settings.BLOCK_SIZE_M_MINUS_ONE; x++)
				{
					// write shared data
					pVertices[nCounter++] = new TerrainVertex.Shared(x, y);
				}
			}
		}
        public static TerrainRendererMesh Load(GraphicsDevice graphicsDevice, Stream stream)
        {
            if (graphicsDevice == null)
            {
                throw new ArgumentNullException("graphicsDevice");
            }
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            var reader = new BinaryReader(stream);

            // Version
            reader.ReadInt32();

            // Number of levels and cells per level.
            int numberOfLevels = reader.ReadInt32();
            int cellsPerLevel  = reader.ReadInt32();

            // Number of vertices
            int vertexCount = reader.ReadInt32();

            // Vertices
            var vertices = new TerrainVertex[vertexCount];

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Position             = new HalfVector4();
                vertices[i].Position.PackedValue = reader.ReadUInt64();
            }

            // Number of indices.
            int indexCount = reader.ReadInt32();

            // Indices
            Submesh submesh;

            if (vertexCount <= ushort.MaxValue)
            {
                var indices = new ushort[indexCount];
                for (int i = 0; i < indices.Length; i++)
                {
                    indices[i] = reader.ReadUInt16();
                }

                submesh = CreateSubmesh(graphicsDevice, vertices, indices);
            }
            else
            {
                var indices = new int[indexCount];
                for (int i = 0; i < indices.Length; i++)
                {
                    indices[i] = reader.ReadInt32();
                }

                submesh = CreateSubmesh(graphicsDevice, vertices, indices);
            }

            return(new TerrainRendererMesh(numberOfLevels, cellsPerLevel, submesh));
        }
        private static Submesh CreateGeoClipmapMesh(GraphicsDevice graphicsDevice, int numberOfLevels,
                                                    int cellsPerLevel, bool useDiamondTessellation)
        {
            if (graphicsDevice == null)
            {
                throw new ArgumentNullException("graphicsDevice");
            }
            if (cellsPerLevel < 1)
            {
                throw new ArgumentOutOfRangeException("cellsPerLevel", "The number of cells per level must be greater than 0.");
            }

            // Round to even number of cells.
            if (cellsPerLevel % 2 != 0)
            {
                cellsPerLevel++;
            }

            // Allocate a mesh with conservative list capacities.
            int cellsPerLevelUpperBound    = (cellsPerLevel + 3) * (cellsPerLevel + 3);
            int verticesPerLevelUpperBound = useDiamondTessellation ? cellsPerLevelUpperBound * 9 : cellsPerLevelUpperBound * 4;
            int indicesPerLevelUpperBound  = useDiamondTessellation ? cellsPerLevelUpperBound * 8 * 3 : cellsPerLevelUpperBound * 2 * 3;
            var triangleMesh = new TriangleMesh(verticesPerLevelUpperBound * numberOfLevels, indicesPerLevelUpperBound * numberOfLevels);

            // The levels are created in a separate mesh and then combined into the final mesh.
            var triangleMeshes = new TriangleMesh[numberOfLevels];

            triangleMeshes[0] = triangleMesh;
            for (int i = 1; i < numberOfLevels; i++)
            {
                triangleMeshes[i] = new TriangleMesh(verticesPerLevelUpperBound, indicesPerLevelUpperBound);
            }

            //for (int level = 0; level < numberOfLevels; level++)
            Parallel.For(0, numberOfLevels, level =>
            {
                var levelTriangleMesh = triangleMeshes[level];
                int cellSize          = (1 << level);
                float y = level; // Store LOD in Y coordinate.

                Debug.Assert(cellsPerLevel % 2 == 0);

                int halfWidthInCells = cellsPerLevel / 2;
                int halfWidth        = cellSize * (halfWidthInCells);
                int minInclusive     = -halfWidth - cellSize; // We add an extra border on the top and left.
                int maxInclusive     = halfWidth - cellSize;  // Normal loop limit without extra border.

                int previousHalfWidth = (level > 0) ? halfWidth / 2 : -1;

                if (useDiamondTessellation)
                {
                    int index = 0;
                    for (int z = minInclusive; z <= maxInclusive; z += cellSize)
                    {
                        for (int x = minInclusive; x <= maxInclusive; x += cellSize)
                        {
                            // No triangles in the area which are covered by previous levels.
                            // (We compare cell centers with radius of last LOD.)
                            if (Math.Max(Math.Abs(x + cellSize / 2), Math.Abs(z + cellSize / 2)) < previousHalfWidth)
                            {
                                continue;
                            }

                            // Each cell will be tessellated like this:
                            //   A-----B-----C
                            //   | \   |   / |
                            //   |   \ | /   |
                            //   D-----E-----F
                            //   |   / | \   |
                            //   | /   |   \ |
                            //   G-----H-----I

                            var indexA = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z));

                            var indexB = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + 0.5f * cellSize, y, z));

                            var indexC = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z));

                            var indexD = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z + 0.5f * cellSize));

                            var indexE = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + 0.5f * cellSize, y, z + 0.5f * cellSize));

                            var indexF = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z + 0.5f * cellSize));

                            var indexG = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z + cellSize));

                            var indexH = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + 0.5f * cellSize, y, z + cellSize));

                            var indexI = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z + cellSize));

                            // Triangles using ADEG:
                            if (x != minInclusive)
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexD);
                                levelTriangleMesh.Indices.Add(indexA);

                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexG);
                                levelTriangleMesh.Indices.Add(indexD);
                            }
                            else
                            {
                                // The outer cells are tessellated differently to stitch to the next level.
                                //   A-----B-----C
                                //   | \   |   / |
                                //   |   \ | /   |
                                //   |     E-----F
                                //   |   / | \   |
                                //   | /   |   \ |
                                //   G-----H-----I
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexG);
                                levelTriangleMesh.Indices.Add(indexA);
                            }

                            // Triangles using ABCE:
                            if (z != minInclusive)
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexB);
                                levelTriangleMesh.Indices.Add(indexC);

                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexA);
                                levelTriangleMesh.Indices.Add(indexB);
                            }
                            else
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexA);
                                levelTriangleMesh.Indices.Add(indexC);
                            }

                            // Triangles using CEFI:
                            if (x != maxInclusive)
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexF);
                                levelTriangleMesh.Indices.Add(indexI);

                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexC);
                                levelTriangleMesh.Indices.Add(indexF);
                            }
                            else
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexC);
                                levelTriangleMesh.Indices.Add(indexI);
                            }

                            // Triangles using EGHI:
                            if (z != maxInclusive)
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexH);
                                levelTriangleMesh.Indices.Add(indexG);

                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexI);
                                levelTriangleMesh.Indices.Add(indexH);
                            }
                            else
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexI);
                                levelTriangleMesh.Indices.Add(indexG);
                            }
                        }
                    }

                    Debug.Assert(levelTriangleMesh.Vertices.Count <= verticesPerLevelUpperBound, "Bad estimate for upper bound of vertices.");
                    Debug.Assert(levelTriangleMesh.Indices.Count <= indicesPerLevelUpperBound, "Bad estimate for upper bound of indices.");

                    levelTriangleMesh.WeldVertices(0.1f);
                }
                else
                {
                    // Add one extra border to hide gaps.
                    minInclusive -= cellSize;
                    maxInclusive += cellSize;

                    int index = 0;
                    for (int z = minInclusive; z <= maxInclusive; z += cellSize)
                    {
                        for (int x = minInclusive; x <= maxInclusive; x += cellSize)
                        {
                            // No triangles in the area which are covered by previous levels.
                            // (We compare cell centers with radius of last LOD.)
                            if (Math.Max(Math.Abs(x + cellSize / 2), Math.Abs(z + cellSize / 2)) < previousHalfWidth)
                            {
                                continue;
                            }

                            // Each 2x2 cells will be tessellated like this:
                            //   A-----B
                            //   |   / |
                            //   | /   |
                            //   C-----D

                            int indexA = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z));

                            int indexB = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z));

                            int indexC = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z + cellSize));

                            int indexD = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z + cellSize));

                            levelTriangleMesh.Indices.Add(indexA);
                            levelTriangleMesh.Indices.Add(indexB);
                            levelTriangleMesh.Indices.Add(indexC);

                            levelTriangleMesh.Indices.Add(indexC);
                            levelTriangleMesh.Indices.Add(indexB);
                            levelTriangleMesh.Indices.Add(indexD);
                        }
                    }

                    Debug.Assert(levelTriangleMesh.Vertices.Count <= verticesPerLevelUpperBound, "Bad estimate for upper bound of vertices.");
                    Debug.Assert(levelTriangleMesh.Indices.Count <= indicesPerLevelUpperBound, "Bad estimate for upper bound of indices.");

                    levelTriangleMesh.WeldVertices(0.1f);
                }
            });

            // Combine meshes.
            for (int i = 1; i < numberOfLevels; i++)
            {
                triangleMesh.Add(triangleMeshes[i]);
            }

            var vertices = new TerrainVertex[triangleMesh.Vertices.Count];
            {
                int index = 0;
                for (int i = 0; i < vertices.Length; i++)
                {
                    Vector3 v = triangleMesh.Vertices[i];
                    vertices[index++] = new TerrainVertex(new HalfVector4(v.X, v.Y, v.Z, 1));
                }
            }

            var submesh = CreateSubmesh(graphicsDevice, vertices, triangleMesh.Indices.ToArray());

            //Debug.WriteLine("Number of terrain vertices:" + vertices.Length);
            //Debug.WriteLine("Number of terrain triangles:" + triangleMesh.Indices.Count / 3);

            return(submesh);
        }
        /// <summary>
        /// Creates patch skirt vertices
        /// </summary>
        /// <param name="firstVertex">First vertex in the patch</param>
        private static unsafe void CreateSkirtVertices( TerrainVertex* firstVertex )
        {
            if ( DebugInfo.DisableTerainSkirts )
            {
                return;
            }

            int vRes = TerrainPatchConstants.PatchResolution - 1;

            //	First horizontal skirt
            TerrainVertex* skirtVertex = firstVertex + TerrainPatchConstants.PatchArea;
            CreateSkirtVertices( firstVertex, 1, skirtVertex );

            //	First vertical skirt
            skirtVertex += TerrainPatchConstants.PatchResolution;
            CreateSkirtVertices( firstVertex, TerrainPatchConstants.PatchResolution, skirtVertex );

            //	Last horizontal skirt
            skirtVertex += TerrainPatchConstants.PatchResolution;
            CreateSkirtVertices( firstVertex + vRes * TerrainPatchConstants.PatchResolution, 1, skirtVertex );

            //	Last vertical skirt
            skirtVertex += TerrainPatchConstants.PatchResolution;
            CreateSkirtVertices( firstVertex + vRes, TerrainPatchConstants.PatchResolution, skirtVertex );
        }
Example #12
0
        /// <summary>
        ///  This implements the method in resource, to load the mesh data(vertex buffer, index buffer)
        ///  of this terrain tile.
        /// </summary>
        protected override void load()
        {
            // 读取地形数据
            // This line will load the terrain data in this tile.
            float[] data = TerrainData.Instance.GetData(tileX, tileY, terrEdgeSize);

            float radtc = MathEx.Degree2Radian(tileCol);
            float radtl = MathEx.Degree2Radian(tileLat);

            float radSpan = MathEx.Degree2Radian(10);

            int vertexCount = terrEdgeSize * terrEdgeSize;
            int terrEdgeLen = terrEdgeSize - 1;

            if (terrEdgeSize == 33)
                material.SetEffect(EffectManager.Instance.GetModelEffect(TerrainEffect33Factory.Name));
            else
                material.SetEffect(EffectManager.Instance.GetModelEffect(TerrainEffect17Factory.Name));

            #region 顶点数据

            vtxDecl = factory.CreateVertexDeclaration(TerrainVertex.Elements);

            vtxBuffer = factory.CreateVertexBuffer(vertexCount, vtxDecl, BufferUsage.WriteOnly);

            TerrainVertex[] vtxArray = new TerrainVertex[vertexCount];


            float cellAngle = radSpan / (float)terrEdgeLen;
            #region 计算顶点坐标
            // Caluclate the position of each vertex

            // i为纬度方向
            // i is in the latitude direction
            for (int i = 0; i < terrEdgeSize; i++)
            {
                // j为经度方向
                // j is in the longitude direction
                for (int j = 0; j < terrEdgeSize; j++)
                {
                    Vector3 pos = PlanetEarth.GetPosition(radtc + j * cellAngle, radtl - i * cellAngle);

                    int index = i * terrEdgeSize + j;

                    // 计算海拔高度
                    // calculate the elevation
                    float height = (data[index] - TerrainMeshManager.PostZeroLevel) * TerrainMeshManager.PostHeightScale;

                    //if (height > 0)
                    //{
                    //    height = (height - 0) * TerrainMeshManager.PostHeightScale;
                    //}
                    //else
                    //{
                    //    height *= TerrainMeshManager.PostHeightScale;
                    //    height -= 10;
                    //    //if (height < -30)
                    //    //    height = -30;
                    //}

                    Vector3 normal = pos;
                    normal.Normalize();
                    vtxArray[index].Position = pos + normal * height;

                    // this index is used to generate detailed texture coordinate in vertex shader
                    vtxArray[index].Index = index;


                    // map the texture coordinate for global texturing
                    float curCol = radtc + j * cellAngle;
                    float curLat = radSpan + radtl - i * cellAngle;

                    curCol += MathEx.PIf;
                    curLat -= MathEx.Degree2Radian(10);

                    vtxArray[index].u = 0.5f * curCol / MathEx.PIf;
                    vtxArray[index].v = (-curLat + MathEx.PiOver2) / MathEx.PIf;
                }
            }
            #endregion

            #endregion

            #region 索引数据
            SharedIndexData sindexData = TerrainMeshManager.Instance.GetIndexData(terrEdgeSize);
            indexBuffer = sindexData.Index;
            #endregion

            #region 构造GeomentryData
            defGeometryData = new GeomentryData();
            defGeometryData.VertexDeclaration = vtxDecl;

            defGeometryData.VertexSize = TerrainVertex.Size;
            defGeometryData.VertexBuffer = vtxBuffer;
            defGeometryData.IndexBuffer = indexBuffer;
            defGeometryData.PrimCount = indexBuffer.IndexCount / 3;
            defGeometryData.VertexCount = terrEdgeSize * terrEdgeSize;

            defGeometryData.PrimitiveType = RenderPrimitiveType.TriangleList;

            defGeometryData.BaseVertex = 0;

            #endregion

            vtxBuffer.SetData<TerrainVertex>(vtxArray);
        }
 /// <summary>
 /// Generates vertices for a patch. Calculates maximum error between this patch and next higher detail patch
 /// </summary>
 /// <param name="patch">Patch</param>
 /// <param name="res">Patch resolution</param>
 /// <param name="firstVertex">Patch vertices</param>
 /// <param name="error">Maximum error value between this patch and higher level patch</param>
 public unsafe void GenerateTerrainPatchVertices( ITerrainPatch patch, int res, TerrainVertex* firstVertex, out float error )
 {
     SetPatchPlanetParameters( patch );
     SafeTerrainGenerator.GenerateVertices( patch.LocalOrigin, patch.LocalUStep, patch.LocalVStep, res, res, patch.Uv, patch.UvResolution, firstVertex, out error );
 }
Example #14
0
        private static Submesh CreateSubmesh(GraphicsDevice graphicsDevice, TerrainVertex[] vertices, Array indices)
        {
            var submesh = new Submesh();

              submesh.VertexBuffer = new VertexBuffer(
            graphicsDevice,
            TerrainVertex.VertexDeclaration,
            vertices.Length,
            BufferUsage.None);
              submesh.VertexBuffer.SetData(vertices);
              submesh.VertexCount = submesh.VertexBuffer.VertexCount;

              // Build array of indices.
              if (vertices.Length <= ushort.MaxValue)
              {
            var indicesUInt16 = indices as ushort[];
            if (indicesUInt16 == null)
            {
              var indicesInt32 = (int[])indices;
              indicesUInt16 = new ushort[indices.Length];
              for (int i = 0; i < indicesUInt16.Length; i++)
            indicesUInt16[i] = (ushort)indicesInt32[i];
            }

            submesh.IndexBuffer = new IndexBuffer(
              graphicsDevice,
              IndexElementSize.SixteenBits,
              indicesUInt16.Length,
              BufferUsage.None);
            submesh.IndexBuffer.SetData(indicesUInt16);
              }
              else
              {
            var indicesInt32 = (int[])indices;
            submesh.IndexBuffer = new IndexBuffer(
              graphicsDevice,
              IndexElementSize.ThirtyTwoBits,
              indicesInt32.Length,
              BufferUsage.None);
            submesh.IndexBuffer.SetData(indicesInt32);
              }

              submesh.PrimitiveType = PrimitiveType.TriangleList;
              submesh.PrimitiveCount = indices.Length / 3;
              return submesh;
        }
Example #15
0
        private static Submesh CreateGeoClipmapMesh(GraphicsDevice graphicsDevice, int numberOfLevels, 
            int cellsPerLevel, bool useDiamondTessellation)
        {
            if (graphicsDevice == null)
            throw new ArgumentNullException("graphicsDevice");
              if (cellsPerLevel < 1)
            throw new ArgumentOutOfRangeException("cellsPerLevel", "The number of cells per level must be greater than 0.");

              // Round to even number of cells.
              if (cellsPerLevel % 2 != 0)
            cellsPerLevel++;

              // Allocate a mesh with conservative list capacities.
              int cellsPerLevelUpperBound = (cellsPerLevel + 3) * (cellsPerLevel + 3);
              int verticesPerLevelUpperBound = useDiamondTessellation ? cellsPerLevelUpperBound * 9 : cellsPerLevelUpperBound * 4;
              int indicesPerLevelUpperBound = useDiamondTessellation ? cellsPerLevelUpperBound * 8 * 3 : cellsPerLevelUpperBound * 2 * 3;
              var triangleMesh = new TriangleMesh(verticesPerLevelUpperBound * numberOfLevels, indicesPerLevelUpperBound * numberOfLevels);

              // The levels are created in a separate mesh and then combined into the final mesh.
              var triangleMeshes = new TriangleMesh[numberOfLevels];
              triangleMeshes[0] = triangleMesh;
              for (int i = 1; i < numberOfLevels; i++)
            triangleMeshes[i] = new TriangleMesh(verticesPerLevelUpperBound, indicesPerLevelUpperBound);

              //for (int level = 0; level < numberOfLevels; level++)
              Parallel.For(0, numberOfLevels, level =>
              {
            var levelTriangleMesh = triangleMeshes[level];
            int cellSize = (1 << level);
            float y = level;  // Store LOD in Y coordinate.

            Debug.Assert(cellsPerLevel % 2 == 0);

            int halfWidthInCells = cellsPerLevel / 2;
            int halfWidth = cellSize * (halfWidthInCells);
            int minInclusive = -halfWidth - cellSize;  // We add an extra border on the top and left.
            int maxInclusive = halfWidth - cellSize;   // Normal loop limit without extra border.

            int previousHalfWidth = (level > 0) ? halfWidth / 2 : -1;

            if (useDiamondTessellation)
            {
              #region ----- Diamond tessellation -----

              int index = 0;
              for (int z = minInclusive; z <= maxInclusive; z += cellSize)
              {
            for (int x = minInclusive; x <= maxInclusive; x += cellSize)
            {
              // No triangles in the area which are covered by previous levels.
              // (We compare cell centers with radius of last LOD.)
              if (Math.Max(Math.Abs(x + cellSize / 2), Math.Abs(z + cellSize / 2)) < previousHalfWidth)
                continue;

              // Each cell will be tessellated like this:
              //   A-----B-----C
              //   | \   |   / |
              //   |   \ | /   |
              //   D-----E-----F
              //   |   / | \   |
              //   | /   |   \ |
              //   G-----H-----I

              var indexA = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x, y, z));

              var indexB = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x + 0.5f * cellSize, y, z));

              var indexC = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x + cellSize, y, z));

              var indexD = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x, y, z + 0.5f * cellSize));

              var indexE = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x + 0.5f * cellSize, y, z + 0.5f * cellSize));

              var indexF = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x + cellSize, y, z + 0.5f * cellSize));

              var indexG = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x, y, z + cellSize));

              var indexH = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x + 0.5f * cellSize, y, z + cellSize));

              var indexI = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x + cellSize, y, z + cellSize));

              // Triangles using ADEG:
              if (x != minInclusive)
              {
                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexD);
                levelTriangleMesh.Indices.Add(indexA);

                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexG);
                levelTriangleMesh.Indices.Add(indexD);
              }
              else
              {
                // The outer cells are tessellated differently to stitch to the next level.
                //   A-----B-----C
                //   | \   |   / |
                //   |   \ | /   |
                //   |     E-----F
                //   |   / | \   |
                //   | /   |   \ |
                //   G-----H-----I
                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexG);
                levelTriangleMesh.Indices.Add(indexA);
              }

              // Triangles using ABCE:
              if (z != minInclusive)
              {
                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexB);
                levelTriangleMesh.Indices.Add(indexC);

                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexA);
                levelTriangleMesh.Indices.Add(indexB);
              }
              else
              {
                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexA);
                levelTriangleMesh.Indices.Add(indexC);
              }

              // Triangles using CEFI:
              if (x != maxInclusive)
              {
                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexF);
                levelTriangleMesh.Indices.Add(indexI);

                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexC);
                levelTriangleMesh.Indices.Add(indexF);
              }
              else
              {
                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexC);
                levelTriangleMesh.Indices.Add(indexI);
              }

              // Triangles using EGHI:
              if (z != maxInclusive)
              {
                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexH);
                levelTriangleMesh.Indices.Add(indexG);

                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexI);
                levelTriangleMesh.Indices.Add(indexH);
              }
              else
              {
                levelTriangleMesh.Indices.Add(indexE);
                levelTriangleMesh.Indices.Add(indexI);
                levelTriangleMesh.Indices.Add(indexG);
              }
            }
              }

              Debug.Assert(levelTriangleMesh.Vertices.Count <= verticesPerLevelUpperBound, "Bad estimate for upper bound of vertices.");
              Debug.Assert(levelTriangleMesh.Indices.Count <= indicesPerLevelUpperBound, "Bad estimate for upper bound of indices.");

              levelTriangleMesh.WeldVertices(0.1f);
              #endregion
            }
            else
            {
              #region ----- Simple tessellation -----

              // Add one extra border to hide gaps.
              minInclusive -= cellSize;
              maxInclusive += cellSize;

              int index = 0;
              for (int z = minInclusive; z <= maxInclusive; z += cellSize)
              {
            for (int x = minInclusive; x <= maxInclusive; x += cellSize)
            {
              // No triangles in the area which are covered by previous levels.
              // (We compare cell centers with radius of last LOD.)
              if (Math.Max(Math.Abs(x + cellSize / 2), Math.Abs(z + cellSize / 2)) < previousHalfWidth)
                continue;

              // Each 2x2 cells will be tessellated like this:
              //   A-----B
              //   |   / |
              //   | /   |
              //   C-----D

              int indexA = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x, y, z));

              int indexB = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x + cellSize, y, z));

              int indexC = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x, y, z + cellSize));

              int indexD = index++;
              levelTriangleMesh.Vertices.Add(new Vector3F(x + cellSize, y, z + cellSize));

              levelTriangleMesh.Indices.Add(indexA);
              levelTriangleMesh.Indices.Add(indexB);
              levelTriangleMesh.Indices.Add(indexC);

              levelTriangleMesh.Indices.Add(indexC);
              levelTriangleMesh.Indices.Add(indexB);
              levelTriangleMesh.Indices.Add(indexD);
            }
              }

              Debug.Assert(levelTriangleMesh.Vertices.Count <= verticesPerLevelUpperBound, "Bad estimate for upper bound of vertices.");
              Debug.Assert(levelTriangleMesh.Indices.Count <= indicesPerLevelUpperBound, "Bad estimate for upper bound of indices.");

              levelTriangleMesh.WeldVertices(0.1f);
              #endregion
            }
              });

              // Combine meshes.
              for (int i = 1; i < numberOfLevels; i++)
            triangleMesh.Add(triangleMeshes[i]);

              var vertices = new TerrainVertex[triangleMesh.Vertices.Count];
              {
            int index = 0;
            for (int i = 0; i < vertices.Length; i++)
            {
              Vector3F v = triangleMesh.Vertices[i];
              vertices[index++] = new TerrainVertex(new HalfVector4(v.X, v.Y, v.Z, 1));
            }
              }

              var submesh = CreateSubmesh(graphicsDevice, vertices, triangleMesh.Indices.ToArray());

              //Debug.WriteLine("Number of terrain vertices:" + vertices.Length);
              //Debug.WriteLine("Number of terrain triangles:" + triangleMesh.Indices.Count / 3);

              return submesh;
        }
Example #16
0
        /// <summary>
        /// Writes the mesh data to the specified stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="stream"/> is <see langword="null"/>.
        /// </exception>
        public void Save(Stream stream)
        {
            if (stream == null)
            throw new ArgumentNullException("stream");

              var writer = new BinaryWriter(stream);

              // Version
              writer.Write(0);

              // Number of levels and cells per level.
              writer.Write(NumberOfLevels);
              writer.Write(CellsPerLevel);

              // Number of vertices
              int vertexCount = Submesh.VertexCount;
              writer.Write(vertexCount);

              // Vertices
              var vertices = new TerrainVertex[vertexCount];
              Submesh.VertexBuffer.GetData(vertices);

              for (int i = 0; i < vertices.Length; i++)
            writer.Write(vertices[i].Position.PackedValue);

              // Number of indices.
              int indexCount = Submesh.PrimitiveCount * 3;
              writer.Write(indexCount);

              // Indices
              if (vertexCount <= ushort.MaxValue)
              {
            var indices = new ushort[indexCount];
            Submesh.IndexBuffer.GetData(indices);

            for (int i = 0; i < indexCount; i++)
              writer.Write(indices[i]);
              }
              else
              {
            var indices = new int[indexCount];
            Submesh.IndexBuffer.GetData(indices);

            for (int i = 0; i < indexCount; i++)
              writer.Write(indices[i]);
              }

              writer.Flush();
        }
Example #17
0
        public static TerrainRendererMesh Load(GraphicsDevice graphicsDevice, Stream stream)
        {
            if (graphicsDevice == null)
            throw new ArgumentNullException("graphicsDevice");
              if (stream == null)
            throw new ArgumentNullException("stream");

              var reader = new BinaryReader(stream);

              // Version
              reader.ReadInt32();

              // Number of levels and cells per level.
              int numberOfLevels = reader.ReadInt32();
              int cellsPerLevel = reader.ReadInt32();

              // Number of vertices
              int vertexCount = reader.ReadInt32();

              // Vertices
              var vertices = new TerrainVertex[vertexCount];
              for (int i = 0; i < vertices.Length; i++)
              {
            vertices[i].Position = new HalfVector4();
            vertices[i].Position.PackedValue = reader.ReadUInt64();
              }

              // Number of indices.
              int indexCount = reader.ReadInt32();

              // Indices
              Submesh submesh;
              if (vertexCount <= ushort.MaxValue)
              {
            var indices = new ushort[indexCount];
            for (int i = 0; i < indices.Length; i++)
              indices[i] = reader.ReadUInt16();

            submesh = CreateSubmesh(graphicsDevice, vertices, indices);
              }
              else
              {
            var indices = new int[indexCount];
            for (int i = 0; i < indices.Length; i++)
              indices[i] = reader.ReadInt32();

            submesh = CreateSubmesh(graphicsDevice, vertices, indices);
              }

              return new TerrainRendererMesh(numberOfLevels, cellsPerLevel, submesh);
        }
        /// <summary>
        /// Creates a strip of patch skirt vertices
        /// </summary>
        /// <param name="srcVertex"></param>
        /// <param name="srcOffset"></param>
        /// <param name="dstVertex"></param>
        private static unsafe void CreateSkirtVertices( TerrainVertex* srcVertex, int srcOffset, TerrainVertex* dstVertex )
        {
            float skirtSize = -10;
            for ( int i = 0; i < TerrainPatchConstants.PatchResolution; ++i )
            {
                Vector3 offset = srcVertex->Normal * skirtSize;
                srcVertex->CopyTo( dstVertex, offset );

                srcVertex += srcOffset;
                ++dstVertex;
            }
        }
Example #19
0
        public void MeshRects(int level, GraphicsDevice device)
        {
            var rects = RoofRects[level - 2];

            if (rects == null)
            {
                return;
            }
            if (Drawgroups[level - 2] != null && Drawgroups[level - 2].NumPrimitives > 0)
            {
                Drawgroups[level - 2].VertexBuffer.Dispose();
                Drawgroups[level - 2].IndexBuffer.Dispose();
            }

            var numQuads = rects.Count * 4; //4 sides for each roof rectangle

            TerrainVertex[] Geom    = new TerrainVertex[numQuads * 4];
            int[]           Indexes = new int[numQuads * 6];

            var numPrimitives = (numQuads * 2);
            int geomOffset    = 0;
            int indexOffset   = 0;

            foreach (var rect in rects)
            {
                //determine roof height of the smallest edge. This height will be used on all edges
                var height = Math.Min(rect.x2 - rect.x1, rect.y2 - rect.y1) / 2;
                //    /    \
                //   /      \
                //  /________\  Draw 4 segments like this. two segments will have the top middle section so short it will not appear.

                var heightMod = height / 400f;
                var pitch     = RoofPitch;
                var tl        = ToWorldPos(rect.x1, rect.y1, 0, level, pitch) + new Vector3(0, heightMod, 0);
                var tr        = ToWorldPos(rect.x2, rect.y1, 0, level, pitch) + new Vector3(0, heightMod, 0);
                var bl        = ToWorldPos(rect.x1, rect.y2, 0, level, pitch) + new Vector3(0, heightMod, 0);
                var br        = ToWorldPos(rect.x2, rect.y2, 0, level, pitch) + new Vector3(0, heightMod, 0);

                //middle vertices. todo: height modifier (not hard)

                var m_tl = ToWorldPos(rect.x1 + height, rect.y1 + height, height, level, pitch) + new Vector3(0, heightMod, 0);
                var m_tr = ToWorldPos(rect.x2 - height, rect.y1 + height, height, level, pitch) + new Vector3(0, heightMod, 0);
                var m_bl = ToWorldPos(rect.x1 + height, rect.y2 - height, height, level, pitch) + new Vector3(0, heightMod, 0);
                var m_br = ToWorldPos(rect.x2 - height, rect.y2 - height, height, level, pitch) + new Vector3(0, heightMod, 0);

                Color   topCol   = Color.Lerp(Color.White, new Color(175, 175, 175), pitch);
                Color   rightCol = Color.White;
                Color   btmCol   = Color.Lerp(Color.White, new Color(200, 200, 200), pitch);
                Color   leftCol  = Color.Lerp(Color.White, new Color(150, 150, 150), pitch);
                Vector4 darken   = new Vector4(0.8f, 0.8f, 0.8f, 1.0f);

                //quad as two tris
                for (int j = 0; j < 16; j += 4)
                {
                    Indexes[indexOffset++] = geomOffset + j;
                    Indexes[indexOffset++] = (geomOffset + 1) + j;
                    Indexes[indexOffset++] = (geomOffset + 2) + j;

                    Indexes[indexOffset++] = (geomOffset + 2) + j;
                    Indexes[indexOffset++] = (geomOffset + 3) + j;
                    Indexes[indexOffset++] = geomOffset + j;
                }

                Vector2 texScale = new Vector2(2 / 3f, 1f);
                Geom[geomOffset++] = new TerrainVertex(tl, topCol.ToVector4() * darken, new Vector2(tl.X, tl.Z * -1) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(tr, topCol.ToVector4() * darken, new Vector2(tr.X, tr.Z * -1) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(m_tr, topCol.ToVector4(), new Vector2(m_tr.X, m_tr.Z * -1) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(m_tl, topCol.ToVector4(), new Vector2(m_tl.X, m_tl.Z * -1) * texScale, 0);

                Geom[geomOffset++] = new TerrainVertex(tr, rightCol.ToVector4() * darken, new Vector2(tr.Z, tr.X) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(br, rightCol.ToVector4() * darken, new Vector2(br.Z, br.X) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(m_br, rightCol.ToVector4(), new Vector2(m_br.Z, m_br.X) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(m_tr, rightCol.ToVector4(), new Vector2(m_tr.Z, m_tr.X) * texScale, 0);

                Geom[geomOffset++] = new TerrainVertex(br, btmCol.ToVector4() * darken, new Vector2(br.X, br.Z) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(bl, btmCol.ToVector4() * darken, new Vector2(bl.X, bl.Z) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(m_bl, btmCol.ToVector4(), new Vector2(m_bl.X, m_bl.Z) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(m_br, btmCol.ToVector4(), new Vector2(m_br.X, m_br.Z) * texScale, 0);

                Geom[geomOffset++] = new TerrainVertex(bl, leftCol.ToVector4() * darken, new Vector2(bl.Z, bl.X * -1) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(tl, leftCol.ToVector4() * darken, new Vector2(tl.Z, tl.X * -1) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(m_tl, leftCol.ToVector4(), new Vector2(m_tl.Z, m_tl.X * -1) * texScale, 0);
                Geom[geomOffset++] = new TerrainVertex(m_bl, leftCol.ToVector4(), new Vector2(m_bl.Z, m_bl.X * -1) * texScale, 0);
            }

            var result = new RoofDrawGroup();

            if (numPrimitives > 0)
            {
                result.VertexBuffer = new VertexBuffer(device, typeof(TerrainVertex), Geom.Length, BufferUsage.None);
                if (Geom.Length > 0)
                {
                    result.VertexBuffer.SetData(Geom);
                }

                result.IndexBuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits, sizeof(int) * Indexes.Length, BufferUsage.None);
                if (Geom.Length > 0)
                {
                    result.IndexBuffer.SetData(Indexes);
                }
            }

            result.NumPrimitives = numPrimitives;

            Drawgroups[level - 2] = result;
        }
 /// <summary>
 /// Generates vertices for a terrain patch
 /// </summary>
 /// <param name="patch">Terrain patch</param>
 /// <param name="res">Terrain patch resolution</param>
 /// <param name="firstVertex">Pointer to terrain vertices</param>
 /// <param name="error">Terrain patch error output here</param>
 public unsafe void GenerateTerrainPatchVertices( ITerrainPatch patch, int res, TerrainVertex* firstVertex, out float error )
 {
     m_Gen.GenerateVertices( patch.LocalOrigin, patch.LocalUStep, patch.LocalVStep, res, res, patch.Uv, patch.UvResolution, firstVertex, out error );
 }
Example #21
0
        public Unit GenerateBlock(int X, int Y)
        {
            int x = 0;
            int y = 0;

            BlockTitle = "";
            Unit block = new Unit();

            block.X = X;
            block.Y = Y;
            CreateGrid();
            SetHeights(X, Y);
            SetupVertexField(_heightmap);
            SetTileID(50, 50, 1);
            SetTileColour(51, 50, Color.Red);
            SetTileColour(49, 50, Color.Green);

            /*
             * for (x = 0; x < BlockSize; x++)
             *  for (y = 0; y < BlockSize; y++)
             *  {
             *      SetTileID(x, y, 2);
             *  }
             * //*/
            CalculateNormals();
            block.indices   = _indices2;
            block.vertices  = _vertices;// new TerrainVertex[(BlockSize * 2 ) * (BlockSize * 2 )];
            block.indices   = _indices;
            block.vertices  = new TerrainVertex[(BlockSize * 2) * (BlockSize * 2)];
            block.heightmap = new float[BlockSize + 1, BlockSize + 1];
            TerrainVertex current;

            for (x = 0; x < BlockSize + 1; x++)
            {
                for (y = 0; y < BlockSize + 1; y++)
                {
                    block.heightmap[x, y] = _heightmap[x + 1, y + 1];
                    // block.vertices[x + y * BlockSize].Position.X = x;
                    //block.vertices[x + y * BlockSize].Position.Z = y;
                }
            }


            for (x = 0; x < BlockSize; x++)
            {
                for (y = 0; y < BlockSize; y++)
                {
                    //*
                    block.vertices[(y * 4 * BlockSize) + (x * 4) + 0] = _vertices[(1 + y) * 4 * (BlockSize + 2) + (1 + x) * 4 + 0];
                    block.vertices[(y * 4 * BlockSize) + (x * 4) + 1] = _vertices[(1 + y) * 4 * (BlockSize + 2) + (1 + x) * 4 + 1];
                    block.vertices[(y * 4 * BlockSize) + (x * 4) + 2] = _vertices[(1 + y) * 4 * (BlockSize + 2) + (1 + x) * 4 + 2];
                    block.vertices[(y * 4 * BlockSize) + (x * 4) + 3] = _vertices[(1 + y) * 4 * (BlockSize + 2) + (1 + x) * 4 + 3];

                    /*
                     * block.vertices[(y * 4 * BlockSize) + (x * 4) + 0].Position.X = x;
                     * block.vertices[(y * 4 * BlockSize) + (x * 4) + 1].Position.X = x+1;
                     * block.vertices[(y * 4 * BlockSize) + (x * 4) + 2].Position.X = x;
                     * block.vertices[(y * 4 * BlockSize) + (x * 4) + 3].Position.X = x+1;
                     * block.vertices[(y * 4 * BlockSize) + (x * 4) + 0].Position.Z = y;
                     * block.vertices[(y * 4 * BlockSize) + (x * 4) + 1].Position.Z = y;
                     * block.vertices[(y * 4 * BlockSize) + (x * 4) + 2].Position.Z = y+1;
                     * block.vertices[(y * 4 * BlockSize) + (x * 4) + 3].Position.Z = y+1;
                     * //*/
                }
            }

            TerrainVertex probe1 = block.vertices[(y - 1) * 4 * BlockSize + (x - 1) * 4];
            TerrainVertex probe2 = block.vertices[(y - 1) * 4 * BlockSize + (x - 2) * 4];
            TerrainVertex probe3 = block.vertices[(y - 1) * 4 * BlockSize + (x - 1) * 4 + 1];

            // Console.Write("^00A000 Generated block at " + X.ToString() + "," + Y.ToString() + ".");
            block.Name = BlockTitle;
            return(block);
        }
Example #22
0
        public Tuple <TerrainVertex[], int[], int> MeshRectData(int level)
        {
            var rects = RoofRects[level - 2];

            if (rects == null)
            {
                return(null);
            }

            var numQuads = rects.Count * 4; //4 sides for each roof rectangle

            TerrainVertex[] Geom    = new TerrainVertex[numQuads * 4];
            int[]           Indexes = new int[numQuads * 6];

            var numPrimitives = (numQuads * 2);
            int geomOffset    = 0;
            int indexOffset   = 0;

            foreach (var rect in rects)
            {
                //determine roof height of the smallest edge. This height will be used on all edges
                var height = Math.Min(rect.x2 - rect.x1, rect.y2 - rect.y1) / 2;
                //    /    \
                //   /      \
                //  /________\  Draw 4 segments like this. two segments will have the top middle section so short it will not appear.

                var heightMod = height / 400f;
                var pitch     = RoofPitch;
                var tl        = ToWorldPos(rect.x1, rect.y1, 0, level, pitch) + new Vector3(0, heightMod, 0);
                var tr        = ToWorldPos(rect.x2, rect.y1, 0, level, pitch) + new Vector3(0, heightMod, 0);
                var bl        = ToWorldPos(rect.x1, rect.y2, 0, level, pitch) + new Vector3(0, heightMod, 0);
                var br        = ToWorldPos(rect.x2, rect.y2, 0, level, pitch) + new Vector3(0, heightMod, 0);

                //middle vertices. todo: height modifier (not hard)

                var m_tl = ToWorldPos(rect.x1 + height, rect.y1 + height, height, level, pitch) + new Vector3(0, heightMod, 0);
                var m_tr = ToWorldPos(rect.x2 - height, rect.y1 + height, height, level, pitch) + new Vector3(0, heightMod, 0);
                var m_bl = ToWorldPos(rect.x1 + height, rect.y2 - height, height, level, pitch) + new Vector3(0, heightMod, 0);
                var m_br = ToWorldPos(rect.x2 - height, rect.y2 - height, height, level, pitch) + new Vector3(0, heightMod, 0);

                Color   topCol   = Color.White; //Color.Lerp(Color.White, new Color(175, 175, 175), pitch);
                Color   rightCol = Color.White; //Color.White;
                Color   btmCol   = Color.White; //Color.Lerp(Color.White, new Color(200, 200, 200), pitch);
                Color   leftCol  = Color.White; //Color.Lerp(Color.White, new Color(150, 150, 150), pitch);
                Vector4 darken   = new Vector4(0.8f, 0.8f, 0.8f, 1.0f);

                //quad as two tris
                for (int j = 0; j < 16; j += 4)
                {
                    Indexes[indexOffset++] = (geomOffset + 2) + j;
                    Indexes[indexOffset++] = (geomOffset + 1) + j;
                    Indexes[indexOffset++] = geomOffset + j;

                    Indexes[indexOffset++] = geomOffset + j;
                    Indexes[indexOffset++] = (geomOffset + 3) + j;
                    Indexes[indexOffset++] = (geomOffset + 2) + j;
                }

                var     n1       = -Vector3.Normalize(Vector3.Cross(tl - tr, tr - m_tr));
                var     n1m      = Vector3.Normalize(n1 + Vector3.Up);
                Vector2 texScale = new Vector2(2 / 3f, 1f);
                Geom[geomOffset++] = new TerrainVertex(tl, topCol.ToVector4(), new Vector2(tl.X, tl.Z * -1) * texScale, 0, n1);
                Geom[geomOffset++] = new TerrainVertex(tr, topCol.ToVector4(), new Vector2(tr.X, tr.Z * -1) * texScale, 0, n1);
                Geom[geomOffset++] = new TerrainVertex(m_tr, topCol.ToVector4(), new Vector2(m_tr.X, m_tr.Z * -1) * texScale, 0, n1m);
                Geom[geomOffset++] = new TerrainVertex(m_tl, topCol.ToVector4(), new Vector2(m_tl.X, m_tl.Z * -1) * texScale, 0, n1m);

                n1  = -Vector3.Normalize(Vector3.Cross(tr - br, br - m_br));
                n1m = Vector3.Normalize(n1 + Vector3.Up);
                Geom[geomOffset++] = new TerrainVertex(tr, rightCol.ToVector4(), new Vector2(tr.Z, tr.X) * texScale, 0, n1);
                Geom[geomOffset++] = new TerrainVertex(br, rightCol.ToVector4(), new Vector2(br.Z, br.X) * texScale, 0, n1);
                Geom[geomOffset++] = new TerrainVertex(m_br, rightCol.ToVector4(), new Vector2(m_br.Z, m_br.X) * texScale, 0, n1m);
                Geom[geomOffset++] = new TerrainVertex(m_tr, rightCol.ToVector4(), new Vector2(m_tr.Z, m_tr.X) * texScale, 0, n1m);

                n1  = -Vector3.Normalize(Vector3.Cross(br - bl, bl - m_bl));
                n1m = Vector3.Normalize(n1 + Vector3.Up);
                Geom[geomOffset++] = new TerrainVertex(br, btmCol.ToVector4(), new Vector2(br.X, br.Z) * texScale, 0, n1);
                Geom[geomOffset++] = new TerrainVertex(bl, btmCol.ToVector4(), new Vector2(bl.X, bl.Z) * texScale, 0, n1);
                Geom[geomOffset++] = new TerrainVertex(m_bl, btmCol.ToVector4(), new Vector2(m_bl.X, m_bl.Z) * texScale, 0, n1m);
                Geom[geomOffset++] = new TerrainVertex(m_br, btmCol.ToVector4(), new Vector2(m_br.X, m_br.Z) * texScale, 0, n1m);

                n1  = -Vector3.Normalize(Vector3.Cross(bl - tl, tl - m_tl));
                n1m = Vector3.Normalize(n1 + Vector3.Up);
                Geom[geomOffset++] = new TerrainVertex(bl, leftCol.ToVector4(), new Vector2(bl.Z, bl.X * -1) * texScale, 0, n1);
                Geom[geomOffset++] = new TerrainVertex(tl, leftCol.ToVector4(), new Vector2(tl.Z, tl.X * -1) * texScale, 0, n1);
                Geom[geomOffset++] = new TerrainVertex(m_tl, leftCol.ToVector4(), new Vector2(m_tl.Z, m_tl.X * -1) * texScale, 0, n1m);
                Geom[geomOffset++] = new TerrainVertex(m_bl, leftCol.ToVector4(), new Vector2(m_bl.Z, m_bl.X * -1) * texScale, 0, n1m);
            }

            return(new Tuple <TerrainVertex[], int[], int>(Geom, Indexes, numPrimitives));
        }
Example #23
0
        public void RegenTerrain(GraphicsDevice device, WorldState world, Blueprint blueprint)
        {
            if (VertexBuffer != null)
            {
                IndexBuffer.Dispose();
                BladeIndexBuffer.Dispose();
                VertexBuffer.Dispose();
            }

            /** Convert rectangle to world units **/
            var quads = Size.Width;

            var quadWidth  = WorldSpace.GetWorldFromTile((float)Size.Width / (float)quads);
            var quadHeight = WorldSpace.GetWorldFromTile((float)Size.Height / (float)quads);
            var numQuads   = quads * quads;

            TerrainVertex[] Geom         = new TerrainVertex[numQuads * 4];
            int[]           Indexes      = new int[numQuads * 6];
            int[]           BladeIndexes = new int[numQuads * 6];
            NumPrimitives = (numQuads * 2);

            int geomOffset   = 0;
            int indexOffset  = 0;
            int bindexOffset = 0;

            var offsetX = WorldSpace.GetWorldFromTile(Size.X);
            var offsetY = WorldSpace.GetWorldFromTile(Size.Y);

            for (var y = 0; y < quads; y++)
            {
                for (var x = 0; x < quads; x++)
                {
                    var tl = new Vector3(offsetX + (x * quadWidth), 0.0f, offsetY + (y * quadHeight));
                    var tr = new Vector3(tl.X + quadWidth, 0.0f, tl.Z);
                    var bl = new Vector3(tl.X, 0.0f, tl.Z + quadHeight);
                    var br = new Vector3(tl.X + quadWidth, 0.0f, tl.Z + quadHeight);

                    Indexes[indexOffset++] = geomOffset;
                    Indexes[indexOffset++] = (geomOffset + 1);
                    Indexes[indexOffset++] = (geomOffset + 2);

                    Indexes[indexOffset++] = (geomOffset + 2);
                    Indexes[indexOffset++] = (geomOffset + 3);
                    Indexes[indexOffset++] = geomOffset;

                    short tx = (short)(x + 1), ty = (short)(y + 1);

                    if (blueprint.GetFloor(tx, ty, 1).Pattern == 0 &&
                        (blueprint.GetWall(tx, ty, 1).Segments & (WallSegments.HorizontalDiag | WallSegments.VerticalDiag)) == 0)
                    {
                        BladeIndexes[bindexOffset++] = geomOffset;
                        BladeIndexes[bindexOffset++] = (geomOffset + 1);
                        BladeIndexes[bindexOffset++] = (geomOffset + 2);

                        BladeIndexes[bindexOffset++] = (geomOffset + 2);
                        BladeIndexes[bindexOffset++] = (geomOffset + 3);
                        BladeIndexes[bindexOffset++] = geomOffset;
                    }

                    Color tlCol = Color.Lerp(LightGreen, LightBrown, GrassState[y * quads + x]);
                    Color trCol = Color.Lerp(LightGreen, LightBrown, GrassState[y * quads + ((x + 1) % quads)]);
                    Color blCol = Color.Lerp(LightGreen, LightBrown, GrassState[((y + 1) % quads) * quads + x]);
                    Color brCol = Color.Lerp(LightGreen, LightBrown, GrassState[((y + 1) % quads) * quads + ((x + 1) % quads)]);

                    Geom[geomOffset++] = new TerrainVertex(tl, tlCol.ToVector4(), new Vector2(x * 64, y * 64), GrassState[y * quads + x]);
                    Geom[geomOffset++] = new TerrainVertex(tr, trCol.ToVector4(), new Vector2((x + 1) * 64, y * 64), GrassState[y * quads + ((x + 1) % quads)]);
                    Geom[geomOffset++] = new TerrainVertex(br, brCol.ToVector4(), new Vector2((x + 1) * 64, (y + 1) * 64), GrassState[((y + 1) % quads) * quads + ((x + 1) % quads)]);
                    Geom[geomOffset++] = new TerrainVertex(bl, blCol.ToVector4(), new Vector2(x * 64, (y + 1) * 64), GrassState[((y + 1) % quads) * quads + x]);
                }
            }

            var rand = new Random();

            VertexBuffer = new VertexBuffer(device, typeof(TerrainVertex), Geom.Length, BufferUsage.None);
            VertexBuffer.SetData(Geom);

            IndexBuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits, sizeof(int) * Indexes.Length, BufferUsage.None);
            IndexBuffer.SetData(Indexes);

            BladePrimitives = (bindexOffset / 3);

            BladeIndexBuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits, sizeof(int) * Indexes.Length, BufferUsage.None);
            BladeIndexBuffer.SetData(BladeIndexes);
            GeomLength = Geom.Length;
        }
Example #24
0
        private static StaticBuffer <TerrainVertex> CreateVertexBuffer(
            GraphicsDevice graphicsDevice,
            ResourceUploadBatch uploadBatch,
            HeightMap heightMap,
            Int32Rect patchBounds,
            ushort[] indices,
            out BoundingBox boundingBox,
            out Triangle[] triangles)
        {
            var numVertices = patchBounds.Width * patchBounds.Height;

            var vertices = new TerrainVertex[numVertices];
            var points   = new Vector3[numVertices];

            var vertexIndex = 0;

            for (var y = patchBounds.Y; y < patchBounds.Y + patchBounds.Height; y++)
            {
                for (var x = patchBounds.X; x < patchBounds.X + patchBounds.Width; x++)
                {
                    var position = heightMap.GetPosition(x, y);
                    points[vertexIndex]     = position;
                    vertices[vertexIndex++] = new TerrainVertex
                    {
                        Position = position,
                        Normal   = heightMap.Normals[x, y],
                        UV       = new Vector2(x, y)
                    };
                }
            }

            boundingBox = BoundingBox.CreateFromPoints(points);

            triangles = new Triangle[(patchBounds.Width - 1) * (patchBounds.Height) * 2];

            var triangleIndex = 0;
            var indexIndex    = 0;

            for (var y = 0; y < patchBounds.Height - 1; y++)
            {
                for (var x = 0; x < patchBounds.Width - 1; x++)
                {
                    // Triangle 1
                    triangles[triangleIndex++] = new Triangle
                    {
                        V0 = points[indices[indexIndex++]],
                        V1 = points[indices[indexIndex++]],
                        V2 = points[indices[indexIndex++]]
                    };

                    // Triangle 2
                    triangles[triangleIndex++] = new Triangle
                    {
                        V0 = points[indices[indexIndex++]],
                        V1 = points[indices[indexIndex++]],
                        V2 = points[indices[indexIndex++]]
                    };
                }
            }

            return(StaticBuffer.Create(
                       graphicsDevice,
                       uploadBatch,
                       vertices));
        }
Example #25
0
        public PatchContent Build()
        {
            #region Local vertex buffer

            // create local vertex buffer for patch
            int numVertices = _patchSize * _patchSize;
            VertexBufferContent localVertexBuffer = new VertexBufferContent(numVertices);

            // fill vertex buffer
            TerrainVertex[] vertices = new TerrainVertex[numVertices];

            int nStartX = _patchOffsetX * (_patchSize - 1);
            int nStartY = _patchOffsetY * (_patchSize - 1);
            int nEndX = nStartX + _patchSize;
            int nEndY = nStartY + _patchSize;

            float fMinZ = float.MaxValue, fMaxZ = float.MinValue;
            int index = 0;
            for (int y = nStartY; y < nEndY; y++)
            {
                for (int x = nStartX; x < nEndX; x++)
                {
                    // write local data
                    float fZ = _heightMap[x, y];

                    if (fZ < fMinZ) fMinZ = fZ;
                    if (fZ > fMaxZ) fMaxZ = fZ;

                    Vector2 texCoords1 = new Vector2(x / (float) (_heightMap.Width - 1), y / (float) (_heightMap.Height - 1));
                    Vector2 texCoords2 = texCoords1 * _detailTextureTiling;

                    vertices[index++] = new TerrainVertex(
                        new Vector3(x * _horizontalScale, fZ, y * _horizontalScale),
                        new Vector3(0, 1, 0),
                        texCoords1,
                        texCoords2);
                }
            }

            localVertexBuffer.Write(0, VertexBufferContent.SizeOf(typeof(TerrainVertex)), vertices);
            localVertexBuffer.VertexDeclaration = new VertexDeclarationContent();
            foreach (VertexElement vertexElement in TerrainVertex.VertexDeclaration.GetVertexElements())
                localVertexBuffer.VertexDeclaration.VertexElements.Add(vertexElement);

            #endregion

            LevelContent[] levels = new LevelContent[_numLevels];
            for (int i = 0; i < _numLevels; i++)
            {
                LevelContentBuilder levelContentBuilder = new LevelContentBuilder(_heightMap, _patchSize, _numLevels, i, nStartX,
                    nEndX, nStartY, nEndY);
                levels[i] = levelContentBuilder.Build();
            }

            #region Bounding box, centre, and offset

            BoundingBox boundingBox = new BoundingBox(
                new Vector3(nStartX * _horizontalScale, fMinZ, nStartY * _horizontalScale),
                new Vector3(nEndX * _horizontalScale, fMaxZ, nEndY * _horizontalScale));

            float fAverageZ = (fMinZ + fMaxZ) / 2.0f;

            Vector3 center = new Vector3(
                (nStartX + ((_patchSize - 1) / 2.0f)) * _horizontalScale,
                fAverageZ,
                (nStartY + ((_patchSize - 1) / 2.0f)) * _horizontalScale);

            Vector2 offset = new Vector2(
                (_patchOffsetX * (_patchSize - 1)) * _horizontalScale,
                (_patchOffsetY * (_patchSize - 1)) * _horizontalScale);

            #endregion

            return new PatchContent
            {
                VertexBuffer = localVertexBuffer,
                Levels = levels,
                BoundingBox  =boundingBox,
                Center = center,
                Offset = offset
            };
        }
Example #26
0
        //this function calculates the actual height/colour/etc of a vertex.
        //this should be corrected to generate from a WorldMap.

        TerrainVertex GainVertex2(int X, int Y, int DX, int DY, int Seed = 0)
        {
            TerrainVertex v = new TerrainVertex();

            float One32nd = 1.0f / 64.0f;

            v.Position.X = X;
            v.Position.Z = Y;
            int MapX = X + DX * (BlockSize);
            int MapY = Y + DY * (BlockSize);
            // Z = 0;
            // v.Position.Y= noise.PerlinNoise3F(MapX, MapY, Z, 1, One32nd / 1, One32nd / 1, One32nd / 1);
            //*
            //  v.Position.Y *= 10;
            //v.Position.Y += 6;
            // v.Position.Y *= 10;
            float to256 = 1 / 256;
            float H     = 0.0f;

            Simplex.Seed = this.Seed;
            MapY        += 65535;
            MapX        += 65535;
            //land/water scaling
            H = Simplex.CalcPixel2D(MapX, MapY, 1f / 16384f) - 35f;
            //values from -35 to 220ish.
            H += (Simplex.CalcPixel2D(MapX, MapY, 1f / 256) / 16);
            //+-16 variation, values -51..246
            float Hills = Simplex.CalcPixel2D(MapX, MapY, 1f / 256) - 128;

            Hills /= 16;
            //+-8 noise
            //*/
            v.Position.Y = H;
            float Temp = Simplex.CalcPixel2D(MapX, MapY, 1f / 4024f);
            //0 to 255 temp
            int Blend1 = Math.Min((int)(Temp * 2), 160);
            int Blend2 = Math.Min((510 - (int)(Temp * 2)), 200);

            Color grass = new Color(Blend1, Blend2, 0);
            Color sea   = new Color(0, 50, 255);
            Color Snow  = new Color(245, 245, 255);
            Color sand  = new Color(200, 200, 100);
            Color sand2 = new Color(150, 150, 50);

            sea     = sand;
            v.Color = grass;
            // v.Color =
            float BeachRange     = 12;
            float SnowRange      = 185;
            float GroundBaseline = WaterHeight + BeachRange;

            if (H < WaterHeight)
            {
                v.MultiTexData.Z = 1;
                v.Color          = sea;
            }
            if (H > WaterHeight && H < GroundBaseline)
            {
                float dif = H - WaterHeight;
                dif             /= BeachRange;
                dif              = (float)Math.Pow(dif, 7.3);
                v.Position.Y     = WaterHeight + dif * BeachRange;
                v.Color          = sand;
                v.MultiTexData.Z = 1;
            }

            if (H > GroundBaseline)
            {
                unchecked
                {
                    Simplex.Seed = Simplex.Seed ^ (int)0xFFFFFFFF;
                }
                //hill horizontal scale
                float random1 = Simplex.CalcPixel2D(MapX + 1112, MapY + 13123, 2f) / 512f;
                float random2 = Simplex.CalcPixel2D(MapX + 1112, MapY + 13123, 1f) / 1024f;

                float ground    = Simplex.CalcPixel2D(MapX + 1112, MapY + 13123, 0.0006125f / 1f);
                float beachdist = H - GroundBaseline;
                float evenness  = 16f;
                ground    /= 256f;
                ground     = (float)(Math.Pow(ground, 4.4));
                ground    *= 256f;
                beachdist /= evenness;
                beachdist  = MathHelper.Clamp(beachdist, 0.0f, 1.0f);
                float finalground = GroundBaseline + ground * beachdist + Hills * beachdist + (random1 + random2) * beachdist;


                v.Position.Y = finalground;// + random1 + random2;

                v.MultiTexData.Z = (float)Math.Pow((float)MathHelper.Clamp((((Temp / 2f) - finalground + 76f) / 100f), 0f, 1f), 3f);
                if (v.MultiTexData.Z < 0.2f)
                {
                    v.MultiTexData.Z = 0f;
                }
                if (finalground > SnowRange)
                {
                    v.Color          = Snow;
                    v.MultiTexData.Z = 0.20f;
                }
            }
            //  v.Color = new Color(Math.Min(255, (int)H), 0, 0);
            v.TextureCoordinate.X = X / 4f;
            v.TextureCoordinate.Y = Y / 4f;
            v.Normal = new Vector3(0, 0, 0);
            // v.Position.Y = 6;
            return(v);
        }
Example #27
0
        /// <summary>
        ///  This implements the method in resource, to load the mesh data(vertex buffer, index buffer)
        ///  of this terrain tile.
        /// </summary>
        protected override void load()
        {
            // 读取地形数据
            // This line will load the terrain data in this tile.
            float[] data = TerrainData.Instance.GetData(tileX, tileY, terrEdgeSize);

            float radtc = MathEx.Degree2Radian(tileCol);
            float radtl = MathEx.Degree2Radian(tileLat);

            float radSpan = MathEx.Degree2Radian(10);

            int vertexCount = terrEdgeSize * terrEdgeSize;
            int terrEdgeLen = terrEdgeSize - 1;

            if (terrEdgeSize == 33)
            {
                material.SetEffect(EffectManager.Instance.GetModelEffect(TerrainEffect33Factory.Name));
            }
            else
            {
                material.SetEffect(EffectManager.Instance.GetModelEffect(TerrainEffect17Factory.Name));
            }

            #region 顶点数据

            vtxDecl = factory.CreateVertexDeclaration(TerrainVertex.Elements);

            vtxBuffer = factory.CreateVertexBuffer(vertexCount, vtxDecl, BufferUsage.WriteOnly);

            TerrainVertex[] vtxArray = new TerrainVertex[vertexCount];


            float cellAngle = radSpan / (float)terrEdgeLen;
            #region 计算顶点坐标
            // Caluclate the position of each vertex

            // i为纬度方向
            // i is in the latitude direction
            for (int i = 0; i < terrEdgeSize; i++)
            {
                // j为经度方向
                // j is in the longitude direction
                for (int j = 0; j < terrEdgeSize; j++)
                {
                    Vector3 pos = PlanetEarth.GetPosition(radtc + j * cellAngle, radtl - i * cellAngle);

                    int index = i * terrEdgeSize + j;

                    // 计算海拔高度
                    // calculate the elevation
                    float height = (data[index] - TerrainMeshManager.PostZeroLevel) * TerrainMeshManager.PostHeightScale;

                    //if (height > 0)
                    //{
                    //    height = (height - 0) * TerrainMeshManager.PostHeightScale;
                    //}
                    //else
                    //{
                    //    height *= TerrainMeshManager.PostHeightScale;
                    //    height -= 10;
                    //    //if (height < -30)
                    //    //    height = -30;
                    //}

                    Vector3 normal = pos;
                    normal.Normalize();
                    vtxArray[index].Position = pos + normal * height;

                    // this index is used to generate detailed texture coordinate in vertex shader
                    vtxArray[index].Index = index;


                    // map the texture coordinate for global texturing
                    float curCol = radtc + j * cellAngle;
                    float curLat = radSpan + radtl - i * cellAngle;

                    curCol += MathEx.PIf;
                    curLat -= MathEx.Degree2Radian(10);

                    vtxArray[index].u = 0.5f * curCol / MathEx.PIf;
                    vtxArray[index].v = (-curLat + MathEx.PiOver2) / MathEx.PIf;
                }
            }
            #endregion

            #endregion

            #region 索引数据
            SharedIndexData sindexData = TerrainMeshManager.Instance.GetIndexData(terrEdgeSize);
            indexBuffer = sindexData.Index;
            #endregion

            #region 构造GeomentryData
            defGeometryData = new GeomentryData();
            defGeometryData.VertexDeclaration = vtxDecl;

            defGeometryData.VertexSize   = TerrainVertex.Size;
            defGeometryData.VertexBuffer = vtxBuffer;
            defGeometryData.IndexBuffer  = indexBuffer;
            defGeometryData.PrimCount    = indexBuffer.IndexCount / 3;
            defGeometryData.VertexCount  = terrEdgeSize * terrEdgeSize;

            defGeometryData.PrimitiveType = RenderPrimitiveType.TriangleList;

            defGeometryData.BaseVertex = 0;

            #endregion

            vtxBuffer.SetData <TerrainVertex>(vtxArray);
        }