You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.9 KiB

#include <stack>
#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<node_t, tbb::tbb_allocator<node_t>> nodes{};
};
std::vector<blobtree_t, tbb::tbb_allocator<blobtree_t>> structures{};
std::vector<primitive_node_t, tbb::tbb_allocator<primitive_node_t>> primitives{};
std::stack<uint32_t, std::deque<uint32_t, tbb::tbb_allocator<uint32_t>>> free_structure_list{};
/* getter/setter for node_t */
template <typename _Tp>
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 <typename _Fp>
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<bool>(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<bool>(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<uint32_t>(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<bool>(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<bool>(node, 10u, 0xFFFFu); }
// use in cross node
static constexpr inline auto node_fetch_main_index(node_t& node) { return node_proxy<bool>(node, 2u, 0xFFu); }
/* basic functionalities */
// primitives
BPE_API std::vector<primitive_node_t, tbb::tbb_allocator<primitive_node_t>>& 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<uint32_t>(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<uint32_t>(primitives.size() - 1);
return {0, static_cast<uint32_t>(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));
}