feat(physics): complete retail collision — indoor BSP, dual sphere, step-up, swept-sphere, 6-path dispatcher
Indoor CellStruct PhysicsBSP collision for room walls/ceilings. Dual sphere (body+head) from Setup dimensions. StepUp attempts before sliding when hitting low obstacles. FindTimeOfCollision for exact parametric BSP contact time. Full 6-path BSP dispatcher wired into FindEnvCollisions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1f30fbd2f5
commit
cadc72ed08
4 changed files with 362 additions and 100 deletions
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Concurrent;
|
||||
using System.Numerics;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using DatReaderWriter.Enums;
|
||||
using DatReaderWriter.Types;
|
||||
|
|
@ -15,6 +16,7 @@ public sealed class PhysicsDataCache
|
|||
{
|
||||
private readonly ConcurrentDictionary<uint, GfxObjPhysics> _gfxObj = new();
|
||||
private readonly ConcurrentDictionary<uint, SetupPhysics> _setup = new();
|
||||
private readonly ConcurrentDictionary<uint, CellPhysics> _cellStruct = new();
|
||||
|
||||
/// <summary>
|
||||
/// Extract and cache the physics BSP + polygon data from a GfxObj.
|
||||
|
|
@ -53,10 +55,35 @@ public sealed class PhysicsDataCache
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract and cache the physics BSP + polygon data from a CellStruct
|
||||
/// (indoor room geometry). No-ops if the id is already cached or the
|
||||
/// CellStruct has no physics BSP.
|
||||
/// </summary>
|
||||
public void CacheCellStruct(uint envCellId, CellStruct cellStruct,
|
||||
Matrix4x4 worldTransform)
|
||||
{
|
||||
if (_cellStruct.ContainsKey(envCellId)) return;
|
||||
if (cellStruct.PhysicsBSP?.Root is null) return;
|
||||
|
||||
Matrix4x4.Invert(worldTransform, out var inverseTransform);
|
||||
|
||||
_cellStruct[envCellId] = new CellPhysics
|
||||
{
|
||||
BSP = cellStruct.PhysicsBSP,
|
||||
PhysicsPolygons = cellStruct.PhysicsPolygons,
|
||||
Vertices = cellStruct.VertexArray,
|
||||
WorldTransform = worldTransform,
|
||||
InverseWorldTransform = inverseTransform,
|
||||
};
|
||||
}
|
||||
|
||||
public GfxObjPhysics? GetGfxObj(uint id) => _gfxObj.TryGetValue(id, out var p) ? p : null;
|
||||
public SetupPhysics? GetSetup(uint id) => _setup.TryGetValue(id, out var p) ? p : null;
|
||||
public CellPhysics? GetCellStruct(uint id) => _cellStruct.TryGetValue(id, out var p) ? p : null;
|
||||
public int GfxObjCount => _gfxObj.Count;
|
||||
public int SetupCount => _setup.Count;
|
||||
public int CellStructCount => _cellStruct.Count;
|
||||
}
|
||||
|
||||
/// <summary>Cached physics data for a single GfxObj part.</summary>
|
||||
|
|
@ -78,3 +105,17 @@ public sealed class SetupPhysics
|
|||
public float StepUpHeight { get; init; }
|
||||
public float StepDownHeight { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cached physics data for an indoor cell's room geometry (CellStruct).
|
||||
/// Used for wall/floor/ceiling collision in EnvCells.
|
||||
/// ACE: EnvCell.find_env_collisions queries CellStructure.PhysicsBSP.
|
||||
/// </summary>
|
||||
public sealed class CellPhysics
|
||||
{
|
||||
public required PhysicsBSPTree BSP { get; init; }
|
||||
public required Dictionary<ushort, Polygon> PhysicsPolygons { get; init; }
|
||||
public required VertexArray Vertices { get; init; }
|
||||
public Matrix4x4 WorldTransform { get; init; }
|
||||
public Matrix4x4 InverseWorldTransform { get; init; }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue