]> git.localhorst.tv Git - blobs.git/commitdiff
concerning orbits
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 7 Nov 2017 22:50:25 +0000 (23:50 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 7 Nov 2017 22:50:25 +0000 (23:50 +0100)
src/app/states.cpp
src/blobs.cpp
src/const.hpp [new file with mode: 0644]
src/graphics/PlanetSurface.hpp
src/graphics/const.hpp [deleted file]
src/graphics/shader.cpp
src/graphics/viewport.cpp
src/world/Body.hpp
src/world/Simulation.hpp
src/world/sim.cpp
src/world/world.cpp

index 0298e0ce6b1a7eeb6e3b923beefe0d7eceb3e952..ef8b5140141c5cbe8481712b86a78da95f37292b 100644 (file)
@@ -17,7 +17,7 @@ MasterState::MasterState(Assets &assets, world::Simulation &sim) noexcept
 , cam()
 , remain(0)
 , thirds(0) {
-       cam.View(glm::translate(glm::vec3(-3.0f, -2.0f, -10.0f)));
+       cam.View(glm::lookAt(glm::vec3(2.0f, 3.0f, 10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)));
 }
 
 MasterState::~MasterState() noexcept {
@@ -47,9 +47,11 @@ int MasterState::FrameMS() const noexcept {
 
 
 void MasterState::OnRender(graphics::Viewport &viewport) {
+       glm::mat4 ppos = reference->ToParent();
        assets.shaders.planet_surface.Activate();
        assets.shaders.planet_surface.SetMVP(glm::mat4(1.0f), cam.View(), cam.Projection());
        assets.shaders.planet_surface.SetTexture(assets.textures.tiles);
+       assets.shaders.planet_surface.SetLight(glm::vec3(cam.View() * ppos[3]), glm::vec3(1.0f, 1.0f, 1.0f), 100.0f);
        reference->Draw(assets, viewport);
 }
 
index 8577e32a901cdc5fcda828dbec7eb51a4dd6b432..5f7bb7674dfb67caa51565040baad6c7c90d43d8 100644 (file)
@@ -1,3 +1,4 @@
+#include "const.hpp"
 #include "app/Application.hpp"
 #include "app/Assets.hpp"
 #include "app/init.hpp"
@@ -16,10 +17,14 @@ int main(int argc, char *argv[]) {
        app::Assets assets;
 
        world::Sun sun;
+       sun.Mass(1.0e13);
        world::Simulation sim(sun);
        world::Planet planet(3);
+       planet.Mass(1.0e7);
+       planet.Inclination(PI * 0.25);
        world::GenerateTest(planet);
        planet.SetParent(sun);
+       planet.SemiMajorAxis(10.0);
 
        app::MasterState state(assets, sim);
        state.SetReference(planet);
diff --git a/src/const.hpp b/src/const.hpp
new file mode 100644 (file)
index 0000000..edbbe7c
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef BLOBS_CONST_HPP_
+#define BLOBS_CONST_HPP_
+
+
+namespace blobs {
+
+constexpr double PI = 3.141592653589793238462643383279502884;
+constexpr double PI_0p25 = PI * 0.25;
+constexpr double PI_0p5 = PI * 0.5;
+constexpr double PI_1p5 = PI * 1.5;
+constexpr double PI_2p0 = PI * 2.0;
+
+constexpr double PI_inv = 1.0 / PI;
+constexpr double PI_0p5_inv = 1.0 / PI_0p5;
+
+constexpr double G = 6.674e-11; // m³kg¯¹s¯²
+
+}
+
+#endif
index 2e73fbc1542e113a60eb95a1c0a6239011b06b28..2482703b070b8eff0fe4e07409933b0b852afb92 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "Program.hpp"
 
+#include "glm.hpp"
+
 
 namespace blobs {
 namespace graphics {
@@ -27,16 +29,33 @@ public:
        void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept;
        void SetNormal(const glm::vec3 &) noexcept;
        void SetTexture(ArrayTexture &) noexcept;
+       void SetLight(const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept;
+
+       const glm::mat4 &M() const noexcept { return m; }
+       const glm::mat4 &V() const noexcept { return v; }
+       const glm::mat4 &P() const noexcept { return p; }
+       const glm::mat4 &MV() const noexcept { return mv; }
+       const glm::mat4 &MVP() const noexcept { return mvp; }
 
 private:
        Program prog;
 
+       glm::mat4 m;
+       glm::mat4 v;
+       glm::mat4 p;
+       glm::mat4 mv;
+       glm::mat4 mvp;
+
        GLuint m_handle;
        GLuint mv_handle;
        GLuint mvp_handle;
        GLuint sampler_handle;
        GLuint normal_handle;
 
+       GLuint light_position_handle;
+       GLuint light_color_handle;
+       GLuint light_strength_handle;
+
 };
 
 }
diff --git a/src/graphics/const.hpp b/src/graphics/const.hpp
deleted file mode 100644 (file)
index a65dc10..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef BLOBS_GRAPHICS_CONST_HPP_
-#define BLOBS_GRAPHICS_CONST_HPP_
-
-
-namespace blobs {
-namespace graphics {
-
-constexpr double PI = 3.141592653589793238462643383279502884;
-constexpr double PI_0p25 = PI * 0.25;
-constexpr double PI_0p5 = PI * 0.5;
-constexpr double PI_1p5 = PI * 1.5;
-constexpr double PI_2p0 = PI * 2.0;
-
-constexpr double PI_inv = 1.0 / PI;
-constexpr double PI_0p5_inv = 1.0 / PI_0p5;
-
-}
-}
-
-#endif
index ca74766e9474125840014abf1c54ef9e1e7e3089..b184bb98d08d6009bde2af53c30027b623f67ecc 100644 (file)
@@ -193,18 +193,35 @@ PlanetSurface::PlanetSurface()
                GL_FRAGMENT_SHADER,
                "#version 330 core\n"
 
+               "struct LightSource {\n"
+                       "vec3 position;\n"
+                       "vec3 color;\n"
+                       "float strength;\n"
+               "};\n"
+
                "in vec3 vtx_viewspace;\n"
                "in vec3 frag_tex_uv;\n"
 
                "uniform sampler2DArray tex_sampler;\n"
                "uniform vec3 normal;\n"
+               "uniform LightSource light;\n"
 
                "out vec3 color;\n"
 
                "void main() {\n"
                        "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n"
-                       // TODO: lighting
-                       "color = tex_color;\n"
+                       "vec3 to_light = light.position - vtx_viewspace;\n"
+                       "float distance = length(to_light);\n"
+                       "vec3 light_dir = normalize(to_light);\n"
+                       "float attenuation = light.strength / (distance * distance);\n"
+                       "vec3 ambient = tex_color * vec3(0.01, 0.01, 0.01);\n"
+                       "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light.color * tex_color;\n"
+                       "vec3 view_dir = vec3(0.0, 0.0, 1.0);\n"
+                       "vec3 specular = vec3(0.0, 0.0, 0.0);\n"
+                       "if (dot(normal, light_dir) >= 0.0) {\n"
+                               "attenuation * light.color * pow(max(0.0, dot(reflect(-light_dir, normal), view_dir)), 25.0);\n"
+                       "}\n"
+                       "color = ambient + diffuse + specular;\n"
                "}\n"
        );
        prog.Link();
@@ -217,6 +234,9 @@ PlanetSurface::PlanetSurface()
        mvp_handle = prog.UniformLocation("MVP");
        sampler_handle = prog.UniformLocation("tex_sampler");
        normal_handle = prog.UniformLocation("normal");
+       light_position_handle = prog.UniformLocation("light.position");
+       light_color_handle = prog.UniformLocation("light.color");
+       light_strength_handle = prog.UniformLocation("light.strength");
 }
 
 PlanetSurface::~PlanetSurface() {
@@ -226,15 +246,19 @@ void PlanetSurface::Activate() noexcept {
        prog.Use();
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);
-       glDisable(GL_CULL_FACE);
+       glEnable(GL_CULL_FACE);
        glDisable(GL_BLEND);
 }
 
-void PlanetSurface::SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept {
+void PlanetSurface::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       m = mm;
+       v = vv;
+       p = pp;
+       mv = v * m;
+       mvp = p * mv;
        prog.Uniform(m_handle, m);
-       glm::mat4 mv(v * m);
        prog.Uniform(mv_handle, mv);
-       prog.Uniform(mvp_handle, p * mv);
+       prog.Uniform(mvp_handle, mvp);
 }
 
 void PlanetSurface::SetNormal(const glm::vec3 &n) noexcept {
@@ -247,5 +271,11 @@ void PlanetSurface::SetTexture(ArrayTexture &tex) noexcept {
        prog.Uniform(sampler_handle, GLint(0));
 }
 
+void PlanetSurface::SetLight(const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept {
+       prog.Uniform(light_position_handle, pos);
+       prog.Uniform(light_color_handle, color);
+       prog.Uniform(light_strength_handle, strength);
+}
+
 }
 }
index 499a22772025f64c2edbee3277a67f2a2944c522..cb8d786227f28a2cedf6fbb1a370b047570f5d7e 100644 (file)
@@ -1,7 +1,7 @@
 #include "Camera.hpp"
 #include "Viewport.hpp"
 
-#include "const.hpp"
+#include "../const.hpp"
 
 #include <GL/glew.h>
 #include <glm/gtx/transform.hpp>
index e3fd8ded17d2684befa5436fa76891b2c6ab3099..2f87d22723cd2239575355bf5153c006ef8d13af 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef BLOBS_WORLD_BODY_HPP_
 #define BLOBS_WORLD_BODY_HPP_
 
+#include "../graphics/glm.hpp"
+
 #include <vector>
 
 
@@ -13,6 +15,8 @@ namespace graphics {
 }
 namespace world {
 
+class Simulation;
+
 class Body {
 
 public:
@@ -26,12 +30,46 @@ public:
        Body &operator =(Body &&) = delete;
 
 public:
+       bool HasSimulation() const noexcept { return sim; }
+       const Simulation &GetSimulation() const noexcept { return *sim; }
+       void SetSimulation(Simulation &) noexcept;
+
        bool HasParent() const { return parent; }
        Body &Parent() { return *parent; }
        const Body &Parent() const { return *parent; }
        void SetParent(Body &);
        void UnsetParent();
 
+       double Mass() const noexcept;
+       void Mass(double) noexcept;
+
+       double Radius() const noexcept;
+       void Radius(double) noexcept;
+
+       double SemiMajorAxis() const noexcept;
+       void SemiMajorAxis(double) noexcept;
+
+       double Eccentricity() const noexcept;
+       void Eccentricity(double) noexcept;
+
+       double Inclination() const noexcept;
+       void Inclination(double) noexcept;
+
+       double LongitudeAscending() const noexcept;
+       void LongitudeAscending(double) noexcept;
+
+       double ArgumentPeriapsis() const noexcept;
+       void ArgumentPeriapsis(double) noexcept;
+
+       double MeanAnomaly() const noexcept;
+       void MeanAnomaly(double) noexcept;
+
+       double GravitationalParameter() const noexcept;
+       double OrbitalPeriod() const noexcept;
+
+       glm::mat4 ToParent() const noexcept;
+       glm::mat4 FromParent() const noexcept;
+
        virtual void Draw(app::Assets &, graphics::Viewport &) { }
 
 private:
@@ -39,11 +77,20 @@ private:
        void RemoveChild(Body &);
 
 private:
+       Simulation *sim;
        Body *parent;
        std::vector<Body *> children;
        double mass;
        double radius;
 
+       // Orbit
+       double sma; // semi-major axis
+       double ecc; // eccentricity
+       double inc; // inclination
+       double asc; // longitude of ascending node
+       double arg; // argument of periapsis
+       double mna; // mean anomaly (at t=0)
+
 };
 
 }
index 2acf54981b29b9bc04177a44a9b5cd84256503ca..6d22ed3ef9e5087f886e2f1c62e94ef34af57aea 100644 (file)
@@ -25,8 +25,11 @@ public:
        Body &Root() { return root; }
        const Body &Root() const { return root; }
 
+       double Time() const noexcept { return time; }
+
 private:
        Body &root;
+       double time;
 
 };
 
index 0e0b46616694dfd9bf05fbf7089a3cb21b831024..abf2829498f20356115a128801279bf5c53eb10e 100644 (file)
@@ -1,11 +1,14 @@
 #include "Simulation.hpp"
 
+#include "Body.hpp"
+
 
 namespace blobs {
 namespace world {
 
 Simulation::Simulation(Body &r)
 : root(r) {
+       r.SetSimulation(*this);
 }
 
 Simulation::~Simulation() {
@@ -13,6 +16,7 @@ Simulation::~Simulation() {
 
 
 void Simulation::Tick() {
+       time += 0.01666666666666666666666666666666;
 }
 
 }
index 7029667b0a06ebd26c31b7e24065f9977275f9af..5c1135049612f63e1492fa225f867939cc6de0f2 100644 (file)
@@ -1,27 +1,53 @@
 #include "Body.hpp"
 #include "Planet.hpp"
+#include "Simulation.hpp"
 #include "Sun.hpp"
 #include "Tile.hpp"
 
+#include "../const.hpp"
 #include "../app/Assets.hpp"
 #include "../graphics/Viewport.hpp"
 
 #include <algorithm>
+#include <cmath>
+#include <glm/gtx/transform.hpp>
+
+using blobs::G;
+using blobs::PI_2p0;
+
+using std::sin;
+using std::cos;
+using std::pow;
+using std::sqrt;
 
 
 namespace blobs {
 namespace world {
 
 Body::Body()
-: parent(nullptr)
+: sim(nullptr)
+, parent(nullptr)
 , children()
 , mass(1.0)
-, radius(1.0) {
+, radius(1.0)
+, sma(1.0)
+, ecc(0.0)
+, inc(0.0)
+, asc(0.0)
+, arg(0.0)
+, mna(0.0) {
 }
 
 Body::~Body() {
 }
 
+void Body::SetSimulation(Simulation &s) noexcept {
+       sim = &s;
+       for (auto child : children) {
+               child->SetSimulation(s);
+       }
+}
+
 void Body::SetParent(Body &p) {
        if (HasParent()) {
                UnsetParent();
@@ -38,6 +64,7 @@ void Body::UnsetParent() {
 
 void Body::AddChild(Body &c) {
        children.push_back(&c);
+       c.SetSimulation(*sim);
 }
 
 void Body::RemoveChild(Body &c) {
@@ -47,6 +74,126 @@ void Body::RemoveChild(Body &c) {
        }
 }
 
+double Body::Mass() const noexcept {
+       return mass;
+}
+
+void Body::Mass(double m) noexcept {
+       mass = m;
+}
+
+double Body::Radius() const noexcept {
+       return radius;
+}
+
+void Body::Radius(double r) noexcept {
+       radius = r;
+}
+
+double Body::SemiMajorAxis() const noexcept {
+       return sma;
+}
+
+void Body::SemiMajorAxis(double s) noexcept {
+       sma = s;
+}
+
+double Body::Eccentricity() const noexcept {
+       return ecc;
+}
+
+void Body::Eccentricity(double e) noexcept {
+       ecc = e;
+}
+
+double Body::Inclination() const noexcept {
+       return inc;
+}
+
+void Body::Inclination(double i) noexcept {
+       inc = i;
+}
+
+double Body::LongitudeAscending() const noexcept {
+       return asc;
+}
+
+void Body::LongitudeAscending(double l) noexcept {
+       asc = l;
+}
+
+double Body::ArgumentPeriapsis() const noexcept {
+       return arg;
+}
+
+void Body::ArgumentPeriapsis(double a) noexcept {
+       arg = a;
+}
+
+double Body::MeanAnomaly() const noexcept {
+       return mna;
+}
+
+void Body::MeanAnomaly(double m) noexcept {
+       mna = m;
+}
+
+double Body::GravitationalParameter() const noexcept {
+       return G * Mass();
+}
+
+double Body::OrbitalPeriod() const noexcept {
+       if (parent) {
+               return PI_2p0 * sqrt((sma * sma * sma) / (G * (parent->Mass() + Mass())));
+       } else {
+               return 0.0;
+       }
+}
+
+glm::mat4 Body::ToParent() const noexcept {
+       if (!parent) {
+               return glm::mat4(1.0f);
+       }
+
+       double T = OrbitalPeriod();
+
+       double M = mna + PI_2p0 * (GetSimulation().Time() / T); // + time
+
+       double E = M; // eccentric anomaly, solve M = E - e sin E
+       while (true) {
+               double dE = (E - ecc * sin(E) - M) / (1 - ecc * cos(E));
+               E -= dE;
+               if (abs(dE) < 1.0e-6) break;
+       }
+
+       // coordinates in orbital plane
+       double P = sma * (cos(E) - ecc);
+       double Q = sma * sin(E) * sqrt(1 - (ecc * ecc));
+
+       // tile by argument of periapsis, …
+       double x = cos(arg) * P - sin(arg) * Q;
+       double y = sin(arg) * P + cos(arg) * Q;
+       // …inclination, …
+       double z = sin(inc) * x;
+              x = cos(inc) * x;
+       // …and longitude of ascending node
+       glm::vec3 pos(
+               cos(asc) * x - sin(asc) * y,
+               sin(asc) * x + cos(asc) * y,
+               z);
+
+       // TODO: calculate complete matrix
+       return glm::translate(-pos);
+}
+
+glm::mat4 Body::FromParent() const noexcept {
+       if (!parent) {
+               return glm::mat4(1.0f);
+       }
+       // TODO: calculate real position
+       return glm::translate(glm::vec3(-sma, 0.0f, 0.0f));
+}
+
 
 Planet::Planet(int sidelength)
 : Body()
@@ -109,7 +256,20 @@ void Planet::BuildVAOs() {
        vao.ReserveElements(TilesTotal() * 6, GL_STATIC_DRAW);
        {
                auto element = vao.MapElements(GL_WRITE_ONLY);
-               for (int index = 0, surface = 0; surface < 6; ++surface) {
+               int index = 0;
+               for (int surface = 0; surface < 3; ++surface) {
+                       for (int y = 0; y < sidelength; ++y) {
+                               for (int x = 0; x < sidelength; ++x, ++index) {
+                                       element[6 * index + 0] = 4 * index + 0;
+                                       element[6 * index + 1] = 4 * index + 2;
+                                       element[6 * index + 2] = 4 * index + 1;
+                                       element[6 * index + 3] = 4 * index + 1;
+                                       element[6 * index + 4] = 4 * index + 2;
+                                       element[6 * index + 5] = 4 * index + 3;
+                               }
+                       }
+               }
+               for (int surface = 3; surface < 6; ++surface) {
                        for (int y = 0; y < sidelength; ++y) {
                                for (int x = 0; x < sidelength; ++x, ++index) {
                                        element[6 * index + 0] = 4 * index + 0;
@@ -127,19 +287,19 @@ void Planet::BuildVAOs() {
 
 void Planet::Draw(app::Assets &assets, graphics::Viewport &viewport) {
        vao.Bind();
-       // TODO: premultiply normal with model matrix (i.e. just take it from M)
-       assets.shaders.planet_surface.SetNormal(glm::vec3(0.0f, 0.0f, 1.0f));
-       vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 0);
-       assets.shaders.planet_surface.SetNormal(glm::vec3(1.0f, 0.0f, 0.0f));
-       vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 1);
-       assets.shaders.planet_surface.SetNormal(glm::vec3(0.0f, 1.0f, 0.0f));
-       vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 2);
-       assets.shaders.planet_surface.SetNormal(glm::vec3(0.0f, 0.0f, -1.0f));
-       vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 3);
-       assets.shaders.planet_surface.SetNormal(glm::vec3(-1.0f, 0.0f, 0.0f));
-       vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 4);
-       assets.shaders.planet_surface.SetNormal(glm::vec3(0.0f, -1.0f, 0.0f));
-       vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 5);
+       const glm::mat4 &MV = assets.shaders.planet_surface.MV();
+       assets.shaders.planet_surface.SetNormal(glm::vec3(MV * glm::vec4(0.0f, 0.0f, 1.0f, 0.0f)));
+       vao.DrawTriangles(TilesPerSurface() * 6, TilesPerSurface() * 6 * 0);
+       assets.shaders.planet_surface.SetNormal(glm::vec3(MV * glm::vec4(1.0f, 0.0f, 0.0f, 0.0f)));
+       vao.DrawTriangles(TilesPerSurface() * 6, TilesPerSurface() * 6 * 1);
+       assets.shaders.planet_surface.SetNormal(glm::vec3(MV * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f)));
+       vao.DrawTriangles(TilesPerSurface() * 6, TilesPerSurface() * 6 * 2);
+       assets.shaders.planet_surface.SetNormal(glm::vec3(MV * glm::vec4(0.0f, 0.0f, -1.0f, 0.0f)));
+       vao.DrawTriangles(TilesPerSurface() * 6, TilesPerSurface() * 6 * 3);
+       assets.shaders.planet_surface.SetNormal(glm::vec3(MV * glm::vec4(-1.0f, 0.0f, 0.0f, 0.0f)));
+       vao.DrawTriangles(TilesPerSurface() * 6, TilesPerSurface() * 6 * 4);
+       assets.shaders.planet_surface.SetNormal(glm::vec3(MV * glm::vec4(0.0f, -1.0f, 0.0f, 0.0f)));
+       vao.DrawTriangles(TilesPerSurface() * 6, TilesPerSurface() * 6 * 5);
 }