test(physics): Phase W triage — fix stale GetMaxSpeed tests; file #104 (particle cell-clip deferral)

GetMaxSpeed deliberately does NOT branch on ForwardCommand — it returns RunAnimSpeed x run-rate as the InterpolationManager.AdjustOffset catch-up speed (doc comment + ACE MotionInterp.cs:670-678, retail-verified; the slow catch-up fixed the 1-Hz remote-blip). The 3 failing tests (WalkForward/WalkBackward/Idle) asserted a REMOVED command-branching design. Consolidated into one [Theory] pinning the no-branch contract across commands.

Also files #104 (LOW): scene VFX particles not clipped to the PView visible cell set — deferred out of the Phase W seal (entity bleed already gated by Stage 5; scene particles depth-tested; sky particles scissored). Needs OwnerCellId plumbing (~6-8 files).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-02 16:37:49 +02:00
parent 872dd34943
commit 21609a7cd7
2 changed files with 47 additions and 29 deletions

View file

@ -44,6 +44,37 @@ Copy this block when adding a new issue:
---
## #104 — Scene VFX particles not clipped to the PView visible cell set
**Status:** OPEN
**Severity:** LOW
**Filed:** 2026-06-02
**Component:** render, vfx
**Description:** Scene-pass VFX particles (spell effects, smoke) are drawn from their world-space
position only; they are not gated by the PView visible cell set, so a particle emitter in a
sealed (non-visible) cell can bleed past a wall edge. In practice this is mostly masked: scene
particles ARE depth-tested (walls occlude most of their geometry), the dominant indoor entity
bleed is already gated by the Phase W Stage 5 entity gate
(`WbDrawDispatcher.EntityPassesVisibleCellGate`), and Stage 4 already scissors the SKY particle
passes to the doorway. The residual is the occasional additive particle visible past a wall edge.
**Root cause / status:** Particles carry no cell id. `ParticleEmitter` (`Vfx/VfxModel.cs`) has
`AnchorPos` + `AttachedObjectId` but no owning-cell id; `Particle` has a world `Position` only. A
clean fix adds an `OwnerCellId` to `ParticleEmitter` (set at spawn from the owning entity's
`ParentCellId`), threads a `HashSet<uint>? visibleCellIds` into `ParticleRenderer.BuildDrawList`,
and skips emitters whose `OwnerCellId` ∉ the visible set. That touches `IParticleSystem.SpawnEmitter`,
`ParticleSystem`, `ParticleHookSink`, and the `SpawnEmitter` call sites (~68 files) — a plumbing
pass, deliberately deferred out of the Phase W seal (which covers sky/terrain/walls/entities).
**Files:** `src/AcDream.App/Rendering/ParticleRenderer.cs` (BuildDrawList), `src/AcDream.Core/Vfx/`
(ParticleSystem, VfxModel), `src/AcDream.App/Rendering/Vfx/ParticleHookSink.cs`.
**Acceptance:** A scene-particle emitter in a non-visible cell does not draw; outdoor particles
(null `visibleCellIds`) unaffected; no regression on fireplace/spell VFX in the visible cell.
---
## #103 — Phase A8.F portal-frame indoor rendering broken at runtime (visual-gate failure)
**Status:** SUPERSEDED 2026-05-30 by **Phase U (Unified Render Pipeline)**. The