Position rendered zone bodies from daemon poses
This commit is contained in:
parent
95e09dc241
commit
140028d0db
4 changed files with 183 additions and 13 deletions
|
|
@ -1501,8 +1501,9 @@ static void RequireTypedOrbitConsumerKeys(string root)
|
|||
[Path.Combine(root, "Assets", "Scripts", "Zone Display", "ZoneRenderer.cs")] = new[]
|
||||
{
|
||||
"body => body.OrbitKey == orbit.OrbitKey",
|
||||
"Zone.GetOrbitPosition(planetInstance.OrbitKey)",
|
||||
"Zone.GetOrbitPosition(planetInstance.Orbit.ParentOrbitKey)"
|
||||
"_daemonBodyPosesByBodyKey.TryGetValue(planet.Key, out var pose)",
|
||||
"var p = new float2((float)pose.CenterX, (float)pose.CenterZ);",
|
||||
"var parent = new float2((float)pose.ParentCenterX, (float)pose.ParentCenterZ);"
|
||||
},
|
||||
[Path.Combine(root, "Assets", "Scripts", "ServerShared", "Behaviors", "ResourceScanner.cs")] = new[]
|
||||
{
|
||||
|
|
@ -1812,7 +1813,10 @@ static void RequireDaemonRenderQueryAuthority(string root)
|
|||
"TryResolveBodyCenter(body, orbitPositions, out var center)",
|
||||
"public static double EvaluateGravityTerrainHeight(",
|
||||
"zone.GravityTerrainRadius",
|
||||
"zone.GravityTerrainWaveFrequency"
|
||||
"zone.GravityTerrainWaveFrequency",
|
||||
"public static AetheriaRuntimeDaemonBodyPose[] QueryBodyPoses(",
|
||||
"public static int QueryBodyPoses(",
|
||||
"new AetheriaRuntimeDaemonBodyPose("
|
||||
};
|
||||
|
||||
var missingQuerySymbols = requiredQuerySymbols
|
||||
|
|
@ -1878,12 +1882,22 @@ static void RequireDaemonRenderQueryAuthority(string root)
|
|||
"ZoneRenderer must evaluate gravity terrain from daemon render queries instead of the mirrored Unity Zone height evaluator.");
|
||||
}
|
||||
|
||||
if (zoneRenderer.Contains("Zone.GetOrbitPosition(", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"ZoneRenderer must position bodies from daemon render body poses instead of the mirrored Unity Zone orbit evaluator.");
|
||||
}
|
||||
|
||||
var requiredZoneRendererSymbols = new[]
|
||||
{
|
||||
"private AetheriaRuntimeZoneSnapshotCommit _daemonZoneSnapshot;",
|
||||
"private readonly List<AetheriaRuntimeDaemonBodyPose> _daemonBodyPoses",
|
||||
"private readonly Dictionary<string, AetheriaRuntimeDaemonBodyPose> _daemonBodyPosesByBodyKey",
|
||||
"public void LoadZone(Zone zone, AetheriaRuntimeZoneSnapshotCommit daemonZone = null)",
|
||||
"_daemonZoneSnapshot = daemonZone;",
|
||||
"AetheriaRuntimeDaemonRenderQueries.EvaluateGravityTerrainHeight("
|
||||
"AetheriaRuntimeDaemonRenderQueries.EvaluateGravityTerrainHeight(",
|
||||
"AetheriaRuntimeDaemonRenderQueries.QueryBodyPoses(_daemonZoneSnapshot, _daemonBodyPoses);",
|
||||
"_daemonBodyPosesByBodyKey.TryGetValue(planet.Key, out var pose)"
|
||||
};
|
||||
var missingZoneRendererSymbols = requiredZoneRendererSymbols
|
||||
.Where(symbol => !zoneRenderer.Contains(symbol, StringComparison.Ordinal))
|
||||
|
|
|
|||
|
|
@ -730,6 +730,60 @@ public class DaemonRuntimeDocumentTests
|
|||
Assert.AreEqual(-24.9968, height, 0.0001);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DaemonRenderQueriesPublishBodyPosesFromZoneSnapshot()
|
||||
{
|
||||
var zone = new AetheriaRuntimeZoneSnapshotCommit
|
||||
{
|
||||
Orbits = new[]
|
||||
{
|
||||
new AetheriaRuntimeOrbitSnapshotCommit
|
||||
{
|
||||
OrbitKey = "orbit:parent",
|
||||
FixedPositionX = 10,
|
||||
FixedPositionY = 20
|
||||
},
|
||||
new AetheriaRuntimeOrbitSnapshotCommit
|
||||
{
|
||||
OrbitKey = "orbit:child",
|
||||
ParentOrbitKey = "orbit:parent",
|
||||
Distance = 5,
|
||||
Phase = 0.25
|
||||
}
|
||||
},
|
||||
Bodies = new[]
|
||||
{
|
||||
new AetheriaRuntimeBodySnapshotCommit
|
||||
{
|
||||
BodyKey = "body:child",
|
||||
OrbitKey = "orbit:child",
|
||||
Kind = "planet"
|
||||
},
|
||||
new AetheriaRuntimeBodySnapshotCommit
|
||||
{
|
||||
BodyKey = "body:explicit",
|
||||
OrbitKey = "orbit:missing",
|
||||
Kind = "gas_giant",
|
||||
GravityInfluenceCenterX = -3,
|
||||
GravityInfluenceCenterZ = 7
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var poses = AetheriaRuntimeDaemonRenderQueries.QueryBodyPoses(zone);
|
||||
|
||||
Assert.AreEqual(2, poses.Length);
|
||||
Assert.AreEqual("body:child", poses[0].BodyKey);
|
||||
Assert.AreEqual("orbit:parent", poses[0].ParentOrbitKey);
|
||||
Assert.AreEqual(10, poses[0].CenterX, 0.0001);
|
||||
Assert.AreEqual(25, poses[0].CenterZ, 0.0001);
|
||||
Assert.AreEqual(10, poses[0].ParentCenterX, 0.0001);
|
||||
Assert.AreEqual(20, poses[0].ParentCenterZ, 0.0001);
|
||||
Assert.AreEqual("body:explicit", poses[1].BodyKey);
|
||||
Assert.AreEqual(-3, poses[1].CenterX, 0.0001);
|
||||
Assert.AreEqual(7, poses[1].CenterZ, 0.0001);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SoaViewIndexRejectsInvalidRenderGroups()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,6 +86,9 @@ public class ZoneRenderer : MonoBehaviour
|
|||
private PlanetObject[] _suns;
|
||||
private bool _showAsteroidUI;
|
||||
private AetheriaRuntimeZoneSnapshotCommit _daemonZoneSnapshot;
|
||||
private readonly List<AetheriaRuntimeDaemonBodyPose> _daemonBodyPoses = new List<AetheriaRuntimeDaemonBodyPose>();
|
||||
private readonly Dictionary<string, AetheriaRuntimeDaemonBodyPose> _daemonBodyPosesByBodyKey =
|
||||
new Dictionary<string, AetheriaRuntimeDaemonBodyPose>(StringComparer.Ordinal);
|
||||
|
||||
public Dictionary<Wormhole, (GameObject gravity, CompassIcon icon)> WormholeInstances = new Dictionary<Wormhole, (GameObject, CompassIcon)>();
|
||||
private List<ItemPickup> _loot = new List<ItemPickup>();
|
||||
|
|
@ -466,6 +469,7 @@ public class ZoneRenderer : MonoBehaviour
|
|||
// }
|
||||
|
||||
Shader.SetGlobalFloat("_AsteroidVerticalOffset", ActionGameManager.Instance.Settings.PlanetSettings.AsteroidVerticalOffset);
|
||||
RefreshDaemonBodyPoses();
|
||||
|
||||
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(MainCamera);
|
||||
bool isVisible(Bounds bounds) => GeometryUtility.TestPlanesAABB(planes, bounds);
|
||||
|
|
@ -504,8 +508,11 @@ public class ZoneRenderer : MonoBehaviour
|
|||
|
||||
foreach (var planet in Planets)
|
||||
{
|
||||
if (!_daemonBodyPosesByBodyKey.TryGetValue(planet.Key, out var pose))
|
||||
continue;
|
||||
|
||||
var planetInstance = Zone.PlanetInstances[planet.Key];
|
||||
var p = Zone.GetOrbitPosition(planetInstance.OrbitKey);
|
||||
var p = new float2((float)pose.CenterX, (float)pose.CenterZ);
|
||||
var height = GetTerrainHeight(p);
|
||||
if (-height > maxDepth) maxDepth = -height;
|
||||
planet.Value.transform.position = new Vector3(p.x, 0, p.y);
|
||||
|
|
@ -513,10 +520,11 @@ public class ZoneRenderer : MonoBehaviour
|
|||
if (planet.Value is GasGiantObject gasGiantObject)
|
||||
{
|
||||
gasGiantObject.GravityWaves.material.SetFloat("_Phase",
|
||||
Zone.Time * ((GasGiant) Zone.PlanetInstances[planet.Key]).GravityWavesSpeed);
|
||||
Zone.Time * ((GasGiant) Zone.PlanetInstances[planet.Key]).GravityWavesSpeed);
|
||||
if (!(planet.Value is SunObject))
|
||||
{
|
||||
var toParent = normalize(Zone.GetOrbitPosition(planetInstance.Orbit.ParentOrbitKey) - p);
|
||||
var parent = new float2((float)pose.ParentCenterX, (float)pose.ParentCenterZ);
|
||||
var toParent = normalize(parent - p);
|
||||
gasGiantObject.SunMaterial.LightingDirection = new Vector3(toParent.x, 0, toParent.y);
|
||||
}
|
||||
}
|
||||
|
|
@ -564,6 +572,17 @@ public class ZoneRenderer : MonoBehaviour
|
|||
// MinimapTintQuad.transform.position = gravPos - Vector3.up*10;
|
||||
}
|
||||
|
||||
private void RefreshDaemonBodyPoses()
|
||||
{
|
||||
AetheriaRuntimeDaemonRenderQueries.QueryBodyPoses(_daemonZoneSnapshot, _daemonBodyPoses);
|
||||
_daemonBodyPosesByBodyKey.Clear();
|
||||
foreach (var pose in _daemonBodyPoses)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(pose.BodyKey))
|
||||
_daemonBodyPosesByBodyKey[pose.BodyKey] = pose;
|
||||
}
|
||||
}
|
||||
|
||||
private float GetTerrainHeight(float2 position)
|
||||
{
|
||||
return (float)AetheriaRuntimeDaemonRenderQueries.EvaluateGravityTerrainHeight(
|
||||
|
|
|
|||
|
|
@ -69,6 +69,38 @@ namespace GameCult.Aetheria.State.Verse
|
|||
public double WaveSpeed { get; }
|
||||
}
|
||||
|
||||
public readonly struct AetheriaRuntimeDaemonBodyPose
|
||||
{
|
||||
public AetheriaRuntimeDaemonBodyPose(
|
||||
string bodyKey,
|
||||
string orbitKey,
|
||||
string parentOrbitKey,
|
||||
string kind,
|
||||
double centerX,
|
||||
double centerZ,
|
||||
double parentCenterX,
|
||||
double parentCenterZ)
|
||||
{
|
||||
BodyKey = bodyKey ?? "";
|
||||
OrbitKey = orbitKey ?? "";
|
||||
ParentOrbitKey = parentOrbitKey ?? "";
|
||||
Kind = kind ?? "";
|
||||
CenterX = centerX;
|
||||
CenterZ = centerZ;
|
||||
ParentCenterX = parentCenterX;
|
||||
ParentCenterZ = parentCenterZ;
|
||||
}
|
||||
|
||||
public string BodyKey { get; }
|
||||
public string OrbitKey { get; }
|
||||
public string ParentOrbitKey { get; }
|
||||
public string Kind { get; }
|
||||
public double CenterX { get; }
|
||||
public double CenterZ { get; }
|
||||
public double ParentCenterX { get; }
|
||||
public double ParentCenterZ { get; }
|
||||
}
|
||||
|
||||
public static class AetheriaRuntimeDaemonRenderQueries
|
||||
{
|
||||
public static AetheriaRuntimeGravityInfluenceBrush[] QueryGravityInfluences(
|
||||
|
|
@ -119,6 +151,49 @@ namespace GameCult.Aetheria.State.Verse
|
|||
return brushes.Count;
|
||||
}
|
||||
|
||||
public static AetheriaRuntimeDaemonBodyPose[] QueryBodyPoses(
|
||||
AetheriaRuntimeZoneSnapshotCommit? zone)
|
||||
{
|
||||
var poses = new List<AetheriaRuntimeDaemonBodyPose>();
|
||||
QueryBodyPoses(zone, poses);
|
||||
return poses.Count == 0 ? Array.Empty<AetheriaRuntimeDaemonBodyPose>() : poses.ToArray();
|
||||
}
|
||||
|
||||
public static int QueryBodyPoses(
|
||||
AetheriaRuntimeZoneSnapshotCommit? zone,
|
||||
List<AetheriaRuntimeDaemonBodyPose> poses)
|
||||
{
|
||||
if (poses == null) throw new ArgumentNullException(nameof(poses));
|
||||
poses.Clear();
|
||||
if (zone == null)
|
||||
return 0;
|
||||
|
||||
var orbitPositions = BuildOrbitPositions(zone);
|
||||
var orbits = BuildOrbitMap(zone);
|
||||
foreach (var body in zone.Bodies ?? Array.Empty<AetheriaRuntimeBodySnapshotCommit>())
|
||||
{
|
||||
if (body == null || !TryResolveBodyCenter(body, orbitPositions, out var center))
|
||||
continue;
|
||||
|
||||
var orbitKey = body.OrbitKey ?? "";
|
||||
var parentOrbitKey = orbits.TryGetValue(orbitKey, out var orbit) ? orbit.ParentOrbitKey ?? "" : "";
|
||||
var parentCenter = orbitPositions.TryGetValue(parentOrbitKey, out var parent)
|
||||
? parent
|
||||
: new AetheriaRuntimeXzPoint(0, 0);
|
||||
poses.Add(new AetheriaRuntimeDaemonBodyPose(
|
||||
body.BodyKey,
|
||||
orbitKey,
|
||||
parentOrbitKey,
|
||||
body.Kind,
|
||||
center.x,
|
||||
center.z,
|
||||
parentCenter.x,
|
||||
parentCenter.z));
|
||||
}
|
||||
|
||||
return poses.Count;
|
||||
}
|
||||
|
||||
public static AetheriaRuntimeDaemonRenderGroupDocument[] QueryRenderGroups(
|
||||
AetheriaRuntimeDaemonSoaViewIndex? index,
|
||||
double minX,
|
||||
|
|
@ -211,12 +286,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
|
||||
private static Dictionary<string, AetheriaRuntimeXzPoint> BuildOrbitPositions(AetheriaRuntimeZoneSnapshotCommit zone)
|
||||
{
|
||||
var source = new Dictionary<string, AetheriaRuntimeOrbitSnapshotCommit>(StringComparer.Ordinal);
|
||||
foreach (var orbit in zone.Orbits ?? Array.Empty<AetheriaRuntimeOrbitSnapshotCommit>())
|
||||
{
|
||||
if (orbit != null && !string.IsNullOrWhiteSpace(orbit.OrbitKey))
|
||||
source[orbit.OrbitKey] = orbit;
|
||||
}
|
||||
var source = BuildOrbitMap(zone);
|
||||
|
||||
var positions = new Dictionary<string, AetheriaRuntimeXzPoint>(StringComparer.Ordinal)
|
||||
{
|
||||
|
|
@ -228,6 +298,19 @@ namespace GameCult.Aetheria.State.Verse
|
|||
return positions;
|
||||
}
|
||||
|
||||
private static Dictionary<string, AetheriaRuntimeOrbitSnapshotCommit> BuildOrbitMap(
|
||||
AetheriaRuntimeZoneSnapshotCommit zone)
|
||||
{
|
||||
var source = new Dictionary<string, AetheriaRuntimeOrbitSnapshotCommit>(StringComparer.Ordinal);
|
||||
foreach (var orbit in zone.Orbits ?? Array.Empty<AetheriaRuntimeOrbitSnapshotCommit>())
|
||||
{
|
||||
if (orbit != null && !string.IsNullOrWhiteSpace(orbit.OrbitKey))
|
||||
source[orbit.OrbitKey] = orbit;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeXzPoint ResolveOrbitPosition(
|
||||
string orbitKey,
|
||||
Dictionary<string, AetheriaRuntimeOrbitSnapshotCommit> source,
|
||||
|
|
|
|||
Loading…
Reference in a new issue