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