From b51dd99005f22955e60b3f0ed1822460edc4f18f Mon Sep 17 00:00:00 2001 From: Xiaolong Date: Sun, 29 Dec 2024 19:29:32 +0800 Subject: [PATCH] bug fix --- blobtree_structure/include/globals.hpp | 8 +- blobtree_structure/interface/internal_api.hpp | 23 +- .../interface/internal_structs.hpp | 22 +- blobtree_structure/src/blobtree.cpp | 255 ++++++++++++------ .../src/primitive_node_build.cpp | 5 +- .../implicit_surface_network_processor.cpp | 10 +- 6 files changed, 215 insertions(+), 108 deletions(-) diff --git a/blobtree_structure/include/globals.hpp b/blobtree_structure/include/globals.hpp index e7fd729..bf97492 100644 --- a/blobtree_structure/include/globals.hpp +++ b/blobtree_structure/include/globals.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include @@ -9,11 +9,13 @@ #include "internal_structs.hpp" struct blobtree_t { - std::vector> nodes{}; - std::vector> leaf_index{}; + std::vector> nodes{}; + std::vector> leaf_index{}; + std::vector> transform{}; }; extern std::vector> structures; extern std::vector> aabbs; extern std::vector> primitives; +extern std::vector> counter{}; extern std::stack>> free_structure_list; \ No newline at end of file diff --git a/blobtree_structure/interface/internal_api.hpp b/blobtree_structure/interface/internal_api.hpp index f2339da..b33acdd 100644 --- a/blobtree_structure/interface/internal_api.hpp +++ b/blobtree_structure/interface/internal_api.hpp @@ -28,7 +28,7 @@ BS_API size_t blobtree_get_node_count(uint32_t index) noexcept; BS_API std::vector> blobtree_get_leaf_nodes(uint32_t index) noexcept; BS_API node_t& blobtree_get_node(const virtual_node_t& node) noexcept; -BS_API size_t get_primitive_count() noexcept; +BS_API size_t get_primitive_count(const virtual_node_t& tree_node) noexcept; BS_API const primitive_node_t& get_primitive_node(uint32_t index) noexcept; BS_API const aabb_t& get_aabb(uint32_t index) noexcept; @@ -64,12 +64,21 @@ BS_API void blobtree_free_virtual_node(const virtual_node_t& node); // Geometry Operations -BS_API void virtual_node_boolean_union(virtual_node_t& node1, const virtual_node_t& node2); -BS_API void virtual_node_boolean_intersect(virtual_node_t& node1, const virtual_node_t& node2); -BS_API void virtual_node_boolean_difference(virtual_node_t& node1, const virtual_node_t& node2); -BS_API void virtual_node_offset(virtual_node_t& node, const raw_vector3d_t& direction, const double length); -BS_API void virtual_node_offset(virtual_node_t& node, const raw_vector3d_t& offset); -BS_API void virtual_node_split(virtual_node_t& node, raw_vector3d_t base_point, raw_vector3d_t normal); +BS_API virtual_node_t virtual_node_boolean_union(const virtual_node_t& node1, + const virtual_node_t& node2, + const bool keep1 = false, + const bool keep2 = false); +BS_API virtual_node_t virtual_node_boolean_intersect(const virtual_node_t& node1, + const virtual_node_t& node2, + const bool keep1 = false, + const bool keep2 = false); +BS_API virtual_node_t virtual_node_boolean_difference(const virtual_node_t& node1, + const virtual_node_t& node2, + const bool keep1 = false, + const bool keep2 = false); +BS_API void virtual_node_offset(virtual_node_t& node, const raw_vector3d_t& direction, const double length); +BS_API void virtual_node_offset(virtual_node_t& node, const raw_vector3d_t& offset); +BS_API void virtual_node_split(virtual_node_t& node, raw_vector3d_t base_point, raw_vector3d_t normal); // Tree Node Operations diff --git a/blobtree_structure/interface/internal_structs.hpp b/blobtree_structure/interface/internal_structs.hpp index 5988675..6d6236f 100644 --- a/blobtree_structure/interface/internal_structs.hpp +++ b/blobtree_structure/interface/internal_structs.hpp @@ -163,28 +163,36 @@ static constexpr inline auto node_fetch_operation(node_t& node) { return node_pr static constexpr inline auto node_fetch_in_out(node_t& node) { return node_proxy(node, 123u, 2); } // If primitive node, the index to the primitive information -static constexpr inline auto node_fetch_primitive_index(node_t& node) { return node_proxy(node, 96u, 24); } +static constexpr inline auto node_fetch_primitive_index(node_t& node) { return node_proxy(node, 102u, 21); } + +// If primitive node, the index to the transform information +static constexpr inline auto node_fetch_transform_index(node_t& node) { return node_proxy(node, 81u, 21); } + +static constexpr inline auto node_is_transform_null(const node_t& node) +{ + return const_node_proxy(node, 81u, 21) == 0x1FFFFFu; +} // Parent node index -static constexpr inline auto node_fetch_parent_index(node_t& node) { return node_proxy(node, 64u, 32); } +static constexpr inline auto node_fetch_parent_index(node_t& node) { return node_proxy(node, 54u, 27); } static constexpr inline auto node_is_parent_null(const node_t& node) { - return const_node_proxy(node, 64u, 32) == 0xFFFFFFFFu; + return const_node_proxy(node, 54u, 27) == 0x7FFFFFFu; } // Left child node index -static constexpr inline auto node_fetch_left_child_index(node_t& node) { return node_proxy(node, 32u, 32); } +static constexpr inline auto node_fetch_left_child_index(node_t& node) { return node_proxy(node, 27u, 27); } static constexpr inline auto node_is_left_child_null(const node_t& node) { - return const_node_proxy(node, 32u, 32) == 0xFFFFFFFFu; + return const_node_proxy(node, 27u, 27) == 0x7FFFFFFu; } // Right child node index -static constexpr inline auto node_fetch_right_child_index(node_t& node) { return node_proxy(node, 0u, 32); } +static constexpr inline auto node_fetch_right_child_index(node_t& node) { return node_proxy(node, 0u, 27); } static constexpr inline auto node_is_right_child_null(const node_t& node) { - return const_node_proxy(node, 0u, 32) == 0xFFFFFFFFu; + return const_node_proxy(node, 0u, 27) == 0x7FFFFFFu; } \ No newline at end of file diff --git a/blobtree_structure/src/blobtree.cpp b/blobtree_structure/src/blobtree.cpp index d4e4bb6..0b535a8 100644 --- a/blobtree_structure/src/blobtree.cpp +++ b/blobtree_structure/src/blobtree.cpp @@ -6,9 +6,13 @@ #include "primitive_node_destroyer.hpp" /* internal global variables for blobtree */ -std::vector> structures{}; -std::vector> aabbs{}; -std::vector> primitives{}; +std::vector> structures{}; +std::vector> use_mark{}; + +std::vector> primitives{}; +std::vector> aabbs{}; +std::vector> counter{}; + std::stack>> free_structure_list{}; /* ============================================================================================= @@ -27,10 +31,34 @@ BS_API node_t& blobtree_get_node(const virtual_node_t& node) noexcept return structures[node.main_index].nodes[node.inner_index]; } -BS_API size_t get_primitive_count() noexcept +BS_API size_t get_primitive_count(const virtual_node_t& tree_node) noexcept { assert(primitives.size() == aabbs.size()); - return primitives.size(); + return structures[tree_node.main_index].leaf_index.size(); +} + +BS_API std::vector> get_all_primitive_index(const virtual_node_t& tree_node) +{ + std::vector> result; + auto& tree = structures[tree_node.main_index]; + for (auto& index : tree.leaf_index) { result.push_back(node_fetch_primitive_index(tree.nodes[index])); } + return std::move(result); +} + +BS_API std::vector> get_all_primitive_offset( + const virtual_node_t& tree_node) +{ + std::vector> result; + auto& tree = structures[tree_node.main_index]; + for (auto& index : tree.leaf_index) { + auto& node = tree.nodes[index]; + if (node_is_transform_null(node)) { + result.push_back(Eigen::Vector3d{0.0, 0.0, 0.0}); + } else { + result.push_back(tree.transform[node_fetch_transform_index(node)].block<3, 1>(0, 3)); + } + } + return std::move(result); } BS_API const primitive_node_t& get_primitive_node(uint32_t index) noexcept @@ -47,21 +75,50 @@ BS_API const aabb_t& get_aabb(uint32_t index) noexcept void shrink_primitives() { primitives.shrink_to_fit(); } +uint32_t get_next_available_blobtree_index() +{ + auto index = std::find(use_mark.begin(), use_mark.end(), false); + if (index == use_mark.end()) { + structures.resize(structures.size() + 1); + use_mark.push_back(false); + return structures.size() - 1; + } else { + return *index; + } +} + +void blobtree_merge_update_index(blobtree_t& old_tree, virtual_node_t new_node) +{ + const auto size = static_cast(structures[new_node.main_index].nodes.size()); + for (uint32_t i = 0; i < old_tree.nodes.size(); i++) { + if (!node_is_parent_null(old_tree.nodes[i])) node_fetch_parent_index(old_tree.nodes[i]) += size; + if (!node_is_left_child_null(old_tree.nodes[i])) node_fetch_left_child_index(old_tree.nodes[i]) += size; + if (!node_is_right_child_null(old_tree.nodes[i])) node_fetch_right_child_index(old_tree.nodes[i]) += size; + } + for (uint32_t i = 0; i < old_tree.leaf_index.size(); i++) { old_tree.leaf_index[i] += size; } + + const auto transform_size = static_cast(structures[new_node.main_index].transform.size()); + for (uint32_t i = 0; i < old_tree.leaf_index.size(); i++) { + if (!node_is_transform_null(old_tree.nodes[old_tree.leaf_index[i]])) { + node_fetch_transform_index(old_tree.nodes[old_tree.leaf_index[i]]) += transform_size; + } + } +} + virtual_node_t copy(virtual_node_t old_node, virtual_node_t new_node) { assert(old_node.main_index != new_node.main_index); + // Incrementing the reference count + for (auto& index : structures[old_node.main_index].leaf_index) { + counter[node_fetch_primitive_index(structures[old_node.main_index].nodes[index])]++; + } // Copy a tree and its subtrees to a temporary tree - auto temp = structures[old_node.main_index]; + const auto size = static_cast(structures[new_node.main_index].nodes.size()); + auto temp = structures[old_node.main_index]; // Update all index - const auto size = static_cast(structures[new_node.main_index].nodes.size()); - for (uint32_t i = 0; i < temp.nodes.size(); i++) { - if (!node_is_parent_null(temp.nodes[i])) node_fetch_parent_index(temp.nodes[i]) += size; - if (!node_is_left_child_null(temp.nodes[i])) node_fetch_left_child_index(temp.nodes[i]) += size; - if (!node_is_right_child_null(temp.nodes[i])) node_fetch_right_child_index(temp.nodes[i]) += size; - } - for (uint32_t i = 0; i < temp.leaf_index.size(); i++) { temp.leaf_index[i] += size; } + blobtree_merge_update_index(temp, new_node); // Copy the updated index tree to the array at the new location structures[new_node.main_index].nodes.insert(structures[new_node.main_index].nodes.end(), @@ -70,6 +127,34 @@ virtual_node_t copy(virtual_node_t old_node, virtual_node_t new_node) structures[new_node.main_index].leaf_index.insert(structures[new_node.main_index].leaf_index.end(), temp.leaf_index.begin(), temp.leaf_index.end()); + structures[new_node.main_index].transform.insert(structures[new_node.main_index].transform.end(), + temp.transform.begin(), + temp.transform.end()); + + return virtual_node_t{new_node.main_index, old_node.inner_index + size}; +} + +virtual_node_t move(virtual_node_t old_node, virtual_node_t new_node) +{ + assert(old_node.main_index != new_node.main_index); + + // Get a reference of a tree and its subtrees + const auto size = static_cast(structures[new_node.main_index].nodes.size()); + auto& old = structures[old_node.main_index]; + + // Update all index + blobtree_merge_update_index(old, new_node); + + // Mode the updated index tree to the array at the new location + structures[new_node.main_index].nodes.insert(structures[new_node.main_index].nodes.end(), + std::make_move_iterator(old.nodes.begin()), + std::make_move_iterator(old.nodes.end())); + structures[new_node.main_index].leaf_index.insert(structures[new_node.main_index].leaf_index.end(), + std::make_move_iterator(old.leaf_index.begin()), + std::make_move_iterator(old.leaf_index.end())); + structures[new_node.main_index].transform.insert(structures[new_node.main_index].transform.end(), + std::make_move_iterator(old.transform.begin()), + std::make_move_iterator(old.transform.end())); return virtual_node_t{new_node.main_index, old_node.inner_index + size}; } @@ -80,6 +165,18 @@ BS_API void free_sub_blobtree(uint32_t index) noexcept free_structure_list.push(index); } +BS_API void free_blobtree(virtual_node_t node) +{ + use_mark[node.main_index] = false; + auto& tree = structures[node.main_index]; + + for (auto& index : tree.leaf_index) { counter[node_fetch_primitive_index(tree.nodes[index])]--; } + + tree.leaf_index.clear(); + tree.nodes.clear(); + tree.transform.clear(); +} + BS_API void clear_blobtree() noexcept { structures.clear(); @@ -108,7 +205,8 @@ BS_API void clear_blobtree() noexcept // case eNodeOperation::unionOp: { // if (left_child_in_out_flag == eNodeLocation::in || right_child_in_out_flag == eNodeLocation::in) { // node_in_out_flag = eNodeLocation::in; -// } else if (left_child_in_out_flag == eNodeLocation::out && right_child_in_out_flag == eNodeLocation::out) { +// } else if (left_child_in_out_flag == eNodeLocation::out && right_child_in_out_flag == +// eNodeLocation::out) { // node_in_out_flag = eNodeLocation::out; // } else { // return false; @@ -118,7 +216,8 @@ BS_API void clear_blobtree() noexcept // case eNodeOperation::intersectionOp: { // if (left_child_in_out_flag == eNodeLocation::in && right_child_in_out_flag == eNodeLocation::in) { // node_in_out_flag = eNodeLocation::in; -// } else if (left_child_in_out_flag == eNodeLocation::out || right_child_in_out_flag == eNodeLocation::out) { +// } else if (left_child_in_out_flag == eNodeLocation::out || right_child_in_out_flag == +// eNodeLocation::out) { // node_in_out_flag = eNodeLocation::out; // } else { // return false; @@ -353,91 +452,81 @@ BS_API bool virtual_node_remove_child(const virtual_node_t& node, const virtual_ * geometry operations * ============================================================================================= */ -static inline void virtual_node_boolean_op(virtual_node_t& node1, const virtual_node_t& node2, eNodeOperation op) +static inline virtual_node_t virtual_node_boolean_op(virtual_node_t& node1, + const virtual_node_t& node2, + eNodeOperation op, + const bool keep1 = false, + const bool keep2 = false) { - auto new_node2 = copy(node2, node1); + virtual_node_t new_node1, new_node2, result_node; + + if (keep1 && keep2) { + new_node1.main_index = get_next_available_blobtree_index(); + new_node1.inner_index = 0; + new_node1 = copy(node1, new_node1); + new_node2 = copy(new_node2, new_node1); + use_mark[new_node1.main_index] = true; + } else if (keep1) { + new_node2 = node2; + new_node1 = copy(node1, node2); + } else if (keep2) { + new_node1 = node1; + new_node2 = copy(node1, node2); + } else { + new_node1 = node1; + new_node2 = move(node1, node2); + } - auto& inserted_node = structures[node1.main_index].nodes.emplace_back(standard_new_node); + auto& inserted_node = structures[new_node1.main_index].nodes.emplace_back(standard_new_node); node_fetch_is_primitive(inserted_node) = false; // weird bug: need to force cast, or it will be treated as uint32_t instead of eNodeOperation node_fetch_operation(inserted_node) = (eNodeOperation)op; - node_fetch_left_child_index(inserted_node) = node1.inner_index; + node_fetch_left_child_index(inserted_node) = new_node1.inner_index; node_fetch_right_child_index(inserted_node) = new_node2.inner_index; - uint32_t parent_index = structures[node1.main_index].nodes.size() - 1; - node_fetch_parent_index(structures[node1.main_index].nodes[node1.inner_index]) = parent_index; + uint32_t parent_index = structures[new_node1.main_index].nodes.size() - 1; + node_fetch_parent_index(structures[new_node1.main_index].nodes[new_node1.inner_index]) = parent_index; node_fetch_parent_index(structures[new_node2.main_index].nodes[new_node2.inner_index]) = parent_index; - node1.inner_index = parent_index; + result_node.main_index = new_node1.main_index; + result_node.inner_index = parent_index; + + return result_node; } -BS_API void virtual_node_boolean_union(virtual_node_t& node1, const virtual_node_t& node2) +BS_API virtual_node_t virtual_node_boolean_union(virtual_node_t& node1, + const virtual_node_t& node2, + const bool keep1 = false, + const bool keep2 = false) { - virtual_node_boolean_op(node1, node2, eNodeOperation::unionOp); + return virtual_node_boolean_op(node1, node2, eNodeOperation::unionOp, keep1, keep2); } -BS_API void virtual_node_boolean_intersect(virtual_node_t& node1, const virtual_node_t& node2) +BS_API virtual_node_t virtual_node_boolean_intersect(virtual_node_t& node1, + const virtual_node_t& node2, + const bool keep1 = false, + const bool keep2 = false) { - virtual_node_boolean_op(node1, node2, eNodeOperation::intersectionOp); + return virtual_node_boolean_op(node1, node2, eNodeOperation::intersectionOp, keep1, keep2); } -BS_API void virtual_node_boolean_difference(virtual_node_t& node1, const virtual_node_t& node2) +BS_API virtual_node_t virtual_node_boolean_difference(virtual_node_t& node1, + const virtual_node_t& node2, + const bool keep1 = false, + const bool keep2 = false) { - virtual_node_boolean_op(node1, node2, eNodeOperation::differenceOp); + return virtual_node_boolean_op(node1, node2, eNodeOperation::differenceOp, keep1, keep2); } -void offset_primitive(primitive_node_t& node, const Eigen::Vector3d& offset) +void offset_primitive_node(virtual_node_t& tree, node_t& primitive_node, const Eigen::Vector3d& offset) { - auto offset_point = [](raw_vector3d_t& point, const Eigen::Vector3d& offset) { - Eigen::Map point_map(&point.x); - point_map += offset; - }; - - auto type = node.type; - switch (type) { - case PRIMITIVE_TYPE_CONSTANT: { - break; - } - case PRIMITIVE_TYPE_PLANE: { - auto desc = static_cast(node.desc); - offset_point(desc->point, offset); - break; - } - case PRIMITIVE_TYPE_SPHERE: { - auto desc = static_cast(node.desc); - offset_point(desc->center, offset); - break; - } - case PRIMITIVE_TYPE_CYLINDER: { - auto desc = static_cast(node.desc); - offset_point(desc->bottom_origion, offset); - break; - } - case PRIMITIVE_TYPE_CONE: { - auto desc = static_cast(node.desc); - offset_point(desc->top_point, offset); - offset_point(desc->bottom_point, offset); - break; - } - case PRIMITIVE_TYPE_BOX: { - auto desc = static_cast(node.desc); - offset_point(desc->center, offset); - - break; - } - case PRIMITIVE_TYPE_MESH: { - auto desc = static_cast(node.desc); - for (int i = 0; i < desc->point_number; i++) { offset_point(desc->points[i], offset); } - break; - } - case PRIMITIVE_TYPE_EXTRUDE: { - auto desc = static_cast(node.desc); - for (int i = 0; i < desc->edges_number; i++) { offset_point(desc->points[i], offset); } - break; - } - default: { - break; - } + if (node_is_transform_null(primitive_node)) { + Eigen::Matrix4d transform = Eigen::Matrix4d::Identity(); + transform.block<3, 1>(0, 3) = offset; + structures[tree.main_index].transform.push_back(transform); + node_fetch_transform_index(primitive_node) = structures[tree.main_index].transform.size() - 1; + } else { + structures[tree.main_index].transform[node_fetch_transform_index(primitive_node)].block<3, 1>(0, 3) += offset; } } @@ -451,13 +540,9 @@ BS_API void virtual_node_offset(virtual_node_t& node, const raw_vector3d_t& offs { Eigen::Map offset_(&offset.x); - auto& all_leaf = structures[node.main_index].leaf_index; for (const auto& leaf_index : structures[node.main_index].leaf_index) { - auto& primitive_node = structures[node.main_index].nodes[leaf_index]; - const uint32_t primitive_index = node_fetch_primitive_index(primitive_node); - - offset_primitive(primitives[primitive_index], offset_); - aabbs[primitive_index].offset(offset_); + auto& primitive_node = structures[node.main_index].nodes[leaf_index]; + offset_primitive_node(node, primitive_node, offset_); } } diff --git a/blobtree_structure/src/primitive_node_build.cpp b/blobtree_structure/src/primitive_node_build.cpp index 40b8b92..550d146 100644 --- a/blobtree_structure/src/primitive_node_build.cpp +++ b/blobtree_structure/src/primitive_node_build.cpp @@ -14,6 +14,7 @@ virtual_node_t push_primitive_node(primitive_node_t&& primitive_node, const aabb { aabbs.emplace_back(aabb); primitives.emplace_back(primitive_node); + counter.emplace_back(1); node_t node = standard_new_node; node_fetch_primitive_index(node) = static_cast(primitives.size() - 1); @@ -44,7 +45,7 @@ BS_API void blobtree_free_virtual_node(const virtual_node_t& node) { free_sub_bl // ================================================================================================== #define PRIM_NODE_COPY_CONSTRUCTOR(low_name, high_name, desc_constructor, aabb_initer) \ - BS_API virtual_node_t blobtree_new_virtual_node(const low_name##_descriptor_t& desc) \ + BS_API virtual_node_t blobtree_new_virtual_node(const low_name##_descriptor_t& desc) \ { \ return insert_primitive_node(desc, \ std::bind(desc_constructor, desc, std::placeholders::_1), \ @@ -67,7 +68,7 @@ PRIM_NODE_COPY_CONSTRUCTOR(extrude, EXTRUDE, extrude_desc_copy_constructor, extr // ================================================================================================== #define PRIM_NODE_MOVE_CONSTRUCTOR(low_name, high_name, desc_constructor, aabb_initer) \ - BS_API virtual_node_t blobtree_new_virtual_node(const low_name##_descriptor_t&& desc) \ + BS_API virtual_node_t blobtree_new_virtual_node(const low_name##_descriptor_t&& desc) \ { \ return insert_primitive_node(desc, \ std::bind(desc_constructor, desc, std::placeholders::_1), \ diff --git a/frontend/src/implicit_surface_network_processor.cpp b/frontend/src/implicit_surface_network_processor.cpp index 6d638f9..d679b83 100644 --- a/frontend/src/implicit_surface_network_processor.cpp +++ b/frontend/src/implicit_surface_network_processor.cpp @@ -55,9 +55,11 @@ solve_result_t ImplicitSurfaceNetworkProcessor::run(const virtual_node_t& tree_n return {}; } - const auto num_vert = background_vertices.size(); - const auto num_tets = background_indices.size(); - const auto num_funcs = get_primitive_count(); + const auto num_vert = background_vertices.size(); + const auto num_tets = background_indices.size(); + const auto num_funcs = get_primitive_count(tree_node); + const auto all_funcs = get_all_primitive_index(tree_node); + const auto all_offset = get_all_primitive_offset(tree_node); // temporary geometry results stl_vector_mp iso_faces{}; ///< Polygonal faces at the surface network mesh @@ -86,7 +88,7 @@ solve_result_t ImplicitSurfaceNetworkProcessor::run(const virtual_node_t& tree_n for (uint32_t i = 0; i < num_vert; ++i) { const auto& point = background_vertices[i]; for (uint32_t j = 0; j < num_funcs; ++j) { - vertex_scalar_values[i][j] = evaluate(j, point); + vertex_scalar_values[i][j] = evaluate(all_funcs[j], point - all_offset[j]); const auto sign = scalar_field_sign(vertex_scalar_values[i][j]); switch (sign) { case -1: is_negative_scalar_field_sign[i * num_funcs + j] = true; break;