Cleanup: remove redundant doxygen \file argument
[blender.git] / source / blender / bmesh / operators / bmo_poke.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file \ingroup bmesh
18  *
19  * Pokes a face.
20  *
21  * Splits a face into a triangle fan.
22  */
23
24 #include "BLI_math.h"
25
26 #include "bmesh.h"
27
28 #include "intern/bmesh_operators_private.h" /* own include */
29
30 #include "BKE_customdata.h"
31
32 #define ELE_NEW 1
33
34 /**
35  * Pokes a face
36  *
37  * Splits a face into a triangle fan.
38  * Iterate over all selected faces, create a new center vertex and
39  * create triangles between original face edges and new center vertex.
40  */
41 void bmo_poke_exec(BMesh *bm, BMOperator *op)
42 {
43         const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
44         BMOIter oiter;
45         BMFace *f;
46
47         const float offset = BMO_slot_float_get(op->slots_in, "offset");
48         const bool use_relative_offset = BMO_slot_bool_get(op->slots_in,  "use_relative_offset");
49         const int center_mode = BMO_slot_int_get(op->slots_in, "center_mode");
50         void (*bm_face_calc_center_fn)(const BMFace *f, float r_cent[3]);
51
52         switch (center_mode) {
53                 case BMOP_POKE_MEDIAN_WEIGHTED:
54                         bm_face_calc_center_fn = BM_face_calc_center_median_weighted;
55                         break;
56                 case BMOP_POKE_BOUNDS:
57                         bm_face_calc_center_fn = BM_face_calc_center_bounds;
58                         break;
59                 case BMOP_POKE_MEDIAN:
60                         bm_face_calc_center_fn = BM_face_calc_center_median;
61                         break;
62                 default:
63                         BLI_assert(0);
64                         return;
65         }
66
67         BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
68                 BMFace *f_new;
69                 float f_center[3], f_center_mean[3];
70                 BMVert *v_center = NULL;
71                 BMLoop *l_iter, *l_first;
72                 /* only interpolate the central loop from the face once,
73                  * then copy to all others in the fan */
74                 BMLoop *l_center_example;
75
76                 /* 1.0 or the average length from the center to the face verts */
77                 float offset_fac;
78
79                 int i;
80
81                 bm_face_calc_center_fn(f, f_center);
82                 v_center = BM_vert_create(bm, f_center, NULL, BM_CREATE_NOP);
83                 BMO_vert_flag_enable(bm, v_center, ELE_NEW);
84
85                 if (cd_loop_mdisp_offset != -1) {
86                         if (center_mode == BMOP_POKE_MEDIAN) {
87                                 copy_v3_v3(f_center_mean, f_center);
88                         }
89                         else {
90                                 BM_face_calc_center_median(f, f_center_mean);
91                         }
92                 }
93
94                 /* handled by BM_loop_interp_from_face */
95                 // BM_vert_interp_from_face(bm, v_center, f);
96
97                 if (use_relative_offset) {
98                         offset_fac = 0.0f;
99                 }
100                 else {
101                         offset_fac = 1.0f;
102                 }
103
104                 i = 0;
105                 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
106                 do {
107                         BMLoop *l_new;
108
109                         f_new = BM_face_create_quad_tri(bm, l_iter->v, l_iter->next->v, v_center, NULL, f, BM_CREATE_NOP);
110                         l_new = BM_FACE_FIRST_LOOP(f_new);
111
112                         if (i == 0) {
113                                 l_center_example = l_new->prev;
114                                 BM_loop_interp_from_face(bm, l_center_example, f, true, false);
115                         }
116                         else {
117                                 BM_elem_attrs_copy(bm, bm, l_center_example, l_new->prev);
118                         }
119
120                         /* Copy Loop Data */
121                         BM_elem_attrs_copy(bm, bm, l_iter, l_new);
122                         BM_elem_attrs_copy(bm, bm, l_iter->next, l_new->next);
123
124                         BMO_face_flag_enable(bm, f_new, ELE_NEW);
125
126                         if (cd_loop_mdisp_offset != -1) {
127                                 float f_new_center[3];
128                                 BM_face_calc_center_median(f_new, f_new_center);
129                                 BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset);
130                         }
131
132                         if (use_relative_offset) {
133                                 offset_fac += len_v3v3(f_center, l_iter->v->co);
134                         }
135
136                 } while ((void)i++, (l_iter = l_iter->next) != l_first);
137
138                 if (use_relative_offset) {
139                         offset_fac /= (float)f->len;
140                 }
141                 /* else remain at 1.0 */
142
143                 copy_v3_v3(v_center->no, f->no);
144                 madd_v3_v3fl(v_center->co, v_center->no, offset * offset_fac);
145
146                 /* Kill Face */
147                 BM_face_kill(bm, f);
148         }
149
150         BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, ELE_NEW);
151         BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW);
152 }