From 4c302f3e79996996a67dd1e026069cc4fe72dd42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0toura=C4=8D?= <525032@mail.muni.cz> Date: Wed, 8 May 2024 13:10:35 +0200 Subject: [PATCH] collision detection uses spheres, add connecting to cardinal directions --- src/edit/include/edit/editor.hpp | 2 +- src/edit/src/editor.cpp | 50 +++++++++++++++++------------ src/gui/src/ui.cpp | 8 ++--- src/rofi/include/rofi/connector.hpp | 2 +- src/rofi/include/rofi/rofiworld.hpp | 2 +- src/rofi/src/connector.cpp | 25 ++++++++------- src/rofi/src/rofiworld.cpp | 30 +++++------------ src/utils/include/utils/math.hpp | 2 ++ 8 files changed, 59 insertions(+), 62 deletions(-) diff --git a/src/edit/include/edit/editor.hpp b/src/edit/include/edit/editor.hpp index 5a91cf6..e1e2a11 100644 --- a/src/edit/include/edit/editor.hpp +++ b/src/edit/include/edit/editor.hpp @@ -476,7 +476,7 @@ private: void addRofiWorldNodeTreeToScene(const std::vector<node_ptr> &node_tree); void removeRofiWorldNodeTreeFromScene(const std::vector<node_ptr> &node_tree); - bool rebuildRofiWorldNodeTree(module_ptr module, rofiworld_ptr rofiworld); + bool rebuildRofiWorldNodeTree(module_ptr module, node_ptr root_node, rofiworld_ptr rofiworld); bool rebuildRofiWorldNodeTree(voxel_ptr voxel, node_ptr root_component_node, rofiworld_ptr rofiworld); /* COLLISION DETECTION */ diff --git a/src/edit/src/editor.cpp b/src/edit/src/editor.cpp index a1853a0..c3a8493 100644 --- a/src/edit/src/editor.cpp +++ b/src/edit/src/editor.cpp @@ -2365,7 +2365,7 @@ void Editor::manipulateModule() return; if (mouse.just_released().contains("MouseLeft")) - rebuildRofiWorldNodeTree(selected_module, rofiworld); + rebuildRofiWorldNodeTree(selected_module, selected_module->getNode(), rofiworld); if (is_removing_module) removeModule(selected_module); @@ -2431,7 +2431,8 @@ void Editor::connectModule() // Connect else if (checkConnectModuleValid(selected_connectors.first, selected_connectors.second)) { - rebuildRofiWorldNodeTree(rofiworld->getModuleWithNode(selected_connectors.first->getNode()), rofiworld); + auto source_node = selected_connectors.first->getNode(); + rebuildRofiWorldNodeTree(rofiworld->getModuleWithNode(source_node), source_node, rofiworld); voxel_graph->joinConnectors(selected_connectors.first, selected_connectors.second); @@ -2463,8 +2464,7 @@ bool Editor::checkConnectModuleValid(const connector_ptr fst_connector, const co auto snd_node = snd_connector->getNode(); if (fst_connector->isFull() - || snd_connector->isFull() - || !face_each_other(fst_node, snd_node, rofi::enum_to_vec(rofi::side::z_neg))) + || snd_connector->isFull()) return false; float epsilon = 0.0001f; @@ -2477,23 +2477,31 @@ bool Editor::checkConnectModuleValid(const connector_ptr fst_connector, const co void Editor::teleportModulesByConnectors(const connector_ptr source_connector, const connector_ptr destination_connector) { - auto first_con_node = source_connector->getNode(); - auto first_parent = first_con_node->getRootParent().lock(); - auto second_world_pos = destination_connector->getNode()->getPositionWorld(); - auto first_con_parent_diff = first_con_node->getPositionWorld() - first_parent->getPositionWorld(); - first_parent->setPosVec(second_world_pos - first_con_parent_diff); + const auto source_node = source_connector->getNode(); + const auto destination_node = destination_connector->getNode(); + const auto source_parent = source_node->getRootParent().lock(); - auto destination_facing = -destination_connector->getNode()->getRotationAxisZWorld(); - auto destination_north = destination_connector->getNode()->getRotationAxisXWorld(); - auto source_facing = -first_con_node->getRotationAxisZWorld(); - auto source_north = source_connector->getNode()->getRotationAxisXWorld(); + //Rotation - // rotate to face each other - // first_parent->rotateRotationQuat(glm::angleAxis) - - // rotate to selected cardinality - // auto north_delta = glm::orientedAngle(source_north, destination_north, ) - // first_parent->rotateRotationQuat(glm::angleAxis()) + // Rotate to equal plane + const auto &source_facing = source_node->getRotationAxisZWorld(); + const auto &destination_facing = destination_node->getRotationAxisZWorld(); + source_parent->rotateRotationQuat(glm::rotation(source_facing, -destination_facing)); + // Rotate North to North + const auto &source_north = source_connector->getNode()->getRotationAxisXWorld(); + const auto &destination_north = destination_node->getRotationAxisXWorld(); + const auto oriented_angle = glm::orientedAngle(source_north, destination_north, destination_facing); + + source_parent->rotateRotationQuat(glm::angleAxis(oriented_angle, destination_facing)); + // Rotate to selected cardinality + // Have to use -radians because carinality is from destination to source and this needs to rotate the source to the destination + source_parent->rotateRotationQuat(glm::angleAxis(-glm::radians(rofi::cardinal_to_degree(selected_cardinality)), destination_facing)); + + // Translation + + const auto &destination_world_pos = destination_node->getPositionWorld(); + const auto &source_world_pos = source_node->getPositionWorld(); + source_parent->translatePosVec(destination_world_pos - source_world_pos); } void Editor::rotateModule(module_ptr selected_module, glm::vec3 &rotation_angles) @@ -2607,11 +2615,11 @@ void Editor::removeRofiWorldNodeTreeFromScene(const std::vector<node_ptr> &node_ { return std::find(node_tree.begin(), node_tree.end(), node) != node_tree.end(); }); } -bool Editor::rebuildRofiWorldNodeTree(module_ptr module, rofiworld_ptr rofiworld) +bool Editor::rebuildRofiWorldNodeTree(module_ptr module, node_ptr root_node, rofiworld_ptr rofiworld) { removeRofiWorldNodeTreeFromScene(rofiworld->getNodeTree()); - rofiworld->rebuildNodeTree(module); + rofiworld->rebuildNodeTree(module, root_node); addRofiWorldNodeTreeToScene(rofiworld->getNodeTree()); diff --git a/src/gui/src/ui.cpp b/src/gui/src/ui.cpp index 95cc086..fd507e7 100644 --- a/src/gui/src/ui.cpp +++ b/src/gui/src/ui.cpp @@ -625,10 +625,10 @@ void module_rotation_ui(const osi::Window &window, edit::UIData &data) ImGui::DragFloat("Step", &data.module_rotation_step, 0.25f, 0.0f, 90.0f, "%.3f", ImGuiSliderFlags_AlwaysClamp); - glm::vec3 euler_angles; - euler_angles.x = glm::orientedAngle(glm::vec3(0.0f, 0.0f, 1.0f), data.selected_module->getNode()->getRotationAxisZLocal(), glm::vec3(1.0f, 0.0f, 0.0f)); - euler_angles.y = glm::orientedAngle(glm::vec3(1.0f, 0.0f, 0.0f), data.selected_module->getNode()->getRotationAxisXLocal(), glm::vec3(0.0f, 1.0f, 0.0f)); - euler_angles.z = glm::orientedAngle(glm::vec3(1.0f, 0.0f, 0.0f), data.selected_module->getNode()->getRotationAxisXLocal(), glm::vec3(0.0f, 0.0f, 1.0f)); + glm::vec3 euler_angles = glm::eulerAngles(data.selected_module->getNode()->getRotationWorld()); + // euler_angles.x = glm::orientedAngle(glm::vec3(0.0f, 0.0f, 1.0f), data.selected_module->getNode()->getRotationAxisZLocal(), glm::vec3(1.0f, 0.0f, 0.0f)); + // euler_angles.y = glm::orientedAngle(glm::vec3(1.0f, 0.0f, 0.0f), data.selected_module->getNode()->getRotationAxisXLocal(), glm::vec3(0.0f, 1.0f, 0.0f)); + // euler_angles.z = glm::orientedAngle(glm::vec3(1.0f, 0.0f, 0.0f), data.selected_module->getNode()->getRotationAxisXLocal(), glm::vec3(0.0f, 0.0f, 1.0f)); euler_angles = glm::degrees(euler_angles); glm::vec3 prev_euler_angles = euler_angles; diff --git a/src/rofi/include/rofi/connector.hpp b/src/rofi/include/rofi/connector.hpp index fa8bbf7..9ee57d9 100644 --- a/src/rofi/include/rofi/connector.hpp +++ b/src/rofi/include/rofi/connector.hpp @@ -47,7 +47,7 @@ public: static connector_ptr copy(connector_ptr other_connector); static bool shares_module_link(connector_ptr fst_connector, connector_ptr snd_connector); - static cardinal get_mutual_orientation(connector_ptr fst_connector, connector_ptr snd_connector); + static cardinal get_mutual_orientation(connector_ptr source_connector, connector_ptr destination_connector); bool isFull() const { return !connection.first.expired() && !connection.second.expired(); } bool isEmpty() const { return connection.first.expired() && connection.second.expired(); } diff --git a/src/rofi/include/rofi/rofiworld.hpp b/src/rofi/include/rofi/rofiworld.hpp index ba1ac0a..613dffe 100644 --- a/src/rofi/include/rofi/rofiworld.hpp +++ b/src/rofi/include/rofi/rofiworld.hpp @@ -47,7 +47,7 @@ public: bool reachable(module_ptr fst_module, module_ptr snd_module) const; - bool rebuildNodeTree(module_ptr module); + bool rebuildNodeTree(module_ptr module, node_ptr root_node); bool rebuildNodeTree(voxel_ptr voxel, node_ptr root_node); bool detectCollision() const; diff --git a/src/rofi/src/connector.cpp b/src/rofi/src/connector.cpp index f90561c..9019983 100644 --- a/src/rofi/src/connector.cpp +++ b/src/rofi/src/connector.cpp @@ -75,15 +75,15 @@ bool Connector::shares_module_link(connector_ptr fst_connector, connector_ptr sn return false; } -cardinal Connector::get_mutual_orientation(connector_ptr fst_connector, connector_ptr snd_connector) +cardinal Connector::get_mutual_orientation(connector_ptr source_connector, connector_ptr destination_connector) { - ASSUMPTION(Connector::shares_module_link(fst_connector, snd_connector)); + ASSUMPTION(Connector::shares_module_link(source_connector, destination_connector)); - auto fst_north = fst_connector->getNode()->getRotationAxisXWorld(); - auto snd_north = snd_connector->getNode()->getRotationAxisXWorld(); - auto oriented_angle = glm::degrees(glm::orientedAngle(fst_north, - snd_north, - fst_connector->getNode()->getRotationAxisZWorld())); + auto source_north = source_connector->getNode()->getRotationAxisXWorld(); + auto destination_north = destination_connector->getNode()->getRotationAxisXWorld(); + auto oriented_angle = glm::degrees(glm::orientedAngle(destination_north, + source_north, + destination_connector->getNode()->getRotationAxisZWorld())); return degree_to_cardinal(oriented_angle); } @@ -387,14 +387,15 @@ cardinal degree_to_cardinal(float degree_angle) float epsilon = 0.001f; if (glm::epsilonEqual(degree_angle, 0.0f, epsilon)) return North; - if (glm::epsilonEqual(degree_angle, -90.0f, epsilon)) + if (glm::epsilonEqual(degree_angle, 90.0f, epsilon)) return East; if (glm::epsilonEqual(degree_angle, 180.0f, epsilon)) return South; - if (glm::epsilonEqual(degree_angle, 90.0f, epsilon)) + if (glm::epsilonEqual(degree_angle, -90.0f, epsilon)) return West; - ASSUMPTION(false); + ASSUMPTION(false); + return North; } float cardinal_to_degree(cardinal orientation) { @@ -404,11 +405,11 @@ float cardinal_to_degree(cardinal orientation) case North: return 0.0f; case East: - return -90.0f; + return 90.0f; case South: return 180.0f; case West: - return 90.0f; + return -90.0f; default: ASSUMPTION(false); return 0.0f; diff --git a/src/rofi/src/rofiworld.cpp b/src/rofi/src/rofiworld.cpp index 87c9404..f9682c1 100644 --- a/src/rofi/src/rofiworld.cpp +++ b/src/rofi/src/rofiworld.cpp @@ -90,7 +90,7 @@ bool RofiWorld::reachable(module_ptr fst_module, module_ptr snd_module) const return found_modules.contains(snd_module); } -bool RofiWorld::rebuildNodeTree(module_ptr module) // NOTE: Maybe could use views if I knew how to. +bool RofiWorld::rebuildNodeTree(module_ptr module, node_ptr root_node) // NOTE: Maybe could use views if I knew how to. { std::set<module_ptr> found_modules; bool has_cycle = false; // Not being detected here @@ -104,7 +104,7 @@ bool RofiWorld::rebuildNodeTree(module_ptr module) // NOTE: Maybe could use view // found modules are set as children of selected module, their frame is automatically recalculated into selected module base std::vector<node_ptr> found_modules_nodes; std::ranges::transform(found_modules, std::back_inserter(found_modules_nodes), [](const auto m) { return m->getNode(); } ); - module->getNode()->extendChildren(found_modules_nodes, true); + root_node->extendChildren(found_modules_nodes, true); // Remaining modules are placed into the tree vector, including the selected module std::set<module_ptr> independent_modules; @@ -170,30 +170,16 @@ bool RofiWorld::detectCollision() const { for (const auto &voxel : module->getParts()->getVoxels()) { - for (const auto &object : voxel->getNode()->getObjects()) + + for (const auto &[module_node2, module2] : nodes_map) { - auto mesh = std::dynamic_pointer_cast<Mesh>(object); - if (!mesh) + if (module_node == module_node2) continue; - for (const auto &[module_node2, module2] : nodes_map) + for (const auto &voxel2 : module2->getParts()->getVoxels()) { - if (module_node == module_node2) - continue; - - for (const auto &voxel2 : module2->getParts()->getVoxels()) - { - for (const auto &object2 : voxel2->getNode()->getObjects()) - { - auto mesh2 = std::dynamic_pointer_cast<Mesh>(object2); - if (!mesh2) - continue; - - if (AABB_intersect(mesh->getAABB(), mesh2->getAABB(), voxel->getNode(), voxel2->getNode())) - return true; - - } - } + if (glm::distance(voxel->getNode()->getPositionWorld(), voxel2->getNode()->getPositionWorld()) < 0.86f) + return true; } } } diff --git a/src/utils/include/utils/math.hpp b/src/utils/include/utils/math.hpp index 9ff0162..3666188 100644 --- a/src/utils/include/utils/math.hpp +++ b/src/utils/include/utils/math.hpp @@ -18,4 +18,6 @@ #include "glm/gtc/epsilon.hpp" #include <glm/gtx/vector_angle.hpp> +#include <cmath> + #endif -- GitLab