Position asteroid belts from daemon poses
This commit is contained in:
parent
5bfe9d9b29
commit
4e68ce29af
4 changed files with 166 additions and 8 deletions
|
|
@ -1816,7 +1816,11 @@ static void RequireDaemonRenderQueryAuthority(string root)
|
|||
"zone.GravityTerrainWaveFrequency",
|
||||
"public static AetheriaRuntimeDaemonBodyPose[] QueryBodyPoses(",
|
||||
"public static int QueryBodyPoses(",
|
||||
"new AetheriaRuntimeDaemonBodyPose("
|
||||
"new AetheriaRuntimeDaemonBodyPose(",
|
||||
"AetheriaRuntimeDaemonAsteroidBeltPose",
|
||||
"public static AetheriaRuntimeDaemonAsteroidBeltPose[] QueryAsteroidBeltPoses(",
|
||||
"public static int QueryAsteroidBeltPoses(",
|
||||
"ResolveAsteroidBeltRadius(body)"
|
||||
};
|
||||
|
||||
var missingQuerySymbols = requiredQuerySymbols
|
||||
|
|
@ -1894,16 +1898,27 @@ static void RequireDaemonRenderQueryAuthority(string root)
|
|||
"ZoneRenderer frame updates must read body render state from daemon body poses instead of indexed mirrored Unity planets.");
|
||||
}
|
||||
|
||||
if (zoneRenderer.Contains("belt.OrbitPosition", StringComparison.Ordinal) ||
|
||||
zoneRenderer.Contains("belt.Radius", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"ZoneRenderer frame updates must read asteroid belt pose and radius from daemon belt poses instead of mirrored Unity asteroid belts.");
|
||||
}
|
||||
|
||||
var requiredZoneRendererSymbols = new[]
|
||||
{
|
||||
"private AetheriaRuntimeZoneSnapshotCommit _daemonZoneSnapshot;",
|
||||
"private readonly List<AetheriaRuntimeDaemonBodyPose> _daemonBodyPoses",
|
||||
"private readonly Dictionary<string, AetheriaRuntimeDaemonBodyPose> _daemonBodyPosesByBodyKey",
|
||||
"private readonly List<AetheriaRuntimeDaemonAsteroidBeltPose> _daemonAsteroidBeltPoses",
|
||||
"private readonly Dictionary<string, AetheriaRuntimeDaemonAsteroidBeltPose> _daemonAsteroidBeltPosesByBodyKey",
|
||||
"public void LoadZone(Zone zone, AetheriaRuntimeZoneSnapshotCommit daemonZone = null)",
|
||||
"_daemonZoneSnapshot = daemonZone;",
|
||||
"AetheriaRuntimeDaemonRenderQueries.EvaluateGravityTerrainHeight(",
|
||||
"AetheriaRuntimeDaemonRenderQueries.QueryBodyPoses(_daemonZoneSnapshot, _daemonBodyPoses);",
|
||||
"AetheriaRuntimeDaemonRenderQueries.QueryAsteroidBeltPoses(_daemonZoneSnapshot, _daemonAsteroidBeltPoses);",
|
||||
"_daemonBodyPosesByBodyKey.TryGetValue(planet.Key, out var pose)",
|
||||
"_daemonAsteroidBeltPosesByBodyKey.TryGetValue(key, out var beltPose)",
|
||||
"pose.GravityWaveSpeed"
|
||||
};
|
||||
var missingZoneRendererSymbols = requiredZoneRendererSymbols
|
||||
|
|
|
|||
|
|
@ -786,6 +786,54 @@ public class DaemonRuntimeDocumentTests
|
|||
Assert.AreEqual(3.5, poses[1].GravityWaveSpeed, 0.0001);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DaemonRenderQueriesPublishAsteroidBeltPosesFromZoneSnapshot()
|
||||
{
|
||||
var zone = new AetheriaRuntimeZoneSnapshotCommit
|
||||
{
|
||||
Orbits = new[]
|
||||
{
|
||||
new AetheriaRuntimeOrbitSnapshotCommit
|
||||
{
|
||||
OrbitKey = "orbit:belt",
|
||||
FixedPositionX = 11,
|
||||
FixedPositionY = -4
|
||||
}
|
||||
},
|
||||
Bodies = new[]
|
||||
{
|
||||
new AetheriaRuntimeBodySnapshotCommit
|
||||
{
|
||||
BodyKey = "body:belt",
|
||||
OrbitKey = "orbit:belt",
|
||||
Kind = "asteroid_belt",
|
||||
Asteroids = new[]
|
||||
{
|
||||
new AetheriaRuntimeAsteroidCommit { Distance = 3 },
|
||||
new AetheriaRuntimeAsteroidCommit { Distance = 7 },
|
||||
new AetheriaRuntimeAsteroidCommit { Distance = 5 }
|
||||
}
|
||||
},
|
||||
new AetheriaRuntimeBodySnapshotCommit
|
||||
{
|
||||
BodyKey = "body:planet",
|
||||
OrbitKey = "orbit:belt",
|
||||
Kind = "planet"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var poses = AetheriaRuntimeDaemonRenderQueries.QueryAsteroidBeltPoses(zone);
|
||||
|
||||
Assert.AreEqual(1, poses.Length);
|
||||
Assert.AreEqual("body:belt", poses[0].BodyKey);
|
||||
Assert.AreEqual("orbit:belt", poses[0].OrbitKey);
|
||||
Assert.AreEqual(11, poses[0].CenterX, 0.0001);
|
||||
Assert.AreEqual(-4, poses[0].CenterZ, 0.0001);
|
||||
Assert.AreEqual(7, poses[0].Radius, 0.0001);
|
||||
Assert.AreEqual(3, poses[0].AsteroidCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SoaViewIndexRejectsInvalidRenderGroups()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ public class ZoneRenderer : MonoBehaviour
|
|||
private readonly List<AetheriaRuntimeDaemonBodyPose> _daemonBodyPoses = new List<AetheriaRuntimeDaemonBodyPose>();
|
||||
private readonly Dictionary<string, AetheriaRuntimeDaemonBodyPose> _daemonBodyPosesByBodyKey =
|
||||
new Dictionary<string, AetheriaRuntimeDaemonBodyPose>(StringComparer.Ordinal);
|
||||
private readonly List<AetheriaRuntimeDaemonAsteroidBeltPose> _daemonAsteroidBeltPoses =
|
||||
new List<AetheriaRuntimeDaemonAsteroidBeltPose>();
|
||||
private readonly Dictionary<string, AetheriaRuntimeDaemonAsteroidBeltPose> _daemonAsteroidBeltPosesByBodyKey =
|
||||
new Dictionary<string, AetheriaRuntimeDaemonAsteroidBeltPose>(StringComparer.Ordinal);
|
||||
|
||||
public Dictionary<Wormhole, (GameObject gravity, CompassIcon icon)> WormholeInstances = new Dictionary<Wormhole, (GameObject, CompassIcon)>();
|
||||
private List<ItemPickup> _loot = new List<ItemPickup>();
|
||||
|
|
@ -470,16 +474,21 @@ public class ZoneRenderer : MonoBehaviour
|
|||
|
||||
Shader.SetGlobalFloat("_AsteroidVerticalOffset", ActionGameManager.Instance.Settings.PlanetSettings.AsteroidVerticalOffset);
|
||||
RefreshDaemonBodyPoses();
|
||||
RefreshDaemonAsteroidBeltPoses();
|
||||
|
||||
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(MainCamera);
|
||||
bool isVisible(Bounds bounds) => GeometryUtility.TestPlanesAABB(planes, bounds);
|
||||
|
||||
foreach (var (key, belt) in Zone.AsteroidBelts)
|
||||
{
|
||||
var height = GetTerrainHeight(belt.OrbitPosition);
|
||||
if (!_daemonAsteroidBeltPosesByBodyKey.TryGetValue(key, out var beltPose))
|
||||
continue;
|
||||
|
||||
var center = new float2((float)beltPose.CenterX, (float)beltPose.CenterZ);
|
||||
var height = GetTerrainHeight(center);
|
||||
if(isVisible(new Bounds(
|
||||
new Vector3(belt.OrbitPosition.x,height,belt.OrbitPosition.y),
|
||||
new Vector3(belt.Radius * 2,100,belt.Radius * 2))))
|
||||
new Vector3(center.x,height,center.y),
|
||||
new Vector3((float)beltPose.Radius * 2,100,(float)beltPose.Radius * 2))))
|
||||
{
|
||||
var meshes = _beltMeshes[key];
|
||||
var matrices = _beltMatrices[key];
|
||||
|
|
@ -503,7 +512,7 @@ public class ZoneRenderer : MonoBehaviour
|
|||
}
|
||||
|
||||
if(_showAsteroidUI)
|
||||
_beltObjects[key].Update(belt.Transforms, height);
|
||||
_beltObjects[key].Update(belt.Transforms, center, height, (float)beltPose.Radius);
|
||||
}
|
||||
|
||||
foreach (var planet in Planets)
|
||||
|
|
@ -583,6 +592,17 @@ public class ZoneRenderer : MonoBehaviour
|
|||
}
|
||||
}
|
||||
|
||||
private void RefreshDaemonAsteroidBeltPoses()
|
||||
{
|
||||
AetheriaRuntimeDaemonRenderQueries.QueryAsteroidBeltPoses(_daemonZoneSnapshot, _daemonAsteroidBeltPoses);
|
||||
_daemonAsteroidBeltPosesByBodyKey.Clear();
|
||||
foreach (var pose in _daemonAsteroidBeltPoses)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(pose.BodyKey))
|
||||
_daemonAsteroidBeltPosesByBodyKey[pose.BodyKey] = pose;
|
||||
}
|
||||
}
|
||||
|
||||
private float GetTerrainHeight(float2 position)
|
||||
{
|
||||
return (float)AetheriaRuntimeDaemonRenderQueries.EvaluateGravityTerrainHeight(
|
||||
|
|
@ -716,9 +736,8 @@ public class AsteroidBeltUI
|
|||
//_collider.sharedMesh = _mesh;
|
||||
}
|
||||
|
||||
public void Update(float4[] transforms, float height)
|
||||
public void Update(float4[] transforms, float2 center, float height, float radius)
|
||||
{
|
||||
var parentPosition = _belt.OrbitPosition;
|
||||
for (var i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
var transform = transforms[i];
|
||||
|
|
@ -730,7 +749,8 @@ public class AsteroidBeltUI
|
|||
_vertices[i * 4 + 3] = rotation * new Vector3(transform.w * _scale, -transform.w * _scale, 0) + position;
|
||||
}
|
||||
|
||||
_mesh.bounds = new Bounds(new Vector3(parentPosition.x, 0, parentPosition.y), Vector3.one * (_size * 2));
|
||||
var boundsRadius = Math.Max(_size, radius);
|
||||
_mesh.bounds = new Bounds(new Vector3(center.x, 0, center.y), Vector3.one * (boundsRadius * 2));
|
||||
_mesh.vertices = _vertices;
|
||||
//_collider.sharedMesh = _mesh;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,32 @@ namespace GameCult.Aetheria.State.Verse
|
|||
public double GravityWaveSpeed { get; }
|
||||
}
|
||||
|
||||
public readonly struct AetheriaRuntimeDaemonAsteroidBeltPose
|
||||
{
|
||||
public AetheriaRuntimeDaemonAsteroidBeltPose(
|
||||
string bodyKey,
|
||||
string orbitKey,
|
||||
double centerX,
|
||||
double centerZ,
|
||||
double radius,
|
||||
int asteroidCount)
|
||||
{
|
||||
BodyKey = bodyKey ?? "";
|
||||
OrbitKey = orbitKey ?? "";
|
||||
CenterX = centerX;
|
||||
CenterZ = centerZ;
|
||||
Radius = Math.Max(0, radius);
|
||||
AsteroidCount = Math.Max(0, asteroidCount);
|
||||
}
|
||||
|
||||
public string BodyKey { get; }
|
||||
public string OrbitKey { get; }
|
||||
public double CenterX { get; }
|
||||
public double CenterZ { get; }
|
||||
public double Radius { get; }
|
||||
public int AsteroidCount { get; }
|
||||
}
|
||||
|
||||
public static class AetheriaRuntimeDaemonRenderQueries
|
||||
{
|
||||
public static AetheriaRuntimeGravityInfluenceBrush[] QueryGravityInfluences(
|
||||
|
|
@ -198,6 +224,43 @@ namespace GameCult.Aetheria.State.Verse
|
|||
return poses.Count;
|
||||
}
|
||||
|
||||
public static AetheriaRuntimeDaemonAsteroidBeltPose[] QueryAsteroidBeltPoses(
|
||||
AetheriaRuntimeZoneSnapshotCommit? zone)
|
||||
{
|
||||
var poses = new List<AetheriaRuntimeDaemonAsteroidBeltPose>();
|
||||
QueryAsteroidBeltPoses(zone, poses);
|
||||
return poses.Count == 0 ? Array.Empty<AetheriaRuntimeDaemonAsteroidBeltPose>() : poses.ToArray();
|
||||
}
|
||||
|
||||
public static int QueryAsteroidBeltPoses(
|
||||
AetheriaRuntimeZoneSnapshotCommit? zone,
|
||||
List<AetheriaRuntimeDaemonAsteroidBeltPose> poses)
|
||||
{
|
||||
if (poses == null) throw new ArgumentNullException(nameof(poses));
|
||||
poses.Clear();
|
||||
if (zone == null)
|
||||
return 0;
|
||||
|
||||
var orbitPositions = BuildOrbitPositions(zone);
|
||||
foreach (var body in zone.Bodies ?? Array.Empty<AetheriaRuntimeBodySnapshotCommit>())
|
||||
{
|
||||
if (body == null ||
|
||||
!string.Equals(body.Kind, "asteroid_belt", StringComparison.OrdinalIgnoreCase) ||
|
||||
!TryResolveBodyCenter(body, orbitPositions, out var center))
|
||||
continue;
|
||||
|
||||
poses.Add(new AetheriaRuntimeDaemonAsteroidBeltPose(
|
||||
body.BodyKey,
|
||||
body.OrbitKey,
|
||||
center.x,
|
||||
center.z,
|
||||
ResolveAsteroidBeltRadius(body),
|
||||
body.Asteroids?.Count ?? 0));
|
||||
}
|
||||
|
||||
return poses.Count;
|
||||
}
|
||||
|
||||
public static AetheriaRuntimeDaemonRenderGroupDocument[] QueryRenderGroups(
|
||||
AetheriaRuntimeDaemonSoaViewIndex? index,
|
||||
double minX,
|
||||
|
|
@ -419,6 +482,18 @@ namespace GameCult.Aetheria.State.Verse
|
|||
return body.GravityWaveSpeed;
|
||||
}
|
||||
|
||||
private static double ResolveAsteroidBeltRadius(AetheriaRuntimeBodySnapshotCommit body)
|
||||
{
|
||||
var radius = 0.0;
|
||||
foreach (var asteroid in body.Asteroids ?? Array.Empty<AetheriaRuntimeAsteroidCommit>())
|
||||
{
|
||||
if (asteroid != null && asteroid.Distance > radius)
|
||||
radius = asteroid.Distance;
|
||||
}
|
||||
|
||||
return radius;
|
||||
}
|
||||
|
||||
private static double Clamp(double value, double min, double max)
|
||||
{
|
||||
return value < min ? min : value > max ? max : value;
|
||||
|
|
|
|||
Loading…
Reference in a new issue