fix(physics): seal collision generations before activation
This commit is contained in:
parent
be94bc9b06
commit
d94145e6b8
15 changed files with 1556 additions and 410 deletions
|
|
@ -182,12 +182,12 @@ public sealed class PhysicsEngine
|
|||
return staging;
|
||||
}
|
||||
|
||||
internal PreparedPhysicsEngineLandblock PrepareLandblockReplacement(
|
||||
internal LandblockReplacementBuilder CreateLandblockReplacementBuilder(
|
||||
PhysicsEngine staging,
|
||||
uint landblockId,
|
||||
ReadOnlySpan<uint> gfxObjectIds,
|
||||
ReadOnlySpan<uint> setupIds,
|
||||
IReadOnlyDictionary<uint, ulong> expectedDynamicVersions)
|
||||
uint[] gfxObjectIds,
|
||||
uint[] setupIds,
|
||||
IReadOnlyDictionary<uint, ulong> expectedRetainedVersions)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(staging);
|
||||
uint canonical = (landblockId & 0xFFFF0000u) | 0xFFFFu;
|
||||
|
|
@ -201,31 +201,25 @@ public sealed class PhysicsEngine
|
|||
PhysicsDataCache stagingCache = staging.DataCache
|
||||
?? throw new InvalidOperationException(
|
||||
"Staging collision engine has no data cache.");
|
||||
return new PreparedPhysicsEngineLandblock(
|
||||
return new LandblockReplacementBuilder(
|
||||
canonical,
|
||||
landblock,
|
||||
stagingCache.PrepareLandblockReplacement(
|
||||
(DataCache ?? throw new InvalidOperationException(
|
||||
"Active collision engine has no data cache."))
|
||||
.CreateLandblockReplacementBuilder(
|
||||
stagingCache,
|
||||
canonical,
|
||||
gfxObjectIds,
|
||||
setupIds),
|
||||
ShadowObjects.PrepareLandblockReplacement(
|
||||
ShadowObjects.CreateLandblockReplacementBuilder(
|
||||
staging.ShadowObjects,
|
||||
canonical,
|
||||
expectedDynamicVersions));
|
||||
expectedRetainedVersions));
|
||||
}
|
||||
|
||||
internal bool ValidateLandblockReplacement(
|
||||
PreparedPhysicsEngineLandblock replacement) =>
|
||||
ShadowObjects.ValidateLandblockReplacement(replacement.Shadows);
|
||||
|
||||
internal void CommitLandblockReplacement(
|
||||
PreparedPhysicsEngineLandblock replacement)
|
||||
{
|
||||
if (!ValidateLandblockReplacement(replacement))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Collision generation changed after it was sealed.");
|
||||
}
|
||||
(DataCache ?? throw new InvalidOperationException(
|
||||
"Active collision engine has no data cache."))
|
||||
.CommitLandblockReplacement(replacement.DataCache);
|
||||
|
|
@ -253,6 +247,64 @@ public sealed class PhysicsEngine
|
|||
internal ShadowObjectRegistry.PreparedLandblockShadowReplacement Shadows { get; }
|
||||
}
|
||||
|
||||
internal sealed class LandblockReplacementBuilder : IDisposable
|
||||
{
|
||||
private readonly uint _landblockId;
|
||||
private readonly LandblockPhysics _landblock;
|
||||
private readonly PhysicsDataCache.LandblockReplacementBuilder _data;
|
||||
private readonly ShadowObjectRegistry.LandblockReplacementBuilder _shadows;
|
||||
private int _phase;
|
||||
|
||||
internal LandblockReplacementBuilder(
|
||||
uint landblockId,
|
||||
LandblockPhysics landblock,
|
||||
PhysicsDataCache.LandblockReplacementBuilder data,
|
||||
ShadowObjectRegistry.LandblockReplacementBuilder shadows)
|
||||
{
|
||||
_landblockId = landblockId;
|
||||
_landblock = landblock;
|
||||
_data = data;
|
||||
_shadows = shadows;
|
||||
}
|
||||
|
||||
internal int WorkUnits => _data.WorkUnits + _shadows.WorkUnits;
|
||||
internal bool IsStable => _shadows.IsStable;
|
||||
internal PreparedPhysicsEngineLandblock? Prepared { get; private set; }
|
||||
|
||||
internal bool Advance()
|
||||
{
|
||||
if (_phase == 0)
|
||||
{
|
||||
if (!_data.Advance())
|
||||
return false;
|
||||
_phase++;
|
||||
return false;
|
||||
}
|
||||
if (_phase == 1)
|
||||
{
|
||||
if (!_shadows.Advance())
|
||||
return false;
|
||||
if (IsStable && _data.Prepared is not null
|
||||
&& _shadows.Prepared is not null)
|
||||
{
|
||||
Prepared = new PreparedPhysicsEngineLandblock(
|
||||
_landblockId,
|
||||
_landblock,
|
||||
_data.Prepared,
|
||||
_shadows.Prepared);
|
||||
}
|
||||
_phase++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_data.Dispose();
|
||||
_shadows.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a landblock with its terrain surface, indoor cells, portal
|
||||
/// planes, and world-space origin offset.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue