ClientServer/Client/Assets/Koenigz/Perfect Culling/Scripts/PerfectCullingBakingBehaviour.cs
TG9six 03a642d635 first push
first push
2025-09-06 17:17:39 +04:00

159 lines
5.7 KiB
C#

// Perfect Culling (C) 2021 Patrick König
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Serialization;
namespace Koenigz.PerfectCulling
{
/// <summary>
/// This is the base class that provides an easy interface for baking.
/// Hopefully the built-in baking scripts are sufficient but if you need something else you can inherit it and roll your own.
/// </summary>
public abstract class PerfectCullingBakingBehaviour : MonoBehaviour
{
public enum EOutOfBoundsBehaviour
{
ClampToNearestCell,
Cull,
IgnoreDoNothing,
}
[Tooltip("Try to find a non-empty cell if we hit an empty one?")]
public bool searchForNonEmptyCells = false;
[Tooltip("What should happen if we encounter an empty cell? Cull everything or make everything visible?")]
public EEmptyCellCullBehaviour emptyCellCullBehaviour = EEmptyCellCullBehaviour.CullEverything;
[Tooltip("Should this volume be culled if the camera is not inside it or should the camera position be clamped to the nearest cell?")]
public EOutOfBoundsBehaviour outOfBoundsBehaviour = EOutOfBoundsBehaviour.ClampToNearestCell;
private IActiveSamplingProvider[] m_activeSamplingProviders;
public IActiveSamplingProvider[] QuerySamplingProviders()
{
return GetComponentsInChildren<IActiveSamplingProvider>();
}
public void InitializeAllSamplingProviders()
{
m_activeSamplingProviders = GetComponentsInChildren<IActiveSamplingProvider>();
DefaultSamplingProvider.InitializeSamplingProvider();
foreach (var provider in m_activeSamplingProviders)
{
provider.InitializeSamplingProvider();
}
}
public bool SamplingProvidersIsPositionActive(Vector3 pos)
{
switch (DefaultSamplingProvider.IsSamplingPositionActive(this, pos))
{
case DefaultSamplingProvider.Result.IncludeCell:
return true;
case DefaultSamplingProvider.Result.ExcludeCell:
return false;
}
foreach (IActiveSamplingProvider provider in m_activeSamplingProviders)
{
if (!provider.IsSamplingPositionActive(this, pos))
{
return false;
}
}
return true;
}
[SerializeField] public PerfectCullingBakeGroup[] bakeGroups = System.Array.Empty<PerfectCullingBakeGroup>(); // Important to initialize or AddRange will fail
[SerializeField] public List<Renderer> additionalOccluders = new List<Renderer>();
public virtual PerfectCullingBakeData BakeData { get; } = null;
[System.NonSerialized] public int TotalVertexCount = 0;
private bool[] m_renderersState;
public virtual void Start()
{
TotalVertexCount = 0;
m_renderersState = new bool[bakeGroups.Length];
foreach (PerfectCullingBakeGroup group in bakeGroups)
{
group.Init();
#if UNITY_EDITOR
TotalVertexCount += group.vertexCount;
#endif
}
}
public void QueueToggleAllRenderers(bool state)
{
try
{
for (var index = 0; index < bakeGroups.Length; index++)
{
m_renderersState[index] = state;
}
}
catch (Exception e)
{
// ignored
}
}
/// <summary>
/// Queue up renderer state change. This will not take effect until ExecuteQueue was called.
/// </summary>
public void QueueToggleRenderer(int index, bool state, out PerfectCullingBakeGroup modifiedBakeGroup)
{
m_renderersState[index] = state;
modifiedBakeGroup = bakeGroups[index];
}
/// <summary>
/// Applies renderers state changes.
/// </summary>
public void ExecuteQueue(bool forceNullCheck = false)
{
for (var index = 0; index < bakeGroups.Length; index++)
{
PerfectCullingBakeGroup r = bakeGroups[index];
r?.Toggle(m_renderersState[index], forceNullCheck);
}
}
public virtual void SetBakeData(PerfectCullingBakeData bakeData) => throw new System.NotImplementedException();
public virtual List<Vector3> GetSamplingPositions(Space space = Space.Self) => throw new System.NotImplementedException();
public virtual void GetIndicesForWorldPos(Vector3 worldPos, List<ushort> indices) => throw new System.NotImplementedException();
public virtual int GetIndexForWorldPos(Vector3 worldPos, out bool isOutOfBounds) => throw new System.NotImplementedException();
public virtual void GetIndicesForIndex(int index, List<ushort> indices) =>
BakeData.SampleAtIndex(index, indices);
public virtual bool PreBake() => throw new System.NotImplementedException();
public virtual void PostBake() => throw new System.NotImplementedException();
public virtual int GetBakeHash() => throw new System.NotImplementedException();
public virtual void CullAdditionalOccluders(ref HashSet<Renderer> additionalOccluders) =>
throw new System.NotImplementedException();
}
}