Blender  V3.3
mesh_runtime.cc
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 "atomic_ops.h"
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_mesh_types.h"
13 #include "DNA_meshdata_types.h"
14 #include "DNA_object_types.h"
15 
16 #include "BLI_math_geom.h"
17 #include "BLI_task.hh"
18 
19 #include "BKE_bvhutils.h"
20 #include "BKE_lib_id.h"
21 #include "BKE_mesh.h"
22 #include "BKE_mesh_runtime.h"
23 #include "BKE_shrinkwrap.h"
24 #include "BKE_subdiv_ccg.h"
25 
26 /* -------------------------------------------------------------------- */
36 {
37  mesh->runtime.eval_mutex = MEM_new<ThreadMutex>("mesh runtime eval_mutex");
39  mesh->runtime.normals_mutex = MEM_new<ThreadMutex>("mesh runtime normals_mutex");
41  mesh->runtime.render_mutex = MEM_new<ThreadMutex>("mesh runtime render_mutex");
43 }
44 
49 {
50  if (mesh->runtime.eval_mutex != nullptr) {
53  mesh->runtime.eval_mutex = nullptr;
54  }
55  if (mesh->runtime.normals_mutex != nullptr) {
58  mesh->runtime.normals_mutex = nullptr;
59  }
60  if (mesh->runtime.render_mutex != nullptr) {
63  mesh->runtime.render_mutex = nullptr;
64  }
65 }
66 
68 {
70 }
71 
73 {
76 }
77 
79 {
80  Mesh_Runtime *runtime = &mesh->runtime;
81 
82  runtime->mesh_eval = nullptr;
83  runtime->edit_data = nullptr;
84  runtime->batch_cache = nullptr;
85  runtime->subdiv_ccg = nullptr;
86  runtime->looptris = blender::dna::shallow_zero_initialize();
87  runtime->bvh_cache = nullptr;
88  runtime->shrinkwrap_data = nullptr;
89  runtime->subsurf_face_dot_tags = nullptr;
90 
91  runtime->vert_normals_dirty = true;
92  runtime->poly_normals_dirty = true;
93  runtime->vert_normals = nullptr;
94  runtime->poly_normals = nullptr;
95 
97 }
98 
100 {
101  if (mesh->runtime.mesh_eval != nullptr) {
102  mesh->runtime.mesh_eval->edit_mesh = nullptr;
103  BKE_id_free(nullptr, mesh->runtime.mesh_eval);
104  mesh->runtime.mesh_eval = nullptr;
105  }
110 }
111 
119 {
120  /* This is a ported copy of `DM_ensure_looptri_data(dm)`. */
121  const uint totpoly = mesh->totpoly;
122  const int looptris_len = poly_to_tri_count(totpoly, mesh->totloop);
123 
125 
127 
128  if ((looptris_len > mesh->runtime.looptris.len_alloc) ||
129  (looptris_len < mesh->runtime.looptris.len_alloc * 2) || (totpoly == 0)) {
132  mesh->runtime.looptris.len = 0;
133  }
134 
135  if (totpoly) {
136  if (mesh->runtime.looptris.array_wip == nullptr) {
137  mesh->runtime.looptris.array_wip = static_cast<MLoopTri *>(
138  MEM_malloc_arrayN(looptris_len, sizeof(*mesh->runtime.looptris.array_wip), __func__));
139  mesh->runtime.looptris.len_alloc = looptris_len;
140  }
141 
142  mesh->runtime.looptris.len = looptris_len;
143  }
144 }
145 
147 {
149  BLI_assert(mesh->totpoly == 0 || mesh->runtime.looptris.array_wip != nullptr);
150 
152  mesh->mpoly,
153  mesh->mvert,
154  mesh->totloop,
155  mesh->totpoly,
157 
158  BLI_assert(mesh->runtime.looptris.array == nullptr);
162  mesh->runtime.looptris.array_wip = nullptr;
163 }
164 
166 {
167  /* This is a ported copy of `dm_getNumLoopTri(dm)`. */
168  const int looptri_len = poly_to_tri_count(mesh->totpoly, mesh->totloop);
169  BLI_assert(ELEM(mesh->runtime.looptris.len, 0, looptri_len));
170  return looptri_len;
171 }
172 
174 {
175  ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
176  BLI_mutex_lock(mesh_eval_mutex);
177 
178  MLoopTri *looptri = mesh->runtime.looptris.array;
179 
180  if (looptri != nullptr) {
182  }
183  else {
184  /* Must isolate multithreaded tasks while holding a mutex lock. */
186  [&]() { BKE_mesh_runtime_looptri_recalc(const_cast<Mesh *>(mesh)); });
187  looptri = mesh->runtime.looptris.array;
188  }
189 
190  BLI_mutex_unlock(mesh_eval_mutex);
191 
192  return looptri;
193 }
194 
196  const MLoop *mloop,
197  const MLoopTri *looptri,
198  int looptri_num)
199 {
200  for (int i = 0; i < looptri_num; i++) {
201  r_verttri[i].tri[0] = mloop[looptri[i].tri[0]].v;
202  r_verttri[i].tri[1] = mloop[looptri[i].tri[1]].v;
203  r_verttri[i].tri[2] = mloop[looptri[i].tri[2]].v;
204  }
205 }
206 
208 {
209  if (mesh->runtime.edit_data != nullptr) {
210  return false;
211  }
212 
213  mesh->runtime.edit_data = MEM_cnew<EditMeshData>(__func__);
214  return true;
215 }
216 
218 {
219  EditMeshData *edit_data = mesh->runtime.edit_data;
220  if (edit_data == nullptr) {
221  return false;
222  }
223 
224  MEM_SAFE_FREE(edit_data->polyCos);
225  MEM_SAFE_FREE(edit_data->polyNos);
226  MEM_SAFE_FREE(edit_data->vertexCos);
227  MEM_SAFE_FREE(edit_data->vertexNos);
228 
229  return true;
230 }
231 
233 {
234  if (mesh->runtime.edit_data == nullptr) {
235  return false;
236  }
238 
240  mesh->runtime.edit_data = nullptr;
241 
242  return true;
243 }
244 
246 {
248 
249  /* TODO(sergey): Does this really belong here? */
250  if (mesh->runtime.subdiv_ccg != nullptr) {
252  mesh->runtime.subdiv_ccg = nullptr;
253  }
255 
257 }
258 
260 {
263  if (mesh->runtime.bvh_cache) {
265  mesh->runtime.bvh_cache = nullptr;
266  }
267 }
268 
270 {
271  const bool vert_normals_were_dirty = BKE_mesh_vertex_normals_are_dirty(mesh);
272  const bool poly_normals_were_dirty = BKE_mesh_poly_normals_are_dirty(mesh);
273 
275  /* The normals didn't change, since all vertices moved by the same amount. */
276  if (!vert_normals_were_dirty) {
278  }
279  if (!poly_normals_were_dirty) {
281  }
282 }
283 
286 /* -------------------------------------------------------------------- */
290 /* Draw Engine */
293 
295 {
296  if (me->runtime.batch_cache) {
298  }
299 }
301 {
302  if (me->runtime.batch_cache) {
304  }
305 }
306 
309 /* -------------------------------------------------------------------- */
313 #ifndef NDEBUG
314 
316 {
317  const bool do_verbose = true;
318  const bool do_fixes = false;
319 
320  bool is_valid = true;
321  bool changed = true;
322 
323  if (do_verbose) {
324  printf("MESH: %s\n", me_eval->id.name + 2);
325  }
326 
328  &me_eval->vdata,
329  me_eval->totvert,
330  &me_eval->edata,
331  me_eval->totedge,
332  &me_eval->ldata,
333  me_eval->totloop,
334  &me_eval->pdata,
335  me_eval->totpoly,
336  false, /* setting mask here isn't useful, gives false positives */
337  do_verbose,
338  do_fixes,
339  &changed);
340 
342  me_eval->mvert,
343  me_eval->totvert,
344  me_eval->medge,
345  me_eval->totedge,
346  me_eval->mface,
347  me_eval->totface,
348  me_eval->mloop,
349  me_eval->totloop,
350  me_eval->mpoly,
351  me_eval->totpoly,
352  me_eval->dvert,
353  do_verbose,
354  do_fixes,
355  &changed);
356 
357  BLI_assert(changed == false);
358 
359  return is_valid;
360 }
361 
362 #endif /* NDEBUG */
363 
void bvhcache_free(struct BVHCache *bvh_cache)
Definition: bvhutils.cc:135
void BKE_id_free(struct Main *bmain, void *idv)
bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh)
void BKE_mesh_poly_normals_clear_dirty(struct Mesh *mesh)
bool BKE_mesh_validate_arrays(struct Mesh *me, struct MVert *mverts, unsigned int totvert, struct MEdge *medges, unsigned int totedge, struct MFace *mfaces, unsigned int totface, struct MLoop *mloops, unsigned int totloop, struct MPoly *mpolys, unsigned int totpoly, struct MDeformVert *dverts, bool do_verbose, bool do_fixes, bool *r_change)
void BKE_mesh_recalc_looptri(const struct MLoop *mloop, const struct MPoly *mpoly, const struct MVert *mvert, int totloop, int totpoly, struct MLoopTri *mlooptri)
void BKE_mesh_clear_derived_normals(struct Mesh *mesh)
bool BKE_mesh_validate_all_customdata(struct CustomData *vdata, uint totvert, struct CustomData *edata, uint totedge, struct CustomData *ldata, uint totloop, struct CustomData *pdata, uint totpoly, bool check_meshmask, bool do_verbose, bool do_fixes, bool *r_change)
bool BKE_mesh_vertex_normals_are_dirty(const struct Mesh *mesh)
void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh)
void BKE_mesh_normals_tag_dirty(struct Mesh *mesh)
Definition: mesh_normals.cc:95
eMeshBatchDirtyMode
Definition: BKE_mesh_types.h:9
void BKE_shrinkwrap_discard_boundary_data(struct Mesh *mesh)
Definition: shrinkwrap.c:152
void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg)
Definition: subdiv_ccg.c:615
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
unsigned int uint
Definition: BLI_sys_types.h:67
void BLI_mutex_end(ThreadMutex *mutex)
Definition: threads.cc:388
void BLI_mutex_init(ThreadMutex *mutex)
Definition: threads.cc:368
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
#define SWAP(type, a, b)
#define UNUSED(x)
#define ELEM(...)
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE void * atomic_cas_ptr(void **v, void *old, void *_new)
bool is_valid
SyclQueue void void size_t num_bytes void
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void(* BKE_mesh_batch_cache_free_cb)(Mesh *me)
bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
static void mesh_ensure_looptri_data(Mesh *mesh)
void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag))
Definition: mesh_runtime.cc:78
const MLoopTri * BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
void BKE_mesh_tag_coords_changed_uniformly(Mesh *mesh)
void BKE_mesh_tag_coords_changed(Mesh *mesh)
void BKE_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
void BKE_mesh_runtime_free_data(Mesh *mesh)
Free all data (and mutexes) inside the runtime of the given mesh.
Definition: mesh_runtime.cc:72
static void mesh_runtime_free_mutexes(Mesh *mesh)
free the mutexes of the given mesh runtime.
Definition: mesh_runtime.cc:48
void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri, const MLoop *mloop, const MLoopTri *looptri, int looptri_num)
void BKE_mesh_runtime_clear_cache(Mesh *mesh)
This function clears runtime cache of the given mesh.
Definition: mesh_runtime.cc:99
void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
static void mesh_runtime_init_mutexes(Mesh *mesh)
Initialize the runtime mutexes of the given mesh.
Definition: mesh_runtime.cc:35
void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
bool BKE_mesh_runtime_reset_edit_data(Mesh *mesh)
void BKE_mesh_runtime_init_data(Mesh *mesh)
Initialize the runtime of the given mesh.
Definition: mesh_runtime.cc:67
int BKE_mesh_runtime_looptri_len(const Mesh *mesh)
bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
void(* BKE_mesh_batch_cache_dirty_tag_cb)(Mesh *me, eMeshBatchDirtyMode mode)
void BKE_mesh_batch_cache_free(Mesh *me)
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh)
void isolate_task(const Function &function)
Definition: BLI_task.hh:125
float const (* polyNos)[3]
const float(* polyCos)[3]
float const (* vertexNos)[3]
const float(* vertexCos)[3]
char name[66]
Definition: DNA_ID.h:378
struct MLoopTri * array
struct MLoopTri * array_wip
unsigned int tri[3]
unsigned int v
unsigned int tri[3]
char vert_normals_dirty
float(* vert_normals)[3]
struct Mesh * mesh_eval
struct EditMeshData * edit_data
uint32_t * subsurf_face_dot_tags
char poly_normals_dirty
struct BVHCache * bvh_cache
void * batch_cache
struct SubdivCCG * subdiv_ccg
struct MLoopTri_Store looptris
void * render_mutex
struct ShrinkwrapBoundaryData * shrinkwrap_data
float(* poly_normals)[3]
void * normals_mutex
void * eval_mutex
struct MEdge * medge
struct BMEditMesh * edit_mesh
CustomData vdata
struct MVert * mvert
struct MDeformVert * dvert
int totedge
int totvert
struct MLoop * mloop
int totface
Mesh_Runtime runtime
CustomData pdata
int totpoly
CustomData edata
int totloop
struct MFace * mface
struct MPoly * mpoly
CustomData ldata