Blender  V3.3
editmesh.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "DNA_listBase.h"
11 #include "DNA_mesh_types.h"
12 #include "DNA_object_types.h"
13 
14 #include "BLI_bitmap.h"
15 #include "BLI_math.h"
16 
17 #include "BKE_DerivedMesh.h"
18 #include "BKE_customdata.h"
19 #include "BKE_editmesh.h"
20 #include "BKE_editmesh_cache.h"
21 #include "BKE_lib_id.h"
22 #include "BKE_mesh.h"
23 #include "BKE_mesh_iterators.h"
24 #include "BKE_mesh_wrapper.h"
25 #include "BKE_object.h"
26 
27 #include "DEG_depsgraph_query.h"
28 
30 {
31  BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__);
32  em->bm = bm;
33  return em;
34 }
35 
37 {
38  BMEditMesh *em_copy = MEM_callocN(sizeof(BMEditMesh), __func__);
39  *em_copy = *em;
40 
41  em_copy->bm = BM_mesh_copy(em->bm);
42 
43  /* The tessellation is NOT calculated on the copy here,
44  * because currently all the callers of this function use
45  * it to make a backup copy of the #BMEditMesh to restore
46  * it in the case of errors in an operation. For performance reasons,
47  * in that case it makes more sense to do the
48  * tessellation only when/if that copy ends up getting used. */
49  em_copy->looptris = NULL;
50 
51  /* Copy various settings. */
52  em_copy->selectmode = em->selectmode;
53  em_copy->mat_nr = em->mat_nr;
54 
55  return em_copy;
56 }
57 
59 {
60  BLI_assert(ob->type == OB_MESH);
61  /* sanity check */
62 #if 0 /* disable in mutlti-object edit. */
63 # ifndef NDEBUG
64  if (((Mesh *)ob->data)->edit_mesh) {
65  BLI_assert(((Mesh *)ob->data)->edit_mesh->ob == ob);
66  }
67 # endif
68 #endif
69  return ((Mesh *)ob->data)->edit_mesh;
70 }
71 
74 {
75  /* allocating space before calculating the tessellation */
76 
77  BMesh *bm = em->bm;
78 
79  /* This assumes all faces can be scan-filled, which isn't always true,
80  * worst case we over allocate a little which is acceptable. */
81  const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
82  const int looptris_tot_prev_alloc = em->looptris ?
83  (MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) :
84  0;
85 
86  BMLoop *(*looptris)[3];
87 
88  /* this means no reallocs for quad dominant models, for */
89  if ((em->looptris != NULL) &&
90  /* (*em->tottri >= looptris_tot)) */
91  /* Check against allocated size in case we over allocated a little. */
92  ((looptris_tot_prev_alloc >= looptris_tot) &&
93  (looptris_tot_prev_alloc <= looptris_tot * 2))) {
94  looptris = em->looptris;
95  }
96  else {
97  if (em->looptris) {
98  MEM_freeN(em->looptris);
99  }
100  looptris = MEM_mallocN(sizeof(*looptris) * looptris_tot, __func__);
101  }
102 
103  em->looptris = looptris;
104  em->tottri = looptris_tot;
105 
106  /* after allocating the em->looptris, we're ready to tessellate */
108 }
109 
111  const struct BMeshCalcTessellation_Params *params)
112 {
114 
115  /* commented because editbmesh_build_data() ensures we get tessfaces */
116 #if 0
117  if (em->mesh_eval_final && em->mesh_eval_final == em->mesh_eval_cage) {
118  BKE_mesh_runtime_looptri_ensure(em->mesh_eval_final);
119  }
120  else if (em->mesh_eval_final) {
121  BKE_mesh_runtime_looptri_ensure(em->mesh_eval_final);
122  BKE_mesh_runtime_looptri_ensure(em->mesh_eval_cage);
123  }
124 #endif
125 }
126 
128 {
130  &(const struct BMeshCalcTessellation_Params){
131  .face_normals = false,
132  });
133 }
134 
136 {
138  &(const struct BMeshCalcTessellation_Params){
139  .face_normals = true,
140  });
142  &(const struct BMeshNormalsUpdate_Params){
143  .face_normals = false,
144  });
145 }
146 
148  struct BMPartialUpdate *bmpinfo,
149  const struct BMeshCalcTessellation_Params *params)
150 {
151  BLI_assert(em->tottri == poly_to_tri_count(em->bm->totface, em->bm->totloop));
152  BLI_assert(em->looptris != NULL);
153 
155 }
156 
158 {
160  bmpinfo,
161  &(const struct BMeshCalcTessellation_Params){
162  .face_normals = false,
163  });
164 }
165 
167  struct BMPartialUpdate *bmpinfo)
168 {
170  bmpinfo,
171  &(const struct BMeshCalcTessellation_Params){
172  .face_normals = true,
173  });
175  bmpinfo,
176  &(const struct BMeshNormalsUpdate_Params){
177  .face_normals = false,
178  });
179 }
180 
182 {
183 
184  if (em->looptris) {
185  MEM_freeN(em->looptris);
186  }
187 
188  if (em->bm) {
189  BM_mesh_free(em->bm);
190  }
191 }
192 
193 struct CageUserData {
194  int totvert;
197 };
198 
199 static void cage_mapped_verts_callback(void *userData,
200  int index,
201  const float co[3],
202  const float UNUSED(no[3]))
203 {
204  struct CageUserData *data = userData;
205 
206  if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
207  BLI_BITMAP_ENABLE(data->visit_bitmap, index);
208  copy_v3_v3(data->cos_cage[index], co);
209  }
210 }
211 
213  BMEditMesh *em,
214  struct Scene *scene,
215  Object *ob,
216  int *r_vert_len))[3]
217 {
219  float(*cos_cage)[3] = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
220 
221  /* When initializing cage verts, we only want the first cage coordinate for each vertex,
222  * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate. */
223  BLI_bitmap *visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
224 
225  struct CageUserData data;
226  data.totvert = em->bm->totvert;
227  data.cos_cage = cos_cage;
228  data.visit_bitmap = visit_bitmap;
229 
231 
233 
234  if (r_vert_len) {
235  *r_vert_len = em->bm->totvert;
236  }
237 
238  return cos_cage;
239 }
240 
242  BMEditMesh *em,
243  struct Scene *scene,
244  Object *ob,
245  int *r_vert_len,
246  bool *r_is_alloc))[3]
247 {
248  const float(*coords)[3] = NULL;
249  *r_is_alloc = false;
250 
251  Mesh *me = ob->data;
252  Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
253  Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object_eval);
254 
255  if ((me->runtime.edit_data != NULL) && (me->runtime.edit_data->vertexCos != NULL)) {
256  /* Deformed, and we have deformed coords already. */
257  coords = me->runtime.edit_data->vertexCos;
258  }
259  else if ((editmesh_eval_final != NULL) &&
260  (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
261  /* If this is an edit-mesh type, leave NULL as we can use the vertex coords. */
262  }
263  else {
264  /* Constructive modifiers have been used, we need to allocate coordinates. */
265  *r_is_alloc = true;
266  coords = BKE_editmesh_vert_coords_alloc(depsgraph, em, scene, ob, r_vert_len);
267  }
268  return coords;
269 }
270 
272 {
273  return BM_mesh_vert_coords_alloc(em->bm, r_vert_len);
274 }
275 
277 {
278  BMesh *bm = em->bm;
279 
280  /* We need to create custom-loop-normals (CLNORS) data if none exist yet,
281  * otherwise there is no way to edit them.
282  * Similar code to #MESH_OT_customdata_custom_splitnormals_add operator,
283  * we want to keep same shading in case we were using auto-smooth so far.
284  * NOTE: there is a problem here, which is that if someone starts a normal editing operation on
285  * previously auto-smooth-ed mesh, and cancel that operation, generated CLNORS data remain,
286  * with related sharp edges (and hence auto-smooth is 'lost').
287  * Not sure how critical this is, and how to fix that issue? */
289  if (me->flag & ME_AUTOSMOOTH) {
291  }
292  }
293 
295 }
296 
298 {
299  if (!(me->flag & ME_AUTOSMOOTH)) {
300  me->flag |= ME_AUTOSMOOTH;
302  }
303 }
304 
306 {
307  if (object->runtime.editmesh_bb_cage == NULL) {
308  float min[3], max[3];
309  INIT_MINMAX(min, max);
310  if (object->runtime.editmesh_eval_cage) {
312  }
313 
314  object->runtime.editmesh_bb_cage = MEM_callocN(sizeof(BoundBox), "BMEditMesh.bb_cage");
316  }
317 
318  return object->runtime.editmesh_bb_cage;
319 }
typedef float(TangentPoint)[2]
struct Mesh * editbmesh_get_eval_cage(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *obedit, struct BMEditMesh *em, const struct CustomData_MeshMasks *dataMask)
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const struct CustomData *data, int type)
const CustomData_MeshMasks CD_MASK_BAREMESH
Definition: customdata.cc:2051
void BKE_mesh_foreach_mapped_vert(struct Mesh *mesh, void(*func)(void *userData, int index, const float co[3], const float no[3]), void *userData, MeshForeachFlag flag)
@ MESH_FOREACH_NOP
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
bool BKE_mesh_wrapper_minmax(const struct Mesh *me, float min[3], float max[3])
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_editmesh_eval_final(const struct Object *object)
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3])
Definition: object.cc:3645
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:64
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:81
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define INIT_MINMAX(min, max)
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ CD_CUSTOMLOOPNORMAL
These structs are the foundation for all linked lists in the library system.
@ ME_WRAPPER_TYPE_BMESH
@ ME_AUTOSMOOTH
Object is a sort of wrapper for general info.
@ OB_MESH
Read Guarded memory(de)allocation.
BMesh * BM_mesh_copy(BMesh *bm_old)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
float(* BM_mesh_vert_coords_alloc(BMesh *bm, int *r_vert_len))[3]
Definition: bmesh_mesh.cc:1320
void BM_mesh_normals_update_with_partial_ex(BMesh *UNUSED(bm), const BMPartialUpdate *bmpinfo, const struct BMeshNormalsUpdate_Params *params)
void BM_mesh_normals_update_ex(BMesh *bm, const struct BMeshNormalsUpdate_Params *params)
BMesh Compute Normals.
void BM_lnorspace_update(BMesh *bm)
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
void BM_mesh_calc_tessellation_ex(BMesh *bm, BMLoop *(*looptris)[3], const struct BMeshCalcTessellation_Params *params)
void BM_mesh_calc_tessellation_with_partial_ex(BMesh *bm, BMLoop *(*looptris)[3], const BMPartialUpdate *bmpinfo, const struct BMeshCalcTessellation_Params *params)
Scene scene
const Depsgraph * depsgraph
void BKE_editmesh_free_data(BMEditMesh *em)
Definition: editmesh.c:181
void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, Mesh *me)
Definition: editmesh.c:297
BoundBox * BKE_editmesh_cage_boundbox_get(struct Object *object, BMEditMesh *UNUSED(em))
Definition: editmesh.c:305
void BKE_editmesh_looptri_calc(BMEditMesh *em)
Definition: editmesh.c:127
static void editmesh_tessface_calc_intern(BMEditMesh *em, const struct BMeshCalcTessellation_Params *params)
Definition: editmesh.c:72
void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em)
Definition: editmesh.c:135
static void cage_mapped_verts_callback(void *userData, int index, const float co[3], const float UNUSED(no[3]))
Definition: editmesh.c:199
void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em, struct BMPartialUpdate *bmpinfo)
Definition: editmesh.c:166
void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me)
Definition: editmesh.c:276
BMEditMesh * BKE_editmesh_create(BMesh *bm)
Definition: editmesh.c:29
void BKE_editmesh_looptri_calc_ex(BMEditMesh *em, const struct BMeshCalcTessellation_Params *params)
Definition: editmesh.c:110
const float(* BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph, BMEditMesh *em, struct Scene *scene, Object *ob, int *r_vert_len, bool *r_is_alloc))[3]
Definition: editmesh.c:241
BMEditMesh * BKE_editmesh_copy(BMEditMesh *em)
Definition: editmesh.c:36
float(* BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]
Definition: editmesh.c:271
void BKE_editmesh_looptri_calc_with_partial(BMEditMesh *em, struct BMPartialUpdate *bmpinfo)
Definition: editmesh.c:157
float(* BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph, BMEditMesh *em, struct Scene *scene, Object *ob, int *r_vert_len))[3]
Definition: editmesh.c:212
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:58
void BKE_editmesh_looptri_calc_with_partial_ex(BMEditMesh *em, struct BMPartialUpdate *bmpinfo, const struct BMeshCalcTessellation_Params *params)
Definition: editmesh.c:147
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:26
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define min(a, b)
Definition: sort.c:35
short selectmode
Definition: BKE_editmesh.h:52
struct BMLoop *(* looptris)[3]
Definition: BKE_editmesh.h:48
struct BMesh * bm
Definition: BKE_editmesh.h:40
short mat_nr
Definition: BKE_editmesh.h:54
int totloop
Definition: bmesh_class.h:297
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
BLI_bitmap * visit_bitmap
Definition: editmesh.c:196
float(* cos_cage)[3]
Definition: editmesh.c:195
const float(* vertexCos)[3]
struct EditMeshData * edit_data
float smoothresh
uint16_t flag
Mesh_Runtime runtime
struct BoundBox * editmesh_bb_cage
struct Mesh * editmesh_eval_cage
Object_Runtime runtime
void * data
float max