From f31f484dc5e142549ae3a4b84884c366ed42bf98 Mon Sep 17 00:00:00 2001 From: Cat Flynn Date: Mon, 5 Sep 2022 00:46:18 +0100 Subject: [PATCH] move planet around ellipse --- scenes/Main.tscn | 5 +- scenes/OrbitSystem.tscn | 15 --- scenes/orbits/OrbitSystem.tscn | 21 ++++ scenes/orbits/Planet.tscn | 11 ++ scripts/orbits/ILocation.cs | 5 +- scripts/orbits/IPointMass.cs | 3 + scripts/orbits/Orbit.cs | 42 +++++++- scripts/orbits/OrbitSystem.cs | 185 ++++++++++++++++++++------------- scripts/orbits/Planet.cs | 30 ++++-- scripts/orbits/PointMass.cs | 25 ----- 10 files changed, 215 insertions(+), 127 deletions(-) delete mode 100644 scenes/OrbitSystem.tscn create mode 100644 scenes/orbits/OrbitSystem.tscn create mode 100644 scenes/orbits/Planet.tscn create mode 100644 scripts/orbits/IPointMass.cs delete mode 100644 scripts/orbits/PointMass.cs diff --git a/scenes/Main.tscn b/scenes/Main.tscn index 1051db3..fa3a7eb 100644 --- a/scenes/Main.tscn +++ b/scenes/Main.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=2] [ext_resource path="res://scenes/OrbitCamera.tscn" type="PackedScene" id=3] -[ext_resource path="res://scenes/OrbitSystem.tscn" type="PackedScene" id=4] +[ext_resource path="res://scenes/orbits/OrbitSystem.tscn" type="PackedScene" id=4] [node name="Main" type="Node2D"] @@ -11,3 +11,6 @@ transform = Transform( 0.515898, 0.606099, -0.605386, -0.393123, 0.795389, 0.461 [node name="OrbitCamera" parent="." instance=ExtResource( 3 )] [node name="Orbit System" parent="." instance=ExtResource( 4 )] +transform = Transform( 0.856869, 0.3292, -0.396741, 0.0949996, 0.655565, 0.749139, 0.506706, -0.679604, 0.53046, -0.599122, 0, 0 ) +SemiMajorAxis = 6.166 +Eccentricity = 0.239 diff --git a/scenes/OrbitSystem.tscn b/scenes/OrbitSystem.tscn deleted file mode 100644 index b0cb744..0000000 --- a/scenes/OrbitSystem.tscn +++ /dev/null @@ -1,15 +0,0 @@ -[gd_scene load_steps=2 format=2] - -[ext_resource path="res://scripts/orbits/OrbitSystem.cs" type="Script" id=1] - -[node name="Orbit System" type="Spatial"] -script = ExtResource( 1 ) -_a = NodePath("A") -_b = NodePath("B") -_barycenter = NodePath("Barycenter") - -[node name="A" type="Spatial" parent="."] - -[node name="B" type="Spatial" parent="."] - -[node name="Barycenter" type="Spatial" parent="."] diff --git a/scenes/orbits/OrbitSystem.tscn b/scenes/orbits/OrbitSystem.tscn new file mode 100644 index 0000000..0806b26 --- /dev/null +++ b/scenes/orbits/OrbitSystem.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://scripts/orbits/OrbitSystem.cs" type="Script" id=1] +[ext_resource path="res://scenes/orbits/Planet.tscn" type="PackedScene" id=2] + +[node name="Orbit System" type="Spatial"] +script = ExtResource( 1 ) +SemiMajorAxis = 5.994 +Eccentricity = 0.518 +_a = NodePath("Planet A") +_b = NodePath("Planet B") +_barycenter = NodePath("Barycenter") + +[node name="Barycenter" type="Spatial" parent="."] + +[node name="Planet A" parent="." instance=ExtResource( 2 )] +transform = Transform( 0.999977, 0.00603502, 0.00319089, -0.00604282, 0.999979, 0.0024369, -0.00317609, -0.00245615, 0.999992, 0, 0, 0 ) + +[node name="Planet B" parent="." instance=ExtResource( 2 )] +transform = Transform( 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, -6.57314, 0, 4.18169 ) +Mass = 0.125 diff --git a/scenes/orbits/Planet.tscn b/scenes/orbits/Planet.tscn new file mode 100644 index 0000000..4ddb444 --- /dev/null +++ b/scenes/orbits/Planet.tscn @@ -0,0 +1,11 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://scripts/orbits/Planet.cs" type="Script" id=1] + +[node name="Planet" type="Spatial"] +script = ExtResource( 1 ) +Mass = 1.0 + +[node name="CSGSphere" type="CSGSphere" parent="."] +radial_segments = 20 +rings = 20 diff --git a/scripts/orbits/ILocation.cs b/scripts/orbits/ILocation.cs index 50c1af4..b13f214 100644 --- a/scripts/orbits/ILocation.cs +++ b/scripts/orbits/ILocation.cs @@ -1,7 +1,6 @@ -using Godot; -using System; +using Vim.Math3d; public interface ILocation { - Vector3 Position { get; } + DVector3 Position { get; set; } } diff --git a/scripts/orbits/IPointMass.cs b/scripts/orbits/IPointMass.cs new file mode 100644 index 0000000..c7c1e78 --- /dev/null +++ b/scripts/orbits/IPointMass.cs @@ -0,0 +1,3 @@ +public interface IPointMass : IMassive, ILocation +{ +} diff --git a/scripts/orbits/Orbit.cs b/scripts/orbits/Orbit.cs index 0aca13e..e47600b 100644 --- a/scripts/orbits/Orbit.cs +++ b/scripts/orbits/Orbit.cs @@ -1,12 +1,48 @@ using Godot; using System; +using Vim.Math3d; public class Orbit { - public Orbit(PointMass a, PointMass b) - { + // the position of the primary body relative to the ellipse - the + // orbit itself is presented as being centred on the primary, but + // all our math is ellipse stuff + private DVector2 PrimaryPosition => Ellipse.Focus0; + public Ellipse Ellipse { get; set; } + + public DVector3 GetPosition(float t) + { + var p = PrimaryPosition + Ellipse.GetPosition(t); + return new DVector3(p.X, 0, p.Y); } - // ellipse + public void Draw(ImmediateGeometry geo) + { + geo.Clear(); + geo.Begin(Mesh.PrimitiveType.LineLoop); + DrawEllipse(geo); + geo.End(); + } + + private void DrawEllipse(ImmediateGeometry geo) + { + geo.SetColor(new Color(1, 0, 0)); + + int steps = 100; + + for (int i = 0; i < steps; i++) + { + float t = i / (float)steps; + float a = t * Mathf.Tau; + + var v2 = Ellipse.Focus0 + Ellipse.GetPosition(a); + + geo.AddVertex(new Godot.Vector3 + { + x = (float)v2.X, + z = (float)v2.Y + }); + } + } } diff --git a/scripts/orbits/OrbitSystem.cs b/scripts/orbits/OrbitSystem.cs index 61a432a..aee2ac4 100644 --- a/scripts/orbits/OrbitSystem.cs +++ b/scripts/orbits/OrbitSystem.cs @@ -1,91 +1,73 @@ using Godot; using System; +using Vim.Math3d; +[Tool] public class OrbitSystem : Node, IMassive, ILocation { [Export] private NodePath _a; [Export] private NodePath _b; [Export] private NodePath _barycenter; - private readonly PointMass[] _pointMasses = new PointMass[2]; - - public Vector3 Position => Barycenter; - + private double _semiMajorAxis; [Export] - public Vector3 Barycenter + private double SemiMajorAxis + { + get => _semiMajorAxis; + set + { + _semiMajorAxis = value; + + if (!Engine.EditorHint) return; + + InvalidateGeometry(); + } + } + + + private double _eccentricity; + [Export(PropertyHint.Range, "0,1")] + private double Eccentricity + { + get => _eccentricity; + set + { + _eccentricity = value; + + if (!Engine.EditorHint) return; + + InvalidateGeometry(); + } + } + + #region Point Masses + private IPointMass Primary { get { - var p0 = _pointMasses[0].Position; - var p1 = _pointMasses[1].Position; - - return p0.LinearInterpolate(p1, .5f); - } - set => _ = value; - } - - public float Mass { get; } = 1; - - private Orbit _orbit; - - private ImmediateGeometry _orbitGeometry; - - public override void _Ready() - { - InitPointMasses(); - InitGeometry(); - } - - public override void _Process(float delta) - { - DrawOrbit(); - } - - private void InitOrbit() - { - - } - - private void DrawOrbit() - { - int steps = 100; - - _orbitGeometry.Clear(); - _orbitGeometry.Begin(Mesh.PrimitiveType.LineLoop); - _orbitGeometry.SetColor(new Color(1, 0, 0)); - - var ellipse = new Ellipse(1, .5); - - for (int i = 0; i < steps; i++) - { - float t = i / (float)steps; - float a = t * Mathf.Tau; - - var v2 = ellipse.Focus0 + ellipse.GetPosition(a); - - _orbitGeometry.AddVertex(new Vector3 + if (_pointMasses[0] == null) { - x = (float)v2.X, - z = (float)v2.Y - }); + InitPointMasses(); + } + return _pointMasses[0]; } - _orbitGeometry.End(); } - - private void InitGeometry() + private IPointMass Secondary { - _orbitGeometry = new ImmediateGeometry(); - var m = new SpatialMaterial(); - m.VertexColorUseAsAlbedo = true; - m.FlagsUnshaded = true; - _orbitGeometry.MaterialOverride = m; - AddChild(_orbitGeometry); + get + { + if (_pointMasses[1] == null) + { + InitPointMasses(); + } + return _pointMasses[1]; + } } - + private readonly IPointMass[] _pointMasses = new IPointMass[2]; private void InitPointMasses() { - var a = GetPointMass(_a); - var b = GetPointMass(_b); + var a = GetNode(_a); + var b = GetNode(_b); if (a.Mass > b.Mass) { @@ -98,12 +80,71 @@ public class OrbitSystem : Node, IMassive, ILocation _pointMasses[1] = a; } } + #endregion - private PointMass GetPointMass(NodePath path) + public float Mass => Primary.Mass + Secondary.Mass; + public DVector3 Position { - var spatial = GetNode(path); - //var massive = node.GetChild(0); + get => Barycenter; + set => Barycenter = value; + } - return new PointMass(spatial, 1f); + public DVector3 Barycenter + { + get + { + var p0 = Primary.Position; + var p1 = Secondary.Position; + return p0.Lerp(p1, .5f); + } + // TODO - make setting the berycenter do something sensible? + set => _ = value; + } + + private Orbit _orbit = null; + private Orbit Orbit + { + get + { + if (_orbit == null) + { + _orbit = new Orbit(); + } + return _orbit; + } + } + + private ImmediateGeometry _orbitGeometry = null; + public ImmediateGeometry OrbitGeometry + { + get + { + if (_orbitGeometry == null) + { + _orbitGeometry = new ImmediateGeometry(); + var m = new SpatialMaterial(); + m.VertexColorUseAsAlbedo = true; + m.FlagsUnshaded = true; + _orbitGeometry.MaterialOverride = m; + AddChild(_orbitGeometry); + } + return _orbitGeometry; + } + } + + private float _time = 0; + + public override void _Process(float delta) + { + _time += delta * 3f; + InvalidateGeometry(); + } + + private void InvalidateGeometry() + { + Orbit.Ellipse = new Ellipse(SemiMajorAxis, Eccentricity); + Orbit.Draw(OrbitGeometry); + + Secondary.Position = Orbit.GetPosition(_time); } } diff --git a/scripts/orbits/Planet.cs b/scripts/orbits/Planet.cs index 877455f..b12c0bc 100644 --- a/scripts/orbits/Planet.cs +++ b/scripts/orbits/Planet.cs @@ -1,18 +1,32 @@ using Godot; using System; +using Vim.Math3d; -public class Planet : Node, IMassive +[Tool] +public class Planet : Spatial, IPointMass { [Export] public float Mass { get; set; } - public override void _Ready() + private DVector3? _position; + public DVector3 Position { + get + { + if (_position.HasValue) return _position.Value; + var t = Translation; + return new DVector3(t.x, t.y, t.z); + } + set + { + _position = value; + Translation = new Godot.Vector3 + { + x = (float)value.X, + y = (float)value.Y, + z = (float)value.Z + }; + } } - - // public override void _Process(float delta) - // { - // - // } -} +} \ No newline at end of file diff --git a/scripts/orbits/PointMass.cs b/scripts/orbits/PointMass.cs deleted file mode 100644 index bbeaa14..0000000 --- a/scripts/orbits/PointMass.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Godot; - -public struct PointMass : IMassive, ILocation -{ - public float Mass => _massive == null ? _mass : _massive.Mass; - public Vector3 Position => _spatial.Translation; - - private IMassive _massive; - private Spatial _spatial; - private float _mass; - - public PointMass(Spatial spatial, IMassive massive) - { - _spatial = spatial; - _massive = massive; - _mass = 0; - } - - public PointMass(Spatial spatial, float mass) - { - _spatial = spatial; - _massive = null; - _mass = mass; - } -}