shmodot/scripts/orbits/OrbitSystem.cs

125 lines
2.7 KiB
C#

using Godot;
using System;
using System.Collections.Generic;
using Vim.Math3d;
[Tool]
public class OrbitSystem : Node, IPointMass
{
[Export]
private NodePath[] _pointMassPaths;
private double _semiMajorAxis;
[Export]
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();
}
}
private IPointMass[] _pointMasses;
public IPointMass[] Orbiters
{
get
{
if (_pointMasses == null)
{
_pointMasses = new IPointMass[_pointMassPaths.Length];
// give each body an orbit around ourselves
for (int i = 0; i < _pointMassPaths.Length; i++)
{
_pointMasses[i] = GetNode<IPointMass>(_pointMassPaths[i]);
}
}
return _pointMasses;
}
}
public double Mass
{
get
{
double mass = 0;
foreach (var pointMass in _pointMasses)
{
mass += pointMass.Mass;
}
return mass;
}
}
public DVector3 Position { get; set; }
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;
[Export]
private float _speed = 3f;
public override void _Process(float delta)
{
_time += delta * _speed;
InvalidateGeometry();
}
private void InvalidateGeometry()
{
Orbit.Ellipse = new Ellipse(SemiMajorAxis, Eccentricity);
Orbit.Draw(OrbitGeometry);
Orbiter.Position = Orbit.GetPosition(_time);
}
}