199 lines
5.2 KiB
C#
199 lines
5.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|