feat(physics): cell-based ShadowObject collision
Register static entities into terrain cells during streaming. Transition system queries nearby objects and runs BSP collision. Player can no longer walk through trees and buildings. - ShadowObjectRegistry: 24m×24m cell index, Register/Deregister/ RemoveLandblock/GetNearbyObjects matching retail AC's approach - PhysicsEngine: ShadowObjects property + DataCache wiring point; RemoveLandblock now also clears shadow objects; TryGetLandblockContext helper lets Transition resolve landblock id+offset for a world pos - Transition.FindObjCollisions: queries registry, broad-phase sphere test, narrow-phase BSPQuery.SphereIntersectsPoly in object-local space, returns Slid on hit to redirect movement along the surface - GameWindow.ApplyLoadedTerrainLocked: registers each static entity after physics BSP data is cached; selects radius from BSP bounding sphere or Setup.Radius; wires PhysicsDataCache into engine on OnLoad - 16 new ShadowObjectRegistry unit tests, all 361 tests green Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
246713e2cc
commit
e2f0c8580e
5 changed files with 541 additions and 2 deletions
|
|
@ -178,6 +178,10 @@ public sealed class GameWindow : IDisposable
|
|||
|
||||
private void OnLoad()
|
||||
{
|
||||
// Task 7: wire the physics data cache into the engine so Transition can
|
||||
// run narrow-phase BSP tests during FindObjCollisions.
|
||||
_physicsEngine.DataCache = _physicsDataCache;
|
||||
|
||||
_gl = GL.GetApi(_window!);
|
||||
_input = _window!.CreateInput();
|
||||
foreach (var kb in _input.Keyboards)
|
||||
|
|
@ -1749,6 +1753,63 @@ public sealed class GameWindow : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
// Task 7: register static entities into the ShadowObjectRegistry so the
|
||||
// Transition system can find and collide against them during movement.
|
||||
// Only entities backed by a GfxObj with a physics BSP are registered —
|
||||
// entities with no BSP (pure visual, no physics) are skipped.
|
||||
//
|
||||
// Radius source priority:
|
||||
// 1. GfxObj: use the BSP root bounding sphere radius if available.
|
||||
// 2. Setup: use Setup.Radius (the capsule radius) if available.
|
||||
// 3. Fallback: 1.0m (conservative default for trees / small objects).
|
||||
foreach (var entity in lb.Entities)
|
||||
{
|
||||
float bestRadius = 0f;
|
||||
uint physicsGfxId = 0;
|
||||
|
||||
uint sourceId = entity.SourceGfxObjOrSetupId;
|
||||
if ((sourceId & 0xFF000000u) == 0x01000000u)
|
||||
{
|
||||
// Direct GfxObj stab.
|
||||
var cached = _physicsDataCache.GetGfxObj(sourceId);
|
||||
if (cached?.BSP?.Root is not null)
|
||||
{
|
||||
physicsGfxId = sourceId;
|
||||
bestRadius = cached.BoundingSphere?.Radius ?? 1f;
|
||||
}
|
||||
}
|
||||
else if ((sourceId & 0xFF000000u) == 0x02000000u)
|
||||
{
|
||||
// Setup (multi-part building / creature proxy). Use the first
|
||||
// part that has a physics BSP; register using Setup.Radius for
|
||||
// the broad-phase sphere so the query covers the whole assembly.
|
||||
var setupCached = _physicsDataCache.GetSetup(sourceId);
|
||||
if (setupCached is not null && setupCached.Radius > 0f)
|
||||
bestRadius = setupCached.Radius;
|
||||
|
||||
foreach (var meshRef in entity.MeshRefs)
|
||||
{
|
||||
var partCached = _physicsDataCache.GetGfxObj(meshRef.GfxObjId);
|
||||
if (partCached?.BSP?.Root is not null)
|
||||
{
|
||||
physicsGfxId = meshRef.GfxObjId;
|
||||
if (bestRadius <= 0f)
|
||||
bestRadius = partCached.BoundingSphere?.Radius ?? 1f;
|
||||
break; // register just the first physics part for MVP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (physicsGfxId != 0)
|
||||
{
|
||||
float reg_radius = bestRadius > 0f ? bestRadius : 1f;
|
||||
_physicsEngine.ShadowObjects.Register(
|
||||
entity.Id, physicsGfxId,
|
||||
entity.Position, reg_radius,
|
||||
origin.X, origin.Y, lb.LandblockId);
|
||||
}
|
||||
}
|
||||
|
||||
// Register each stab as a plugin snapshot so the plugin host has
|
||||
// visibility into the streaming world state.
|
||||
foreach (var entity in lb.Entities)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue