fix(picker): Cluster A #86 — cell-BSP ray occlusion in WorldPicker
WorldPicker.Pick previously had no occlusion test — any entity along the click ray within maxDistance was a candidate, including ones behind walls. Adds the CellBspRayOccluder static helper that Möller-Trumbore-tests the click ray against every polygon in every currently-cached EnvCell BSP, returning the nearest wall-hit `t`. Both Pick overloads gate candidate selection by that wall-t (legacy ray-sphere via world-space `t`, screen-rect via camera-space clip.W depth — matching ScreenProjection.TryProjectSphereToScreenRect's convention). PhysicsDataCache exposes a new CellStructIds snapshot accessor so the caller can iterate without needing the private cache dictionary. CellPhysics.BSP/PhysicsPolygons/Vertices relaxed from required to nullable so test fixtures can construct a CellPhysics from Resolved alone without a real DAT BSP object. GameWindow snapshots the loaded cell physics on each Pick call and passes the occluder callback. Closes #86. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
27d7de11d8
commit
3764867566
6 changed files with 355 additions and 6 deletions
|
|
@ -9131,6 +9131,17 @@ public sealed class GameWindow : IDisposable
|
|||
var camera = _cameraController.Active;
|
||||
var viewport = new System.Numerics.Vector2((float)_window.Size.X, (float)_window.Size.Y);
|
||||
|
||||
// Indoor walking Phase 1 #86 (2026-05-19): snapshot the currently-
|
||||
// cached EnvCell physics so the picker can occlude entities behind
|
||||
// walls. Snapshot is per-pick (one click), iteration is bounded
|
||||
// by the streaming radius (~80 cells at radius 4).
|
||||
var loadedCellPhysics = new List<AcDream.Core.Physics.CellPhysics>();
|
||||
foreach (var cellId in _physicsDataCache.CellStructIds)
|
||||
{
|
||||
var cp = _physicsDataCache.GetCellStruct(cellId);
|
||||
if (cp is not null) loadedCellPhysics.Add(cp);
|
||||
}
|
||||
|
||||
var picked = AcDream.Core.Selection.WorldPicker.Pick(
|
||||
mouseX: _lastMouseX, mouseY: _lastMouseY,
|
||||
view: camera.View, projection: camera.Projection,
|
||||
|
|
@ -9153,7 +9164,11 @@ public sealed class GameWindow : IDisposable
|
|||
// Match the indicator's TriangleSize (8 px) so the click area
|
||||
// extends out to the bracket corners — what the user perceives
|
||||
// as "selectable extent."
|
||||
inflatePixels: 8f);
|
||||
inflatePixels: 8f,
|
||||
cellOccluder: loadedCellPhysics.Count > 0
|
||||
? (origin, direction) =>
|
||||
AcDream.Core.Selection.CellBspRayOccluder.NearestWallT(origin, direction, loadedCellPhysics)
|
||||
: null);
|
||||
|
||||
if (picked is uint guid)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue