Revert "fix(render): Phase A8 — animated entities exempt from stencil-gated outdoor pass"

This reverts commit a2ad5c1ac4.
This commit is contained in:
Erik 2026-05-26 09:38:37 +02:00
parent c897a179fa
commit 96f8bd2bd7
2 changed files with 10 additions and 87 deletions

View file

@ -357,12 +357,9 @@ public sealed unsafe class WbDrawDispatcher : IDisposable
foreach (var animatedId in animatedEntityIds)
{
if (!entry.AnimatedById.TryGetValue(animatedId, out var entity)) continue;
// Phase A8 fix: every entity in this loop IS animated (we're iterating
// animatedEntityIds). Animated entities (player, NPCs, monsters) are live
// server-spawned objects that have ParentCellId == null but must ALWAYS
// render in the indoor pass — never stencil-gated by OutdoorOnly.
// Otherwise the character disappears when the camera enters a building.
if (set == EntitySet.OutdoorOnly) continue;
// Phase A8: EntitySet partition for indoor/outdoor split passes.
if (set == EntitySet.IndoorOnly && !entity.ParentCellId.HasValue) continue;
if (set == EntitySet.OutdoorOnly && entity.ParentCellId.HasValue) continue;
if (entity.MeshRefs.Count == 0) continue;
if (entity.ParentCellId.HasValue && visibleCellIds is not null
&& !visibleCellIds.Contains(entity.ParentCellId.Value)) continue;
@ -375,13 +372,9 @@ public sealed unsafe class WbDrawDispatcher : IDisposable
foreach (var entity in entry.Entities)
{
// Phase A8 fix: animated entities (player, NPCs, monsters) are live
// server-spawned objects with ParentCellId == null. They must ALWAYS render
// in the indoor pass — never stencil-gated by OutdoorOnly — or the character
// disappears when the camera enters a building.
bool isAnimated = animatedEntityIds is not null && animatedEntityIds.Contains(entity.Id);
if (set == EntitySet.IndoorOnly && !entity.ParentCellId.HasValue && !isAnimated) continue;
if (set == EntitySet.OutdoorOnly && (entity.ParentCellId.HasValue || isAnimated)) continue;
// Phase A8: EntitySet partition for indoor/outdoor split passes.
if (set == EntitySet.IndoorOnly && !entity.ParentCellId.HasValue) continue;
if (set == EntitySet.OutdoorOnly && entity.ParentCellId.HasValue) continue;
if (entity.MeshRefs.Count == 0) continue;
// Detect cell entity for indoor probes — first MeshRef.GfxObjId
@ -410,7 +403,7 @@ public sealed unsafe class WbDrawDispatcher : IDisposable
// Per-entity AABB frustum cull (perf #3). Animated entities bypass —
// they're tracked at landblock level + need per-frame work regardless.
// A.5 T18 Change #2: read cached AABB, refresh lazily on AabbDirty.
// Note: isAnimated already computed above for the EntitySet partition.
bool isAnimated = animatedEntityIds?.Contains(entity.Id) == true;
bool aabbVisible = true;
if (frustum is not null && !isAnimated && entry.LandblockId != neverCullLandblockId)
{
@ -1357,18 +1350,13 @@ public sealed unsafe class WbDrawDispatcher : IDisposable
public static List<uint> WalkEntitiesForTest(
IReadOnlyList<AcDream.Core.World.WorldEntity> entities,
HashSet<uint>? visibleCellIds,
EntitySet set,
HashSet<uint>? animatedEntityIds = null)
EntitySet set)
{
var output = new List<uint>();
foreach (var entity in entities)
{
// Phase A8 fix: animated entities (player, NPCs, monsters) are live
// server-spawned objects with ParentCellId == null. They must ALWAYS render
// in the indoor pass — never stencil-gated by OutdoorOnly.
bool isAnimated = animatedEntityIds is not null && animatedEntityIds.Contains(entity.Id);
if (set == EntitySet.IndoorOnly && !entity.ParentCellId.HasValue && !isAnimated) continue;
if (set == EntitySet.OutdoorOnly && (entity.ParentCellId.HasValue || isAnimated)) continue;
if (set == EntitySet.IndoorOnly && !entity.ParentCellId.HasValue) continue;
if (set == EntitySet.OutdoorOnly && entity.ParentCellId.HasValue) continue;
if (entity.MeshRefs.Count == 0) continue;
bool cellInVis = !(entity.ParentCellId.HasValue