diff --git a/src/algo/include/algo/misc.hpp b/src/algo/include/algo/misc.hpp index dd1bed06df408d57d325d66231b9838521fc91ee..3d1c9e49c4f3218cb378a3c7ec4db6bd6bc7318f 100644 --- a/src/algo/include/algo/misc.hpp +++ b/src/algo/include/algo/misc.hpp @@ -30,8 +30,9 @@ glm::vec3 convert_to_rofi_coordinates(const glm::vec3 &position); glm::mat4 convert_to_rofi_coordinates(const glm::mat4 &matrix); glm::vec3 convert_to_rofi_export_coordinates(const glm::vec3 &position, const glm::vec3 &to_voxel_center); -glm::mat4 convert_to_rofi_export_coordinates(const glm::mat4 &matrix); +glm::mat4 convert_to_rofi_export_coordinates(const glm::mat4 &editor_matrix); glm::vec3 convert_to_editor_coordinates(const glm::vec3 &rofi_position); +glm::mat4 convert_to_editor_import_coordinates(const glm::mat4 &rofi_matrix); #endif \ No newline at end of file diff --git a/src/algo/src/misc.cpp b/src/algo/src/misc.cpp index a8acdd27d548288ee726fa834f5c14a846133593..96fed7a1dc2c2ca009df8f09eaca758014a7926c 100644 --- a/src/algo/src/misc.cpp +++ b/src/algo/src/misc.cpp @@ -134,7 +134,7 @@ glm::vec3 convert_to_rofi_export_coordinates(const glm::vec3 &position, const gl return glm::vec3(voxel_position.z, voxel_position.x, voxel_position.y); } -glm::mat4 convert_to_rofi_export_coordinates(const glm::mat4 &matrix) +glm::mat4 convert_to_rofi_export_coordinates(const glm::mat4 &editor_matrix) { // E -> E' @@ -149,7 +149,7 @@ glm::mat4 convert_to_rofi_export_coordinates(const glm::mat4 &matrix) 0, 0, 0, 1 // col W ); - const auto corrected_component_matrix = matrix * A_neg_X_local_correction_matrix; + const auto corrected_component_matrix = editor_matrix * A_neg_X_local_correction_matrix; auto m = get_magic_matrix() * corrected_component_matrix; @@ -161,3 +161,19 @@ glm::vec3 convert_to_editor_coordinates(const glm::vec3 &rofi_position) { return glm::vec3(rofi_position.y, rofi_position.z, rofi_position.x); } + +glm::mat4 convert_to_editor_import_coordinates(const glm::mat4 &rofi_matrix) +{ + const auto A_neg_X_local_correction_matrix = glm::mat4(0, 0, 1, 0, // col X + 0, -1, 0, 0, // col Y + 1, 0, 0, 0, // col Z + 0, 0, 0, 1 // col W + ); + + // const auto corrected_component_matrix = rofi_matrix * A_neg_X_local_correction_matrix; + + auto m = glm::inverse(get_magic_matrix()) * rofi_matrix * glm::inverse(A_neg_X_local_correction_matrix); + + m[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + return m; +} \ No newline at end of file diff --git a/src/edit/include/edit/editor.hpp b/src/edit/include/edit/editor.hpp index 99055875e1bf935f29d45f347fba12b8172e818c..539793f2d6f260ba2225e909a6c2914273c8b88a 100644 --- a/src/edit/include/edit/editor.hpp +++ b/src/edit/include/edit/editor.hpp @@ -226,7 +226,7 @@ class Editor std::map<build_mode_I, voxel_graph_ptr> module_type_voxel_graphs; /* Modules available to be used in RofiWorld creation */ - std::vector<module_ptr> modules = import_saved_configurations(); + std::vector<module_ptr> modules = import_saved_configurations_module(); rofiworld_ptr rofiworld = std::make_shared<rofi::RofiWorld>(); @@ -441,9 +441,6 @@ private: void addVoxelGraphToScene(voxel_graph_ptr vg); void removeVoxelGraphFromScene(voxel_graph_ptr vg); void resetModuleVoxelGraph(const build_mode_I type); - void setModuleNodeHierarchy(voxel_graph_ptr vg, std::string type); - void setModuleNodeHierarchyCube(voxel_graph_ptr vg); - void setModuleNodeHierarchyUniversal(voxel_graph_ptr vg); void addToModules(std::string name, std::string type); void removeFromModules(voxel_graph_ptr vg); void removeFromModules(module_ptr module); @@ -501,7 +498,6 @@ private: void setRoFIMesh(const voxel_graph_ptr vg, bool invalid_state = false); void setVoxelMesh(const voxel_ptr voxel, bool invalid_state = false); void setConnectorMesh(const connector_ptr connector, bool invalid_state = false); - void linkImportVoxelGraphToNodes(const voxel_graph_ptr vg); /* ROFI -- PHASE TWO */ @@ -548,8 +544,6 @@ private: void connectModule(); void disconnectModule(); bool checkConnectModuleValid(const connector_ptr fst_connector, const connector_ptr snd_connector); - void teleportModulesByConnectors(const connector_ptr source_connector, const connector_ptr destination_connector); - /* MANIPULATE MODULE */ void manipulateModule(); @@ -564,8 +558,6 @@ private: /* ROTATE COMPONENT */ void rotateComponent(); - void rotateVoxel(voxel_ptr voxel, float angle); - void rotateConnector(connector_ptr connector, float angle); /* NODE TREE REBUILD */ void setRofiWorldNodeTreeToScene(const std::vector<node_ptr> &prev_node_tree, const std::vector<node_ptr> &new_node_tree); diff --git a/src/edit/src/editor.cpp b/src/edit/src/editor.cpp index 1c6467e14dc269848daab2f3175987e9b9ce5f89..663483d5a58bbe9ddd28e7ddd7a9c44375818b85 100644 --- a/src/edit/src/editor.cpp +++ b/src/edit/src/editor.cpp @@ -1213,54 +1213,6 @@ void Editor::resetModuleVoxelGraph(const build_mode_I type) voxel_graph = module_type_voxel_graphs[type]; } -void Editor::setModuleNodeHierarchy(voxel_graph_ptr vg, std::string type) -{ - if (type == "cube") - setModuleNodeHierarchyCube(vg); - else if (type == "universal") - setModuleNodeHierarchyUniversal(vg); -} - -void Editor::setModuleNodeHierarchyCube(voxel_graph_ptr vg) -{ - ASSUMPTION(!vg->getVoxels().empty()); - auto body_node = vg->getVoxels().front()->getNode(); - - for (auto connector : vg->getConnections()) - { - auto con_node = connector->getNode(); - if (!con_node->getParent().expired()) - con_node->getParent().lock()->transferChild(con_node, body_node, true); - } - - const auto rot = glm::angleAxis(glm::radians(90.0f), glm::vec3(0.0f, 0.0f, -1.0f)) - * glm::angleAxis(glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f)); - body_node->rotateRotationQuat(rot); -} - -void Editor::setModuleNodeHierarchyUniversal(voxel_graph_ptr vg) -{ - for (auto &voxel : vg->getVoxels()) - { - if (!voxel->hasRotationConnector()) - continue; - - auto voxel_node = voxel->getNode(); - - auto rot_con = std::dynamic_pointer_cast<rofi::RotationConnector>(voxel->getRotationConnector().lock()); - auto [fst, snd] = rot_con->getBoundConnectors(); - auto rot_con_node = rot_con->getNode(); - std::vector<node_ptr> connector_nodes = { rot_con_node, fst.lock()->getNode(), snd.lock()->getNode() }; - std::vector<node_ptr> parent_nodes = { voxel_node, rot_con_node, rot_con_node }; - - for (int i = 0; i < 3; ++i) - { - if (!connector_nodes[i]->getParent().expired()) - connector_nodes[i]->getParent().lock()->transferChild(connector_nodes[i], parent_nodes[i], true); - } - } -} - void Editor::addToModules(std::string name, std::string type) { scene->manageSelection(nullptr); @@ -1269,8 +1221,8 @@ void Editor::addToModules(std::string name, std::string type) const std::string module_file = name + std::string(".json"); const std::filesystem::path module_path = modules_directory + module_file; module_ptr new_module = import_module(module_path); - linkImportVoxelGraphToNodes(new_module->getParts()); - setModuleNodeHierarchy(new_module->getParts(), type); + rofi::VoxelGraph::linkImportVoxelGraphToNodes(new_module->getParts()); + rofi::Module::setModuleNodeHierarchy(new_module->getParts(), type); setRoFIMesh(new_module->getParts()); if (const auto it = std::find_if(modules.begin(), modules.end(), @@ -2117,15 +2069,6 @@ void Editor::updateRoFIMesh(const voxel_graph_ptr vg) } } -void Editor::linkImportVoxelGraphToNodes(const voxel_graph_ptr vg) -{ - for (const auto &voxel : vg->getVoxels()) - voxel->getNode()->addObject(voxel); - - for (const auto &connector : vg->getConnections()) - connector->getNode()->addObject(connector); -} - void Editor::toggleRoFIInvalidStateMesh(bool invalid, const std::set<module_ptr> &modules) { for (auto &module : modules) @@ -2637,7 +2580,7 @@ void Editor::connectModule() voxel_graph->joinConnectors(selected_connectors.first, selected_connectors.second); - teleportModulesByConnectors(selected_connectors.first, selected_connectors.second); + rofiworld->teleportModulesByConnectors(selected_connectors.first, selected_connectors.second, selected_cardinality); setConnectorMesh(selected_connectors.first); setConnectorMesh(selected_connectors.second); @@ -2687,48 +2630,6 @@ bool Editor::checkConnectModuleValid(const connector_ptr fst_connector, const co return true; } -void Editor::teleportModulesByConnectors(const connector_ptr source_connector, const connector_ptr destination_connector) -{ - const auto source_node = source_connector->getNode(); - const auto destination_node = destination_connector->getNode(); - const auto source_parent = source_node->getRootParent().lock(); - - //Rotation - - // 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 - // auto source_north = source_connector->getNode()->getRotationAxisXWorld(); - // auto destination_north = destination_connector->getNode()->getRotationAxisXWorld(); - auto source_rot_con = std::dynamic_pointer_cast<rofi::RotationConnector>(source_connector); - bool source_is_head = source_rot_con && source_rot_con->isHead(); - auto destination_rot_con = std::dynamic_pointer_cast<rofi::RotationConnector>(destination_connector); - bool destination_is_head = destination_rot_con && destination_rot_con->isHead(); - const auto source_north = source_is_head - ? -source_connector->getNode()->getRotationAxisXWorld() - : source_connector->getNode()->getRotationAxisXWorld(); - const auto destination_north = destination_is_head - ? -destination_connector->getNode()->getRotationAxisXWorld() - : destination_connector->getNode()->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 - auto orientation = glm::radians(rofi::cardinal_to_degree(selected_cardinality)); - - source_parent->rotateRotationQuat(glm::angleAxis(orientation, 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) { if (is_resetting_module_rotation) @@ -2790,48 +2691,21 @@ void Editor::rotateComponent() } if (is_voxel) - rotateVoxel(voxel, component_rotation_angle); + rofiworld->rotateVoxel(voxel, component_rotation_angle); else - rotateConnector(getConnector(selection), component_rotation_angle); + rofiworld->rotateConnector(getConnector(selection), component_rotation_angle); } -void Editor::rotateVoxel(voxel_ptr voxel, float angle) -{ - voxel->getNode()->rotateRotationQuat(glm::angleAxis(glm::radians(angle), glm::vec3(1.0f, 0.0f, 0.0f))); - // voxel->getNode()->rotateRotationQuat(glm::angleAxis(glm::radians(angle), -voxel->getNode()->getRotationAxisZLocal())); -} - -void Editor::rotateConnector(connector_ptr connector, float angle) -{ - using namespace rofi; - auto rot_con = std::dynamic_pointer_cast<RotationConnector>(connector); - ASSUMPTION(rot_con); - - float current_rotation = rot_con->getCurrentRotation(); - - angle = glm::clamp(angle, - rot_con->getNegRotationLimit() - current_rotation, - rot_con->getPosRotationLimit() - current_rotation); - - rot_con->setCurrentRotation(current_rotation + angle); - - auto connector_node = rot_con->getNode(); - auto rotation_mat = glm::toMat4(glm::angleAxis(glm::radians(-angle), glm::vec3(1.0f, 0.0f, 0.0f))); - connector_node->translatePosVec(rotation_mat); - connector_node->rotateRotationQuat(glm::toQuat(rotation_mat)); -} - - void Editor::linkModulesNodes(const std::vector<module_ptr> &modules) { for (const auto &module : modules) - linkImportVoxelGraphToNodes(module->getParts()); + rofi::VoxelGraph::linkImportVoxelGraphToNodes(module->getParts()); } void Editor::setModulesNodesHierarchy(const std::vector<module_ptr> &modules) { for (const auto &module : modules) - setModuleNodeHierarchy(module->getParts(), module->getType()); + rofi::Module::setModuleNodeHierarchy(module->getParts(), module->getType()); } void Editor::setModulesMesh(const std::vector<module_ptr> &modules) diff --git a/src/filein/include/filein/json_loader.hpp b/src/filein/include/filein/json_loader.hpp index 38504122c1e7f6d5a25057bfe24f4f4180454237..41fb5a655c1a38ce2d80467d7afbd06ac054c1f9 100644 --- a/src/filein/include/filein/json_loader.hpp +++ b/src/filein/include/filein/json_loader.hpp @@ -2,6 +2,7 @@ #define JSON_LOADER_INCLUDED #include <boost/json.hpp> +#include <utils/math.hpp> #include <filesystem> #include <fstream> @@ -11,6 +12,7 @@ void save_configuration(const boost::json::value &value, const std::filesystem::path directory, const char* file_name); const boost::json::value read_file(const std::filesystem::path &filename); +glm::mat4 get_transformation_matrix(const boost::json::value &matrix_array); void pretty_print( std::ostream& os, boost::json::value const& jv, std::string* indent = nullptr ); #endif \ No newline at end of file diff --git a/src/filein/include/filein/module_loader.hpp b/src/filein/include/filein/module_loader.hpp index c613d52c692b393d44e377eb3523fb1418365fb9..5fd6e1c0164aac7160965eded467fb6867152480 100644 --- a/src/filein/include/filein/module_loader.hpp +++ b/src/filein/include/filein/module_loader.hpp @@ -52,7 +52,7 @@ void export_module_type(boost::json::object &module_object, voxel_graph_ptr &vox /* IMPORT */ -std::vector<module_ptr> import_saved_configurations(); +std::vector<module_ptr> import_saved_configurations_module(); module_ptr import_module(const std::filesystem::path file_path); void get_module_data(const boost::json::object &json_object, boost::json::array &components_array, boost::json::value &id_value, boost::json::array &joints_array, boost::json::string &type_string); @@ -66,8 +66,6 @@ std::vector<std::tuple<uint64_t, uint64_t, glm::mat4>> get_rigid_joints(const bo const std::set<uint64_t> &body_ids, const std::set<uint64_t> &roficom_ids); -glm::mat4 get_transformation_matrix(const boost::json::value &matrix_array); - std::map<uint64_t, objectbase_ptr> import_rigid_joints(voxel_graph_ptr vg, const std::vector<std::tuple<uint64_t, uint64_t, glm::mat4>> &from_to_std, const std::map<uint64_t, objectbase_ptr> &from_components); diff --git a/src/filein/include/filein/rofiworld_loader.hpp b/src/filein/include/filein/rofiworld_loader.hpp index e3c342c4cf5bd81f5ccc59c80d3e7b59e168afd9..be78aa7b841156dda8f2ad54b16e48473ff1ca07 100644 --- a/src/filein/include/filein/rofiworld_loader.hpp +++ b/src/filein/include/filein/rofiworld_loader.hpp @@ -43,8 +43,25 @@ void export_moduleJoint_orientation(boost::json::object &moduleJoint_object, con /* IMPORT */ -// std::vector<rofiworld_ptr> import_saved_configurations(); + +std::vector<rofiworld_ptr> import_saved_configurations_rofiworld(); rofiworld_ptr import_rofiworld(const std::filesystem::path file_path); -void get_rofiworld_data(const boost::json::array &modules_array, const boost::json::array &spaceJoints_array, const boost::json::array &moduleJoints_array); +void get_rofiworld_data(const boost::json::object &json_object, + boost::json::array &modules_array, + boost::json::array &spaceJoints_array, + boost::json::array &moduleJoints_array); + +bool import_modules(rofiworld_ptr rofiworld, const boost::json::array &modules_array); + +bool import_spaceJoints(rofiworld_ptr rofiworld, const boost::json::array &spaceJoints_array); +bool import_spaceJoint(rofiworld_ptr rofiworld, const boost::json::object &spaceJoint_object); +module_ptr import_spaceJoint_to(rofiworld_ptr rofiworld, const boost::json::object &to_object); +void import_spaceJoint_point(const module_ptr module, const boost::json::array &point); +void import_spaceJoint_joint(rofiworld_ptr rofiworld, const module_ptr module, const boost::json::object &joint); + +void import_moduleJoints(rofiworld_ptr rofiworld, const boost::json::array &moduleJoints_array); +void import_moduleJoint(rofiworld_ptr rofiworld, const boost::json::object &moduleJoint_object); +std::pair<module_ptr, connector_ptr> get_moduleJoint_module_connector(rofiworld_ptr rofiworld, const boost::json::object &where_object); +rofi::cardinal get_moduleJoint_orientation(const boost::json::string &orientation_string); #endif \ No newline at end of file diff --git a/src/filein/src/json_loader.cpp b/src/filein/src/json_loader.cpp index c597c23af3fb1b8611166d4e62168bd100411025..b66bd6d9bd317199237375651adb70ac398d387f 100644 --- a/src/filein/src/json_loader.cpp +++ b/src/filein/src/json_loader.cpp @@ -32,6 +32,36 @@ const boost::json::value read_file(const std::filesystem::path &filename) return boost::json::parse(buffer /*, opt */); } +glm::mat4 get_transformation_matrix(const boost::json::value &matrix) +{ + if (matrix.is_string()) // if "identity" + { + return glm::mat4(1.0f); + } + + glm::mat4 mat; + const auto matrix_array = matrix.as_array(); + int row_index = 0; + for (const auto &row : matrix_array) + { + const auto row_array = row.as_array(); + int col_index = 0; + for (const auto &elem : row_array) + { + if (elem.is_int64()) + mat[col_index][row_index] = static_cast<float>(elem.as_int64()); + else + mat[col_index][row_index] = static_cast<float>(elem.as_double()); + + ++col_index; + } + + ++row_index; + } + + return mat; +} + // Code from: // https://www.boost.org/doc/libs/1_76_0/libs/json/doc/html/json/examples.html void pretty_print(std::ostream& os, boost::json::value const& jv, std::string* indent) diff --git a/src/filein/src/module_loader.cpp b/src/filein/src/module_loader.cpp index d4be21977ac016b4bf08e081f2ed5c308c03ad7d..af1b500e46035078848997f0462dbdc8e0707ac0 100644 --- a/src/filein/src/module_loader.cpp +++ b/src/filein/src/module_loader.cpp @@ -617,7 +617,7 @@ void export_module_type(boost::json::object &module_object, voxel_graph_ptr &vox /* IMPORT */ /* ------------------------------------- */ -std::vector<module_ptr> import_saved_configurations() +std::vector<module_ptr> import_saved_configurations_module() { const std::filesystem::path modules_directory = "./data/rofi/modules"; std::vector<module_ptr> imported_configurations; @@ -797,36 +797,6 @@ std::vector<std::tuple<uint64_t, uint64_t, glm::mat4>> get_rigid_joints(const bo return from_to_std; } -glm::mat4 get_transformation_matrix(const boost::json::value &matrix) -{ - if (matrix.is_string()) // if "identity" - { - return glm::mat4(1.0f); - } - - glm::mat4 mat; - const auto matrix_array = matrix.as_array(); - int row_index = 0; - for (const auto &row : matrix_array) - { - const auto row_array = row.as_array(); - int col_index = 0; - for (const auto &elem : row_array) - { - if (elem.is_int64()) - mat[col_index][row_index] = static_cast<float>(elem.as_int64()); - else - mat[col_index][row_index] = static_cast<float>(elem.as_double()); - - ++col_index; - } - - ++row_index; - } - - return mat; -} - std::map<uint64_t, objectbase_ptr> import_rigid_joints(voxel_graph_ptr vg, const std::vector<std::tuple<uint64_t, uint64_t, glm::mat4>> &from_to_std, const std::map<uint64_t, objectbase_ptr> &from_components) diff --git a/src/filein/src/rofiworld_loader.cpp b/src/filein/src/rofiworld_loader.cpp index 424585d6b711b22f38a9d64daae78da51a4096c2..0cddeee3416ee3b9fb188b77479187f0f2acc50c 100644 --- a/src/filein/src/rofiworld_loader.cpp +++ b/src/filein/src/rofiworld_loader.cpp @@ -2,6 +2,7 @@ #include <algo/misc.hpp> #include <filein/json_loader.hpp> +#include <filein/module_loader.hpp> void export_rofiworld(const rofiworld_ptr rofiworld, const std::vector<objectbase_ptr> &selected_spaceJoints, const char* file_name) { @@ -281,36 +282,245 @@ void export_moduleJoint_orientation(boost::json::object &moduleJoint_object, con moduleJoint_object.emplace("orientation", orientation); } -// std::vector<rofiworld_ptr> import_saved_configurations() -// { -// const std::filesystem::path rofiworlds_directory = "./data/rofi/rofiworlds"; -// std::vector<rofiworld_ptr> imported_configurations; +std::vector<rofiworld_ptr> import_saved_configurations_rofiworld() +{ + const std::filesystem::path rofiworlds_directory = "./data/rofi/rofiworlds"; + std::vector<rofiworld_ptr> imported_configurations; -// for (auto const& dir_entry : std::filesystem::directory_iterator{rofiworlds_directory}) -// { -// if (dir_entry.path().filename().string() == "." || dir_entry.path().filename().string() == "..") -// continue; + for (auto const& dir_entry : std::filesystem::directory_iterator{rofiworlds_directory}) + { + if (dir_entry.path().filename().string() == "." || dir_entry.path().filename().string() == "..") + continue; -// const auto rofiworld = import_rofiworld(dir_entry); -// if (rofiworld) -// imported_configurations.emplace_back(rofiworld); -// } + const auto rofiworld = import_rofiworld(dir_entry); + if (rofiworld) + imported_configurations.emplace_back(rofiworld); + } -// return imported_configurations; -// } + return imported_configurations; +} rofiworld_ptr import_rofiworld(const std::filesystem::path file_path) { + const auto json_object = read_file(file_path).as_object(); + boost::json::array modules_array; boost::json::array spaceJoints_array; boost::json::array moduleJoints_array; - get_rofiworld_data(modules_array, spaceJoints_array, moduleJoints_array); + get_rofiworld_data(json_object, modules_array, spaceJoints_array, moduleJoints_array); + + rofiworld_ptr rofiworld = std::make_shared<rofi::RofiWorld>(); + + if (!import_modules(rofiworld, modules_array)) + { + { + std::cerr << "Cannot import RofiWorld. Invalid module type." << file_path << std::endl; + return nullptr; + } + } + + if (!import_spaceJoints(rofiworld, spaceJoints_array)) + { + std::cerr << "Cannot import RofiWorld. Specified spaceJoint component is other than 0." << file_path << std::endl; + return nullptr; + } - return nullptr; + import_moduleJoints(rofiworld, moduleJoints_array); + + return rofiworld; +} + +void get_rofiworld_data(const boost::json::object &json_object, + boost::json::array &modules_array, + boost::json::array &spaceJoints_array, + boost::json::array &moduleJoints_array) +{ + modules_array = json_object.at("modules").as_array(); + spaceJoints_array = json_object.at("spaceJoints").as_array(); + moduleJoints_array = json_object.at("moduleJoints").as_array(); } -void get_rofiworld_data(const boost::json::array &modules_array, const boost::json::array &spaceJoints_array, const boost::json::array &moduleJoints_array) +bool import_modules(rofiworld_ptr rofiworld, const boost::json::array &modules_array) { + const std::string modules_directory = "./data/rofi/modules"; + const auto universal = import_module(modules_directory + std::string("UM.json")); + const auto cube = import_module(modules_directory + std::string("cube_full.json")); + + for (const auto &module_value : modules_array) + { + const auto module_object = module_value.as_object(); + const auto module_type = module_object.at("type"); + const auto module_type_string = module_type.if_string(); + const auto module_id = module_object.at("id").as_uint64(); + + module_ptr module_copy = nullptr; + + if (!module_type_string) + return false; + + if (*module_type_string == "universal") + { + module_copy = rofi::Module::copy(universal); + + const auto alpha = module_object.at("alpha").is_int64() ? module_object.at("alpha").as_int64() : module_object.at("alpha").as_double(); + const auto shoe_a = module_copy->getConnectorByDock("A-Z"); + rofiworld->rotateConnector(shoe_a, static_cast<float>(alpha)); + + const auto beta = module_object.at("beta").is_int64() ? module_object.at("beta").as_int64() : module_object.at("beta").as_double(); + const auto shoe_b = module_copy->getConnectorByDock("B-Z"); + rofiworld->rotateConnector(shoe_b, static_cast<float>(beta)); + + const auto gamma = module_object.at("gamma").is_int64() ? module_object.at("gamma").as_int64() : module_object.at("gamma").as_double(); + const auto body_b = module_copy->getParts()->getVoxels().front()->getNode()->getPositionLocal() == glm::vec3(0.0f) + ? module_copy->getParts()->getVoxels().back() + : module_copy->getParts()->getVoxels().front(); + rofiworld->rotateVoxel(body_b, static_cast<float>(gamma)); + + rofiworld->addModule(rofi::Module::copy(universal)); + } + else if (*module_type_string == "cube") + { + module_copy = rofi::Module::copy(cube); + rofiworld->addModule(module_copy); + } + else if (*module_type_string == "pad") + { + const auto width = module_object.at("width").as_int64(); + const auto height = module_object.at("height").as_int64(); + + // TO DO + // module_copy = std::make_shared<rofi::Module>() + // rofiworld->addModule() + } + else + return false; + + rofiworld->changeModuleID(module_copy, module_id); + + rofi::VoxelGraph::linkImportVoxelGraphToNodes(module_copy->getParts()); + rofi::Module::setModuleNodeHierarchy(module_copy->getParts(), std::string(*module_type_string)); + } + + return true; + +} + +bool import_spaceJoints(rofiworld_ptr rofiworld, const boost::json::array &spaceJoints_array) +{ + for (const auto &spaceJoint_value : spaceJoints_array) + { + if (!import_spaceJoint(rofiworld, spaceJoint_value.as_object())) + return false; + } + + return true; +} + +bool import_spaceJoint(rofiworld_ptr rofiworld, const boost::json::object &spaceJoint_object) +{ + const auto to = spaceJoint_object.at("to").as_object(); + const auto module = import_spaceJoint_to(rofiworld, to); + if (!module) + return false; + + const auto point = spaceJoint_object.at("point").as_array(); + import_spaceJoint_point(module, point); + const auto joint = spaceJoint_object.at("joint").as_object(); + import_spaceJoint_joint(rofiworld, module, joint); + + return true; +} + +module_ptr import_spaceJoint_to(rofiworld_ptr rofiworld, const boost::json::object &to_object) +{ + if (to_object.at("component").as_uint64() != 0) + return nullptr; + + const auto id = to_object.at("id").as_uint64(); + ASSUMPTION(rofiworld->containsID(id)); + return rofiworld->getModuleByID(id); +} + +void import_spaceJoint_point(const module_ptr module, const boost::json::array &point) +{ + auto position = glm::vec3(0.0f); + for (int i = 0; i < 3; ++i) + { + const auto &value = point[i]; + if (value.is_int64()) + position[i] = static_cast<float>(value.as_int64()); + else + position[i] = static_cast<float>(value.as_double()); + } + + module->getNode()->setPosVec(position); +} + +void import_spaceJoint_joint(rofiworld_ptr rofiworld, const module_ptr module, const boost::json::object &joint) +{ + const auto rofi_rotation_mat = get_transformation_matrix(joint.at("sourceToDestination")); + + const auto editor_rotation_mat = convert_to_editor_import_coordinates(rofi_rotation_mat); + + // TO DO rotate somehow +} + +void import_moduleJoints(rofiworld_ptr rofiworld, const boost::json::array &moduleJoints_array) +{ + for (const auto &moduleJoint_value : moduleJoints_array) + { + import_moduleJoint(rofiworld, moduleJoint_value.as_object()); + } +} + +void import_moduleJoint(rofiworld_ptr rofiworld, const boost::json::object &moduleJoint_object) +{ + const auto from_object = moduleJoint_object.at("from").as_object(); + const auto to_object = moduleJoint_object.at("to").as_object(); + const auto orientation_string = moduleJoint_object.at("orientation").as_string(); + + const auto [from_module, from_connector] = get_moduleJoint_module_connector(rofiworld, from_object); + const auto [to_module, to_connector] = get_moduleJoint_module_connector(rofiworld, to_object); + const auto mutual_orientation = get_moduleJoint_orientation(orientation_string); + + rofiworld->rebuildNodeTree(from_module, from_connector->getNode()); + rofiworld->getVoxelGraph()->joinConnectors(from_connector, to_connector); + rofiworld->teleportModulesByConnectors(from_connector, to_connector, mutual_orientation); + + // rebuildRofiWorldNodeTree(rofiworld->getModuleWithNode(source_node), source_node, rofiworld); + + // voxel_graph->joinConnectors(selected_connectors.first, selected_connectors.second); + + // rofiworld->teleportModulesByConnectors(selected_connectors.first, selected_connectors.second, selected_cardinality); } + +std::pair<module_ptr, connector_ptr> get_moduleJoint_module_connector(rofiworld_ptr rofiworld, const boost::json::object &where_object) +{ + const auto id = where_object.at("id").as_uint64(); + const auto module = rofiworld->getModuleByID(id); + + const auto dock = where_object.at("connector"); + connector_ptr connector; + if (dock.is_string()) + return {module, module->getConnectorByDock(std::string(dock.as_string()))}; + else // number + return {module, std::dynamic_pointer_cast<rofi::Connector>(module->getComponentByID(dock.as_uint64()))}; +} + +rofi::cardinal get_moduleJoint_orientation(const boost::json::string &orientation_string) +{ + using enum rofi::cardinal; + if (orientation_string == "North") + return North; + if (orientation_string == "East") + return East; + if (orientation_string == "South") + return South; + if (orientation_string == "West") + return West; + + ASSUMPTION(false); + return Invalid; +} diff --git a/src/rofi/include/rofi/module.hpp b/src/rofi/include/rofi/module.hpp index 442cd25517ab48b5bf88d209c50149e839b78416..23284262f22b7a61b1e6a9dfb7c4b59c94875e0f 100644 --- a/src/rofi/include/rofi/module.hpp +++ b/src/rofi/include/rofi/module.hpp @@ -48,6 +48,9 @@ public: ~Module() = default; static module_ptr copy(const module_ptr other_module); + static void setModuleNodeHierarchy(voxel_graph_ptr vg, std::string type); + static void setModuleNodeHierarchyCube(voxel_graph_ptr vg); + static void setModuleNodeHierarchyUniversal(voxel_graph_ptr vg); node_ptr getNode() const { return node; } voxel_graph_ptr getParts() const { return parts; } @@ -56,9 +59,16 @@ public: const std::string &getType() const { return type; } const std::map<objectbase_ptr, uint64_t> &getComponentIDs() const { return component_ids; } - const std::map<connector_ptr, std::string> &getConnectorDocks() const { return connector_docks; } const uint64_t &getComponentID(objectbase_ptr component) const { return component_ids.at(component); } + const objectbase_ptr &getComponentByID(uint64_t id) const { return std::find_if(component_ids.begin(), + component_ids.end(), + [&id] (const auto pair) { return pair.second == id; } )->first; } + + const std::map<connector_ptr, std::string> &getConnectorDocks() const { return connector_docks; } const std::string &getConnectorDock(connector_ptr connector) const { return connector_docks.at(connector); } + const connector_ptr getConnectorByDock(const std::string &dock) const { return std::find_if(connector_docks.begin(), + connector_docks.end(), + [&dock] (const auto pair) { return pair.second == dock; } )->first; } }; } diff --git a/src/rofi/include/rofi/rofiworld.hpp b/src/rofi/include/rofi/rofiworld.hpp index 8d80e05795d90c00b509d40416aeb6e5945f91d3..0c8fb2dd9d76f13927eb1f1840ec4bc0e47dd3c3 100644 --- a/src/rofi/include/rofi/rofiworld.hpp +++ b/src/rofi/include/rofi/rofiworld.hpp @@ -37,6 +37,7 @@ public: const std::map<module_ptr, uint64_t> &getModulesMap() const { return modules_map; } const uint64_t getModuleID(const module_ptr module) const { return modules_map.at(module); } + const module_ptr getModuleByID(const uint64_t id) const; bool containsID(uint64_t id) const { return ids_set.contains(id); } void changeModuleID(module_ptr module, uint64_t new_id); /* Returns module with given node that is either directly associated with the node or nearest parent node. @@ -50,6 +51,10 @@ public: void addModule(module_ptr module); void removeModule(module_ptr module); + void rotateVoxel(voxel_ptr voxel, float angle); + void rotateConnector(connector_ptr connector, float angle); + void teleportModulesByConnectors(const connector_ptr source_connector, const connector_ptr destination_connector, const cardinal mutual_orientation); + bool reachable(module_ptr fst_module, module_ptr snd_module) const; std::set<module_ptr> reachableModules(objectbase_ptr component) const; diff --git a/src/rofi/include/rofi/voxel_graph.hpp b/src/rofi/include/rofi/voxel_graph.hpp index 6eaa86ab8808502a3cb1acb0330c908cf2b8dce0..fd2e1c8f1f230d08c0e9d071cd521793a622dbbd 100644 --- a/src/rofi/include/rofi/voxel_graph.hpp +++ b/src/rofi/include/rofi/voxel_graph.hpp @@ -43,6 +43,7 @@ public: static void copy_nodes(const std::vector<std::pair<voxel_ptr, voxel_ptr>> &voxel_pairs, const std::vector<std::pair<connector_ptr, connector_ptr>> &connection_pairs, const std::vector<node_ptr> &new_nodes); + static void linkImportVoxelGraphToNodes(const voxel_graph_ptr vg); void extend(const voxel_graph_ptr other_voxel_graph); void erase(const voxel_graph_ptr other_voxel_graph); diff --git a/src/rofi/src/module.cpp b/src/rofi/src/module.cpp index 5d6f4ced9e8a12a1ca9a23b32cd09e675c755863..409e9cefab6b9e986c2143d20122fa4d594d4b81 100644 --- a/src/rofi/src/module.cpp +++ b/src/rofi/src/module.cpp @@ -230,4 +230,52 @@ module_ptr Module::copy(const module_ptr other_module) return module_ptr{ new Module(*other_module) }; } +void Module::setModuleNodeHierarchy(voxel_graph_ptr vg, std::string type) +{ + if (type == "cube") + setModuleNodeHierarchyCube(vg); + else if (type == "universal") + setModuleNodeHierarchyUniversal(vg); +} + +void Module::setModuleNodeHierarchyCube(voxel_graph_ptr vg) +{ + ASSUMPTION(!vg->getVoxels().empty()); + auto body_node = vg->getVoxels().front()->getNode(); + + for (auto connector : vg->getConnections()) + { + auto con_node = connector->getNode(); + if (!con_node->getParent().expired()) + con_node->getParent().lock()->transferChild(con_node, body_node, true); + } + + const auto rot = glm::angleAxis(glm::radians(90.0f), glm::vec3(0.0f, 0.0f, -1.0f)) + * glm::angleAxis(glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f)); + body_node->rotateRotationQuat(rot); +} + +void Module::setModuleNodeHierarchyUniversal(voxel_graph_ptr vg) +{ + for (auto &voxel : vg->getVoxels()) + { + if (!voxel->hasRotationConnector()) + continue; + + auto voxel_node = voxel->getNode(); + + auto rot_con = std::dynamic_pointer_cast<rofi::RotationConnector>(voxel->getRotationConnector().lock()); + auto [fst, snd] = rot_con->getBoundConnectors(); + auto rot_con_node = rot_con->getNode(); + std::vector<node_ptr> connector_nodes = { rot_con_node, fst.lock()->getNode(), snd.lock()->getNode() }; + std::vector<node_ptr> parent_nodes = { voxel_node, rot_con_node, rot_con_node }; + + for (int i = 0; i < 3; ++i) + { + if (!connector_nodes[i]->getParent().expired()) + connector_nodes[i]->getParent().lock()->transferChild(connector_nodes[i], parent_nodes[i], true); + } + } +} + } diff --git a/src/rofi/src/rofiworld.cpp b/src/rofi/src/rofiworld.cpp index 0cdf577aa6c4438d0f5715f3d5e19bac0433a06c..69617dfbde0420befff870455465eece7d953e6c 100644 --- a/src/rofi/src/rofiworld.cpp +++ b/src/rofi/src/rofiworld.cpp @@ -9,6 +9,15 @@ namespace rofi { +const module_ptr RofiWorld::getModuleByID(const uint64_t id) const +{ + const auto it = std::find_if(modules_map.begin(), modules_map.end(), [&id] (const auto pair) { return pair.second == id; } ); + + ASSUMPTION(it != modules_map.end()); + + return it->first; +} + void RofiWorld::changeModuleID(module_ptr module, uint64_t new_id) { ASSUMPTION(modules_map.contains(module)); @@ -102,6 +111,74 @@ bool RofiWorld::reachable(module_ptr fst_module, module_ptr snd_module) const return found_modules.contains(snd_module); } +void RofiWorld::rotateVoxel(voxel_ptr voxel, float angle) +{ + voxel->getNode()->rotateRotationQuat(glm::angleAxis(glm::radians(angle), glm::vec3(1.0f, 0.0f, 0.0f))); + // voxel->getNode()->rotateRotationQuat(glm::angleAxis(glm::radians(angle), -voxel->getNode()->getRotationAxisZLocal())); +} + +void RofiWorld::rotateConnector(connector_ptr connector, float angle) +{ + using namespace rofi; + auto rot_con = std::dynamic_pointer_cast<RotationConnector>(connector); + ASSUMPTION(rot_con); + + float current_rotation = rot_con->getCurrentRotation(); + + angle = glm::clamp(angle, + rot_con->getNegRotationLimit() - current_rotation, + rot_con->getPosRotationLimit() - current_rotation); + + rot_con->setCurrentRotation(current_rotation + angle); + + auto connector_node = rot_con->getNode(); + auto rotation_mat = glm::toMat4(glm::angleAxis(glm::radians(-angle), glm::vec3(1.0f, 0.0f, 0.0f))); + connector_node->translatePosVec(rotation_mat); + connector_node->rotateRotationQuat(glm::toQuat(rotation_mat)); +} + +void RofiWorld::teleportModulesByConnectors(const connector_ptr source_connector, const connector_ptr destination_connector, const cardinal mutual_orientation) +{ + const auto source_node = source_connector->getNode(); + const auto destination_node = destination_connector->getNode(); + const auto source_parent = source_node->getRootParent().lock(); + + //Rotation + + // 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 + // auto source_north = source_connector->getNode()->getRotationAxisXWorld(); + // auto destination_north = destination_connector->getNode()->getRotationAxisXWorld(); + auto source_rot_con = std::dynamic_pointer_cast<RotationConnector>(source_connector); + bool source_is_head = source_rot_con && source_rot_con->isHead(); + auto destination_rot_con = std::dynamic_pointer_cast<RotationConnector>(destination_connector); + bool destination_is_head = destination_rot_con && destination_rot_con->isHead(); + const auto source_north = source_is_head + ? -source_connector->getNode()->getRotationAxisXWorld() + : source_connector->getNode()->getRotationAxisXWorld(); + const auto destination_north = destination_is_head + ? -destination_connector->getNode()->getRotationAxisXWorld() + : destination_connector->getNode()->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 + auto orientation = glm::radians(cardinal_to_degree(mutual_orientation)); + + source_parent->rotateRotationQuat(glm::angleAxis(orientation, 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); +} + std::set<module_ptr> RofiWorld::reachableModules(objectbase_ptr component) const { node_ptr start_node; diff --git a/src/rofi/src/voxel_graph.cpp b/src/rofi/src/voxel_graph.cpp index b024b278a80f9c10fb85c95d3e246eadb7ad3710..3d355b70e4441a2016e7da2adb7d38b8c1c3dd49 100644 --- a/src/rofi/src/voxel_graph.cpp +++ b/src/rofi/src/voxel_graph.cpp @@ -177,6 +177,15 @@ void VoxelGraph::copy_nodes(const std::vector<std::pair<voxel_ptr, voxel_ptr>> & } } +void VoxelGraph::linkImportVoxelGraphToNodes(const voxel_graph_ptr vg) +{ + for (const auto &voxel : vg->getVoxels()) + voxel->getNode()->addObject(voxel); + + for (const auto &connector : vg->getConnections()) + connector->getNode()->addObject(connector); +} + void VoxelGraph::extend(const voxel_graph_ptr other_voxel_graph) { voxels.reserve(voxels.size() + other_voxel_graph->getVoxels().size());