refactor: extract Orbiter class
split render logic across objects move rendering code from main loop to Orbiter make objects responsible for setting up their own render contexts
This commit is contained in:
parent
51c755be64
commit
441a0748d1
|
@ -30,6 +30,7 @@ add_executable(${PROJECT_NAME}
|
||||||
src/icosphere.cpp
|
src/icosphere.cpp
|
||||||
src/gfx.cpp
|
src/gfx.cpp
|
||||||
src/orbit.cpp
|
src/orbit.cpp
|
||||||
|
src/orbiter.cpp
|
||||||
src/widget.cpp
|
src/widget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -146,8 +146,11 @@ void Icosphere::updateModelMatrix()
|
||||||
glUniformMatrix4fv(modelLocation, 1, GL_FALSE, &model[0][0]);
|
glUniformMatrix4fv(modelLocation, 1, GL_FALSE, &model[0][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icosphere::render()
|
void Icosphere::render(const float time)
|
||||||
{
|
{
|
||||||
|
glUseProgram(_shaderProgram);
|
||||||
|
updateModelViewProjectionMatrix(_shaderProgram, time);
|
||||||
|
|
||||||
updateModelMatrix();
|
updateModelMatrix();
|
||||||
|
|
||||||
glBindVertexArray(_vao);
|
glBindVertexArray(_vao);
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Icosphere
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Icosphere(float radius, int subdivisions, GLuint shaderProgram);
|
Icosphere(float radius, int subdivisions, GLuint shaderProgram);
|
||||||
void render();
|
void render(const float time);
|
||||||
|
|
||||||
void setPosition(glm::vec3 position);
|
void setPosition(glm::vec3 position);
|
||||||
|
|
||||||
|
|
41
src/main.cpp
41
src/main.cpp
|
@ -42,6 +42,7 @@
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "icosphere.hpp"
|
#include "icosphere.hpp"
|
||||||
#include "orbit.hpp"
|
#include "orbit.hpp"
|
||||||
|
#include "orbiter.hpp"
|
||||||
#include "widget.hpp"
|
#include "widget.hpp"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@ -54,7 +55,7 @@ int main()
|
||||||
GLuint unlitProgram = compileShaderProgram("./frag_unlit.glsl");
|
GLuint unlitProgram = compileShaderProgram("./frag_unlit.glsl");
|
||||||
|
|
||||||
Icosphere planet(0.2, 3, litProgram);
|
Icosphere planet(0.2, 3, litProgram);
|
||||||
Icosphere orbiter(0.07, 2, litProgram);
|
|
||||||
|
|
||||||
std::vector<float> keplerianElements(6);
|
std::vector<float> keplerianElements(6);
|
||||||
keplerianElements[astro::semiMajorAxisIndex] = .75;
|
keplerianElements[astro::semiMajorAxisIndex] = .75;
|
||||||
|
@ -62,9 +63,10 @@ int main()
|
||||||
keplerianElements[astro::inclinationIndex] = 3.142 / 2.0 + 1;
|
keplerianElements[astro::inclinationIndex] = 3.142 / 2.0 + 1;
|
||||||
keplerianElements[astro::argumentOfPeriapsisIndex] = 2.0;
|
keplerianElements[astro::argumentOfPeriapsisIndex] = 2.0;
|
||||||
keplerianElements[astro::longitudeOfAscendingNodeIndex] = 0;
|
keplerianElements[astro::longitudeOfAscendingNodeIndex] = 0;
|
||||||
Orbit orbit(keplerianElements);
|
Orbit orbit(keplerianElements, unlitProgram);
|
||||||
|
|
||||||
Widget widget(orbit, unlitProgram);
|
Icosphere orbiterSphere(0.07, 2, litProgram);
|
||||||
|
Orbiter orbiter(orbiterSphere, orbit, unlitProgram);
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
while (!glfwWindowShouldClose(window))
|
while (!glfwWindowShouldClose(window))
|
||||||
|
@ -73,39 +75,8 @@ int main()
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
float time = glfwGetTime();
|
float time = glfwGetTime();
|
||||||
const float orbitalPeriod = 6.284;
|
|
||||||
|
|
||||||
const int ANIM_ORBITING = 0;
|
orbiter.render(time);
|
||||||
const int ANIM_ECCENTRICITY = 1;
|
|
||||||
int animation = (int)(time / orbitalPeriod) % 2 == 1;
|
|
||||||
|
|
||||||
glm::vec3 pos;
|
|
||||||
if (animation == ANIM_ORBITING)
|
|
||||||
{
|
|
||||||
pos = orbit.getPosition(time);
|
|
||||||
}
|
|
||||||
else if (animation == ANIM_ECCENTRICITY)
|
|
||||||
{
|
|
||||||
float e = .25 + .2 * sin(time);
|
|
||||||
keplerianElements[astro::eccentricityIndex] = e;
|
|
||||||
orbit.setElements(keplerianElements);
|
|
||||||
|
|
||||||
pos = orbit.getPosition(0);
|
|
||||||
}
|
|
||||||
orbiter.setPosition(pos);
|
|
||||||
|
|
||||||
// Render lit objects
|
|
||||||
glUseProgram(litProgram);
|
|
||||||
updateModelViewProjectionMatrix(litProgram, time);
|
|
||||||
|
|
||||||
planet.render();
|
|
||||||
orbiter.render();
|
|
||||||
|
|
||||||
// Render unlit objects
|
|
||||||
glUseProgram(unlitProgram);
|
|
||||||
updateModelViewProjectionMatrix(unlitProgram, time);
|
|
||||||
orbit.render();
|
|
||||||
widget.render();
|
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
#include "gfx.hpp"
|
||||||
#include "orbit.hpp"
|
#include "orbit.hpp"
|
||||||
|
|
||||||
#include "astro/stateVectorIndices.hpp"
|
#include "astro/stateVectorIndices.hpp"
|
||||||
#include "astro/orbitalElementConversions.hpp"
|
#include "astro/orbitalElementConversions.hpp"
|
||||||
|
|
||||||
Orbit::Orbit(Vector6 keplerianElements) :
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
_keplerianElements(keplerianElements)
|
|
||||||
|
Orbit::Orbit(Vector6 keplerianElements, GLuint shaderProgram) :
|
||||||
|
_keplerianElements(keplerianElements),
|
||||||
|
_shaderProgram(shaderProgram)
|
||||||
{
|
{
|
||||||
glGenVertexArrays(1, &_vao);
|
glGenVertexArrays(1, &_vao);
|
||||||
glGenBuffers(1, &_vbo);
|
glGenBuffers(1, &_vbo);
|
||||||
|
@ -45,6 +49,32 @@ void Orbit::setElements(Vector6 keplerianElements)
|
||||||
regenerateVertices();
|
regenerateVertices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Orbit::getElements(Vector6& keplerianElements) const
|
||||||
|
{
|
||||||
|
keplerianElements = _keplerianElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 Orbit::getLookAlongMatrix(const float meanAnomaly)
|
||||||
|
{
|
||||||
|
glm::vec3 position = getPosition(meanAnomaly);
|
||||||
|
|
||||||
|
// get the tangent of the orbital ellipse
|
||||||
|
glm::vec3 tan = getTangent(meanAnomaly);
|
||||||
|
// we want to point along the orbit
|
||||||
|
glm::vec3 target = position + tan;
|
||||||
|
// TODO: this is not 'up' with respect to the orbited body!
|
||||||
|
// 'up' is just the normalized position vector because the orbit is centred at the origin
|
||||||
|
glm::vec3 up = glm::normalize(position);
|
||||||
|
// easy peasy lookAt matrix
|
||||||
|
glm::mat4 look = glm::lookAt(position, target, up);
|
||||||
|
|
||||||
|
// invert the lookat matrix because it's meant for cameras, cameras work backwards and
|
||||||
|
// we are not a camera
|
||||||
|
glm::mat4 lookAlong = glm::inverse(look);
|
||||||
|
|
||||||
|
return lookAlong;
|
||||||
|
}
|
||||||
|
|
||||||
float Orbit::getEccentricAnomaly(const float meanAnomaly)
|
float Orbit::getEccentricAnomaly(const float meanAnomaly)
|
||||||
{
|
{
|
||||||
const float eccentricity = _keplerianElements[astro::eccentricityIndex];
|
const float eccentricity = _keplerianElements[astro::eccentricityIndex];
|
||||||
|
@ -92,8 +122,11 @@ glm::vec3 Orbit::getTangent(const float meanAnomaly)
|
||||||
return glm::normalize(ahead - behind);
|
return glm::normalize(ahead - behind);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Orbit::render()
|
void Orbit::render(const float time)
|
||||||
{
|
{
|
||||||
|
glUseProgram(_shaderProgram);
|
||||||
|
updateModelViewProjectionMatrix(_shaderProgram, time);
|
||||||
|
|
||||||
glBindVertexArray(_vao);
|
glBindVertexArray(_vao);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||||
|
|
||||||
|
|
|
@ -10,15 +10,17 @@ typedef std::vector<float> Vector6;
|
||||||
class Orbit
|
class Orbit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Orbit(Vector6 keplerianElements);
|
Orbit(Vector6 keplerianElements, GLuint shaderProgram);
|
||||||
void render();
|
void render(const float time);
|
||||||
|
|
||||||
// TODO: meanAnomaly in all these arguments actually means eccentricMeanAnomaly,
|
// TODO: meanAnomaly in all these arguments actually means eccentricMeanAnomaly,
|
||||||
// will have to change that when adding non-ellipctical orbits - don't get confused!
|
// will have to change that when adding non-ellipctical orbits - don't get confused!
|
||||||
glm::vec3 getPosition(const float meanAnomaly);
|
glm::vec3 getPosition(const float meanAnomaly);
|
||||||
glm::vec3 getTangent(const float meanAnomaly);
|
glm::vec3 getTangent(const float meanAnomaly);
|
||||||
|
glm::mat4 getLookAlongMatrix(const float meanAnomaly);
|
||||||
|
|
||||||
void setElements(Vector6 keplerianElements);
|
void setElements(Vector6 keplerianElements);
|
||||||
|
void getElements(Vector6& keplerianElements) const;
|
||||||
|
|
||||||
~Orbit();
|
~Orbit();
|
||||||
private:
|
private:
|
||||||
|
@ -27,6 +29,7 @@ private:
|
||||||
|
|
||||||
GLuint _vbo;
|
GLuint _vbo;
|
||||||
GLuint _vao;
|
GLuint _vao;
|
||||||
|
GLuint _shaderProgram;
|
||||||
|
|
||||||
std::vector<float> _vertices;
|
std::vector<float> _vertices;
|
||||||
Vector6 _keplerianElements;
|
Vector6 _keplerianElements;
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include "orbiter.hpp"
|
||||||
|
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <astro/stateVectorIndices.hpp>
|
||||||
|
|
||||||
|
Orbiter::Orbiter(Icosphere& sphere, Orbit& orbit, GLuint unlitShaderProgram) :
|
||||||
|
_sphere(sphere),
|
||||||
|
_orbit(orbit),
|
||||||
|
_widget(unlitShaderProgram)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float Orbiter::getMeanAnomaly()
|
||||||
|
{
|
||||||
|
float time = glfwGetTime();
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 Orbiter::getPosition(const float time)
|
||||||
|
{
|
||||||
|
std::vector<float> keplerianElements(6);
|
||||||
|
_orbit.getElements(keplerianElements);
|
||||||
|
|
||||||
|
int animation = (int)(time/ORBITAL_PERIOD) % 2 == 1;
|
||||||
|
|
||||||
|
if (animation == ANIM_ORBITING)
|
||||||
|
return _orbit.getPosition(time);
|
||||||
|
|
||||||
|
// TODO: i want to modify the eccentricity of the orbit with a control,
|
||||||
|
// not an automatic animation
|
||||||
|
if (animation == ANIM_ECCENTRICITY)
|
||||||
|
{
|
||||||
|
// TODO: what are these magic numbers
|
||||||
|
float e = .25 + .2 * sin(time);
|
||||||
|
keplerianElements[astro::eccentricityIndex] = e;
|
||||||
|
// TODO: extract set from getter
|
||||||
|
_orbit.setElements(keplerianElements);
|
||||||
|
|
||||||
|
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 orbit
|
||||||
|
_orbit.render(time);
|
||||||
|
|
||||||
|
// render widget
|
||||||
|
glm::mat4 widgetMatrix = _orbit.getLookAlongMatrix(time);
|
||||||
|
_widget.setModelMatrix(widgetMatrix);
|
||||||
|
_widget.render(time);
|
||||||
|
|
||||||
|
// render sphere
|
||||||
|
_sphere.setPosition(pos);
|
||||||
|
_sphere.render(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
Orbiter::~Orbiter()
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "icosphere.hpp"
|
||||||
|
#include "orbit.hpp"
|
||||||
|
#include "widget.hpp"
|
||||||
|
|
||||||
|
class Orbiter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Orbiter(Icosphere& sphere, Orbit& orbit, GLuint unlitShaderProgram);
|
||||||
|
~Orbiter();
|
||||||
|
|
||||||
|
void render(const float time);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
const int ANIM_ORBITING = 0;
|
||||||
|
const int ANIM_ECCENTRICITY = 1;
|
||||||
|
};
|
|
@ -1,10 +1,7 @@
|
||||||
#include "widget.hpp"
|
#include "widget.hpp"
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
Widget::Widget(Orbit& orbit, GLuint shaderProgram) :
|
Widget::Widget(GLuint shaderProgram) :
|
||||||
_orbit(orbit),
|
|
||||||
_shaderProgram(shaderProgram)
|
_shaderProgram(shaderProgram)
|
||||||
{
|
{
|
||||||
const float lineLength = 0.1;
|
const float lineLength = 0.1;
|
||||||
|
@ -30,36 +27,22 @@ Widget::Widget(Orbit& orbit, GLuint shaderProgram) :
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::render()
|
void Widget::render(const float time)
|
||||||
{
|
{
|
||||||
updateModelMatrix();
|
glUseProgram(_shaderProgram);
|
||||||
|
updateModelViewProjectionMatrix(_shaderProgram, time);
|
||||||
|
|
||||||
|
GLint modelLocation = getShaderUniformLocation(_shaderProgram, "_Model");
|
||||||
|
glUniformMatrix4fv(modelLocation, 1, GL_FALSE, &_modelMatrix[0][0]);
|
||||||
|
|
||||||
glBindVertexArray(_vao);
|
glBindVertexArray(_vao);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||||
glDrawArrays(GL_LINES, 0, 6);
|
glDrawArrays(GL_LINES, 0, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::updateModelMatrix()
|
void Widget::setModelMatrix(const glm::mat4 matrix)
|
||||||
{
|
{
|
||||||
float p = glfwGetTime();
|
_modelMatrix = matrix;
|
||||||
|
|
||||||
_position = _orbit.getPosition(p);
|
|
||||||
|
|
||||||
// get the tangent of the orbital ellipse
|
|
||||||
glm::vec3 tan = _orbit.getTangent(p);
|
|
||||||
// we want to point along the orbit
|
|
||||||
glm::vec3 target = _position + tan;
|
|
||||||
// 'up' is just the normalized position vector because the orbit is centred at the origin
|
|
||||||
glm::vec3 up = glm::normalize(_position);
|
|
||||||
// easy peasy lookAt matrix
|
|
||||||
glm::mat4 look = glm::lookAt(_position, target, up);
|
|
||||||
|
|
||||||
// invert the lookat matrix because it's meant for cameras, cameras work backwards and
|
|
||||||
// we are not a camera
|
|
||||||
glm::mat4 model = glm::inverse(look);
|
|
||||||
|
|
||||||
GLint modelLocation = getShaderUniformLocation(_shaderProgram, "_Model");
|
|
||||||
glUniformMatrix4fv(modelLocation, 1, GL_FALSE, &model[0][0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget::~Widget()
|
Widget::~Widget()
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "orbit.hpp"
|
#include <GL/glew.h>
|
||||||
#include <glm/glm.hpp>
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
class Widget
|
class Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// A widget is renderer at a point on the orbit.
|
// A widget is 3D cross.
|
||||||
// It consists of 3 orthagonally intersecting lines.
|
// It consists of 3 orthagonally intersecting lines.
|
||||||
|
|
||||||
Widget(Orbit& orbit, GLuint shaderProgram);
|
Widget(GLuint shaderProgram);
|
||||||
void render();
|
void render(const float time);
|
||||||
|
|
||||||
|
void setModelMatrix(const glm::mat4 matrix);
|
||||||
|
|
||||||
void setPosition(glm::vec3 position);
|
|
||||||
~Widget();
|
~Widget();
|
||||||
private:
|
private:
|
||||||
Orbit& _orbit;
|
|
||||||
glm::vec3 _position;
|
|
||||||
|
|
||||||
GLuint _vao;
|
GLuint _vao;
|
||||||
GLuint _vbo;
|
GLuint _vbo;
|
||||||
GLuint _shaderProgram;
|
GLuint _shaderProgram;
|
||||||
|
glm::mat4 _modelMatrix;
|
||||||
void updateModelMatrix();
|
|
||||||
|
|
||||||
float _lineLength = 0.2;
|
float _lineLength = 0.2;
|
||||||
float _vertices[3*6] =
|
float _vertices[3*6] =
|
||||||
|
|
Loading…
Reference in New Issue