diff --git a/CMakeLists.txt b/CMakeLists.txt index 17adffc..773473a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) diff --git a/lib/skein/include/skein/orbit.h b/lib/skein/include/skein/orbit.h index 6420c76..dd16ed5 100644 --- a/lib/skein/include/skein/orbit.h +++ b/lib/skein/include/skein/orbit.h @@ -9,18 +9,26 @@ typedef std::vector 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; diff --git a/lib/skein/src/orbit.cpp b/lib/skein/src/orbit.cpp index 1a9335f..c7f4e97 100644 --- a/lib/skein/src/orbit.cpp +++ b/lib/skein/src/orbit.cpp @@ -5,28 +5,57 @@ #include -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); diff --git a/src/main.cpp b/src/main.cpp index cdf52ab..620fa05 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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); diff --git a/src/orbiter.cpp b/src/orbiter.cpp index 0dabbfa..f155377 100644 --- a/src/orbiter.cpp +++ b/src/orbiter.cpp @@ -1,66 +1,7 @@ #include "orbiter.hpp" -#include - -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() -{ -} diff --git a/src/orbiter.hpp b/src/orbiter.hpp index 99093c4..e4e622b 100644 --- a/src/orbiter.hpp +++ b/src/orbiter.hpp @@ -1,37 +1,15 @@ #pragma once -#include "gfx.hpp" -#include "icosphere.hpp" -#include "widget.hpp" - -#include #include 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; }; diff --git a/src/orbitervisualizer.cpp b/src/orbitervisualizer.cpp new file mode 100644 index 0000000..e4f2144 --- /dev/null +++ b/src/orbitervisualizer.cpp @@ -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); +} diff --git a/src/orbitervisualizer.hpp b/src/orbitervisualizer.hpp new file mode 100644 index 0000000..63bc967 --- /dev/null +++ b/src/orbitervisualizer.hpp @@ -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; +}; diff --git a/src/orbitvisualizer.cpp b/src/orbitvisualizer.cpp index fa61d94..096f5c5 100644 --- a/src/orbitvisualizer.cpp +++ b/src/orbitvisualizer.cpp @@ -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);