#include #include "internal_api.hpp" #include "primitive_descriptor.h" static constexpr auto tree_vector_length = 65535; /* internal global variables for blobtree */ struct blobtree_t { std::vector> nodes{}; }; std::vector> structures{}; std::vector> primitives{}; std::stack>> free_structure_list{}; /* getter/setter for node_t */ template struct node_proxy { constexpr node_proxy(node_t& _data, uint32_t _offset, uint32_t _mask) : data(&_data), offset(_offset), mask(_mask) {} node_proxy(const node_proxy&) = delete; node_proxy(node_proxy&&) = delete; constexpr node_proxy& operator=(const node_proxy& other) { const auto _mask = mask << offset; *data = (*data & ~_mask) | (other.data & _mask); return *this; } constexpr node_proxy& operator=(node_proxy&& other) { const auto _mask = mask << offset; *data = (*data & ~_mask) | (std::forward(other.data) & _mask); return *this; } template constexpr node_proxy& operator=(_Fp&& other) { const auto _mask = mask << offset; *data = (*data & ~_mask) | (std::forward<_Fp>(other) & _mask); return *this; } constexpr operator _Tp() const { return static_cast<_Tp>(((*data) >> offset) & mask); } protected: node_t* data; uint32_t offset{}; uint32_t mask{}; }; // 0 for null pointer, 1 for non-null nodes static constexpr inline auto node_fetch_is_non_null(node_t& node) { return node_proxy(node, 31u, 0x01u); } // 0 for internal node, 1 for primitive node static constexpr inline auto node_fetch_is_primitive(node_t& node) { return node_proxy(node, 30u, 0x01u); } // 0 for union, 1 for intersection, 2 for difference, 3 for unset static constexpr inline auto node_fetch_operation(node_t& node) { return node_proxy(node, 28u, 0x03u); } // 0 for no cross, 1 for cross to parent, 2 for cross left child, 3 for cross right child static constexpr inline auto node_fetch_fetch_cross(node_t& node) { return node_proxy(node, 26u, 0x03u); } // If primitive node, the index to the primitive information, if cross node, the index to the cross node static constexpr inline auto node_fetch_primitive_index(node_t& node) { return node_proxy(node, 10u, 0xFFFFu); } // use in cross node static constexpr inline auto node_fetch_main_index(node_t& node) { return node_proxy(node, 2u, 0xFFu); } /* basic functionalities */ // primitives BPE_API std::vector>& get_primitives() { return primitives; } void shrink_primitives() { primitives.shrink_to_fit(); } // sub tree uint32_t create_new_sub_blobtree() { auto& tree = structures.emplace_back(); tree.nodes.reserve(tree_vector_length); primitives.reserve(primitives.capacity() + ((tree_vector_length + 1) >> 1)); return static_cast(structures.size() - 1); } void free_sub_blobtree(uint32_t index) { // 这里尽量打标记,延迟修改和删除 free_structure_list.push(index); } // node insertion static constexpr auto standard_new_node = 0xF0000000u; // i.e. non_null, primitive, but invalid operation // others are all zero-valued virtual_node_t push_primitive_node(primitive_node_t&& primitive_node) { primitives.emplace_back(primitive_node); auto& node = structures[0].nodes.emplace_back(standard_new_node); node_fetch_primitive_index(node) = static_cast(primitives.size() - 1); return {0, static_cast(primitives.size() - 1)}; } BPE_API virtual_node_t blobtree_new_virtual_node(const constant_descriptor_t& desc) { primitive_node_t node{PRIMITIVE_TYPE_CONSTANT, malloc(sizeof(constant_descriptor_t))}; std::move(&desc, &desc + 1, node.desc); return push_primitive_node(std::move(node)); } BPE_API virtual_node_t blobtree_new_virtual_node(const plane_descriptor_t& desc) { primitive_node_t node{PRIMITIVE_TYPE_PLANE, malloc(sizeof(plane_descriptor_t))}; std::move(&desc, &desc + 1, node.desc); return push_primitive_node(std::move(node)); } BPE_API virtual_node_t blobtree_new_virtual_node(const sphere_descriptor_t& desc) { primitive_node_t node{PRIMITIVE_TYPE_SPHERE, malloc(sizeof(sphere_descriptor_t))}; std::move(&desc, &desc + 1, node.desc); return push_primitive_node(std::move(node)); } BPE_API virtual_node_t blobtree_new_virtual_node(const cylinder_descriptor_t& desc) { primitive_node_t node{PRIMITIVE_TYPE_CYLINDER, malloc(sizeof(cylinder_descriptor_t))}; std::move(&desc, &desc + 1, node.desc); return push_primitive_node(std::move(node)); } BPE_API virtual_node_t blobtree_new_virtual_node(const cone_descriptor_t& desc) { primitive_node_t node{PRIMITIVE_TYPE_CONE, malloc(sizeof(cone_descriptor_t))}; std::move(&desc, &desc + 1, node.desc); return push_primitive_node(std::move(node)); } BPE_API virtual_node_t blobtree_new_virtual_node(const box_descriptor_t& desc) { primitive_node_t node{PRIMITIVE_TYPE_BOX, malloc(sizeof(box_descriptor_t))}; std::move(&desc, &desc + 1, node.desc); return push_primitive_node(std::move(node)); } BPE_API virtual_node_t blobtree_new_virtual_node(const mesh_descriptor_t& desc) { primitive_node_t node{PRIMITIVE_TYPE_MESH, malloc(sizeof(mesh_descriptor_t))}; std::move(&desc, &desc + 1, node.desc); return push_primitive_node(std::move(node)); } BPE_API virtual_node_t blobtree_new_virtual_node(const extrude_descriptor_t& desc) { primitive_node_t node{PRIMITIVE_TYPE_EXTRUDE, malloc(sizeof(extrude_descriptor_t))}; std::move(&desc, &desc + 1, node.desc); return push_primitive_node(std::move(node)); }