diff --git a/FinalProject/camera.cpp b/FinalProject/camera.cpp index 9c0e83f..0951b2a 100644 --- a/FinalProject/camera.cpp +++ b/FinalProject/camera.cpp @@ -4,7 +4,7 @@ #include "camera.h" -// If no default input, set camera to (1, 1, 1) looking at (0, 0, 0) +// If no default input, set camera to (0, 0, 1) looking at (0, 0, 0) Camera::Camera() : Camera(defaultOrigin(), defaultTarget()) {} Camera::Camera(glm::vec3 position, glm::vec3 target) : _position(position) { @@ -46,4 +46,49 @@ void Camera::updateCameraState() { // Update up vector _up = glm::normalize(glm::cross(_right, _front)); -} \ No newline at end of file +} + +void Camera::rotate(glm::vec3 center, float deltaPitchAngle, float deltaYawAngle) { + if (deltaPitchAngle + _pitch > 89.0f) { + deltaPitchAngle = 89.0f - _pitch; + } + if (deltaPitchAngle + _pitch < -89.0f) { + deltaPitchAngle = -89.0f - _pitch; + } + // Get the normalized direction vector + glm::vec3 direction = glm::normalize(_position - center); + // Get the original distance from the center + float distance = glm::length(_position - center); + // Rotate the direction vector + glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(deltaPitchAngle), _right); + rotation = glm::rotate(rotation, glm::radians(deltaYawAngle), _worldUp); + direction = glm::normalize(glm::vec3(rotation * glm::vec4(direction, 1.0f))); + // Get new position + _position = center + direction * distance; + // Update the position + _pitch += deltaPitchAngle; + _yaw -= deltaYawAngle; + + updateCameraState(); +} + +void Camera::setRotation(glm::vec3 center, float pitchAngle, float yawAngle) { + if (pitchAngle > 89.0f) { + pitchAngle = 89.0f; + } + if (pitchAngle < -89.0f) { + pitchAngle = -89.0f; + } + // Get the direction vector + glm::vec3 direction = _position - center; + // Rotate the direction vector + glm::mat4 rotationMatrix = glm::rotate(glm::mat4(1.0f), glm::radians(pitchAngle), _right); + rotationMatrix = glm::rotate(rotationMatrix, glm::radians(yawAngle), _worldUp); + direction = glm::vec3(rotationMatrix * glm::vec4(direction, 1.0f)); + // Update the position + _position = center + direction; + _pitch = pitchAngle; + _yaw = yawAngle; + + updateCameraState(); +} diff --git a/FinalProject/camera.h b/FinalProject/camera.h index a8f416b..e1b0ee5 100644 --- a/FinalProject/camera.h +++ b/FinalProject/camera.h @@ -8,7 +8,7 @@ class Camera { public: - inline glm::vec3 defaultOrigin() { return glm::vec3(1.0f, 1.0f, 1.0f); } + inline glm::vec3 defaultOrigin() { return glm::vec3(0.0f, 0.0f, 1.0f); } inline glm::vec3 defaultTarget() { return glm::vec3(0.0f, 0.0f, 0.0f); } private: @@ -32,8 +32,11 @@ public: Camera(glm::vec3 position, float yaw, float pitch); public: + inline glm::vec3 front() const { return _front; } inline float zoomVal() const { return _zoom; } inline glm::mat4 viewMatrix(); + + inline glm::vec3 position() const { return _position; } public: inline void move(glm::vec2 offset); @@ -44,6 +47,8 @@ public: inline void setYaw(float angle); inline void rotate(float deltaPitchAngle, float deltaYawAngle); inline void setRotation(float pitchAngle, float yawAngle); + void rotate(glm::vec3 center, float deltaPitchAngle, float deltaYawAngle); + void setRotation(glm::vec3 center, float pitchAngle, float yawAngle); inline void zoom(float deltaZoom); inline void setZoom(float zoom); inline void push(float distance); @@ -87,7 +92,19 @@ inline void Camera::setYaw(float angle) { inline void Camera::rotate(float deltaPitchAngle, float deltaYawAngle) { _pitch += deltaPitchAngle; + if (_pitch > 89.0f) { + _pitch = 89.0f; + } + if (_pitch < -89.0f) { + _pitch = -89.0f; + } _yaw += deltaYawAngle; + if (_yaw > 360.0f) { + _yaw -= 360.0f; + } + if (_yaw < 0.0f) { + _yaw += 360.0f; + } updateCameraState(); } diff --git a/FinalProject/sceneviewer.cpp b/FinalProject/sceneviewer.cpp index 4b17423..2ddb15f 100644 --- a/FinalProject/sceneviewer.cpp +++ b/FinalProject/sceneviewer.cpp @@ -70,9 +70,7 @@ void SceneViewer::initializeGL() { Renderable backpack(backpackModel); _objects.push_back(backpack); - _camera.setPosition(glm::vec3(0.0f, 0.0f, 3.0f)); - _camera.setYaw(-90.0f); - _camera.setPitch(0.0f); + _camera.setPosition(glm::vec3(0.0f, 0.0f, 5.0f)); } void SceneViewer::resizeGL(int w, int h) { @@ -93,6 +91,8 @@ void SceneViewer::paintGL() { for (auto object : _objects) { object.render(_shaderProgram); } + + _shaderProgram.unbind(); } void SceneViewer::mousePressEvent(QMouseEvent* event) { @@ -122,8 +122,12 @@ void SceneViewer::mouseMoveEvent(QMouseEvent* event) { float yoffset = _lastMousePosition.y() - event->y(); // reversed since y-coordinates go from bottom to top float xmovement = xoffset * _cameraMovementSpeed; float ymovement = yoffset * _cameraMovementSpeed; - Logger::debug("Camera movement: " + std::to_string(xmovement) + ", " + std::to_string(ymovement)); + glm::vec3 cameraPrevPos = _camera.position(); _camera.move({ -xmovement, -ymovement }); + glm::vec3 cameraNewPos = _camera.position(); + _rotateCenter += cameraNewPos - cameraPrevPos; + Logger::debug("Camera moved to: " + std::to_string(_camera.position().x) + ", " + std::to_string(_camera.position().y) + ", " + std::to_string(_camera.position().z)); + Logger::debug("New center: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z)); break; } case Qt::MiddleButton: { @@ -134,8 +138,9 @@ void SceneViewer::mouseMoveEvent(QMouseEvent* event) { float pitch = yoffset * _cameraRotationSpeed; // Calculate yaw angle float yaw = xoffset * _cameraRotationSpeed; - Logger::debug("Camera rotation: " + std::to_string(pitch) + ", " + std::to_string(yaw)); - _camera.rotate(pitch, yaw); + _camera.rotate(_rotateCenter, pitch, -yaw); + Logger::debug("Camera rotated to: " + std::to_string(_camera.position().x) + ", " + std::to_string(_camera.position().y) + ", " + std::to_string(_camera.position().z)); + Logger::debug("Center at: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z)); break; } default: { @@ -155,6 +160,10 @@ void SceneViewer::wheelEvent(QWheelEvent* event) { float wheelOffset = event->angleDelta().y(); Logger::debug("Wheel offset: " + std::to_string(wheelOffset)); _camera.push(wheelOffset * _cameraPushSpeed); + glm::vec3 cameraFront = _camera.front(); + _rotateCenter += wheelOffset * _cameraPushSpeed * cameraFront; + Logger::debug("New camera position: " + std::to_string(_camera.position().x) + ", " + std::to_string(_camera.position().y) + ", " + std::to_string(_camera.position().z)); + Logger::debug("New center position: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z)); // Update the view update(); } diff --git a/FinalProject/sceneviewer.h b/FinalProject/sceneviewer.h index ed0f99f..a854b32 100644 --- a/FinalProject/sceneviewer.h +++ b/FinalProject/sceneviewer.h @@ -28,6 +28,8 @@ private: float _cameraMovementSpeed = 0.02f; float _cameraRotationSpeed = 0.3f; float _cameraPushSpeed = 0.02f; + // Rotate center + glm::vec3 _rotateCenter = glm::vec3(0.0f, 0.0f, 0.0f); // User Interaction flags section--------------------- QPoint _lastMousePosition;