docs: file #333 — the broadphase reach filter has AP-156's defect at the query site
Found while fixing AP-156 and deliberately NOT bundled into it: the shadow broadphase at TransitionTypes.cs:3756-3764 measures `currPos - obj.Position` against `sphereRadius + obj.Radius + movement + 2f`, where `obj.Position` is the PART ORIGIN but `obj.Radius` is the BSP root bounding sphere's radius, measured about that sphere's own centre. The same discarded origin, one layer down. It admits a real contact only when the sphere's centre is within about `movement + 2` metres of the part origin. For Setup 0x02000255 that offset is 9.911 m against a budget near 2.5 m, so a mover touching the upper half of the prop is discarded before BSPQuery runs. This is newly load-bearing: before AP-156 those objects were mostly not in the cell at all, so the filter never got to reject them. AP-156 puts them in the right cells and this becomes the next gate. It is the first place to look if the connected session finds a tall prop that still does not block. Filed rather than fixed because it is a different code path with an unanswered retail question — the `+ 2f` slack and the movement term look like acdream's own broadphase rather than a port of anything in CPhysicsObj::FindObjCollisions @0x0050f050, in which case it needs a divergence row of its own before it is touched. Bundling it would also make AP-156's connected gate un-attributable, which is exactly the fault that split AP-155. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b52967def3
commit
e2b2d04cb5
1 changed files with 71 additions and 0 deletions
|
|
@ -24,6 +24,77 @@ What does NOT go here:
|
|||
- Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
|
||||
- Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed.
|
||||
|
||||
## #333 — The shadow broadphase reach filter measures from the PART ORIGIN, so an off-centre BSP part can be in the right cell and still never be tested
|
||||
|
||||
**Status:** OPEN
|
||||
**Severity:** high for the tall-prop population. It is the gate immediately
|
||||
downstream of the AP-156 membership fix, so that fix alone may not be enough to
|
||||
make the worst objects block.
|
||||
**Filed:** 2026-08-06 at the AP-156 fix (commit `b52967de`), which surfaced it.
|
||||
**Do NOT bundle with AP-156.** Different code path (collision query, not cell
|
||||
membership), and it needs its own retail question answered first.
|
||||
|
||||
### The mechanism
|
||||
|
||||
`src/AcDream.Core/Physics/TransitionTypes.cs:3756-3764`, the shadow broadphase:
|
||||
|
||||
```csharp
|
||||
Vector3 deltaToCurr = currPos - obj.Position;
|
||||
...
|
||||
float maxReach = sphereRadius + obj.Radius + movement.Length() + 2f;
|
||||
if (distToCurr > maxReach)
|
||||
continue; // candidate discarded, never tested
|
||||
```
|
||||
|
||||
`obj.Position` is the shadow row's PART placement —
|
||||
`entityWorldPos + rotate(shape.LocalPosition, entityWorldRot)` — while
|
||||
`obj.Radius` is the physics-BSP ROOT BOUNDING SPHERE radius, which is measured
|
||||
about that sphere's own centre, not about the part origin. AP-156 established
|
||||
that the two are frequently far apart: 376 of 973 installed physics-BSP parts
|
||||
have a root-sphere origin further from the part origin than half their own
|
||||
radius, worst 20.762 m on a 27.708 m sphere.
|
||||
|
||||
Write `d` for the distance from part origin to the true sphere centre, `R` for
|
||||
`obj.Radius`, `r` for the mover's sphere radius. A mover just touching the
|
||||
geometry is `R + r` from the sphere's TRUE centre, hence up to `d + R + r` from
|
||||
`obj.Position`. The filter admits it only when
|
||||
`d + R + r <= r + R + movement + 2`, i.e. only when `d <= movement + 2`. Per
|
||||
physics tick the movement term is well under a metre, so any part whose root
|
||||
sphere sits more than about 2 m from its part origin can have a genuine contact
|
||||
discarded before `BSPQuery` ever runs.
|
||||
|
||||
Worked case — Setup `0x02000255`, one part, root sphere
|
||||
origin `(0.000, -0.007, 9.911)`, radius `10.522`, `Setup.Height = 18.692`.
|
||||
`d = 9.911` against a budget of roughly 2.5 m. A player standing against the
|
||||
upper half of that prop is about 20.4 m from the part origin while `maxReach`
|
||||
is about 13.5 m. Discarded.
|
||||
|
||||
### Why it matters now
|
||||
|
||||
Before AP-156 those objects were usually not registered in the cell at all, so
|
||||
this filter never got the chance to reject them. AP-156 puts them into the
|
||||
correct cells; this filter is the next gate they hit. If the connected session
|
||||
finds a tall prop that still does not block after AP-156, look here first.
|
||||
|
||||
### What to establish before fixing
|
||||
|
||||
1. Does retail have this pre-filter at all? `CPhysicsObj::FindObjCollisions`
|
||||
@0x0050f050 walks the cell's object list and dispatches per object; the
|
||||
`+ 2f` slack and the `movement.Length()` term look like acdream's own
|
||||
broadphase rather than a port. If it is acdream's, it also needs a
|
||||
divergence-register row, which it does not currently have.
|
||||
2. If it is kept, it must measure from where the geometry is: `ShadowEntry`
|
||||
needs the `BoundsCenter` that `ShadowShape` now carries, and `deltaToCurr`
|
||||
must be taken against `obj.Position + rotate(obj.BoundsCenter, obj.Rotation)`.
|
||||
3. Cylinder rows are unaffected (`BoundsCenter == Zero` by construction) — the
|
||||
change must not move them.
|
||||
|
||||
### Test to write first
|
||||
|
||||
A mover adjacent to an off-centre BSP part's geometry, with the part origin far
|
||||
outside `maxReach`. It must reach `BSPQuery`. Sabotage by restoring the
|
||||
part-origin measurement; it must go back to reporting no collision.
|
||||
|
||||
## #332 — Headless bots appear to have no remote dead-reckoning at all
|
||||
|
||||
**Status:** OPEN (observation, not yet established as a defect)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue