180 lines
7.8 KiB
C#
180 lines
7.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Assets.ThoMagic.Renderer
|
|
{
|
|
public class CellLayout
|
|
{
|
|
public Vector3 Origin;
|
|
private readonly int _cellsX;
|
|
private readonly int _cellsZ;
|
|
private readonly float _cellSizeX;
|
|
private readonly float _cellSizeZ;
|
|
private readonly Cell[] _cells;
|
|
private readonly Dictionary<int, Plane[]> _cameraPlanes = new Dictionary<int, Plane[]>();
|
|
private const int _planeCount = 6;
|
|
private int _cachedFrameId;
|
|
private Camera _cachedCamera;
|
|
private Plane[] _planes = new Plane[6];
|
|
private Double3[] _absNormals = new Double3[6];
|
|
private Double3[] _planeNormal = new Double3[6];
|
|
private double[] _planeDistance = new double[6];
|
|
|
|
public CellLayout(float cellSizeX, float cellSizeZ, Bounds worldBounds)
|
|
{
|
|
Origin = worldBounds.min;
|
|
_cellSizeX = cellSizeX;
|
|
_cellSizeZ = cellSizeZ;
|
|
_cellsX = Mathf.CeilToInt(worldBounds.size.x / _cellSizeX);
|
|
_cellsZ = Mathf.CeilToInt(worldBounds.size.z / _cellSizeZ);
|
|
_cells = new Cell[_cellsX * _cellsZ];
|
|
float num1 = _cellSizeX * 0.5f;
|
|
float num2 = _cellSizeZ * 0.5f;
|
|
for (int index1 = 0; index1 < _cellsZ; ++index1)
|
|
{
|
|
for (int index2 = 0; index2 < _cellsX; ++index2)
|
|
{
|
|
int index3 = index1 * _cellsX + index2;
|
|
float num3 = (float)index2 * _cellSizeX + num1;
|
|
float num4 = (float)index1 * _cellSizeZ + num2;
|
|
_cells[index3].HeightMin = double.MaxValue;
|
|
_cells[index3].HeightMax = double.MinValue;
|
|
_cells[index3].Center = new Double3((double)num3, 0.0, (double)num4);
|
|
_cells[index3].Extends = new Double3((double)num1, double.NaN, (double)num2);
|
|
}
|
|
}
|
|
}
|
|
|
|
public Cell[] GetCells() => _cells;
|
|
|
|
public int GetCellCount() => _cells.Length;
|
|
|
|
public void OverwriteCellHeightBounds()
|
|
{
|
|
int length = _cells.Length;
|
|
for (int index = 0; index < length; ++index)
|
|
_cells[index].HeightOverwrite = true;
|
|
}
|
|
|
|
public void SetCellHeightBounds(int cellIndex, double min, double max)
|
|
{
|
|
ref Cell local = ref _cells[cellIndex];
|
|
if (local.HeightOverwrite)
|
|
{
|
|
local.HeightOverwrite = false;
|
|
local.HeightMax = max;
|
|
local.HeightMin = min;
|
|
}
|
|
else
|
|
{
|
|
local.HeightMax = Math.Max(local.HeightMax, max);
|
|
local.HeightMin = Math.Min(local.HeightMin, min);
|
|
}
|
|
local.Center = new Double3(local.Center.x, (local.HeightMax + local.HeightMin) * 0.5, local.Center.z);
|
|
local.Extends = new Double3(local.Extends.x, (local.HeightMax + local.HeightMin) * 0.5, local.Extends.z);
|
|
}
|
|
|
|
public void Update(Camera camera, int frameId, bool frustumCulling)
|
|
{
|
|
if (camera == _cachedCamera && frameId == _cachedFrameId)
|
|
return;
|
|
_cachedCamera = camera;
|
|
_cachedFrameId = frameId;
|
|
Plane[] planes;
|
|
if (!_cameraPlanes.TryGetValue(((object)camera).GetHashCode(), out planes))
|
|
_cameraPlanes[((object)camera).GetHashCode()] = planes = new Plane[6];
|
|
GeometryUtility.CalculateFrustumPlanes(camera, planes);
|
|
SetPlanes(planes);
|
|
double x1 = camera.transform.position.x;
|
|
double z1 = camera.transform.position.z;
|
|
Double3 absNormal1 = _absNormals[0];
|
|
Double3 absNormal2 = _absNormals[1];
|
|
Double3 absNormal3 = _absNormals[2];
|
|
Double3 absNormal4 = _absNormals[3];
|
|
Double3 absNormal5 = _absNormals[4];
|
|
Double3 absNormal6 = _absNormals[5];
|
|
Double3 double3_1 = _planeNormal[0];
|
|
Double3 double3_2 = _planeNormal[1];
|
|
Double3 double3_3 = _planeNormal[2];
|
|
Double3 double3_4 = _planeNormal[3];
|
|
Double3 double3_5 = _planeNormal[4];
|
|
Double3 double3_6 = _planeNormal[5];
|
|
double num1 = _planeDistance[0];
|
|
double num2 = _planeDistance[1];
|
|
double num3 = _planeDistance[2];
|
|
double num4 = _planeDistance[3];
|
|
double num5 = _planeDistance[4];
|
|
double num6 = _planeDistance[5];
|
|
double x2 = (double)Origin.x;
|
|
double y = (double)Origin.y;
|
|
double z2 = (double)Origin.z;
|
|
int length = _cells.Length;
|
|
for (int index = 0; index < length; ++index)
|
|
{
|
|
ref Cell local = ref _cells[index];
|
|
double num7 = local.Center.x + x2;
|
|
double num8 = local.Center.y + y;
|
|
double num9 = local.Center.z + z2;
|
|
Double3 extends = local.Extends;
|
|
local.DistanceX = Math.Abs(x1 - num7);
|
|
local.DistanceZ = Math.Abs(z1 - num9);
|
|
if (frustumCulling && !double.IsNaN(extends.y))
|
|
{
|
|
bool flag = extends.x * absNormal1.x + extends.y * absNormal1.y + extends.z * absNormal1.z + (double3_1.x * num7 + double3_1.y * num8 + double3_1.z * num9) < -num1 || extends.x * absNormal2.x + extends.y * absNormal2.y + extends.z * absNormal2.z + (double3_2.x * num7 + double3_2.y * num8 + double3_2.z * num9) < -num2 || extends.x * absNormal3.x + extends.y * absNormal3.y + extends.z * absNormal3.z + (double3_3.x * num7 + double3_3.y * num8 + double3_3.z * num9) < -num3 || extends.x * absNormal4.x + extends.y * absNormal4.y + extends.z * absNormal4.z + (double3_4.x * num7 + double3_4.y * num8 + double3_4.z * num9) < -num4 || extends.x * absNormal5.x + extends.y * absNormal5.y + extends.z * absNormal5.z + (double3_5.x * num7 + double3_5.y * num8 + double3_5.z * num9) < -num5 || extends.x * absNormal6.x + extends.y * absNormal6.y + extends.z * absNormal6.z + (double3_6.x * num7 + double3_6.y * num8 + double3_6.z * num9) < -num6;
|
|
local.InFrustum = !flag;
|
|
}
|
|
else
|
|
local.InFrustum = true;
|
|
}
|
|
}
|
|
|
|
private void SetPlanes(Plane[] planes)
|
|
{
|
|
_planes = planes;
|
|
for (int index = 0; index < 6; ++index)
|
|
{
|
|
Plane plane = _planes[index];
|
|
Vector3 vector = plane.normal;
|
|
Double3 double3 = new Double3(in vector);
|
|
_absNormals[index] = new Double3(Math.Abs(double3.x), Math.Abs(double3.y), Math.Abs(double3.z));
|
|
_planeNormal[index] = double3;
|
|
_planeDistance[index] = plane.distance;
|
|
}
|
|
}
|
|
|
|
public struct Cell
|
|
{
|
|
public double DistanceX;
|
|
public double DistanceZ;
|
|
public bool InFrustum;
|
|
public Double3 Center;
|
|
public Double3 Extends;
|
|
public double HeightMin;
|
|
public double HeightMax;
|
|
public bool HeightOverwrite;
|
|
}
|
|
|
|
public readonly struct Double3
|
|
{
|
|
public readonly double x;
|
|
public readonly double y;
|
|
public readonly double z;
|
|
|
|
public Double3(in Vector3 vector)
|
|
{
|
|
x = (double)vector.x;
|
|
y = (double)vector.y;
|
|
z = (double)vector.z;
|
|
}
|
|
|
|
public Double3(double x, double y, double z)
|
|
{
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
}
|
|
}
|
|
}
|
|
}
|