]> git.localhorst.tv Git - tacos.git/commitdiff
controllable camera
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 7 Mar 2016 16:46:10 +0000 (17:46 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 8 Mar 2016 09:17:27 +0000 (10:17 +0100)
src/app/keymap.cpp [new file with mode: 0644]
src/app/keymap.hpp [new file with mode: 0644]
src/graphics/camera.cpp
src/graphics/camera.hpp
src/graphics/viewport.cpp
src/tacos.cpp

diff --git a/src/app/keymap.cpp b/src/app/keymap.cpp
new file mode 100644 (file)
index 0000000..6fa41a1
--- /dev/null
@@ -0,0 +1,44 @@
+#include "keymap.hpp"
+
+#include <stdexcept>
+
+
+namespace tacos {
+
+Keymap::Keymap()
+: codemap{ NONE } {
+
+}
+
+void Keymap::Map(SDL_Scancode scancode, Action action) {
+       if (scancode > MAX_SCANCODE) {
+               throw std::runtime_error("cannot map out of bounds scancode");
+       }
+       codemap[scancode] = action;
+}
+
+Keymap::Action Keymap::Lookup(SDL_Scancode scancode) const {
+       if (scancode < NUM_SCANCODES) {
+               return codemap[scancode];
+       } else {
+               return NONE;
+       }
+}
+
+void Keymap::LoadDefault() {
+       Map(SDL_SCANCODE_ESCAPE, EXIT);
+       Map(SDL_SCANCODE_W, CAMERA_FORWARD);
+       Map(SDL_SCANCODE_S, CAMERA_BACK);
+       Map(SDL_SCANCODE_A, CAMERA_LEFT);
+       Map(SDL_SCANCODE_D, CAMERA_RIGHT);
+       Map(SDL_SCANCODE_Q, CAMERA_YAW_CW);
+       Map(SDL_SCANCODE_E, CAMERA_YAW_CCW);
+       Map(SDL_SCANCODE_INSERT, CAMERA_PITCH_CCW);
+       Map(SDL_SCANCODE_DELETE, CAMERA_PITCH_CW);
+       Map(SDL_SCANCODE_HOME, CAMERA_UP);
+       Map(SDL_SCANCODE_END, CAMERA_DOWN);
+       Map(SDL_SCANCODE_PAGEUP, CAMERA_NEARER);
+       Map(SDL_SCANCODE_PAGEDOWN, CAMERA_FARTHER);
+}
+
+}
diff --git a/src/app/keymap.hpp b/src/app/keymap.hpp
new file mode 100644 (file)
index 0000000..34aa8d9
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef TACOS_APP_KEYMAP_HPP
+#define TACOS_APP_KEYMAP_HPP
+
+#include <SDL.h>
+
+
+namespace tacos {
+
+class Keymap {
+
+public:
+       enum Action {
+               NONE,
+
+               CAMERA_RIGHT,
+               CAMERA_LEFT,
+               CAMERA_UP,
+               CAMERA_DOWN,
+               CAMERA_BACK,
+               CAMERA_FORWARD,
+               CAMERA_NEARER,
+               CAMERA_FARTHER,
+               CAMERA_PITCH_CCW,
+               CAMERA_PITCH_CW,
+               CAMERA_YAW_CCW,
+               CAMERA_YAW_CW,
+
+               EXIT,
+       };
+
+       static constexpr unsigned int MAX_SCANCODE = 0xFF;
+       static constexpr unsigned int NUM_SCANCODES = MAX_SCANCODE + 1;
+
+public:
+       Keymap();
+
+       void Map(SDL_Scancode scancode, Action);
+       Action Lookup(SDL_Scancode scancode) const;
+       Action Lookup(const SDL_Keysym &s) const { return Lookup(s.scancode); }
+       Action Lookup(const SDL_KeyboardEvent &e) const { return Lookup(e.keysym); }
+
+       void LoadDefault();
+
+private:
+       Action codemap[NUM_SCANCODES];
+
+};
+
+}
+
+#endif
index bc43e04292e233696e0a60b7c5339031f57db912..d9b8e848c779a5bb5ff1c889934e906295114b40 100644 (file)
@@ -5,21 +5,33 @@
 
 namespace tacos {
 
-Camera::Camera(const glm::vec3 &f)
-: focus(&f)
+Camera::Camera()
+: focus(0.0f)
 , distance(100.0f)
-, pitch(1.04719755119659774614f) // π/3
-, yaw(0.0f) {
+, orientation(0.52359877559829887307f, 0.0f) { // π/6
 
 }
 
-void Camera::Focus(const glm::vec3 &f) noexcept {
-       focus = &f;
+glm::mat4 Camera::View() const noexcept {
+       // zero yaw is into the screen, so -Z is the base view direction we're transforming from
+       // pitch needs to be inverted because we're projecting the distance back
+       const glm::vec3 position(focus - distance * rotateY(rotateX(glm::vec3(0.0f, 0.0f, -1.0f), -orientation.x), orientation.y));
+       return glm::lookAt(position, focus, glm::vec3(0.0f, 1.0f, 0.0f));
 }
 
-glm::mat4 Camera::View() const noexcept {
-       const glm::vec3 position(*focus - distance * rotateY(rotateX(glm::vec3(0.0f, 0.0f, 1.0f), pitch), yaw));
-       return glm::lookAt(position, *focus, glm::vec3(0.0f, 1.0f, 0.0f));
+void Camera::Move(const glm::vec3 &delta) noexcept {
+       focus += rotateY(delta, orientation.y);
+}
+
+void Camera::Rotate(const glm::vec2 &delta) noexcept {
+       orientation += delta;
+       orientation.x = glm::clamp(orientation.x, -1.55f, 1.55f);
+       while (orientation.y > 3.14159265358979323844f) { // π
+               orientation.y -= 6.28318530717958647688f; // 2π
+       }
+       while (orientation.y < -3.14159265358979323844f) {
+               orientation.y += 6.28318530717958647688f;
+       }
 }
 
 }
index a1660ca75cb2f11cb15720457ad601096fc72176..9d1953a27a6f74916efa0ca020f22822086b78a3 100644 (file)
@@ -13,17 +13,29 @@ namespace tacos {
 class Camera {
 
 public:
-       explicit Camera(const glm::vec3 &focus);
+       Camera();
 
        glm::mat4 View() const noexcept;
 
-       void Focus(const glm::vec3 &) noexcept;
+       /// set focal point to given position
+       void Warp(const glm::vec3 &position) noexcept { focus = position; }
+       /// move focal point by given delta
+       void Move(const glm::vec3 &delta) noexcept;
+
+       /// set distance of camera to focal point
+       void Distance(float dist) noexcept { distance = dist; }
+       /// adjust distance of camera to focal point
+       void BackOff(float delta) noexcept { distance += delta; }
+
+       /// set pitch and yaw
+       void Orient(const glm::vec2 &orient) noexcept { orientation = orient; }
+       /// change pitch and yaw
+       void Rotate(const glm::vec2 &delta) noexcept;
 
 private:
-       const glm::vec3 *focus;
+       glm::vec3 focus;
        float distance;
-       float pitch;
-       float yaw;
+       glm::vec2 orientation;
 
 };
 
index 4ee85c86b3c01ab15709236341a09284492a2fe7..17c99c7a8ff9a05b6a9a6974fb664534c917286b 100644 (file)
@@ -12,7 +12,7 @@ Viewport::Viewport(int w, int h)
 , fov(0.78539816339744830961f) // π/4
 , aspect(float(w) / float(h))
 , near(0.1f)
-, far(100.0f)
+, far(256.0f)
 , perspective(glm::perspective(fov, aspect, near, far))
 , ortho(glm::ortho(0.0f, float(width), float(height), 0.0f, near, far)) {
 
index 580becb9caa0e391a5b779de2010976a9609ad22..0e47e6e27af2baa545bbd961d1d0aab3f0887fcf 100644 (file)
@@ -1,6 +1,7 @@
 #include "app/assets.hpp"
 #include "app/config.hpp"
 #include "app/init.hpp"
+#include "app/keymap.hpp"
 #include "graphics/camera.hpp"
 #include "graphics/shader.hpp"
 #include "graphics/viewport.hpp"
@@ -24,6 +25,9 @@ int main(int argc, char *argv[]) {
        Window window(1440, 900);
        Viewport viewport(1440, 900);
 
+       Keymap keymap;
+       keymap.LoadDefault();
+
        constexpr float noise_scale = 1.0f/64.0f;
        constexpr float height_scale = 5.0f;
 
@@ -46,21 +50,123 @@ int main(int argc, char *argv[]) {
        }
        floor.GenerateVertices();
 
-       glm::vec3 focus(20.0f, 0.0f, 20.0f);
-       Camera camera(focus);
+       Camera camera;
+       camera.Warp(glm::vec3(20.0f, 0.0f, 20.0f));
 
        glm::mat4 M;
        glm::mat4 V;
        glm::mat4 MV;
        glm::mat4 MVP;
 
+       constexpr float cam_speed = 15.0f; // units per second
+       constexpr float cam_rot_speed = 2.0f; // radians per second
+
+       glm::vec3 cam_fwd(0.0f);
+       glm::vec3 cam_rev(0.0f);
+       float cam_near = 0.0f;
+       float cam_far = 0.0f;
+       glm::vec2 cam_rot_ccw(0.0f);
+       glm::vec2 cam_rot_cw(0.0f);
+
        floor_program.Use();
 
        bool running = true;
+       Uint32 last = SDL_GetTicks();
        SDL_Event event;
        while (running) {
+               Uint32 now = SDL_GetTicks();
+               // handle
                while (SDL_PollEvent(&event)) {
                        switch (event.type) {
+                               case SDL_KEYDOWN:
+                                       switch (keymap.Lookup(event.key)) {
+                                               case Keymap::CAMERA_RIGHT:
+                                                       cam_fwd.x = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_LEFT:
+                                                       cam_rev.x = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_UP:
+                                                       cam_fwd.y = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_DOWN:
+                                                       cam_rev.y = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_BACK:
+                                                       cam_fwd.z = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_FORWARD:
+                                                       cam_rev.z = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_NEARER:
+                                                       cam_near = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_FARTHER:
+                                                       cam_far = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_PITCH_CCW:
+                                                       cam_rot_ccw.x = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_PITCH_CW:
+                                                       cam_rot_cw.x = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_YAW_CCW:
+                                                       cam_rot_ccw.y = 1.0f;
+                                                       break;
+                                               case Keymap::CAMERA_YAW_CW:
+                                                       cam_rot_cw.y = 1.0f;
+                                                       break;
+                                               case Keymap::EXIT:
+                                                       running = false;
+                                                       break;
+                                               default:
+                                               case Keymap::NONE:
+                                                       break;
+                                       }
+                                       break;
+                               case SDL_KEYUP:
+                                       switch (keymap.Lookup(event.key)) {
+                                               case Keymap::CAMERA_RIGHT:
+                                                       cam_fwd.x = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_LEFT:
+                                                       cam_rev.x = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_UP:
+                                                       cam_fwd.y = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_DOWN:
+                                                       cam_rev.y = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_BACK:
+                                                       cam_fwd.z = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_FORWARD:
+                                                       cam_rev.z = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_NEARER:
+                                                       cam_near = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_FARTHER:
+                                                       cam_far = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_PITCH_CCW:
+                                                       cam_rot_ccw.x = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_PITCH_CW:
+                                                       cam_rot_cw.x = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_YAW_CCW:
+                                                       cam_rot_ccw.y = 0.0f;
+                                                       break;
+                                               case Keymap::CAMERA_YAW_CW:
+                                                       cam_rot_cw.y = 0.0f;
+                                                       break;
+                                               default:
+                                               case Keymap::NONE:
+                                                       break;
+                                       }
+                                       break;
                                case SDL_QUIT:
                                        running = false;
                                        break;
@@ -73,6 +179,14 @@ int main(int argc, char *argv[]) {
                                        break;
                        }
                }
+
+               // update
+               float dt = (now - last) * 0.001f;
+               camera.Move((cam_fwd - cam_rev) * cam_speed * dt);
+               camera.BackOff((cam_far - cam_near) * cam_speed * dt);
+               camera.Rotate((cam_rot_ccw - cam_rot_cw) * cam_rot_speed * dt);
+
+               // render
                V = camera.View();
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                for (int z = 0; z < floor.VAODepth(); ++z) {
@@ -86,6 +200,8 @@ int main(int argc, char *argv[]) {
                        }
                }
                window.Flip();
+
+               last = now;
        }
 
        return 0;