forked from omega13a/stargen
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOrbitalSimulator.h
More file actions
179 lines (160 loc) · 5.39 KB
/
Copy pathOrbitalSimulator.h
File metadata and controls
179 lines (160 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#ifndef ORBITAL_SIMULATOR_H
#define ORBITAL_SIMULATOR_H
#include <unordered_map>
#include <cmath>
#include "structs.h"
#include "Vector3.h"
/**
* @brief Runtime state for a celestial body
*
* IMPORTANT: This is SEPARATE from the planet struct.
* - planet struct = static orbital parameters (generated once)
* - OrbitalState = dynamic runtime position (calculated each frame)
*/
struct OrbitalState {
Vec3 position; // Current 3D position (AU)
Vec3 velocity; // Current 3D velocity (AU/year)
double mean_anomaly; // Current mean anomaly (radians)
double last_update_time; // Last simulation time (years)
OrbitalState()
: position(0, 0, 0)
, velocity(0, 0, 0)
, mean_anomaly(0)
, last_update_time(0) {}
};
/**
* @brief Real-time orbital mechanics simulator
*
* ## NON-INVASIVE DESIGN
*
* This class does NOT modify planet generation:
* - Reads orbital parameters from planet structs (const access)
* - Stores runtime positions in separate OrbitalState structures
* - Can be disabled/removed without affecting generation
*
* ## Usage
*
* After generating a system:
* planet* system = generate_stellar_system(...); // ← Existing code
*
* OrbitalSimulator sim; // ← New code
* sim.initializeSystem(system); // ← Read parameters
*
* while (running) {
* sim.advance(delta_time); // ← Calculate positions
* Vec3 pos = sim.getPosition(planet); // ← Get current position
* renderer.drawPlanet(planet, pos); // ← Render
* }
*
* ## Physics
*
* Uses Kepler's laws to calculate positions from orbital elements:
* - Semi-major axis (a) - from planet->getA()
* - Eccentricity (e) - from planet->getE()
* - Inclination (i) - from planet->getInclination()
* - Longitude of ascending node (Ω) - from planet->getAscendingNode()
* - Argument of periapsis (ω) - from planet->getArgPerihelion()
* - Mean anomaly at epoch (M0) - calculated from planet position
*/
class OrbitalSimulator {
public:
/**
* @brief Initialize simulator with a planetary system
*
* Reads orbital parameters from planet structs and creates runtime state.
* Does NOT modify the planet structs.
*
* @param system_root Innermost planet in the system
*/
void initializeSystem(planet* system_root);
/**
* @brief Advance simulation time
*
* @param delta_time Time step in years (e.g., 0.01 = ~3.65 days)
*/
void advance(double delta_time);
/**
* @brief Update all planetary positions for current time
*
* Recalculates positions using Kepler's equation.
* Call this after advance() or when jumping to a new time.
*/
void updatePositions();
/**
* @brief Get current 3D position of a planet
*
* @param p Planet to query (non-const as planet getters aren't const)
* @return Position in AU (sun at origin)
*/
Vec3 getPosition(planet* p) const;
/**
* @brief Get current 3D velocity of a planet
*
* @param p Planet to query (non-const as planet getters aren't const)
* @return Velocity in AU/year
*/
Vec3 getVelocity(planet* p) const;
/**
* @brief Get current simulation time
*
* @return Time in years since epoch
*/
double getCurrentTime() const { return current_time_; }
/**
* @brief Set simulation time directly (jump to specific time)
*
* @param time Time in years
*/
void setTime(double time);
/**
* @brief Set time scale multiplier
*
* @param scale Speed multiplier (1.0 = real-time, 365.25 = 1 year per second)
*/
void setTimeScale(double scale) { time_scale_ = scale; }
/**
* @brief Get time scale multiplier
*/
double getTimeScale() const { return time_scale_; }
/**
* @brief Check if simulator has state for a planet
*/
bool hasState(planet* p) const;
private:
// Runtime state for each planet (separate from planet structs)
std::unordered_map<planet*, OrbitalState> states_;
// Simulation time
double current_time_ = 0.0; // Years since epoch
double time_scale_ = 1.0; // Speed multiplier
/**
* @brief Solve Kepler's equation iteratively
*
* Finds eccentric anomaly (E) from mean anomaly (M) and eccentricity (e)
* using Newton-Raphson iteration.
*
* M = E - e*sin(E) (Kepler's equation)
*
* @param M Mean anomaly (radians)
* @param e Eccentricity
* @param tolerance Convergence threshold (default: 1e-8)
* @param max_iterations Maximum iterations (default: 50)
* @return Eccentric anomaly (radians)
*/
double solveKeplersEquation(double M, double e,
double tolerance = 1e-8,
int max_iterations = 50) const;
/**
* @brief Calculate mean anomaly at given time
*
* M = M0 + n*t
* where n = mean motion = sqrt(μ/a³) = 2π·sqrt(M_star)/a^(3/2)
*
* @param a Semi-major axis (AU)
* @param t Time (years)
* @param m_star Stellar mass (solar masses); scales μ. <=0 falls back to 1.
* @param M0 Initial mean anomaly (radians)
* @return Current mean anomaly (radians)
*/
double calculateMeanAnomaly(double a, double t, double m_star, double M0 = 0.0) const;
};
#endif // ORBITAL_SIMULATOR_H