/// <summary> /// Triangulate an height map and generates a base of given height /// </summary> /// <param name="heightMap">Gridded set of points. Corrdinates can differ, /// but height map should be organized a set of rows and columns</param> /// <returns>TriangulationResult</returns> public Triangulation GenerateTriangleMesh_Boxed(HeightMap heightMap , BoxBaseThickness thickness, float zValue) { Triangulation triangulationResult = new Triangulation(); triangulationResult.NumIndices = ((heightMap.Width - 1) * 6) * (heightMap.Height - 1); // height map plane triangulationResult.NumIndices += ((heightMap.Width - 1) * 6) * 2; // two sides triangulationResult.NumIndices += ((heightMap.Height - 1) * 6) * 2; // two sizes triangulationResult.NumIndices += 6; // bottom (two big triangles) // Regular triangulation triangulationResult.Positions = heightMap.Coordinates; triangulationResult.Indices = TriangulateHeightMap_Internal(heightMap, true); // Generate box vertices and trianglation AddHeightMapBase(triangulationResult, heightMap, thickness, zValue); return(triangulationResult); }
private void AddHeightMapBase(Triangulation triangulation, HeightMap heightMap, BoxBaseThickness thickness, float zValue) { // bake coordinates to avoid executing the coords transfrom pipeline var coords = heightMap.Coordinates.ToList(); int capacity = heightMap.Width * 2 + (heightMap.Height - 2) * 2; var basePoints = new List <GeoPoint>(capacity); var baseIndexes = new List <int>(capacity); float baseElevation = 0; switch (thickness) { case BoxBaseThickness.FromMinimumPoint: baseElevation = (float)coords.Min(p => p.Elevation).GetValueOrDefault(0) - zValue; break; default: case BoxBaseThickness.FixedElevation: baseElevation = zValue; break; } // x : 0 => width // y : 0 int baseIndex0 = coords.Count; int baseIndex = baseIndex0; for (int x = 0; x < heightMap.Width - 1; x++) { var pBase = coords[x].Clone(); pBase.Elevation = baseElevation; basePoints.Add(pBase); baseIndexes.Add(x); baseIndexes.Add(baseIndex + 1); baseIndexes.Add(baseIndex); baseIndexes.Add(x + 1); baseIndexes.Add(baseIndex + 1); baseIndexes.Add(x); baseIndex++; } // x : width // y : 0 => height // for (int y = 0; y < heightMap.Height - 1; y++) { int x = heightMap.Width - 1; int index = x + y * heightMap.Width; var pBase = coords[index].Clone(); pBase.Elevation = baseElevation; basePoints.Add(pBase); baseIndexes.Add(x + y * heightMap.Width); baseIndexes.Add(baseIndex + 1); baseIndexes.Add(baseIndex); baseIndexes.Add(x + y * heightMap.Width); baseIndexes.Add(x + (y + 1) * heightMap.Width); baseIndexes.Add(baseIndex + 1); baseIndex++; } //// x : width => 0 // y : height for (int x = heightMap.Width - 1; x > 0; x--) { int index = x + (heightMap.Height - 1) * heightMap.Width; var pBase = coords[index].Clone(); pBase.Elevation = baseElevation; basePoints.Add(pBase); baseIndexes.Add(index); baseIndexes.Add(index - 1); baseIndexes.Add(baseIndex); baseIndexes.Add(index - 1); baseIndexes.Add(baseIndex + 1); baseIndexes.Add(baseIndex); baseIndex++; } //// x : 0 // y : height => 0 for (int y = heightMap.Height - 1; y > 0; y--) { int x = 0; int index = x + y * heightMap.Width; var pBase = coords[index].Clone(); pBase.Elevation = baseElevation; basePoints.Add(pBase); // last base position is the first base generated int nextBaseIndex = baseIndex + 1 > baseIndex0 + capacity - 1 ? baseIndex0 : baseIndex + 1; baseIndexes.Add(x + y * heightMap.Width); baseIndexes.Add(nextBaseIndex); baseIndexes.Add(baseIndex); baseIndexes.Add(x + y * heightMap.Width); baseIndexes.Add(x + (y - 1) * heightMap.Width); baseIndexes.Add(nextBaseIndex); baseIndex++; } // base (2 big triangles) baseIndexes.Add(baseIndex0); baseIndexes.Add(baseIndex0 + heightMap.Width - 1); baseIndexes.Add(baseIndex0 + heightMap.Width - 1 + heightMap.Height - 1); baseIndexes.Add(baseIndex0); baseIndexes.Add(baseIndex0 + heightMap.Width - 1 + heightMap.Height - 1); baseIndexes.Add(baseIndex0 + 2 * (heightMap.Width - 1) + heightMap.Height - 1); triangulation.Positions = triangulation.Positions.Concat(basePoints); triangulation.NumPositions += basePoints.Count; triangulation.Indices = triangulation.Indices.Concat(baseIndexes); }
/// <summary> /// Generate a triangle mesh from supplied height map, triangulating and optionaly mapping UVs /// and generate sides and bottom (like a box where the top is the triangulated height map) /// </summary> /// <param name="heightMap">Height map.</param> /// <param name="thickness">Determines how box height will be calculated</param> /// <param name="zValue">Z value to apply for box calculation</param> /// <returns></returns> public MeshPrimitive GenerateTriangleMesh_Boxed(HeightMap heightMap, BoxBaseThickness thickness = BoxBaseThickness.FixedElevation, float zValue = 0f) { Triangulation triangulation = _meshService.GenerateTriangleMesh_Boxed(heightMap, thickness, zValue); return(GenerateTriangleMesh(triangulation)); }