Cleanup: spelling
[blender.git] / source / blender / bmesh / operators / bmo_planar_faces.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/bmesh/operators/bmo_planar_faces.c
22  *  \ingroup bmesh
23  *
24  * Iteratively flatten 4+ sided faces.
25  */
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_math.h"
30 #include "BLI_ghash.h"
31
32 #include "bmesh.h"
33
34 #include "intern/bmesh_operators_private.h" /* own include */
35
36 #define ELE_VERT_ADJUST (1 << 0)
37 #define ELE_FACE_ADJUST (1 << 1)
38
39 struct VertAccum {
40         float co[3];
41         int co_tot;
42 };
43
44 void bmo_planar_faces_exec(BMesh *bm, BMOperator *op)
45 {
46         const float fac = BMO_slot_float_get(op->slots_in, "factor");
47         const int iterations = BMO_slot_int_get(op->slots_in, "iterations");
48         const int faces_num = BMO_slot_buffer_count(op->slots_in, "faces");
49
50         const float eps = 0.00001f;
51         const float eps_sq = SQUARE(eps);
52
53         BMOIter oiter;
54         BMFace *f;
55         BLI_mempool *vert_accum_pool;
56         GHash *vaccum_map;
57         float (*faces_center)[3];
58         int i, iter_step, shared_vert_num;
59
60         faces_center = MEM_mallocN(sizeof(*faces_center) * faces_num, __func__);
61
62         shared_vert_num = 0;
63         BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
64                 BMLoop *l_iter, *l_first;
65
66                 if (f->len == 3) {
67                         continue;
68                 }
69
70                 BM_face_calc_center_mean_weighted(f, faces_center[i]);
71
72                 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
73                 do {
74                         if (!BMO_elem_flag_test(bm, l_iter->v, ELE_VERT_ADJUST)) {
75                                 BMO_elem_flag_enable(bm, l_iter->v, ELE_VERT_ADJUST);
76                                 shared_vert_num += 1;
77                         }
78                 } while ((l_iter = l_iter->next) != l_first);
79
80                 BMO_elem_flag_enable(bm, f, ELE_FACE_ADJUST);
81         }
82
83         vert_accum_pool = BLI_mempool_create(sizeof(struct VertAccum), 0, 512, BLI_MEMPOOL_NOP);
84         vaccum_map = BLI_ghash_ptr_new_ex(__func__, shared_vert_num);
85
86         for (iter_step = 0; iter_step < iterations; iter_step++) {
87                 GHashIterator gh_iter;
88                 bool changed = false;
89
90                 BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
91                         BMLoop *l_iter, *l_first;
92                         float plane[4];
93
94                         if (!BMO_elem_flag_test(bm, f, ELE_FACE_ADJUST)) {
95                                 continue;
96                         }
97                         BMO_elem_flag_disable(bm, f, ELE_FACE_ADJUST);
98
99                         BLI_assert(f->len != 3);
100
101                         /* keep original face data (else we 'move' the face) */
102 #if 0
103                         BM_face_normal_update(f);
104                         BM_face_calc_center_mean_weighted(f, f_center);
105 #endif
106
107                         plane_from_point_normal_v3(plane, faces_center[i], f->no);
108
109                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
110                         do {
111                                 struct VertAccum *va;
112                                 void **va_p;
113                                 float co[3];
114
115                                 if (!BLI_ghash_ensure_p(vaccum_map, l_iter->v, &va_p)) {
116                                         *va_p = BLI_mempool_calloc(vert_accum_pool);
117                                 }
118                                 va = *va_p;
119
120                                 closest_to_plane_normalized_v3(co, plane, l_iter->v->co);
121                                 va->co_tot += 1;
122
123                                 interp_v3_v3v3(va->co, va->co, co, 1.0f / (float)va->co_tot);
124                         } while ((l_iter = l_iter->next) != l_first);
125                 }
126
127                 GHASH_ITER (gh_iter, vaccum_map) {
128                         BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
129                         struct VertAccum *va = BLI_ghashIterator_getValue(&gh_iter);
130                         BMIter iter;
131
132                         if (len_squared_v3v3(v->co, va->co) > eps_sq) {
133                                 BMO_elem_flag_enable(bm, v, ELE_VERT_ADJUST);
134                                 interp_v3_v3v3(v->co, v->co, va->co, fac);
135                                 changed = true;
136                         }
137
138                         /* tag for re-calculation */
139                         BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
140                                 if (f->len != 3) {
141                                         BMO_elem_flag_enable(bm, f, ELE_FACE_ADJUST);
142                                 }
143                         }
144                 }
145
146                 /* if nothing changed, break out early */
147                 if (changed == false) {
148                         break;
149                 }
150
151                 BLI_ghash_clear(vaccum_map, NULL, NULL);
152                 BLI_mempool_clear(vert_accum_pool);
153         }
154
155         MEM_freeN(faces_center);
156         BLI_ghash_free(vaccum_map, NULL, NULL);
157         BLI_mempool_destroy(vert_accum_pool);
158 }