Files
HauntedBloodlines/Assets/HTraceWSGI/Scripts/PassHandlers/VoxelsHandler.cs
2025-05-29 22:31:40 +03:00

318 lines
10 KiB
C#

using System;
using HTraceWSGI.Scripts.Globals;
using HTraceWSGI.Scripts.Infrastructure;
using HTraceWSGI.Scripts.Passes;
using HTraceWSGI.Scripts.Pipeline;
using HTraceWSGI.Scripts.Structs;
using HTraceWSGI.Scripts.VoxelCameras;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
namespace HTraceWSGI.Scripts.PassHandlers
{
[ExecuteInEditMode]
internal class VoxelsHandler : PassHandler
{
private bool _initialized;
//Debug fields
public bool ShowVoxelBounds = false;
internal Bounds BoundsGizmo;
internal Bounds BoundsGizmoFromUI = new Bounds();
private VoxelizationPassConstant _voxelizationPassConstant;
private VoxelizationPassPartial _voxelizationPassPartial;
private Transform _prevAttachTo;
private VoxelizationUpdateMode _prevVoxelizationUpdateMode;
private int _prevLodMax;
public bool NeedToReallocForUI
{
get { return _needToReallocForUI; }
}
//UI fields for Apply Params button
private bool _needToReallocForUI = false;
private float _prevDensityUI;
private int _prevVoxelBoundsUI;
private int _prevOverrideBoundsHeightUI;
private void OnEnable()
{
}
public void Initialize(CustomPass[] passes)
{
for (int index = 0; index < passes.Length; index++)
{
if (passes[index] is VoxelizationPassConstant voxelizationPassConstant)
_voxelizationPassConstant = voxelizationPassConstant;
if (passes[index] is VoxelizationPassPartial voxelizationPassPassPartial)
_voxelizationPassPartial = voxelizationPassPassPartial;
}
CreateVoxelCamera();
CreateVoxelCullingCamera();
CreateVoxelOctantCamera();
CreateHTraceCameraDirectional();
SwitchPass();
VoxelizationRuntimeData.FullVoxelization = false;
VoxelizationRuntimeData.OnReallocTextures += ReallocTextures;
if (HResources.VoxelizationData.AttachTo == null && Camera.main != null)
HResources.VoxelizationData.AttachTo = Camera.main.transform;
_prevAttachTo = HResources.VoxelizationData.AttachTo;
_initialized = true;
}
private void ReallocTextures()
{
_needToReallocForUI = false;
}
private void SwitchPass()
{
switch (_prevVoxelizationUpdateMode)
{
case VoxelizationUpdateMode.Constant:
_voxelizationPassConstant.Release();
_voxelizationPassConstant.enabled = false;
break;
case VoxelizationUpdateMode.Partial:
_voxelizationPassPartial.Release();
_voxelizationPassPartial.enabled = false;
break;
}
switch (HResources.VoxelizationData.VoxelizationUpdateMode)
{
case VoxelizationUpdateMode.Constant:
_voxelizationPassConstant.Initialize();
break;
case VoxelizationUpdateMode.Partial:
_voxelizationPassPartial.Initialize();
break;
}
_prevVoxelizationUpdateMode = HResources.VoxelizationData.VoxelizationUpdateMode;
VoxelizationRuntimeData.VoxelizationModeChanged = true;
}
protected override void Update()
{
base.Update();
if (!_initialized || HResources.VoxelizationData == null || VoxelizationRuntimeData.FakeDirectionalCamera == null)
return;
if (_prevVoxelizationUpdateMode != HResources.VoxelizationData.VoxelizationUpdateMode)
SwitchPass();
//gizmo update for camera bounds
#if UNITY_EDITOR
if (Application.isEditor)
{
BoundsGizmo = GetVoxelCameraBounds();
SetVoxelCameraBounds(BoundsGizmo);
}
#endif
CheckBounds();
HResources.VoxelizationData.UpdateData();
CheckPrevValues();
}
public void OnSceneGUI()
{
//gizmo update
BoundsGizmo = GetVoxelCameraBounds();
if (BoundsGizmoFromUI.size != BoundsGizmo.size /* && _boundsGizmoFromUIEdited*/)
{
SetVoxelCameraBounds(BoundsGizmoFromUI);
BoundsGizmo = GetVoxelCameraBounds();
// _boundsGizmoFromUIEdited = false;
}
}
public Bounds GetVoxelCameraBounds()
{
Vector3 boundCenter = VoxelizationRuntimeData.VoxelCamera.transform.position;
float height = HResources.VoxelizationData.OverrideBoundsHeightEnable == false ? HResources.VoxelizationData.VoxelBounds : HResources.VoxelizationData.OverrideBoundsHeight;
if (HResources.VoxelizationData.GroundLevelEnable == true && (VoxelizationRuntimeData.VoxelCamera.transform.position.y - height / 2) < HResources.VoxelizationData.GroundLevel)
{
boundCenter = new Vector3(VoxelizationRuntimeData.VoxelCamera.transform.position.x, HResources.VoxelizationData.GroundLevel + height / 2, VoxelizationRuntimeData.VoxelCamera.transform.position.z);
}
BoundsGizmo.center = boundCenter;
BoundsGizmo.size = new Vector3(
HResources.VoxelizationData.VoxelBounds,
height,
HResources.VoxelizationData.VoxelBounds);
return BoundsGizmo;
}
public void SetVoxelCameraBounds(Bounds newBounds)
{
if (newBounds.size.x < 1 || newBounds.size.y < 1 || newBounds.size.z < 1)
return;
int newWidthDepth = 0;
if ((int)BoundsGizmo.size.x != (int)newBounds.size.x)
newWidthDepth = (int)newBounds.size.x;
if ((int)BoundsGizmo.size.z != (int)newBounds.size.z)
newWidthDepth = (int)newBounds.size.z;
if (newWidthDepth == 0)
{
if (HResources.VoxelizationData.OverrideBoundsHeightEnable == false)
newWidthDepth = (int)newBounds.size.y;
else
newWidthDepth = (int)newBounds.size.x;
}
HResources.VoxelizationData.VoxelBounds = newWidthDepth;
HResources.VoxelizationData.OverrideBoundsHeight = HResources.VoxelizationData.OverrideBoundsHeightEnable == true ? (int)newBounds.size.y : HResources.VoxelizationData.OverrideBoundsHeight;
if (HResources.VoxelizationData.OverrideBoundsHeightEnable == true)
HResources.VoxelizationData.OverrideBoundsHeight = Mathf.Clamp(HResources.VoxelizationData.OverrideBoundsHeight, 1, HResources.VoxelizationData.VoxelBounds);
// float height = HResources.VoxelizationData.OverrideBoundsHeightEnable == false ? HResources.VoxelizationData.VoxelBounds : HResources.VoxelizationData.OverrideBoundsHeight;
// if (HResources.VoxelizationData.GroundLevelEnable == true && (VoxelizationRuntimeData.VoxelCamera.transform.position.y - height / 2) <= HResources.VoxelizationData.GroundLevel)
// {
// _boundsGizmo.center = newBounds.center;
// }
//_boundsGizmo.size = newBounds.size;
BoundsGizmo = GetVoxelCameraBounds();
}
private void CheckBounds()
{
if (VoxelizationRuntimeData.CheckBounds(HResources.VoxelizationData.VoxelDensity, HResources.VoxelizationData.VoxelBounds, HResources.VoxelizationData.OverrideBoundsHeight))
{
if (Time.frameCount > 3) // hack for enter and exit in Play mode
_needToReallocForUI = true;
VoxelizationRuntimeData.SetParamsForApplyButton(HResources.VoxelizationData.VoxelDensity, HResources.VoxelizationData.VoxelBounds, HResources.VoxelizationData.OverrideBoundsHeight);
}
}
private void CheckPrevValues()
{
if (HResources.VoxelizationData.AttachTo != _prevAttachTo)
{
_prevAttachTo = HResources.VoxelizationData.AttachTo;
VoxelizationRuntimeData.OnReallocTextures?.Invoke();
}
if (HResources.VoxelizationData.LODMax != _prevLodMax)
{
_prevLodMax = HResources.VoxelizationData.LODMax;
VoxelizationRuntimeData.FullVoxelization = true;
}
}
private void CreateVoxelCamera()
{
if (VoxelizationRuntimeData.VoxelCamera != null)
{
VoxelizationRuntimeData.VoxelCamera.Initialize(this);
return;
}
GameObject cameraGO = new GameObject(HTraceNames.HTRACE_VOXEL_CAMERA_NAME);
cameraGO.layer = gameObject.layer;
cameraGO.hideFlags = HResources.DebugData.ShowBowels ? HideFlags.None : HideFlags.HideAndDontSave;
// cameraGO.transform.parent = Camera.main.transform;
// cameraGO.transform.localPosition = Vector3.zero;
VoxelizationRuntimeData.VoxelCamera = cameraGO.AddComponent<VoxelCamera>();
VoxelizationRuntimeData.VoxelCamera.Initialize(this);
}
private void CreateVoxelCullingCamera()
{
if (VoxelizationRuntimeData.CullingCamera != null)
{
VoxelizationRuntimeData.CullingCamera.Initialize();
return;
}
GameObject cameraGO = new GameObject(HTraceNames.HTRACE_VOXEL_CULLING_CAMERA_NAME);
cameraGO.layer = gameObject.layer;
cameraGO.transform.parent = VoxelizationRuntimeData.VoxelCamera.gameObject.transform;
cameraGO.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
cameraGO.hideFlags = HResources.DebugData.ShowBowels ? HideFlags.None : HideFlags.HideAndDontSave;
// cameraGO.transform.parent = Camera.main.transform;
// cameraGO.transform.localPosition = Vector3.zero;
VoxelizationRuntimeData.CullingCamera = cameraGO.AddComponent<VoxelCullingCamera>();
VoxelizationRuntimeData.CullingCamera.Initialize();
}
private void CreateVoxelOctantCamera()
{
if (VoxelizationRuntimeData.VoxelOctantCamera != null)
{
VoxelizationRuntimeData.VoxelOctantCamera.Initialize();
return;
}
GameObject cameraGO = new GameObject(HTraceNames.HTRACE_VOXEL_OCTANT_CAMERA_NAME);
cameraGO.layer = gameObject.layer;
cameraGO.transform.parent = VoxelizationRuntimeData.VoxelCamera.gameObject.transform;
cameraGO.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
cameraGO.hideFlags = HResources.DebugData.ShowBowels ? HideFlags.None : HideFlags.HideAndDontSave;
// cameraGO.transform.parent = Camera.main.transform;
// cameraGO.transform.localPosition = Vector3.zero;
VoxelizationRuntimeData.VoxelOctantCamera = cameraGO.AddComponent<VoxelOctantCamera>();
VoxelizationRuntimeData.VoxelOctantCamera.Initialize();
}
private void CreateHTraceCameraDirectional()
{
if (VoxelizationRuntimeData.FakeDirectionalCamera != null)
{
VoxelizationRuntimeData.FakeDirectionalCamera.Initialize(this);
return;
}
GameObject cameraFromFakeDirLightGo = new GameObject("HTraceDirectionalCameraHandler");
cameraFromFakeDirLightGo.layer = gameObject.layer;
cameraFromFakeDirLightGo.hideFlags = HResources.DebugData.ShowBowels ? HideFlags.None : HideFlags.HideAndDontSave;
VoxelizationRuntimeData.FakeDirectionalCamera = cameraFromFakeDirLightGo.AddComponent<HTraceDirectionalCamera>();
VoxelizationRuntimeData.FakeDirectionalCamera.Initialize(this);
}
public bool PingVoxelsHandler(VoxelCamera voxelCamera)
{
return VoxelizationRuntimeData.VoxelCamera != voxelCamera;
}
public bool PingFakeDirLight(HTraceDirectionalCamera camera)
{
return VoxelizationRuntimeData.FakeDirectionalCamera != camera;
}
private void OnDestroy()
{
Release();
}
internal void Release()
{
_voxelizationPassConstant?.Release();
_voxelizationPassPartial?.Release();
VoxelizationRuntimeData.OnReallocTextures -= ReallocTextures;
_initialized = false;
}
}
}