using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using UnityEngine; namespace Gaia { public class HeightMap { public enum CopyType { AlwaysCopy = 0, CopyIfLessThan = 1, CopyIfGreaterThan = 2 } protected int m_widthX; protected int m_depthZ; protected float[,] m_heights; protected bool m_isPowerOf2; protected float m_widthInvX; protected float m_depthInvZ; protected float m_statMinVal; protected float m_statMaxVal; protected double m_statSumVals; protected bool m_isDirty; protected byte[] m_metaData = new byte[0]; private const int LEFT = 0; private const int RIGHT = 1; private const int BOTTOM = 2; private const int TOP = 3; private const float TIME = 0.2f; public float this[int x, int z] { get { return m_heights[x, z]; } set { m_heights[x, z] = value; m_isDirty = true; } } public float this[float x, float z] { get { return GetInterpolatedHeight(x, z); } set { x *= (float)m_widthX; z *= (float)m_depthZ; int num = (int)x; if (num == m_widthX) { num = m_widthX - 1; } int num2 = (int)z; if (num2 == m_depthZ) { num2 = m_depthZ - 1; } m_heights[num, num2] = value; m_isDirty = true; } } public HeightMap() { Reset(); } public HeightMap(int width, int depth) { m_widthX = width; m_depthZ = depth; 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); m_statMinVal = (m_statMaxVal = 0f); m_statSumVals = 0.0; m_metaData = new byte[0]; m_isDirty = false; } public HeightMap(float[,] source) { m_widthX = source.GetLength(0); m_depthZ = source.GetLength(1); 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); m_statMinVal = (m_statMaxVal = 0f); m_statSumVals = 0.0; m_metaData = new byte[0]; Buffer.BlockCopy(source, 0, m_heights, 0, m_widthX * m_depthZ * 4); m_isDirty = false; } public HeightMap(float[,,] source, int slice) { m_widthX = source.GetLength(0); m_depthZ = source.GetLength(1); 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); m_statMinVal = (m_statMaxVal = 0f); m_statSumVals = 0.0; m_metaData = new byte[0]; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = source[i, j, slice]; } } m_isDirty = false; } public HeightMap(int[,] source) { m_widthX = source.GetLength(0); m_depthZ = source.GetLength(1); 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); m_statMinVal = (m_statMaxVal = 0f); m_statSumVals = 0.0; m_metaData = new byte[0]; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = source[i, j]; } } m_isDirty = false; } public HeightMap(HeightMap source) { Reset(); m_widthX = source.m_widthX; m_depthZ = source.m_depthZ; m_widthInvX = 1f / (float)m_widthX; m_depthInvZ = 1f / (float)m_depthZ; m_heights = new float[m_widthX, m_depthZ]; m_isPowerOf2 = source.m_isPowerOf2; SetMetaData(source.m_metaData); Buffer.BlockCopy(source.m_heights, 0, m_heights, 0, m_widthX * m_depthZ * 4); m_isDirty = false; } public HeightMap(string sourceFile) { Reset(); LoadFromBinaryFile(sourceFile); m_isDirty = false; } public HeightMap(byte[] sourceBytes) { Reset(); LoadFromByteArray(sourceBytes); m_isDirty = false; } public int Width() { return m_widthX; } public int Depth() { return m_depthZ; } public float MinVal() { return m_statMinVal; } public float MaxVal() { return m_statMaxVal; } public double SumVal() { return m_statSumVals; } public byte[] GetMetaData() { return m_metaData; } public bool IsDirty() { return m_isDirty; } public void SetDirty(bool dirty = true) { m_isDirty = dirty; } public void ClearDirty() { m_isDirty = false; } public void SetMetaData(byte[] metadata) { m_metaData = new byte[metadata.Length]; Buffer.BlockCopy(metadata, 0, m_metaData, 0, metadata.Length); m_isDirty = true; } public float[,] Heights() { return m_heights; } public float[] Heights1D() { float[] array = new float[m_widthX * m_depthZ]; Buffer.BlockCopy(m_heights, 0, array, 0, array.Length * 4); return array; } public void SetHeights(float[] heights) { int num = (int)Mathf.Sqrt(heights.Length); if (num != m_widthX || num != m_depthZ) { Debug.LogError("SetHeights: Heights do not match. Aborting."); return; } Buffer.BlockCopy(heights, 0, m_heights, 0, heights.Length * 4); m_isDirty = true; } public void SetHeights(float[,] heights) { if (m_widthX != heights.GetLength(0) || m_depthZ != heights.GetLength(1)) { Debug.LogError("SetHeights: Sizes do not match. Aborting."); return; } int num = heights.GetLength(0) * heights.GetLength(1); Buffer.BlockCopy(heights, 0, m_heights, 0, num * 4); m_isDirty = true; } public float GetSafeHeight(int x, int z) { if (x < 0) { x = 0; } if (z < 0) { z = 0; } if (x >= m_widthX) { x = m_widthX - 1; } if (z >= m_depthZ) { z = m_depthZ - 1; } return m_heights[x, z]; } public void SetSafeHeight(int x, int z, float height) { if (x < 0) { x = 0; } if (z < 0) { z = 0; } if (x >= m_widthX) { x = m_widthX - 1; } if (z >= m_depthZ) { z = m_depthZ - 1; } m_heights[x, z] = height; m_isDirty = true; } protected float GetInterpolatedHeight(float x, float z) { x *= (float)m_widthX; z *= (float)m_depthZ; int num = (int)x; if (num == m_widthX) { num = m_widthX - 1; } int num2 = (int)z; if (num2 == m_depthZ) { num2 = m_depthZ - 1; } int num3 = num + 1; int num4 = num2 + 1; if (num3 == m_widthX) { num3 = num; } if (num4 == m_depthZ) { num4 = num2; } float num5 = x - (float)num; float num6 = z - (float)num2; float num7 = 1f - num5; float num8 = 1f - num6; return num7 * num8 * m_heights[num, num2] + num7 * num6 * m_heights[num, num4] + num5 * num8 * m_heights[num3, num2] + num5 * num6 * m_heights[num3, num4]; } public HeightMap SetHeight(float height) { float num = GaiaUtils.Math_Clamp(0f, 1f, height); for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = num; } } m_isDirty = true; return this; } public void GetHeightRange(ref float minHeight, ref float maxHeight) { maxHeight = float.MinValue; minHeight = float.MaxValue; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j]; if (num > maxHeight) { maxHeight = num; } if (num < minHeight) { minHeight = num; } } } } public float GetSlope(int x, int z) { float num = m_heights[x, z]; float num2 = m_heights[x + 1, z] - num; float num3 = m_heights[x, z + 1] - num; return (float)Math.Sqrt(num2 * num2 + num3 * num3); } public float GetSlope(float x, float z) { float num = GetInterpolatedHeight(x + m_widthInvX * 0.9f, z) - GetInterpolatedHeight(x - m_widthInvX * 0.9f, z); float num2 = GetInterpolatedHeight(x, z + m_depthInvZ * 0.9f) - GetInterpolatedHeight(x, z - m_depthInvZ * 0.9f); return GaiaUtils.Math_Clamp(0f, 90f, (float)(Math.Sqrt(num * num + num2 * num2) * 10000.0)); } public float GetSlope_a(float x, float z) { float interpolatedHeight = GetInterpolatedHeight(x, z); float num = Math.Abs(GetInterpolatedHeight(x - m_widthInvX, z) - interpolatedHeight); float num2 = Math.Abs(GetInterpolatedHeight(x + m_widthInvX, z) - interpolatedHeight); float num3 = Math.Abs(GetInterpolatedHeight(x, z - m_depthInvZ) - interpolatedHeight); float num4 = Math.Abs(GetInterpolatedHeight(x, z + m_depthInvZ) - interpolatedHeight); return (num + num2 + num3 + num4) / 4f * 400f; } public float GetBaseLevel() { float num = 0f; for (int i = 0; i < m_widthX; i++) { if (m_heights[i, 0] > num) { num = m_heights[i, 0]; } if (m_heights[i, m_depthZ - 1] > num) { num = m_heights[i, m_depthZ - 1]; } } for (int j = 0; j < m_depthZ; j++) { if (m_heights[0, j] > num) { num = m_heights[0, j]; } if (m_heights[m_widthX - 1, j] > num) { num = m_heights[m_widthX - 1, j]; } } return num; } public bool HasData() { if (m_widthX <= 0 || m_depthZ <= 0) { return false; } if (m_heights == null) { return false; } if (m_heights.GetLength(0) != m_widthX || m_heights.GetLength(1) != m_depthZ) { return false; } return true; } public float[] GetRow(int rowX) { float[] array = new float[m_depthZ]; for (int i = 0; i < m_depthZ; i++) { array[i] = m_heights[rowX, i]; } return array; } public void SetRow(int rowX, float[] values) { for (int i = 0; i < m_depthZ; i++) { m_heights[rowX, i] = values[i]; } } public float[] GetColumn(int columnZ) { float[] array = new float[m_widthX]; for (int i = 0; i < m_widthX; i++) { array[i] = m_heights[i, columnZ]; } return array; } public void SetColumn(int columnZ, float[] values) { for (int i = 0; i < m_widthX; i++) { m_heights[i, columnZ] = values[i]; } } public void Reset() { m_widthX = (m_depthZ = 0); m_widthInvX = (m_depthInvZ = 0f); m_heights = null; m_statMinVal = (m_statMaxVal = 0f); m_statSumVals = 0.0; m_metaData = new byte[0]; m_heights = new float[0, 0]; m_isDirty = false; } public void UpdateStats() { m_statMinVal = 1f; m_statMaxVal = 0f; m_statSumVals = 0.0; float num = 0f; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { num = m_heights[i, j]; if (num < m_statMinVal) { m_statMinVal = num; } if (num > m_statMaxVal) { m_statMaxVal = num; } m_statSumVals += num; } } } public HeightMap Smooth(int iterations) { for (int i = 0; i < iterations; i++) { for (int j = 0; j < m_widthX; j++) { for (int k = 0; k < m_depthZ; k++) { m_heights[j, k] = GaiaUtils.Math_Clamp(0f, 1f, (GetSafeHeight(j - 1, k) + GetSafeHeight(j + 1, k) + GetSafeHeight(j, k - 1) + GetSafeHeight(j, k + 1)) / 4f); } } } m_isDirty = true; return this; } public HeightMap SmoothRadius(int radius) { radius = Mathf.Max(5, radius); HeightMap heightMap = new HeightMap(m_widthX, m_depthZ); float num = 1f / (float)((2 * radius + 1) * (2 * radius + 1)); for (int i = 0; i < m_depthZ; i++) { for (int j = 0; j < m_widthX; j++) { heightMap[j, i] = num * m_heights[j, i]; } } for (int k = radius; k < m_widthX - radius; k++) { int num2 = radius; float num3 = 0f; for (int l = -radius; l < radius + 1; l++) { for (int m = -radius; m < radius + 1; m++) { num3 += heightMap[k + m, num2 + l]; } } for (num2++; num2 < m_depthZ - radius; num2++) { for (int n = -radius; n < radius + 1; n++) { num3 -= heightMap[k + n, num2 - radius - 1]; num3 += heightMap[k + n, num2 + radius]; } m_heights[k, num2] = num3; } } m_isDirty = true; return this; } public HeightMap Convolve(float[,] kernel) { float num = 0f; int num2 = Mathf.FloorToInt((float)kernel.GetLength(0) / 2f); int length = kernel.GetLength(0); int length2 = kernel.GetLength(1); int num3 = length * length2; int num4 = 0; for (int i = 0; i < length; i++) { for (int j = 0; j < length2; j++) { num += kernel[i, j]; } } if (GaiaUtils.Math_ApproximatelyEqual(num, 0f)) { num = 1f; } for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { float num5 = 0f; float num6 = 0f; num4 = 0; for (int m = -num2; m <= num2; m++) { int num7 = k + m; if (num7 < 0 || num7 >= m_widthX) { continue; } for (int n = -num2; n <= num2; n++) { int num8 = l + n; if (num8 >= 0 && num8 < m_depthZ) { float num9 = kernel[m + num2, n + num2]; num6 += num9; num5 += m_heights[num7, num8] * num9; num4++; } } } if (num4 == num3) { m_heights[k, l] = Mathf.Clamp01(num5 / num); } } } m_isDirty = true; return this; } public HeightMap DeNoise(int radius) { float num = 0f; for (int i = radius; i < m_widthX - radius; i++) { for (int j = radius; j < m_depthZ - radius; j++) { float num2 = float.MaxValue; float num3 = float.MinValue; for (int k = -radius; k <= radius; k++) { for (int l = -radius; l <= radius; l++) { if (k != 0 || l != 0) { num = m_heights[i + k, j + l]; if (num < num2) { num2 = num; } if (num > num3) { num3 = num; } } } } num = m_heights[i, j]; if (num > num3) { m_heights[i, j] = num3; } else if (num < num2) { m_heights[i, j] = num2; } } } m_isDirty = true; return this; } public HeightMap GrowEdges(int radius) { float num = 0f; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num2 = float.MaxValue; float num3 = float.MinValue; for (int k = -radius; k <= radius; k++) { for (int l = -radius; l <= radius; l++) { int num4 = i + k; if (num4 < 0 || num4 >= m_widthX || (k == 0 && l == 0)) { continue; } int num5 = j + l; if (num5 >= 0 && num5 < m_depthZ) { num = m_heights[num4, num5]; if (num < num2) { num2 = num; } if (num > num3) { num3 = num; } } } } num = m_heights[i, j]; if (num3 > num) { m_heights[i, j] = (num3 + num) / 2f; } } } m_isDirty = true; return this; } public HeightMap ShrinkEdges(int radius) { float num = 0f; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num2 = float.MaxValue; float num3 = float.MinValue; for (int k = -radius; k <= radius; k++) { int num4 = i + k; if (num4 < 0 || num4 == m_widthX) { continue; } for (int l = -radius; l <= radius; l++) { if (k == 0 && l == 0) { continue; } int num5 = j + l; if (num5 >= 0 && num5 < m_depthZ) { num = m_heights[num4, num5]; if (num < num2) { num2 = num; } if (num > num3) { num3 = num; } } } } num = m_heights[i, j]; if (num2 < num) { m_heights[i, j] = (num2 + num) / 2f; } } } m_isDirty = true; return this; } public HeightMap GetSlopeMap() { HeightMap heightMap = new HeightMap(this); for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { heightMap[i, j] = GetSlope(i, j); } } return heightMap; } public HeightMap Copy(HeightMap heightMap, CopyType copyType = CopyType.AlwaysCopy) { switch (copyType) { case CopyType.AlwaysCopy: { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int num11 = 0; num11 < m_widthX; num11++) { for (int num12 = 0; num12 < m_depthZ; num12++) { m_heights[num11, num12] = heightMap[m_widthInvX * (float)num11, m_depthInvZ * (float)num12]; } } break; } for (int num13 = 0; num13 < m_widthX; num13++) { for (int num14 = 0; num14 < m_depthZ; num14++) { m_heights[num13, num14] = heightMap.m_heights[num13, num14]; } } break; } case CopyType.CopyIfLessThan: { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int m = 0; m < m_widthX; m++) { for (int n = 0; n < m_depthZ; n++) { float num5 = m_heights[m, n]; float num6 = heightMap[m_widthInvX * (float)m, m_depthInvZ * (float)n]; if (num6 < num5) { m_heights[m, n] = num6; } } } break; } for (int num7 = 0; num7 < m_widthX; num7++) { for (int num8 = 0; num8 < m_depthZ; num8++) { float num9 = m_heights[num7, num8]; float num10 = heightMap[num7, num8]; if (num10 < num9) { m_heights[num7, num8] = num10; } } } break; } case CopyType.CopyIfGreaterThan: { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j]; float num2 = heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; if (num2 > num) { m_heights[i, j] = num2; } } } break; } for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { float num3 = m_heights[k, l]; float num4 = heightMap[k, l]; if (num4 > num3) { m_heights[k, l] = num4; } } } break; } } m_isDirty = true; return this; } public HeightMap CopyClamped(HeightMap heightMap, float min, float max) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { float num2 = heightMap.m_heights[k, l]; if (num2 < min) { num2 = min; } else if (num2 > max) { num2 = max; } m_heights[k, l] = num2; } } } m_isDirty = true; return this; } public HeightMap Duplicate() { return new HeightMap(this); } public HeightMap Invert() { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = 1f - m_heights[i, j]; } } m_isDirty = true; return this; } public HeightMap Flip() { float[,] array = new float[m_depthZ, m_widthX]; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { array[j, i] = m_heights[i, j]; } } m_heights = array; m_widthX = array.GetLength(0); m_depthZ = array.GetLength(1); m_widthInvX = 1f / (float)m_widthX; m_depthInvZ = 1f / (float)m_depthZ; m_isPowerOf2 = GaiaUtils.Math_IsPowerOf2(m_widthX) && GaiaUtils.Math_IsPowerOf2(m_depthZ); m_statMinVal = (m_statMaxVal = 0f); m_statSumVals = 0.0; m_isDirty = true; return this; } public HeightMap Normalise() { float num = float.MinValue; float num2 = float.MaxValue; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num3 = m_heights[i, j]; if (num3 > num) { num = num3; } if (num3 < num2) { num2 = num3; } } } float num4 = num - num2; if (num4 > 0f) { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { m_heights[k, l] = (m_heights[k, l] - num2) / num4; } } m_isDirty = true; } return this; } public HeightMap ErodeThermal(int iterations, float talusMin, float talusMax, HeightMap hardnessMask) { for (int i = 0; i < iterations; i++) { for (int j = 1; j < m_widthX - 1; j++) { for (int k = 1; k < m_depthZ - 1; k++) { float num = m_heights[j, k]; float num2 = m_heights[j, k + 1]; float num3 = m_heights[j - 1, k]; float num4 = m_heights[j + 1, k]; float num5 = m_heights[j, k - 1]; float num6 = num - num2; float num7 = num - num3; float num8 = num - num4; float num9 = num - num5; int num10 = 0; int num11 = 0; float num12 = 0f; if (num6 > num12) { num12 = num6; num11 = 1; } if (num7 > num12) { num12 = num7; num10 = -1; num11 = 0; } if (num8 > num12) { num12 = num8; num10 = 1; num11 = 0; } if (num9 > num12) { num12 = num9; num10 = 0; num11 = -1; } if (!(num12 < talusMin) && !(num12 > talusMax)) { num12 *= 1f - hardnessMask[m_widthInvX * (float)j, m_depthInvZ * (float)k]; num12 *= 0.5f; m_heights[j, k] -= num12; m_heights[j + num10, k + num11] = m_heights[j + num10, k + num11] + num12; m_isDirty = true; } } } } return this; } public HeightMap Quantize(float divisor) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = Mathf.Round(m_heights[i, j] / divisor) * divisor; } } m_isDirty = true; return this; } public HeightMap Quantize(float[] startHeights, AnimationCurve[] curves) { int length = startHeights.GetLength(0); if (length == 0) { Debug.LogWarning("Quantize : must supply heights!"); return this; } if (curves.GetLength(0) != length) { Debug.LogWarning("Quantize : startHeights and curves do not match!"); return this; } for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { int num = 0; float num2 = 0f; float num3 = 1f; float num4 = m_heights[i, j]; for (num = length - 1; num >= 0; num--) { num2 = startHeights[num]; num3 = ((num != length - 1) ? startHeights[num + 1] : 1f); if (num2 <= num4 && num4 <= num3) { break; } } m_heights[i, j] = num2 + (num4 - num2) * curves[num].Evaluate((num4 - num2) / (num3 - num2)); } } m_isDirty = true; return this; } public HeightMap CurvatureMap(GaiaConstants.CurvatureType curvatureType) { float limit = 10000f; int depthZ = m_depthZ; int widthX = m_widthX; float num = 1f / ((float)widthX - 1f); float num2 = 1f / ((float)depthZ - 1f); float[] array = Heights1D(); HeightMap heightMap = Duplicate(); for (int i = 0; i < depthZ; i++) { for (int j = 0; j < widthX; j++) { int num3 = ((j == widthX - 1) ? j : (j + 1)); int num4 = ((j == 0) ? j : (j - 1)); int num5 = ((i == depthZ - 1) ? i : (i + 1)); int num6 = ((i == 0) ? i : (i - 1)); float num7 = array[j + i * widthX]; float num8 = array[num4 + i * widthX]; float num9 = array[num3 + i * widthX]; float num10 = array[j + num6 * widthX]; float num11 = array[j + num5 * widthX]; float num12 = array[num4 + num6 * widthX]; float num13 = array[num4 + num5 * widthX]; float num14 = array[num3 + num6 * widthX]; float num15 = array[num3 + num5 * widthX]; float dx = (num9 - num8) / (2f * num); float dy = (num11 - num10) / (2f * num2); float dxx = (num9 - 2f * num7 + num8) / (num * num); float dyy = (num11 - 2f * num7 + num10) / (num2 * num2); float dxy = (num15 - num14 - num13 + num12) / (4f * num * num2); float value = 0f; switch (curvatureType) { case GaiaConstants.CurvatureType.Horizontal: value = HorizontalCurve(limit, dx, dy, dxx, dyy, dxy); break; case GaiaConstants.CurvatureType.Vertical: value = VerticalCurve(limit, dx, dy, dxx, dyy, dxy); break; case GaiaConstants.CurvatureType.Average: value = AverageCurve(limit, dx, dy, dxx, dyy, dxy); break; } heightMap[j, i] = value; } } return heightMap; } private float HorizontalCurve(float limit, float dx, float dy, float dxx, float dyy, float dxy) { float num = -2f * (dy * dy * dxx + dx * dx * dyy - dx * dy * dxy); num /= dx * dx + dy * dy; if (float.IsInfinity(num) || float.IsNaN(num)) { num = 0f; } if (num < 0f - limit) { num = 0f - limit; } if (num > limit) { num = limit; } num /= limit; return num * 0.5f + 0.5f; } private float VerticalCurve(float limit, float dx, float dy, float dxx, float dyy, float dxy) { float num = -2f * (dx * dx * dxx + dy * dy * dyy + dx * dy * dxy); num /= dx * dx + dy * dy; if (float.IsInfinity(num) || float.IsNaN(num)) { num = 0f; } if (num < 0f - limit) { num = 0f - limit; } if (num > limit) { num = limit; } num /= limit; return num * 0.5f + 0.5f; } private float AverageCurve(float limit, float dx, float dy, float dxx, float dyy, float dxy) { float num = HorizontalCurve(limit, dx, dy, dxx, dyy, dxy); float num2 = VerticalCurve(limit, dx, dy, dxx, dyy, dxy); return (num + num2) * 0.5f; } public HeightMap Aspect(GaiaConstants.AspectType aspectType) { int depthZ = m_depthZ; int widthX = m_widthX; float[] array = Heights1D(); float num = 1f / ((float)widthX - 1f); float num2 = 1f / ((float)depthZ - 1f); for (int i = 0; i < depthZ; i++) { for (int j = 0; j < widthX; j++) { int num3 = ((j == widthX - 1) ? j : (j + 1)); int num4 = ((j == 0) ? j : (j - 1)); int num5 = ((i == depthZ - 1) ? i : (i + 1)); int num6 = ((i == 0) ? i : (i - 1)); float num7 = array[num4 + i * widthX]; float num8 = array[num3 + i * widthX]; float num9 = array[j + num6 * widthX]; float num10 = array[j + num5 * widthX]; float num11 = (num8 - num7) / (2f * num); float num12 = (num10 - num9) / (2f * num2); float num13 = Mathf.Sqrt(num11 * num11 + num12 * num12); float num14 = Mathf.Acos((0f - num12) / num13) * 57.29578f; if (float.IsInfinity(num14) || float.IsNaN(num14)) { num14 = 0f; } float num15 = 180f * (1f + Sign(num11)) - Sign(num11) * num14; switch (aspectType) { case GaiaConstants.AspectType.Northerness: num15 = Mathf.Cos(num15 * (MathF.PI / 180f)); num15 = num15 * 0.5f + 0.5f; break; case GaiaConstants.AspectType.Easterness: num15 = Mathf.Sin(num15 * (MathF.PI / 180f)); num15 = num15 * 0.5f + 0.5f; break; default: num15 /= 360f; break; } m_heights[j, i] = num15; } } m_isDirty = true; return this; } private float Sign(float v) { if (v > 0f) { return 1f; } if (v < 0f) { return -1f; } return 0f; } public HeightMap ErodeHydraulic(int iterations, HeightMap hardnessMap, HeightMap rainMap, int rainFrequency, float sedimentDisolveRate, ref HeightMap sedimentMap) { HeightMap heightMap = new HeightMap(m_widthX, m_depthZ); float[,,] outFlow = new float[m_widthX, m_depthZ, 4]; HeightMap heightMap2 = new HeightMap(m_widthX, m_depthZ); HeightMap heightMap3 = new HeightMap(m_widthX, m_depthZ); float value = 1f / (float)rainFrequency; for (int i = 0; i < iterations; i++) { if (i % rainFrequency == 0) { heightMap.Add(rainMap); } CalculateWaterOutflow(this, heightMap, outFlow); UpdateWaterMap(heightMap, outFlow); for (int j = 0; j < m_widthX; j++) { for (int k = 0; k < m_depthZ; k++) { float num = m_heights[j, k]; float num2 = heightMap[j, k]; float num3 = hardnessMap[j, k]; float num4 = 0f; int num5 = 0; for (int l = j - 1; l <= j + 1; l++) { if (l < 0 || l == m_widthX) { continue; } for (int m = k - 1; m <= k + 1; m++) { if (m >= 0 && m != m_depthZ) { float num6 = num - m_heights[l, m]; if (num6 > 0f) { num4 += num6; num5++; } } } } if (num5 <= 0) { continue; } float num7 = num2 * num4 * sedimentDisolveRate * (1f - num3); heightMap3[j, k] -= num7; for (int n = j - 1; n <= j + 1; n++) { if (n < 0 || n == m_widthX) { continue; } for (int num8 = k - 1; num8 <= k + 1; num8++) { if (num8 >= 0 && num8 != m_depthZ) { float num9 = num - m_heights[n, num8]; if (num9 > 0f) { float num10 = num7 * (num9 / num4); heightMap3[n, num8] += num10; } } } } } } sedimentMap.Add(heightMap3); AddClamped(heightMap3, 0f, 1f); heightMap.SubtractClamped(value, 0f, 1f); heightMap2.SetHeight(0f); heightMap3.SetHeight(0f); m_isDirty = true; } return this; } private void CalculateWaterOutflow(HeightMap heightMap, HeightMap waterMap, float[,,] outFlow) { int num = heightMap.Width(); int num2 = heightMap.Depth(); for (int i = 0; i < num; i++) { for (int j = 0; j < num2; j++) { int x = ((i != 0) ? (i - 1) : 0); int x2 = ((i == num - 1) ? (num - 1) : (i + 1)); int z = ((j != 0) ? (j - 1) : 0); int z2 = ((j == num2 - 1) ? (num2 - 1) : (j + 1)); float num3 = waterMap[i, j]; float num4 = waterMap[x, j]; float num5 = waterMap[x2, j]; float num6 = waterMap[i, z]; float num7 = waterMap[i, z2]; float num8 = heightMap[i, j]; float num9 = heightMap[x, j]; float num10 = heightMap[x2, j]; float num11 = heightMap[i, z]; float num12 = heightMap[i, z2]; float num13 = num3 + num8 - (num4 + num9); float num14 = num3 + num8 - (num5 + num10); float num15 = num3 + num8 - (num6 + num11); float num16 = num3 + num8 - (num7 + num12); float num17 = Mathf.Max(0f, outFlow[i, j, 0] + num13); float num18 = Mathf.Max(0f, outFlow[i, j, 1] + num14); float num19 = Mathf.Max(0f, outFlow[i, j, 2] + num15); float num20 = Mathf.Max(0f, outFlow[i, j, 3] + num16); float num21 = num17 + num18 + num19 + num20; if (num21 > 0f) { float num22 = num3 / (num21 * 0.2f); if (num22 > 1f) { num22 = 1f; } if (num22 < 0f) { num22 = 0f; } outFlow[i, j, 0] = num17 * num22; outFlow[i, j, 1] = num18 * num22; outFlow[i, j, 2] = num19 * num22; outFlow[i, j, 3] = num20 * num22; } else { outFlow[i, j, 0] = 0f; outFlow[i, j, 1] = 0f; outFlow[i, j, 2] = 0f; outFlow[i, j, 3] = 0f; } } } } private void UpdateWaterMap(HeightMap waterMap, float[,,] outFlow) { int num = waterMap.Width(); int num2 = waterMap.Depth(); for (int i = 0; i < num; i++) { for (int j = 0; j < num2; j++) { float num3 = outFlow[i, j, 0] + outFlow[i, j, 1] + outFlow[i, j, 2] + outFlow[i, j, 3]; float num4 = 0f; num4 += ((i == 0) ? 0f : outFlow[i - 1, j, 1]); num4 += ((i == num - 1) ? 0f : outFlow[i + 1, j, 0]); num4 += ((j == 0) ? 0f : outFlow[i, j - 1, 3]); num4 += ((j == num2 - 1) ? 0f : outFlow[i, j + 1, 2]); float num5 = waterMap[i, j] + (num4 - num3) * 0.2f; if (num5 < 0f) { num5 = 0f; } waterMap[i, j] = num5; } } } public HeightMap FlowMap(int iterations) { int depthZ = m_depthZ; int widthX = m_widthX; float[] heightMap = Heights1D(); float[,] waterMap = new float[widthX, depthZ]; float[,,] outFlow = new float[widthX, depthZ, 4]; FillWaterMap(0.0001f, waterMap, widthX, depthZ); for (int i = 0; i < iterations; i++) { ComputeOutflow(waterMap, outFlow, heightMap, widthX, depthZ); UpdateWaterMap(waterMap, outFlow, widthX, depthZ); } float[,] array = new float[widthX, depthZ]; CalculateVelocityField(array, outFlow, widthX, depthZ); NormalizeMap(array, widthX, depthZ); return new HeightMap(array); } private void FillWaterMap(float amount, float[,] waterMap, int width, int height) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { waterMap[j, i] = amount; } } } private void ComputeOutflow(float[,] waterMap, float[,,] outFlow, float[] heightMap, int width, int height) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int num = ((j != 0) ? (j - 1) : 0); int num2 = ((j == width - 1) ? (width - 1) : (j + 1)); int num3 = ((i != 0) ? (i - 1) : 0); int num4 = ((i == height - 1) ? (height - 1) : (i + 1)); float num5 = waterMap[j, i]; float num6 = waterMap[num, i]; float num7 = waterMap[num2, i]; float num8 = waterMap[j, num3]; float num9 = waterMap[j, num4]; float num10 = heightMap[j + i * width]; float num11 = heightMap[num + i * width]; float num12 = heightMap[num2 + i * width]; float num13 = heightMap[j + num3 * width]; float num14 = heightMap[j + num4 * width]; float num15 = num5 + num10 - (num6 + num11); float num16 = num5 + num10 - (num7 + num12); float num17 = num5 + num10 - (num8 + num13); float num18 = num5 + num10 - (num9 + num14); float num19 = Mathf.Max(0f, outFlow[j, i, 0] + num15); float num20 = Mathf.Max(0f, outFlow[j, i, 1] + num16); float num21 = Mathf.Max(0f, outFlow[j, i, 2] + num17); float num22 = Mathf.Max(0f, outFlow[j, i, 3] + num18); float num23 = num19 + num20 + num21 + num22; if (num23 > 0f) { float num24 = num5 / (num23 * 0.2f); if (num24 > 1f) { num24 = 1f; } if (num24 < 0f) { num24 = 0f; } outFlow[j, i, 0] = num19 * num24; outFlow[j, i, 1] = num20 * num24; outFlow[j, i, 2] = num21 * num24; outFlow[j, i, 3] = num22 * num24; } else { outFlow[j, i, 0] = 0f; outFlow[j, i, 1] = 0f; outFlow[j, i, 2] = 0f; outFlow[j, i, 3] = 0f; } } } } private void UpdateWaterMap(float[,] waterMap, float[,,] outFlow, int width, int height) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { float num = outFlow[j, i, 0] + outFlow[j, i, 1] + outFlow[j, i, 2] + outFlow[j, i, 3]; float num2 = 0f; num2 += ((j == 0) ? 0f : outFlow[j - 1, i, 1]); num2 += ((j == width - 1) ? 0f : outFlow[j + 1, i, 0]); num2 += ((i == 0) ? 0f : outFlow[j, i - 1, 3]); num2 += ((i == height - 1) ? 0f : outFlow[j, i + 1, 2]); float num3 = waterMap[j, i] + (num2 - num) * 0.2f; if (num3 < 0f) { num3 = 0f; } waterMap[j, i] = num3; } } } private void CalculateVelocityField(float[,] velocityMap, float[,,] outFlow, int width, int height) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { float num = ((j == 0) ? 0f : (outFlow[j - 1, i, 1] - outFlow[j, i, 0])); float num2 = ((j == width - 1) ? 0f : (outFlow[j, i, 1] - outFlow[j + 1, i, 0])); float num3 = ((i == height - 1) ? 0f : (outFlow[j, i + 1, 2] - outFlow[j, i, 3])); float num4 = ((i == 0) ? 0f : (outFlow[j, i, 2] - outFlow[j, i - 1, 3])); float num5 = (num + num2) * 0.5f; float num6 = (num4 + num3) * 0.5f; velocityMap[j, i] = Mathf.Sqrt(num5 * num5 + num6 * num6); } } } private void NormalizeMap(float[,] map, int width, int height) { float num = float.PositiveInfinity; float num2 = float.NegativeInfinity; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { float num3 = map[j, i]; if (num3 < num) { num = num3; } if (num3 > num2) { num2 = num3; } } } float num4 = num2 - num; for (int k = 0; k < height; k++) { for (int l = 0; l < width; l++) { float num5 = map[l, k]; num5 = ((!(num4 < 1E-12f)) ? ((num5 - num) / num4) : 0f); map[l, k] = num5; } } } public HeightMap SlopeMap() { int depthZ = m_depthZ; int widthX = m_widthX; float[] array = Heights1D(); float num = 1f / ((float)widthX - 1f); float num2 = 1f / ((float)depthZ - 1f); float num3 = 0.5f; float num4 = 0.5f; HeightMap heightMap = new HeightMap(widthX, depthZ); for (int i = 0; i < depthZ; i++) { for (int j = 0; j < widthX; j++) { int num5 = ((j == widthX - 1) ? j : (j + 1)); int num6 = ((j == 0) ? j : (j - 1)); int num7 = ((i == depthZ - 1) ? i : (i + 1)); int num8 = ((i == 0) ? i : (i - 1)); float num9 = array[num6 + i * widthX] * num3; float num10 = array[num5 + i * widthX] * num3; float num11 = array[j + num8 * widthX] * num4; float num12 = array[j + num7 * widthX] * num4; float num13 = (num10 - num9) / (2f * num); float num14 = (num12 - num11) / (2f * num2); float num15 = Mathf.Sqrt(num13 * num13 + num14 * num14); float value = num15 / Mathf.Sqrt(1f + num15 * num15); heightMap[j, i] = value; } } return heightMap; } public HeightMap Add(float value) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] += value; } } m_isDirty = true; return this; } public HeightMap Add(HeightMap heightMap) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] += heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { m_heights[k, l] += heightMap.m_heights[k, l]; } } } m_isDirty = true; return this; } public HeightMap AddClamped(float value, float min, float max) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j] + value; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } m_isDirty = true; return this; } public HeightMap AddClamped(HeightMap heightMap, float min, float max) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j] + heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { float num2 = m_heights[k, l] + heightMap.m_heights[k, l]; if (num2 < min) { num2 = min; } else if (num2 > max) { num2 = max; } m_heights[k, l] = num2; } } } m_isDirty = true; return this; } public HeightMap Subtract(float value) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] -= value; } } m_isDirty = true; return this; } public HeightMap Subtract(HeightMap heightMap) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] -= heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { m_heights[k, l] -= heightMap.m_heights[k, l]; } } } m_isDirty = true; return this; } public HeightMap SubtractClamped(float value, float min, float max) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j] - value; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } m_isDirty = true; return this; } public HeightMap SubtractClamped(HeightMap heightMap, float min, float max) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j] - heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { float num2 = m_heights[k, l] - heightMap.m_heights[k, l]; if (num2 < min) { num2 = min; } else if (num2 > max) { num2 = max; } m_heights[k, l] = num2; } } } m_isDirty = true; return this; } public HeightMap Multiply(float value) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] *= value; } } m_isDirty = true; return this; } public HeightMap Multiply(HeightMap heightMap) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] *= heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { m_heights[k, l] *= heightMap.m_heights[k, l]; } } } m_isDirty = true; return this; } public HeightMap MultiplyClamped(float value, float min, float max) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j] * value; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } m_isDirty = true; return this; } public HeightMap MultiplyClamped(HeightMap heightMap, float min, float max) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j] * heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { float num2 = m_heights[k, l] * heightMap.m_heights[k, l]; if (num2 < min) { num2 = min; } else if (num2 > max) { num2 = max; } m_heights[k, l] = num2; } } } m_isDirty = true; return this; } public HeightMap Divide(float value) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] /= value; } } m_isDirty = true; return this; } public HeightMap Divide(HeightMap heightMap) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] /= heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { m_heights[k, l] /= heightMap.m_heights[k, l]; } } } m_isDirty = true; return this; } public HeightMap DivideClamped(float value, float min, float max) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j] / value; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } m_isDirty = true; return this; } public HeightMap DivideClamped(HeightMap heightMap, float min, float max) { if (m_widthX != heightMap.m_widthX || m_depthZ != heightMap.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { float num = m_heights[i, j] / heightMap[m_widthInvX * (float)i, m_depthInvZ * (float)j]; if (num < min) { num = min; } else if (num > max) { num = max; } m_heights[i, j] = num; } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { float num2 = m_heights[k, l] / heightMap.m_heights[k, l]; if (num2 < min) { num2 = min; } else if (num2 > max) { num2 = max; } m_heights[k, l] = num2; } } } m_isDirty = true; return this; } public HeightMap Lerp(HeightMap hmNewValues, HeightMap hmLerpMask) { if (m_widthX != hmNewValues.m_widthX || m_depthZ != hmNewValues.m_depthZ) { if (m_widthX != hmLerpMask.m_widthX || m_depthZ != hmLerpMask.m_depthZ) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = Mathf.Lerp(m_heights[i, j], hmNewValues[m_widthInvX * (float)i, m_depthInvZ * (float)j], hmLerpMask[m_widthInvX * (float)i, m_depthInvZ * (float)j]); } } } else { for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { m_heights[k, l] = Mathf.Lerp(m_heights[k, l], hmNewValues[m_widthInvX * (float)k, m_depthInvZ * (float)l], hmLerpMask[k, l]); } } } } else if (m_widthX != hmLerpMask.m_widthX || m_depthZ != hmLerpMask.m_depthZ) { for (int m = 0; m < m_widthX; m++) { for (int n = 0; n < m_depthZ; n++) { m_heights[m, n] = Mathf.Lerp(m_heights[m, n], hmNewValues[m, n], hmLerpMask[m_widthInvX * (float)m, m_depthInvZ * (float)n]); } } } else { for (int num = 0; num < m_widthX; num++) { for (int num2 = 0; num2 < m_depthZ; num2++) { m_heights[num, num2] = Mathf.Lerp(m_heights[num, num2], hmNewValues[num, num2], hmLerpMask[num, num2]); } } } m_isDirty = true; return this; } public float Sum() { float num = 0f; for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { num += m_heights[i, j]; } } return num; } public float Average() { return Sum() / (float)(m_widthX * m_depthZ); } public HeightMap Power(float exponent) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = Mathf.Pow(m_heights[i, j], exponent); } } m_isDirty = true; return this; } public HeightMap Contrast(float contrast) { for (int i = 0; i < m_widthX; i++) { for (int j = 0; j < m_depthZ; j++) { m_heights[i, j] = (m_heights[i, j] - 0.5f) * contrast + 0.5f; } } m_isDirty = true; return this; } public void SaveToBinaryFile(string fileName) { BinaryFormatter binaryFormatter = new BinaryFormatter(); Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None); binaryFormatter.Serialize(stream, m_widthX); binaryFormatter.Serialize(stream, m_depthZ); binaryFormatter.Serialize(stream, m_metaData); binaryFormatter.Serialize(stream, m_heights); stream.Close(); m_isDirty = false; } public void LoadFromBinaryFile(string fileName) { if (!File.Exists(fileName)) { Debug.LogError("Could not locate file : " + fileName); return; } Reset(); BinaryFormatter binaryFormatter = new BinaryFormatter(); Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); m_widthX = (int)binaryFormatter.Deserialize(stream); m_depthZ = (int)binaryFormatter.Deserialize(stream); m_metaData = (byte[])binaryFormatter.Deserialize(stream); m_heights = (float[,])binaryFormatter.Deserialize(stream); stream.Close(); m_widthInvX = 1f / (float)m_widthX; m_depthInvZ = 1f / (float)m_depthZ; m_isPowerOf2 = GaiaUtils.Math_IsPowerOf2(m_widthX) && GaiaUtils.Math_IsPowerOf2(m_depthZ); m_isDirty = false; } public void LoadFromByteArray(byte[] source) { if (source == null) { Debug.LogError("No data provided"); return; } Reset(); BinaryFormatter binaryFormatter = new BinaryFormatter(); Stream stream = new MemoryStream(source); m_widthX = (int)binaryFormatter.Deserialize(stream); m_depthZ = (int)binaryFormatter.Deserialize(stream); m_metaData = (byte[])binaryFormatter.Deserialize(stream); m_heights = (float[,])binaryFormatter.Deserialize(stream); stream.Close(); m_widthInvX = 1f / (float)m_widthX; m_depthInvZ = 1f / (float)m_depthZ; m_isPowerOf2 = GaiaUtils.Math_IsPowerOf2(m_widthX) && GaiaUtils.Math_IsPowerOf2(m_depthZ); m_isDirty = false; } public void LoadFromRawFile(string fileName, GaiaConstants.RawByteOrder byteOrder, ref GaiaConstants.RawBitDepth bitDepth, ref int resolution) { if (!File.Exists(fileName)) { Debug.LogError("Could not locate raw file : " + fileName); return; } Reset(); using (FileStream fileStream = File.OpenRead(fileName)) { using (BinaryReader binaryReader = ((byteOrder == GaiaConstants.RawByteOrder.IBM) ? new BinaryReader(fileStream) : new BinaryReaderMac(fileStream))) { if (bitDepth == GaiaConstants.RawBitDepth.Sixteen) { if (fileStream.Length % 2 == 0L) { resolution = (m_widthX = (m_depthZ = Mathf.CeilToInt(Mathf.Sqrt(fileStream.Length / 2)))); m_heights = new float[m_widthX, 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; } } } else { m_widthX = (m_depthZ = Mathf.CeilToInt(Mathf.Sqrt(fileStream.Length))); } } else { resolution = (m_widthX = (m_depthZ = Mathf.CeilToInt(Mathf.Sqrt(fileStream.Length)))); m_heights = new float[m_widthX, m_depthZ]; for (int k = 0; k < m_widthX; k++) { for (int l = 0; l < m_depthZ; l++) { m_heights[k, l] = (float)(int)binaryReader.ReadByte() / 255f; } } } } fileStream.Close(); } m_widthInvX = 1f / (float)m_widthX; m_depthInvZ = 1f / (float)m_depthZ; m_isPowerOf2 = GaiaUtils.Math_IsPowerOf2(m_widthX) && GaiaUtils.Math_IsPowerOf2(m_depthZ); m_isDirty = false; } public void DumpMap(float scaleValue, int precision, string spacer, bool flip) { StringBuilder stringBuilder = new StringBuilder(); string text = ""; if (precision == 0) { text = "{0:0}"; } else { text = "{0:0."; for (int i = 0; i < precision; i++) { text += "0"; } text += "}"; } if (!string.IsNullOrEmpty(spacer)) { text += spacer; } for (int j = 0; j < m_widthX; j++) { for (int k = 0; k < m_depthZ; k++) { if (!flip) { stringBuilder.AppendFormat(text, m_heights[j, k] * scaleValue); } else { stringBuilder.AppendFormat(text, m_heights[k, j] * scaleValue); } } stringBuilder.AppendLine(); } Debug.Log(stringBuilder.ToString()); } public void DumpRow(int rowX, float scaleValue, int precision, string spacer) { StringBuilder stringBuilder = new StringBuilder(); string text = ""; if (precision == 0) { text = "{0:0}"; } else { text = "{0:0."; for (int i = 0; i < precision; i++) { text += "0"; } text += "}"; } if (!string.IsNullOrEmpty(spacer)) { text += spacer; } float[] row = GetRow(rowX); for (int j = 0; j < row.Length; j++) { stringBuilder.AppendFormat(text, row[j] * scaleValue); } Debug.Log(stringBuilder.ToString()); } public void DumpColumn(int columnZ, float scaleValue, int precision, string spacer) { StringBuilder stringBuilder = new StringBuilder(); string text = ""; if (precision == 0) { text = "{0:0}"; } else { text = "{0:0."; for (int i = 0; i < precision; i++) { text += "0"; } text += "}"; } if (!string.IsNullOrEmpty(spacer)) { text += spacer; } float[] column = GetColumn(columnZ); for (int j = 0; j < column.Length; j++) { stringBuilder.AppendFormat(text, column[j] * scaleValue); } Debug.Log(stringBuilder.ToString()); } } }