From 004c05d35054210d9f8cd4d9a2fc805a60f3c11e Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 22 Jul 2026 01:53:42 +0100 Subject: [PATCH] Keep entity fields aligned with orbital poses --- .../Tests/DaemonRuntimeDocumentTests.cs | 65 +++++++++++++++++++ .../Runtime/AetheriaRuntimeGameDocuments.cs | 42 ++++++++---- 2 files changed, 96 insertions(+), 11 deletions(-) diff --git a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs index b6f78242f..ce410f48d 100644 --- a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs +++ b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs @@ -1610,6 +1610,71 @@ public class DaemonRuntimeDocumentTests Assert.AreEqual(3.5, poses[1].GravityWaveSpeed, 0.0001); } + [Test] + public void RenderSplatsUseTheSameResolvedOrbitPoseAsCelestialEntities() + { + var zone = new AetheriaRuntimeZoneSnapshotCommit + { + ZoneIndex = 2, + Orbits = new[] + { + new AetheriaRuntimeOrbitSnapshotCommit + { + OrbitKey = "orbit:sun", + FixedPositionX = 120, + FixedPositionY = -45 + } + }, + Bodies = new[] + { + new AetheriaRuntimeBodySnapshotCommit + { + BodyKey = "body:sun", + OrbitKey = "orbit:sun", + Kind = "sun", + GravityInfluenceCenterX = double.NaN, + GravityInfluenceCenterZ = double.NaN, + GravityInfluenceRadius = 40, + GravityWellDepth = 8, + Mass = 16, + SunVisual = new AetheriaRuntimeSunVisualCommit + { + FogTintColorX = 1, + FogTintColorY = 0.5, + FogTintColorZ = 0.25 + } + } + } + }; + var frame = new AetheriaRuntimeDaemonFrameDocument + { + FrameId = 7, + Run = new AetheriaRuntimeRunCheckpointCommit + { + RunId = "run-orbit-fields", + CurrentZoneIndex = zone.ZoneIndex, + Zones = new[] { zone } + } + }; + + var document = AetheriaRuntimeGameDocuments.RenderSplatsViewport( + frame, + new AetheriaRuntimeViewportBounds + { + MinX = 50, + MinY = -100, + MaxX = 170, + MaxY = 20 + }); + var bodySplats = Enumerable.Range(0, document.Splats.Count) + .Where(index => document.Splats.SourceKey[index].StartsWith("body:sun", StringComparison.Ordinal)) + .ToArray(); + + Assert.IsNotEmpty(bodySplats); + Assert.That(bodySplats.All(index => Math.Abs(document.Splats.CenterX[index] - 120) < 0.0001)); + Assert.That(bodySplats.All(index => Math.Abs(document.Splats.CenterY[index] + 45) < 0.0001)); + } + [Test] public void DaemonRenderQueriesPublishBodyViewsFromZoneSnapshot() { diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeGameDocuments.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeGameDocuments.cs index 3dc0ee147..820055b2d 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeGameDocuments.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeGameDocuments.cs @@ -182,16 +182,28 @@ namespace GameCult.Aetheria.State.Verse AddFossilGlobalFogBrushes(splats, layerIndices); + var bodyPoses = AetheriaRuntimeDaemonRenderQueries.QueryBodyPoses(zone) + .ToDictionary(pose => pose.BodyKey, StringComparer.Ordinal); foreach (var body in zone.Bodies ?? Array.Empty()) { - if (!GravityInfluenceIntersectsViewport(body, normalizedViewport)) + if (body == null || + string.IsNullOrWhiteSpace(body.BodyKey) || + !bodyPoses.TryGetValue(body.BodyKey, out var pose)) continue; var radius = ResolveGravityRadius(body); + if (pose.CenterX + radius < normalizedViewport.MinX || + pose.CenterX - radius > normalizedViewport.MaxX || + pose.CenterZ + radius < normalizedViewport.MinY || + pose.CenterZ - radius > normalizedViewport.MaxY) + { + continue; + } + splats.Add( layerIndices[AetheriaRuntimeRenderSplatLayerKeys.GravityHeight], - body.GravityInfluenceCenterX, - body.GravityInfluenceCenterZ, + pose.CenterX, + pose.CenterZ, radius, radius, AetheriaRuntimeRenderSplatChannels.Gravity, @@ -205,8 +217,8 @@ namespace GameCult.Aetheria.State.Verse falloffExponent: Math.Max(0.0001, body.GravityDepthExponent)); splats.Add( layerIndices[AetheriaRuntimeRenderSplatLayerKeys.FogSurfaceHeight], - body.GravityInfluenceCenterX, - body.GravityInfluenceCenterZ, + pose.CenterX, + pose.CenterZ, radius, radius, AetheriaRuntimeRenderSplatChannels.Gravity, @@ -220,8 +232,8 @@ namespace GameCult.Aetheria.State.Verse falloffExponent: Math.Max(0.0001, body.GravityDepthExponent)); splats.Add( layerIndices[AetheriaRuntimeRenderSplatLayerKeys.FogPatchHeight], - body.GravityInfluenceCenterX, - body.GravityInfluenceCenterZ, + pose.CenterX, + pose.CenterZ, radius, radius, AetheriaRuntimeRenderSplatChannels.Tint, @@ -241,18 +253,24 @@ namespace GameCult.Aetheria.State.Verse splats, layerIndices[AetheriaRuntimeRenderSplatLayerKeys.GravityWave], body, + pose.CenterX, + pose.CenterZ, AetheriaRuntimeRenderSplatChannels.GravityWave, $"{body.BodyKey ?? ""}:gravity.wave"); AddFossilRadialWaveBrush( splats, layerIndices[AetheriaRuntimeRenderSplatLayerKeys.FogSurfaceHeight], body, + pose.CenterX, + pose.CenterZ, AetheriaRuntimeRenderSplatChannels.Tint, $"{body.BodyKey ?? ""}:fog.surface_height.wave"); AddFossilRadialWaveBrush( splats, layerIndices[AetheriaRuntimeRenderSplatLayerKeys.FogPatchHeight], body, + pose.CenterX, + pose.CenterZ, AetheriaRuntimeRenderSplatChannels.Tint, $"{body.BodyKey ?? ""}:fog.patch_height.wave"); } @@ -264,8 +282,8 @@ namespace GameCult.Aetheria.State.Verse Math.Max(0.01, body.SunVisual?.LightRadiusMultiplier ?? 1.0) * 0.5; splats.Add( layerIndices[AetheriaRuntimeRenderSplatLayerKeys.FogTint], - body.GravityInfluenceCenterX, - body.GravityInfluenceCenterZ, + pose.CenterX, + pose.CenterZ, tintHalfExtent, tintHalfExtent, AetheriaRuntimeRenderSplatChannels.Tint, @@ -519,6 +537,8 @@ namespace GameCult.Aetheria.State.Verse RenderSplatBuilder splats, int layerIndex, AetheriaRuntimeBodySnapshotCommit body, + double centerX, + double centerY, int channel, string sourceKey) { @@ -527,8 +547,8 @@ namespace GameCult.Aetheria.State.Verse var halfExtent = body.GravityWaveRadius * 0.5; splats.Add( layerIndex, - body.GravityInfluenceCenterX, - body.GravityInfluenceCenterZ, + centerX, + centerY, halfExtent, halfExtent, channel,