From 56aa50251b71cdea29c7f97488f7e45a5a60a5c5 Mon Sep 17 00:00:00 2001 From: Cat Flynn Date: Tue, 20 Aug 2024 00:35:43 +0100 Subject: [PATCH] feat: add particle map --- README.md | 9 +++++++ lib/skein/CMakeLists.txt | 1 + lib/skein/include/skein/particle.h | 11 +++++--- lib/skein/include/skein/particlemap.h | 27 +++++++++++++++++++ lib/skein/src/particle.cpp | 18 +++++++++++-- lib/skein/src/particlemap.cpp | 39 +++++++++++++++++++++++++++ src/gfx.cpp | 2 +- src/main.cpp | 38 +++++++++++++++----------- src/particlevisualizer.cpp | 21 ++++++++------- src/particlevisualizer.hpp | 7 ++--- 10 files changed, 140 insertions(+), 33 deletions(-) create mode 100644 README.md create mode 100644 lib/skein/include/skein/particlemap.h create mode 100644 lib/skein/src/particlemap.cpp diff --git a/README.md b/README.md new file mode 100644 index 0000000..4153633 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Skein + +Skein is a library for efficiently simulating Keplerian astrodynamics. + +## Usage + +Kepler models orbiting bodies as particles. Particles are zero-dimensional objects which can be on elliptical orbits around other particles. The orbited particle is assumed to make up the overwhelming majority of the mass of the combined two-object system. + + diff --git a/lib/skein/CMakeLists.txt b/lib/skein/CMakeLists.txt index 5b5858a..a9dd29e 100644 --- a/lib/skein/CMakeLists.txt +++ b/lib/skein/CMakeLists.txt @@ -4,6 +4,7 @@ project(skein) add_library(skein STATIC src/orbit.cpp src/particle.cpp + src/particlemap.cpp ) target_include_directories(skein PUBLIC diff --git a/lib/skein/include/skein/particle.h b/lib/skein/include/skein/particle.h index 3d2d72b..ec00aa5 100644 --- a/lib/skein/include/skein/particle.h +++ b/lib/skein/include/skein/particle.h @@ -2,14 +2,19 @@ #include +#include + class Particle { public: - Particle() = default; + Particle(const std::string& id, double mass); + Particle(const Particle& other); ~Particle() = default; - Orbit& getOrbit(); + const std::string& getId() const; + double getMass() const; private: - Orbit _orbit; + const std::string _id; + const double _mass; }; diff --git a/lib/skein/include/skein/particlemap.h b/lib/skein/include/skein/particlemap.h new file mode 100644 index 0000000..b9b5aa8 --- /dev/null +++ b/lib/skein/include/skein/particlemap.h @@ -0,0 +1,27 @@ +#pragma once + +#include "skein/particle.h" + +#include +#include + +class ParticleMap +{ + public: + ParticleMap() = default; + ~ParticleMap() = default; + + // providing these as two methods keeps things unambiguous - manipulating particles + // is just done for setup + const Particle& getParticle(const std::string& id) const; + glm::vec3 getParticlePosition(const std::string& id, double time) const; + const Orbit& getOrbit(const std::string& id) const; + + void setParticle(const Particle& particle); + void setRelationship(const std::string& parentId, const std::string& childId, const Orbit& orbit); + + private: + std::map _particles; + std::map _relationships; + std::map _orbits; +}; diff --git a/lib/skein/src/particle.cpp b/lib/skein/src/particle.cpp index 36e7c87..bbdf5cc 100644 --- a/lib/skein/src/particle.cpp +++ b/lib/skein/src/particle.cpp @@ -1,7 +1,21 @@ #include "skein/particle.h" -Orbit& Particle::getOrbit() +Particle::Particle(const std::string& id, double mass) + : _id(id), _mass(mass) { - return _orbit; } +Particle::Particle(const Particle& other) + : _id(other.getId()), _mass(other.getMass()) +{ +} + +const std::string& Particle::getId() const +{ + return _id; +} + +double Particle::getMass() const +{ + return _mass; +} diff --git a/lib/skein/src/particlemap.cpp b/lib/skein/src/particlemap.cpp new file mode 100644 index 0000000..119fddc --- /dev/null +++ b/lib/skein/src/particlemap.cpp @@ -0,0 +1,39 @@ +#include "skein/particlemap.h" +#include "skein/particle.h" + + +const Particle& ParticleMap::getParticle(const std::string& id) const +{ + return _particles.at(id); +} + +const Orbit& ParticleMap::getOrbit(const std::string& id) const +{ + return _orbits.at(id); +} + +glm::vec3 ParticleMap::getParticlePosition(const std::string& id, double time) const +{ + // TODO: actually nest stuff so position is determined from all parents + + if (_orbits.find(id) != _orbits.end()) + { + const Orbit& orbit = _orbits.at(id); + return orbit.getPosition(time); + } + + return {0,0,0}; +} + +void ParticleMap::setParticle(const Particle& particle) +{ + _particles.insert({particle.getId(), particle}); +} + +void ParticleMap::setRelationship(const std::string& parentId, const std::string& childId, const Orbit& orbit) +{ + // map children to parent - children can only have one parent, so we use the map to + // identify the parent directly using the child as the key + _relationships.insert({childId, parentId}); + _orbits.insert({childId, orbit}); +} diff --git a/src/gfx.cpp b/src/gfx.cpp index 6155253..4461a1a 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -110,7 +110,7 @@ GLuint compileShaderProgram(const std::string& fragShaderPath) void updateProjectionMatrix(GLuint shaderProgram) { - float left = -aspect_, right = aspect_, bottom = -1.0, top = 1.0, near = -1.0, far = 1.0; + float left = -aspect_, right = aspect_, bottom = -1.0, top = 1.0, near = -2.0, far = 1.0; glm::mat4 projection = glm::ortho(left, right, bottom, top, near, far); GLint projectionLocation = getShaderUniformLocation(shaderProgram, "_Projection"); glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, &projection[0][0]); diff --git a/src/main.cpp b/src/main.cpp index 6f33f09..708df89 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,7 @@ #include #include +#include // INPUT! // @@ -92,19 +93,26 @@ int main() GLuint litProgram = compileShaderProgram("./frag_lit.glsl"); GLuint unlitProgram = compileShaderProgram("./frag_unlit.glsl"); - // set up scene - Icosphere planet(0.2, 3, litProgram); + // set parameters of moon's orbit around earth + Orbit orbit; + orbit.setSemiMajorAxis(1.0); // in km + // TODO: implement zoom + //orbit.setSemiMajorAxis(384748); // in km + orbit.setEccentricity(0.055); + orbit.setInclination(5.15); // degreees + orbit.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 - Particle particle; - Orbit& orbit = particle.getOrbit(); - orbit.setSemiMajorAxis(.75); - orbit.setEccentricity(.5); - orbit.setInclination(3.142 / 2.0 + 1); - orbit.setArgumentOfPeriapsis(2.0); - orbit.setLongitudeOfAscendingNode(0.1); - - ParticleVisualizer particleVisualizer(particle, litProgram, unlitProgram); - OrbitVisualizer orbitVisualizer(orbit, unlitProgram); + // TODO: add something in a nice eccentric orbit around the moon + // make the earth-moon system + ParticleMap map; + map.setParticle({"moon", 7.3e22}); + map.setParticle({"earth", 5.9e24}); + map.setRelationship("moon", "earth", orbit); + // TODO: there is a bug where re-ordering the visualizers breaks rendering + ParticleVisualizer moonVis(map, "moon", 0.1, litProgram, unlitProgram); + ParticleVisualizer earthVis(map, "earth", 0.2, litProgram, unlitProgram); + OrbitVisualizer orbitVis(orbit, unlitProgram); // register input glfwSetKeyCallback(window, keyCallback); @@ -148,9 +156,9 @@ int main() glClearColor(0.2, 0.3, 0.3, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - planet.render(time); - particleVisualizer.render(time); - orbitVisualizer.render(time); + earthVis.render(time); + moonVis.render(time); + orbitVis.render(time); glfwSwapBuffers(window); } diff --git a/src/particlevisualizer.cpp b/src/particlevisualizer.cpp index 117bddf..ce7a52c 100644 --- a/src/particlevisualizer.cpp +++ b/src/particlevisualizer.cpp @@ -1,21 +1,24 @@ #include "particlevisualizer.hpp" -ParticleVisualizer::ParticleVisualizer(Particle& particle, GLuint sphereShaderProgram, GLuint widgetShaderProgram) - : _particle(particle), _sphere({0.07, 2, sphereShaderProgram}), _widget(widgetShaderProgram) +ParticleVisualizer::ParticleVisualizer(const ParticleMap& map, const std::string& particleId, float radius, + GLuint sphereShaderProgram, GLuint widgetShaderProgram) + : _map(map), _particleId(particleId), _sphere({radius, 2, sphereShaderProgram}), _widget(widgetShaderProgram) { } void ParticleVisualizer::render(float time) { - const Orbit& orbit = _particle.getOrbit(); - + // TODO: get mean anomly from particle which has the mass!! const float meanAnomaly = time; - glm::vec3 pos = orbit.getPosition(meanAnomaly); + glm::vec3 pos = _map.getParticlePosition(_particleId, meanAnomaly); - // render widget - glm::mat4 widgetMatrix = orbit.getLookAlongMatrix(time); - _widget.setModelMatrix(widgetMatrix); - _widget.render(time); + // TODO: extract widget to its own visualizer since we know it wants an orbit but we + // might not have one here + //// render widget + //const Orbit& orbit = _map.getOrbit(_particleId); + //glm::mat4 widgetMatrix = orbit.getLookAlongMatrix(time); + //_widget.setModelMatrix(widgetMatrix); + //_widget.render(time); // render sphere _sphere.setPosition(pos); diff --git a/src/particlevisualizer.hpp b/src/particlevisualizer.hpp index 2a7b9b0..19808e2 100644 --- a/src/particlevisualizer.hpp +++ b/src/particlevisualizer.hpp @@ -3,12 +3,12 @@ #include "widget.hpp" #include "icosphere.hpp" -#include +#include class ParticleVisualizer { public: - ParticleVisualizer(Particle& particle, GLuint sphereShaderProgram, GLuint widgetShaderProgram); + ParticleVisualizer(const ParticleMap& map, const std::string& particleId, float radius, GLuint sphereShaderProgram, GLuint widgetShaderProgram); ~ParticleVisualizer() = default; void render(float time); @@ -16,7 +16,8 @@ class ParticleVisualizer private: void updateModelMatrix(); - Particle& _particle; + const ParticleMap& _map; + const std::string& _particleId; Icosphere _sphere; Widget _widget; };