refactor(render): extract world scene frame owner

Move fallback and PView world drawing, shared alpha, particles, visibility, selection, and diagnostics behind focused frame owners. Make exceptional frames failure-atomic by restoring the shared GL baseline and preserving primary alpha failures through cleanup.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-22 07:22:09 +02:00
parent 85239fb373
commit 28e1cf8029
25 changed files with 2679 additions and 844 deletions

View file

@ -0,0 +1,117 @@
using System.Numerics;
using AcDream.App.Input;
using AcDream.App.Streaming;
using AcDream.Core.Physics;
using AcDream.Core.World;
namespace AcDream.App.Rendering;
internal interface IWorldSceneSkyStateSource
{
DayGroupData? ActiveDayGroup { get; }
float DayFraction { get; }
}
/// <summary>
/// Holds the selected retail day group beside the world clock that provides
/// its current interpolation point. Day-group selection remains an update-time
/// concern; render owners receive this read-only seam.
/// </summary>
internal sealed class WorldSceneSkyState : IWorldSceneSkyStateSource
{
private readonly WorldTimeService _worldTime;
public WorldSceneSkyState(WorldTimeService worldTime)
{
_worldTime = worldTime ?? throw new ArgumentNullException(nameof(worldTime));
}
public DayGroupData? ActiveDayGroup { get; set; }
public float DayFraction => (float)_worldTime.DayFraction;
}
internal interface IWorldSceneEntitySource
{
IEnumerable<(uint LandblockId, Vector3 AabbMin, Vector3 AabbMax,
IReadOnlyList<WorldEntity> Entities,
IReadOnlyDictionary<uint, WorldEntity>? AnimatedById)> LandblockEntries
{ get; }
IEnumerable<(uint LandblockId, Vector3 AabbMin, Vector3 AabbMax)> LandblockBounds { get; }
}
internal sealed class RuntimeWorldSceneEntitySource : IWorldSceneEntitySource
{
private readonly GpuWorldState _world;
public RuntimeWorldSceneEntitySource(GpuWorldState world)
{
_world = world ?? throw new ArgumentNullException(nameof(world));
}
public IEnumerable<(uint LandblockId, Vector3 AabbMin, Vector3 AabbMax,
IReadOnlyList<WorldEntity> Entities,
IReadOnlyDictionary<uint, WorldEntity>? AnimatedById)> LandblockEntries =>
_world.LandblockEntries;
public IEnumerable<(uint LandblockId, Vector3 AabbMin, Vector3 AabbMax)> LandblockBounds =>
_world.LandblockBounds;
}
internal interface IWorldScenePViewDiagnosticSource
{
Vector3 RawPlayerPositionOr(Vector3 fallback);
float PlayerYaw { get; }
float? SampleTerrainZ(float worldX, float worldY);
CameraCellResolution CameraCellResolution { get; }
}
internal sealed class RuntimeWorldScenePViewDiagnosticSource :
IWorldScenePViewDiagnosticSource
{
private readonly ILocalPlayerControllerSource _player;
private readonly PhysicsEngine _physics;
private readonly CellVisibility _visibility;
public RuntimeWorldScenePViewDiagnosticSource(
ILocalPlayerControllerSource player,
PhysicsEngine physics,
CellVisibility visibility)
{
_player = player ?? throw new ArgumentNullException(nameof(player));
_physics = physics ?? throw new ArgumentNullException(nameof(physics));
_visibility = visibility ?? throw new ArgumentNullException(nameof(visibility));
}
public Vector3 RawPlayerPositionOr(Vector3 fallback) =>
_player.Controller?.Position ?? fallback;
public float PlayerYaw => _player.Controller?.Yaw ?? 0f;
public float? SampleTerrainZ(float worldX, float worldY) =>
_physics.SampleTerrainZ(worldX, worldY);
public CameraCellResolution CameraCellResolution =>
_visibility.LastCameraCellResolution;
}
internal interface IWorldSceneDebugStateSource
{
bool CollisionWireframesVisible { get; }
}
internal sealed class WorldSceneDebugState : IWorldSceneDebugStateSource
{
public bool CollisionWireframesVisible { get; private set; }
public bool ToggleCollisionWireframes()
{
CollisionWireframesVisible = !CollisionWireframesVisible;
return CollisionWireframesVisible;
}
}