Files
UltimateFishing2020/Assets/Scripts/Assembly-CSharp/Gaia/HeightMap.cs
2026-03-04 10:03:45 +08:00

2332 lines
53 KiB
C#

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());
}
}
}