fix(physics): always register CylSphere alongside BSP parts
Previously CylSphere was only registered when no BSP parts existed. Retail tests BOTH: CylSphere as the broad collision volume (trunk) plus BSP parts for polygon-level collision. This ensures the trunk cylinder catches collisions that individual BSP parts might miss, especially at the base of large trees. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2ebbfc4864
commit
bfe6a49d67
1 changed files with 7 additions and 5 deletions
|
|
@ -1801,10 +1801,10 @@ public sealed class GameWindow : IDisposable
|
||||||
partIndex++;
|
partIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no BSP parts were registered, check for CylSphere collision
|
// ALWAYS register CylSphere when the Setup has one, even if BSP parts
|
||||||
// from the Setup (trees, rocks, NPCs use cylinder collision).
|
// were also registered. Retail tests both: CylSphere as the broad
|
||||||
if (partIndex == 0 || !entity.MeshRefs.Any(mr =>
|
// collision volume (trunk) plus BSP parts for precise polygon collision.
|
||||||
_physicsDataCache.GetGfxObj(mr.GfxObjId)?.BSP?.Root is not null))
|
// The CylSphere catches the base/trunk that BSP parts might miss.
|
||||||
{
|
{
|
||||||
var setup = _physicsDataCache.GetSetup(entity.SourceGfxObjOrSetupId);
|
var setup = _physicsDataCache.GetSetup(entity.SourceGfxObjOrSetupId);
|
||||||
if (setup is not null && setup.CylSpheres.Count > 0)
|
if (setup is not null && setup.CylSpheres.Count > 0)
|
||||||
|
|
@ -1813,6 +1813,7 @@ public sealed class GameWindow : IDisposable
|
||||||
float cylRadius = cyl.Radius > 0 ? cyl.Radius : setup.Radius;
|
float cylRadius = cyl.Radius > 0 ? cyl.Radius : setup.Radius;
|
||||||
if (cylRadius > 0)
|
if (cylRadius > 0)
|
||||||
{
|
{
|
||||||
|
// Use entity.Id directly (not partId) for the CylSphere entry.
|
||||||
_physicsEngine.ShadowObjects.Register(
|
_physicsEngine.ShadowObjects.Register(
|
||||||
entity.Id, entity.SourceGfxObjOrSetupId,
|
entity.Id, entity.SourceGfxObjOrSetupId,
|
||||||
entity.Position + new System.Numerics.Vector3(cyl.Origin.X, cyl.Origin.Y, cyl.Origin.Z),
|
entity.Position + new System.Numerics.Vector3(cyl.Origin.X, cyl.Origin.Y, cyl.Origin.Z),
|
||||||
|
|
@ -1821,8 +1822,9 @@ public sealed class GameWindow : IDisposable
|
||||||
AcDream.Core.Physics.ShadowCollisionType.Cylinder, cyl.Height);
|
AcDream.Core.Physics.ShadowCollisionType.Cylinder, cyl.Height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (setup is not null && setup.Spheres.Count > 0)
|
else if (setup is not null && setup.Spheres.Count > 0 && partIndex == 0)
|
||||||
{
|
{
|
||||||
|
// Fallback: use bounding sphere only if no BSP and no CylSphere.
|
||||||
var sph = setup.Spheres[0];
|
var sph = setup.Spheres[0];
|
||||||
if (sph.Radius > 0)
|
if (sph.Radius > 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue