Browse Source

bug fix

pull/8/head
Xiaolong 3 months ago
parent
commit
b51dd99005
  1. 8
      blobtree_structure/include/globals.hpp
  2. 23
      blobtree_structure/interface/internal_api.hpp
  3. 22
      blobtree_structure/interface/internal_structs.hpp
  4. 255
      blobtree_structure/src/blobtree.cpp
  5. 5
      blobtree_structure/src/primitive_node_build.cpp
  6. 10
      frontend/src/implicit_surface_network_processor.cpp

8
blobtree_structure/include/globals.hpp

@ -1,7 +1,7 @@
#pragma once
#include <vector>
#include <stack>
#include <vector>
#include <tbb/tbb.h>
@ -9,11 +9,13 @@
#include "internal_structs.hpp"
struct blobtree_t {
std::vector<node_t, tbb::tbb_allocator<node_t>> nodes{};
std::vector<uint32_t, tbb::tbb_allocator<uint32_t>> leaf_index{};
std::vector<node_t, tbb::tbb_allocator<node_t>> nodes{};
std::vector<uint32_t, tbb::tbb_allocator<uint32_t>> leaf_index{};
std::vector<Eigen::Matrix4d, tbb::tbb_allocator<Eigen::Matrix4d>> transform{};
};
extern std::vector<blobtree_t, tbb::tbb_allocator<blobtree_t>> structures;
extern std::vector<aabb_t, tbb::tbb_allocator<aabb_t>> aabbs;
extern std::vector<primitive_node_t, tbb::tbb_allocator<primitive_node_t>> primitives;
extern std::vector<uint32_t, tbb::tbb_allocator<uint32_t>> counter{};
extern std::stack<uint32_t, std::deque<uint32_t, tbb::tbb_allocator<uint32_t>>> free_structure_list;

23
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<uint32_t, tbb::tbb_allocator<uint32_t>> 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

22
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<eNodeLocation>(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<uint32_t>(node, 96u, 24); }
static constexpr inline auto node_fetch_primitive_index(node_t& node) { return node_proxy<uint32_t>(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<uint32_t>(node, 81u, 21); }
static constexpr inline auto node_is_transform_null(const node_t& node)
{
return const_node_proxy<uint32_t>(node, 81u, 21) == 0x1FFFFFu;
}
// Parent node index
static constexpr inline auto node_fetch_parent_index(node_t& node) { return node_proxy<uint32_t>(node, 64u, 32); }
static constexpr inline auto node_fetch_parent_index(node_t& node) { return node_proxy<uint32_t>(node, 54u, 27); }
static constexpr inline auto node_is_parent_null(const node_t& node)
{
return const_node_proxy<uint32_t>(node, 64u, 32) == 0xFFFFFFFFu;
return const_node_proxy<uint32_t>(node, 54u, 27) == 0x7FFFFFFu;
}
// Left child node index
static constexpr inline auto node_fetch_left_child_index(node_t& node) { return node_proxy<uint32_t>(node, 32u, 32); }
static constexpr inline auto node_fetch_left_child_index(node_t& node) { return node_proxy<uint32_t>(node, 27u, 27); }
static constexpr inline auto node_is_left_child_null(const node_t& node)
{
return const_node_proxy<uint32_t>(node, 32u, 32) == 0xFFFFFFFFu;
return const_node_proxy<uint32_t>(node, 27u, 27) == 0x7FFFFFFu;
}
// Right child node index
static constexpr inline auto node_fetch_right_child_index(node_t& node) { return node_proxy<uint32_t>(node, 0u, 32); }
static constexpr inline auto node_fetch_right_child_index(node_t& node) { return node_proxy<uint32_t>(node, 0u, 27); }
static constexpr inline auto node_is_right_child_null(const node_t& node)
{
return const_node_proxy<uint32_t>(node, 0u, 32) == 0xFFFFFFFFu;
return const_node_proxy<uint32_t>(node, 0u, 27) == 0x7FFFFFFu;
}

255
blobtree_structure/src/blobtree.cpp

@ -6,9 +6,13 @@
#include "primitive_node_destroyer.hpp"
/* internal global variables for blobtree */
std::vector<blobtree_t, tbb::tbb_allocator<blobtree_t>> structures{};
std::vector<aabb_t, tbb::tbb_allocator<aabb_t>> aabbs{};
std::vector<primitive_node_t, tbb::tbb_allocator<primitive_node_t>> primitives{};
std::vector<blobtree_t, tbb::tbb_allocator<blobtree_t>> structures{};
std::vector<bool, tbb::tbb_allocator<bool>> use_mark{};
std::vector<primitive_node_t, tbb::tbb_allocator<primitive_node_t>> primitives{};
std::vector<aabb_t, tbb::tbb_allocator<aabb_t>> aabbs{};
std::vector<uint32_t, tbb::tbb_allocator<uint32_t>> counter{};
std::stack<uint32_t, std::deque<uint32_t, tbb::tbb_allocator<uint32_t>>> 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<uint32_t, tbb::tbb_allocator<uint32_t>> get_all_primitive_index(const virtual_node_t& tree_node)
{
std::vector<uint32_t, tbb::tbb_allocator<uint32_t>> 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<Eigen::Vector3d, tbb::tbb_allocator<Eigen::Vector3d>> get_all_primitive_offset(
const virtual_node_t& tree_node)
{
std::vector<Eigen::Vector3d, tbb::tbb_allocator<Eigen::Vector3d>> 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<uint32_t>(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<uint32_t>(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<uint32_t>(structures[new_node.main_index].nodes.size());
auto temp = structures[old_node.main_index];
// Update all index
const auto size = static_cast<uint32_t>(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<uint32_t>(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<Eigen::Vector3d> 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<plane_descriptor_t*>(node.desc);
offset_point(desc->point, offset);
break;
}
case PRIMITIVE_TYPE_SPHERE: {
auto desc = static_cast<sphere_descriptor_t*>(node.desc);
offset_point(desc->center, offset);
break;
}
case PRIMITIVE_TYPE_CYLINDER: {
auto desc = static_cast<cylinder_descriptor_t*>(node.desc);
offset_point(desc->bottom_origion, offset);
break;
}
case PRIMITIVE_TYPE_CONE: {
auto desc = static_cast<cone_descriptor_t*>(node.desc);
offset_point(desc->top_point, offset);
offset_point(desc->bottom_point, offset);
break;
}
case PRIMITIVE_TYPE_BOX: {
auto desc = static_cast<box_descriptor_t*>(node.desc);
offset_point(desc->center, offset);
break;
}
case PRIMITIVE_TYPE_MESH: {
auto desc = static_cast<mesh_descriptor_t*>(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<extrude_descriptor_t*>(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<const Eigen::Vector3d> 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_);
}
}

5
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<uint32_t>(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<PRIMITIVE_TYPE_##high_name>(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<PRIMITIVE_TYPE_##high_name>(desc, \
std::bind(desc_constructor, desc, std::placeholders::_1), \

10
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<polygon_face_t> 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;

Loading…
Cancel
Save