Cleanup: remove redundant, invalid info from headers
[blender.git] / source / blender / blenkernel / intern / mesh_runtime.c
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 blender/blenkernel/intern/mesh_runtime.c
21  *  \ingroup bke
22  */
23
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_mesh.h"
37 #include "BKE_mesh_runtime.h"
38 #include "BKE_subdiv_ccg.h"
39 #include "BKE_shrinkwrap.h"
40
41 /* -------------------------------------------------------------------- */
42 /** \name Mesh Runtime Struct Utils
43  * \{ */
44
45 static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
46
47 /**
48  * Default values defined at read time.
49  */
50 void BKE_mesh_runtime_reset(Mesh *mesh)
51 {
52         memset(&mesh->runtime, 0, sizeof(mesh->runtime));
53 }
54
55 /* Clear all pointers which we don't want to be shared on copying the datablock.
56  * However, keep all the flags which defines what the mesh is (for example, that
57  * it's deformed only, or that its custom data layers are out of date.) */
58 void BKE_mesh_runtime_reset_on_copy(Mesh *mesh)
59 {
60         Mesh_Runtime *runtime = &mesh->runtime;
61         runtime->edit_data = NULL;
62         runtime->batch_cache = NULL;
63         runtime->subdiv_ccg = NULL;
64         memset(&runtime->looptris, 0, sizeof(runtime->looptris));
65         runtime->bvh_cache = NULL;
66         runtime->shrinkwrap_data = NULL;
67 }
68
69 void BKE_mesh_runtime_clear_cache(Mesh *mesh)
70 {
71         BKE_mesh_runtime_clear_geometry(mesh);
72         BKE_mesh_batch_cache_free(mesh);
73         BKE_mesh_runtime_clear_edit_data(mesh);
74 }
75
76 /* This is a ported copy of DM_ensure_looptri_data(dm) */
77 /**
78  * Ensure the array is large enough
79  *
80  * /note This function must always be thread-protected by caller. It should only be used by internal code.
81  */
82 static void mesh_ensure_looptri_data(Mesh *mesh)
83 {
84         const unsigned int totpoly = mesh->totpoly;
85         const int looptris_len = poly_to_tri_count(totpoly, mesh->totloop);
86
87         BLI_assert(mesh->runtime.looptris.array_wip == NULL);
88
89         SWAP(MLoopTri *, mesh->runtime.looptris.array, mesh->runtime.looptris.array_wip);
90
91         if ((looptris_len > mesh->runtime.looptris.len_alloc) ||
92             (looptris_len < mesh->runtime.looptris.len_alloc * 2) ||
93             (totpoly == 0))
94         {
95                 MEM_SAFE_FREE(mesh->runtime.looptris.array_wip);
96                 mesh->runtime.looptris.len_alloc = 0;
97                 mesh->runtime.looptris.len = 0;
98         }
99
100         if (totpoly) {
101                 if (mesh->runtime.looptris.array_wip == NULL) {
102                         mesh->runtime.looptris.array_wip = MEM_malloc_arrayN(looptris_len, sizeof(*mesh->runtime.looptris.array_wip), __func__);
103                         mesh->runtime.looptris.len_alloc = looptris_len;
104                 }
105
106                 mesh->runtime.looptris.len = looptris_len;
107         }
108 }
109
110 /* This is a ported copy of CDDM_recalc_looptri(dm). */
111 void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
112 {
113         mesh_ensure_looptri_data(mesh);
114         BLI_assert(mesh->totpoly == 0 || mesh->runtime.looptris.array_wip != NULL);
115
116         BKE_mesh_recalc_looptri(
117                 mesh->mloop, mesh->mpoly,
118                 mesh->mvert,
119                 mesh->totloop, mesh->totpoly,
120                 mesh->runtime.looptris.array_wip);
121
122         BLI_assert(mesh->runtime.looptris.array == NULL);
123         atomic_cas_ptr((void **)&mesh->runtime.looptris.array, mesh->runtime.looptris.array, mesh->runtime.looptris.array_wip);
124         mesh->runtime.looptris.array_wip = NULL;
125 }
126
127 /* This is a ported copy of dm_getNumLoopTri(dm). */
128 int BKE_mesh_runtime_looptri_len(const Mesh *mesh)
129 {
130         const int looptri_len = poly_to_tri_count(mesh->totpoly, mesh->totloop);
131         BLI_assert(ELEM(mesh->runtime.looptris.len, 0, looptri_len));
132         return looptri_len;
133 }
134
135 /* This is a ported copy of dm_getLoopTriArray(dm). */
136 const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh)
137 {
138         MLoopTri *looptri;
139
140         BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ);
141         looptri = mesh->runtime.looptris.array;
142         BLI_rw_mutex_unlock(&loops_cache_lock);
143
144         if (looptri != NULL) {
145                 BLI_assert(BKE_mesh_runtime_looptri_len(mesh) == mesh->runtime.looptris.len);
146         }
147         else {
148                 BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE);
149                 /* We need to ensure array is still NULL inside mutex-protected code, some other thread might have already
150                  * recomputed those looptris. */
151                 if (mesh->runtime.looptris.array == NULL) {
152                         BKE_mesh_runtime_looptri_recalc(mesh);
153                 }
154                 looptri = mesh->runtime.looptris.array;
155                 BLI_rw_mutex_unlock(&loops_cache_lock);
156         }
157         return looptri;
158 }
159
160 /* This is a copy of DM_verttri_from_looptri(). */
161 void BKE_mesh_runtime_verttri_from_looptri(
162         MVertTri *r_verttri, const MLoop *mloop,
163         const MLoopTri *looptri, int looptri_num)
164 {
165         int i;
166         for (i = 0; i < looptri_num; i++) {
167                 r_verttri[i].tri[0] = mloop[looptri[i].tri[0]].v;
168                 r_verttri[i].tri[1] = mloop[looptri[i].tri[1]].v;
169                 r_verttri[i].tri[2] = mloop[looptri[i].tri[2]].v;
170         }
171 }
172
173
174 bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh)
175 {
176         if (mesh->runtime.edit_data != NULL) {
177                 return false;
178         }
179
180         mesh->runtime.edit_data = MEM_callocN(sizeof(EditMeshData), "EditMeshData");
181         return true;
182 }
183
184 bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
185 {
186         if (mesh->runtime.edit_data == NULL) {
187                 return false;
188         }
189
190         if (mesh->runtime.edit_data->polyCos != NULL)
191                 MEM_freeN((void *)mesh->runtime.edit_data->polyCos);
192         if (mesh->runtime.edit_data->polyNos != NULL)
193                 MEM_freeN((void *)mesh->runtime.edit_data->polyNos);
194         if (mesh->runtime.edit_data->vertexCos != NULL)
195                 MEM_freeN((void *)mesh->runtime.edit_data->vertexCos);
196         if (mesh->runtime.edit_data->vertexNos != NULL)
197                 MEM_freeN((void *)mesh->runtime.edit_data->vertexNos);
198
199         MEM_SAFE_FREE(mesh->runtime.edit_data);
200         return true;
201 }
202
203 void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
204 {
205         bvhcache_free(&mesh->runtime.bvh_cache);
206         MEM_SAFE_FREE(mesh->runtime.looptris.array);
207         /* TODO(sergey): Does this really belong here? */
208         if (mesh->runtime.subdiv_ccg != NULL) {
209                 BKE_subdiv_ccg_destroy(mesh->runtime.subdiv_ccg);
210                 mesh->runtime.subdiv_ccg = NULL;
211         }
212         BKE_shrinkwrap_discard_boundary_data(mesh);
213 }
214
215 /** \} */
216
217 /* -------------------------------------------------------------------- */
218 /** \name Mesh Batch Cache Callbacks
219  * \{ */
220
221 /* Draw Engine */
222 void (*BKE_mesh_batch_cache_dirty_tag_cb)(Mesh *me, int mode) = NULL;
223 void (*BKE_mesh_batch_cache_free_cb)(Mesh *me) = NULL;
224
225 void BKE_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
226 {
227         if (me->runtime.batch_cache) {
228                 BKE_mesh_batch_cache_dirty_tag_cb(me, mode);
229         }
230 }
231 void BKE_mesh_batch_cache_free(Mesh *me)
232 {
233         if (me->runtime.batch_cache) {
234                 BKE_mesh_batch_cache_free_cb(me);
235         }
236 }
237
238 /** \} */
239
240 /** \name Mesh runtime debug helpers.
241  * \{ */
242 /* evaluated mesh info printing function,
243  * to help track down differences output */
244
245 #ifndef NDEBUG
246 #include "BLI_dynstr.h"
247
248 static void mesh_runtime_debug_info_layers(
249         DynStr *dynstr, CustomData *cd)
250 {
251         int type;
252
253         for (type = 0; type < CD_NUMTYPES; type++) {
254                 if (CustomData_has_layer(cd, type)) {
255                         /* note: doesn't account for multiple layers */
256                         const char *name = CustomData_layertype_name(type);
257                         const int size = CustomData_sizeof(type);
258                         const void *pt = CustomData_get_layer(cd, type);
259                         const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0;
260                         const char *structname;
261                         int structnum;
262                         CustomData_file_write_info(type, &structname, &structnum);
263                         BLI_dynstr_appendf(
264                                 dynstr,
265                                 "        dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
266                                 name, structname, type, (const void *)pt, size, pt_size);
267                 }
268         }
269 }
270
271 char *BKE_mesh_runtime_debug_info(Mesh *me_eval)
272 {
273         DynStr *dynstr = BLI_dynstr_new();
274         char *ret;
275
276         BLI_dynstr_appendf(dynstr, "{\n");
277         BLI_dynstr_appendf(dynstr, "    'ptr': '%p',\n", (void *)me_eval);
278 #if 0
279         const char *tstr;
280         switch (me_eval->type) {
281                 case DM_TYPE_CDDM:     tstr = "DM_TYPE_CDDM";     break;
282                 case DM_TYPE_CCGDM:    tstr = "DM_TYPE_CCGDM";     break;
283                 default:               tstr = "UNKNOWN";           break;
284         }
285         BLI_dynstr_appendf(dynstr, "    'type': '%s',\n", tstr);
286 #endif
287         BLI_dynstr_appendf(dynstr, "    'totvert': %d,\n", me_eval->totvert);
288         BLI_dynstr_appendf(dynstr, "    'totedge': %d,\n", me_eval->totedge);
289         BLI_dynstr_appendf(dynstr, "    'totface': %d,\n", me_eval->totface);
290         BLI_dynstr_appendf(dynstr, "    'totpoly': %d,\n", me_eval->totpoly);
291         BLI_dynstr_appendf(dynstr, "    'deformed_only': %d,\n", me_eval->runtime.deformed_only);
292
293         BLI_dynstr_appendf(dynstr, "    'vertexLayers': (\n");
294         mesh_runtime_debug_info_layers(dynstr, &me_eval->vdata);
295         BLI_dynstr_appendf(dynstr, "    ),\n");
296
297         BLI_dynstr_appendf(dynstr, "    'edgeLayers': (\n");
298         mesh_runtime_debug_info_layers(dynstr, &me_eval->edata);
299         BLI_dynstr_appendf(dynstr, "    ),\n");
300
301         BLI_dynstr_appendf(dynstr, "    'loopLayers': (\n");
302         mesh_runtime_debug_info_layers(dynstr, &me_eval->ldata);
303         BLI_dynstr_appendf(dynstr, "    ),\n");
304
305         BLI_dynstr_appendf(dynstr, "    'polyLayers': (\n");
306         mesh_runtime_debug_info_layers(dynstr, &me_eval->pdata);
307         BLI_dynstr_appendf(dynstr, "    ),\n");
308
309         BLI_dynstr_appendf(dynstr, "    'tessFaceLayers': (\n");
310         mesh_runtime_debug_info_layers(dynstr, &me_eval->fdata);
311         BLI_dynstr_appendf(dynstr, "    ),\n");
312
313         BLI_dynstr_appendf(dynstr, "}\n");
314
315         ret = BLI_dynstr_get_cstring(dynstr);
316         BLI_dynstr_free(dynstr);
317         return ret;
318 }
319
320 void BKE_mesh_runtime_debug_print(Mesh *me_eval)
321 {
322         char *str = BKE_mesh_runtime_debug_info(me_eval);
323         puts(str);
324         fflush(stdout);
325         MEM_freeN(str);
326 }
327
328 /* XXX Should go in customdata file? */
329 void BKE_mesh_runtime_debug_print_cdlayers(CustomData *data)
330 {
331         int i;
332         const CustomDataLayer *layer;
333
334         printf("{\n");
335
336         for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) {
337
338                 const char *name = CustomData_layertype_name(layer->type);
339                 const int size = CustomData_sizeof(layer->type);
340                 const char *structname;
341                 int structnum;
342                 CustomData_file_write_info(layer->type, &structname, &structnum);
343                 printf("        dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
344                        name, structname, layer->type, (const void *)layer->data, size, (int)(MEM_allocN_len(layer->data) / size));
345         }
346
347         printf("}\n");
348 }
349
350 bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
351 {
352         const bool do_verbose = true;
353         const bool do_fixes = false;
354
355         bool is_valid = true;
356         bool changed = true;
357
358         if (do_verbose) {
359                 printf("MESH: %s\n", me_eval->id.name + 2);
360         }
361
362         is_valid &= BKE_mesh_validate_all_customdata(
363                 &me_eval->vdata, me_eval->totvert,
364                 &me_eval->edata, me_eval->totedge,
365                 &me_eval->ldata, me_eval->totloop,
366                 &me_eval->pdata, me_eval->totpoly,
367                 false,  /* setting mask here isn't useful, gives false positives */
368                 do_verbose, do_fixes,
369                 &changed);
370
371         is_valid &= BKE_mesh_validate_arrays(
372                 me_eval,
373                 me_eval->mvert, me_eval->totvert,
374                 me_eval->medge, me_eval->totedge,
375                 me_eval->mface, me_eval->totface,
376                 me_eval->mloop, me_eval->totloop,
377                 me_eval->mpoly, me_eval->totpoly,
378                 me_eval->dvert,
379                 do_verbose, do_fixes,
380                 &changed);
381
382         BLI_assert(changed == false);
383
384         return is_valid;
385 }
386
387 #endif  /* NDEBUG */
388
389 /** \} */