From: Daniel Karbach Date: Wed, 29 Nov 2017 19:44:22 +0000 (+0100) Subject: camera controls X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=dd8b3145a03ed676b0ae6311c29fc3d68f666b15;p=blobs.git camera controls yay --- diff --git a/src/app/MasterState.hpp b/src/app/MasterState.hpp index 959af62..24a29e6 100644 --- a/src/app/MasterState.hpp +++ b/src/app/MasterState.hpp @@ -39,6 +39,10 @@ private: void OnResize(int w, int h) override; void OnKeyDown(const SDL_KeyboardEvent &) override; + void OnMouseDown(const SDL_MouseButtonEvent &) override; + void OnMouseUp(const SDL_MouseButtonEvent &) override; + void OnMouseMotion(const SDL_MouseMotionEvent &) override; + void OnMouseWheel(const SDL_MouseWheelEvent &) override; void OnUpdate(int dt) override; void OnRender(graphics::Viewport &) override; @@ -51,6 +55,11 @@ private: world::Simulation ∼ graphics::Camera cam; + double cam_dist; + double cam_tgt_dist; + glm::dvec3 cam_orient; + bool cam_dragging; + ui::CreaturePanel cp; int remain; diff --git a/src/app/states.cpp b/src/app/states.cpp index b1a20db..cfac2fa 100644 --- a/src/app/states.cpp +++ b/src/app/states.cpp @@ -2,6 +2,7 @@ #include "../creature/Creature.hpp" #include "../graphics/Viewport.hpp" +#include "../math/const.hpp" #include "../world/Body.hpp" #include "../world/Planet.hpp" #include "../world/Simulation.hpp" @@ -18,6 +19,10 @@ MasterState::MasterState(Assets &assets, world::Simulation &sim) noexcept , assets(assets) , sim(sim) , cam(sim.Root()) +, cam_dist(10.0) +, cam_tgt_dist(10.0) +, cam_orient(PI * 0.125, 0.0, 0.0) +, cam_dragging(false) , cp(assets) , remain(0) , thirds(0) @@ -51,11 +56,19 @@ void MasterState::OnUpdate(int dt) { } void MasterState::Tick() { + constexpr double dt = 0.01666666666666666666666666666666; if (!paused) { - sim.Tick(); + sim.Tick(dt); } remain -= FrameMS(); thirds = (thirds + 1) % 3; + + double cam_diff = cam_tgt_dist - cam_dist; + if (std::abs(cam_diff) > 0.001) { + cam_dist += cam_diff * 0.25; + } else { + cam_dist = cam_tgt_dist; + } } int MasterState::FrameMS() const noexcept { @@ -69,9 +82,40 @@ void MasterState::OnKeyDown(const SDL_KeyboardEvent &e) { } } +void MasterState::OnMouseDown(const SDL_MouseButtonEvent &e) { + if (e.button == SDL_BUTTON_RIGHT) { + SDL_SetRelativeMouseMode(SDL_TRUE); + cam_dragging = true; + } +} + +void MasterState::OnMouseUp(const SDL_MouseButtonEvent &e) { + if (e.button == SDL_BUTTON_RIGHT) { + SDL_SetRelativeMouseMode(SDL_FALSE); + cam_dragging = false; + } +} + +void MasterState::OnMouseMotion(const SDL_MouseMotionEvent &e) { + constexpr double pitch_scale = PI * 0.001; + constexpr double yaw_scale = PI * 0.002; + if (cam_dragging) { + cam_orient.x = glm::clamp(cam_orient.x + double(e.yrel) * pitch_scale, 0.0, PI * 0.5); + cam_orient.y = std::fmod(cam_orient.y + double(e.xrel) * yaw_scale, PI * 2.0); + } +} + +void MasterState::OnMouseWheel(const SDL_MouseWheelEvent &e) { + constexpr double roll_scale = PI * 0.0625; + constexpr double zoom_scale = -1.0; + constexpr double zoom_base = 1.125; + cam_orient.z = glm::clamp(cam_orient.z + double(e.x) * roll_scale, PI * -0.5, PI * 0.5); + cam_tgt_dist = std::max(1.0, cam_tgt_dist * std::pow(zoom_base, double(e.y) * zoom_scale)); +} + void MasterState::OnRender(graphics::Viewport &viewport) { if (cp.Shown()) { - cam.TopDown(cp.GetCreature(), 10.0f); + cam.Radial(cp.GetCreature(), cam_dist, cam_orient); assets.shaders.planet_surface.Activate(); assets.shaders.planet_surface.SetV(cam.View()); assets.shaders.sun_surface.Activate(); diff --git a/src/graphics/Camera.hpp b/src/graphics/Camera.hpp index 736020d..1632916 100644 --- a/src/graphics/Camera.hpp +++ b/src/graphics/Camera.hpp @@ -42,7 +42,9 @@ public: /// look at center, position relative to orbital reference plane for children Camera &Orbital(const glm::vec3 &pos) noexcept; /// look at creature from above - Camera &TopDown(const creature::Creature &, float distance, float roll = 0.0f); + Camera &TopDown(const creature::Creature &, double distance, double roll = 0.0f); + /// look at creature from the side, angle in euler (ZXY in surface reference plane) + Camera &Radial(const creature::Creature &, double distance, const glm::dvec3 &angle); const glm::mat4 &Projection() const noexcept { return projection; } const glm::mat4 &View() const noexcept { return view; } diff --git a/src/graphics/viewport.cpp b/src/graphics/viewport.cpp index 398eb42..6137eb2 100644 --- a/src/graphics/viewport.cpp +++ b/src/graphics/viewport.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include #include @@ -68,8 +70,7 @@ Camera &Camera::FirstPerson(int srf, const glm::vec3 &pos, const glm::vec3 &at) 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 up(world::Planet::SurfaceNormal(srf)); glm::vec3 target; target[(srf + 0) % 3] = at.x; @@ -99,24 +100,47 @@ Camera &Camera::MapView(int srf, const glm::vec3 &pos, float roll) noexcept { return *this; } -Camera &Camera::TopDown(const creature::Creature &c, float distance, float roll) { +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; +} + +Camera &Camera::TopDown(const creature::Creature &c, double distance, double roll) { const creature::Situation &s = c.GetSituation(); - if (s.OnPlanet()) { + if (s.OnSurface()) { int srf = s.Surface(); - glm::vec3 pos(s.Position()); - pos[(srf + 2) % 3] += srf < 3 ? distance : -distance; + glm::vec3 pos(s.Position() + (world::Planet::SurfaceNormal(srf) * distance)); Reference(s.GetPlanet()); return MapView(srf, pos, roll); } else { glm::vec3 pos(s.Position()); - pos += glm::normalize(pos) * distance; + pos += glm::normalize(pos) * float(distance); return Orbital(pos); } } -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)); +Camera &Camera::Radial(const creature::Creature &c, double distance, const glm::dvec3 &angle) { + const creature::Situation &s = c.GetSituation(); + glm::dvec3 pos(s.Position()); + glm::dvec3 up(0.0); + glm::dvec3 dir(0.0, 0.0, -distance); + if (s.OnSurface()) { + Reference(s.GetPlanet()); + track_orient = true; + int srf = s.Surface(); + up = world::Planet::SurfaceNormal(srf); + dir = + world::Planet::SurfaceOrientation(srf) + * glm::dmat3(glm::eulerAngleYX(angle.y, -angle.x)) + * dir; + } else { + up.y = 1.0; + dir = glm::dmat3(glm::eulerAngleYX(angle.y, -angle.x)) * dir; + } + pos += up * (c.Size() * 0.5); + up = glm::rotate(up, angle.z, glm::normalize(-dir)); + view = glm::lookAt(pos - dir, pos, up); return *this; } diff --git a/src/world/Planet.hpp b/src/world/Planet.hpp index 28ecaa0..c109934 100644 --- a/src/world/Planet.hpp +++ b/src/world/Planet.hpp @@ -75,6 +75,19 @@ public: // center point of tile on surface at elevation glm::dvec3 TileCenter(int surface, int x, int y, double elevation = 0.0) const noexcept; + static glm::dvec3 SurfaceNormal(int srf) noexcept { + glm::dvec3 nrm(0.0); + nrm[(srf + 2) % 3] = srf < 3 ? 1.0 : -1.0; + return nrm; + } + static glm::dmat3 SurfaceOrientation(int srf) noexcept { + glm::dmat3 mat(0.0); + mat[(srf + 0) % 3][0] = 1.0; + mat[(srf + 2) % 3][1] = srf < 3 ? 1.0 : -1.0; + mat[(srf + 1) % 3][2] = srf < 3 ? 1.0 : -1.0; + return mat; + } + void BuildVAO(const Set &); void Draw(app::Assets &, graphics::Viewport &) override; diff --git a/src/world/Simulation.hpp b/src/world/Simulation.hpp index ee497a8..31489c6 100644 --- a/src/world/Simulation.hpp +++ b/src/world/Simulation.hpp @@ -29,7 +29,7 @@ public: Simulation &operator =(Simulation &&) = delete; public: - void Tick(); + void Tick(double dt); void AddBody(Body &); void AddPlanet(Planet &); diff --git a/src/world/sim.cpp b/src/world/sim.cpp index b6a198d..8c3749f 100644 --- a/src/world/sim.cpp +++ b/src/world/sim.cpp @@ -37,8 +37,7 @@ void Simulation::AddSun(Sun &s) { suns.insert(&s); } -void Simulation::Tick() { - constexpr double dt = 0.01666666666666666666666666666666; +void Simulation::Tick(double dt) { time += dt; for (auto body : bodies) { body->Tick(dt);