Merge branch 'master' into boundingBox

This commit is contained in:
Liu Yuming 2022-12-14 17:06:51 +08:00 committed by GitHub
commit 8fa81048c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 228 additions and 47 deletions

View File

@ -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) {
@ -46,4 +46,49 @@ 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();
}

View File

@ -3,9 +3,12 @@
#include <GLM/glm.hpp> #include <GLM/glm.hpp>
#include <GLM/ext/matrix_transform.hpp> #include <GLM/ext/matrix_transform.hpp>
#define CAMERA_MAX_ZOOM 90.0f
#define CAMERA_MIN_ZOOM 1.0f
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:
@ -16,11 +19,7 @@ private:
glm::vec3 _up; glm::vec3 _up;
float _yaw = 0.0f; float _yaw = 0.0f;
float _pitch = 0.0f; float _pitch = 0.0f;
float _zoom = 90.0f; float _zoom = 45.0f;
private:
// Camera settings
float _moveStep = 1.0f;
private: private:
// World settings // World settings
@ -33,27 +32,36 @@ public:
Camera(glm::vec3 position, float yaw, float pitch); Camera(glm::vec3 position, float yaw, float pitch);
public: public:
inline float zoom() const { return _zoom; } inline glm::vec3 front() const { return _front; }
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::vec3 direction, float step); inline void move(glm::vec2 offset);
inline void setPosition(glm::vec3 position); inline void setPosition(glm::vec3 position);
inline void pitch(float deltaAngle); inline void pitch(float deltaAngle);
inline void setPitch(float angle); inline void setPitch(float angle);
inline void yaw(float deltaAngle); inline void yaw(float deltaAngle);
inline void setYaw(float angle); 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);
private: private:
void updateCameraState(); void updateCameraState();
}; };
inline glm::mat4 Camera::viewMatrix() { inline void Camera::move(glm::vec2 offset) {
return glm::lookAt(_position, _position + _front, _up); // Offset describe the movement on the xy plane in the camera's coordinate system
} // Should convert to the movement of position vector in world coordinate system
glm::vec3 worldSpaceOffset = offset.x * _right + offset.y * _up;
inline void Camera::move(glm::vec3 direction, float step) { _position += worldSpaceOffset;
_position += direction * step;
updateCameraState(); updateCameraState();
} }
@ -81,3 +89,58 @@ inline void Camera::setYaw(float angle) {
_yaw = angle; _yaw = angle;
updateCameraState(); updateCameraState();
} }
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();
}
inline void Camera::setRotation(float pitchAngle, float yawAngle) {
_pitch = pitchAngle;
_yaw = yawAngle;
updateCameraState();
}
inline void Camera::zoom(float deltaZoom) {
_zoom += deltaZoom;
if (_zoom > CAMERA_MAX_ZOOM) {
_zoom = CAMERA_MAX_ZOOM;
}
else if (_zoom < CAMERA_MIN_ZOOM) {
_zoom = CAMERA_MIN_ZOOM;
}
updateCameraState();
}
inline void Camera::setZoom(float zoom) {
_zoom = zoom;
if (_zoom > CAMERA_MAX_ZOOM) {
_zoom = CAMERA_MAX_ZOOM;
}
else if (_zoom < CAMERA_MIN_ZOOM) {
_zoom = CAMERA_MIN_ZOOM;
}
updateCameraState();
}
inline void Camera::push(float distance) {
_position += distance * _front;
updateCameraState();
}
inline glm::mat4 Camera::viewMatrix() {
return glm::lookAt(_position, _position + _front, _up);
}

View File

@ -55,22 +55,6 @@ void SceneViewer::initializeGL() {
Logger::info("Currently running on OpenGL version: " + std::string((const char*)glGetString(GL_VERSION))); Logger::info("Currently running on OpenGL version: " + std::string((const char*)glGetString(GL_VERSION)));
_vao.ensureInitialized();
Logger::info("Vertex Array Object initialized");
vector<Vertex> vertices = {
{ { -0.5f, -0.5f, 0.0f } },
{ { 0.5f, -0.5f, 0.0f } },
{ { 0.0f, 0.5f, 0.0f } }
};
VertexBufferObject vbo(vertices);
Logger::info("Vertex Buffer Object initialized");
_vao.bindVertexBufferObject(vbo);
_vao.setVertexAttributePointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
_vao.enableVertexAttribute(0);
Logger::info("Vertex Buffer Object bound to Vertex Array Object");
_shaderProgram.ensureInitialized(); _shaderProgram.ensureInitialized();
Logger::info("Shader Program initialized"); Logger::info("Shader Program initialized");
@ -83,20 +67,11 @@ void SceneViewer::initializeGL() {
Model* backpackModel = new Model("D:/code/ComputerGraphic/SceneEditor/obj/nanosuit/nanosuit.obj"); Model* backpackModel = new Model("D:/code/ComputerGraphic/SceneEditor/obj/nanosuit/nanosuit.obj");
Logger::info("Model loaded"); Logger::info("Model loaded");
Renderable renderable(backpackModel); Renderable backpack(backpackModel);
_objects.push_back(backpackModel); _objects.push_back(backpack);
renderable.move(glm::vec3(100.0f, 0.0f, 0.0f));
renderable.rotate(glm::vec3(0, 1, 0), 3.1415926f/2);
renderable.check_boundary();
auto t1 = renderable.get_lower_boundary();
auto t2 = renderable.get_upper_boundary();
_camera.setPosition(glm::vec3(0.0f, 15.0f, 8.0f));
_camera.setYaw(-90.0f);
_camera.setPitch(-30.0f);
_camera.setPosition(glm::vec3(0.0f, 0.0f, 5.0f));
} }
@ -111,11 +86,86 @@ void SceneViewer::paintGL() {
// Set view and projection matrices // Set view and projection matrices
glm::mat4 view = _camera.viewMatrix(); glm::mat4 view = _camera.viewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(_camera.zoom()), (float)width() / (float)height(), 0.1f, 100.0f); glm::mat4 projection = glm::perspective(glm::radians(_camera.zoomVal()), (float)width() / (float)height(), 0.1f, 100.0f);
_shaderProgram.setUniform("view", view); _shaderProgram.setUniform("view", view);
_shaderProgram.setUniform("projection", projection); _shaderProgram.setUniform("projection", projection);
for (auto object : _objects) { for (auto object : _objects) {
object.render(_shaderProgram); object.render(_shaderProgram);
} }
}
_shaderProgram.unbind();
}
void SceneViewer::mousePressEvent(QMouseEvent* event) {
Logger::debug("Mouse pressed at: " + std::to_string(event->x()) + ", " + std::to_string(event->y()));
if (event->button() == Qt::LeftButton) {
// TODO: Hit test on objects
}
else {
_lastMousePosition = event->pos();
}
}
void SceneViewer::mouseMoveEvent(QMouseEvent* event) {
Logger::debug("Mouse moved with offset: " + std::to_string(event->x() - _lastMousePosition.x()) + ", " + std::to_string(event->y() - _lastMousePosition.y()));
// Check the type of button pressed
switch (event->buttons()) {
case Qt::LeftButton: {
// Move the selected object
if (_selectedObject != nullptr) {
// TODO: move the selected object
}
break;
}
case Qt::RightButton: {
// Move the camera
float xoffset = event->x() - _lastMousePosition.x();
float yoffset = _lastMousePosition.y() - event->y(); // reversed since y-coordinates go from bottom to top
float xmovement = xoffset * _cameraMovementSpeed;
float ymovement = yoffset * _cameraMovementSpeed;
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: {
// Rotate the camera
float xoffset = event->x() - _lastMousePosition.x();
float yoffset = _lastMousePosition.y() - event->y(); // reversed since y-coordinates go from bottom to top
// Calculate pitch angle
float pitch = yoffset * _cameraRotationSpeed;
// Calculate yaw angle
float yaw = xoffset * _cameraRotationSpeed;
_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: {
Logger::warning("Unknown mouse button input");
Logger::warning("Mouse button: " + std::to_string(event->buttons()));
break;
}
}
// Update the last mouse position
_lastMousePosition = event->pos();
// Update the view
update();
}
void SceneViewer::wheelEvent(QWheelEvent* event) {
// Zoom in or out
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();
}

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <qwidget.h> #include <qwidget.h>
#include <qevent.h>
#include <qopenglfunctions.h> #include <qopenglfunctions.h>
#include <QtOpenGLWidgets/qopenglwidget.h> #include <QtOpenGLWidgets/qopenglwidget.h>
@ -17,17 +18,36 @@ class SceneViewer : public QOpenGLWidget, protected QOpenGLFunctions
Q_OBJECT Q_OBJECT
private: private:
// OpenGL section-------------------------------------
// List of objects currently in the scene
std::vector<Renderable> _objects; std::vector<Renderable> _objects;
// Shader program for objects
ShaderProgram _shaderProgram = ShaderProgram::empty(); ShaderProgram _shaderProgram = ShaderProgram::empty();
VertexArrayObject _vao = VertexArrayObject::empty(); // Main camera
Camera _camera; Camera _camera;
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;
Renderable* _selectedObject = nullptr;
public: public:
SceneViewer(QWidget* parent = 0); SceneViewer(QWidget* parent = 0);
~SceneViewer(); ~SceneViewer();
protected: protected:
// OpenGL functions
virtual void initializeGL() override; virtual void initializeGL() override;
virtual void paintGL() override; virtual void paintGL() override;
virtual void resizeGL(int w, int h) override; virtual void resizeGL(int w, int h) override;
// Mouse events
virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void wheelEvent(QWheelEvent* event) override;
}; };

View File

@ -25,6 +25,9 @@ Texture::Texture(TextureType type, std::string path) {
OPENGL_FUNCTIONS->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); OPENGL_FUNCTIONS->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
OPENGL_FUNCTIONS->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); OPENGL_FUNCTIONS->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Set stbi to reverse the y-axis
stbi_set_flip_vertically_on_load(true);
// Load image, create texture and generate mipmaps // Load image, create texture and generate mipmaps
int width, height, nrChannels; int width, height, nrChannels;
unsigned char* data = stbi_load(path.c_str(), &width, &height, &nrChannels, 0); unsigned char* data = stbi_load(path.c_str(), &width, &height, &nrChannels, 0);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 MiB

After

Width:  |  Height:  |  Size: 5.2 MiB