fix(physics): Phase 2 — pass foot-sphere center to ResolveCellId
Visual test of Phase 2 portal traversal showed walls still didn't block from inside buildings. Diagnosis: ResolveCellId was being called with sp.CheckPos (entity reference, at the feet — world Z=terrain) instead of sp.GlobalSphere[0].Origin (foot sphere center, ~0.5m above terrain). Combined with the +0.02f Z-bump on cached cell origins (for render z-fight prevention), the test position landed at cell-local Z=-0.02 — just below the cell floor — and PointInsideCellBsp correctly reported "outside" for every cell. CheckBuildingTransit never added candidates; player CellId stayed outdoor; indoor cell-BSP collision branch never fired; walls didn't block. Retail's check_building_transit uses sphere.Center (the sphere CENTER, not the entity reference) per the pseudocode at docs/research/acclient_indoor_transitions_pseudocode.md:222-238. Three call sites updated (PhysicsEngine x2 inside ResolveWithTransition; TransitionTypes inside Transition.FindEnvCollisions). Also adds a [check-bldg] diagnostic line to CheckBuildingTransit (gated on the existing ACDREAM_PROBE_INDOOR_BSP flag) so future verification captures show per-portal inside/outside results without needing another diagnostic flag. Spec: docs/superpowers/specs/2026-05-19-indoor-portal-cell-tracking-design.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
702b30a63e
commit
3ffe1e44f6
3 changed files with 22 additions and 5 deletions
|
|
@ -186,11 +186,28 @@ public static class CellTransit
|
|||
foreach (var portal in building.Portals)
|
||||
{
|
||||
var otherCell = cache.GetCellStruct(portal.OtherCellId);
|
||||
if (otherCell?.CellBSP?.Root is null) continue;
|
||||
if (otherCell?.CellBSP?.Root is null)
|
||||
{
|
||||
if (PhysicsDiagnostics.ProbeIndoorBspEnabled)
|
||||
{
|
||||
string reason = otherCell is null ? "cell not cached" : "CellBSP null";
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[check-bldg] portal->0x{portal.OtherCellId:X8} skipped: {reason}"));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sphere center in the OTHER cell's local space.
|
||||
var localCenter = Vector3.Transform(worldSphereCenter, otherCell.InverseWorldTransform);
|
||||
if (BSPQuery.PointInsideCellBsp(otherCell.CellBSP.Root, localCenter))
|
||||
bool inside = BSPQuery.PointInsideCellBsp(otherCell.CellBSP.Root, localCenter);
|
||||
|
||||
if (PhysicsDiagnostics.ProbeIndoorBspEnabled)
|
||||
{
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[check-bldg] portal->0x{portal.OtherCellId:X8} wpos=({worldSphereCenter.X:F3},{worldSphereCenter.Y:F3},{worldSphereCenter.Z:F3}) lpos=({localCenter.X:F3},{localCenter.Y:F3},{localCenter.Z:F3}) inside={inside}"));
|
||||
}
|
||||
|
||||
if (inside)
|
||||
{
|
||||
candidates.Add(portal.OtherCellId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -769,7 +769,7 @@ public sealed class PhysicsEngine
|
|||
|
||||
return new ResolveResult(
|
||||
sp.CheckPos,
|
||||
ResolveCellId(sp.CheckPos, sphereRadius, sp.CheckCellId),
|
||||
ResolveCellId(sp.GlobalSphere[0].Origin, sphereRadius, sp.CheckCellId),
|
||||
onGround,
|
||||
collisionNormalValid,
|
||||
collisionNormal);
|
||||
|
|
@ -787,7 +787,7 @@ public sealed class PhysicsEngine
|
|||
uint partialCellId = sp.CheckCellId != 0 ? sp.CheckCellId : cellId;
|
||||
return new ResolveResult(
|
||||
sp.CheckPos,
|
||||
ResolveCellId(sp.CheckPos, sphereRadius, partialCellId),
|
||||
ResolveCellId(sp.GlobalSphere[0].Origin, sphereRadius, partialCellId),
|
||||
partialOnGround,
|
||||
collisionNormalValid,
|
||||
collisionNormal);
|
||||
|
|
|
|||
|
|
@ -1181,7 +1181,7 @@ public sealed class Transition
|
|||
Vector3 footCenter = sp.GlobalSphere[0].Origin;
|
||||
float sphereRadius = sp.GlobalSphere[0].Radius;
|
||||
|
||||
uint resolvedOutdoorCellId = engine.ResolveCellId(sp.CheckPos, sphereRadius, sp.CheckCellId);
|
||||
uint resolvedOutdoorCellId = engine.ResolveCellId(sp.GlobalSphere[0].Origin, sphereRadius, sp.CheckCellId);
|
||||
if (resolvedOutdoorCellId != sp.CheckCellId)
|
||||
sp.SetCheckPos(sp.CheckPos, resolvedOutdoorCellId);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue