--- /dev/null
+#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);
+}
+
+}
--- /dev/null
+#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
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;
+ }
}
}
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;
};
, 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)) {
#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"
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;
}
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;
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) {
}
}
window.Flip();
+
+ last = now;
}
return 0;