Blender  V3.3
mesh_wrapper.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
21 #include "MEM_guardedalloc.h"
22 
23 #include "DNA_mesh_types.h"
24 #include "DNA_meshdata_types.h"
25 #include "DNA_modifier_types.h"
26 #include "DNA_object_types.h"
27 
28 #include "BLI_ghash.h"
29 #include "BLI_math.h"
30 #include "BLI_task.hh"
31 #include "BLI_threads.h"
32 #include "BLI_utildefines.h"
33 
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_runtime.h"
39 #include "BKE_mesh_wrapper.h"
40 #include "BKE_modifier.h"
41 #include "BKE_object.h"
42 #include "BKE_subdiv.h"
43 #include "BKE_subdiv_mesh.h"
44 #include "BKE_subdiv_modifier.h"
45 
46 #include "DEG_depsgraph.h"
47 #include "DEG_depsgraph_query.h"
48 
50  const CustomData_MeshMasks *cd_mask_extra,
51  const float (*vert_coords)[3],
52  const Mesh *me_settings)
53 {
54  Mesh *me = static_cast<Mesh *>(BKE_id_new_nomain(ID_ME, nullptr));
55  BKE_mesh_copy_parameters_for_eval(me, me_settings);
57 
59  if (cd_mask_extra) {
60  me->runtime.cd_mask_extra = *cd_mask_extra;
61  }
62 
63  /* Use edit-mesh directly where possible. */
64  me->runtime.is_original = true;
65 
66  me->edit_mesh = static_cast<BMEditMesh *>(MEM_dupallocN(em));
67  me->edit_mesh->is_shallow_copy = true;
68 
69  /* Make sure we crash if these are ever used. */
70 #ifdef DEBUG
71  me->totvert = INT_MAX;
72  me->totedge = INT_MAX;
73  me->totpoly = INT_MAX;
74  me->totloop = INT_MAX;
75 #else
76  me->totvert = 0;
77  me->totedge = 0;
78  me->totpoly = 0;
79  me->totloop = 0;
80 #endif
81 
82  EditMeshData *edit_data = me->runtime.edit_data;
83  edit_data->vertexCos = vert_coords;
84  return me;
85 }
86 
88  const CustomData_MeshMasks *cd_mask_extra,
89  const Mesh *me_settings)
90 {
91  return BKE_mesh_wrapper_from_editmesh_with_coords(em, cd_mask_extra, nullptr, me_settings);
92 }
93 
95 {
96  ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime.eval_mutex;
97  BLI_mutex_lock(mesh_eval_mutex);
98 
100  BLI_mutex_unlock(mesh_eval_mutex);
101  return;
102  }
103 
104  /* Must isolate multithreaded tasks while holding a mutex lock. */
106  switch (static_cast<eMeshWrapperType>(me->runtime.wrapper_type)) {
107  case ME_WRAPPER_TYPE_MDATA:
108  case ME_WRAPPER_TYPE_SUBD: {
109  break; /* Quiet warning. */
110  }
111  case ME_WRAPPER_TYPE_BMESH: {
112  me->totvert = 0;
113  me->totedge = 0;
114  me->totpoly = 0;
115  me->totloop = 0;
116 
117  BLI_assert(me->edit_mesh != nullptr);
118  BLI_assert(me->runtime.edit_data != nullptr);
119 
120  BMEditMesh *em = me->edit_mesh;
121  BM_mesh_bm_to_me_for_eval(em->bm, me, &me->runtime.cd_mask_extra);
122 
123  /* Adding original index layers assumes that all BMesh mesh wrappers are created from
124  * original edit mode meshes (the only case where adding original indices makes sense).
125  * If that assumption is broken, the layers might be incorrect in that they might not
126  * actually be "original".
127  *
128  * There is also a performance aspect, where this also assumes that original indices are
129  * always needed when converting an edit mesh to a mesh. That might be wrong, but it's not
130  * harmful. */
131  BKE_mesh_ensure_default_orig_index_customdata_no_check(me);
132 
133  EditMeshData *edit_data = me->runtime.edit_data;
134  if (edit_data->vertexCos) {
135  BKE_mesh_vert_coords_apply(me, edit_data->vertexCos);
136  me->runtime.is_original = false;
137  }
138  break;
139  }
140  }
141 
142  if (me->runtime.wrapper_type_finalize) {
143  BKE_mesh_wrapper_deferred_finalize_mdata(me, &me->runtime.cd_mask_extra);
144  }
145 
146  /* Keep type assignment last, so that read-only access only uses the mdata code paths after all
147  * the underlying data has been initialized. */
148  me->runtime.wrapper_type = ME_WRAPPER_TYPE_MDATA;
149  });
150 
151  BLI_mutex_unlock(mesh_eval_mutex);
152 }
153 
154 bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])
155 {
156  switch ((eMeshWrapperType)me->runtime.wrapper_type) {
161  return BKE_mesh_minmax(me, min, max);
162  }
164  return false;
165 }
166 
167 /* -------------------------------------------------------------------- */
172  float (*vert_coords)[3],
173  int vert_coords_len)
174 {
175  switch ((eMeshWrapperType)me->runtime.wrapper_type) {
176  case ME_WRAPPER_TYPE_BMESH: {
177  BMesh *bm = me->edit_mesh->bm;
178  BLI_assert(vert_coords_len <= bm->totvert);
179  EditMeshData *edit_data = me->runtime.edit_data;
180  if (edit_data->vertexCos != nullptr) {
181  for (int i = 0; i < vert_coords_len; i++) {
182  copy_v3_v3(vert_coords[i], edit_data->vertexCos[i]);
183  }
184  }
185  else {
186  BMIter iter;
187  BMVert *v;
188  int i;
189  BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
190  copy_v3_v3(vert_coords[i], v->co);
191  }
192  }
193  return;
194  }
196  case ME_WRAPPER_TYPE_SUBD: {
197  BLI_assert(vert_coords_len <= me->totvert);
198  const MVert *mvert = me->mvert;
199  for (int i = 0; i < vert_coords_len; i++) {
200  copy_v3_v3(vert_coords[i], mvert[i].co);
201  }
202  return;
203  }
204  }
206 }
207 
209  float (*vert_coords)[3],
210  int vert_coords_len,
211  const float mat[4][4])
212 {
213  switch ((eMeshWrapperType)me->runtime.wrapper_type) {
214  case ME_WRAPPER_TYPE_BMESH: {
215  BMesh *bm = me->edit_mesh->bm;
216  BLI_assert(vert_coords_len == bm->totvert);
217  EditMeshData *edit_data = me->runtime.edit_data;
218  if (edit_data->vertexCos != nullptr) {
219  for (int i = 0; i < vert_coords_len; i++) {
220  mul_v3_m4v3(vert_coords[i], mat, edit_data->vertexCos[i]);
221  }
222  }
223  else {
224  BMIter iter;
225  BMVert *v;
226  int i;
227  BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
228  mul_v3_m4v3(vert_coords[i], mat, v->co);
229  }
230  }
231  return;
232  }
234  case ME_WRAPPER_TYPE_SUBD: {
235  BLI_assert(vert_coords_len == me->totvert);
236  const MVert *mvert = me->mvert;
237  for (int i = 0; i < vert_coords_len; i++) {
238  mul_v3_m4v3(vert_coords[i], mat, mvert[i].co);
239  }
240  return;
241  }
242  }
244 }
245 
248 /* -------------------------------------------------------------------- */
253 {
254  switch ((eMeshWrapperType)me->runtime.wrapper_type) {
256  return me->edit_mesh->bm->totvert;
259  return me->totvert;
260  }
262  return -1;
263 }
264 
266 {
267  switch ((eMeshWrapperType)me->runtime.wrapper_type) {
269  return me->edit_mesh->bm->totedge;
272  return me->totedge;
273  }
275  return -1;
276 }
277 
279 {
280  switch ((eMeshWrapperType)me->runtime.wrapper_type) {
282  return me->edit_mesh->bm->totloop;
285  return me->totloop;
286  }
288  return -1;
289 }
290 
292 {
293  switch ((eMeshWrapperType)me->runtime.wrapper_type) {
295  return me->edit_mesh->bm->totface;
298  return me->totpoly;
299  }
301  return -1;
302 }
303 
306 /* -------------------------------------------------------------------- */
311 {
313  if (runtime_data == nullptr || runtime_data->settings.level == 0) {
314  return me;
315  }
316 
317  /* Initialize the settings before ensuring the descriptor as this is checked to decide whether
318  * subdivision is needed at all, and checking the descriptor status might involve checking if the
319  * data is out-of-date, which is a very expensive operation. */
320  SubdivToMeshSettings mesh_settings;
321  mesh_settings.resolution = runtime_data->resolution;
322  mesh_settings.use_optimal_display = runtime_data->use_optimal_display;
323 
324  if (mesh_settings.resolution < 3) {
325  return me;
326  }
327 
328  Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, me, false);
329  if (subdiv == nullptr) {
330  /* Happens on bad topology, but also on empty input mesh. */
331  return me;
332  }
333  const bool use_clnors = runtime_data->use_loop_normals;
334  if (use_clnors) {
335  /* If custom normals are present and the option is turned on calculate the split
336  * normals and clear flag so the normals get interpolated to the result mesh. */
339  }
340 
341  Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me);
342 
343  if (use_clnors) {
344  float(*lnors)[3] = static_cast<float(*)[3]>(
345  CustomData_get_layer(&subdiv_mesh->ldata, CD_NORMAL));
346  BLI_assert(lnors != NULL);
347  BKE_mesh_set_custom_normals(subdiv_mesh, lnors);
350  }
351  else if (runtime_data->calc_loop_normals) {
352  BKE_mesh_calc_normals_split(subdiv_mesh);
353  }
354 
355  if (subdiv != runtime_data->subdiv) {
356  BKE_subdiv_free(subdiv);
357  }
358 
359  if (subdiv_mesh != me) {
360  if (me->runtime.mesh_eval != nullptr) {
361  BKE_id_free(nullptr, me->runtime.mesh_eval);
362  }
363  me->runtime.mesh_eval = subdiv_mesh;
365  }
366 
367  return me->runtime.mesh_eval;
368 }
369 
371 {
372  ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime.eval_mutex;
373  BLI_mutex_lock(mesh_eval_mutex);
374 
376  BLI_mutex_unlock(mesh_eval_mutex);
377  return me->runtime.mesh_eval;
378  }
379 
380  Mesh *result;
381 
382  /* Must isolate multithreaded tasks while holding a mutex lock. */
384 
385  BLI_mutex_unlock(mesh_eval_mutex);
386  return result;
387 }
388 
typedef float(TangentPoint)[2]
void CustomData_clear_layer_flag(struct CustomData *data, int type, int flag)
Definition: customdata.cc:2635
void * CustomData_get_layer(const struct CustomData *data, int type)
void CustomData_set_layer_flag(struct CustomData *data, int type, int flag)
Definition: customdata.cc:2626
bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em, struct EditMeshData *emd, float min[3], float max[3])
void * BKE_id_new_nomain(short type, const char *name)
Definition: lib_id.c:1173
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_mesh_copy_parameters_for_eval(struct Mesh *me_dst, const struct Mesh *me_src)
void BKE_mesh_calc_normals_split(struct Mesh *mesh)
Definition: mesh.cc:1911
bool BKE_mesh_minmax(const struct Mesh *me, float r_min[3], float r_max[3])
void BKE_mesh_set_custom_normals(struct Mesh *mesh, float(*r_custom_loopnors)[3])
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh)
General operations, lookup, etc. for blender objects.
void BKE_subdiv_free(Subdiv *subdiv)
Definition: subdiv.c:184
struct Mesh * BKE_subdiv_to_mesh(struct Subdiv *subdiv, const SubdivToMeshSettings *settings, const struct Mesh *coarse_mesh)
struct Subdiv * BKE_subsurf_modifier_subdiv_descriptor_ensure(struct SubsurfRuntimeData *runtime_data, const struct Mesh *mesh, bool for_draw_code)
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
MINLINE void copy_v3_v3(float r[3], const float a[3])
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:373
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:378
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:82
@ ID_ME
Definition: DNA_ID_enums.h:48
@ CD_FLAG_TEMPORARY
eMeshWrapperType
@ ME_WRAPPER_TYPE_MDATA
@ ME_WRAPPER_TYPE_SUBD
@ ME_WRAPPER_TYPE_BMESH
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_VERTS_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
ATTR_WARN_UNUSED_RESULT const BMVert * v
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
int BKE_mesh_wrapper_edge_len(const Mesh *me)
int BKE_mesh_wrapper_loop_len(const Mesh *me)
int BKE_mesh_wrapper_poly_len(const Mesh *me)
Mesh * BKE_mesh_wrapper_from_editmesh(BMEditMesh *em, const CustomData_MeshMasks *cd_mask_extra, const Mesh *me_settings)
Definition: mesh_wrapper.cc:87
bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])
static Mesh * mesh_wrapper_ensure_subdivision(Mesh *me)
Mesh * BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em, const CustomData_MeshMasks *cd_mask_extra, const float(*vert_coords)[3], const Mesh *me_settings)
Definition: mesh_wrapper.cc:49
Mesh * BKE_mesh_wrapper_ensure_subdivision(Mesh *me)
void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
Definition: mesh_wrapper.cc:94
void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const Mesh *me, float(*vert_coords)[3], int vert_coords_len, const float mat[4][4])
int BKE_mesh_wrapper_vert_len(const Mesh *me)
void BKE_mesh_wrapper_vert_coords_copy(const Mesh *me, float(*vert_coords)[3], int vert_coords_len)
void isolate_task(const Function &function)
Definition: BLI_task.hh:125
#define min(a, b)
Definition: sort.c:35
struct BMesh * bm
Definition: BKE_editmesh.h:40
char is_shallow_copy
Definition: BKE_editmesh.h:62
float co[3]
Definition: bmesh_class.h:87
int totvert
Definition: bmesh_class.h:297
int totedge
Definition: bmesh_class.h:297
int totloop
Definition: bmesh_class.h:297
int totface
Definition: bmesh_class.h:297
const float(* vertexCos)[3]
struct SubsurfRuntimeData * subsurf_runtime_data
struct Mesh * mesh_eval
struct EditMeshData * edit_data
CustomData_MeshMasks cd_mask_extra
void * eval_mutex
struct BMEditMesh * edit_mesh
struct MVert * mvert
int totedge
int totvert
Mesh_Runtime runtime
int totpoly
int totloop
CustomData ldata
struct Subdiv * subdiv
SubdivSettings settings
float max