refactor: extract OrbiterVisualizer class

This commit is contained in:
Cat Flynn 2024-08-18 01:43:57 +01:00
parent 129d65c31e
commit bb9b8320ec
9 changed files with 139 additions and 111 deletions

View File

@ -32,6 +32,7 @@ add_executable(${PROJECT_NAME}
src/icosphere.cpp
src/gfx.cpp
src/orbitvisualizer.cpp
src/orbitervisualizer.cpp
src/orbiter.cpp
src/widget.cpp
)

View File

@ -9,18 +9,26 @@ typedef std::vector<float> Vector6;
class Orbit
{
public:
Orbit(float semiMajorAxis, float eccentricity, float inclination,
float argumentOfPeriapsis, float longitudeOfAscendingNode);
Orbit();
~Orbit() = default;
float getSemiMajorAxis() const;
float getEccentricity() const;
float getInclination() const;
float getArgumentOfPeriapsis() const;
float getLongitudeOfAscendingNode() const;
void setSemiMajorAxis(float semiMajorAxis);
void setEccentricity(float eccentricity);
void setInclination(float inclination);
void setArgumentOfPeriapsis(float argumentOfPeriapsis);
void setLongitudeOfAscendingNode(float longitudeOfAscendingNode);
// TODO: meanAnomaly in all these arguments actually means eccentricMeanAnomaly,
// will have to change that when adding non-ellipctical orbits - don't get confused!
const glm::vec3 getPosition(const float meanAnomaly) const;
glm::vec3 getTangent(const float meanAnomaly);
glm::mat4 getLookAlongMatrix(const float meanAnomaly);
glm::vec3 getPosition(const float meanAnomaly) const;
glm::vec3 getTangent(const float meanAnomaly) const;
glm::mat4 getLookAlongMatrix(const float meanAnomaly) const;
private:
Vector6 _keplerianElements;

View File

@ -5,28 +5,57 @@
#include <glm/gtc/matrix_transform.hpp>
Orbit::Orbit(float semiMajorAxis, float eccentricity, float inclination,
float argumentOfPeriapsis, float longitudeOfAscendingNode)
Orbit::Orbit()
{
_keplerianElements.resize(6);
}
float Orbit::getSemiMajorAxis() const
{
return _keplerianElements[astro::semiMajorAxisIndex];
}
void Orbit::setSemiMajorAxis(float semiMajorAxis)
{
_keplerianElements[astro::semiMajorAxisIndex] = semiMajorAxis;
_keplerianElements[astro::eccentricityIndex] = eccentricity;
_keplerianElements[astro::inclinationIndex] = inclination;
_keplerianElements[astro::argumentOfPeriapsisIndex] = argumentOfPeriapsis;
_keplerianElements[astro::longitudeOfAscendingNodeIndex] = semiMajorAxis;
}
float Orbit::getEccentricity() const
{
return _keplerianElements[astro::eccentricityIndex];
}
void Orbit::setEccentricity(float eccentricity)
{
_keplerianElements[astro::eccentricityIndex] = eccentricity;
}
glm::mat4 Orbit::getLookAlongMatrix(const float meanAnomaly)
float Orbit::getInclination() const
{
return _keplerianElements[astro::inclinationIndex];
}
void Orbit::setInclination(float inclination)
{
_keplerianElements[astro::inclinationIndex] = inclination;
}
float Orbit::getArgumentOfPeriapsis() const
{
return _keplerianElements[astro::argumentOfPeriapsisIndex];
}
void Orbit::setArgumentOfPeriapsis(float argumentOfPeriapsis)
{
_keplerianElements[astro::argumentOfPeriapsisIndex] = argumentOfPeriapsis;
}
float Orbit::getLongitudeOfAscendingNode() const
{
return _keplerianElements[astro::longitudeOfAscendingNodeIndex];
}
void Orbit::setLongitudeOfAscendingNode(float longitudeOfAscendingNode)
{
_keplerianElements[astro::longitudeOfAscendingNodeIndex] = longitudeOfAscendingNode;
}
glm::mat4 Orbit::getLookAlongMatrix(const float meanAnomaly) const
{
glm::vec3 position = getPosition(meanAnomaly);
@ -60,7 +89,7 @@ const float Orbit::getEccentricAnomaly(const float meanAnomaly) const
// Interpolate a position around the orbit.
// t is in range 0..1 and wraps.
const glm::vec3 Orbit::getPosition(const float meanAnomaly) const
glm::vec3 Orbit::getPosition(const float meanAnomaly) const
{
Vector6 cartesian = getCartesianCoordinates(meanAnomaly);
return glm::vec3(
@ -85,7 +114,7 @@ const Vector6 Orbit::getCartesianCoordinates(const float meanAnomaly) const
return astro::convertKeplerianToCartesianElements(kepler, 1.0);
}
glm::vec3 Orbit::getTangent(const float meanAnomaly)
glm::vec3 Orbit::getTangent(const float meanAnomaly) const
{
float epsilon = 0.01;
glm::vec3 ahead = getPosition(meanAnomaly + epsilon);

View File

@ -42,6 +42,7 @@
#include "gfx.hpp"
#include "icosphere.hpp"
#include "orbiter.hpp"
#include "orbitervisualizer.hpp"
#include "orbitvisualizer.hpp"
#include "widget.hpp"
@ -94,15 +95,28 @@ int main()
// set up scene
Icosphere planet(0.2, 3, litProgram);
Orbit orbit(.75f, .5, 3.142 / 2.0 + 1, 2.0, 0);
OrbitVisualizer orbitVisualizer(orbit, unlitProgram);
//Orbiter orbiter(orbiterSphere, orbit, unlitProgram);
Orbiter orbiter;
Orbit& orbit = orbiter.getOrbit();
orbit.setSemiMajorAxis(.75);
orbit.setEccentricity(.5);
orbit.setInclination(3.142 / 2.0 + 1);
orbit.setArgumentOfPeriapsis(2.0);
orbit.setLongitudeOfAscendingNode(0.1);
Icosphere orbiterSphere(0.07, 2, litProgram);
Orbiter orbiter(orbiterSphere, orbit, unlitProgram);
OrbiterVisualizer orbiterVisualizer(orbiter, orbiterSphere, unlitProgram);
OrbitVisualizer orbitVisualizer(orbit, unlitProgram);
// register input
glfwSetKeyCallback(window, keyCallback);
// TODO: convert these to an enum
const int ANIM_ORBITING = 0;
const int ANIM_ECCENTRICITY = 1;
int animation = 0;
float time = glfwGetTime();
// Main loop
while (!glfwWindowShouldClose(window))
{
@ -114,17 +128,30 @@ int main()
// apply input
if (input.cycleAnimation)
{
orbiter.cycleAnimation();
animation++;
if (animation > ANIM_ECCENTRICITY)
{
animation = 0;
}
}
// only update time if playing the orbiting animation
if (animation == ANIM_ORBITING)
{
time = glfwGetTime();
}
else
{
float e = .25 + .2 * sin(glfwGetTime());
orbit.setEccentricity(e);
}
// rendering
glClearColor(0.2, 0.3, 0.3, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float time = glfwGetTime();
planet.render(time);
orbiter.render(time);
orbiterVisualizer.render(time);
orbitVisualizer.render(time);
glfwSwapBuffers(window);

View File

@ -1,66 +1,7 @@
#include "orbiter.hpp"
#include <iostream>
Orbiter::Orbiter(Icosphere& sphere, Orbit& orbit, GLuint shaderProgram) :
_sphere(sphere),
_orbit(orbit),
_widget(shaderProgram)
Orbit& Orbiter::getOrbit()
{
return _orbit;
}
float Orbiter::getMeanAnomaly()
{
float time = glfwGetTime();
return time;
}
void Orbiter::cycleAnimation()
{
_animation++;
if (_animation > ANIM_ECCENTRICITY)
{
_animation = 0;
}
}
glm::vec3 Orbiter::getPosition(const float time)
{
//int animation = (int)(time/ORBITAL_PERIOD) % 2 == 1;
if (_animation == ANIM_ORBITING)
return _orbit.getPosition(time);
// TODO: modify the eccentricity of the orbit with a control instead
// of an automatic animation
if (_animation == ANIM_ECCENTRICITY)
{
float e = .25 + .2 * sin(time);
_orbit.setEccentricity(e);
return _orbit.getPosition(0);
}
std::cerr << "unknown animation " << _animation << std::endl;
throw 1;
}
void Orbiter::render(const float time)
{
const float meanAnomaly = time;
glm::vec3 pos = getPosition(meanAnomaly);
// render widget
glm::mat4 widgetMatrix = _orbit.getLookAlongMatrix(time);
_widget.setModelMatrix(widgetMatrix);
_widget.render(time);
// render sphere
_sphere.setPosition(pos);
_sphere.render(time);
}
Orbiter::~Orbiter()
{
}

View File

@ -1,37 +1,15 @@
#pragma once
#include "gfx.hpp"
#include "icosphere.hpp"
#include "widget.hpp"
#include <GLFW/glfw3.h>
#include <skein/orbit.h>
class Orbiter
{
public:
Orbiter(Icosphere& sphere, Orbit& orbit, GLuint shaderProgram);
~Orbiter();
Orbiter() = default;
~Orbiter() = default;
void render(const float time);
void cycleAnimation();
Orbit& getOrbit();
private:
void updateModelMatrix();
float getMeanAnomaly();
glm::vec3 getPosition(const float time);
void getOrbitalElements(const float time, Vector6& keplerianElements);
Icosphere& _sphere;
Orbit& _orbit;
Widget _widget;
const float ORBITAL_PERIOD = 6.284;
// TODO: convert these to an enum
const int ANIM_ORBITING = 0;
const int ANIM_ECCENTRICITY = 1;
int _animation = ANIM_ORBITING;
Orbit _orbit;
};

23
src/orbitervisualizer.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "orbitervisualizer.hpp"
OrbiterVisualizer::OrbiterVisualizer(Orbiter& orbiter, Icosphere& sphere, GLuint shaderProgram)
: _orbiter(orbiter), _sphere(sphere), _widget(shaderProgram)
{
}
void OrbiterVisualizer::render(float time)
{
const Orbit& orbit = _orbiter.getOrbit();
const float meanAnomaly = time;
glm::vec3 pos = orbit.getPosition(meanAnomaly);
// render widget
glm::mat4 widgetMatrix = orbit.getLookAlongMatrix(time);
_widget.setModelMatrix(widgetMatrix);
_widget.render(time);
// render sphere
_sphere.setPosition(pos);
_sphere.render(time);
}

21
src/orbitervisualizer.hpp Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include "widget.hpp"
#include "icosphere.hpp"
#include "orbiter.hpp"
class OrbiterVisualizer
{
public:
OrbiterVisualizer(Orbiter& orbiter, Icosphere& sphere, GLuint shaderProgram);
~OrbiterVisualizer() = default;
void render(float time);
private:
void updateModelMatrix();
Orbiter& _orbiter;
Icosphere& _sphere;
Widget _widget;
};

View File

@ -6,12 +6,12 @@ OrbitVisualizer::OrbitVisualizer(const Orbit& orbit, const GLuint shaderProgram)
{
glGenVertexArrays(1, &_vao);
glGenBuffers(1, &_vbo);
regenerateVertices();
}
void OrbitVisualizer::render(const float time)
{
regenerateVertices();
glUseProgram(_shaderProgram);
updateModelViewProjectionMatrix(_shaderProgram, time);