Files
2026-05-31 14:27:52 -07:00

166 lines
5.2 KiB
C#

#if !RUKHANKA_NO_DEBUG_DRAWER
using Rukhanka.DebugDrawer;
#endif
using Unity.Burst;
using Unity.Burst.Intrinsics;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Collections;
/////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka
{
partial struct AnimationCullingSystem
{
[BurstCompile]
struct CullAnimationsJob: IJobChunk
{
[ReadOnly]
public AnimationCullingContext actx;
[ReadOnly]
public ComponentTypeHandle<ChunkWorldRenderBounds> chunkWrbTypeHandle;
[ReadOnly]
public ComponentTypeHandle<WorldRenderBounds> wrbTypeHandle;
[ReadOnly]
public ComponentTypeHandle<SkinnedMeshRendererComponent> asmTypeHandle;
[NativeDisableParallelForRestriction]
public ComponentLookup<CullAnimationsTag> cullAnimationsTagLookup;
/////////////////////////////////////////////////////////////////////////////////
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
var cee = new ChunkEntityEnumerator(useEnabledMask, chunkEnabledMask, chunk.Count);
var chunkWRB = chunk.GetChunkComponentData(ref chunkWrbTypeHandle);
var isChunkVisible = IsAxisAlignedBoxVisible(chunkWRB.Value, actx);
var wrbArr = chunk.GetNativeArray(ref wrbTypeHandle);
var asmArr = chunk.GetNativeArray(ref asmTypeHandle);
while (cee.NextEntityIndex(out var i) && isChunkVisible)
{
var arEntity = asmArr[i].animatedRigEntity;
if (arEntity == Entity.Null || !cullAnimationsTagLookup.HasComponent(arEntity))
continue;
var cullAnimsAlreadyDisabled = !cullAnimationsTagLookup.IsComponentEnabled(arEntity);
if (cullAnimsAlreadyDisabled)
{
continue;
}
var wrb = wrbArr[i].Value;
var isVisible = IsAxisAlignedBoxVisible(wrb, actx);
cullAnimationsTagLookup.SetComponentEnabled(arEntity, !isVisible);
}
}
/////////////////////////////////////////////////////////////////////////////////
internal static bool IsAxisAlignedBoxVisible(in AABB wrb, in AnimationCullingContext actx)
{
var isVisible = false;
for (var j = 0; j < actx.cullingVolumePlaneRanges.Length && !isVisible; ++j)
{
var planeRange = actx.cullingVolumePlaneRanges[j];
var isVisibleForPlaneRange = true;
for (var i = 0; i < planeRange.y && isVisibleForPlaneRange; ++i)
{
var pln = actx.cullingPlanes[i + planeRange.x];
var rg0 = pln.xyz * wrb.Extents;
var rg = math.dot(math.abs(rg0), 1);
var distance = math.dot(pln, new float4(wrb.Center, 1));
isVisibleForPlaneRange = distance > -rg;
}
isVisible |= isVisibleForPlaneRange;
}
return isVisible;
}
}
//=================================================================================================================//
#if !RUKHANKA_NO_DEBUG_DRAWER
[BurstCompile]
struct DebugDrawRendererBoundingBoxes: IJobChunk
{
public Drawer dd;
[ReadOnly]
public AnimationCullingContext actx;
[ReadOnly]
public ComponentTypeHandle<ChunkWorldRenderBounds> chunkWrbTypeHandle;
[ReadOnly]
public ComponentTypeHandle<WorldRenderBounds> wrbTypeHandle;
[ReadOnly]
public ComponentTypeHandle<SkinnedMeshRendererComponent> asmTypeHandle;
[NativeDisableParallelForRestriction]
public ComponentLookup<CullAnimationsTag> cullAnimationsTagLookup;
/////////////////////////////////////////////////////////////////////////////////
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
#if RUKHANKA_DEBUG_INFO
var cee = new ChunkEntityEnumerator(useEnabledMask, chunkEnabledMask, chunk.Count);
var chunkWRB = chunk.GetChunkComponentData(ref chunkWrbTypeHandle);
var isChunkVisible = CullAnimationsJob.IsAxisAlignedBoxVisible(chunkWRB.Value, actx);
if (actx.drawSceneBoundingBoxes)
{
var chunkBBColor = isChunkVisible ? actx.visibleChunkColor : actx.invisibleChunkColor;
var xformChunk = new RigidTransform(quaternion.identity, chunkWRB.Value.Center);
dd.DrawWireCuboid(chunkWRB.Value.Size, chunkBBColor, xformChunk);
}
var wrbArr = chunk.GetNativeArray(ref wrbTypeHandle);
var asmArr = chunk.GetNativeArray(ref asmTypeHandle);
while (cee.NextEntityIndex(out var i) && isChunkVisible)
{
var arEntity = asmArr[i].animatedRigEntity;
if (arEntity == Entity.Null || !cullAnimationsTagLookup.HasComponent(arEntity))
continue;
var isEntityVisible = !cullAnimationsTagLookup.IsComponentEnabled(arEntity);
var wrb = wrbArr[i].Value;
if (actx.drawSceneBoundingBoxes)
{
var cl = isEntityVisible ? actx.visibleRendererColor : actx.invisibleRendererColor;
var xform = new RigidTransform(quaternion.identity, wrb.Center);
dd.DrawWireCuboid(wrb.Size, cl, xform);
}
}
#endif
}
}
#endif
//=================================================================================================================//
[BurstCompile]
struct ResetAnimationCullingJob: IJobChunk
{
public ComponentTypeHandle<CullAnimationsTag> cullAnimationsTypeHandle;
/////////////////////////////////////////////////////////////////////////////////
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
chunk.SetComponentEnabledForAll(ref cullAnimationsTypeHandle, true);
}
}
}
}