From: Daniel Karbach Date: Tue, 7 Nov 2017 22:50:25 +0000 (+0100) Subject: concerning orbits X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=0453d6da05d4b29d953f00857d743310d9344ce0;p=blobs.git concerning orbits --- diff --git a/src/app/states.cpp b/src/app/states.cpp index 0298e0c..ef8b514 100644 --- a/src/app/states.cpp +++ b/src/app/states.cpp @@ -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); } diff --git a/src/blobs.cpp b/src/blobs.cpp index 8577e32..5f7bb76 100644 --- a/src/blobs.cpp +++ b/src/blobs.cpp @@ -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 index 0000000..edbbe7c --- /dev/null +++ b/src/const.hpp @@ -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 diff --git a/src/graphics/PlanetSurface.hpp b/src/graphics/PlanetSurface.hpp index 2e73fbc..2482703 100644 --- a/src/graphics/PlanetSurface.hpp +++ b/src/graphics/PlanetSurface.hpp @@ -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 index a65dc10..0000000 --- a/src/graphics/const.hpp +++ /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 diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp index ca74766..b184bb9 100644 --- a/src/graphics/shader.cpp +++ b/src/graphics/shader.cpp @@ -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); +} + } } diff --git a/src/graphics/viewport.cpp b/src/graphics/viewport.cpp index 499a227..cb8d786 100644 --- a/src/graphics/viewport.cpp +++ b/src/graphics/viewport.cpp @@ -1,7 +1,7 @@ #include "Camera.hpp" #include "Viewport.hpp" -#include "const.hpp" +#include "../const.hpp" #include #include diff --git a/src/world/Body.hpp b/src/world/Body.hpp index e3fd8de..2f87d22 100644 --- a/src/world/Body.hpp +++ b/src/world/Body.hpp @@ -1,6 +1,8 @@ #ifndef BLOBS_WORLD_BODY_HPP_ #define BLOBS_WORLD_BODY_HPP_ +#include "../graphics/glm.hpp" + #include @@ -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 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) + }; } diff --git a/src/world/Simulation.hpp b/src/world/Simulation.hpp index 2acf549..6d22ed3 100644 --- a/src/world/Simulation.hpp +++ b/src/world/Simulation.hpp @@ -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; }; diff --git a/src/world/sim.cpp b/src/world/sim.cpp index 0e0b466..abf2829 100644 --- a/src/world/sim.cpp +++ b/src/world/sim.cpp @@ -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; } } diff --git a/src/world/world.cpp b/src/world/world.cpp index 7029667..5c11350 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -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 +#include +#include + +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); }