Files
2026-03-04 10:03:45 +08:00

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