aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/camera.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/camera.hpp')
-rw-r--r--src/camera.hpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/camera.hpp b/src/camera.hpp
new file mode 100644
index 0000000..59e6180
--- /dev/null
+++ b/src/camera.hpp
@@ -0,0 +1,217 @@
+/*
+* Basic camera class
+*
+* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
+*
+* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+*/
+
+#define GLM_FORCE_RADIANS
+#define GLM_FORCE_DEPTH_ZERO_TO_ONE
+#include <glm/glm.hpp>
+#include <glm/gtc/quaternion.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+class Camera
+{
+ float fov;
+ float znear, zfar;
+
+ void updateViewMatrix()
+ {
+ glm::mat4 rotM = glm::mat4(1.0f);
+ glm::mat4 transM;
+
+ rotM = glm::rotate(rotM, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
+ rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
+ rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
+
+ transM = glm::translate(glm::mat4(1.0f), position);
+
+ if (type == CameraType::firstperson)
+ matrices.view = rotM * transM;
+ else
+ matrices.view = transM * rotM;
+ }
+public:
+ enum CameraType { lookat, firstperson };
+ CameraType type = CameraType::lookat;
+
+ glm::vec3 rotation = glm::vec3();
+ glm::vec3 position = glm::vec3();
+
+ float rotationSpeed = 1.0f;
+ float movementSpeed = 1.0f;
+ float zoomSpeed = 0.5f;
+
+ struct
+ {
+ glm::mat4 perspective;
+ glm::mat4 view;
+ } matrices;
+
+ struct {
+ bool left = false;
+ bool right = false;
+ bool up = false;
+ bool down = false;
+ } keys;
+
+ bool moving()
+ {
+ return keys.left || keys.right || keys.up || keys.down;
+ }
+
+ float getNearClip() {
+ return znear;
+ }
+
+ float getFarClip() {
+ return zfar;
+ }
+
+ glm::vec3 getViewDirection () {
+ glm::vec3 camFront;
+ camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
+ camFront.y = sin(glm::radians(rotation.x));
+ camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
+ camFront = glm::normalize(camFront);
+ return camFront;
+ }
+
+ void setPerspective(float fov, float aspect, float znear, float zfar)
+ {
+ this->fov = fov;
+ this->znear = znear;
+ this->zfar = zfar;
+ matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
+ }
+
+ void updateAspectRatio(float aspect)
+ {
+ matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
+ }
+
+ void setPosition(glm::vec3 position)
+ {
+ this->position = position;
+ updateViewMatrix();
+ }
+
+ void setRotation(glm::vec3 rotation)
+ {
+ this->rotation = rotation;
+ updateViewMatrix();
+ }
+
+ void rotate(glm::vec3 delta)
+ {
+ this->rotation += delta;
+ updateViewMatrix();
+ }
+
+ void setTranslation(glm::vec3 translation)
+ {
+ this->position = translation;
+ updateViewMatrix();
+ }
+
+ void translate(glm::vec3 delta)
+ {
+ this->position += delta;
+ updateViewMatrix();
+ }
+
+ void update(float deltaTime)
+ {
+ if (type == CameraType::firstperson)
+ {
+ if (moving())
+ {
+ glm::vec3 camFront;
+ camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
+ camFront.y = sin(glm::radians(rotation.x));
+ camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
+ camFront = glm::normalize(camFront);
+
+ float moveSpeed = deltaTime * movementSpeed;
+
+ if (keys.up)
+ position += camFront * moveSpeed;
+ if (keys.down)
+ position -= camFront * moveSpeed;
+ if (keys.left)
+ position -= glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
+ if (keys.right)
+ position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
+
+ updateViewMatrix();
+ }
+ }
+ }
+
+ // Update camera passing separate axis data (gamepad)
+ // Returns true if view or position has been changed
+ bool updatePad(glm::vec2 axisLeft, glm::vec2 axisRight, float deltaTime)
+ {
+ bool retVal = false;
+
+ if (type == CameraType::firstperson)
+ {
+ // Use the common console thumbstick layout
+ // Left = view, right = move
+
+ const float deadZone = 0.0015f;
+ const float range = 1.0f - deadZone;
+
+ glm::vec3 camFront;
+ camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
+ camFront.y = sin(glm::radians(rotation.x));
+ camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
+ camFront = glm::normalize(camFront);
+
+ float moveSpeed = deltaTime * movementSpeed * 2.0f;
+ float rotSpeed = deltaTime * rotationSpeed * 50.0f;
+
+ // Move
+ if (fabsf(axisLeft.y) > deadZone)
+ {
+ float pos = (fabsf(axisLeft.y) - deadZone) / range;
+ position -= camFront * pos * ((axisLeft.y < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
+ retVal = true;
+ }
+ if (fabsf(axisLeft.x) > deadZone)
+ {
+ float pos = (fabsf(axisLeft.x) - deadZone) / range;
+ position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * pos * ((axisLeft.x < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
+ retVal = true;
+ }
+
+ // Rotate
+ if (fabsf(axisRight.x) > deadZone)
+ {
+ float pos = (fabsf(axisRight.x) - deadZone) / range;
+ rotation.y += pos * ((axisRight.x < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
+ retVal = true;
+ }
+ if (fabsf(axisRight.y) > deadZone)
+ {
+ float pos = (fabsf(axisRight.y) - deadZone) / range;
+ rotation.x -= pos * ((axisRight.y < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
+ retVal = true;
+ }
+ }
+ else
+ {
+ // todo: move code from example base class for look-at
+ }
+
+ if (retVal)
+ {
+ updateViewMatrix();
+ }
+
+ return retVal;
+ }
+
+};