#include using namespace inferno; Camera::Camera() { mProjMatrix = glm::perspective( glm::radians(FOV), 1.0f, 0.1f, 1000.0f ); Roll = 0.0f; Pitch = 0.0f; Yaw = 0.0f; Position = {}; LookDirection = {}; mViewMatrix = {}; UpdateView(); } Camera::Camera(int w, int h) { mProjMatrix = glm::perspective(glm::radians(FOV), (float)w / (float)h, 0.1f, 1000.0f); Roll = 0.0f; Pitch = 0.0f; Yaw = 0.0f; Position = {}; LookDirection = {}; mViewMatrix = {}; UpdateView(); } void Camera::UpdateView() { // roll can be removed glm::mat4 matRoll = glm::mat4(1.0f); //identity matrix glm::mat4 matPitch = glm::mat4(1.0f);//identity matrix glm::mat4 matYaw = glm::mat4(1.0f); //identity matrix // roll, pitch and yaw matRoll = glm::rotate(matRoll, Roll, glm::vec3(0.0f, 0.0f, 1.0f)); matPitch = glm::rotate(matPitch, Pitch, glm::vec3(1.0f, 0.0f, 0.0f)); matYaw = glm::rotate(matYaw, Yaw, glm::vec3( 0.0f, 1.0f, 0.0f)); glm::mat4 rotate = matRoll * matPitch * matYaw; glm::mat4 translate = glm::mat4(1.0f); translate = glm::translate(translate, -Position); mViewMatrix = rotate * translate; // Work out Look Vector glm::mat4 inverseView = glm::inverse(mViewMatrix); LookDirection.x = inverseView[2][0]; LookDirection.y = inverseView[2][1]; LookDirection.z = inverseView[2][2]; } glm::mat4 Camera::GetViewMatrix() { return mViewMatrix; } glm::mat4 Camera::GetProjectionMatrix() { return mProjMatrix; } void Camera::UpdateProjection(int width, int height) { mViewport = {width, height}; mProjMatrix = glm::perspective(glm::radians(FOV), (float)width / (float)height, 0.1f, 1000.0f); } void Camera::UpdateProjection() { mProjMatrix = glm::perspective(glm::radians(FOV), mViewport.x / mViewport.y, 0.1f, 1000.0f); } void Camera::MoveCamera(uint8_t posDelta) { if (posDelta == 0) return; // Rotate by camera direction glm::vec3 delta(0.0f); glm::mat2 rotate { cos(Yaw), -sin(Yaw), sin(Yaw), cos(Yaw) }; glm::vec2 f(0.0, 1.0); f = f * rotate; if (posDelta & 0x80) { delta.z -= f.y; delta.x -= f.x; } if (posDelta & 0x20) { delta.z += f.y; delta.x += f.x; } if (posDelta & 0x40) { delta.z += f.x; delta.x += -f.y; } if (posDelta & 0x10) { delta.z -= f.x; delta.x -= -f.y; } if (posDelta & 0x8) { delta.y += 1; } if (posDelta & 0x4) { delta.y -= 1; } // get current view matrix glm::mat4 mat = GetViewMatrix(); glm::vec3 forward(mat[0][2], mat[1][2], mat[2][2]); glm::vec3 strafe(mat[0][0], mat[1][0], mat[2][0]); // forward vector must be negative to look forward. // read :http://in2gpu.com/2015/05/17/view-matrix/ Position += delta * CameraSpeed; // update the view matrix UpdateView(); } void Camera::MouseMoved(glm::vec2 mouseDelta) { if (glm::length(mouseDelta) == 0) return; // note that yaw and pitch must be converted to radians. // this is done in UpdateView() by glm::rotate Yaw += MouseSensitivity * (mouseDelta.x / 100); Pitch += MouseSensitivity * (mouseDelta.y / 100); Pitch = glm::clamp(Pitch, -M_PI / 2, M_PI / 2); UpdateView(); } void Camera::UpdatePosition(glm::vec3 position) { Position = position; UpdateView(); } void Camera::UpdateEulerLookDirection(float roll, float pitch, float yaw) { Roll = roll; Pitch = pitch; Yaw = yaw; LookDirection.x = cos(Yaw) * cos(Pitch); LookDirection.y = sin(Yaw) * cos(Pitch); LookDirection.z = sin(Pitch); UpdateView(); } void Camera::UpdateLookDirection(glm::vec3 lookDirection) { LookDirection = lookDirection; Pitch = asin(-lookDirection.y); Yaw = atan2(lookDirection.x, lookDirection.z); UpdateView(); }