From 9f404ab9bfee30e50f7fa6ba6bb8aec34a73b1e8 Mon Sep 17 00:00:00 2001 From: denizdiktas Date: Mon, 12 Jun 2023 11:32:05 +0300 Subject: [PATCH] Added Camera class & code refactor --- .../demo/earth/CMakeLists.txt | 6 +- Arrangement_on_surface_2/demo/earth/Camera.h | 58 ++++++++++++++ Arrangement_on_surface_2/demo/earth/main.cpp | 2 +- .../demo/earth/mainwidget.cpp | 80 +++++++------------ .../demo/earth/mainwidget.h | 16 ++-- 5 files changed, 102 insertions(+), 60 deletions(-) create mode 100644 Arrangement_on_surface_2/demo/earth/Camera.h diff --git a/Arrangement_on_surface_2/demo/earth/CMakeLists.txt b/Arrangement_on_surface_2/demo/earth/CMakeLists.txt index 0e75e34a180..500315fb7fb 100644 --- a/Arrangement_on_surface_2/demo/earth/CMakeLists.txt +++ b/Arrangement_on_surface_2/demo/earth/CMakeLists.txt @@ -17,14 +17,18 @@ qt_standard_project_setup() qt_add_executable(earth main.cpp mainwidget.cpp mainwidget.h + Camera.h ) + set_target_properties(earth PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE ) -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE") +if (MSVC) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE") +endif (MSVC) target_link_libraries(earth PRIVATE Qt6::Core diff --git a/Arrangement_on_surface_2/demo/earth/Camera.h b/Arrangement_on_surface_2/demo/earth/Camera.h new file mode 100644 index 00000000000..93c3e5c9657 --- /dev/null +++ b/Arrangement_on_surface_2/demo/earth/Camera.h @@ -0,0 +1,58 @@ + +#ifndef CAMERA_H +#define CAMERA_H + + +#include +#include + + +class Camera +{ +public: + + Camera() : + m_ux(1, 0, 0), + m_uy(0, 1, 0), + m_uz(0, 0, 1) + { + } + + void set_pos(const QVector3D& pos) { m_pos = pos; } + void set_pos(float x, float y, float z) { m_pos = QVector3D(x,y,z); } + + QMatrix4x4 get_view_matrix() const + { + QMatrix4x4 view; + const QVector3D center = m_pos - m_uz; + view.lookAt(m_pos, center, m_uy); + return view; + } + + // rotate the camera around its own axes + void rotate(float theta_around_x, float theta_around_y) + { + // rotate the camera around its x-axis + QMatrix4x4 rot; + rot.rotate(theta_around_x, m_ux); + m_pos = m_pos * rot; + m_uy = m_uy * rot; + m_uz = m_uz * rot; + + // rotate the camera around its y-axis + rot.setToIdentity(); + rot.rotate(theta_around_y, m_uy); + m_pos = m_pos * rot; + m_ux = m_ux * rot; + m_uz = m_uz * rot; + } + +private: + QVector3D m_pos; + QVector3D m_ux; + QVector3D m_uy; + QVector3D m_uz; +}; + + +#endif diff --git a/Arrangement_on_surface_2/demo/earth/main.cpp b/Arrangement_on_surface_2/demo/earth/main.cpp index 91144870b61..2da5819072b 100644 --- a/Arrangement_on_surface_2/demo/earth/main.cpp +++ b/Arrangement_on_surface_2/demo/earth/main.cpp @@ -23,7 +23,7 @@ int main(int argc, char *argv[]) format.setDepthBufferSize(24); QSurfaceFormat::setDefaultFormat(format); - app.setApplicationName("cube"); + app.setApplicationName("Earth"); app.setApplicationVersion("0.1"); #ifndef QT_NO_OPENGL MainWidget widget; diff --git a/Arrangement_on_surface_2/demo/earth/mainwidget.cpp b/Arrangement_on_surface_2/demo/earth/mainwidget.cpp index 2d01f6baf37..f5b7f910a57 100644 --- a/Arrangement_on_surface_2/demo/earth/mainwidget.cpp +++ b/Arrangement_on_surface_2/demo/earth/mainwidget.cpp @@ -9,6 +9,7 @@ #include #include + namespace { // vertex shader const char* vertex_shader_code = R"vs( @@ -89,63 +90,40 @@ void main() MainWidget::~MainWidget() { - // Make sure the context is current when deleting the texture - // and the buffers. - makeCurrent(); - doneCurrent(); + // Make sure the context is current when deleting the texture and the buffers. + makeCurrent(); + doneCurrent(); } -bool mouse_pressed = false; -QVector2D last_mouse_pos; void MainWidget::mousePressEvent(QMouseEvent *e) { - // Save mouse press position - m_mouse_press_position = QVector2D(e->position()); - - mouse_pressed = true; - last_mouse_pos = QVector2D(e->position()); + m_mouse_pressed = true; + m_last_mouse_pos = QVector2D(e->position()); } -QVector3D cam_pos(0, 0, 10); -QVector3D cam_ux(1, 0, 0); -QVector3D cam_uy(0, 1, 0); -QVector3D cam_uz(0, 0, 1); void MainWidget::mouseMoveEvent(QMouseEvent* e) { - //last_mouse_pos = QVector2D(e->position()); auto current_mouse_pos = QVector2D(e->position()); - if (mouse_pressed) - { - - auto diff = current_mouse_pos - last_mouse_pos; + if (m_mouse_pressed) + { + const auto diff = current_mouse_pos - m_last_mouse_pos; const float scale_factor = 0.1f; - auto angle = scale_factor * QVector2D(diff.y(), diff.x()); + const float theta_around_x = scale_factor * diff.y(); + const float theta_around_y = scale_factor * diff.x(); - // rotate the camera around its x-axis - QMatrix4x4 rot; - rot.rotate(angle.x(), cam_ux); - cam_pos = cam_pos * rot; - cam_uy = cam_uy * rot; - cam_uz = cam_uz * rot; - - // rotate the camera around its y-axis - rot.setToIdentity(); - rot.rotate(angle.y(), cam_uy); - cam_pos = cam_pos * rot; - cam_ux = cam_ux * rot; - cam_uz = cam_uz * rot; + m_camera.rotate(theta_around_x, theta_around_y); } - last_mouse_pos = current_mouse_pos; + m_last_mouse_pos = current_mouse_pos; } void MainWidget::mouseReleaseEvent(QMouseEvent *e) { - mouse_pressed = false; + m_mouse_pressed = false; } void MainWidget::timerEvent(QTimerEvent *) @@ -161,6 +139,7 @@ void MainWidget::initializeGL() glClearColor(0, 0, 0, 1); + m_camera.set_pos(0,0,10); init_geometry(); init_shader_program(); @@ -208,39 +187,39 @@ void MainWidget::add_shader(GLuint the_program, const char* shader_code, } void MainWidget::init_shader_program() { - shader = glCreateProgram(); - if (!shader) + m_shader = glCreateProgram(); + if (!m_shader) { std::cout << "error creating shader program!\n"; return; } - add_shader(shader, vertex_shader_code, GL_VERTEX_SHADER); + add_shader(m_shader, vertex_shader_code, GL_VERTEX_SHADER); //add_shader(shader, geometry_shader_code, GL_GEOMETRY_SHADER); - add_shader(shader, fragment_shader_code, GL_FRAGMENT_SHADER); + add_shader(m_shader, fragment_shader_code, GL_FRAGMENT_SHADER); GLint result = 0; GLchar elog[1024] = { 0 }; - glLinkProgram(shader); - glGetProgramiv(shader, GL_LINK_STATUS, &result); + glLinkProgram(m_shader); + glGetProgramiv(m_shader, GL_LINK_STATUS, &result); if (!result) { - glGetProgramInfoLog(shader, sizeof(elog), NULL, elog); + glGetProgramInfoLog(m_shader, sizeof(elog), NULL, elog); std::cout << "! error linking program:\n" << elog << std::endl; return; } - glValidateProgram(shader); - glGetProgramiv(shader, GL_VALIDATE_STATUS, &result); + glValidateProgram(m_shader); + glGetProgramiv(m_shader, GL_VALIDATE_STATUS, &result); if (!result) { - glGetProgramInfoLog(shader, sizeof(elog), NULL, elog); + glGetProgramInfoLog(m_shader, sizeof(elog), NULL, elog); std::cout << "! error validating program:\n" << elog << std::endl; return; } - m_uniform_mvp = glGetUniformLocation(shader, "MVP"); + m_uniform_mvp = glGetUniformLocation(m_shader, "MVP"); std::cout << "uniform loc = " << m_uniform_mvp << std::endl; } @@ -275,8 +254,9 @@ void MainWidget::paintGL() //const QVector3D eye(0, 10, 10), center(0, 0, 0), up(0, 1, 0); // view.lookAt(eye, center, up); - const QVector3D center(0, 0, 0); - view.lookAt(cam_pos, center, cam_uy); + //const QVector3D center(0, 0, 0); + //view.lookAt(camera.pos, center, cam_uy); + view = m_camera.get_view_matrix(); QMatrix4x4 model; //static float angle = 0; @@ -290,7 +270,7 @@ void MainWidget::paintGL() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glUseProgram(shader); + glUseProgram(m_shader); auto mvp = m_projection * view * model; glUniformMatrix4fv(m_uniform_mvp, 1, GL_FALSE, mvp.data()); diff --git a/Arrangement_on_surface_2/demo/earth/mainwidget.h b/Arrangement_on_surface_2/demo/earth/mainwidget.h index 3906e384ba4..63ca07edff5 100644 --- a/Arrangement_on_surface_2/demo/earth/mainwidget.h +++ b/Arrangement_on_surface_2/demo/earth/mainwidget.h @@ -15,7 +15,7 @@ #include #include #include - +#include "Camera.h" class Sphere; using OpenGLFunctionsBase = QOpenGLFunctions_3_3_Core; @@ -52,17 +52,17 @@ class MainWidget : public QOpenGLWidget, protected OpenGLFunctionsBase std::unique_ptr m_sphere; - GLuint shader; + GLuint m_shader; GLuint m_uniform_mvp; // uniform location for MVP-matrix in the shader - QBasicTimer m_timer; - + // camera & controls + Camera m_camera; + bool m_mouse_pressed = false; + QVector2D m_last_mouse_pos; QMatrix4x4 m_projection; - QVector2D m_mouse_press_position; - QVector3D m_rotation_axis; - qreal m_angular_speed = 0; - QQuaternion m_rotation; + + QBasicTimer m_timer; }; class Sphere : protected OpenGLFunctionsBase