Keep entity fields aligned with orbital poses

This commit is contained in:
Meta Vens 2026-07-22 01:53:42 +01:00
commit 004c05d350
2 changed files with 96 additions and 11 deletions

View file

@ -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()
{

View file

@ -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<AetheriaRuntimeBodySnapshotCommit>())
{
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,