diff --git a/include/camera.h b/include/camera.h new file mode 100644 index 0000000..f8c6628 --- /dev/null +++ b/include/camera.h @@ -0,0 +1,94 @@ +#pragma once +#include + +class Camera +{ +public: + + glm::vec3 &getPosition() { return position; } + + glm::ivec3 getPositionInWorld() + { + glm::ivec3 p = position; + + if (position.x < 0) + { + p.x--; + } + + if(position.y < 0) + { + p.y--; + } + + if(position.z < 0) + { + p.z--; + } + + return p; + } + + glm::vec3 getViewDirection(); + + //full view transform matrix + glm::mat4 getProjectionViewMatrix(); + + //view matrix + glm::mat4 getViewMatrix(); + + //just the projection matrix + glm::mat4 getProjectionMatrix(); + + void rotateCamera(glm::vec2 v) { rotateCamera(v.x, v.y); } + void rotateCamera(float x, float y); + + void updateAspectRatio(float w, float h) + { + aspectRatio = w / h; + } + + virtual void move(glm::vec3 direction) = 0; + + +protected: + + glm::vec3 position = {}; + glm::vec3 upVector = { 0,1,0 }; + + glm::vec2 viewAngle = {}; + + float fovRadians = glm::radians(100.f); + float closePlane = 0.1f; + float farPlane = 100.f; + float aspectRatio = 1.f; + +}; + + +//just moves in the direction without taking into acount it's orientation +class KinematicCamera : public Camera +{ +public: + + virtual void move(glm::vec3 direction) override { position += direction; }; + + +}; + +//moves in the direction of the orientation but stays at the same height +class CreativeModeCamera: public Camera +{ +public: + + virtual void move(glm::vec3 direction) override; +}; + +//just moves in the direction of the orientation +class FlyCamera: public Camera +{ +public: + + virtual void move(glm::vec3 direction) override; + +}; diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 0000000..2118af3 --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,104 @@ +#include "camera.h" +#define GLM_ENABLE_EXPERIMENTAL +#include "glm/gtc/matrix_transform.hpp" +#include +#include +#include + +glm::mat4 Camera::getProjectionViewMatrix() +{ + return getProjectionMatrix() * getViewMatrix(); +} + +glm::mat4 Camera::getViewMatrix() +{ + return glm::lookAt({0,0,0}, getViewDirection(), upVector); +} + +glm::mat4 Camera::getProjectionMatrix() +{ + return glm::perspective(fovRadians, + aspectRatio, closePlane, farPlane); +} + +glm::vec3 Camera::getViewDirection() +{ + glm::vec3 viewDirection = {0,0,-1}; + + //now we rotate by y vector + viewDirection = glm::mat3(glm::rotate(viewAngle.x, upVector)) * viewDirection; + + glm::vec3 vectorToTheRight = glm::cross(viewDirection, upVector); + + //now we rotate by x vector + viewDirection = glm::mat3(glm::rotate(viewAngle.y, vectorToTheRight)) * viewDirection; + + + viewDirection = glm::normalize(viewDirection); + + return viewDirection; +} + +void Camera::rotateCamera(float x, float y) +{ + if(!x && !y) + { + return; + } + + x *= -1; + y *= -1; + + //float speed = glm::radians(10.f); + float speed = 0.10; + + viewAngle += glm::vec2{x, y} *speed; + + viewAngle.y = glm::clamp(viewAngle.y, glm::radians(-89.f), glm::radians(89.f)); + +} + +void CreativeModeCamera::move(glm::vec3 direction) +{ + + glm::vec3 m = {}; + m.y = direction.y; + + glm::vec3 moveFront = direction; + + if (direction.x || direction.z) + { + glm::vec3 v = getViewDirection(); + v.y = 0; + m -= glm::normalize(v) * direction.z; + m += glm::normalize(glm::cross(v, upVector)) * direction.x; + } + + + position += m; + +} + +void FlyCamera::move(glm::vec3 direction) +{ + + glm::vec3 m = {}; + m.y = direction.y; + + glm::vec3 moveFront = direction; + + if (direction.x || direction.z || direction.y) + { + glm::vec3 v = getViewDirection(); + + glm::vec3 vectorToTheRight = glm::cross(v, upVector); + + m -= glm::normalize(v) * direction.z; + m += glm::normalize(glm::cross(v, upVector)) * direction.x; + m -= glm::normalize(glm::cross(v, vectorToTheRight)) * direction.y; + + } + + position += m; + +} \ No newline at end of file