144 lines
3.2 KiB
C#
144 lines
3.2 KiB
C#
using Godot;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Vim.Math3d;
|
|
|
|
[Tool]
|
|
public class Barycenter : 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();
|
|
}
|
|
}
|
|
|
|
public double Mass
|
|
{
|
|
get
|
|
{
|
|
double mass = 0;
|
|
foreach (var orbiter in Orbiters)
|
|
{
|
|
mass += orbiter.PointMass.Mass;
|
|
}
|
|
return mass;
|
|
}
|
|
}
|
|
public DVector3 Position { get; set; }
|
|
|
|
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 struct Orbiter
|
|
{
|
|
public IPointMass PointMass { get; set; }
|
|
public IOrbit Orbit { get; set; }
|
|
}
|
|
private Orbiter[] _orbiters = null;
|
|
private Orbiter[] Orbiters
|
|
{
|
|
get
|
|
{
|
|
if (_orbiters == null)
|
|
{
|
|
var length = _pointMassPaths.Length;
|
|
_orbiters = new Orbiter[length];
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
var pointMass = GetNode<IPointMass>(_pointMassPaths[i]);
|
|
var orbit = new Orbit(this, pointMass);
|
|
|
|
var orbiter = new Orbiter
|
|
{
|
|
PointMass = pointMass,
|
|
Orbit = orbit
|
|
};
|
|
_orbiters[i] = orbiter;
|
|
}
|
|
}
|
|
return _orbiters;
|
|
}
|
|
}
|
|
|
|
private IOrbit[] _orbits;
|
|
private IOrbit[] Orbits
|
|
{
|
|
get
|
|
{
|
|
if (_orbits == null)
|
|
{
|
|
|
|
}
|
|
return _orbits;
|
|
}
|
|
}
|
|
|
|
private float _time = 0;
|
|
|
|
[Export]
|
|
private float _speed = 3f;
|
|
|
|
public override void _Process(float delta)
|
|
{
|
|
_time += delta * _speed;
|
|
InvalidateGeometry();
|
|
}
|
|
|
|
private void InvalidateGeometry()
|
|
{
|
|
for (int i = 0; i < Orbiters.Length; i++)
|
|
{
|
|
var orbiter = Orbiters[i];
|
|
var orbit = orbiter.Orbit;
|
|
orbit.Ellipse = new Ellipse(SemiMajorAxis, Eccentricity);
|
|
orbit.Draw(OrbitGeometry);
|
|
|
|
var t = _time + i * Math.PI;
|
|
orbiter.PointMass.Position = orbit.GetPosition(t);
|
|
}
|
|
}
|
|
}
|