move planet around ellipse

This commit is contained in:
Cat Flynn 2022-09-05 00:46:18 +01:00
parent dcc22acb5b
commit 46295a8e96
10 changed files with 215 additions and 127 deletions

View File

@ -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

View File

@ -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="."]

View File

@ -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

11
scenes/orbits/Planet.tscn Normal file
View File

@ -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

View File

@ -1,7 +1,6 @@
using Godot;
using System;
using Vim.Math3d;
public interface ILocation
{
Vector3 Position { get; }
DVector3 Position { get; set; }
}

View File

@ -0,0 +1,3 @@
public interface IPointMass : IMassive, ILocation
{
}

View File

@ -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
});
}
}
}

View File

@ -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<IPointMass>(_a);
var b = GetNode<IPointMass>(_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<Spatial>(path);
//var massive = node.GetChild<IMassive>(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);
}
}

View File

@ -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)
// {
//
// }
}
}

View File

@ -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;
}
}