33#define ASSERT_VALID_ERROR_METRIC(val) BLI_assert(isfinite(val) && (val) >= 0 && (val) <= 2 * M_PI)
78# define USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
81#define FACE_OUT (1 << 0)
82#define FACE_INPUT (1 << 2)
118#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
126 int debug_merge_limit;
129 int debug_merge_count;
144 int debug_neighbor_global_count;
151 bool debug_this_step;
181 float angle_a, angle_b;
192 diff = (angle_a + angle_b) /
float(
M_PI * 2);
201 float edge_vecs[4][3];
228 float area_min, area_max, area_a, area_b;
234 area_min =
min_ff(area_a, area_b);
235 area_max =
max_ff(area_a, area_b);
238 diff = area_max ? (1.0f - (area_min / area_max)) : 1.0f;
259 BLI_assert(
e->l->f->len == 3 &&
e->l->radial_next->f->len == 3);
260 r_v_quad[0] =
e->l->v;
261 r_v_quad[1] =
e->l->radial_next->prev->v;
262 r_v_quad[2] =
e->l->next->v;
263 r_v_quad[3] =
e->l->prev->v;
274struct DelimitData_CD {
285 uint do_angle_face : 1;
286 uint do_angle_shape : 1;
289 float angle_face__cos;
293 DelimitData_CD cdata[4];
303 for (cd_offset = delimit_data->cd_offset; cd_offset < delimit_data->cd_offset_end;
304 cd_offset += delimit_data->cd_size)
317 DelimitData_CD *r_delim_cd)
320 r_delim_cd->cd_type = type;
323 r_delim_cd->cd_offset_end = r_delim_cd->cd_offset + (r_delim_cd->cd_size * layer_len);
324 return (r_delim_cd->cd_offset != -1);
335 DelimitData delimit_data = {0};
342 if (angle_face <
DEG2RADF(180.0f)) {
343 delimit_data.angle_face = angle_face;
344 delimit_data.angle_face__cos =
cosf(angle_face);
345 delimit_data.do_angle_face =
true;
348 delimit_data.do_angle_face =
false;
353 if (angle_shape <
DEG2RADF(180.0f)) {
354 delimit_data.angle_shape = angle_shape;
355 delimit_data.do_angle_shape =
true;
358 delimit_data.do_angle_shape =
false;
365 delimit_data.cdata_len += 1;
368 delimit_data.cdata[delimit_data.cdata_len].cd_offset = -1;
373 delimit_data.cdata_len += 1;
387 BMFace *f_a =
e->l->f, *f_b =
e->l->radial_next->f;
401 if (delimit_data->do_mat && (f_a->
mat_nr != f_b->mat_nr)) {
405 if (delimit_data->do_angle_face) {
406 if (
dot_v3v3(f_a->
no, f_b->no) < delimit_data->angle_face__cos) {
411 if (delimit_data->do_angle_shape) {
420 float edge_vecs[4][3];
433 delimit_data->angle_shape) ||
435 delimit_data->angle_shape) ||
437 delimit_data->angle_shape) ||
439 delimit_data->angle_shape))
445 if (delimit_data->cdata_len) {
447 for (
i = 0;
i < delimit_data->cdata_len;
i++) {
497 for (
uint index = 0; index < neighbor_info.
items_num; index++) {
528 if (l_in_neighbor->
f->
len != 3) {
534 const int items_num_prev = neighbor_info.
items_num;
538 BMLoop *l_other_arr[2] = {l_in_neighbor->
prev, l_in_neighbor->
next};
540 BMLoop *l_other = l_other_arr[
i];
566 const BMVert *quad_verts[4],
568 const float plane_normal[3],
569 float r_quad_coordinates[4][3])
571#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
572 if (s.debug_this_step) {
579 float rotation_axis[3];
583 float quad_normal[3] = {0};
585 quad_normal, quad_verts[0]->co, quad_verts[1]->co, quad_verts[2]->co, quad_verts[3]->co);
589#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
590 if (s.debug_this_step) {
595 for (
int i = 0;
i < 4;
i++) {
596 if (
ELEM(quad_verts[
i], l_shared->
v, l_shared->
next->
v)) {
603 float local_coordinate[3];
643 const float quad_a_vecs[4][3],
644 const BMVert *quad_b_verts[4],
646 const float plane_normal[3])
652 float quad_b_coordinates[4][3];
653 rotate_to_plane(s, quad_b_verts, l_shared, plane_normal, quad_b_coordinates);
655#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
656 if (s.debug_this_step) {
662 copy_v3_v3(
const_cast<BMVert *
>(quad_b_verts[0])->co, quad_b_coordinates[0]);
663 copy_v3_v3(
const_cast<BMVert *
>(quad_b_verts[1])->co, quad_b_coordinates[1]);
664 copy_v3_v3(
const_cast<BMVert *
>(quad_b_verts[2])->co, quad_b_coordinates[2]);
665 copy_v3_v3(
const_cast<BMVert *
>(quad_b_verts[3])->co, quad_b_coordinates[3]);
670 float quad_b_vecs[4][3];
671 sub_v3_v3v3(quad_b_vecs[0], quad_b_coordinates[0], quad_b_coordinates[1]);
672 sub_v3_v3v3(quad_b_vecs[1], quad_b_coordinates[1], quad_b_coordinates[2]);
673 sub_v3_v3v3(quad_b_vecs[2], quad_b_coordinates[2], quad_b_coordinates[3]);
674 sub_v3_v3v3(quad_b_vecs[3], quad_b_coordinates[3], quad_b_coordinates[0]);
693 float error[4] = {0.0f};
720 float alignment = 1.0f - (best_error / (
M_PI / 4.0f));
723 alignment = std::max(alignment, 0.0f);
762 float neighbor_quad_vecs[4][3],
763 const float neighbor_quad_error,
764 const float neighbor_quad_normal[3])
772 if (node ==
nullptr) {
784 if (neighbor_quad_error > join_error_curr) {
786#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
795#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
796 if (s.debug_this_step) {
797 printf(
"Edge improved from ");
802 const BMVert *quad_verts_merge[4];
809 s, neighbor_quad_vecs, quad_verts_merge, l_shared, neighbor_quad_normal);
813 const float improvement = (neighbor_quad_error - join_error_curr);
848 float join_error_next = join_error_curr + (improvement * multiplier);
852#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
853 if (s.debug_this_step) {
854 printf(
"%f to %f with alignment of %f.\n", join_error_curr, join_error_next, alignment);
899 float quad_vecs[4][3];
907#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
908 s.debug_this_step = (s.debug_merge_limit > 0 && s.debug_merge_count == s.debug_merge_limit &&
909 i + 1 == s.debug_neighbor) ||
910 (++s.debug_neighbor_global_count == s.debug_neighbor &&
911 s.debug_merge_limit == 0);
926#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
943 if ((l_a->
f->
len != 3) || (
l_b->f->len != 3)) {
947#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
950 if (++s.debug_merge_count > s.debug_merge_limit && s.debug_merge_limit != -1) {
961 "Doubled face detected at " AT ". Resulting mesh may be corrupt.");
986#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
990 s.debug_merge_count = 0;
991 s.debug_neighbor_global_count = 0;
1018 const BMVert *e_verts[4];
1021 e_verts[0]->co, e_verts[1]->co, e_verts[2]->co, e_verts[3]->co);
1050 f_verts[0]->co, f_verts[1]->co, f_verts[2]->co, f_verts[3]->co);
1077#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
1083#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
1086 if (s.debug_merge_limit != -1 && s.debug_merge_count == s.debug_merge_limit) {
1108#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
1111 if (s.debug_merge_limit != -1 && s.debug_merge_count >= s.debug_merge_limit) {
1117#ifdef USE_JOIN_TRIANGLE_INTERACTIVE_TESTING
1119 if (!(s.debug_merge_limit != -1 && s.debug_merge_count >= s.debug_merge_limit))
CustomData interface, see also DNA_customdata_types.h.
int CustomData_sizeof(eCustomDataType type)
int CustomData_get_n_offset(const CustomData *data, eCustomDataType type, int n)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
#define BLI_assert_msg(a, msg)
A min-heap / priority queue ADT.
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1)
void void float BLI_heap_node_value(const HeapNode *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void bool BLI_heap_is_empty(const Heap *heap) ATTR_NONNULL(1)
float BLI_heap_top_value(const Heap *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_heap_node_value_update(Heap *heap, HeapNode *node, float value) ATTR_NONNULL(1
void * BLI_heap_pop_min(Heap *heap) ATTR_NONNULL(1)
HeapNode * BLI_heap_insert(Heap *heap, float value, void *ptr) ATTR_NONNULL(1)
Heap * BLI_heap_new(void) ATTR_WARN_UNUSED_RESULT
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], float angle)
float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT
MINLINE bool compare_v3v3(const float v1[3], const float v2[3], float limit) ATTR_WARN_UNUSED_RESULT
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Read Guarded memory(de)allocation.
#define BM_elem_index_get(ele)
#define BM_elem_index_set(ele, index)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
BMFace * BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_del, BMFace **r_double)
Faces Join Pair.
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, short oflag)
#define BMO_face_flag_enable(bm, e, oflag)
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
#define BMO_face_flag_disable(bm, e, oflag)
#define BMO_face_flag_test(bm, e, oflag)
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4])
bool BM_edge_is_contiguous_loop_cd(const BMEdge *e, const int cd_loop_type, const int cd_loop_offset)
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
ATTR_WARN_UNUSED_RESULT const BMVert * v
static bool bm_edge_is_delimit(const BMEdge *e, const DelimitData *delimit_data)
static void add_neighbors(JoinEdgesNeighborInfo &neighbor_info, BMLoop *l_in_quad)
#define ASSERT_VALID_ERROR_METRIC(val)
static DelimitData bm_edge_delmimit_data_from_op(BMesh *bm, BMOperator *op)
static void reprioritize_join(JoinEdgesState &s, BMEdge *e_merge, BMLoop *l_shared, float neighbor_quad_vecs[4][3], const float neighbor_quad_error, const float neighbor_quad_normal[3])
void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
static void add_without_duplicates(JoinEdgesNeighborInfo &neighbor_info, BMEdge *e, BMLoop *l)
static void bm_edge_to_quad_verts(const BMEdge *e, const BMVert *r_v_quad[4])
static bool bm_edge_is_contiguous_loop_cd_all(const BMEdge *e, const DelimitData_CD *delimit_data)
static void reprioritize_face_neighbors(JoinEdgesState &s, BMFace *f, float f_error)
static BMFace * bm_faces_join_pair_by_edge(BMesh *bm, BMEdge *e)
static float compute_alignment(const JoinEdgesState &s, const float quad_a_vecs[4][3], const BMVert *quad_b_verts[4], const BMLoop *l_shared, const float plane_normal[3])
static float quad_calc_error(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
static void rotate_to_plane(const JoinEdgesState &s, const BMVert *quad_verts[4], const BMLoop *l_shared, const float plane_normal[3], float r_quad_coordinates[4][3])
static bool bm_edge_delimit_cdata(CustomData *ldata, eCustomDataType type, DelimitData_CD *r_delim_cd)
constexpr float maximum_improvement
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
static void error(const char *str)
struct BMLoop * radial_next
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
JoinEdgesNeighborItem items[8]
HeapNode ** edge_queue_nodes