fix(camera): #38 render-interpolate player motion

Keep local physics authoritative at the retail 30 Hz MinQuantum, but expose a render-only position that lerps between completed physics ticks for the player mesh and chase-camera target. Network outbound continues to use the discrete physics position.

Also make the visually confirmed #47 humanoid close-detail DIDDegrade path default-on, with ACDREAM_RETAIL_CLOSE_DEGRADES=0 left as a diagnostic opt-out.

Verification: dotnet build AcDream.slnx -c Debug; focused #38 interpolation tests passed; visual confirmed smooth 2026-05-06. Full dotnet test AcDream.slnx -c Debug --no-build still has the known 8 AcDream.Core.Tests baseline failures.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-05-06 17:53:34 +02:00
parent e3d8a44c48
commit 71b1622293
5 changed files with 218 additions and 16 deletions

View file

@ -173,15 +173,15 @@ public sealed class GameWindow : IDisposable
private static readonly int s_hidePartIndex =
int.TryParse(Environment.GetEnvironmentVariable("ACDREAM_HIDE_PART"), out var hp) ? hp : -1;
// Issue #47 — opt in to retail's close-detail GfxObj selection on
// Issue #47 — use retail's close-detail GfxObj selection on
// humanoid setups. When enabled, every per-part GfxObj id (after
// server AnimPartChanges are applied) is replaced with Degrades[0]
// from its DIDDegrade table when present. See GfxObjDegradeResolver
// for the full retail-decomp citation. Off by default while the fix
// bakes; flip to default-on once we've confirmed no scenery/setup
// regressions.
// for the full retail-decomp citation. Default-on after visual
// confirmation; set ACDREAM_RETAIL_CLOSE_DEGRADES=0 only for
// diagnostic before/after comparisons.
private static readonly bool s_retailCloseDegrades =
string.Equals(Environment.GetEnvironmentVariable("ACDREAM_RETAIL_CLOSE_DEGRADES"), "1", StringComparison.Ordinal);
!string.Equals(Environment.GetEnvironmentVariable("ACDREAM_RETAIL_CLOSE_DEGRADES"), "0", StringComparison.Ordinal);
/// <summary>
/// Issue #47 humanoid-setup detector. Matches Aluvian Male
@ -5728,7 +5728,7 @@ public sealed class GameWindow : IDisposable
// the physics-resolved location each frame.
if (_entitiesByServerGuid.TryGetValue(_playerServerGuid, out var pe))
{
pe.Position = result.Position;
pe.Position = result.RenderPosition;
pe.Rotation = System.Numerics.Quaternion.CreateFromAxisAngle(
System.Numerics.Vector3.UnitZ, _playerController.Yaw - MathF.PI / 2f);
@ -5750,7 +5750,7 @@ public sealed class GameWindow : IDisposable
// position never changes. With the pin: player visibly
// rises above the camera, matching retail "you can see
// yourself jump" feedback.
_chaseCamera.Update(result.Position, _playerController.Yaw,
_chaseCamera.Update(result.RenderPosition, _playerController.Yaw,
isOnGround: result.IsOnGround,
dt: (float)dt);