ThomagicRenderer/Runtime/CellLayout.cs

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