Blender  V2.93
mesh_runtime.c
Go to the documentation of this file.
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 
24 #include "atomic_ops.h"
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_mesh_types.h"
29 #include "DNA_meshdata_types.h"
30 #include "DNA_object_types.h"
31 
32 #include "BLI_math_geom.h"
33 #include "BLI_threads.h"
34 
35 #include "BKE_bvhutils.h"
36 #include "BKE_lib_id.h"
37 #include "BKE_mesh.h"
38 #include "BKE_mesh_runtime.h"
39 #include "BKE_shrinkwrap.h"
40 #include "BKE_subdiv_ccg.h"
41 
42 /* -------------------------------------------------------------------- */
50 {
51  memset(&mesh->runtime, 0, sizeof(mesh->runtime));
52  mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
54 }
55 
56 /* Clear all pointers which we don't want to be shared on copying the datablock.
57  * However, keep all the flags which defines what the mesh is (for example, that
58  * it's deformed only, or that its custom data layers are out of date.) */
60 {
61  Mesh_Runtime *runtime = &mesh->runtime;
62 
63  runtime->mesh_eval = NULL;
64  runtime->edit_data = NULL;
65  runtime->batch_cache = NULL;
66  runtime->subdiv_ccg = NULL;
67  memset(&runtime->looptris, 0, sizeof(runtime->looptris));
68  runtime->bvh_cache = NULL;
69  runtime->shrinkwrap_data = NULL;
70 
71  mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
73 }
74 
76 {
77  if (mesh->runtime.eval_mutex != NULL) {
81  }
82  if (mesh->runtime.mesh_eval != NULL) {
86  }
90 }
91 
92 /* This is a ported copy of DM_ensure_looptri_data(dm) */
100 {
101  const unsigned int totpoly = mesh->totpoly;
102  const int looptris_len = poly_to_tri_count(totpoly, mesh->totloop);
103 
105 
107 
108  if ((looptris_len > mesh->runtime.looptris.len_alloc) ||
109  (looptris_len < mesh->runtime.looptris.len_alloc * 2) || (totpoly == 0)) {
112  mesh->runtime.looptris.len = 0;
113  }
114 
115  if (totpoly) {
116  if (mesh->runtime.looptris.array_wip == NULL) {
118  looptris_len, sizeof(*mesh->runtime.looptris.array_wip), __func__);
119  mesh->runtime.looptris.len_alloc = looptris_len;
120  }
121 
122  mesh->runtime.looptris.len = looptris_len;
123  }
124 }
125 
126 /* This is a ported copy of CDDM_recalc_looptri(dm). */
128 {
131 
133  mesh->mpoly,
134  mesh->mvert,
135  mesh->totloop,
136  mesh->totpoly,
138 
144 }
145 
146 /* This is a ported copy of dm_getNumLoopTri(dm). */
148 {
149  const int looptri_len = poly_to_tri_count(mesh->totpoly, mesh->totloop);
150  BLI_assert(ELEM(mesh->runtime.looptris.len, 0, looptri_len));
151  return looptri_len;
152 }
153 
154 /* This is a ported copy of dm_getLoopTriArray(dm). */
156 {
157  ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
158  BLI_mutex_lock(mesh_eval_mutex);
159 
160  MLoopTri *looptri = mesh->runtime.looptris.array;
161 
162  if (looptri != NULL) {
164  }
165  else {
167  looptri = mesh->runtime.looptris.array;
168  }
169 
170  BLI_mutex_unlock(mesh_eval_mutex);
171 
172  return looptri;
173 }
174 
175 /* This is a copy of DM_verttri_from_looptri(). */
177  const MLoop *mloop,
178  const MLoopTri *looptri,
179  int looptri_num)
180 {
181  for (int i = 0; i < looptri_num; i++) {
182  r_verttri[i].tri[0] = mloop[looptri[i].tri[0]].v;
183  r_verttri[i].tri[1] = mloop[looptri[i].tri[1]].v;
184  r_verttri[i].tri[2] = mloop[looptri[i].tri[2]].v;
185  }
186 }
187 
189 {
190  if (mesh->runtime.edit_data != NULL) {
191  return false;
192  }
193 
194  mesh->runtime.edit_data = MEM_callocN(sizeof(EditMeshData), "EditMeshData");
195  return true;
196 }
197 
199 {
200  EditMeshData *edit_data = mesh->runtime.edit_data;
201  if (edit_data == NULL) {
202  return false;
203  }
204 
205  MEM_SAFE_FREE(edit_data->polyCos);
206  MEM_SAFE_FREE(edit_data->polyNos);
207  MEM_SAFE_FREE(edit_data->vertexCos);
208  MEM_SAFE_FREE(edit_data->vertexNos);
209 
210  return true;
211 }
212 
214 {
215  if (mesh->runtime.edit_data == NULL) {
216  return false;
217  }
219 
222 
223  return true;
224 }
225 
227 {
228  if (mesh->runtime.bvh_cache) {
231  }
233  /* TODO(sergey): Does this really belong here? */
234  if (mesh->runtime.subdiv_ccg != NULL) {
237  }
239 }
240 
243 /* -------------------------------------------------------------------- */
247 /* Draw Engine */
250 
252 {
253  if (me->runtime.batch_cache) {
255  }
256 }
258 {
259  if (me->runtime.batch_cache) {
261  }
262 }
263 
266 /* -------------------------------------------------------------------- */
269 /* evaluated mesh info printing function,
270  * to help track down differences output */
271 
272 #ifndef NDEBUG
273 # include "BLI_dynstr.h"
274 
276 {
277  int type;
278 
279  for (type = 0; type < CD_NUMTYPES; type++) {
280  if (CustomData_has_layer(cd, type)) {
281  /* note: doesn't account for multiple layers */
282  const char *name = CustomData_layertype_name(type);
283  const int size = CustomData_sizeof(type);
284  const void *pt = CustomData_get_layer(cd, type);
285  const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0;
286  const char *structname;
287  int structnum;
288  CustomData_file_write_info(type, &structname, &structnum);
290  dynstr,
291  " dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
292  name,
293  structname,
294  type,
295  (const void *)pt,
296  size,
297  pt_size);
298  }
299  }
300 }
301 
303 {
304  DynStr *dynstr = BLI_dynstr_new();
305  char *ret;
306 
307  BLI_dynstr_append(dynstr, "{\n");
308  BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)me_eval);
309 # if 0
310  const char *tstr;
311  switch (me_eval->type) {
312  case DM_TYPE_CDDM:
313  tstr = "DM_TYPE_CDDM";
314  break;
315  case DM_TYPE_CCGDM:
316  tstr = "DM_TYPE_CCGDM";
317  break;
318  default:
319  tstr = "UNKNOWN";
320  break;
321  }
322  BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr);
323 # endif
324  BLI_dynstr_appendf(dynstr, " 'totvert': %d,\n", me_eval->totvert);
325  BLI_dynstr_appendf(dynstr, " 'totedge': %d,\n", me_eval->totedge);
326  BLI_dynstr_appendf(dynstr, " 'totface': %d,\n", me_eval->totface);
327  BLI_dynstr_appendf(dynstr, " 'totpoly': %d,\n", me_eval->totpoly);
328  BLI_dynstr_appendf(dynstr, " 'deformed_only': %d,\n", me_eval->runtime.deformed_only);
329 
330  BLI_dynstr_append(dynstr, " 'vertexLayers': (\n");
331  mesh_runtime_debug_info_layers(dynstr, &me_eval->vdata);
332  BLI_dynstr_append(dynstr, " ),\n");
333 
334  BLI_dynstr_append(dynstr, " 'edgeLayers': (\n");
335  mesh_runtime_debug_info_layers(dynstr, &me_eval->edata);
336  BLI_dynstr_append(dynstr, " ),\n");
337 
338  BLI_dynstr_append(dynstr, " 'loopLayers': (\n");
339  mesh_runtime_debug_info_layers(dynstr, &me_eval->ldata);
340  BLI_dynstr_append(dynstr, " ),\n");
341 
342  BLI_dynstr_append(dynstr, " 'polyLayers': (\n");
343  mesh_runtime_debug_info_layers(dynstr, &me_eval->pdata);
344  BLI_dynstr_append(dynstr, " ),\n");
345 
346  BLI_dynstr_append(dynstr, " 'tessFaceLayers': (\n");
347  mesh_runtime_debug_info_layers(dynstr, &me_eval->fdata);
348  BLI_dynstr_append(dynstr, " ),\n");
349 
350  BLI_dynstr_append(dynstr, "}\n");
351 
352  ret = BLI_dynstr_get_cstring(dynstr);
353  BLI_dynstr_free(dynstr);
354  return ret;
355 }
356 
358 {
359  char *str = BKE_mesh_runtime_debug_info(me_eval);
360  puts(str);
361  fflush(stdout);
362  MEM_freeN(str);
363 }
364 
365 /* XXX Should go in customdata file? */
367 {
368  int i;
369  const CustomDataLayer *layer;
370 
371  printf("{\n");
372 
373  for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) {
374 
375  const char *name = CustomData_layertype_name(layer->type);
376  const int size = CustomData_sizeof(layer->type);
377  const char *structname;
378  int structnum;
379  CustomData_file_write_info(layer->type, &structname, &structnum);
380  printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
381  name,
382  structname,
383  layer->type,
384  (const void *)layer->data,
385  size,
386  (int)(MEM_allocN_len(layer->data) / size));
387  }
388 
389  printf("}\n");
390 }
391 
393 {
394  const bool do_verbose = true;
395  const bool do_fixes = false;
396 
397  bool is_valid = true;
398  bool changed = true;
399 
400  if (do_verbose) {
401  printf("MESH: %s\n", me_eval->id.name + 2);
402  }
403 
405  &me_eval->vdata,
406  me_eval->totvert,
407  &me_eval->edata,
408  me_eval->totedge,
409  &me_eval->ldata,
410  me_eval->totloop,
411  &me_eval->pdata,
412  me_eval->totpoly,
413  false, /* setting mask here isn't useful, gives false positives */
414  do_verbose,
415  do_fixes,
416  &changed);
417 
419  me_eval->mvert,
420  me_eval->totvert,
421  me_eval->medge,
422  me_eval->totedge,
423  me_eval->mface,
424  me_eval->totface,
425  me_eval->mloop,
426  me_eval->totloop,
427  me_eval->mpoly,
428  me_eval->totpoly,
429  me_eval->dvert,
430  do_verbose,
431  do_fixes,
432  &changed);
433 
434  BLI_assert(changed == false);
435 
436  return is_valid;
437 }
438 
439 #endif /* NDEBUG */
440 
@ DM_TYPE_CDDM
@ DM_TYPE_CCGDM
void bvhcache_free(struct BVHCache *bvh_cache)
Definition: bvhutils.c:152
bool CustomData_has_layer(const struct CustomData *data, int type)
const char * CustomData_layertype_name(int type)
Definition: customdata.c:4284
void * CustomData_get_layer(const struct CustomData *data, int type)
int CustomData_sizeof(int type)
Definition: customdata.c:4277
void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num)
Definition: customdata.c:4210
void BKE_id_free(struct Main *bmain, void *idv)
bool BKE_mesh_validate_all_customdata(struct CustomData *vdata, const uint totvert, struct CustomData *edata, const uint totedge, struct CustomData *ldata, const uint totloop, struct CustomData *pdata, const uint totpoly, const bool check_meshmask, const bool do_verbose, const 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)
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, const bool do_verbose, const bool do_fixes, bool *r_change)
eMeshBatchDirtyMode
void BKE_shrinkwrap_discard_boundary_data(struct Mesh *mesh)
Definition: shrinkwrap.c:170
void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg)
Definition: subdiv_ccg.c:624
#define BLI_assert(a)
Definition: BLI_assert.h:58
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:71
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:358
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
char * BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:323
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:107
MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
void BLI_mutex_end(ThreadMutex *mutex)
Definition: threads.cc:416
void BLI_mutex_init(ThreadMutex *mutex)
Definition: threads.cc:396
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:401
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:406
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:83
#define SWAP(type, a, b)
#define UNUSED(x)
#define ELEM(...)
@ CD_NUMTYPES
Object is a sort of wrapper for general info.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
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)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
bool is_valid
#define str(s)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:40
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
void(* BKE_mesh_batch_cache_free_cb)(Mesh *me)
Definition: mesh_runtime.c:249
bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
Definition: mesh_runtime.c:392
static void mesh_ensure_looptri_data(Mesh *mesh)
Definition: mesh_runtime.c:99
void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag))
Definition: mesh_runtime.c:59
void BKE_mesh_runtime_debug_print_cdlayers(CustomData *data)
Definition: mesh_runtime.c:366
void BKE_mesh_runtime_reset(Mesh *mesh)
Definition: mesh_runtime.c:49
char * BKE_mesh_runtime_debug_info(Mesh *me_eval)
Definition: mesh_runtime.c:302
void BKE_mesh_runtime_debug_print(Mesh *me_eval)
Definition: mesh_runtime.c:357
void BKE_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
Definition: mesh_runtime.c:251
void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri, const MLoop *mloop, const MLoopTri *looptri, int looptri_num)
Definition: mesh_runtime.c:176
void BKE_mesh_runtime_clear_cache(Mesh *mesh)
Definition: mesh_runtime.c:75
void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
Definition: mesh_runtime.c:226
void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
Definition: mesh_runtime.c:127
bool BKE_mesh_runtime_reset_edit_data(Mesh *mesh)
Definition: mesh_runtime.c:198
static void mesh_runtime_debug_info_layers(DynStr *dynstr, CustomData *cd)
Definition: mesh_runtime.c:275
int BKE_mesh_runtime_looptri_len(const Mesh *mesh)
Definition: mesh_runtime.c:147
bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
Definition: mesh_runtime.c:213
void(* BKE_mesh_batch_cache_dirty_tag_cb)(Mesh *me, eMeshBatchDirtyMode mode)
Definition: mesh_runtime.c:248
const MLoopTri * BKE_mesh_runtime_looptri_ensure(Mesh *mesh)
Definition: mesh_runtime.c:155
void BKE_mesh_batch_cache_free(Mesh *me)
Definition: mesh_runtime.c:257
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh)
Definition: mesh_runtime.c:188
return ret
float const (* polyNos)[3]
const float(* polyCos)[3]
float const (* vertexNos)[3]
const float(* vertexCos)[3]
char name[66]
Definition: DNA_ID.h:283
struct MLoopTri * array
struct MLoopTri * array_wip
unsigned int tri[3]
unsigned int v
unsigned int tri[3]
struct Mesh * mesh_eval
struct EditMeshData * edit_data
struct BVHCache * bvh_cache
void * batch_cache
struct SubdivCCG * subdiv_ccg
struct MLoopTri_Store looptris
struct ShrinkwrapBoundaryData * shrinkwrap_data
void * eval_mutex
struct MEdge * medge
struct BMEditMesh * edit_mesh
struct CustomData pdata ldata
struct MVert * mvert
struct MDeformVert * dvert
int totedge
int totvert
struct MLoop * mloop
int totface
Mesh_Runtime runtime
struct CustomData vdata edata fdata
int totpoly
int totloop
struct MFace * mface
struct MPoly * mpoly
const NodeType * type
Definition: node.h:175