mirror of
https://github.com/Linloir/SceneEditor.git
synced 2025-12-17 15:38:11 +08:00
Update Camera
- Fix precision loss when rotating (by extracting the locked distance and multiply it back after rotating) - Implement a new way of rotating the camera: locked center distance
This commit is contained in:
parent
069aca1cf2
commit
1792c296c7
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "camera.h"
|
#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() : Camera(defaultOrigin(), defaultTarget()) {}
|
||||||
|
|
||||||
Camera::Camera(glm::vec3 position, glm::vec3 target) : _position(position) {
|
Camera::Camera(glm::vec3 position, glm::vec3 target) : _position(position) {
|
||||||
@ -47,3 +47,48 @@ void Camera::updateCameraState() {
|
|||||||
// Update up vector
|
// Update up vector
|
||||||
_up = glm::normalize(glm::cross(_right, _front));
|
_up = glm::normalize(glm::cross(_right, _front));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
class Camera {
|
class Camera {
|
||||||
public:
|
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); }
|
inline glm::vec3 defaultTarget() { return glm::vec3(0.0f, 0.0f, 0.0f); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -32,9 +32,12 @@ public:
|
|||||||
Camera(glm::vec3 position, float yaw, float pitch);
|
Camera(glm::vec3 position, float yaw, float pitch);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
inline glm::vec3 front() const { return _front; }
|
||||||
inline float zoomVal() const { return _zoom; }
|
inline float zoomVal() const { return _zoom; }
|
||||||
inline glm::mat4 viewMatrix();
|
inline glm::mat4 viewMatrix();
|
||||||
|
|
||||||
|
inline glm::vec3 position() const { return _position; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void move(glm::vec2 offset);
|
inline void move(glm::vec2 offset);
|
||||||
inline void setPosition(glm::vec3 position);
|
inline void setPosition(glm::vec3 position);
|
||||||
@ -44,6 +47,8 @@ public:
|
|||||||
inline void setYaw(float angle);
|
inline void setYaw(float angle);
|
||||||
inline void rotate(float deltaPitchAngle, float deltaYawAngle);
|
inline void rotate(float deltaPitchAngle, float deltaYawAngle);
|
||||||
inline void setRotation(float pitchAngle, float yawAngle);
|
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 zoom(float deltaZoom);
|
||||||
inline void setZoom(float zoom);
|
inline void setZoom(float zoom);
|
||||||
inline void push(float distance);
|
inline void push(float distance);
|
||||||
@ -87,7 +92,19 @@ inline void Camera::setYaw(float angle) {
|
|||||||
|
|
||||||
inline void Camera::rotate(float deltaPitchAngle, float deltaYawAngle) {
|
inline void Camera::rotate(float deltaPitchAngle, float deltaYawAngle) {
|
||||||
_pitch += deltaPitchAngle;
|
_pitch += deltaPitchAngle;
|
||||||
|
if (_pitch > 89.0f) {
|
||||||
|
_pitch = 89.0f;
|
||||||
|
}
|
||||||
|
if (_pitch < -89.0f) {
|
||||||
|
_pitch = -89.0f;
|
||||||
|
}
|
||||||
_yaw += deltaYawAngle;
|
_yaw += deltaYawAngle;
|
||||||
|
if (_yaw > 360.0f) {
|
||||||
|
_yaw -= 360.0f;
|
||||||
|
}
|
||||||
|
if (_yaw < 0.0f) {
|
||||||
|
_yaw += 360.0f;
|
||||||
|
}
|
||||||
updateCameraState();
|
updateCameraState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -70,9 +70,7 @@ void SceneViewer::initializeGL() {
|
|||||||
Renderable backpack(backpackModel);
|
Renderable backpack(backpackModel);
|
||||||
_objects.push_back(backpack);
|
_objects.push_back(backpack);
|
||||||
|
|
||||||
_camera.setPosition(glm::vec3(0.0f, 0.0f, 3.0f));
|
_camera.setPosition(glm::vec3(0.0f, 0.0f, 5.0f));
|
||||||
_camera.setYaw(-90.0f);
|
|
||||||
_camera.setPitch(0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneViewer::resizeGL(int w, int h) {
|
void SceneViewer::resizeGL(int w, int h) {
|
||||||
@ -93,6 +91,8 @@ void SceneViewer::paintGL() {
|
|||||||
for (auto object : _objects) {
|
for (auto object : _objects) {
|
||||||
object.render(_shaderProgram);
|
object.render(_shaderProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_shaderProgram.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneViewer::mousePressEvent(QMouseEvent* event) {
|
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 yoffset = _lastMousePosition.y() - event->y(); // reversed since y-coordinates go from bottom to top
|
||||||
float xmovement = xoffset * _cameraMovementSpeed;
|
float xmovement = xoffset * _cameraMovementSpeed;
|
||||||
float ymovement = yoffset * _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 });
|
_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;
|
break;
|
||||||
}
|
}
|
||||||
case Qt::MiddleButton: {
|
case Qt::MiddleButton: {
|
||||||
@ -134,8 +138,9 @@ void SceneViewer::mouseMoveEvent(QMouseEvent* event) {
|
|||||||
float pitch = yoffset * _cameraRotationSpeed;
|
float pitch = yoffset * _cameraRotationSpeed;
|
||||||
// Calculate yaw angle
|
// Calculate yaw angle
|
||||||
float yaw = xoffset * _cameraRotationSpeed;
|
float yaw = xoffset * _cameraRotationSpeed;
|
||||||
Logger::debug("Camera rotation: " + std::to_string(pitch) + ", " + std::to_string(yaw));
|
_camera.rotate(_rotateCenter, pitch, -yaw);
|
||||||
_camera.rotate(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;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@ -155,6 +160,10 @@ void SceneViewer::wheelEvent(QWheelEvent* event) {
|
|||||||
float wheelOffset = event->angleDelta().y();
|
float wheelOffset = event->angleDelta().y();
|
||||||
Logger::debug("Wheel offset: " + std::to_string(wheelOffset));
|
Logger::debug("Wheel offset: " + std::to_string(wheelOffset));
|
||||||
_camera.push(wheelOffset * _cameraPushSpeed);
|
_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 the view
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,8 @@ private:
|
|||||||
float _cameraMovementSpeed = 0.02f;
|
float _cameraMovementSpeed = 0.02f;
|
||||||
float _cameraRotationSpeed = 0.3f;
|
float _cameraRotationSpeed = 0.3f;
|
||||||
float _cameraPushSpeed = 0.02f;
|
float _cameraPushSpeed = 0.02f;
|
||||||
|
// Rotate center
|
||||||
|
glm::vec3 _rotateCenter = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
// User Interaction flags section---------------------
|
// User Interaction flags section---------------------
|
||||||
QPoint _lastMousePosition;
|
QPoint _lastMousePosition;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user