Files
2026-02-21 16:45:37 +08:00

126 lines
4.1 KiB
C#

using UnityEngine;
namespace TT_TerrainTools
{
public static class TT_TerrainHelpers
{
public enum EDirection
{
TOP = 0,
BOTTOM = 1,
LEFT = 2,
RIGHT = 3
}
public static void FixBorders(Terrain p_terrainA, Terrain p_terrainB, EDirection p_borderA, EDirection p_borderB, float p_fade)
{
int heightmapResolution = p_terrainA.terrainData.heightmapResolution;
if (p_terrainA.terrainData.heightmapResolution != heightmapResolution || p_terrainB.terrainData.heightmapResolution != heightmapResolution)
{
Debug.LogError("TT_Terrain9Patch: both TerrainData assets must have the same 'heightmapResolution'!");
return;
}
p_fade = Mathf.Clamp01(p_fade);
bool flag = false;
bool flag2 = false;
float y = p_terrainA.transform.position.y;
float y2 = p_terrainA.terrainData.size.y;
float y3 = p_terrainB.transform.position.y;
float y4 = p_terrainB.terrainData.size.y;
float[,] directedHeights = GetDirectedHeights(p_terrainA.terrainData, p_borderA);
float[,] directedHeights2 = GetDirectedHeights(p_terrainB.terrainData, p_borderB);
for (int i = 0; i < heightmapResolution; i++)
{
float directedWorldHeight = GetDirectedWorldHeight(i, p_borderA, directedHeights, p_terrainA);
float directedWorldHeight2 = GetDirectedWorldHeight(i, p_borderB, directedHeights2, p_terrainB);
float num = directedWorldHeight * (1f - p_fade) + directedWorldHeight2 * p_fade;
SetDirectedWorldHeight(num, i, p_borderA, directedHeights, y, y2);
SetDirectedWorldHeight(num, i, p_borderB, directedHeights2, y3, y4);
flag = flag || num != directedWorldHeight;
flag2 = flag2 || num != directedWorldHeight2;
}
if (flag)
{
SetDirectedHeights(directedHeights, p_terrainA.terrainData, p_borderA);
}
if (flag2)
{
SetDirectedHeights(directedHeights2, p_terrainB.terrainData, p_borderB);
}
}
private static float GetDirectedWorldHeight(int p_index, EDirection p_border, float[,] p_heights, Terrain p_terrain)
{
return p_terrain.transform.position.y + p_terrain.terrainData.size.y * GetDirectedLocalHeight(p_index, p_border, p_heights);
}
private static float GetDirectedLocalHeight(int p_index, EDirection p_border, float[,] p_heights)
{
switch (p_border)
{
case EDirection.LEFT:
case EDirection.RIGHT:
return p_heights[p_index, 0];
default:
return p_heights[0, p_index];
}
}
private static void SetDirectedWorldHeight(float p_value, int p_index, EDirection p_border, float[,] p_heights, float p_terrainPosY, float p_terrainSizeY)
{
float p_value2 = (p_value - p_terrainPosY) / p_terrainSizeY;
SetDirectedLocalHeight(p_value2, p_index, p_border, p_heights);
}
private static void SetDirectedLocalHeight(float p_value, int p_index, EDirection p_border, float[,] p_heights)
{
switch (p_border)
{
case EDirection.LEFT:
case EDirection.RIGHT:
p_heights[p_index, 0] = p_value;
break;
default:
p_heights[0, p_index] = p_value;
break;
}
}
private static float[,] GetDirectedHeights(TerrainData p_terrainData, EDirection p_border)
{
int heightmapResolution = p_terrainData.heightmapResolution;
switch (p_border)
{
case EDirection.RIGHT:
return p_terrainData.GetHeights(heightmapResolution - 1, 0, 1, heightmapResolution);
case EDirection.LEFT:
return p_terrainData.GetHeights(0, 0, 1, heightmapResolution);
case EDirection.BOTTOM:
return p_terrainData.GetHeights(0, 0, heightmapResolution, 1);
default:
return p_terrainData.GetHeights(0, heightmapResolution - 1, heightmapResolution, 1);
}
}
private static void SetDirectedHeights(float[,] p_heights, TerrainData p_terrainData, EDirection p_border)
{
int heightmapResolution = p_terrainData.heightmapResolution;
switch (p_border)
{
case EDirection.RIGHT:
p_terrainData.SetHeights(heightmapResolution - 1, 0, p_heights);
break;
case EDirection.LEFT:
p_terrainData.SetHeights(0, 0, p_heights);
break;
case EDirection.BOTTOM:
p_terrainData.SetHeights(0, 0, p_heights);
break;
default:
p_terrainData.SetHeights(0, heightmapResolution - 1, p_heights);
break;
}
}
}
}