From 8f491fd3c9a43822071cb4c9067354fa9b304ae5 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 15 Oct 2026 16:46:53 +0200 Subject: [PATCH] Core radius is the Roche curve; the global exaggeration divides by the core's growth core-at-roche-and-exaggeration-up: PlanetSettings.CoreRadius and Planet.CoreRadius are deleted; the well's softened core reads the RocheLimit curve (one curve of mass). The core < Roche guard cannot fail and is replaced by a Roche-limit-positive-and-finite check. Settings.asset: CoreRadius removed, HeightExaggeration 10 -> 4.0983607 (10 / (7.32 / 3)). Tests pin the new curves and the peak drawn slope / 2.44x steeper tail. Not yet built or run at this commit. Co-Authored-By: Claude Opus 5.5 --- Assets/Resources/Settings.asset | 4 +- .../Editor/GravityFieldParityVerify.cs | 2 +- Assets/Scripts/ServerShared/Settings.cs | 7 +- Assets/Scripts/ServerShared/Zone.cs | 16 ++- .../Scripts/Zone Display/GravityLowering.cs | 2 +- .../GravitySubtractTests.cs | 3 +- .../PotentialOwnerTests.cs | 98 ++++++++----------- tests/Aetheria.Shared.Tests/WellFixture.cs | 7 +- .../ZonePlacedAtBuildTests.cs | 5 +- 9 files changed, 63 insertions(+), 81 deletions(-) diff --git a/Assets/Resources/Settings.asset b/Assets/Resources/Settings.asset index ec980b8e8..df56f95ed 100644 --- a/Assets/Resources/Settings.asset +++ b/Assets/Resources/Settings.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:51f559958bd719e1d158b526bee1876fc3c838462b638d79c4f448c34331c420 -size 12712 +oid sha256:9d641fe942dfd45990a0609b3017a63cdc27f502ab12aa74ffbf984ea3e8d346 +size 12644 diff --git a/Assets/Scripts/Editor/GravityFieldParityVerify.cs b/Assets/Scripts/Editor/GravityFieldParityVerify.cs index ae512d16e..c6de02c4a 100644 --- a/Assets/Scripts/Editor/GravityFieldParityVerify.cs +++ b/Assets/Scripts/Editor/GravityFieldParityVerify.cs @@ -106,7 +106,7 @@ namespace Aetheria.EditorTools EditorApplication.Exit(_ok ? 0 : 1); } - static float Core(Zone zone, float mass) => zone.Settings.CoreRadius.Evaluate(mass); + static float Core(Zone zone, float mass) => zone.Settings.RocheLimit.Evaluate(mass); static Vector2 At(Orbit orbit) => new Vector2(orbit.Position.x, orbit.Position.y); diff --git a/Assets/Scripts/ServerShared/Settings.cs b/Assets/Scripts/ServerShared/Settings.cs index 6fcdd8f61..24078a658 100644 --- a/Assets/Scripts/ServerShared/Settings.cs +++ b/Assets/Scripts/ServerShared/Settings.cs @@ -16,13 +16,12 @@ public class PlanetSettings public ExponentialCurve LightRadius; public ExponentialCurve BodyRadius; - // The closest a child may orbit its parent, in u, by the parent's mass. Authored like BodyRadius, never per body. + // The closest a child may orbit its parent, in u, by the parent's mass, and the softened core radius of the parent's + // well (the steepest drawn slope sits at the Roche limit). Authored like BodyRadius, never per body. public ExponentialCurve RocheLimit = new ExponentialCurve(); - // A body's well, by its mass (GravityField): its strength c in u^2/s^2 (the pull is c / r beyond the core) and its - // softened core radius in u, which must stay inside the RocheLimit curve. + // A body's well strength by its mass (GravityField): c in u^2/s^2 (the pull is c / r beyond the core, which is the Roche limit). public ExponentialCurve WellStrength = new ExponentialCurve(); - public ExponentialCurve CoreRadius = new ExponentialCurve(); // The one global exaggeration of gravity height: height = potential / K, in u/s^2 per unit of height. public float HeightExaggeration = 1f; diff --git a/Assets/Scripts/ServerShared/Zone.cs b/Assets/Scripts/ServerShared/Zone.cs index ccec8edfd..db4bf6b3d 100644 --- a/Assets/Scripts/ServerShared/Zone.cs +++ b/Assets/Scripts/ServerShared/Zone.cs @@ -614,7 +614,7 @@ public class Zone // The potential of a body's well at the zone's edge, subtracted so every well is zero there: the one owner of the // reference. GetHeight sums with it and the renderer's lowering (GravityLowering) hands it to the shader unchanged. - public float WellReference(Planet body) => GravityField.Potential(body.WellStrength, body.CoreRadius, Pack.Radius); + public float WellReference(Planet body) => GravityField.Potential(body.WellStrength, body.RocheLimit, Pack.Radius); public float GetHeight(float2 position) { @@ -622,7 +622,7 @@ public class Zone foreach (var body in PlanetInstances.Values) { var offset = position - body.Orbit.Position; - result += GravityField.Potential(body.WellStrength, body.CoreRadius, length(offset)) - WellReference(body); + result += GravityField.Potential(body.WellStrength, body.RocheLimit, length(offset)) - WellReference(body); } return result / Settings.HeightExaggeration; @@ -652,7 +652,7 @@ public class Zone { var force = float2.zero; foreach (var body in PlanetInstances.Values) - force += GravityField.Acceleration(body.WellStrength, body.CoreRadius, position - body.Orbit.Position); + force += GravityField.Acceleration(body.WellStrength, body.RocheLimit, position - body.Orbit.Position); return force; } @@ -690,10 +690,9 @@ public class Planet public BodyData BodyData; public float BodyRadius; - // The well (GravityField): strength c and softened core radius R by mass, and the Roche limit, the closest a child - // may orbit. All three are authored PlanetSettings curves of mass; the core must sit inside the Roche limit. + // The well (GravityField): strength c by mass, and the Roche limit, which is both the closest a child may orbit and + // the well's softened core radius R (one curve of mass, never per body). Both are authored PlanetSettings curves. public float WellStrength; - public float CoreRadius; public float RocheLimit; public Planet(PlanetSettings settings, BodyData data, Orbit orbit) @@ -708,12 +707,11 @@ public class Planet { BodyRadius = Settings.BodyRadius.Evaluate(BodyData.Mass) * BodyData.BodyRadiusMultiplier; WellStrength = Settings.WellStrength.Evaluate(BodyData.Mass); - CoreRadius = Settings.CoreRadius.Evaluate(BodyData.Mass); RocheLimit = Settings.RocheLimit.Evaluate(BodyData.Mass); if (!(WellStrength >= 0f) || float.IsInfinity(WellStrength)) throw new InvalidOperationException("A body's well strength must be finite and not negative (PlanetSettings.WellStrength)."); - if (WellStrength > 0 && !(0 < CoreRadius && CoreRadius < RocheLimit)) - throw new InvalidOperationException("A body's core radius must be positive and inside its Roche limit (PlanetSettings.CoreRadius, RocheLimit)."); + if (WellStrength > 0 && !(RocheLimit > 0f && !float.IsInfinity(RocheLimit))) + throw new InvalidOperationException("A body's Roche limit, which is its core radius, must be positive and finite (PlanetSettings.RocheLimit)."); } } diff --git a/Assets/Scripts/Zone Display/GravityLowering.cs b/Assets/Scripts/Zone Display/GravityLowering.cs index cf596a32a..b8c2a062a 100644 --- a/Assets/Scripts/Zone Display/GravityLowering.cs +++ b/Assets/Scripts/Zone Display/GravityLowering.cs @@ -52,7 +52,7 @@ public static class GravityLowering { Position = new Vector2(body.Orbit.Position.x, body.Orbit.Position.y), Strength = body.WellStrength, - CoreRadius = body.CoreRadius, + CoreRadius = body.RocheLimit, Reference = zone.WellReference(body) }; wells.SetData(_records); diff --git a/tests/Aetheria.Shared.Tests/GravitySubtractTests.cs b/tests/Aetheria.Shared.Tests/GravitySubtractTests.cs index 078de12f2..d901b5a39 100644 --- a/tests/Aetheria.Shared.Tests/GravitySubtractTests.cs +++ b/tests/Aetheria.Shared.Tests/GravitySubtractTests.cs @@ -43,7 +43,6 @@ public sealed class GravitySubtractTests : IDisposable private static PlanetSettings Planets() => new PlanetSettings { WellStrength = new ExponentialCurve { Exponent = .2f, Multiplier = 45.08f }, - CoreRadius = new ExponentialCurve { Exponent = .25f, Multiplier = 3f }, RocheLimit = new ExponentialCurve { Exponent = .25f, Multiplier = 7.32f }, BodyRadius = new ExponentialCurve { Exponent = .25f, Multiplier = 3f }, LightRadius = new ExponentialCurve { Exponent = .25f, Multiplier = 300f }, @@ -95,7 +94,7 @@ public sealed class GravitySubtractTests : IDisposable { var plain = WithBody(new PlanetData()); var giants = new[] { WithBody(new GasGiantData()), WithBody(new SunData()) }; - var core = plain.PlanetInstances.Values.Single().CoreRadius; + var core = plain.PlanetInstances.Values.Single().RocheLimit; Assert.True(core > 1f, "the fixture body has a core to sweep around"); var radii = new System.Collections.Generic.List { 0.5f, core }; for (var r = core / 4f; r <= 4f * core; r += core / 16f) radii.Add(r); diff --git a/tests/Aetheria.Shared.Tests/PotentialOwnerTests.cs b/tests/Aetheria.Shared.Tests/PotentialOwnerTests.cs index 2621dd838..bcb5310b5 100644 --- a/tests/Aetheria.Shared.Tests/PotentialOwnerTests.cs +++ b/tests/Aetheria.Shared.Tests/PotentialOwnerTests.cs @@ -40,11 +40,10 @@ public sealed class PotentialOwnerTests : IDisposable Directory.Delete(_root, true); } - // The authored curves of the shipped Settings.asset: strength c = 45.08 m^.2, core R = 3 m^.25, Roche 7.32 m^.25. + // The authored curves of the shipped Settings.asset: strength c = 45.08 m^.2, Roche limit and core R = 7.32 m^.25. private static PlanetSettings Curves(float exaggeration = 1f) => new PlanetSettings { WellStrength = new ExponentialCurve { Exponent = .2f, Multiplier = 45.08f }, - CoreRadius = new ExponentialCurve { Exponent = .25f, Multiplier = 3f }, RocheLimit = new ExponentialCurve { Exponent = .25f, Multiplier = 7.32f }, BodyRadius = new ExponentialCurve { Exponent = .25f, Multiplier = 2f }, LightRadius = new ExponentialCurve(), OrbitPeriod = new ExponentialCurve(), @@ -102,20 +101,20 @@ public sealed class PotentialOwnerTests : IDisposable foreach (var mass in new[] { 29.2f, 273.9f, 14152.4f }) { var zone = ZoneOf(planets, (mass, float2.zero)); - var core = planets.CoreRadius.Evaluate(mass); + var core = planets.RocheLimit.Evaluate(mass); foreach (var r in new[] { 3f * core, 10f * core, PackRadius / 2f }) Near(planets.WellStrength.Evaluate(mass), length(zone.GetForce(new float2(r, 0))) * r, 1e-3f); } } [Fact] - public void TheCoreRadiusFollowsItsOwnCurve() + public void TheCoreRadiusIsTheRocheCurve() { var planets = Curves(); foreach (var mass in new[] { 29.2f, 14152.4f }) { var zone = ZoneOf(planets, (mass, float2.zero)); - var core = planets.CoreRadius.Evaluate(mass); + var core = planets.RocheLimit.Evaluate(mass); float Pull(float r) => length(zone.GetForce(new float2(0, r))); var slope = Pull(.25f * core) / (.25f * core); Near(slope, Pull(.5f * core) / (.5f * core), 1e-3f); @@ -125,70 +124,61 @@ public sealed class PotentialOwnerTests : IDisposable } } + // core-at-roche-and-exaggeration-up: the one curve is both the Roche limit and the core. A body with a well and no + // Roche limit has no core and is an authoring error; any positive, finite limit builds. [Fact] - public void TheCoreSitsInsideTheRocheLimit() + public void TheRocheLimitIsTheCore() { var planets = Curves(); foreach (var mass in new[] { 29.2f, 14152.4f }) Near(planets.RocheLimit.Evaluate(mass), ZoneOf(planets, (mass, float2.zero)).PlanetInstances.Values.Single().RocheLimit, 1e-6f); - PlanetSettings Constants(float core, float roche) => new PlanetSettings + PlanetSettings Constants(float roche) => new PlanetSettings { WellStrength = new ExponentialCurve { Constant = 100f }, - CoreRadius = new ExponentialCurve { Constant = core }, RocheLimit = new ExponentialCurve { Constant = roche }, BodyRadius = new ExponentialCurve { Constant = 10f }, LightRadius = new ExponentialCurve(), OrbitPeriod = new ExponentialCurve() }; - Assert.Throws(() => ZoneOf(Constants(60f, 50f), (100f, float2.zero))); - Assert.Throws(() => ZoneOf(Constants(50f, 50f), (100f, float2.zero))); - Assert.Throws(() => ZoneOf(Constants(0f, 50f), (100f, float2.zero))); - ZoneOf(Constants(20f, 50f), (100f, float2.zero)); // inside the limit, and past the body's radius + Assert.Throws(() => ZoneOf(Constants(0f), (100f, float2.zero))); + Assert.Throws(() => ZoneOf(Constants(-5f), (100f, float2.zero))); + Assert.Throws(() => ZoneOf(Constants(float.PositiveInfinity), (100f, float2.zero))); + ZoneOf(Constants(50f), (100f, float2.zero)); } - // core-inside-roche-curve at every mass: the guard compares the two authored curves for each body, light or heavy. - // Each pair of curves crosses somewhere in the generated mass range (1e-3 to 1e8), so the sweep holds both outcomes. - [Theory] - [InlineData(30f, .25f, 7.32f, .5f)] // the core curve starts above the Roche curve and is overtaken: light bodies throw - [InlineData(3f, .5f, 7.32f, .25f)] // the core curve overtakes the Roche curve: heavy bodies throw - public void TheGuardJudgesEveryMassByItsOwnCurves(float coreMultiplier, float coreExponent, float rocheMultiplier, float rocheExponent) + // core-at-roche-and-exaggeration-up: growing the core to the Roche limit (3 m^.25 to 7.32 m^.25, 2.44x) and dividing the + // global K by that factor leaves the steepest drawn slope (|grad phi| / K, at the core) where it was, and draws every + // slope outside the old core 2.44x steeper. The "before" side is the previous authoring, stated here from the ruling: + // core 3 m^.25 and K 10. The "after" side is the shipped Settings.asset read through the production zone. + [Fact] + public void ThePeakDrawnSlopeStaysAndTheFunnelDrawsSteeper() { - var planets = new PlanetSettings + const float oldCoreMultiplier = 3f, oldExaggeration = 10f; + var planets = AuthoredSettings.Load(RunStartTests.FindRepoRoot()).Read("PlanetSettings"); + foreach (var mass in new[] { 29.2f, 273.9f, 14152.4f }) { - WellStrength = new ExponentialCurve { Constant = 100f }, - CoreRadius = new ExponentialCurve { Multiplier = coreMultiplier, Exponent = coreExponent }, - RocheLimit = new ExponentialCurve { Multiplier = rocheMultiplier, Exponent = rocheExponent }, - BodyRadius = new ExponentialCurve { Constant = 1f }, - LightRadius = new ExponentialCurve(), OrbitPeriod = new ExponentialCurve() - }; - var threw = 0; - var built = 0; - for (var exponent10 = -3f; exponent10 <= 8f; exponent10 += .25f) - { - var mass = pow(10f, exponent10); - var core = planets.CoreRadius.Evaluate(mass); - var roche = planets.RocheLimit.Evaluate(mass); - if (0 < core && core < roche) - { - ZoneOf(planets, (mass, float2.zero)); - built++; - } - else - { - Assert.Throws(() => ZoneOf(planets, (mass, float2.zero))); - threw++; - } + var zone = ZoneOf(planets, (mass, float2.zero)); + var c = planets.WellStrength.Evaluate(mass); + var oldCore = oldCoreMultiplier * pow(mass, .25f); + float Drawn(float r) => length(zone.GetForce(new float2(r, 0))) / zone.Settings.HeightExaggeration; + + var peakBefore = c / oldCore / oldExaggeration; + Assert.InRange(Drawn(planets.RocheLimit.Evaluate(mass)), peakBefore * .98f, peakBefore * 1.02f); + + var rocheOverOldCore = planets.RocheLimit.Evaluate(mass) / oldCore; + var farBefore = c / (3f * oldCore) / oldExaggeration; + Near(rocheOverOldCore, Drawn(3f * oldCore) / farBefore, 1e-2f); + Assert.InRange(Drawn(3f * oldCore) / farBefore, 2.44f * .99f, 2.44f * 1.01f); } - Assert.True(threw > 0 && built > 0, "the sweep holds masses on both sides of the crossing"); } - // The shipped curves keep the core inside the Roche limit over the whole generated mass range. The curves are the ones + // The shipped curves build a well at every mass of the generated range. The curves are the ones // Settings.asset carries, read the way RunStartTests reads them, so a retune of the asset is judged here. [Fact] public void TheAuthoredCurvesBuildAtEveryMass() { var planets = AuthoredSettings.Load(RunStartTests.FindRepoRoot()).Read("PlanetSettings"); - Assert.True(planets.WellStrength.Evaluate(100f) > 0f && planets.CoreRadius.Evaluate(100f) > 0f, "the authored asset carries a well"); + Assert.True(planets.WellStrength.Evaluate(100f) > 0f && planets.RocheLimit.Evaluate(100f) > 0f, "the authored asset carries a well"); for (var exponent10 = -3f; exponent10 <= 8f; exponent10 += .25f) ZoneOf(planets, (pow(10f, exponent10), float2.zero)); } @@ -207,12 +197,11 @@ public sealed class PotentialOwnerTests : IDisposable var planets = Curves(); planets.WellStrength = new ExponentialCurve { Constant = strength }; Assert.Throws(() => ZoneOf(planets, (100f, float2.zero))); - planets.CoreRadius = new ExponentialCurve(); planets.RocheLimit = new ExponentialCurve(); Assert.Throws(() => ZoneOf(planets, (100f, float2.zero))); } - // Zero is the boundary: a well of no strength builds beside the authored core and Roche curves (it digs nothing), where + // Zero is the boundary: a well of no strength builds beside the authored Roche curve (it digs nothing), where // the smallest negative strength does not. [Theory] [InlineData(0f)] @@ -249,9 +238,8 @@ public sealed class PotentialOwnerTests : IDisposable var a = plain.PlanetInstances.Values.Single(); var b = scaled.PlanetInstances.Values.Single(); Assert.Equal(a.WellStrength, b.WellStrength); - Assert.Equal(a.CoreRadius, b.CoreRadius); Assert.Equal(a.RocheLimit, b.RocheLimit); - foreach (var p in new[] { float2(.4f * a.CoreRadius, 0), float2(0, 3f * a.CoreRadius), float2(400f, 300f) }) + foreach (var p in new[] { float2(.4f * a.RocheLimit, 0), float2(0, 3f * a.RocheLimit), float2(400f, 300f) }) { Assert.Equal(plain.GetForce(p), scaled.GetForce(p)); Assert.Equal(plain.GetHeight(p), scaled.GetHeight(p)); @@ -265,7 +253,7 @@ public sealed class PotentialOwnerTests : IDisposable var planets = Curves(); var zone = ZoneOf(planets, (273.9f, float2.zero)); var c = planets.WellStrength.Evaluate(273.9f); - var core = planets.CoreRadius.Evaluate(273.9f); + var core = planets.RocheLimit.Evaluate(273.9f); foreach (var r in new[] { core, 2f * core, PackRadius, 10f * PackRadius, 100f * PackRadius, 1000f * PackRadius }) foreach (var angle in new[] { 0f, 1.1f, 3.5f }) { @@ -307,15 +295,15 @@ public sealed class PotentialOwnerTests : IDisposable var planets = Curves(k); var lone = ZoneOf(planets, (273.9f, float2.zero)); var c = planets.WellStrength.Evaluate(273.9f); - var core = planets.CoreRadius.Evaluate(273.9f); + var core = planets.RocheLimit.Evaluate(273.9f); Assert.Equal(0f, lone.GetHeight(new float2(PackRadius, 0)), 4); Near(-c * (log(PackRadius / core) + .5f) / k, lone.GetHeight(float2.zero), 1e-4f); var two = ZoneOf(planets, (29.2f, new float2(-300f, 0f)), (14152.4f, new float2(300f, 0f))); var c0 = planets.WellStrength.Evaluate(29.2f); - var core0 = planets.CoreRadius.Evaluate(29.2f); + var core0 = planets.RocheLimit.Evaluate(29.2f); var c1 = planets.WellStrength.Evaluate(14152.4f); - var core1 = planets.CoreRadius.Evaluate(14152.4f); + var core1 = planets.RocheLimit.Evaluate(14152.4f); const float step = .5f; // Inside the two cores as well, out to their outer bands (0.5 R to R), where the potential is the quadratic bowl. var inCore = new[] @@ -352,7 +340,7 @@ public sealed class PotentialOwnerTests : IDisposable { var zone = ZoneOf(planets, (mass, float2.zero)); var c = planets.WellStrength.Evaluate(mass); - var core = planets.CoreRadius.Evaluate(mass); + var core = planets.RocheLimit.Evaluate(mass); foreach (var fraction in new[] { .5f, .75f, .9f, .95f, .98f, .99f, .996f }) foreach (var angle in new[] { 0f, 2.3f }) { @@ -371,7 +359,7 @@ public sealed class PotentialOwnerTests : IDisposable foreach (var mass in new[] { 29.2f, 14152.4f }) { var zone = ZoneOf(planets, (mass, float2.zero)); - var core = planets.CoreRadius.Evaluate(mass); + var core = planets.RocheLimit.Evaluate(mass); var inside = new float2(core * (1f - 1e-3f), 0); var outside = new float2(core * (1f + 1e-3f), 0); Assert.InRange(abs(zone.GetHeight(inside) - zone.GetHeight(outside)), 0f, abs(zone.GetHeight(outside)) * 1e-3f); diff --git a/tests/Aetheria.Shared.Tests/WellFixture.cs b/tests/Aetheria.Shared.Tests/WellFixture.cs index 0b895e4c0..54237862d 100644 --- a/tests/Aetheria.Shared.Tests/WellFixture.cs +++ b/tests/Aetheria.Shared.Tests/WellFixture.cs @@ -3,8 +3,8 @@ using GameCult.Caching; // The one fixture that gives a test zone a slope: a body on a parentless orbit (the origin unless `at` says otherwise; call again for more bodies), with the // curves a body needs. Gravity is the sum of body wells (GravityField), so a test that wants ground to slide on -// digs it here and nowhere else. `strength` is the well's c (u^2/s^2) and `coreRadius` its softened core in u; the -// Roche limit curve sits at 2.5 cores so the body is a valid well. +// digs it here and nowhere else. `strength` is the well's c (u^2/s^2) and `coreRadius` its softened core in u, which is +// the Roche limit curve (the one curve of a body's core). internal static class WellFixture { public static void Dig(CultCache cache, ZonePack pack, PlanetSettings settings, float strength, float coreRadius, float2 at = default) @@ -12,8 +12,7 @@ internal static class WellFixture settings.BodyRadius = new ExponentialCurve(); settings.OrbitPeriod = new ExponentialCurve(); settings.WellStrength = new ExponentialCurve { Constant = strength }; - settings.CoreRadius = new ExponentialCurve { Constant = coreRadius }; - settings.RocheLimit = new ExponentialCurve { Constant = 2.5f * coreRadius }; + settings.RocheLimit = new ExponentialCurve { Constant = coreRadius }; var orbit = cache.Upsert(new OrbitData { FixedPosition = at }).Key; var body = cache.Upsert(new PlanetData { Name = $"Well {at.x},{at.y}", Orbit = new CultRecordRef(orbit) }).Key; pack.Orbits.Add(new CultRecordRef(orbit)); diff --git a/tests/Aetheria.Shared.Tests/ZonePlacedAtBuildTests.cs b/tests/Aetheria.Shared.Tests/ZonePlacedAtBuildTests.cs index bdf8822d3..e9673c3f5 100644 --- a/tests/Aetheria.Shared.Tests/ZonePlacedAtBuildTests.cs +++ b/tests/Aetheria.Shared.Tests/ZonePlacedAtBuildTests.cs @@ -38,15 +38,14 @@ public sealed class ZonePlacedAtBuildTests : IDisposable private static ExponentialCurve Flat(float v) => new ExponentialCurve { Constant = v }; - // One planet with a well (c 100, core 20 u, Roche limit 30 u), a fixed root orbit at RootAt and the + // One planet with a well (c 100, Roche limit and core 20 u), a fixed root orbit at RootAt and the // planet orbiting it at Distance from `phase`. Every orbit period is Period seconds. private static PlanetSettings Settings() => new PlanetSettings { OrbitPeriod = Flat(Period), BodyRadius = Flat(20f), WellStrength = Flat(100f), - CoreRadius = Flat(20f), - RocheLimit = Flat(30f), + RocheLimit = Flat(20f), LightRadius = Flat(0f) };