protected override TerrainMeshData RescaleMeshHeight(TerrainMeshData referenceMeshData) { float scale = _metadata.HeightScale / TerrainModelScale; float radius = _metadata.Radius; Vector3[] referenceVertices = referenceMeshData.Vertices; int vertexCount = referenceVertices.Length; Vector3[] rescaledVertices = new Vector3[vertexCount]; for (int i = 0; i < vertexCount; i++) { Vector3 vertex = referenceVertices[i]; // Calculate new distance float distance = vertex.magnitude; float newDistance = (distance - radius) * scale + radius; // Apply new distance vertex *= newDistance / distance; // Store vertex in new array. rescaledVertices[i] = vertex; } return(new TerrainMeshData() { Vertices = rescaledVertices // TODO Normals }); }
// TODO Use a struct or class to pass DEM metadata (ie. scale) to the GenerateMesh methods. /// <summary> /// Generates the mesh data and store it in the member variable. /// </summary> protected override void Generate() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // TODO Add support other image types if necessary. // Create and execute task to convert first image into an RGBImage object. // The task can be executed syncronously in the same thread since Generate() // is called outside of the main thread. IntensityImage baseImage = new LoadIntensityImageFromFileTask(_demFilePaths[0]).ExecuteInCurrentThread(); Debug.Log($"Took {stopwatch.ElapsedMilliseconds}ms to read DEM image file."); // If there are more files to process, then load and merge each image. for (int i = 1; i < _demFilePaths.Length; i++) { // Load the additional image. IntensityImage image = new LoadIntensityImageFromFileTask(_demFilePaths[i]).ExecuteInCurrentThread(); // Merge the images together. try { baseImage.Merge(image, -32768); // NOTE: -32768 happens to be the "blank" value for the global DEM (and probably // any other files in 16-bit integer). This may not work for files in other formats. // Update if necessary. } catch (Exception e) { Debug.LogError(e.Message); continue; } } TerrainMeshData[] meshData = new TerrainMeshData[_metadata.TotalLodLevels]; for (int lodLevel = 0; lodLevel <= _metadata.LodLevels; lodLevel++) { int downsample = 1 << (_metadata.BaseDownsample + lodLevel); meshData[lodLevel] = GenerateForLod(baseImage, downsample); } if (_metadata.GenerateAdditionalPhysicsLod) { meshData[meshData.Length - 1] = GenerateForLod(baseImage, 1 << _metadata.PhysicsDownsample); } _progress = 1.0f; _meshData = meshData; }
protected override TerrainMeshData RescaleMeshHeight(TerrainMeshData referenceMeshData) { float scale = _metadata.HeightScale / TerrainModelScale; float radius = _metadata.Radius; Vector3 min = new Vector3(float.PositiveInfinity, 0, 0); Vector3[] referenceVertices = referenceMeshData.Vertices; int vertexCount = referenceVertices.Length; Vector3[] rescaledVertices = new Vector3[vertexCount]; for (int i = 0; i < vertexCount; i++) { // Undo radius offset Vector3 vertex = referenceVertices[i] + new Vector3(radius, 0, 0); // Calculate new distance float distance = vertex.magnitude; float newDistance = (distance - radius) * scale + radius; // Apply new distance vertex *= newDistance / distance; // Redo radius offset vertex -= new Vector3(radius, 0, 0); // Store vertex in new array. rescaledVertices[i] = vertex; // Keep track of minimum. if (vertex.x < min.x) { min = vertex; } } Vector3[] referenceExtraVertices = referenceMeshData.ExtraVertices; int extraVertexCount = referenceExtraVertices.Length; Vector3[] rescaledExtraVertices = new Vector3[extraVertexCount]; for (int i = 0; i < extraVertexCount; i++) { Vector3 vertex; // Only the first half of the vertex follows the terrain coutours; // the second half is the flat base. if (i >= extraVertexCount / 2) { vertex = referenceExtraVertices[i]; rescaledExtraVertices[i] = new Vector3(min.x, vertex.y, vertex.z); continue; } // Undo radius offset vertex = referenceExtraVertices[i] + new Vector3(radius, 0, 0); // Calculate new distance float distance = vertex.magnitude; float newDistance = (distance - radius) * scale + radius; // Apply new distance vertex *= newDistance / distance; // Redo radius offset vertex -= new Vector3(radius, 0, 0); // Store vertex in new array. rescaledExtraVertices[i] = vertex; } return(new TerrainMeshData() { Vertices = rescaledVertices, ExtraVertices = rescaledExtraVertices, MinimumVertex = min // TODO Normals }); }
protected override void Generate() { float latIncrement = _boundingBox.LatSwing / (LatLongVertCount - 1); float lonIncrement = _boundingBox.LonSwing / (LatLongVertCount - 1); Vector3[] verts = new Vector3[LatLongVertCount * LatLongVertCount]; Vector2[] uvs = new Vector2[LatLongVertCount * LatLongVertCount]; Vector3[] edgeVerts = new Vector3[8 * (LatLongVertCount - 1) + 2]; Vector2 latLongOffset = BoundingBoxUtils.MedianLatLon(_boundingBox); Vector3 min = new Vector3(float.PositiveInfinity, 0, 0); int yIndex = 0, vertIndex = 0; for (float vy = _boundingBox.LatStart; yIndex < LatLongVertCount; vy += latIncrement) { // Create a new vertex using the latitude angle. The coordinates of this vertex // will serve as a base for all the other vertices of the same latitude. Vector3 baseLatVertex = _metadata.Radius * GenerateBaseLatitudeVertex(vy); int xIndex = 0; for (float vx = _boundingBox.LonStart; xIndex < LatLongVertCount; vx += lonIncrement) { Vector3 vertex = GenerateVertex(baseLatVertex, vx, latLongOffset, _metadata.Radius); // Keep track of minimum; this will be used later to position the terrain on the table-top. if (vertex.x < min.x) { min = vertex; } // Add to edge vertices if (yIndex == 0) { edgeVerts[xIndex] = vertex; } else if (xIndex == LatLongVertCount - 1) { edgeVerts[LatLongVertCount + yIndex - 1] = vertex; } else if (yIndex == LatLongVertCount - 1) { edgeVerts[3 * (LatLongVertCount - 1) - xIndex] = vertex; } else if (xIndex == 0) { edgeVerts[4 * (LatLongVertCount - 1) - yIndex] = vertex; } verts[vertIndex] = vertex; uvs[vertIndex] = GenerateUVCoord(xIndex, yIndex, LatLongVertCount, LatLongVertCount, _uvBounds); xIndex++; vertIndex++; } yIndex++; } // Finish generating the data for the terrain edge. ProcessEdgeVertices(edgeVerts, min.x); _progress = 1f; // Only one LOD is generated. _meshData = new TerrainMeshData[] { new TerrainMeshData() { Vertices = verts, TexCoords = uvs, Triangles = GenerateTriangles(LatLongVertCount, LatLongVertCount), ExtraVertices = edgeVerts, ExtraTriangles = GenerateTriangles(edgeVerts.Length / 2, 2, true), MinimumVertex = min } }; }