184 lines
6.3 KiB
C#
184 lines
6.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Unity.Collections;
|
|
using Unity.HLODSystem.SpaceManager;
|
|
using Unity.HLODSystem.Utils;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.HLODSystem
|
|
{
|
|
|
|
//TODO: Separate Data and View
|
|
public class Heightmap
|
|
{
|
|
private int m_width;
|
|
private int m_height;
|
|
private float[,] m_heights;
|
|
|
|
private Vector3 m_size;
|
|
private Vector3 m_scale;
|
|
private Vector3 m_offset;
|
|
|
|
public Vector3 Size => m_size;
|
|
public Vector3 Offset => m_offset;
|
|
|
|
public int Width => m_width;
|
|
public int Height => m_height;
|
|
|
|
|
|
|
|
public float this[int z, int x]
|
|
{
|
|
get { return m_heights[z + 1, x + 1]; }
|
|
}
|
|
|
|
private Heightmap()
|
|
{
|
|
}
|
|
|
|
public Heightmap(int width, int height, Vector3 size, float[,] heights)
|
|
{
|
|
m_width = width;
|
|
m_height = height;
|
|
m_heights = new float[height + 2, width + 2];
|
|
|
|
for (int x = 0; x < width; ++x)
|
|
{
|
|
for (int z = 0; z < height; ++z)
|
|
{
|
|
m_heights[z+1, x+1] = heights[z, x];
|
|
}
|
|
}
|
|
|
|
for (int x = 1; x < width + 2; ++x)
|
|
{
|
|
m_heights[0, x] = m_heights[1, x];
|
|
m_heights[height + 1, x] = m_heights[height, x];
|
|
}
|
|
for (int z = 1; z < height + 2; ++z)
|
|
{
|
|
m_heights[z, 0] = m_heights[z, 1];
|
|
m_heights[z, width + 1] = m_heights[z, width];
|
|
}
|
|
|
|
m_heights[0, 0] = (m_heights[1, 0] + m_heights[0, 1]) * 0.5f;
|
|
m_heights[0, width+1] = (m_heights[1, width+1] + m_heights[0, width]) * 0.5f;
|
|
m_heights[height+1, 0] = (m_heights[height, 0] + m_heights[height+1, 1]) * 0.5f;
|
|
m_heights[height+1, width+1] = (m_heights[height, width+1] + m_heights[height+1, width]) * 0.5f;
|
|
|
|
m_size = size;
|
|
m_scale = new Vector3(size.x / (width - 1), size.y, size.z / (height - 1));
|
|
}
|
|
|
|
public Heightmap GetHeightmap(int beginX, int beginZ, int width, int height)
|
|
{
|
|
Heightmap heightmap = new Heightmap();
|
|
heightmap.m_width = width;
|
|
heightmap.m_height = height;
|
|
|
|
heightmap.m_offset = new Vector3(beginX * m_scale.x, 0.0f, beginZ * m_scale.z);
|
|
heightmap.m_size = new Vector3(m_scale.x * (width-1), m_size.y, m_scale.z * (height-1));
|
|
heightmap.m_scale = m_scale;
|
|
|
|
heightmap.m_heights = new float[height+2, width+2];
|
|
|
|
for (int x = 0; x < width+2; ++x)
|
|
{
|
|
for (int z = 0; z < height+2; ++z)
|
|
{
|
|
heightmap.m_heights[z, x] = m_heights[z + beginZ, x + beginX];
|
|
}
|
|
}
|
|
|
|
return heightmap;
|
|
}
|
|
|
|
public Vector3 GetInterpolatedNormal(float x, float y)
|
|
{
|
|
float fx = x * (m_width - 1) + 1;
|
|
float fy = y * (m_height - 1) + 1;
|
|
int lx = (int) fx;
|
|
int ly = (int) fy;
|
|
|
|
Vector3 n00 = CalculateNormalSobel(lx + 0, ly + 0);
|
|
Vector3 n10 = CalculateNormalSobel(lx + 1, ly + 0);
|
|
Vector3 n01 = CalculateNormalSobel(lx + 0, ly + 1);
|
|
Vector3 n11 = CalculateNormalSobel(lx + 1, ly + 1);
|
|
|
|
float u = fx - lx;
|
|
float v = fy - ly;
|
|
|
|
Vector3 s = Vector3.Slerp(n00, n10, u);
|
|
Vector3 t = Vector3.Slerp(n01, n11, u);
|
|
Vector3 value = Vector3.Slerp(s, t, v);
|
|
|
|
value = Vector3.Normalize(value);
|
|
return value;
|
|
}
|
|
|
|
|
|
Vector3 CalculateNormalSobel(int x, int y)
|
|
{
|
|
return CalculateNormalSobel(x, y, m_scale);
|
|
}
|
|
|
|
float CalculateHeight(int x, int y, float scale)
|
|
{
|
|
x = Mathf.Clamp(x, 0, m_width + 1);
|
|
y = Mathf.Clamp(y, 0, m_height + 1);
|
|
return m_heights[y, x] * scale;
|
|
}
|
|
|
|
|
|
Vector3 CalculateNormalSobel(int x, int y, Vector3 scale)
|
|
{
|
|
float dY, dX;
|
|
|
|
// Do X sobel filter
|
|
dX = CalculateHeight(x - 1, y - 1, scale.y) * -1.0F;
|
|
dX += CalculateHeight(x - 1, y, scale.y) * -2.0F;
|
|
dX += CalculateHeight(x - 1, y + 1, scale.y) * -1.0F;
|
|
dX += CalculateHeight(x + 1, y - 1, scale.y) * 1.0F;
|
|
dX += CalculateHeight(x + 1, y, scale.y) * 2.0F;
|
|
dX += CalculateHeight(x + 1, y + 1, scale.y) * 1.0F;
|
|
|
|
dX /= scale.x;
|
|
|
|
// Do Y sobel filter
|
|
dY = CalculateHeight(x - 1, y - 1, scale.y) * -1.0F;
|
|
dY += CalculateHeight(x, y - 1, scale.y) * -2.0F;
|
|
dY += CalculateHeight(x + 1, y - 1, scale.y) * -1.0F;
|
|
dY += CalculateHeight(x - 1, y + 1, scale.y) * 1.0F;
|
|
dY += CalculateHeight(x, y + 1, scale.y) * 2.0F;
|
|
dY += CalculateHeight(x + 1, y + 1, scale.y) * 1.0F;
|
|
dY /= scale.z;
|
|
|
|
// Cross Product of components of gradient reduces to
|
|
Vector3 normal = new Vector3(-dX, 8, -dY);
|
|
return Vector3.Normalize(normal);
|
|
}
|
|
}
|
|
|
|
public class HLODBuildInfo : IDisposable
|
|
{
|
|
private NativeArray<int> m_detector = new NativeArray<int>(1, Allocator.Persistent);
|
|
|
|
public string Name = "";
|
|
//TODO: remove this.
|
|
public int ParentIndex = -1;
|
|
public SpaceNode Target;
|
|
|
|
public DisposableList<WorkingObject> WorkingObjects = new DisposableList<WorkingObject>();
|
|
public List<WorkingCollider> Colliders = new List<WorkingCollider>();
|
|
public List<int> Distances = new List<int>();
|
|
|
|
|
|
public Heightmap Heightmap;
|
|
|
|
public void Dispose()
|
|
{
|
|
WorkingObjects.Dispose();
|
|
m_detector.Dispose();
|
|
}
|
|
}
|
|
} |