feat: simplified local-space and celestial, removed bubbles
This commit is contained in:
@@ -6,48 +6,44 @@ public sealed partial class ScenarioLoader
|
||||
{
|
||||
private static SystemSpatialGraph BuildSystemSpatialGraph(SystemRuntime system)
|
||||
{
|
||||
var nodes = new List<NodeRuntime>();
|
||||
var bubbles = new List<LocalBubbleRuntime>();
|
||||
var lagrangeNodesByPlanetIndex = new Dictionary<int, Dictionary<string, NodeRuntime>>();
|
||||
var celestials = new List<CelestialRuntime>();
|
||||
var lagrangeNodesByPlanetIndex = new Dictionary<int, Dictionary<string, CelestialRuntime>>();
|
||||
|
||||
var starNode = AddSpatialNode(
|
||||
nodes,
|
||||
bubbles,
|
||||
AddCelestial(
|
||||
celestials,
|
||||
id: $"node-{system.Definition.Id}-star",
|
||||
systemId: system.Definition.Id,
|
||||
kind: SpatialNodeKind.Star,
|
||||
position: Vector3.Zero,
|
||||
radius: MathF.Max(system.Definition.GravityWellRadius + StarBubbleRadiusPadding, 180f));
|
||||
localSpaceRadius: MathF.Max(system.Definition.GravityWellRadius + StarBubbleRadiusPadding, LocalSpaceRadius));
|
||||
|
||||
for (var planetIndex = 0; planetIndex < system.Definition.Planets.Count; planetIndex += 1)
|
||||
{
|
||||
var planet = system.Definition.Planets[planetIndex];
|
||||
var planetNodeId = $"node-{system.Definition.Id}-planet-{planetIndex + 1}";
|
||||
var planetPosition = ComputePlanetPosition(planet);
|
||||
var planetNode = AddSpatialNode(
|
||||
nodes,
|
||||
bubbles,
|
||||
var planetCelestial = AddCelestial(
|
||||
celestials,
|
||||
id: planetNodeId,
|
||||
systemId: system.Definition.Id,
|
||||
kind: SpatialNodeKind.Planet,
|
||||
position: planetPosition,
|
||||
radius: MathF.Max(planet.Size + PlanetBubbleRadiusPadding, 120f),
|
||||
parentNodeId: starNode.Id);
|
||||
localSpaceRadius: LocalSpaceRadius,
|
||||
parentNodeId: $"node-{system.Definition.Id}-star");
|
||||
|
||||
var lagrangeNodes = new Dictionary<string, NodeRuntime>(StringComparer.Ordinal);
|
||||
var lagrangeNodes = new Dictionary<string, CelestialRuntime>(StringComparer.Ordinal);
|
||||
foreach (var point in EnumeratePlanetLagrangePoints(planetPosition, planet))
|
||||
{
|
||||
var lagrangeNode = AddSpatialNode(
|
||||
nodes,
|
||||
bubbles,
|
||||
var lagrangeCelestial = AddCelestial(
|
||||
celestials,
|
||||
id: $"node-{system.Definition.Id}-planet-{planetIndex + 1}-{point.Designation.ToLowerInvariant()}",
|
||||
systemId: system.Definition.Id,
|
||||
kind: SpatialNodeKind.LagrangePoint,
|
||||
position: point.Position,
|
||||
radius: LagrangeBubbleRadius,
|
||||
parentNodeId: planetNode.Id,
|
||||
localSpaceRadius: LocalSpaceRadius,
|
||||
parentNodeId: planetCelestial.Id,
|
||||
orbitReferenceId: point.Designation);
|
||||
lagrangeNodes[point.Designation] = lagrangeNode;
|
||||
lagrangeNodes[point.Designation] = lagrangeCelestial;
|
||||
}
|
||||
|
||||
lagrangeNodesByPlanetIndex[planetIndex] = lagrangeNodes;
|
||||
@@ -61,54 +57,44 @@ public sealed partial class ScenarioLoader
|
||||
for (var moonIndex = 0; moonIndex < planet.MoonCount; moonIndex += 1)
|
||||
{
|
||||
var moonPosition = ComputeMoonPosition(planetPosition, moonOrbitRadius, moonIndex, planetIndex);
|
||||
AddSpatialNode(
|
||||
nodes,
|
||||
bubbles,
|
||||
AddCelestial(
|
||||
celestials,
|
||||
id: $"node-{system.Definition.Id}-planet-{planetIndex + 1}-moon-{moonIndex + 1}",
|
||||
systemId: system.Definition.Id,
|
||||
kind: SpatialNodeKind.Moon,
|
||||
position: moonPosition,
|
||||
radius: MoonBubbleRadiusPadding + 24f,
|
||||
parentNodeId: planetNode.Id);
|
||||
localSpaceRadius: LocalSpaceRadius,
|
||||
parentNodeId: planetCelestial.Id);
|
||||
moonOrbitRadius += 30f;
|
||||
}
|
||||
}
|
||||
|
||||
return new SystemSpatialGraph(system.Definition.Id, nodes, bubbles, lagrangeNodesByPlanetIndex);
|
||||
return new SystemSpatialGraph(system.Definition.Id, celestials, lagrangeNodesByPlanetIndex);
|
||||
}
|
||||
|
||||
private static NodeRuntime AddSpatialNode(
|
||||
ICollection<NodeRuntime> nodes,
|
||||
ICollection<LocalBubbleRuntime> bubbles,
|
||||
private static CelestialRuntime AddCelestial(
|
||||
ICollection<CelestialRuntime> celestials,
|
||||
string id,
|
||||
string systemId,
|
||||
SpatialNodeKind kind,
|
||||
Vector3 position,
|
||||
float radius,
|
||||
float localSpaceRadius,
|
||||
string? parentNodeId = null,
|
||||
string? orbitReferenceId = null)
|
||||
{
|
||||
var bubbleId = $"bubble-{id}";
|
||||
var node = new NodeRuntime
|
||||
var celestial = new CelestialRuntime
|
||||
{
|
||||
Id = id,
|
||||
SystemId = systemId,
|
||||
Kind = kind,
|
||||
Position = position,
|
||||
BubbleId = bubbleId,
|
||||
LocalSpaceRadius = localSpaceRadius,
|
||||
ParentNodeId = parentNodeId,
|
||||
OrbitReferenceId = orbitReferenceId,
|
||||
};
|
||||
|
||||
nodes.Add(node);
|
||||
bubbles.Add(new LocalBubbleRuntime
|
||||
{
|
||||
Id = bubbleId,
|
||||
NodeId = id,
|
||||
SystemId = systemId,
|
||||
Radius = radius,
|
||||
});
|
||||
return node;
|
||||
celestials.Add(celestial);
|
||||
return celestial;
|
||||
}
|
||||
|
||||
private static IEnumerable<LagrangePointPlacement> EnumeratePlanetLagrangePoints(
|
||||
@@ -165,36 +151,36 @@ public sealed partial class ScenarioLoader
|
||||
InitialStationDefinition plan,
|
||||
SystemRuntime system,
|
||||
SystemSpatialGraph graph,
|
||||
IReadOnlyCollection<NodeRuntime> existingNodes)
|
||||
IReadOnlyCollection<CelestialRuntime> existingCelestials)
|
||||
{
|
||||
if (plan.PlanetIndex is int planetIndex &&
|
||||
graph.LagrangeNodesByPlanetIndex.TryGetValue(planetIndex, out var lagrangeNodes))
|
||||
{
|
||||
var designation = ResolveLagrangeDesignation(plan.LagrangeSide);
|
||||
if (lagrangeNodes.TryGetValue(designation, out var lagrangeNode))
|
||||
if (lagrangeNodes.TryGetValue(designation, out var lagrangeCelestial))
|
||||
{
|
||||
return new StationPlacement(lagrangeNode, lagrangeNode.Position);
|
||||
return new StationPlacement(lagrangeCelestial, lagrangeCelestial.Position);
|
||||
}
|
||||
}
|
||||
|
||||
if (plan.Position is { Length: 3 })
|
||||
{
|
||||
var targetPosition = NormalizeScenarioPoint(system, plan.Position);
|
||||
var preferredNode = existingNodes
|
||||
.Where((node) => node.SystemId == system.Definition.Id && node.Kind == SpatialNodeKind.LagrangePoint)
|
||||
.OrderBy((node) => node.Position.DistanceTo(targetPosition))
|
||||
var preferredCelestial = existingCelestials
|
||||
.Where((c) => c.SystemId == system.Definition.Id && c.Kind == SpatialNodeKind.LagrangePoint)
|
||||
.OrderBy((c) => c.Position.DistanceTo(targetPosition))
|
||||
.FirstOrDefault()
|
||||
?? existingNodes
|
||||
.Where((node) => node.SystemId == system.Definition.Id)
|
||||
.OrderBy((node) => node.Position.DistanceTo(targetPosition))
|
||||
?? existingCelestials
|
||||
.Where((c) => c.SystemId == system.Definition.Id)
|
||||
.OrderBy((c) => c.Position.DistanceTo(targetPosition))
|
||||
.First();
|
||||
return new StationPlacement(preferredNode, preferredNode.Position);
|
||||
return new StationPlacement(preferredCelestial, preferredCelestial.Position);
|
||||
}
|
||||
|
||||
var fallbackNode = graph.Nodes
|
||||
.FirstOrDefault((node) => node.Kind == SpatialNodeKind.LagrangePoint && string.IsNullOrEmpty(node.OccupyingStructureId))
|
||||
?? graph.Nodes.First((node) => node.Kind == SpatialNodeKind.Planet);
|
||||
return new StationPlacement(fallbackNode, fallbackNode.Position);
|
||||
var fallbackCelestial = graph.Celestials
|
||||
.FirstOrDefault((c) => c.Kind == SpatialNodeKind.LagrangePoint && string.IsNullOrEmpty(c.OccupyingStructureId))
|
||||
?? graph.Celestials.First((c) => c.Kind == SpatialNodeKind.Planet);
|
||||
return new StationPlacement(fallbackCelestial, fallbackCelestial.Position);
|
||||
}
|
||||
|
||||
private static string ResolveLagrangeDesignation(int? lagrangeSide) => lagrangeSide switch
|
||||
@@ -204,7 +190,7 @@ public sealed partial class ScenarioLoader
|
||||
_ => "L1",
|
||||
};
|
||||
|
||||
private static NodeRuntime? ResolveResourceNodeAnchor(SystemSpatialGraph graph, ResourceNodeDefinition definition)
|
||||
private static CelestialRuntime? ResolveResourceNodeAnchor(SystemSpatialGraph graph, ResourceNodeDefinition definition)
|
||||
{
|
||||
if (definition.AnchorPlanetIndex is not int planetIndex || planetIndex < 0)
|
||||
{
|
||||
@@ -214,14 +200,14 @@ public sealed partial class ScenarioLoader
|
||||
if (definition.AnchorMoonIndex is int moonIndex && moonIndex >= 0)
|
||||
{
|
||||
var moonNodeId = $"node-{graph.SystemId}-planet-{planetIndex + 1}-moon-{moonIndex + 1}";
|
||||
return graph.Nodes.FirstOrDefault((node) => node.Id == moonNodeId);
|
||||
return graph.Celestials.FirstOrDefault((c) => c.Id == moonNodeId);
|
||||
}
|
||||
|
||||
var planetNodeId = $"node-{graph.SystemId}-planet-{planetIndex + 1}";
|
||||
return graph.Nodes.FirstOrDefault((node) => node.Id == planetNodeId);
|
||||
return graph.Celestials.FirstOrDefault((c) => c.Id == planetNodeId);
|
||||
}
|
||||
|
||||
private static Vector3 ComputeResourceNodePosition(NodeRuntime? anchorNode, ResourceNodeDefinition definition, float yPlane)
|
||||
private static Vector3 ComputeResourceNodePosition(CelestialRuntime? anchorCelestial, ResourceNodeDefinition definition, float yPlane)
|
||||
{
|
||||
var verticalOffset = MathF.Sin(DegreesToRadians(definition.InclinationDegrees)) * MathF.Min(definition.RadiusOffset * 0.04f, 25000f);
|
||||
var offset = new Vector3(
|
||||
@@ -229,12 +215,12 @@ public sealed partial class ScenarioLoader
|
||||
verticalOffset,
|
||||
MathF.Sin(definition.Angle) * definition.RadiusOffset);
|
||||
|
||||
if (anchorNode is null)
|
||||
if (anchorCelestial is null)
|
||||
{
|
||||
return new Vector3(offset.X, yPlane + offset.Y, offset.Z);
|
||||
}
|
||||
|
||||
return Add(anchorNode.Position, offset);
|
||||
return Add(anchorCelestial.Position, offset);
|
||||
}
|
||||
|
||||
private static Vector3 ComputePlanetPosition(PlanetDefinition planet)
|
||||
@@ -252,19 +238,18 @@ public sealed partial class ScenarioLoader
|
||||
return Add(planetPosition, new Vector3(MathF.Cos(angle) * orbitRadius, 0f, MathF.Sin(angle) * orbitRadius));
|
||||
}
|
||||
|
||||
private static ShipSpatialStateRuntime CreateInitialShipSpatialState(string systemId, Vector3 position, IReadOnlyCollection<NodeRuntime> nodes)
|
||||
private static ShipSpatialStateRuntime CreateInitialShipSpatialState(string systemId, Vector3 position, IReadOnlyCollection<CelestialRuntime> celestials)
|
||||
{
|
||||
var nearestNode = nodes
|
||||
.Where((node) => node.SystemId == systemId)
|
||||
.OrderBy((node) => node.Position.DistanceTo(position))
|
||||
var nearestCelestial = celestials
|
||||
.Where((c) => c.SystemId == systemId)
|
||||
.OrderBy((c) => c.Position.DistanceTo(position))
|
||||
.FirstOrDefault();
|
||||
|
||||
return new ShipSpatialStateRuntime
|
||||
{
|
||||
CurrentSystemId = systemId,
|
||||
SpaceLayer = SpaceLayerKinds.LocalSpace,
|
||||
CurrentNodeId = nearestNode?.Id,
|
||||
CurrentBubbleId = nearestNode?.BubbleId,
|
||||
CurrentCelestialId = nearestCelestial?.Id,
|
||||
LocalPosition = position,
|
||||
SystemPosition = position,
|
||||
MovementRegime = MovementRegimeKinds.LocalFlight,
|
||||
@@ -273,11 +258,10 @@ public sealed partial class ScenarioLoader
|
||||
|
||||
private sealed record SystemSpatialGraph(
|
||||
string SystemId,
|
||||
List<NodeRuntime> Nodes,
|
||||
List<LocalBubbleRuntime> Bubbles,
|
||||
Dictionary<int, Dictionary<string, NodeRuntime>> LagrangeNodesByPlanetIndex);
|
||||
List<CelestialRuntime> Celestials,
|
||||
Dictionary<int, Dictionary<string, CelestialRuntime>> LagrangeNodesByPlanetIndex);
|
||||
|
||||
private sealed record LagrangePointPlacement(string Designation, Vector3 Position);
|
||||
|
||||
private sealed record StationPlacement(NodeRuntime AnchorNode, Vector3 Position);
|
||||
private sealed record StationPlacement(CelestialRuntime AnchorCelestial, Vector3 Position);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user