checkpoint: preserve user-gated FW closeout fixes
This commit is contained in:
parent
a2f2eb7d78
commit
b8befded8b
22 changed files with 1005 additions and 198 deletions
|
|
@ -1,6 +1,7 @@
|
|||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.Core.Physics;
|
||||
|
||||
namespace AcDream.App.Rendering.Walk;
|
||||
|
||||
|
|
@ -54,6 +55,7 @@ namespace AcDream.App.Rendering.Walk;
|
|||
internal sealed class WalkProductionWorldData : IWalkFrameWorldData
|
||||
{
|
||||
private readonly WalkBuildingRegistry _buildings;
|
||||
private readonly ShadowObjectRegistry _shadows;
|
||||
private RenderSceneQuery _scene;
|
||||
private uint _tupleLandblockId;
|
||||
private int _renderCenterLbX;
|
||||
|
|
@ -77,9 +79,12 @@ internal sealed class WalkProductionWorldData : IWalkFrameWorldData
|
|||
private RenderProjectionRecord[] _arena = new RenderProjectionRecord[4096];
|
||||
private int _arenaLength;
|
||||
|
||||
internal WalkProductionWorldData(WalkBuildingRegistry buildings)
|
||||
internal WalkProductionWorldData(
|
||||
WalkBuildingRegistry buildings,
|
||||
ShadowObjectRegistry shadows)
|
||||
{
|
||||
_buildings = buildings ?? throw new ArgumentNullException(nameof(buildings));
|
||||
_shadows = shadows ?? throw new ArgumentNullException(nameof(shadows));
|
||||
}
|
||||
|
||||
/// <summary>Rebuilds the frame's outdoor/shell buckets and clears the
|
||||
|
|
@ -136,11 +141,12 @@ internal sealed class WalkProductionWorldData : IWalkFrameWorldData
|
|||
shells.Add(record);
|
||||
continue;
|
||||
}
|
||||
uint cellId = LandscapeCellId(
|
||||
record.Transform.Position, _renderCenterLbX, _renderCenterLbY);
|
||||
if (!_outdoorByCell.TryGetValue(cellId, out List<RenderProjectionRecord>? bucket))
|
||||
_outdoorByCell[cellId] = bucket = new List<RenderProjectionRecord>();
|
||||
bucket.Add(record);
|
||||
BucketOutdoorRecord(
|
||||
in record,
|
||||
_shadows.GetOwnerCells(record.Source.LocalEntityId),
|
||||
_outdoorByCell,
|
||||
_renderCenterLbX,
|
||||
_renderCenterLbY);
|
||||
}
|
||||
|
||||
required = _scene.IndexCounts.For(RenderSceneIndex.OutdoorDynamic);
|
||||
|
|
@ -155,18 +161,70 @@ internal sealed class WalkProductionWorldData : IWalkFrameWorldData
|
|||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ref readonly RenderProjectionRecord record = ref _dynamicSweepScratch[i];
|
||||
uint cellId = LandscapeCellId(
|
||||
record.Transform.Position, _renderCenterLbX, _renderCenterLbY);
|
||||
if (!_outdoorDynamicsByCell.TryGetValue(
|
||||
cellId,
|
||||
out List<RenderProjectionRecord>? bucket))
|
||||
{
|
||||
_outdoorDynamicsByCell[cellId] = bucket = new List<RenderProjectionRecord>();
|
||||
}
|
||||
bucket.Add(record);
|
||||
BucketOutdoorRecord(
|
||||
in record,
|
||||
_shadows.GetOwnerCells(record.Source.LocalEntityId),
|
||||
_outdoorDynamicsByCell,
|
||||
_renderCenterLbX,
|
||||
_renderCenterLbY);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs one outdoor object's render shadow in every outdoor cell of
|
||||
/// its authoritative physics <c>CELLARRAY</c>. This is retail's
|
||||
/// <c>CPhysicsObj::add_shadows_to_cells</c> →
|
||||
/// <c>CPartArray::AddPartsShadow</c> path: a large object straddling a
|
||||
/// landblock edge must remain reachable when its origin cell leaves the
|
||||
/// landscape walk. Objects without a collision registration (notably
|
||||
/// short-lived visual effects) retain the root-position fallback.
|
||||
/// </summary>
|
||||
internal static void BucketOutdoorRecord(
|
||||
in RenderProjectionRecord record,
|
||||
IReadOnlyList<uint> shadowCells,
|
||||
Dictionary<uint, List<RenderProjectionRecord>> buckets,
|
||||
int renderCenterLbX,
|
||||
int renderCenterLbY)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(shadowCells);
|
||||
ArgumentNullException.ThrowIfNull(buckets);
|
||||
|
||||
bool added = false;
|
||||
for (int i = 0; i < shadowCells.Count; i++)
|
||||
{
|
||||
uint cellId = shadowCells[i];
|
||||
uint cellIndex = cellId & 0xFFFFu;
|
||||
if (cellIndex is < 1u or > 64u)
|
||||
continue;
|
||||
|
||||
AddToBucket(in record, cellId, buckets);
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (!added)
|
||||
{
|
||||
uint cellId = LandscapeCellId(
|
||||
record.Transform.Position,
|
||||
renderCenterLbX,
|
||||
renderCenterLbY);
|
||||
AddToBucket(in record, cellId, buckets);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddToBucket(
|
||||
in RenderProjectionRecord record,
|
||||
uint cellId,
|
||||
Dictionary<uint, List<RenderProjectionRecord>> buckets)
|
||||
{
|
||||
if (!buckets.TryGetValue(
|
||||
cellId,
|
||||
out List<RenderProjectionRecord>? bucket))
|
||||
{
|
||||
buckets[cellId] = bucket = new List<RenderProjectionRecord>();
|
||||
}
|
||||
bucket.Add(record);
|
||||
}
|
||||
|
||||
/// <summary>The landscape cell owning a RENDER-ORIGIN-RELATIVE position
|
||||
/// — retail's 24 m cell grid inside the 192 m landblock, producing the
|
||||
/// same TRUE <c>(lb & 0xFFFF0000) | (cellX*8 + cellY + 1)</c> encoding
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue