Separate logical ownership, render publication, and GPU retirement across live entities, landblocks, particles, textures, mesh arenas, portal/UI teardown, and per-frame scratch storage. Add bounded DAT/texture caches, upload budgets, three-frame fence retirement, exact-incarnation appearance reconciliation, frame pacing, and extensive lifetime conformance coverage.\n\nThe seven-destination connected route now cuts peak working/private memory roughly in half, returns Caul to 125-153 FPS locally, and produces no WER or AMD reset.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
79 lines
2.8 KiB
C#
79 lines
2.8 KiB
C#
using AcDream.Content.Vfx;
|
|
using AcDream.Content;
|
|
using AcDream.Core.Physics;
|
|
using AcDream.Core.Tests.Conformance;
|
|
using DatReaderWriter;
|
|
using DatReaderWriter.DBObjs;
|
|
using DatReaderWriter.Options;
|
|
using DatReaderWriter.Types;
|
|
|
|
namespace AcDream.Core.Tests.Physics;
|
|
|
|
/// <summary>
|
|
/// Pins the retail Humanoid motion table data consumed by CSequence root motion.
|
|
/// The packet-driven remote mover must use these values, not a velocity guessed
|
|
/// from the interpreted command.
|
|
/// </summary>
|
|
public sealed class HumanoidMotionTableRootMotionTests
|
|
{
|
|
private const uint HumanoidMotionTable = 0x09000001u;
|
|
private const uint HumanoidSetup = 0x02000001u;
|
|
private const uint NonCombatStyle = 0x8000003Du;
|
|
private const uint WalkForward = 0x40000005u;
|
|
private const uint RunForward = 0x40000007u;
|
|
private const uint Ready = 0x41000003u;
|
|
private const uint InterpretedWalkForward = 0x45000005u;
|
|
|
|
[Theory]
|
|
[InlineData(WalkForward)]
|
|
[InlineData(RunForward)]
|
|
public void RetailLocomotionCycle_ExposesItsLiteralMotionDataVelocity(uint motion)
|
|
{
|
|
string? datDir = ConformanceDats.ResolveDatDir();
|
|
if (datDir is null)
|
|
return;
|
|
|
|
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
|
MotionTable table = Assert.IsType<MotionTable>(dats.Get<MotionTable>(HumanoidMotionTable));
|
|
int key = unchecked((int)((NonCombatStyle << 16) | (motion & 0x00FF_FFFFu)));
|
|
MotionData cycle = Assert.IsType<MotionData>(table.Cycles[key]);
|
|
|
|
Assert.Equal(System.Numerics.Vector3.Zero, cycle.Velocity);
|
|
}
|
|
|
|
[Fact]
|
|
public void RetailWalkSequence_ProducesAuthoredRootDisplacement()
|
|
{
|
|
string? datDir = ConformanceDats.ResolveDatDir();
|
|
if (datDir is null)
|
|
return;
|
|
|
|
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
|
using var boundedDats = new DatCollectionAdapter(dats);
|
|
Setup setup = Assert.IsType<Setup>(dats.Get<Setup>(HumanoidSetup));
|
|
MotionTable table = Assert.IsType<MotionTable>(dats.Get<MotionTable>(HumanoidMotionTable));
|
|
var sequencer = new AnimationSequencer(
|
|
setup,
|
|
table,
|
|
new RetailAnimationLoader(boundedDats));
|
|
|
|
sequencer.SetCycle(NonCombatStyle, Ready);
|
|
sequencer.SetCycle(NonCombatStyle, InterpretedWalkForward);
|
|
|
|
float distance = 0f;
|
|
for (int i = 0; i < 120; i++)
|
|
{
|
|
var root = new Frame
|
|
{
|
|
Origin = System.Numerics.Vector3.Zero,
|
|
Orientation = System.Numerics.Quaternion.Identity,
|
|
};
|
|
sequencer.Advance(1f / 60f, root);
|
|
distance += root.Origin.Length();
|
|
}
|
|
|
|
Assert.True(
|
|
distance > 1f,
|
|
$"Installed retail WalkForward should author root travel; got {distance:F3} m over 2 s.");
|
|
}
|
|
}
|