From 2384028542c6a48b8766488be80317220eae6bef Mon Sep 17 00:00:00 2001 From: ktyl Date: Thu, 5 Oct 2023 23:25:37 +0100 Subject: [PATCH] feat(widget): draw axis widget aligned to orbit --- CMakeLists.txt | 1 + src/main.cpp | 4 +++ src/orbit.cpp | 8 ++++++ src/orbit.hpp | 1 + src/widget.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/widget.hpp | 37 +++++++++++++++++++++++++++ 6 files changed, 120 insertions(+) create mode 100644 src/widget.cpp create mode 100644 src/widget.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f608b46..e43728b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ add_executable(${PROJECT_NAME} src/icosphere.cpp src/gfx.cpp src/orbit.cpp + src/widget.cpp ) if(WIN32) diff --git a/src/main.cpp b/src/main.cpp index da9e8ec..5e9d478 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,7 @@ #include "gfx.hpp" #include "icosphere.hpp" #include "orbit.hpp" +#include "widget.hpp" int main() { @@ -55,6 +56,8 @@ int main() Icosphere orbiter(0.07, 2, litProgram); Orbit orbit(100); + Widget widget(orbit, unlitProgram); + // Main loop while (!glfwWindowShouldClose(window)) { @@ -77,6 +80,7 @@ int main() glUseProgram(unlitProgram); updateModelViewProjectionMatrix(unlitProgram, time); orbit.render(); + widget.render(); glfwSwapBuffers(window); glfwPollEvents(); diff --git a/src/orbit.cpp b/src/orbit.cpp index db4dff9..f820af3 100644 --- a/src/orbit.cpp +++ b/src/orbit.cpp @@ -65,6 +65,14 @@ glm::vec3 Orbit::getPosition(const float meanAnomaly) cartesian[astro::zPositionIndex]); } +glm::vec3 Orbit::getTangent(const float meanAnomaly) +{ + float epsilon = 0.01; + glm::vec3 ahead = getPosition(meanAnomaly + epsilon); + glm::vec3 behind = getPosition(meanAnomaly - epsilon); + return glm::normalize(ahead - behind); +} + void Orbit::render() { glBindVertexArray(_vao); diff --git a/src/orbit.hpp b/src/orbit.hpp index ddebd52..e917d89 100644 --- a/src/orbit.hpp +++ b/src/orbit.hpp @@ -12,6 +12,7 @@ public: void render(); glm::vec3 getPosition(const float meanAnomaly); + glm::vec3 getTangent(const float meanAnomaly); ~Orbit(); private: diff --git a/src/widget.cpp b/src/widget.cpp new file mode 100644 index 0000000..92f9d31 --- /dev/null +++ b/src/widget.cpp @@ -0,0 +1,69 @@ +#include "widget.hpp" +#include "gfx.hpp" +#include +#include + +Widget::Widget(Orbit& orbit, GLuint shaderProgram) : + _orbit(orbit), + _shaderProgram(shaderProgram) +{ + const float lineLength = 0.1; + for (int i = 0; i < 3*6; i++) + { + _vertices[i] *= _lineLength; + } + + glGenVertexArrays(1, &_vao); + glGenBuffers(1, &_vbo); + + glBindVertexArray(_vao); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + size_t v3Size = 3 * sizeof(float); + size_t lineSize = 2 * sizeof(float); + size_t vboBufferSize = v3Size * lineSize * 3; + glBufferData(GL_ARRAY_BUFFER, vboBufferSize, &_vertices[0], GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +void Widget::render() +{ + updateModelMatrix(); + + glBindVertexArray(_vao); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glDrawArrays(GL_LINES, 0, 6); +} + +void Widget::updateModelMatrix() +{ + float p = glfwGetTime(); + + _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() +{ + glDeleteVertexArrays(1, &_vao); + glDeleteBuffers(1, &_vbo); +} diff --git a/src/widget.hpp b/src/widget.hpp new file mode 100644 index 0000000..7b203ef --- /dev/null +++ b/src/widget.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "orbit.hpp" +#include + +class Widget +{ +public: + // A widget is renderer at a point on the orbit. + // It consists of 3 orthagonally intersecting lines. + + Widget(Orbit& orbit, GLuint shaderProgram); + void render(); + + void setPosition(glm::vec3 position); + ~Widget(); +private: + Orbit& _orbit; + glm::vec3 _position; + + GLuint _vao; + GLuint _vbo; + GLuint _shaderProgram; + + void updateModelMatrix(); + + float _lineLength = 0.2; + float _vertices[3*6] = + { + -1, 0, 0, + 1, 0, 0, + 0, 1, 0, + 0,-1, 0, + 0, 0, 1, + 0, 0,-1 + }; +};