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 * The Original Code is Copyright (C) 2005 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup bke
22 */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "DNA_listBase.h"
27 #include "DNA_mesh_types.h"
28 #include "DNA_object_types.h"
29
30 #include "BLI_bitmap.h"
31 #include "BLI_math.h"
32
33 #include "BKE_DerivedMesh.h"
34 #include "BKE_editmesh.h"
35 #include "BKE_editmesh_cache.h"
36 #include "BKE_lib_id.h"
37 #include "BKE_mesh.h"
38 #include "BKE_mesh_iterators.h"
39 #include "BKE_mesh_wrapper.h"
40 #include "BKE_object.h"
41
BKE_editmesh_create(BMesh * bm,const bool do_tessellate)42 BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate)
43 {
44 BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__);
45
46 em->bm = bm;
47 if (do_tessellate) {
48 BKE_editmesh_looptri_calc(em);
49 }
50
51 return em;
52 }
53
BKE_editmesh_copy(BMEditMesh * em)54 BMEditMesh *BKE_editmesh_copy(BMEditMesh *em)
55 {
56 BMEditMesh *em_copy = MEM_callocN(sizeof(BMEditMesh), __func__);
57 *em_copy = *em;
58
59 em_copy->mesh_eval_cage = em_copy->mesh_eval_final = NULL;
60 em_copy->bb_cage = NULL;
61
62 em_copy->bm = BM_mesh_copy(em->bm);
63
64 /* The tessellation is NOT calculated on the copy here,
65 * because currently all the callers of this function use
66 * it to make a backup copy of the #BMEditMesh to restore
67 * it in the case of errors in an operation. For performance reasons,
68 * in that case it makes more sense to do the
69 * tessellation only when/if that copy ends up getting used. */
70 em_copy->looptris = NULL;
71
72 /* Copy various settings. */
73 em_copy->selectmode = em->selectmode;
74 em_copy->mat_nr = em->mat_nr;
75
76 return em_copy;
77 }
78
79 /**
80 * \brief Return the BMEditMesh for a given object
81 *
82 * \note this function assumes this is a mesh object,
83 * don't add NULL data check here. caller must do that
84 */
BKE_editmesh_from_object(Object * ob)85 BMEditMesh *BKE_editmesh_from_object(Object *ob)
86 {
87 BLI_assert(ob->type == OB_MESH);
88 /* sanity check */
89 #if 0 /* disable in mutlti-object edit. */
90 # ifndef NDEBUG
91 if (((Mesh *)ob->data)->edit_mesh) {
92 BLI_assert(((Mesh *)ob->data)->edit_mesh->ob == ob);
93 }
94 # endif
95 #endif
96 return ((Mesh *)ob->data)->edit_mesh;
97 }
98
editmesh_tessface_calc_intern(BMEditMesh * em)99 static void editmesh_tessface_calc_intern(BMEditMesh *em)
100 {
101 /* allocating space before calculating the tessellation */
102
103 BMesh *bm = em->bm;
104
105 /* This assumes all faces can be scan-filled, which isn't always true,
106 * worst case we over allocate a little which is acceptable. */
107 const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
108 const int looptris_tot_prev_alloc = em->looptris ?
109 (MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) :
110 0;
111
112 BMLoop *(*looptris)[3];
113
114 /* this means no reallocs for quad dominant models, for */
115 if ((em->looptris != NULL) &&
116 /* (*em->tottri >= looptris_tot)) */
117 /* Check against allocated size in case we over allocated a little. */
118 ((looptris_tot_prev_alloc >= looptris_tot) &&
119 (looptris_tot_prev_alloc <= looptris_tot * 2))) {
120 looptris = em->looptris;
121 }
122 else {
123 if (em->looptris) {
124 MEM_freeN(em->looptris);
125 }
126 looptris = MEM_mallocN(sizeof(*looptris) * looptris_tot, __func__);
127 }
128
129 em->looptris = looptris;
130
131 /* after allocating the em->looptris, we're ready to tessellate */
132 BM_mesh_calc_tessellation(em->bm, em->looptris, &em->tottri);
133 }
134
BKE_editmesh_looptri_calc(BMEditMesh * em)135 void BKE_editmesh_looptri_calc(BMEditMesh *em)
136 {
137 editmesh_tessface_calc_intern(em);
138
139 /* commented because editbmesh_build_data() ensures we get tessfaces */
140 #if 0
141 if (em->mesh_eval_final && em->mesh_eval_final == em->mesh_eval_cage) {
142 BKE_mesh_runtime_looptri_ensure(em->mesh_eval_final);
143 }
144 else if (em->mesh_eval_final) {
145 BKE_mesh_runtime_looptri_ensure(em->mesh_eval_final);
146 BKE_mesh_runtime_looptri_ensure(em->mesh_eval_cage);
147 }
148 #endif
149 }
150
BKE_editmesh_free_derivedmesh(BMEditMesh * em)151 void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
152 {
153 if (em->mesh_eval_cage) {
154 BKE_id_free(NULL, em->mesh_eval_cage);
155 }
156 if (em->mesh_eval_final && em->mesh_eval_final != em->mesh_eval_cage) {
157 BKE_id_free(NULL, em->mesh_eval_final);
158 }
159 em->mesh_eval_cage = em->mesh_eval_final = NULL;
160
161 MEM_SAFE_FREE(em->bb_cage);
162 }
163
164 /*does not free the BMEditMesh struct itself*/
BKE_editmesh_free(BMEditMesh * em)165 void BKE_editmesh_free(BMEditMesh *em)
166 {
167 BKE_editmesh_free_derivedmesh(em);
168
169 if (em->looptris) {
170 MEM_freeN(em->looptris);
171 }
172
173 if (em->bm) {
174 BM_mesh_free(em->bm);
175 }
176 }
177
178 struct CageUserData {
179 int totvert;
180 float (*cos_cage)[3];
181 BLI_bitmap *visit_bitmap;
182 };
183
cage_mapped_verts_callback(void * userData,int index,const float co[3],const float UNUSED (no_f[3]),const short UNUSED (no_s[3]))184 static void cage_mapped_verts_callback(void *userData,
185 int index,
186 const float co[3],
187 const float UNUSED(no_f[3]),
188 const short UNUSED(no_s[3]))
189 {
190 struct CageUserData *data = userData;
191
192 if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
193 BLI_BITMAP_ENABLE(data->visit_bitmap, index);
194 copy_v3_v3(data->cos_cage[index], co);
195 }
196 }
197
BKE_editmesh_vert_coords_alloc(struct Depsgraph * depsgraph,BMEditMesh * em,struct Scene * scene,Object * ob,int * r_vert_len)198 float (*BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph,
199 BMEditMesh *em,
200 struct Scene *scene,
201 Object *ob,
202 int *r_vert_len))[3]
203 {
204 Mesh *cage;
205 BLI_bitmap *visit_bitmap;
206 struct CageUserData data;
207 float(*cos_cage)[3];
208
209 cage = editbmesh_get_eval_cage(depsgraph, scene, ob, em, &CD_MASK_BAREMESH);
210 cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
211
212 /* when initializing cage verts, we only want the first cage coordinate for each vertex,
213 * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
214 visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
215
216 data.totvert = em->bm->totvert;
217 data.cos_cage = cos_cage;
218 data.visit_bitmap = visit_bitmap;
219
220 BKE_mesh_foreach_mapped_vert(cage, cage_mapped_verts_callback, &data, MESH_FOREACH_NOP);
221
222 MEM_freeN(visit_bitmap);
223
224 if (r_vert_len) {
225 *r_vert_len = em->bm->totvert;
226 }
227
228 return cos_cage;
229 }
230
BKE_editmesh_vert_coords_when_deformed(struct Depsgraph * depsgraph,BMEditMesh * em,struct Scene * scene,Object * ob,int * r_vert_len,bool * r_is_alloc)231 const float (*BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph,
232 BMEditMesh *em,
233 struct Scene *scene,
234 Object *ob,
235 int *r_vert_len,
236 bool *r_is_alloc))[3]
237 {
238 const float(*coords)[3] = NULL;
239 *r_is_alloc = false;
240
241 Mesh *me = ob->data;
242
243 if ((me->runtime.edit_data != NULL) && (me->runtime.edit_data->vertexCos != NULL)) {
244 /* Deformed, and we have deformed coords already. */
245 coords = me->runtime.edit_data->vertexCos;
246 }
247 else if ((em->mesh_eval_final != NULL) &&
248 (em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
249 /* If this is an edit-mesh type, leave NULL as we can use the vertex coords. . */
250 }
251 else {
252 /* Constructive modifiers have been used, we need to allocate coordinates. */
253 *r_is_alloc = true;
254 coords = BKE_editmesh_vert_coords_alloc(depsgraph, em, scene, ob, r_vert_len);
255 }
256 return coords;
257 }
258
BKE_editmesh_vert_coords_alloc_orco(BMEditMesh * em,int * r_vert_len)259 float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]
260 {
261 return BM_mesh_vert_coords_alloc(em->bm, r_vert_len);
262 }
263
BKE_editmesh_lnorspace_update(BMEditMesh * em,Mesh * me)264 void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me)
265 {
266 BMesh *bm = em->bm;
267
268 /* We need to create custom-loop-normals (CLNORS) data if none exist yet,
269 * otherwise there is no way to edit them.
270 * Similar code to #MESH_OT_customdata_custom_splitnormals_add operator,
271 * we want to keep same shading in case we were using auto-smooth so far.
272 * Note: there is a problem here, which is that if someone starts a normal editing operation on
273 * previously auto-smooth-ed mesh, and cancel that operation, generated CLNORS data remain,
274 * with related sharp edges (and hence auto-smooth is 'lost').
275 * Not sure how critical this is, and how to fix that issue? */
276 if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
277 if (me->flag & ME_AUTOSMOOTH) {
278 BM_edges_sharp_from_angle_set(bm, me->smoothresh);
279 }
280 }
281
282 BM_lnorspace_update(bm);
283 }
284
285 /* If autosmooth not already set, set it */
BKE_editmesh_ensure_autosmooth(BMEditMesh * em,Mesh * me)286 void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, Mesh *me)
287 {
288 if (!(me->flag & ME_AUTOSMOOTH)) {
289 me->flag |= ME_AUTOSMOOTH;
290 BKE_editmesh_lnorspace_update(em, me);
291 }
292 }
293
BKE_editmesh_cage_boundbox_get(BMEditMesh * em)294 BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em)
295 {
296 if (em->bb_cage == NULL) {
297 float min[3], max[3];
298 INIT_MINMAX(min, max);
299 if (em->mesh_eval_cage) {
300 BKE_mesh_wrapper_minmax(em->mesh_eval_cage, min, max);
301 }
302
303 em->bb_cage = MEM_callocN(sizeof(BoundBox), "BMEditMesh.bb_cage");
304 BKE_boundbox_init_from_minmax(em->bb_cage, min, max);
305 }
306
307 return em->bb_cage;
308 }
309