using System.IO; using UnityEngine; namespace Gaia { public class UnityHeightMap : HeightMap { public Bounds m_boundsWU; public UnityHeightMap() { } public UnityHeightMap(string path) : base(path) { m_boundsWU.size = new Vector3(m_widthX, 0f, m_depthZ); m_isDirty = false; } public UnityHeightMap(TextAsset source) : base(source.bytes) { m_boundsWU.size = new Vector3(m_widthX, 0f, m_depthZ); m_isDirty = false; } public UnityHeightMap(UnityHeightMap source) : base(source) { m_boundsWU = source.m_boundsWU; m_isDirty = false; } public UnityHeightMap(Terrain terrain) { LoadFromTerrain(terrain); } public UnityHeightMap(Bounds bounds, string sourceFile) : base(sourceFile) { m_boundsWU = bounds; m_isDirty = false; } public UnityHeightMap(Texture2D texture) { LoadFromTexture2D(texture); m_isDirty = false; } public Bounds GetBoundsWU() { return m_boundsWU; } public Vector3 GetPositionWU() { return m_boundsWU.center - m_boundsWU.extents; } public void SetBoundsWU(Bounds bounds) { m_boundsWU = bounds; m_isDirty = true; } public void SetPositionWU(Vector3 position) { m_boundsWU.center = position; m_isDirty = true; } public void LoadFromTerrain(Terrain terrain) { Reset(); m_boundsWU.center = terrain.transform.position; m_boundsWU.size = terrain.terrainData.size; m_boundsWU.center += m_boundsWU.extents; m_widthX = terrain.terrainData.heightmapResolution; m_depthZ = terrain.terrainData.heightmapResolution; m_widthInvX = 1f / (float)m_widthX; m_depthInvZ = 1f / (float)m_depthZ; m_heights = terrain.terrainData.GetHeights(0, 0, m_widthX, m_depthZ); m_isPowerOf2 = GaiaUtils.Math_IsPowerOf2(m_widthX) && GaiaUtils.Math_IsPowerOf2(m_depthZ); m_isDirty = false; } public void SaveToTerrain(Terrain terrain) { int heightmapResolution = terrain.terrainData.heightmapResolution; int heightmapResolution2 = terrain.terrainData.heightmapResolution; if (m_widthX == heightmapResolution && m_depthZ == heightmapResolution2) { terrain.terrainData.SetHeights(0, 0, m_heights); m_isDirty = false; return; } float[,] array = new float[heightmapResolution, heightmapResolution2]; for (int i = 0; i < heightmapResolution; i++) { for (int j = 0; j < heightmapResolution2; j++) { array[i, j] = base[(float)i / (float)heightmapResolution, (float)j / (float)heightmapResolution2]; } } terrain.terrainData.SetHeights(0, 0, array); m_isDirty = false; } public void LoadFromTexture2D(Texture2D texture) { GaiaUtils.MakeTextureReadable(texture); GaiaUtils.MakeTextureUncompressed(texture); m_widthX = texture.width; m_depthZ = texture.height; m_widthInvX = 1f / (float)m_widthX; m_depthInvZ = 1f / (float)m_depthZ; m_heights = new float[m_widthX, m_depthZ]; m_isPowerOf2 = GaiaUtils.Math_IsPowerOf2(m_widthX) && GaiaUtils.Math_IsPowerOf2(m_depthZ); for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = texture.GetPixel(i, j).grayscale; } } m_isDirty = false; } public void ReadRawFromTextAsset(TextAsset asset) { using (Stream stream = new MemoryStream(asset.bytes)) { using (BinaryReader binaryReader = new BinaryReader(stream)) { m_widthX = (m_depthZ = Mathf.CeilToInt(Mathf.Sqrt(stream.Length / 2))); m_widthInvX = 1f / (float)m_widthX; m_depthInvZ = 1f / (float)m_depthZ; m_heights = new float[m_widthX, m_depthZ]; m_isPowerOf2 = GaiaUtils.Math_IsPowerOf2(m_widthX) && GaiaUtils.Math_IsPowerOf2(m_depthZ); for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = (float)(int)binaryReader.ReadUInt16() / 65535f; } } } stream.Close(); } m_isDirty = false; } public Texture2D CalculateNormals() { float num = (float)m_widthX / 2f; int widthX = m_widthX; int depthZ = m_depthZ; float num2 = 1f / ((float)widthX - 1f); float num3 = 1f / ((float)depthZ - 1f); float num4 = num / (float)m_widthX; float num5 = num / (float)m_depthZ; float[] array = Heights1D(); Texture2D texture2D = new Texture2D(widthX, depthZ, TextureFormat.RGBAFloat, mipChain: false, linear: true); Vector3 vector = default(Vector3); Color color = default(Color); for (int i = 0; i < depthZ; i++) { for (int j = 0; j < widthX; j++) { int num6 = ((j == widthX - 1) ? j : (j + 1)); int num7 = ((j == 0) ? j : (j - 1)); int num8 = ((i == depthZ - 1) ? i : (i + 1)); int num9 = ((i == 0) ? i : (i - 1)); float num10 = array[num7 + i * widthX] * num4; float num11 = array[num6 + i * widthX] * num4; float num12 = array[j + num9 * widthX] * num5; float num13 = array[j + num8 * widthX] * num5; float num14 = (num11 - num10) / (2f * num2); float num15 = (num13 - num12) / (2f * num3); vector.x = 0f - num14; vector.y = 0f - num15; vector.z = 1f; vector.Normalize(); color.r = vector.x * 0.5f + 0.5f; color.g = vector.y * 0.5f + 0.5f; color.b = vector.z; color.a = 1f; texture2D.SetPixel(j, i, color); } } texture2D.Apply(); return texture2D; } } }