Browse Source

fix problem occured when creating primitives;

now RAII of primitive_node_t should work properly
gjj
Zhicheng Wang 5 months ago
parent
commit
8cd0ba5fe3
  1. 43
      application/basic_test.cpp
  2. 7
      application/xmake.lua
  3. 22
      blobtree_structure/src/blobtree.cpp
  4. 15
      frontend/src/implicit_surface_network_processor.cpp
  5. 11
      primitive_process/interface/internal_primitive_desc.hpp
  6. 121
      primitive_process/src/primitive_node.cpp

43
application/basic_test.cpp

@ -0,0 +1,43 @@
#include <iostream>
#include <any>
#include <Eigen/Core>
#include <environment.h>
#include <execution.h>
#include <io.h>
#include <construct_helper.hpp>
#include "internal_api.hpp"
#include "primitive_descriptor.h"
int main()
{
std::cout << "Setting scene..." << std::endl;
box_descriptor_t box_large{
{500, 50, 50},
{500, 50, 50}
};
box_descriptor_t box_small{
{45, 50, 50},
{5, 50, 50}
};
auto tree_root = make_primitive_node_by_move(box_large);
auto tree_small = make_primitive_node_by_move(box_small);
virtual_node_boolean_difference(&tree_root, &tree_small);
std::cout << "Setting environments..." << std::endl;
setting_descriptor setting_desc{21, 1e-5};
update_setting(setting_desc);
update_environment(&tree_root);
std::cout << "Executing solver..." << std::endl;
auto result = execute_solver(&tree_root);
std::cout << "Surface integral result: " << result.surf_int_result << std::endl;
std::cout << "Volume integral result: " << result.vol_int_result << std::endl;
std::cout << "Time statistics: " << std::endl;
print_statistics();
return 0;
}

7
application/xmake.lua

@ -9,9 +9,6 @@
target("test_frontend")
set_kind("binary")
add_deps("frontend")
add_files("main.cpp")
add_linkdirs("E:\\CProj\\ImplicitSurfaceNetwork\\build\\windows\\x64\\debug")
after_build(function(target)
print("Hello, xmake!")
end)
add_files("basic_test.cpp")
-- add_files("main.cpp")
target_end()

22
blobtree_structure/src/blobtree.cpp

@ -83,11 +83,7 @@ BS_API void clear_blobtree() noexcept
virtual_node_t push_primitive_node(primitive_node_t&& primitive_node)
{
primitives.emplace_back(primitive_node);
primitive_node.desc =
nullptr; // NOTE: primitives.back().desc and primitive_node.desc share same memory, so when this
// function returns, primitive_node.desc will be invalidated, so as primitives.back().desc, which outputs
// errors. Thus, we manually set primitive_node.desc to nullptr to avoid this problem.
primitives.emplace_back(std::move(primitive_node));
node_t node{standard_new_node};
node_fetch_primitive_index(node) = static_cast<uint32_t>(primitives.size() - 1);
@ -286,45 +282,45 @@ void offset_primitive(primitive_node_t& node, const Eigen::Vector3d& offset)
break;
}
case PRIMITIVE_TYPE_PLANE: {
auto desc = static_cast<internal::plane*>(node.desc);
auto desc = static_cast<internal::plane*>(node.data);
offset_point(desc->point, offset);
break;
}
case PRIMITIVE_TYPE_SPHERE: {
auto desc = static_cast<internal::sphere*>(node.desc);
auto desc = static_cast<internal::sphere*>(node.data);
offset_point(desc->center, offset);
break;
}
case PRIMITIVE_TYPE_CYLINDER: {
auto desc = static_cast<internal::cylinder*>(node.desc);
auto desc = static_cast<internal::cylinder*>(node.data);
offset_point(desc->bottom_center, offset);
break;
}
case PRIMITIVE_TYPE_CONE: {
auto desc = static_cast<internal::cone*>(node.desc);
auto desc = static_cast<internal::cone*>(node.data);
offset_point(desc->top_center, offset);
offset_point(desc->bottom_center, offset);
break;
}
case PRIMITIVE_TYPE_BOX: {
auto desc = static_cast<internal::box*>(node.desc);
auto desc = static_cast<internal::box*>(node.data);
offset_point(desc->center, offset);
break;
}
case PRIMITIVE_TYPE_MESH: {
auto desc = static_cast<internal::mesh*>(node.desc);
auto desc = static_cast<internal::mesh*>(node.data);
for (auto& v : desc->vertices) v += offset;
break;
}
case PRIMITIVE_TYPE_EXTRUDE_POLYLINE: {
auto desc = static_cast<internal::extrude_polyline*>(node.desc);
auto desc = static_cast<internal::extrude_polyline*>(node.data);
auto& matrix_handle = desc->axis_to_world.matrix();
matrix_handle.col(3) += offset;
break;
}
case PRIMITIVE_TYPE_EXTRUDE_HELIXLINE: {
auto desc = static_cast<internal::extrude_helixline*>(node.desc);
auto desc = static_cast<internal::extrude_helixline*>(node.data);
auto& matrix_handle = desc->axis_to_world.matrix();
matrix_handle.col(3) += offset;
break;

15
frontend/src/implicit_surface_network_processor.cpp

@ -74,8 +74,8 @@ solve_result_t ImplicitSurfaceNetworkProcessor::run(const virtual_node_t& tree_n
// Eigen::Matrix<int8_t, Eigen::Dynamic, Eigen::Dynamic> scalar_field_signs(num_funcs, num_vert);
auto scalar_field_sign = [](double x) -> int8_t { return (x < 0) ? 1 : ((x > 0) ? -1 : 0); };
stl_vector_mp<stl_vector_mp<double>> vertex_scalar_values(num_vert, stl_vector_mp<double>(num_funcs));
stl_vector_mp<bool> is_positive_scalar_field_sign(num_funcs * num_vert, false);
stl_vector_mp<bool> is_negative_scalar_field_sign(num_funcs * num_vert, false);
stl_vector_mp<stl_vector_mp<bool>> is_positive_scalar_field_sign(num_vert, stl_vector_mp<bool>(num_funcs));
stl_vector_mp<stl_vector_mp<bool>> is_negative_scalar_field_sign(num_vert, stl_vector_mp<bool>(num_funcs));
stl_vector_mp<bool> is_degenerate_vertex(num_vert, false);
bool has_degenerate_vertex{};
{
@ -84,14 +84,14 @@ solve_result_t ImplicitSurfaceNetworkProcessor::run(const virtual_node_t& tree_n
const auto& point = background_vertices[i];
for (uint32_t j = 0; j < num_funcs; ++j) {
vertex_scalar_values[i][j] = evaluate_sdf(j, point);
const auto sign = scalar_field_sign(vertex_scalar_values[i][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;
case -1: is_negative_scalar_field_sign[i][j] = true; break;
case 0:
is_degenerate_vertex[i] = true;
has_degenerate_vertex = true;
break;
case 1: is_positive_scalar_field_sign[i * num_funcs + j] = true; break;
case 1: is_positive_scalar_field_sign[i][j] = true; break;
default: break;
}
}
@ -113,8 +113,9 @@ solve_result_t ImplicitSurfaceNetworkProcessor::run(const virtual_node_t& tree_n
for (Eigen::Index j = 0; j < num_funcs; ++j) {
uint32_t pos_count{}, neg_count{};
for (uint32_t k = 0; k < 4; ++k) {
if (is_positive_scalar_field_sign[background_indices[i][k] * num_funcs + j]) pos_count++;
if (is_negative_scalar_field_sign[background_indices[i][k] * num_funcs + j]) neg_count++;
const auto& vertex_index = background_indices[i][k];
if (is_positive_scalar_field_sign[vertex_index][j]) pos_count++;
if (is_negative_scalar_field_sign[vertex_index][j]) neg_count++;
}
// if (scalar_field_signs(j, tet_ptr[k]) == 1) pos_count++;
// tets[i].size() == 4, this means that the function is active in this tet

11
primitive_process/interface/internal_primitive_desc.hpp

@ -51,15 +51,24 @@ using legal_primitive_descriptor_t = std::variant<constant_descriptor_t,
extrude_polyline_descriptor_t,
extrude_helixline_descriptor_t>;
// EDIT: safe memory block with basic RTTI support, behave like std::unique_ptr
struct PE_API primitive_node_t {
aabb_t<> aabb{};
void* desc{nullptr}; // Type conversion when using
void* data{nullptr};
primitive_type type{};
primitive_node_t(const legal_primitive_descriptor_t&) noexcept;
primitive_node_t(legal_primitive_descriptor_t&&) noexcept;
primitive_node_t(primitive_node_t&&) noexcept;
~primitive_node_t() noexcept;
primitive_node_t(const primitive_node_t&) = delete;
primitive_node_t& operator=(const primitive_node_t&) = delete;
primitive_node_t& operator=(primitive_node_t&& other) noexcept;
void swap(primitive_node_t& other) noexcept;
double evaluate_sdf([[maybe_unused]] const Eigen::Ref<const Eigen::Vector3d>&) const;
Eigen::Vector3d evaluate_cpm([[maybe_unused]] const Eigen::Ref<const Eigen::Vector3d>&) const;
};

121
primitive_process/src/primitive_node.cpp

@ -61,14 +61,38 @@ struct primitive_descriptor_meta<extrude_helixline_descriptor_t> {
// ===========================================================================
static inline void free_data_block(void *ptr, primitive_type type) noexcept
{
if (ptr == nullptr) return;
#define PRIM_DTOR(prim_type, internal_prim_type) \
case prim_type: static_cast<internal::internal_prim_type *>(ptr)->~internal_prim_type(); break
switch (type) {
PRIM_DTOR(PRIMITIVE_TYPE_CONSTANT, constant);
PRIM_DTOR(PRIMITIVE_TYPE_PLANE, plane);
PRIM_DTOR(PRIMITIVE_TYPE_SPHERE, sphere);
PRIM_DTOR(PRIMITIVE_TYPE_CYLINDER, cylinder);
PRIM_DTOR(PRIMITIVE_TYPE_CONE, cone);
PRIM_DTOR(PRIMITIVE_TYPE_BOX, box);
PRIM_DTOR(PRIMITIVE_TYPE_MESH, mesh);
PRIM_DTOR(PRIMITIVE_TYPE_EXTRUDE_POLYLINE, extrude_polyline);
PRIM_DTOR(PRIMITIVE_TYPE_EXTRUDE_HELIXLINE, extrude_helixline);
}
#undef PRIM_DTOR
::free(ptr);
}
primitive_node_t::primitive_node_t(const legal_primitive_descriptor_t &descriptor) noexcept
{
std::visit(
[this](auto &&desc) -> void {
using T = std::decay_t<decltype(desc)>;
using internal_type = typename primitive_descriptor_meta<T>::internal_type;
this->desc = ::malloc(sizeof(internal_type));
auto handle = new (this->desc) internal_type(desc, this->aabb);
this->data = ::malloc(sizeof(internal_type));
auto handle = new (this->data) internal_type(desc, this->aabb);
this->type = primitive_descriptor_meta<T>::type;
},
descriptor);
@ -80,59 +104,82 @@ primitive_node_t::primitive_node_t(legal_primitive_descriptor_t &&descriptor) no
[this](auto &&desc) {
using T = std::decay_t<decltype(desc)>;
using internal_type = typename primitive_descriptor_meta<T>::internal_type;
this->desc = ::malloc(sizeof(internal_type));
auto handle = new (this->desc) internal_type(std::move(desc), this->aabb);
this->data = ::malloc(sizeof(internal_type));
auto handle = new (this->data) internal_type(std::move(desc), this->aabb);
this->type = primitive_descriptor_meta<T>::type;
},
std::move(descriptor));
}
primitive_node_t::~primitive_node_t() noexcept
primitive_node_t::primitive_node_t(primitive_node_t &&other) noexcept
: aabb(std::move(other.aabb)), data(other.data), type(other.type)
{
if (this->desc == nullptr) return;
if (this->type == PRIMITIVE_TYPE_MESH)
static_cast<internal::mesh *>(this->desc)->~mesh();
else if (this->type == PRIMITIVE_TYPE_EXTRUDE_POLYLINE)
static_cast<internal::extrude_polyline *>(this->desc)->~extrude_polyline();
else if (this->type == PRIMITIVE_TYPE_EXTRUDE_HELIXLINE)
static_cast<internal::extrude_helixline *>(this->desc)->~extrude_helixline();
::free(this->desc);
this->desc = nullptr;
other.data = nullptr;
}
primitive_node_t::~primitive_node_t() noexcept { free_data_block(this->data, this->type); }
primitive_node_t &primitive_node_t::operator=(primitive_node_t &&other) noexcept
{
auto old_ptr = std::exchange(this->data, other.data);
free_data_block(old_ptr, type);
this->type = other.type;
other.data = nullptr;
return *this;
}
void primitive_node_t::swap(primitive_node_t &other) noexcept
{
using std::swap;
swap(this->aabb, other.aabb);
swap(this->data, other.data);
swap(this->type, other.type);
}
double primitive_node_t::evaluate_sdf([[maybe_unused]] const Eigen::Ref<const Eigen::Vector3d> &point) const
{
assert(this->data);
#define PRIM_EVAL_SDF(prim_type, internal_prim_type) \
case prim_type: return static_cast<internal::internal_prim_type *>(this->data)->evaluate_sdf(point)
switch (this->type) {
case PRIMITIVE_TYPE_CONSTANT: return static_cast<const internal::constant *>(this->desc)->evaluate_sdf(point);
case PRIMITIVE_TYPE_PLANE: return static_cast<const internal::plane *>(this->desc)->evaluate_sdf(point);
case PRIMITIVE_TYPE_SPHERE: return static_cast<const internal::sphere *>(this->desc)->evaluate_sdf(point);
case PRIMITIVE_TYPE_CYLINDER: return static_cast<const internal::cylinder *>(this->desc)->evaluate_sdf(point);
case PRIMITIVE_TYPE_CONE: return static_cast<const internal::cone *>(this->desc)->evaluate_sdf(point);
case PRIMITIVE_TYPE_BOX: return static_cast<const internal::box *>(this->desc)->evaluate_sdf(point);
case PRIMITIVE_TYPE_MESH: return static_cast<const internal::mesh *>(this->desc)->evaluate_sdf(point);
case PRIMITIVE_TYPE_EXTRUDE_POLYLINE:
return static_cast<const internal::extrude_polyline *>(this->desc)->evaluate_sdf(point);
case PRIMITIVE_TYPE_EXTRUDE_HELIXLINE:
return static_cast<const internal::extrude_helixline *>(this->desc)->evaluate_sdf(point);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_CONSTANT, constant);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_PLANE, plane);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_SPHERE, sphere);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_CYLINDER, cylinder);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_CONE, cone);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_BOX, box);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_MESH, mesh);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_EXTRUDE_POLYLINE, extrude_polyline);
PRIM_EVAL_SDF(PRIMITIVE_TYPE_EXTRUDE_HELIXLINE, extrude_helixline);
default: throw std::runtime_error("Invalid primitive type");
}
#undef PRIM_EVAL_SDF
}
Eigen::Vector3d primitive_node_t::evaluate_cpm([[maybe_unused]] const Eigen::Ref<const Eigen::Vector3d> &point) const
{
assert(this->data);
#define PRIM_EVAL_CPM(prim_type, internal_prim_type) \
case prim_type: return static_cast<internal::internal_prim_type *>(this->data)->evaluate_cpm(point)
switch (this->type) {
case PRIMITIVE_TYPE_CONSTANT: return static_cast<const internal::constant *>(this->desc)->evaluate_cpm(point);
case PRIMITIVE_TYPE_PLANE: return static_cast<const internal::plane *>(this->desc)->evaluate_cpm(point);
case PRIMITIVE_TYPE_SPHERE: return static_cast<const internal::sphere *>(this->desc)->evaluate_cpm(point);
case PRIMITIVE_TYPE_CYLINDER: return static_cast<const internal::cylinder *>(this->desc)->evaluate_cpm(point);
case PRIMITIVE_TYPE_CONE: return static_cast<const internal::cone *>(this->desc)->evaluate_cpm(point);
case PRIMITIVE_TYPE_BOX: return static_cast<const internal::box *>(this->desc)->evaluate_cpm(point);
case PRIMITIVE_TYPE_MESH: return static_cast<const internal::mesh *>(this->desc)->evaluate_cpm(point);
case PRIMITIVE_TYPE_EXTRUDE_POLYLINE:
return static_cast<const internal::extrude_polyline *>(this->desc)->evaluate_cpm(point);
case PRIMITIVE_TYPE_EXTRUDE_HELIXLINE:
return static_cast<const internal::extrude_helixline *>(this->desc)->evaluate_cpm(point);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_CONSTANT, constant);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_PLANE, plane);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_SPHERE, sphere);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_CYLINDER, cylinder);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_CONE, cone);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_BOX, box);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_MESH, mesh);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_EXTRUDE_POLYLINE, extrude_polyline);
PRIM_EVAL_CPM(PRIMITIVE_TYPE_EXTRUDE_HELIXLINE, extrude_helixline);
default: throw std::runtime_error("Invalid primitive type");
}
#undef PRIM_EVAL_CPM
}
Loading…
Cancel
Save