2
* ***** BEGIN GPL LICENSE BLOCK *****
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
* Contributor(s): Campbell Barton
20
* ***** END GPL LICENSE BLOCK *****
23
/** \file blender/bmesh/operators/bmo_connect_nonplanar.c
26
* Connect verts non-planer faces iteratively (splits faces).
29
#include "MEM_guardedalloc.h"
32
#include "BLI_utildefines.h"
33
#include "BLI_alloca.h"
34
#include "BLI_linklist_stack.h"
38
#include "intern/bmesh_operators_private.h" /* own include */
40
#define EDGE_OUT (1 << 0)
41
#define FACE_OUT (1 << 1)
44
* Calculates the face subset normal.
46
static bool bm_face_subset_calc_normal(BMLoop *l_first, BMLoop *l_last, float r_no[3])
48
float const *v_prev, *v_curr;
51
BMLoop *l_iter = l_first;
52
BMLoop *l_term = l_last->next;
56
v_prev = l_last->v->co;
58
v_curr = l_iter->v->co;
59
add_newell_cross_v3_v3v3(r_no, v_prev, v_curr);
61
} while ((l_iter = l_iter->next) != l_term);
63
return (normalize_v3(r_no) != 0.0f);
67
* Calculates how non-planar the face subset is.
69
static float bm_face_subset_calc_planar(BMLoop *l_first, BMLoop *l_last, const float no[3])
76
BMLoop *l_iter = l_first;
77
BMLoop *l_term = l_last->next;
79
axis_dominant_v3_to_m3(axis_mat, no);
81
z_prev = dot_m3_v3_row_z(axis_mat, l_last->v->co);
83
z_curr = dot_m3_v3_row_z(axis_mat, l_iter->v->co);
84
delta_z += fabsf(z_curr - z_prev);
86
} while ((l_iter = l_iter->next) != l_term);
91
static bool bm_face_split_find(BMFace *f, BMVert *v_pair[2], float *r_angle)
93
BMLoop *l_iter, *l_first;
94
BMLoop **l_arr = BLI_array_alloca(l_arr, f->len);
95
const unsigned int f_len = f->len;
96
unsigned int i_a, i_b;
100
float err_best = FLT_MAX;
101
float angle_best = FLT_MAX;
103
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
106
l_arr[i_a++] = l_iter;
107
} while ((l_iter = l_iter->next) != l_first);
109
/* now for the big search, O(N^2), however faces normally aren't so large */
110
for (i_a = 0; i_a < f_len; i_a++) {
111
BMLoop *l_a = l_arr[i_a];
112
for (i_b = i_a + 2; i_b < f_len; i_b++) {
113
BMLoop *l_b = l_arr[i_b];
114
/* check these are not touching
115
* (we could be smarter here) */
116
if ((l_a->next != l_b) &&
119
/* first calculate normals */
120
float no_a[3], no_b[3];
122
if (bm_face_subset_calc_normal(l_a, l_b, no_a) &&
123
bm_face_subset_calc_normal(l_b, l_a, no_b))
125
const float err_a = bm_face_subset_calc_planar(l_a, l_b, no_a);
126
const float err_b = bm_face_subset_calc_planar(l_b, l_a, no_b);
127
const float err_test = err_a + err_b;
129
if (err_test < err_best) {
130
/* check we're legal (we could batch this) */
131
BMLoop *l_split[2] = {l_a, l_b};
132
BM_face_legal_splits(f, &l_split, 1);
138
angle_best = angle_normalized_v3v3(no_a, no_b);
147
*r_angle = angle_best;
154
static bool bm_face_split_by_angle(BMesh *bm, BMFace *f, BMFace *r_f_pair[2], const float angle_limit)
159
if (bm_face_split_find(f, v_pair, &angle) && (angle > angle_limit)) {
162
f_new = BM_face_split(bm, f, v_pair[0], v_pair[1], &l_new, NULL, false);
167
BMO_elem_flag_enable(bm, f, FACE_OUT);
168
BMO_elem_flag_enable(bm, f_new, FACE_OUT);
169
BMO_elem_flag_enable(bm, l_new->e, EDGE_OUT);
178
void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op)
182
int totface = 0, totloop = 0;
183
BLI_LINKSTACK_DECLARE(fstack, BMFace *);
185
const float angle_limit = BMO_slot_float_get(op->slots_in, "angle_limit");
188
BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
199
BLI_LINKSTACK_INIT(fstack);
201
BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
203
BLI_LINKSTACK_PUSH(fstack, f);
207
while ((f = BLI_LINKSTACK_POP(fstack))) {
209
if (bm_face_split_by_angle(bm, f, f_pair, angle_limit)) {
211
for (j = 0; j < 2; j++) {
212
BM_face_normal_update(f_pair[j]);
213
if (f_pair[j]->len > 3) {
214
BLI_LINKSTACK_PUSH(fstack, f_pair[j]);
220
BLI_LINKSTACK_FREE(fstack);
222
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
223
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);