acdream/tests/AcDream.Core.Tests/Physics/HumanoidMotionTableRootMotionTests.cs
Erik 749e8ceeb1 fix(rendering): bound portal resource lifetime
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>
2026-07-18 21:35:16 +02:00

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.");
}
}