]> git.localhorst.tv Git - blobs.git/commitdiff
(slightly) better camera handling
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 12 Nov 2017 17:55:22 +0000 (18:55 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 12 Nov 2017 17:55:22 +0000 (18:55 +0100)
src/app/MasterState.hpp
src/app/states.cpp
src/blobs.cpp
src/graphics/Camera.hpp
src/graphics/viewport.cpp
src/world/Simulation.hpp
src/world/sim.cpp
src/world/world.cpp

index f62c77309ea7ea4a04133c5b1013e5accebded10..d2072ee326c27a30683a18558ff2d6c3de7194d1 100644 (file)
@@ -28,7 +28,8 @@ public:
        MasterState &operator =(MasterState &&) = delete;
 
 public:
-       void SetReference(world::Body &r) { reference = &r; }
+       graphics::Camera &GetCamera() noexcept { return cam; }
+       const graphics::Camera &GetCamera() const noexcept { return cam; }
 
 private:
        void OnResize(int w, int h) override;
@@ -44,7 +45,6 @@ private:
 private:
        Assets &assets;
        world::Simulation &sim;
-       world::Body *reference;
 
        graphics::Camera cam;
 
index 67c073a0d5292b5c6548b0c04044d810f6e5d817..b9fc57a4c3c15ea179d4a83b34490c513c34ecc7 100644 (file)
@@ -1,7 +1,9 @@
 #include "MasterState.hpp"
 
 #include "../world/Body.hpp"
+#include "../world/Planet.hpp"
 #include "../world/Simulation.hpp"
+#include "../world/Sun.hpp"
 
 #include <glm/gtx/transform.hpp>
 
@@ -13,17 +15,10 @@ MasterState::MasterState(Assets &assets, world::Simulation &sim) noexcept
 : State()
 , assets(assets)
 , sim(sim)
-, reference(&sim.Root())
-, cam()
+, cam(sim.Root())
 , remain(0)
 , thirds(0)
 , paused(false) {
-       // sunset view: standing in the center of surface 0 (+Z), looking west (-X)
-       //cam.View(glm::lookAt(glm::vec3(0.0f, 0.0f, 5.6f), glm::vec3(-1.0f, 0.0f, 5.6f), glm::vec3(0.0f, 0.0f, 1.0f)));
-       // sunrise view: standing in the center of surface 0 (+Z), looking east (+X)
-       cam.View(glm::lookAt(glm::vec3(0.0f, 0.0f, 5.6f), glm::vec3(1.0f, 0.0f, 5.6f), glm::vec3(0.0f, 0.0f, 1.0f)));
-       // far out, looking at planet
-       //cam.View(glm::lookAt(glm::vec3(10.0f, 10.0f, 50.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)));
 }
 
 MasterState::~MasterState() noexcept {
@@ -61,22 +56,25 @@ void MasterState::OnKeyDown(const SDL_KeyboardEvent &e) {
 }
 
 void MasterState::OnRender(graphics::Viewport &viewport) {
-       glm::dmat4 ppos = reference->InverseTransform() * reference->ToParent();
+       glm::dmat4 ppos = cam.Model(**sim.Suns().begin());
        assets.shaders.planet_surface.Activate();
        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), 1.0e6f);
 
-       assets.shaders.planet_surface.SetMVP(glm::mat4(1.0f), cam.View(), cam.Projection());
-       assets.shaders.planet_surface.SetLight(glm::vec3(cam.View() * ppos[3]), glm::vec3(1.0f, 1.0f, 1.0f), 2.0e4f);
-       reference->Draw(assets, viewport);
-
-       world::Body *child = reference->Children()[0];
-       assets.shaders.planet_surface.SetMVP(reference->InverseTransform() * child->FromParent() * child->LocalTransform(), cam.View(), cam.Projection());
-       child->Draw(assets, viewport);
+       for (auto planet : sim.Planets()) {
+               assets.shaders.planet_surface.SetMVP(cam.Model(*planet), cam.View(), cam.Projection());
+               planet->Draw(assets, viewport);
+       }
 
        assets.shaders.sun_surface.Activate();
-       assets.shaders.sun_surface.SetMVP(ppos * reference->Parent().LocalTransform(), cam.View(), cam.Projection());
-       assets.shaders.sun_surface.SetLight(glm::vec3(1.0f, 1.0f, 1.0f), 2.0e4f);
-       assets.shaders.sun_surface.Draw();
+       for (auto sun : sim.Suns()) {
+               double sun_radius = sun->Radius();
+               assets.shaders.sun_surface.SetMVP(
+                       cam.Model(*sun) * glm::scale(glm::vec3(sun_radius, sun_radius, sun_radius)),
+                       cam.View(), cam.Projection());
+               assets.shaders.sun_surface.SetLight(glm::vec3(1.0f, 1.0f, 1.0f), 1.0e6f);
+               assets.shaders.sun_surface.Draw();
+       }
 }
 
 }
index c302159c0124bab310d8a55820192b0024a2ac8a..464273bac4f894c387b68dd11e24bf4febf9a578 100644 (file)
 using namespace blobs;
 
 int main(int argc, char *argv[]) {
-       app::Init init;
+       app::Init init(true, 8);
        app::Assets assets;
 
        world::Sun sun;
        sun.Mass(1.0e12);
-       sun.Radius(1.0);
+       sun.Radius(10.0);
        sun.SurfaceTilt(glm::dvec2(PI * 0.25, PI * 0.25));
        sun.AngularMomentum(1.0e9);
 
@@ -27,28 +27,43 @@ int main(int argc, char *argv[]) {
        world::GenerateTest(planet);
        planet.SetParent(sun);
        planet.Mass(1.0e9);
-       planet.GetOrbit().SemiMajorAxis(100.0);
+       planet.GetOrbit().SemiMajorAxis(941.7);
        planet.SurfaceTilt(glm::dvec2(PI * 0.25, PI * 0.25));
        planet.AxialTilt(glm::dvec2(PI * 0.127, 0.0));
-       planet.AngularMomentum(3.0e9);
+       planet.AngularMomentum(1.25e9);
 
        world::Planet moon(3);
        world::GenerateTest(moon);
        moon.SetParent(planet);
        moon.Mass(1.0e6);
        moon.GetOrbit().SemiMajorAxis(25.0);
-       moon.AngularMomentum(1.0e5);
+       moon.Rotation(PI * 0.25);
+       moon.AngularMomentum(1.0e4);
 
        world::Simulation sim(sun);
-       sim.AddBody(planet);
-       sim.AddBody(moon);
+       sim.AddSun(sun);
+       sim.AddPlanet(planet);
+       sim.AddPlanet(moon);
 
        std::cout << "length of year: " << planet.OrbitalPeriod() << "s" << std::endl;
        std::cout << "length of moon cycle: " << moon.OrbitalPeriod() << "s" << std::endl;
        std::cout << "length of day: " << planet.RotationalPeriod() << "s" << std::endl;
+       std::cout << "days per year: " << (planet.OrbitalPeriod() / planet.RotationalPeriod()) << std::endl;
+       std::cout << "moon cycle in days: " << (moon.OrbitalPeriod() / planet.RotationalPeriod()) << std::endl;
+       std::cout << "moon cycles per year: " << (planet.OrbitalPeriod() / moon.OrbitalPeriod()) << std::endl;
 
        app::MasterState state(assets, sim);
-       state.SetReference(planet);
+       state.GetCamera()
+               .Reference(planet)
+               // sunrise
+               .FirstPerson(0, glm::vec3(0.0f, 0.0f, 0.1f), glm::vec3(1.0f, -0.75f, 0.1f))
+               // sunset
+               //.FirstPerson(3, glm::vec3(0.0f, 0.0f, 0.1f), glm::vec3(1.0f, -0.75f, 0.1f))
+               // from afar
+               //.MapView(0, glm::vec3(0.0f, 0.0f, 25.0f), 0.0f)
+               // system view
+               //.Orbital(glm::vec3(50.0f, 2500.0f, 50.0f));
+       ;
        planet.BuildVAOs();
 
        app::Application app(init.window, init.viewport);
index 7cc141ecb65e150b8b65b53632c19586a422ab23..f4a98d50cc0eefe80d5294f6f3c0c934c97c0377 100644 (file)
@@ -5,12 +5,15 @@
 
 
 namespace blobs {
+namespace world {
+       class Body;
+}
 namespace graphics {
 
 class Camera {
 
 public:
-       Camera() noexcept;
+       explicit Camera(const world::Body &) noexcept;
        ~Camera() noexcept;
 
        Camera(const Camera &) = delete;
@@ -20,14 +23,25 @@ public:
        Camera &operator =(Camera &&) = delete;
 
 public:
-       void FOV(float f) noexcept;
-       void Aspect(float r) noexcept;
-       void Aspect(float w, float h) noexcept;
-       void Clip(float near, float far) noexcept;
+       Camera &FOV(float f) noexcept;
+       Camera &Aspect(float r) noexcept;
+       Camera &Aspect(float w, float h) noexcept;
+       Camera &Clip(float near, float far) noexcept;
+
+       const world::Body &Reference() const noexcept { return *ref; }
+       Camera &Reference(const world::Body &) noexcept;
+
+       /// standing on given surface, with pos.z being elevation over NN
+       /// looking at given coordinates
+       Camera &FirstPerson(int surface, const glm::vec3 &pos, const glm::vec3 &at) noexcept;
+       /// looking straight down at surface from above
+       Camera &MapView(int surface, const glm::vec3 &pos, float roll = 0.0f) noexcept;
+       /// look at center, position relative to orbital reference plane for children
+       Camera &Orbital(const glm::vec3 &pos) noexcept;
 
        const glm::mat4 &Projection() const noexcept { return projection; }
        const glm::mat4 &View() const noexcept { return view; }
-       void View(const glm::mat4 &v) noexcept;
+       glm::mat4 Model(const world::Body &) const noexcept;
 
 private:
        void UpdateProjection() noexcept;
@@ -41,6 +55,11 @@ private:
        glm::mat4 projection;
        glm::mat4 view;
 
+       // reference frame
+       const world::Body *ref;
+       // track reference body's orientation
+       bool track_orient;
+
 };
 
 }
index cb8d786227f28a2cedf6fbb1a370b047570f5d7e..2d9b469236a07d8f2ce84da43d014530836c09e7 100644 (file)
@@ -2,7 +2,9 @@
 #include "Viewport.hpp"
 
 #include "../const.hpp"
+#include "../world/Body.hpp"
 
+#include <cmath>
 #include <GL/glew.h>
 #include <glm/gtx/transform.hpp>
 
 namespace blobs {
 namespace graphics {
 
-Camera::Camera() noexcept
+Camera::Camera(const world::Body &r) noexcept
 : fov(PI_0p25)
 , aspect(1.0f)
 , near(0.1f)
-, far(256.0f)
+, far(12560.0f)
 , projection(glm::perspective(fov, aspect, near, far))
-, view(1.0f) {
+, view(1.0f)
+, ref(&r)
+, track_orient(false) {
 
 }
 
 Camera::~Camera() noexcept {
 }
 
-void Camera::FOV(float f) noexcept {
+Camera &Camera::FOV(float f) noexcept {
        fov = f;
        UpdateProjection();
+       return *this;
 }
 
-void Camera::Aspect(float r) noexcept {
+Camera &Camera::Aspect(float r) noexcept {
        aspect = r;
        UpdateProjection();
+       return *this;
 }
 
-void Camera::Aspect(float w, float h) noexcept {
+Camera &Camera::Aspect(float w, float h) noexcept {
        Aspect(w / h);
+       return *this;
 }
 
-void Camera::Clip(float n, float f) noexcept {
+Camera &Camera::Clip(float n, float f) noexcept {
        near = n;
        far = f;
        UpdateProjection();
+       return *this;
 }
 
-void Camera::View(const glm::mat4 &v) noexcept {
-       view = v;
+Camera &Camera::Reference(const world::Body &r) noexcept {
+       ref = &r;
+       return *this;
+}
+
+Camera &Camera::FirstPerson(int srf, const glm::vec3 &pos, const glm::vec3 &at) noexcept {
+       track_orient = true;
+
+       float dir = srf < 3 ? 1.0f : -1.0f;
+
+       glm::vec3 position;
+       position[(srf + 0) % 3] = pos.x;
+       position[(srf + 1) % 3] = pos.y;
+       position[(srf + 2) % 3] = dir * (pos.z + Reference().Radius());
+
+       glm::vec3 up(0.0f);
+       up[(srf + 2) % 3] = dir;
+
+       glm::vec3 target;
+       target[(srf + 0) % 3] = at.x;
+       target[(srf + 1) % 3] = at.y;
+       target[(srf + 2) % 3] = dir * (at.z + Reference().Radius());
+
+       view = glm::lookAt(position, target, up);
+
+       return *this;
+}
+
+Camera &Camera::MapView(int srf, const glm::vec3 &pos, float roll) noexcept {
+       track_orient = true;
+
+       float dir = srf < 3 ? 1.0f : -1.0f;
+
+       glm::vec3 position;
+       position[(srf + 0) % 3] = pos.x;
+       position[(srf + 1) % 3] = pos.y;
+       position[(srf + 2) % 3] = dir * (pos.z + Reference().Radius());
+
+       glm::vec3 up(0.0f);
+       up[(srf + 0) % 3] = std::cos(roll);
+       up[(srf + 1) % 3] = std::sin(roll);
+       up[(srf + 2) % 3] = 0.0f;
+
+       glm::vec3 target = position;
+       target[(srf + 2) % 3] -= dir;
+
+       view = glm::lookAt(position, target, up);
+
+       return *this;
+}
+
+Camera &Camera::Orbital(const glm::vec3 &pos) noexcept {
+       track_orient = false;
+       view = glm::lookAt(pos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
+       return *this;
+}
+
+glm::mat4 Camera::Model(const world::Body &b) const noexcept {
+       if (&b == ref) {
+               return track_orient ? glm::mat4(1.0f) : glm::mat4(ref->LocalTransform());
+       } else if (b.HasParent() && &b.Parent() == ref) {
+               return track_orient
+                       ? ref->InverseTransform() * b.FromParent() * b.LocalTransform()
+                       : b.FromParent() * b.LocalTransform();
+       } else if (ref->HasParent() && &ref->Parent() == &b) {
+               return track_orient
+                       ? ref->InverseTransform() * ref->ToParent() * b.LocalTransform()
+                       : ref->ToParent() * b.LocalTransform();
+       } else {
+               // TODO: model matrices for path distances > 1
+               return track_orient ? glm::mat4(1.0f) : glm::mat4(ref->LocalTransform());
+       }
 }
 
 void Camera::UpdateProjection() noexcept {
index 3025a745b5bebb3665174e3599faf99a4c8cccdf..ea81de5ba226fcc812491aa18bbc44e8c704e361 100644 (file)
@@ -1,13 +1,15 @@
 #ifndef BLOBS_WORLD_SIMULATION_HPP_
 #define BLOBS_WORLD_SIMULATION_HPP_
 
-#include <vector>
+#include <set>
 
 
 namespace blobs {
 namespace world {
 
 class Body;
+class Planet;
+class Sun;
 
 class Simulation {
 
@@ -25,15 +27,23 @@ public:
        void Tick();
 
        void AddBody(Body &);
+       void AddPlanet(Planet &);
+       void AddSun(Sun &);
 
-       Body &Root() { return root; }
-       const Body &Root() const { return root; }
+       Body &Root() noexcept { return root; }
+       const Body &Root() const noexcept { return root; }
+
+       const std::set<Body *> &Bodies() const noexcept { return bodies; }
+       const std::set<Planet *> &Planets() const noexcept { return planets; }
+       const std::set<Sun *> &Suns() const noexcept { return suns; }
 
        double Time() const noexcept { return time; }
 
 private:
        Body &root;
-       std::vector<Body *> all_bodies;
+       std::set<Body *> bodies;
+       std::set<Planet *> planets;
+       std::set<Sun *> suns;
        double time;
 
 };
index 46454fd2952197311b72db9bfeace430a44bebdc..185046d4cfc4eed8e73270513c7568e3a55a9561 100644 (file)
@@ -1,6 +1,8 @@
 #include "Simulation.hpp"
 
 #include "Body.hpp"
+#include "Planet.hpp"
+#include "Sun.hpp"
 
 
 namespace blobs {
@@ -8,7 +10,9 @@ namespace world {
 
 Simulation::Simulation(Body &r)
 : root(r)
-, all_bodies()
+, bodies()
+, planets()
+, suns()
 , time(0.0) {
        AddBody(r);
 }
@@ -19,13 +23,23 @@ Simulation::~Simulation() {
 
 void Simulation::AddBody(Body &b) {
        b.SetSimulation(*this);
-       all_bodies.push_back(&b);
+       bodies.insert(&b);
+}
+
+void Simulation::AddPlanet(Planet &p) {
+       AddBody(p);
+       planets.insert(&p);
+}
+
+void Simulation::AddSun(Sun &s) {
+       AddBody(s);
+       suns.insert(&s);
 }
 
 void Simulation::Tick() {
        constexpr double dt = 0.01666666666666666666666666666666;
        time += dt;
-       for (auto body : all_bodies) {
+       for (auto body : bodies) {
                body->Rotation(body->Rotation() + dt * body->AngularMomentum() / body->Inertia());
        }
 }
index 0b1b22df6fca974c5657d9beeb745b270a4e1c23..eb03490204c722cf3f6f58425a2d88bc3ce2b022 100644 (file)
@@ -254,6 +254,9 @@ void Planet::BuildVAOs() {
                auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
                float offset = sidelength * 0.5f;
 
+               // srf  0  1  2  3  4  5
+               //  up +Z +X +Y -Z -X -Y
+
                for (int index = 0, surface = 0; surface < 6; ++surface) {
                        for (int y = 0; y < sidelength; ++y) {
                                for (int x = 0; x < sidelength; ++x, ++index) {