diff --git a/FinalProject/boundary.h b/FinalProject/boundary.h index 7be63f3..49e3106 100644 --- a/FinalProject/boundary.h +++ b/FinalProject/boundary.h @@ -20,6 +20,7 @@ public: inline glm::vec3 bottomControlPoint() const { return _bottomControlPoint; } inline glm::vec3 topControlPoint() const { return _topControlPoint; } inline glm::vec3 bottomCenterPoint() const; + inline glm::vec3 centerPoint() const; bool hit(const Ray& ray) const; @@ -29,3 +30,7 @@ public: inline glm::vec3 Boundary::bottomCenterPoint() const { return glm::vec3((_bottomControlPoint.x + _topControlPoint.x) / 2.0f, _bottomControlPoint.y, (_bottomControlPoint.z + _topControlPoint.z) / 2.0f); } + +inline glm::vec3 Boundary::centerPoint() const { + return glm::vec3((_bottomControlPoint.x + _topControlPoint.x) / 2.0f, (_bottomControlPoint.y + _topControlPoint.y) / 2.0f, (_bottomControlPoint.z + _topControlPoint.z) / 2.0f); +} diff --git a/FinalProject/logger.cpp b/FinalProject/logger.cpp index a7859f2..4152c96 100644 --- a/FinalProject/logger.cpp +++ b/FinalProject/logger.cpp @@ -5,6 +5,7 @@ #include "logger.h" Logger::LogLevel Logger::_level = Logger::LogLevel::LOCALLOGLEVEL; +std::string Logger::_previous = ""; void Logger::setLogLevel(LogLevel level) { _level = level; diff --git a/FinalProject/logger.h b/FinalProject/logger.h index 8fd9a23..da6290b 100644 --- a/FinalProject/logger.h +++ b/FinalProject/logger.h @@ -2,7 +2,7 @@ #include -#define LOCALLOGLEVEL INFO +#define LOCALLOGLEVEL DEBUG class Logger { public: diff --git a/FinalProject/model.cpp b/FinalProject/model.cpp index 40ca790..fd6fc3c 100644 --- a/FinalProject/model.cpp +++ b/FinalProject/model.cpp @@ -190,13 +190,14 @@ void Model::render(const ShaderProgram& shader) const { } HitRecord Model::hit(const Ray& ray, const glm::mat4& modelMatrix) const { + HitRecord record = HitRecord(); for (unsigned int i = 0; i < _meshes.size(); i++) { HitRecord hitRecord = _meshes[i].hit(ray, modelMatrix); - if (hitRecord.hitted()) { - return hitRecord; + if (hitRecord.hitted() && hitRecord.t() < record.t()) { + record = hitRecord; } } - return HitRecord(); + return record; } Model* Model::copyToCurrentContext() const { diff --git a/FinalProject/modelsetter.cpp b/FinalProject/modelsetter.cpp index 9c4c1c1..fdaa065 100644 --- a/FinalProject/modelsetter.cpp +++ b/FinalProject/modelsetter.cpp @@ -448,14 +448,24 @@ void ModelSetter::update(Renderable* object) { _rotateY->setEnabled(); _rotateZ->setEnabled(); } - // Extract x, y, z axis rotation from rotation matrix - glm::mat4 rotationMatrix = object->rotation(); - float rotateX = glm::degrees(glm::asin(-rotationMatrix[1][2])); - float rotateY = glm::degrees(glm::atan(rotationMatrix[0][2] / rotationMatrix[2][2])); - float rotateZ = glm::degrees(glm::atan(rotationMatrix[1][0] / rotationMatrix[1][1])); - _rotateX->setValue(rotateX); - _rotateY->setValue(rotateY); - _rotateZ->setValue(rotateZ); + // Extract x, y, z axis rotation degree from rotation matrix + glm::quat quat(object->rotation()); + glm::vec3 euler = glm::eulerAngles(quat); + float x = glm::degrees(euler.x); + float y = glm::degrees(euler.y); + float z = glm::degrees(euler.z); + if (x < 0) { + x += 360; + } + if (y < 0) { + y += 360; + } + if (z < 0) { + z += 360; + } + _rotateX->setValue(x); + _rotateY->setValue(y); + _rotateZ->setValue(z); if (_object == nullptr) { _lightSwitch->setEnabled(); diff --git a/FinalProject/renderable.cpp b/FinalProject/renderable.cpp index 219558e..9f435ea 100644 --- a/FinalProject/renderable.cpp +++ b/FinalProject/renderable.cpp @@ -31,11 +31,11 @@ void Renderable::setPosition(glm::vec3 position) { } void Renderable::rotate(glm::vec3 axis, float deltaAngle) { - _rotation = glm::rotate(_rotation, deltaAngle, axis); + _rotation = glm::rotate(_rotation, glm::radians(deltaAngle), axis); } void Renderable::setRotation(glm::vec3 axis, float angle) { - _rotation = glm::rotate(glm::mat4(1.0f), angle, axis); + _rotation = glm::rotate(glm::mat4(1.0f), glm::radians(angle), axis); } void Renderable::scale(float deltaScale) { diff --git a/FinalProject/renderable.h b/FinalProject/renderable.h index eed1222..c95bd37 100644 --- a/FinalProject/renderable.h +++ b/FinalProject/renderable.h @@ -2,6 +2,7 @@ #include #include +#include #include "model.h" #include "illuminer.h" @@ -35,6 +36,7 @@ public: glm::vec3 position() const { return _position; } glm::mat4 rotation() const { return _rotation; } glm::vec3 scaleVal() const { return _scale; } + Model* model() const { return _model; } void setModel(Model* model); void move(glm::vec3 deltaVec); @@ -61,9 +63,23 @@ public: }; inline glm::mat4 Renderable::modelMatrix() const { + // Calculate rotate direction and angle from rotation matrix _rotation without glm + glm::vec3 axis; + float angle; + glm::quat quat(_rotation); + glm::vec3 axisAngle = glm::axis(quat); + axis = glm::normalize(axisAngle); + angle = glm::angle(quat); + //float rotateX = glm::degrees(glm::asin(-_rotation[1][2])); + //float rotateY = glm::degrees(glm::atan(_rotation[0][2] / _rotation[2][2])); + //float rotateZ = glm::degrees(glm::atan(_rotation[1][0] / _rotation[1][1])); + // Calculate model matrix glm::mat4 model = glm::mat4(1.0f); model = glm::translate(model, _position); - model = _rotation * model; + model = glm::rotate(model, angle, axis); + //model = glm::rotate(model, glm::radians(rotateX), glm::vec3(1.0f, 0.0f, 0.0f)); + //model = glm::rotate(model, glm::radians(rotateY), glm::vec3(0.0f, 1.0f, 0.0f)); + //model = glm::rotate(model, glm::radians(rotateZ), glm::vec3(0.0f, 0.0f, 1.0f)); model = glm::scale(model, _scale); return model; } \ No newline at end of file diff --git a/FinalProject/sceneviewer.cpp b/FinalProject/sceneviewer.cpp index 98725b2..7ef7f1d 100644 --- a/FinalProject/sceneviewer.cpp +++ b/FinalProject/sceneviewer.cpp @@ -300,10 +300,18 @@ void SceneViewer::mouseReleaseEvent(QMouseEvent* event) { } } else if (_pressedObject != nullptr && _pressedObject == _selectedObject) { - // Double select on an object, set in operating mode - _operatingObject = _selectedObject; - _hideBound = true; - startOperatingObject = true; + if (!_dragged) { + // Double select on an object, set in operating mode + _operatingObject = _selectedObject; + _hideBound = true; + startOperatingObject = true; + } + else { + // keep it selected + _dragged = false; + _hideBound = false; + _selectedObject->updateBoundary(); + } } else if (_dragged) { _dragged = false; @@ -347,9 +355,9 @@ void SceneViewer::mouseMoveEvent(QMouseEvent* event) { _hideBound = true; // Rotate around camera up glm::vec2 delta = glm::vec2(event->x() - _lastMousePosition.x(), event->y() - _lastMousePosition.y()); - _selectedObject->rotate(_camera.up(), delta.x * 0.01f); + _selectedObject->rotate(_camera.up(), delta.x * 1.0f); // Rotate around camera right - _selectedObject->rotate(_camera.right(), delta.y * 0.01f); + _selectedObject->rotate(_camera.right(), delta.y * 1.0f); emit onUpdate(_selectedObject); } break; @@ -490,34 +498,39 @@ void SceneViewer::moveOperatingObject(const Ray& ray) { } // Move the object so that the bottom center of the object is at the hit point else if (_stickToSurface) { - // Stick the bottom center of the model to the surface - - // Clear current translation and rotation while keeping scale - _operatingObject->setPosition(glm::vec3(0.0f)); - _operatingObject->setRotation(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f); - _operatingObject->updateBoundary(); - // Set the bottom center of the model at local origin glm::vec3 bottomCenter = _operatingObject->boundary().bottomCenterPoint(); - _operatingObject->move(-bottomCenter); + glm::vec3 modelCenter = _operatingObject->modelMatrix() * glm::vec4(glm::vec3(0.0f), 1.0f); // model center in world space // Rotate the model to align with the surface normal glm::vec3 normal = _hitRecord.normal(); glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); glm::vec3 axis = glm::cross(up, normal); float angle = glm::acos(glm::dot(up, normal)); - _operatingObject->rotate(axis, angle); + _operatingObject->setRotation(axis, angle); // Move the model to the hit point glm::vec3 hitPoint = _hitRecord.position(); - _operatingObject->move(hitPoint); + glm::vec3 newCenter = hitPoint + normal * (modelCenter.y - bottomCenter.y); + + // Move the model to the new center + _operatingObject->setPosition(newCenter); - // Update boundary + // Update the boundary _operatingObject->updateBoundary(); } else { // Move the object to the hit point - _operatingObject->setPosition(_hitRecord.position()); + Logger::debug("Hit point: " + std::to_string(_hitRecord.position().x) + ", " + std::to_string(_hitRecord.position().y) + ", " + std::to_string(_hitRecord.position().z)); + Logger::debug("Bottom center: " + std::to_string(_operatingObject->boundary().bottomCenterPoint().x) + ", " + std::to_string(_operatingObject->boundary().bottomCenterPoint().y) + ", " + std::to_string(_operatingObject->boundary().bottomCenterPoint().z)); + glm::vec3 target = _hitRecord.position(); + glm::vec3 modelCenter = _operatingObject->modelMatrix() * glm::vec4(glm::vec3(0.0f), 1.0f); // model center in world space + glm::vec3 bottomCenter = _operatingObject->modelMatrix() * glm::vec4(_operatingObject->model()->boundBox().bottomCenterPoint(), 1.0f); // model center in world space + glm::vec3 newCenter = target + modelCenter - bottomCenter; + _operatingObject->setPosition(newCenter); + + // Update the boundary + _operatingObject->updateBoundary(); } } @@ -559,7 +572,12 @@ void SceneViewer::deleteObject() { void SceneViewer::updateSetting(QPair setting) { makeCurrent(); if (setting.first == "stickSurface") { - _stickToSurface = true; + if (setting.second == "true") { + _stickToSurface = true; + } + else { + _stickToSurface = false; + } } else if (setting.first == "skybox") { if (_sky != nullptr) {