feat: render nested orbits

This commit is contained in:
Cat Flynn 2024-08-24 13:18:08 +01:00
parent 77d7c2a4d0
commit da3a917896
5 changed files with 77 additions and 32 deletions

View File

@ -14,6 +14,7 @@ class ParticleMap
// providing these as two methods keeps things unambiguous - manipulating particles // providing these as two methods keeps things unambiguous - manipulating particles
// is just done for setup // is just done for setup
const Particle& getParticle(const std::string& id) const; const Particle& getParticle(const std::string& id) const;
const Particle& getParent(const std::string& id) const;
glm::dvec3 getParticlePosition(const std::string& id, double time) const; glm::dvec3 getParticlePosition(const std::string& id, double time) const;
const Orbit& getOrbit(const std::string& id) const; const Orbit& getOrbit(const std::string& id) const;

View File

@ -6,6 +6,12 @@ const Particle& ParticleMap::getParticle(const std::string& id) const
return _particles.at(id); return _particles.at(id);
} }
const Particle& ParticleMap::getParent(const std::string& childId) const
{
const std::string parentId = _relationships.at(childId);
return _particles.at(parentId);
}
const Orbit& ParticleMap::getOrbit(const std::string& id) const const Orbit& ParticleMap::getOrbit(const std::string& id) const
{ {
return _orbits.at(id); return _orbits.at(id);
@ -16,13 +22,31 @@ glm::dvec3 ParticleMap::getParticlePosition(const std::string& id, double time)
if (_orbits.find(id) == _orbits.end()) if (_orbits.find(id) == _orbits.end())
return {0,0,0}; return {0,0,0};
const std::string& parentId = _relationships.at(id); const Particle* particle = &(_particles.at(id));
const Particle& parent = _particles.at(parentId); glm::dvec3 pos(0,0,0);
const double gravitationalParameter = parent.getGravitationalParameter();
// TODO: actually nest stuff so position is determined from all parents do
const Orbit& orbit = _orbits.at(id); {
return orbit.getPosition(gravitationalParameter, time); const std::string& id = particle->getId();
const std::string& parentId = _relationships.at(id);
const Particle& parent = _particles.at(parentId);
const double gravitationalParameter = parent.getGravitationalParameter();
const Orbit& orbit = _orbits.at(id);
pos += orbit.getPosition(gravitationalParameter, time);
auto it = _relationships.find(parentId);
if (it != _relationships.end())
{
particle = &parent;
}
else
{
particle = nullptr;
}
} while (particle != nullptr);
return pos;
} }
void ParticleMap::setParticle(const Particle& particle) void ParticleMap::setParticle(const Particle& particle)

View File

@ -66,24 +66,35 @@ int main()
GLuint unlitProgram = compileShaderProgram("./frag_unlit.glsl"); GLuint unlitProgram = compileShaderProgram("./frag_unlit.glsl");
// set parameters of moon's orbit around earth // set parameters of moon's orbit around earth
Orbit orbit; Orbit moonOrbit;
double semiMajorAxis = 3.84748e8; double moonOrbitSemiMajorAxis = 3.84748e8;
orbit.setSemiMajorAxis(semiMajorAxis); // metres moonOrbit.setSemiMajorAxis(moonOrbitSemiMajorAxis); // metres
orbit.setEccentricity(0.055); moonOrbit.setEccentricity(0.055);
orbit.setInclination(glm::radians(5.15)); // radians moonOrbit.setInclination(glm::radians(5.15)); // radians
orbit.setArgumentOfPeriapsis(318.15); // in the case of the moon these last two values are moonOrbit.setArgumentOfPeriapsis(318.15); // in the case of the moon these last two values are
orbit.setLongitudeOfAscendingNode(60.0); // pretty much constantly changing so use whatever moonOrbit.setLongitudeOfAscendingNode(60.0); // pretty much constantly changing so use whatever
// set parameters of satellite orbit around moon
Orbit stationOrbit;
stationOrbit.setSemiMajorAxis(5e7);
stationOrbit.setEccentricity(0.6);
stationOrbit.setInclination(glm::radians(89.0));
stationOrbit.setArgumentOfPeriapsis(43.2);
stationOrbit.setLongitudeOfAscendingNode(239.7);
// TODO: add something in a nice eccentric orbit around the moon
// make the earth-moon system
ParticleMap map; ParticleMap map;
map.setParticle({"earth", 5.9e24}); map.setParticle({"earth", 5.9e24});
map.setParticle({"moon", 7.3e22}); map.setParticle({"moon", 7.3e22});
map.setRelationship("earth", "moon", orbit); map.setParticle({"station", 1e6});
float scale = semiMajorAxis * 1.1; map.setRelationship("earth", "moon", moonOrbit);
ParticleVisualizer earthVis(map, "earth", 0.2, litProgram, unlitProgram, scale); map.setRelationship("moon", "station", stationOrbit);
ParticleVisualizer moonVis(map, "moon", 0.1, litProgram, unlitProgram, scale);
OrbitVisualizer orbitVis(orbit, unlitProgram, scale); float scale = moonOrbitSemiMajorAxis * 1.1;
ParticleVisualizer earthVis(map, "earth", 0.1, litProgram, unlitProgram, scale);
ParticleVisualizer moonVis(map, "moon", 0.02, litProgram, unlitProgram, scale);
ParticleVisualizer stationVis(map, "station", 0.01, litProgram, unlitProgram, scale);
OrbitVisualizer moonOrbitVis(map, "moon", unlitProgram, scale);
OrbitVisualizer stationOrbitVis(map, "station", unlitProgram, scale);
// register input // register input
glfwSetKeyCallback(window, keyCallback); glfwSetKeyCallback(window, keyCallback);
@ -125,7 +136,7 @@ int main()
else else
{ {
double e = .25 + .2 * sin(getTime()); double e = .25 + .2 * sin(getTime());
orbit.setEccentricity(e); moonOrbit.setEccentricity(e);
} }
// rendering // rendering
@ -134,7 +145,9 @@ int main()
earthVis.render(time); earthVis.render(time);
moonVis.render(time); moonVis.render(time);
orbitVis.render(time); stationVis.render(time);
moonOrbitVis.render(time);
stationOrbitVis.render(time);
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }

View File

@ -1,8 +1,8 @@
#include "orbitvisualizer.hpp" #include "orbitvisualizer.hpp"
#include "gfx.hpp" #include "gfx.hpp"
OrbitVisualizer::OrbitVisualizer(const Orbit& orbit, const GLuint shaderProgram, float scale) OrbitVisualizer::OrbitVisualizer(const ParticleMap& map, const std::string& particleId, const GLuint shaderProgram, float scale)
: _orbit(orbit), _shaderProgram(shaderProgram), _scale(scale) : _map(map), _particleId(particleId), _shaderProgram(shaderProgram), _scale(scale)
{ {
glGenVertexArrays(1, &_vao); glGenVertexArrays(1, &_vao);
glGenBuffers(1, &_vbo); glGenBuffers(1, &_vbo);
@ -10,7 +10,11 @@ OrbitVisualizer::OrbitVisualizer(const Orbit& orbit, const GLuint shaderProgram,
void OrbitVisualizer::render(const float time) void OrbitVisualizer::render(const float time)
{ {
regenerateVertices(); // Orbit needs to be drawn relative to its parent
const Particle& parent = _map.getParent(_particleId);
const glm::vec3 parentPos = _map.getParticlePosition(parent.getId(), time);
regenerateVertices(parentPos);
glUseProgram(_shaderProgram); glUseProgram(_shaderProgram);
updateModelViewProjectionMatrix(_shaderProgram, time); updateModelViewProjectionMatrix(_shaderProgram, time);
@ -21,17 +25,19 @@ void OrbitVisualizer::render(const float time)
glDrawArrays(GL_LINE_LOOP, 0, _vertices.size() / 3); glDrawArrays(GL_LINE_LOOP, 0, _vertices.size() / 3);
} }
void OrbitVisualizer::regenerateVertices() void OrbitVisualizer::regenerateVertices(const glm::vec3& basePos)
{ {
_vertices.clear(); const Orbit& orbit = _map.getOrbit(_particleId);
_vertices.clear();
for (int i = 0; i < _vertexCount; i++) for (int i = 0; i < _vertexCount; i++)
{ {
// TODO: this method of getting ellipse vertices is a huge hack. it would be // TODO: this method of getting ellipse vertices is a huge hack. it would be
// better to actually create a first-class ellipse object and use that to generate // better to actually create a first-class ellipse object and use that to generate
// a nice continuous mesh, instead of using orbital positions. // a nice continuous mesh, instead of using orbital positions.
float t = (float)i / (float)_vertexCount * 2.0 * _pi; float t = (float)i / (float)_vertexCount * 2.0 * _pi;
glm::vec3 pos = _orbit.getPositionFromMeanAnomaly(t); glm::vec3 pos = orbit.getPositionFromMeanAnomaly(t);
pos += basePos;
// Vertices come out of the library with X and Y being in the 'flat' plane. Re-order them // Vertices come out of the library with X and Y being in the 'flat' plane. Re-order them
// here such that Z is up. // here such that Z is up.

View File

@ -2,12 +2,12 @@
#include <GL/glew.h> #include <GL/glew.h>
#include <vector> #include <vector>
#include <skein/orbit.h> #include <skein/particlemap.h>
class OrbitVisualizer class OrbitVisualizer
{ {
public: public:
OrbitVisualizer(const Orbit& orbit, const GLuint shaderProgram, float scale); OrbitVisualizer(const ParticleMap& map, const std::string& particleId, const GLuint shaderProgram, float scale);
~OrbitVisualizer(); ~OrbitVisualizer();
void render(const float time); void render(const float time);
@ -17,12 +17,13 @@ class OrbitVisualizer
const int _vertexCount = 100; const int _vertexCount = 100;
const GLuint _shaderProgram; const GLuint _shaderProgram;
const Orbit& _orbit; const ParticleMap& _map;
const std::string _particleId;
const float _scale; const float _scale;
GLuint _vbo; GLuint _vbo;
GLuint _vao; GLuint _vao;
std::vector<float> _vertices; std::vector<float> _vertices;
void regenerateVertices(); void regenerateVertices(const glm::vec3& basePos);
}; };