4 changed files with 833 additions and 18 deletions
			
			
		@ -1,25 +1,66 @@ | 
				
			|||
#pragma once | 
				
			|||
 | 
				
			|||
#include "primitive_descriptor.h" | 
				
			|||
 | 
				
			|||
typedef struct Blobtree    blobtree_t;     // fixed complete binary tree of 16 layers
 | 
				
			|||
typedef struct Node        node_t;         // real node in the tree
 | 
				
			|||
typedef struct VirtualNode virtual_node_t; // almost same as node_t, but has parent's and children's pointers to indicate the
 | 
				
			|||
                                           // hierarchy, and it is outside of the tree
 | 
				
			|||
// double node in the tree
 | 
				
			|||
typedef struct _node_t { | 
				
			|||
    unsigned int non_null  : 1; // 0 for null pointer, 1 for non-null nodes
 | 
				
			|||
    unsigned int primitive : 1; // 0 for internal node, 1 for primitive node
 | 
				
			|||
    unsigned int operate   : 2; // 0 for union, 1 for intersection, 2 for difference, 3 for unset
 | 
				
			|||
    unsigned int cross     : 2; // 0 for no cross, 1 for cross to parent, 2 for cross left child, 3 for cross right child
 | 
				
			|||
    unsigned int | 
				
			|||
        index : 16; // If primitive node, the index to the primitive information, if cross node, the index to the cross node
 | 
				
			|||
    unsigned int main_index  : 8; // use in cross node
 | 
				
			|||
    unsigned int placeholder : 2; // unused
 | 
				
			|||
} node_t; | 
				
			|||
 | 
				
			|||
typedef struct _primitive_node_t { | 
				
			|||
    descriptor type; | 
				
			|||
    void*      desc; // Type conversion when using
 | 
				
			|||
} primitive_node_t; | 
				
			|||
 | 
				
			|||
// almost same as node_t, but has parent's and children's pointers to indicate
 | 
				
			|||
// the hierarchy, and it is outside of the tree
 | 
				
			|||
typedef struct _virtual_node_t { | 
				
			|||
    unsigned int main_index  : 16; | 
				
			|||
    unsigned int inner_index : 16; | 
				
			|||
} virtual_node_t; | 
				
			|||
 | 
				
			|||
// fixed complete binary tree of 16 layers
 | 
				
			|||
typedef struct _blobtree_t { | 
				
			|||
    node_t**          structure; | 
				
			|||
    int               structure_size; | 
				
			|||
    primitive_node_t* primitive; | 
				
			|||
    int               primitive_size; | 
				
			|||
} blobtree_t; | 
				
			|||
 | 
				
			|||
EXTERN_C_BEGIN | 
				
			|||
 | 
				
			|||
API blobtree_t* create_blobtree(); | 
				
			|||
API void        free_blobtree(blobtree_t* blobtree); | 
				
			|||
 | 
				
			|||
API virtual_node_t* blobtree_new_virtual_node(const constant_descriptor_t* desc); | 
				
			|||
API void            blobtree_free_virtual_node(virtual_node_t* node); | 
				
			|||
API virtual_node_t blobtree_new_virtual_node_constant(const constant_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API virtual_node_t blobtree_new_virtual_node_plane(const plane_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API virtual_node_t blobtree_new_virtual_node_sphere(const sphere_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API virtual_node_t blobtree_new_virtual_node_cylinder(const cylinder_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API virtual_node_t blobtree_new_virtual_node_cone(const cone_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API virtual_node_t blobtree_new_virtual_node_box(const box_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API virtual_node_t blobtree_new_virtual_node_mesh(const mesh_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API virtual_node_t blobtree_new_virtual_node_extrude(const extrude_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API void           blobtree_free_virtual_node(virtual_node_t* node); | 
				
			|||
 | 
				
			|||
API bool virtual_node_set_parent(virtual_node_t* node, virtual_node_t* parent, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_set_left_child(virtual_node_t* node, virtual_node_t* child, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_set_right_child(virtual_node_t* node, virtual_node_t* child, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_add_child(virtual_node_t* node, virtual_node_t* child, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_remove_child(virtual_node_t* node, virtual_node_t* child, blobtree_t* blobtree); | 
				
			|||
 | 
				
			|||
API void virtual_node_set_parent(virtual_node_t* node, virtual_node_t* parent); | 
				
			|||
API void virtual_node_set_left_child(virtual_node_t* node, virtual_node_t* child); | 
				
			|||
API void virtual_node_set_right_child(virtual_node_t* node, virtual_node_t* child); | 
				
			|||
API void virtual_node_add_child(virtual_node_t* node, virtual_node_t* child); | 
				
			|||
API void virtual_node_remove_child(virtual_node_t* node, virtual_node_t* child); | 
				
			|||
API void virtual_node_replace_primitive(virtual_node_t* node, const constant_descriptor_t* desc); | 
				
			|||
API bool virtual_node_replace_primitive_constant(virtual_node_t* node, const constant_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_replace_primitive_plane(virtual_node_t* node, const plane_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_replace_primitive_sphere(virtual_node_t* node, const sphere_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_replace_primitive_cylinder(virtual_node_t* node, const cylinder_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_replace_primitive_cone(virtual_node_t* node, const cone_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_replace_primitive_box(virtual_node_t* node, const box_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_replace_primitive_mesh(virtual_node_t* node, const mesh_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
API bool virtual_node_replace_primitive_extrude(virtual_node_t* node, const extrude_descriptor_t* desc, blobtree_t* blobtree); | 
				
			|||
 | 
				
			|||
EXTERN_C_END | 
				
			|||
@ -0,0 +1,462 @@ | 
				
			|||
#include "blobtree.h" | 
				
			|||
#include <cstdlib> | 
				
			|||
 | 
				
			|||
constexpr auto tree_vector_length = 65535; | 
				
			|||
 | 
				
			|||
void create_new_sub_blobtree(blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    blobtree->structure_size += 1; | 
				
			|||
    blobtree->structure       = static_cast<node_t**>(realloc(blobtree->structure, blobtree->structure_size * sizeof(node_t*))); | 
				
			|||
    if (blobtree->structure == nullptr) { throw std::runtime_error("Memory allocation failed."); } | 
				
			|||
 | 
				
			|||
    blobtree->structure[blobtree->structure_size - 1] = static_cast<node_t*>(malloc(tree_vector_length * sizeof(node_t))); | 
				
			|||
    if (blobtree->structure[blobtree->structure_size - 1] == nullptr) { throw std::runtime_error("Memory allocation failed."); } | 
				
			|||
    memset(blobtree->structure[blobtree->structure_size - 1], 0.0, tree_vector_length * sizeof(node_t)); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void free_sub_blobtree(blobtree_t* blobtree, const int index) | 
				
			|||
{ | 
				
			|||
    free(blobtree->structure[index]); | 
				
			|||
    blobtree->structure[index] = nullptr; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
int get_next_available_index(blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    for (int i = 0; i < blobtree->structure_size; i++) { | 
				
			|||
        if (blobtree->structure[i] == nullptr) { | 
				
			|||
            blobtree->structure[i] = static_cast<node_t*>(malloc(tree_vector_length * sizeof(node_t))); | 
				
			|||
            if (blobtree->structure[i] == nullptr) { throw std::runtime_error("Memory allocation failed."); } | 
				
			|||
            memset(blobtree->structure[i], 0.0, tree_vector_length * sizeof(node_t)); | 
				
			|||
            return i; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    create_new_sub_blobtree(blobtree); | 
				
			|||
    return blobtree->structure_size - 1; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
blobtree_t* create_blobtree() | 
				
			|||
{ | 
				
			|||
    blobtree_t* blobtree = static_cast<blobtree_t*>(malloc(sizeof(blobtree_t))); | 
				
			|||
    if (blobtree == nullptr) { throw std::runtime_error("Memory allocation failed."); } | 
				
			|||
 | 
				
			|||
    blobtree->structure = static_cast<node_t**>(malloc(sizeof(node_t*))); | 
				
			|||
    if (blobtree->structure == nullptr) { throw std::runtime_error("Memory allocation failed."); } | 
				
			|||
    blobtree->structure_size = 0; | 
				
			|||
 | 
				
			|||
    blobtree->primitive = static_cast<primitive_node_t*>(malloc(sizeof(primitive_node_t))); | 
				
			|||
    if (blobtree->primitive == nullptr) { throw std::runtime_error("Memory allocation failed."); } | 
				
			|||
    blobtree->primitive_size = 0; | 
				
			|||
 | 
				
			|||
    return blobtree; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void free_blobtree(blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    for (int i = 0; i < blobtree->structure_size; i++) { free(blobtree->structure[i]); } | 
				
			|||
    free(blobtree->structure); | 
				
			|||
    free(blobtree->primitive); | 
				
			|||
    free(blobtree); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t push_primitive_node(blobtree_t* blobtree, const primitive_node_t& primitive_node) | 
				
			|||
{ | 
				
			|||
    blobtree->primitive_size += 1; | 
				
			|||
    blobtree->primitive = | 
				
			|||
        static_cast<primitive_node_t*>(realloc(blobtree->primitive, (blobtree->primitive_size) * sizeof(primitive_node_t))); | 
				
			|||
    if (blobtree->primitive == nullptr) { throw std::runtime_error("Memory allocation failed."); } | 
				
			|||
    blobtree->primitive[blobtree->primitive_size - 1] = primitive_node; | 
				
			|||
 | 
				
			|||
    node_t new_node; | 
				
			|||
    new_node.non_null   = 1; | 
				
			|||
    new_node.primitive  = 1; | 
				
			|||
    new_node.operate    = 3; | 
				
			|||
    new_node.cross      = 0; | 
				
			|||
    new_node.index      = blobtree->primitive_size - 1; | 
				
			|||
    new_node.main_index = 0; | 
				
			|||
 | 
				
			|||
    blobtree->structure[0] = static_cast<node_t*>(realloc(blobtree->structure[0], (blobtree->primitive_size) * sizeof(node_t))); | 
				
			|||
    if (blobtree->primitive == nullptr) { throw std::runtime_error("Memory allocation failed."); } | 
				
			|||
    blobtree->structure[0][blobtree->primitive_size - 1] = new_node; | 
				
			|||
 | 
				
			|||
    virtual_node_t virtual_node; | 
				
			|||
    virtual_node.main_index  = 0; | 
				
			|||
    virtual_node.inner_index = blobtree->primitive_size - 1; | 
				
			|||
    return virtual_node; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t blobtree_new_virtual_node_constant(const constant_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    primitive_node_t primitive_node; | 
				
			|||
    primitive_node.desc = (void*)desc; | 
				
			|||
    primitive_node.type = constant; | 
				
			|||
    return push_primitive_node(blobtree, primitive_node); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t blobtree_new_virtual_node_plane(const plane_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    primitive_node_t primitive_node; | 
				
			|||
    primitive_node.desc = (void*)desc; | 
				
			|||
    primitive_node.type = plane; | 
				
			|||
    return push_primitive_node(blobtree, primitive_node); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t blobtree_new_virtual_node_sphere(const sphere_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    primitive_node_t primitive_node; | 
				
			|||
    primitive_node.desc = (void*)desc; | 
				
			|||
    primitive_node.type = sphere; | 
				
			|||
    return push_primitive_node(blobtree, primitive_node); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t blobtree_new_virtual_node_cylinder(const cylinder_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    primitive_node_t primitive_node; | 
				
			|||
    primitive_node.desc = (void*)desc; | 
				
			|||
    primitive_node.type = cylinder; | 
				
			|||
    return push_primitive_node(blobtree, primitive_node); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t blobtree_new_virtual_node_cone(const cone_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    primitive_node_t primitive_node; | 
				
			|||
    primitive_node.desc = (void*)desc; | 
				
			|||
    primitive_node.type = cone; | 
				
			|||
    return push_primitive_node(blobtree, primitive_node); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t blobtree_new_virtual_node_box(const box_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    primitive_node_t primitive_node; | 
				
			|||
    primitive_node.desc = (void*)desc; | 
				
			|||
    primitive_node.type = box; | 
				
			|||
    return push_primitive_node(blobtree, primitive_node); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t blobtree_new_virtual_node_mesh(const mesh_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    primitive_node_t primitive_node; | 
				
			|||
    primitive_node.desc = (void*)desc; | 
				
			|||
    primitive_node.type = mesh; | 
				
			|||
    return push_primitive_node(blobtree, primitive_node); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t blobtree_new_virtual_node_extrude(const extrude_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    primitive_node_t primitive_node; | 
				
			|||
    primitive_node.desc = (void*)desc; | 
				
			|||
    primitive_node.type = extrude; | 
				
			|||
    return push_primitive_node(blobtree, primitive_node); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void blobtree_free_virtual_node(virtual_node_t* node) { ; } | 
				
			|||
 | 
				
			|||
virtual_node_t get_left_child_index(virtual_node_t node, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    int  left_child_index = 2 * node.inner_index + 1; | 
				
			|||
    auto temp             = blobtree->structure[node.main_index][left_child_index]; | 
				
			|||
    if (temp.cross == 2) { | 
				
			|||
        return virtual_node_t{temp.main_index, temp.index}; | 
				
			|||
    } else if (left_child_index >= tree_vector_length) { | 
				
			|||
        auto main_index = get_next_available_index(blobtree); | 
				
			|||
        return virtual_node_t{(unsigned int)main_index, 0}; | 
				
			|||
    } else { | 
				
			|||
        return virtual_node_t{node.main_index, (unsigned int)left_child_index}; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t get_right_child_index(virtual_node_t node, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    int  right_child_index = 2 * node.inner_index + 2; | 
				
			|||
    auto temp              = blobtree->structure[node.main_index][right_child_index]; | 
				
			|||
    if (temp.cross == 3) { | 
				
			|||
        return virtual_node_t{temp.main_index, temp.index}; | 
				
			|||
    } else if (right_child_index >= tree_vector_length) { | 
				
			|||
        auto main_index = get_next_available_index(blobtree); | 
				
			|||
        return virtual_node_t{(unsigned int)main_index, 0}; | 
				
			|||
    } else { | 
				
			|||
        return virtual_node_t{node.main_index, (unsigned int)right_child_index}; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
virtual_node_t get_parent_index(virtual_node_t node, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    int  parent_child_index = (node.inner_index - 1) / 2; | 
				
			|||
    auto temp               = blobtree->structure[node.main_index][parent_child_index]; | 
				
			|||
    if (temp.cross == 1) { | 
				
			|||
        return virtual_node_t{temp.main_index, temp.index}; | 
				
			|||
    } else { | 
				
			|||
        return virtual_node_t{node.main_index, (unsigned int)parent_child_index}; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool is_primitive_node(node_t node) { return node.primitive == 1; } | 
				
			|||
 | 
				
			|||
bool is_null_node(node_t node) { return node.non_null == 0; } | 
				
			|||
 | 
				
			|||
bool is_left_node(const int index) { return index % 2 == 1; } | 
				
			|||
 | 
				
			|||
bool is_right_node(const int index) { return index % 2 == 0; } | 
				
			|||
 | 
				
			|||
bool is_root_node(const int index) { return index == 0; } | 
				
			|||
 | 
				
			|||
bool update_inner(virtual_node_t old_node, virtual_node_t new_node, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (is_null_node(blobtree->structure[old_node.main_index][old_node.inner_index])) { return true; } | 
				
			|||
 | 
				
			|||
    if (new_node.inner_index >= tree_vector_length) { return false; } | 
				
			|||
 | 
				
			|||
    if (!is_null_node(blobtree->structure[new_node.main_index][new_node.inner_index])) { return false; } | 
				
			|||
 | 
				
			|||
    if (is_primitive_node(blobtree->structure[new_node.main_index][new_node.inner_index])) { | 
				
			|||
        blobtree->structure[new_node.main_index][new_node.inner_index] = | 
				
			|||
            blobtree->structure[old_node.main_index][old_node.inner_index]; | 
				
			|||
        blobtree->structure[old_node.main_index][old_node.inner_index].non_null = 0; | 
				
			|||
        return true; | 
				
			|||
    } else { | 
				
			|||
        if (!update_inner(get_left_child_index(old_node, blobtree), get_left_child_index(new_node, blobtree), blobtree)) { | 
				
			|||
            return false; | 
				
			|||
        } | 
				
			|||
        if (!update_inner(get_right_child_index(old_node, blobtree), get_right_child_index(new_node, blobtree), blobtree)) { | 
				
			|||
            return false; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        blobtree->structure[new_node.main_index][new_node.inner_index] = | 
				
			|||
            blobtree->structure[old_node.main_index][old_node.inner_index]; | 
				
			|||
        blobtree->structure[old_node.main_index][old_node.inner_index].non_null = 0; | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void copy_sub_blobtree(const int dst_main_index, const int src_main_index, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    memcpy(blobtree->structure[dst_main_index], blobtree->structure[src_main_index], tree_vector_length * sizeof(node_t)); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool update(virtual_node_t old_node, virtual_node_t new_node, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    // Virtual update, check for out-of-bounds
 | 
				
			|||
    auto temp_mian_index = get_next_available_index(blobtree); | 
				
			|||
    copy_sub_blobtree(temp_mian_index, new_node.main_index, blobtree); | 
				
			|||
 | 
				
			|||
    if (update_inner(old_node, virtual_node_t{(unsigned)temp_mian_index, new_node.inner_index}, blobtree)) { | 
				
			|||
        copy_sub_blobtree(new_node.main_index, temp_mian_index, blobtree); | 
				
			|||
        free_sub_blobtree(blobtree, temp_mian_index); | 
				
			|||
        return true; | 
				
			|||
    } else { | 
				
			|||
        free_sub_blobtree(blobtree, temp_mian_index); | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_boolean_union(virtual_node_t* node1, virtual_node_t* node2, blobtree_t* blobtree) { return false; } | 
				
			|||
 | 
				
			|||
bool virtual_node_boolean_union_save_mode(virtual_node_t* node1, virtual_node_t* node2, blobtree_t* blobtree) { return false; } | 
				
			|||
 | 
				
			|||
bool check(virtual_node_t node, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (is_null_node(blobtree->structure[node.main_index][node.inner_index])) { return false; } | 
				
			|||
 | 
				
			|||
    if (is_primitive_node(blobtree->structure[node.main_index][node.inner_index])) { return true; } | 
				
			|||
 | 
				
			|||
    if (!check(get_left_child_index(node, blobtree), blobtree)) { return false; } | 
				
			|||
    if (!check(get_right_child_index(node, blobtree), blobtree)) { return false; } | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_set_parent(virtual_node_t* node, virtual_node_t* parent, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (node->main_index == 0) { return false; } | 
				
			|||
 | 
				
			|||
    auto parent_index = get_parent_index(*node, blobtree); | 
				
			|||
    if (!is_root_node(parent_index.inner_index) | 
				
			|||
        && !is_null_node(blobtree->structure[parent_index.main_index][parent_index.inner_index])) { | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    auto left_child_index  = get_left_child_index(*parent, blobtree); | 
				
			|||
    auto right_child_index = get_right_child_index(*parent, blobtree); | 
				
			|||
    if (is_left_node(node->inner_index) | 
				
			|||
        && is_null_node(blobtree->structure[left_child_index.main_index][left_child_index.inner_index])) { | 
				
			|||
        if (is_root_node(node->inner_index)) { | 
				
			|||
            if (!update(*node, get_left_child_index(*node, blobtree), blobtree)) { return false; } | 
				
			|||
        } | 
				
			|||
        if (!update(*parent, get_parent_index(*node, blobtree), blobtree)) { return false; } | 
				
			|||
        return true; | 
				
			|||
    } else if (is_right_node(node->inner_index) | 
				
			|||
               && is_null_node(blobtree->structure[right_child_index.main_index][right_child_index.inner_index])) { | 
				
			|||
        if (is_root_node(node->inner_index)) { | 
				
			|||
            if (!update(*node, get_right_child_index(*node, blobtree), blobtree)) { return false; } | 
				
			|||
        } | 
				
			|||
        if (!update(*parent, get_parent_index(*node, blobtree), blobtree)) { return false; } | 
				
			|||
        return true; | 
				
			|||
    } else { | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_set_left_child(virtual_node_t* node, virtual_node_t* child, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    int parent_index     = get_parent_index(*child, blobtree).inner_index; | 
				
			|||
    int left_child_index = get_left_child_index(*node, blobtree).inner_index; | 
				
			|||
 | 
				
			|||
    if (!is_root_node(child->inner_index) && !is_null_node(blobtree->structure[child->main_index][parent_index])) { | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
    if (!is_null_node(blobtree->structure[node->main_index][left_child_index])) { return false; } | 
				
			|||
 | 
				
			|||
    if (update(*child, virtual_node_t{node->main_index, (unsigned int)left_child_index}, blobtree)) { | 
				
			|||
        *child = *node; | 
				
			|||
        return true; | 
				
			|||
    } else { | 
				
			|||
        blobtree->structure[node->main_index][left_child_index].non_null   = 1; | 
				
			|||
        blobtree->structure[node->main_index][left_child_index].cross      = 2; | 
				
			|||
        blobtree->structure[node->main_index][left_child_index].main_index = child->main_index; | 
				
			|||
        blobtree->structure[node->main_index][left_child_index].index      = child->inner_index; | 
				
			|||
 | 
				
			|||
        blobtree->structure[child->main_index][parent_index].non_null   = 1; | 
				
			|||
        blobtree->structure[child->main_index][parent_index].cross      = 1; | 
				
			|||
        blobtree->structure[child->main_index][parent_index].main_index = node->main_index; | 
				
			|||
        blobtree->structure[child->main_index][parent_index].index      = node->inner_index; | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_set_right_child(virtual_node_t* node, virtual_node_t* child, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    int parent_index      = get_parent_index(*child, blobtree).inner_index; | 
				
			|||
    int right_child_index = get_right_child_index(*node, blobtree).inner_index; | 
				
			|||
 | 
				
			|||
    if (!is_root_node(child->inner_index) && !is_null_node(blobtree->structure[child->main_index][parent_index])) { | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
    if (!is_null_node(blobtree->structure[node->main_index][right_child_index])) { return false; } | 
				
			|||
 | 
				
			|||
    if (update(*child, virtual_node_t{node->main_index, (unsigned int)right_child_index}, blobtree)) { | 
				
			|||
        *child = *node; | 
				
			|||
        return true; | 
				
			|||
    } else { | 
				
			|||
        blobtree->structure[node->main_index][right_child_index].non_null   = 1; | 
				
			|||
        blobtree->structure[node->main_index][right_child_index].cross      = 3; | 
				
			|||
        blobtree->structure[node->main_index][right_child_index].main_index = child->main_index; | 
				
			|||
        blobtree->structure[node->main_index][right_child_index].index      = child->inner_index; | 
				
			|||
 | 
				
			|||
        blobtree->structure[child->main_index][parent_index].non_null   = 1; | 
				
			|||
        blobtree->structure[child->main_index][parent_index].cross      = 1; | 
				
			|||
        blobtree->structure[child->main_index][parent_index].main_index = node->main_index; | 
				
			|||
        blobtree->structure[child->main_index][parent_index].index      = node->inner_index; | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_add_child(virtual_node_t* node, virtual_node_t* child, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    auto parent_index = get_parent_index(*child, blobtree).inner_index; | 
				
			|||
    if (!is_root_node(child->inner_index) && !is_null_node(blobtree->structure[child->main_index][parent_index])) { | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    if (is_null_node(blobtree->structure[node->main_index][get_left_child_index(*node, blobtree).inner_index])) { | 
				
			|||
        virtual_node_set_left_child(node, child, blobtree); | 
				
			|||
        return true; | 
				
			|||
    } else if (is_null_node(blobtree->structure[node->main_index][get_right_child_index(*node, blobtree).inner_index])) { | 
				
			|||
        virtual_node_set_right_child(node, child, blobtree); | 
				
			|||
        return true; | 
				
			|||
    } else { | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void remove(virtual_node_t node, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (is_null_node(blobtree->structure[node.main_index][node.inner_index])) { return; } | 
				
			|||
 | 
				
			|||
    blobtree->structure[node.main_index][node.inner_index].non_null = 0; | 
				
			|||
 | 
				
			|||
    if (is_primitive_node(blobtree->structure[node.main_index][node.inner_index])) { return; } | 
				
			|||
 | 
				
			|||
    remove(get_left_child_index(node, blobtree), blobtree); | 
				
			|||
    remove(get_right_child_index(node, blobtree), blobtree); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool operator==(const virtual_node_t& node1, const virtual_node_t& node2) | 
				
			|||
{ | 
				
			|||
    return node1.main_index == node2.main_index && node1.inner_index == node2.inner_index; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_remove_child(virtual_node_t* node, virtual_node_t* child, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (get_left_child_index(*node, blobtree) == *child) { | 
				
			|||
        remove(*child, blobtree); | 
				
			|||
        return true; | 
				
			|||
    } else if (get_right_child_index(*node, blobtree) == *child) { | 
				
			|||
        remove(*child, blobtree); | 
				
			|||
        return true; | 
				
			|||
    } else { | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_replace_primitive_constant(virtual_node_t* node, const constant_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (!is_primitive_node(blobtree->structure[node->main_index][node->inner_index])) { return false; } | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].desc = (void*)desc; | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].type = constant; | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_replace_primitive_plane(virtual_node_t* node, const plane_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (!is_primitive_node(blobtree->structure[node->main_index][node->inner_index])) { return false; } | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].desc = (void*)desc; | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].type = plane; | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_replace_primitive_sphere(virtual_node_t* node, const sphere_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (!is_primitive_node(blobtree->structure[node->main_index][node->inner_index])) { return false; } | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].desc = (void*)desc; | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].type = sphere; | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_replace_primitive_cylinder(virtual_node_t* node, const cylinder_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (!is_primitive_node(blobtree->structure[node->main_index][node->inner_index])) { return false; } | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].desc = (void*)desc; | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].type = cylinder; | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_replace_primitive_cone(virtual_node_t* node, const cone_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (!is_primitive_node(blobtree->structure[node->main_index][node->inner_index])) { return false; } | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].desc = (void*)desc; | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].type = cone; | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_replace_primitive_box(virtual_node_t* node, const box_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (!is_primitive_node(blobtree->structure[node->main_index][node->inner_index])) { return false; } | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].desc = (void*)desc; | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].type = box; | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_replace_primitive_mesh(virtual_node_t* node, const mesh_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (!is_primitive_node(blobtree->structure[node->main_index][node->inner_index])) { return false; } | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].desc = (void*)desc; | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].type = mesh; | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool virtual_node_replace_primitive_extrude(virtual_node_t* node, const extrude_descriptor_t* desc, blobtree_t* blobtree) | 
				
			|||
{ | 
				
			|||
    if (!is_primitive_node(blobtree->structure[node->main_index][node->inner_index])) { return false; } | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].desc = (void*)desc; | 
				
			|||
    blobtree->primitive[blobtree->structure[node->main_index][node->inner_index].index].type = extrude; | 
				
			|||
    return true; | 
				
			|||
} | 
				
			|||
@ -0,0 +1,266 @@ | 
				
			|||
#include "primitive_descriptor.h" | 
				
			|||
 | 
				
			|||
typedef raw_vector3d_t vec3; | 
				
			|||
 | 
				
			|||
vec3 add(const vec3& point1, const vec3& point2) { return vec3{point1.x + point2.x, point1.y + point2.y, point1.z + point2.z}; } | 
				
			|||
 | 
				
			|||
vec3 operator+(const vec3& point1, const vec3& point2) { return add(point1, point2); } | 
				
			|||
 | 
				
			|||
vec3 sub(const vec3& point1, const vec3& point2) { return vec3{point1.x - point2.x, point1.y - point2.y, point1.z - point2.z}; } | 
				
			|||
 | 
				
			|||
vec3 operator-(const vec3& point1, const vec3& point2) { return sub(point1, point2); } | 
				
			|||
 | 
				
			|||
vec3 mul(const vec3& vector, const double scalar) { return vec3{vector.x * scalar, vector.y * scalar, vector.z * scalar}; } | 
				
			|||
 | 
				
			|||
vec3 operator*(const vec3& point1, const double scalar) { return mul(point1, scalar); } | 
				
			|||
 | 
				
			|||
vec3 div(const vec3& vector, const double scalar) | 
				
			|||
{ | 
				
			|||
    if (scalar == 0) { throw std::runtime_error("Division by zero error."); } | 
				
			|||
    return vec3{vector.x / scalar, vector.y / scalar, vector.z / scalar}; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
vec3 operator/(const vec3& point1, const double scalar) { return div(point1, scalar); } | 
				
			|||
 | 
				
			|||
double dot(const vec3& vector1, const vec3& vector2) | 
				
			|||
{ | 
				
			|||
    return vector1.x * vector2.x + vector1.y * vector2.y + vector1.z * vector2.z; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double dot2(const vec3& vector) { return dot(vector, vector); } | 
				
			|||
 | 
				
			|||
vec3 cross(const vec3& vector1, const vec3& vector2) | 
				
			|||
{ | 
				
			|||
    return vec3{vector1.y * vector2.z - vector1.z * vector2.y, | 
				
			|||
                vector1.z * vector2.x - vector1.x * vector2.z, | 
				
			|||
                vector1.x * vector2.y - vector1.y * vector2.x}; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double len(const vec3& vector) { return sqrt(dot(vector, vector)); } | 
				
			|||
 | 
				
			|||
double dis(const vec3& point1, const vec3& point2) { return len(sub(point1, point2)); } | 
				
			|||
 | 
				
			|||
double clamp(const double t, const double min, const double max) | 
				
			|||
{ | 
				
			|||
    if (t <= min) { return min; } | 
				
			|||
    if (t >= max) { return max; } | 
				
			|||
    return t; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double sign(const double t) { return t >= 0.0 ? 1.0 : -1.0; } | 
				
			|||
 | 
				
			|||
vec3 normalize(const vec3& vector) | 
				
			|||
{ | 
				
			|||
    double temp = len(vector); | 
				
			|||
    if (abs(temp) < 1e-8) { throw std::runtime_error("Cannot normalize a zero-length vector."); } | 
				
			|||
    temp = 1.0 / temp; | 
				
			|||
    return vec3{vector.x * temp, vector.y * temp, vector.z * temp}; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double evaluate_constant(constant_descriptor_t* desc, raw_vector3d_t point) { return desc->value; } | 
				
			|||
 | 
				
			|||
double evaluate_plane(plane_descriptor_t* desc, raw_vector3d_t point) { return dot(point - desc->point, desc->normal); } | 
				
			|||
 | 
				
			|||
double evaluate_sphere(sphere_descriptor_t* desc, raw_vector3d_t point) { return dis(point, desc->center) - desc->radius; } | 
				
			|||
 | 
				
			|||
double evaluate_cylinder(cylinder_descriptor_t* desc, raw_vector3d_t point) | 
				
			|||
{ | 
				
			|||
    vec3&  b = desc->bottom_origion; | 
				
			|||
    vec3   a = b + desc->offset; | 
				
			|||
    vec3&  p = point; | 
				
			|||
    double r = desc->radius; | 
				
			|||
 | 
				
			|||
    vec3   ba   = b - a; | 
				
			|||
    vec3   pa   = p - a; | 
				
			|||
    double baba = dot(ba, ba); | 
				
			|||
    double paba = dot(pa, ba); | 
				
			|||
    double x    = len(pa * baba - ba * paba) - r * baba; | 
				
			|||
    double y    = abs(paba - baba * 0.5) - baba * 0.5; | 
				
			|||
    double x2   = x * x; | 
				
			|||
    double y2   = y * y * baba; | 
				
			|||
    double d    = (fmax(x, y) < 0.0) ? -fmin(x2, y2) : (((x > 0.0) ? x2 : 0.0) + ((y > 0.0) ? y2 : 0.0)); | 
				
			|||
    return sign(d) * sqrt(abs(d)) / baba; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double evaluate_cone(cone_descriptor_t* desc, raw_vector3d_t point) | 
				
			|||
{ | 
				
			|||
    vec3&  a  = desc->top_point; | 
				
			|||
    vec3&  b  = desc->bottom_point; | 
				
			|||
    vec3&  p  = point; | 
				
			|||
    double ra = desc->radius1; | 
				
			|||
    double rb = desc->radius2; | 
				
			|||
 | 
				
			|||
    double rba  = rb - ra; | 
				
			|||
    double baba = dot(b - a, b - a); | 
				
			|||
    double papa = dot(p - a, p - a); | 
				
			|||
    double paba = dot(p - a, b - a) / baba; | 
				
			|||
    double x    = sqrt(papa - paba * paba * baba); | 
				
			|||
    double cax  = fmax(0.0, x - ((paba < 0.5) ? ra : rb)); | 
				
			|||
    double cay  = abs(paba - 0.5) - 0.5; | 
				
			|||
    double k    = rba * rba + baba; | 
				
			|||
    double f    = clamp((rba * (x - ra) + paba * baba) / k, 0.0, 1.0); | 
				
			|||
    double cbx  = x - ra - f * rba; | 
				
			|||
    double cby  = paba - f; | 
				
			|||
    double s    = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0; | 
				
			|||
    return s * sqrt(fmin(cax * cax + cay * cay * baba, cbx * cbx + cby * cby * baba)); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double evaluate_box(box_descriptor_t* desc, raw_vector3d_t point) | 
				
			|||
{ | 
				
			|||
    // Get the minimum and maximum bounding coordinates of the box
 | 
				
			|||
    auto min_point = desc->left_bottom_point; | 
				
			|||
    auto max_point = min_point + vec3{desc->length, desc->width, desc->height}; | 
				
			|||
 | 
				
			|||
    // Point in the box
 | 
				
			|||
    if (point.x >= min_point.x && point.x <= max_point.x && point.y >= min_point.y && point.y <= max_point.y | 
				
			|||
        && point.z >= min_point.z && point.z <= max_point.z) { | 
				
			|||
        double min = fmin(point.x - min_point.x, max_point.x - point.x); | 
				
			|||
        min        = fmin(min, fmin(point.y - min_point.y, max_point.y - point.y)); | 
				
			|||
        min        = fmin(min, fmin(point.z - min_point.y, max_point.z - point.z)); | 
				
			|||
        return -min; | 
				
			|||
    } else { | 
				
			|||
        // Calculate the closest distance from the point to the border of each dimension of the box
 | 
				
			|||
        double dx = fmax(fmax(min_point.x - point.x, point.x - max_point.x), 0.0); | 
				
			|||
        double dy = fmax(fmax(min_point.y - point.y, point.y - max_point.y), 0.0); | 
				
			|||
        double dz = fmax(fmax(min_point.z - point.z, point.z - max_point.z), 0.0); | 
				
			|||
        return sqrt(dx * dx + dy * dy + dz * dz); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double triangle_sdf(const vec3& p, const vec3& a, const vec3& b, const vec3& c) | 
				
			|||
{ | 
				
			|||
    vec3 ba  = b - a; | 
				
			|||
    vec3 pa  = p - a; | 
				
			|||
    vec3 cb  = c - b; | 
				
			|||
    vec3 pb  = p - b; | 
				
			|||
    vec3 ac  = a - c; | 
				
			|||
    vec3 pc  = p - c; | 
				
			|||
    vec3 nor = cross(ba, ac); | 
				
			|||
 | 
				
			|||
    return sqrt((sign(dot(cross(ba, nor), pa)) + sign(dot(cross(cb, nor), pb)) + sign(dot(cross(ac, nor), pc)) < 2.0) | 
				
			|||
                    ? fmin(fmin(dot2(ba * clamp(dot(ba, pa) / dot2(ba), 0.0, 1.0) - pa), | 
				
			|||
                                dot2(cb * clamp(dot(cb, pb) / dot2(cb), 0.0, 1.0) - pb)), | 
				
			|||
                           dot2(ac * clamp(dot(ac, pc) / dot2(ac), 0.0, 1.0) - pc)) | 
				
			|||
                    : dot(nor, pa) * dot(nor, pa) / dot2(nor)); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool ray_intersects_triangle(const vec3& point, const vec3& dir, const vec3& v0, const vec3& v1, const vec3& v2) | 
				
			|||
{ | 
				
			|||
    vec3   e1    = v1 - v0; | 
				
			|||
    vec3   e2    = v2 - v0; | 
				
			|||
    vec3   s     = point - v0; | 
				
			|||
    vec3   s1    = cross(dir, e2); | 
				
			|||
    vec3   s2    = cross(s, e1); | 
				
			|||
    double coeff = 1.0 / dot(s1, e1); | 
				
			|||
    double t     = coeff * dot(s2, e2); | 
				
			|||
    double b1    = coeff * dot(s1, s); | 
				
			|||
    double b2    = coeff * dot(s2, dir); | 
				
			|||
    return t >= 0 && b1 >= 0 && b2 >= 0 && (1 - b1 - b2) >= 0; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double evaluate_mesh(mesh_descriptor_t* desc, raw_vector3d_t point) | 
				
			|||
{ | 
				
			|||
    // Note: There is no check for out-of-bounds access to points, indexes and faces
 | 
				
			|||
    auto points = desc->points; | 
				
			|||
    auto indexs = desc->indexs; | 
				
			|||
    auto face   = desc->faces; | 
				
			|||
 | 
				
			|||
    double min_distance = std::numeric_limits<double>::infinity(); | 
				
			|||
    int    count        = 0; | 
				
			|||
    for (int i = 0; i < desc->face_number; i++) { | 
				
			|||
        int begin_index = face[i][0]; | 
				
			|||
        int length      = face[i][1]; | 
				
			|||
 | 
				
			|||
        auto& point0 = points[indexs[begin_index]]; | 
				
			|||
        bool  flag   = false; | 
				
			|||
        for (int j = 1; j < length - 1; j++) { | 
				
			|||
            double temp  = triangle_sdf(point, point0, points[indexs[j]], points[indexs[j + 1]]); | 
				
			|||
            min_distance = fmin(min_distance, temp); | 
				
			|||
            if (!flag | 
				
			|||
                && ray_intersects_triangle(point, vec3{1.0, 0.0, 0.0}, point0, points[indexs[j]], points[indexs[j + 1]])) { | 
				
			|||
                flag = true; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        if (flag) { count++; } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    if (min_distance < 1e-8) { return 0; } | 
				
			|||
    if (count % 2 == 1) { | 
				
			|||
        return -min_distance; | 
				
			|||
    } else { | 
				
			|||
        return min_distance; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
double evaluate_extrude(extrude_descriptor_t* desc, raw_vector3d_t point) | 
				
			|||
{ | 
				
			|||
    // Note: There is no check for out-of-bounds access to points and bulges
 | 
				
			|||
    auto points   = desc->points; | 
				
			|||
    auto bulges   = desc->bulges; | 
				
			|||
    auto extusion = desc->extusion; | 
				
			|||
 | 
				
			|||
    double min_distance = std::numeric_limits<double>::infinity(); | 
				
			|||
    int    count        = 0; | 
				
			|||
 | 
				
			|||
    // Note: Currently only straight edges are considered, the bottom and top surfaces are polygons
 | 
				
			|||
    auto& point0 = points[0]; | 
				
			|||
    bool  flag1  = false; | 
				
			|||
    bool  flag2  = false; | 
				
			|||
    for (int i = 1; i < desc->edges_number - 1; i++) { | 
				
			|||
        // Bottom
 | 
				
			|||
        double temp  = triangle_sdf(point, point0, points[i], points[i + 1]); | 
				
			|||
        min_distance = fmin(min_distance, temp); | 
				
			|||
        if (!flag1 && ray_intersects_triangle(point, vec3{1.0, 0.0, 0.0}, point0, points[i], points[i + 1])) { flag1 = true; } | 
				
			|||
 | 
				
			|||
        // Top
 | 
				
			|||
        temp         = triangle_sdf(point, point0 + extusion, points[i] + extusion, points[i + 1] + extusion); | 
				
			|||
        min_distance = fmin(min_distance, temp); | 
				
			|||
        if (!flag2 | 
				
			|||
            && ray_intersects_triangle(point, | 
				
			|||
                                       vec3{1.0, 0.0, 0.0}, | 
				
			|||
                                       point0 + extusion, | 
				
			|||
                                       points[i] + extusion, | 
				
			|||
                                       points[i + 1] + extusion)) { | 
				
			|||
            flag2 = true; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
    if (flag1) { count++; } | 
				
			|||
    if (flag2) { count++; } | 
				
			|||
 | 
				
			|||
    // Side
 | 
				
			|||
    for (int i = 0; i < desc->edges_number; i++) { | 
				
			|||
        auto& point1 = points[i]; | 
				
			|||
        vec3  point2; | 
				
			|||
        if (i + 1 == desc->edges_number) { | 
				
			|||
            point2 = points[0]; | 
				
			|||
        } else { | 
				
			|||
            point2 = points[i + 1]; | 
				
			|||
        } | 
				
			|||
        auto point3 = point2 + extusion; | 
				
			|||
        auto point4 = point1 + extusion; | 
				
			|||
 | 
				
			|||
        auto bulge = bulges[i]; | 
				
			|||
        if (abs(bulge) < 1e-8) { | 
				
			|||
            // Straight Edge
 | 
				
			|||
            bool flag = false; | 
				
			|||
 | 
				
			|||
            double temp  = triangle_sdf(point, point1, point2, point3); | 
				
			|||
            min_distance = fmin(min_distance, temp); | 
				
			|||
            if (!flag && ray_intersects_triangle(point, vec3{1.0, 0.0, 0.0}, point1, point2, point3)) { flag = true; } | 
				
			|||
 | 
				
			|||
            temp         = triangle_sdf(point, point1, point3, point4); | 
				
			|||
            min_distance = fmin(min_distance, temp); | 
				
			|||
            if (!flag && ray_intersects_triangle(point, vec3{1.0, 0.0, 0.0}, point1, point3, point4)) { flag = true; } | 
				
			|||
 | 
				
			|||
            if (flag) { count++; } | 
				
			|||
        } else { | 
				
			|||
            // Curved Edge
 | 
				
			|||
            // TODO
 | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
    if (count % 2 == 1) { | 
				
			|||
        return -min_distance; | 
				
			|||
    } else { | 
				
			|||
        return min_distance; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
					Loading…
					
					
				
		Reference in new issue