From 98a1321af2dd5b79c3109d69c4eb2b1972730e8a Mon Sep 17 00:00:00 2001 From: Linloir <3145078758@qq.com> Date: Sun, 18 Dec 2022 17:30:46 +0800 Subject: [PATCH] [CORE][ADD] Hit Test --- FinalProject/hitrecord.h | 6 ++-- FinalProject/mesh.cpp | 2 +- FinalProject/sceneviewer.cpp | 68 ++++++++++++++++++++---------------- FinalProject/sceneviewer.h | 10 +++--- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/FinalProject/hitrecord.h b/FinalProject/hitrecord.h index 1a44c7b..da38ad3 100644 --- a/FinalProject/hitrecord.h +++ b/FinalProject/hitrecord.h @@ -5,15 +5,17 @@ class HitRecord { private: bool _hitted; + float _t; glm::vec3 _position = glm::vec3(0.0f); glm::vec3 _normal = glm::vec3(0.0f); public: - HitRecord() : _hitted(false) {} - HitRecord(glm::vec3 position, glm::vec3 normal) : _hitted(true), _position(position), _normal(normal) {} + HitRecord() : _hitted(false), _t(std::numeric_limits::max()) {} + HitRecord(float t, glm::vec3 position, glm::vec3 normal) : _hitted(true), _t(t), _position(position), _normal(normal) {} public: inline bool hitted() const { return _hitted; } + inline float t() const { return _t; } inline glm::vec3 position() const { return _position; } inline glm::vec3 normal() const { return _normal; } }; diff --git a/FinalProject/mesh.cpp b/FinalProject/mesh.cpp index 7edf097..35402b0 100644 --- a/FinalProject/mesh.cpp +++ b/FinalProject/mesh.cpp @@ -83,7 +83,7 @@ HitRecord Mesh::hit(const Ray& ray) const { // Hit glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2)); glm::vec3 hitPoint = ray.origin() + t * ray.direction(); - return HitRecord(hitPoint, normal); + return HitRecord(t, hitPoint, normal); } } return HitRecord(); diff --git a/FinalProject/sceneviewer.cpp b/FinalProject/sceneviewer.cpp index 120f99e..c0fb943 100644 --- a/FinalProject/sceneviewer.cpp +++ b/FinalProject/sceneviewer.cpp @@ -11,6 +11,8 @@ SceneViewer::SceneViewer(QWidget* parent) : QOpenGLWidget(parent) { + // Set mouse tracking + setMouseTracking(true); // OpenGL initialize QSurfaceFormat format; format.setProfile(QSurfaceFormat::CoreProfile); @@ -57,6 +59,33 @@ void SceneViewer::extractShaderResorce(const QString& shaderName) { QFile::setPermissions(shaderTempPath, QFile::ReadOwner | QFile::WriteOwner); } +void SceneViewer::hitTest(const Ray& ray) { + HitRecord newRecord = HitRecord(); + Renderable* newObject = nullptr; + int newObjectIndex = -1; + for (int i = 0; i < _objects.size(); i++) { + Logger::debug("Testing object " + std::to_string(i)); + Renderable* obj = _objects[i]; + HitRecord hitRecord = obj->hit(ray); + if (hitRecord.hitted()) { + Logger::debug("Hitted object " + std::to_string(i)); + } + else { + Logger::debug("Missed object " + std::to_string(i)); + } + if (hitRecord.hitted() && hitRecord.t() < newRecord.t()) { + newRecord = hitRecord; + newObject = obj; + newObjectIndex = i; + } + } + if (newRecord.hitted()) { + Logger::debug("Hit test hitted object with index " + std::to_string(newObjectIndex)); + } + _hitRecord = newRecord; + _hoveredObject = newObject; +} + void SceneViewer::initializeGL() { initializeOpenGLFunctions(); @@ -95,10 +124,10 @@ void SceneViewer::initializeGL() { Model* model = new Model("E:\\Repositories\\CollegeProjects\\CGAssignments\\FinalProject\\Models\\backpack\\backpack.obj"); Renderable* backpack = new Renderable(model); + backpack->move(glm::vec3(-5.0f, -2.0f, -2.0f)); _objects.push_back(backpack); Renderable* backpack2 = new Renderable(model); - backpack2->move(glm::vec3(-5.0f, -2.0f, -2.0f)); backpack2->makeLight(); backpack2->originalLight()->setIdealDistance(500); _objects.push_back(backpack2); @@ -173,9 +202,6 @@ void SceneViewer::mousePressEvent(QMouseEvent* event) { } void SceneViewer::mouseMoveEvent(QMouseEvent* event) { - if (event->buttons() != Qt::NoButton) { - 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: { @@ -212,6 +238,14 @@ void SceneViewer::mouseMoveEvent(QMouseEvent* event) { Logger::debug("Center at: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z)); break; } + case Qt::NoButton: { + // If no button pressed, do hit test and move the current object if selected + float relX = (float)event->x() / (float)width(); + float relY = 1 - (float)event->y() / (float)height(); + Ray ray = _camera.generateRay(glm::vec2(relX, relY), (float)width() / (float)height()); + hitTest(ray); + break; + } default: { Logger::warning("Unknown mouse button input"); Logger::warning("Mouse button: " + std::to_string(event->buttons())); @@ -236,29 +270,3 @@ void SceneViewer::wheelEvent(QWheelEvent* event) { // Update the view parentWidget()->update(); } - -void SceneViewer::showEvent(QShowEvent* event) { - // Call show event of super class - QOpenGLWidget::showEvent(event); - - if (_initialized) { - return; - } - - //// Create mask for rounded corner - //QPainterPath mask; - //mask.addRoundedRect(rect(), _cornerRadius, _cornerRadius); - //setMask(mask.toFillPolygon().toPolygon()); - - _initialized = true; -} - -void SceneViewer::resizeEvent(QResizeEvent* event) { - // Call resize event of super class - QOpenGLWidget::resizeEvent(event); - - //// Create mask for rounded corner - //QPainterPath mask; - //mask.addRoundedRect(rect(), _cornerRadius, _cornerRadius); - //setMask(mask.toFillPolygon().toPolygon()); -} diff --git a/FinalProject/sceneviewer.h b/FinalProject/sceneviewer.h index 4c35136..99e9f37 100644 --- a/FinalProject/sceneviewer.h +++ b/FinalProject/sceneviewer.h @@ -37,9 +37,14 @@ private: // Rotate center glm::vec3 _rotateCenter = glm::vec3(0.0f, 0.0f, 0.0f); + // User preferences + bool _stickToSurface = false; // whether to rotate the object to the normal of the hitted surface + // User Interaction flags section--------------------- QPoint _lastMousePosition; + Renderable* _hoveredObject = nullptr; Renderable* _selectedObject = nullptr; + HitRecord _hitRecord; // UI interface control const int _cornerRadius = 10; @@ -51,6 +56,7 @@ public: private: void extractShaderResorce(const QString& shaderName); + void hitTest(const Ray& ray); protected: // OpenGL functions @@ -62,8 +68,4 @@ protected: virtual void mousePressEvent(QMouseEvent* event) override; virtual void mouseMoveEvent(QMouseEvent* event) override; virtual void wheelEvent(QWheelEvent* event) override; - - // UI update events - virtual void showEvent(QShowEvent* event) override; - virtual void resizeEvent(QResizeEvent* event) override; }; \ No newline at end of file