void BuildTerrainData(TerrainData terrainData) { // Define the size of the arrays that Unity's terrain will // use internally to represent the terrain. Bigger numbers // mean more fine details. //if(CoRoutineShouldPause()) // yield return null; // "Heightmap Resolution": "Pixel resolution of the terrain’s heightmap (should be a power of two plus one, eg, 513 = 512 + 1)." // AFAIK, this defines the size of the 2-dimensional array that holds the information about the terrain (i.e. terrainData.GetHeights()) // Larger numbers lead to finer terrain details (if populated by a suitable source image heightmap). // As for actual physical size of the terrain (in Unity world space), this is defined as: // terrainData.Size = terrainData.heightmapScale * terrainData.heightmapResolution terrainData.heightmapResolution = 128 + 1; // "Base Texture Resolution": "Resolution of the composite texture used on the terrain when viewed from a distance greater than the Basemap Distance" // AFAIK, this doesn't affect the terrain mesh -- only how the terrain texture (i.e. Splats) are rendered terrainData.baseMapResolution = 512 + 1; // "Detail Resolution" and "Detail Resolution Per Patch" // (used for Details -- i.e. grass/flowers/etc...) terrainData.SetDetailResolution(1024, 32); // Set the Unity worldspace size of the terrain AFTER you set the resolution. // This effectively just sets terrainData.heightmapScale for you, depending on the value of terrainData.heightmapResolution terrainData.size = new Vector3(WorldUnitsPerChunk, TerrainHeight, WorldUnitsPerChunk); // Get the 2-dimensional array of floats that defines the actual height data for the terrain. // Each float has a value from 0..1, where a value of 1 means the maximum height of the terrain as defined by terrainData.size.y // // AFAIK, terrainData.heightmapWidth and terrainData.heightmapHeight will always be equal to terrainData.heightmapResolution // float[,] heights = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight); float halfDegreesPerChunk = DegreesPerChunk / 2f; // Caching these dimensions and... int w = terrainData.heightmapWidth; int h = terrainData.heightmapHeight; // Replacing loop divisions with mults cuts this function by about 10% // -- Shout out to Karl Goodloe float widthAdjust = 1f / (w - 1f); float heightAdjust = 1f / (h - 1f); // Loop through each point in the terrainData heightmap. for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { // Normalize x and y to a value from 0..1 // NOTE: We are INVERTING the x and y because internally Unity does this float xPos = (float)x * widthAdjust; float yPos = (float)y * heightAdjust; // This converts our chunk position to a latitude/longitude, // which we can then use to get UV coordinates from the heightmap // FIXME: I think this is doing a pincushion effect // Someone smarter than me will have to figure this out. Quaternion pointRotation = ChunkRotation * Quaternion.Euler( xPos * DegreesPerChunk - halfDegreesPerChunk, yPos * DegreesPerChunk - halfDegreesPerChunk, 0 ); Vector2 uv = CoordHelper.RotationToUV(pointRotation); // Get the pixel from the heightmap image texture at the appropriate position Color pix = HeightMapTexture.GetPixelBilinear(uv.x, uv.y); // Update the heights array heights[x, y] = pix.grayscale / heightMapTextureScaling; } } // Update the terrain data based on our changed heights array terrainData.SetHeights(0, 0, heights); }