Blender V5.0
multires.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 by Nicholas Bishop. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11/* for reading old multires */
12#define DNA_DEPRECATED_ALLOW
13
14#include "DNA_mesh_types.h"
15#include "DNA_meshdata_types.h"
16#include "DNA_object_types.h"
17#include "DNA_scene_types.h"
18
19#include "BLI_bitmap.h"
20#include "BLI_index_mask.hh"
21#include "BLI_listbase.h"
22#include "BLI_math_matrix.h"
23#include "BLI_math_vector.h"
24#include "BLI_task.h"
25
26#include "BKE_ccg.hh"
27#include "BKE_editmesh.hh"
28#include "BKE_mesh.h"
29#include "BKE_mesh_runtime.hh"
30#include "BKE_mesh_types.hh"
31#include "BKE_modifier.hh"
32#include "BKE_multires.hh"
33#include "BKE_paint.hh"
34#include "BKE_paint_bvh.hh"
35#include "BKE_scene.hh"
36#include "BKE_subdiv_ccg.hh"
37
38#include "BKE_object.hh"
39
41
42#include <cmath>
43#include <cstring>
44
45/* MULTIRES MODIFIER */
46static const int multires_grid_tot[] = {
47 0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409};
48static const int multires_side_tot[] = {
49 0, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097};
50
52
54{
55 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
56 /* CustomData_external_remove is used here only to mark layer
57 * as non-external for further freeing, so zero element count
58 * looks safer than `em->bm->totface`. */
59 CustomData_external_remove(&em->bm->ldata, &mesh->id, CD_MDISPS, 0);
60
61 if (CustomData_has_layer(&em->bm->ldata, CD_MDISPS)) {
62 BM_data_layer_free(em->bm, &em->bm->ldata, CD_MDISPS);
63 }
64
65 if (CustomData_has_layer(&em->bm->ldata, CD_GRID_PAINT_MASK)) {
66 BM_data_layer_free(em->bm, &em->bm->ldata, CD_GRID_PAINT_MASK);
67 }
68 }
69 else {
72
74 }
75}
76
78 const int old_level,
79 const int new_level)
80{
81 const int new_gridsize = CCG_grid_size(new_level);
82 const int old_gridsize = CCG_grid_size(old_level);
83
84 BLI_assert(new_level <= old_level);
85 const int factor = CCG_grid_factor(new_level, old_level);
86 BLI_bitmap *new_hidden = BLI_BITMAP_NEW(square_i(new_gridsize), "downsample hidden");
87
88 for (int y = 0; y < new_gridsize; y++) {
89 for (int x = 0; x < new_gridsize; x++) {
90 const int old_value = BLI_BITMAP_TEST(old_hidden, factor * y * old_gridsize + x * factor);
91
92 BLI_BITMAP_SET(new_hidden, y * new_gridsize + x, old_value);
93 }
94 }
95
96 return new_hidden;
97}
98
100{
101 Object *object_eval = DEG_get_evaluated(depsgraph, object);
104 depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
105 ModifierEvalContext modifier_ctx{};
106 modifier_ctx.depsgraph = depsgraph;
107 modifier_ctx.object = object_eval;
109
111 Mesh *result = mti->modify_mesh(&mmd->modifier, &modifier_ctx, deformed_mesh);
112
113 if (result == deformed_mesh) {
114 result = BKE_mesh_copy_for_eval(*deformed_mesh);
115 }
116 return result;
117}
118
120 Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
121{
123 Object *object_eval = DEG_get_evaluated(depsgraph, object);
124
125 Object object_for_eval = blender::dna::shallow_copy(*object_eval);
126 blender::bke::ObjectRuntime runtime = *object_eval->runtime;
127 object_for_eval.runtime = &runtime;
128
129 object_for_eval.data = object->data;
130 object_for_eval.sculpt = nullptr;
131
132 const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
133 ModifierEvalContext mesh_eval_context = {depsgraph, &object_for_eval, ModifierApplyFlag(0)};
134 if (use_render) {
135 mesh_eval_context.flag |= MOD_APPLY_RENDER;
136 }
137 const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
138
139 VirtualModifierData virtual_modifier_data;
140 ModifierData *first_md = BKE_modifiers_get_virtual_modifierlist(&object_for_eval,
141 &virtual_modifier_data);
142
143 Mesh *base_mesh = static_cast<Mesh *>(object->data);
144
145 blender::Array<blender::float3> deformed_verts(base_mesh->vert_positions());
146
147 for (ModifierData *md = first_md; md != nullptr; md = md->next) {
149 if (md == &mmd->modifier) {
150 break;
151 }
152 if (!BKE_modifier_is_enabled(scene_eval, md, required_mode)) {
153 continue;
154 }
156 break;
157 }
158 BKE_modifier_deform_verts(md, &mesh_eval_context, base_mesh, deformed_verts);
159 }
160
161 return deformed_verts;
162}
163
165{
166
167 for (ModifierData *md = lastmd; md; md = md->prev) {
168 if (md->type == eModifierType_Multires) {
170 return reinterpret_cast<MultiresModifierData *>(md);
171 }
172 }
173 }
174
175 return nullptr;
176}
177
178MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, const bool use_first)
179{
180 MultiresModifierData *mmd = nullptr, *firstmmd = nullptr;
181
182 /* find first active multires modifier */
184 if (md->type == eModifierType_Multires) {
185 if (!firstmmd) {
186 firstmmd = reinterpret_cast<MultiresModifierData *>(md);
187 }
188
190 mmd = reinterpret_cast<MultiresModifierData *>(md);
191 break;
192 }
193 }
194 }
195
196 if (!mmd && use_first) {
197 /* active multires have not been found
198 * try to use first one */
199 return firstmmd;
200 }
201
202 return mmd;
203}
204
205int multires_get_level(const Scene *scene,
206 const Object *ob,
207 const MultiresModifierData *mmd,
208 const bool render,
209 const bool ignore_simplify)
210{
211 if (render) {
212 return (scene != nullptr) ? get_render_subsurf_level(&scene->r, mmd->renderlvl, true) :
213 mmd->renderlvl;
214 }
215 if (ob->mode == OB_MODE_SCULPT) {
216 return mmd->sculptlvl;
217 }
218 if (ignore_simplify) {
219 return mmd->lvl;
220 }
221
222 return (scene != nullptr) ? get_render_subsurf_level(&scene->r, mmd->lvl, false) : mmd->lvl;
223}
224
226{
227 mmd->totlvl = lvl;
228
229 if (ob->mode != OB_MODE_SCULPT) {
230 mmd->lvl = std::clamp<char>(std::max<char>(mmd->lvl, lvl), 0, mmd->totlvl);
231 }
232
233 mmd->sculptlvl = std::clamp<char>(std::max<char>(mmd->sculptlvl, lvl), 0, mmd->totlvl);
234 mmd->renderlvl = std::clamp<char>(std::max<char>(mmd->renderlvl, lvl), 0, mmd->totlvl);
235}
236
238{
239 if (flags & MULTIRES_COORDS_MODIFIED) {
240 subdiv_ccg->dirty.coords = true;
241 }
242 if (flags & MULTIRES_HIDDEN_MODIFIED) {
243 subdiv_ccg->dirty.hidden = true;
244 }
245}
246
248 Object *object,
249 const MultiresModifiedFlags flags)
250{
251 if (object == nullptr) {
252 return;
253 }
254 /* NOTE: CCG live inside of evaluated object.
255 *
256 * While this is a bit weird to tag the only one, this is how other areas were built
257 * historically: they are tagging multires for update and then rely on object re-evaluation to
258 * do an actual update.
259 *
260 * In a longer term maybe special dependency graph tag can help sanitizing this a bit. */
261 Object *object_eval = DEG_get_evaluated(depsgraph, object);
262 Mesh *mesh = static_cast<Mesh *>(object_eval->data);
263 SubdivCCG *subdiv_ccg = mesh->runtime->subdiv_ccg.get();
264 if (subdiv_ccg == nullptr) {
265 return;
266 }
267 multires_ccg_mark_as_modified(subdiv_ccg, flags);
268}
269
271{
272 if (object == nullptr || object->sculpt == nullptr) {
273 return;
274 }
276 if (!pbvh) {
277 return;
278 }
279
280 SculptSession *sculpt_session = object->sculpt;
281 if (pbvh->type() != blender::bke::pbvh::Type::Grids || !sculpt_session->multires.active ||
282 sculpt_session->multires.modifier == nullptr)
283 {
284 return;
285 }
286
287 SubdivCCG *subdiv_ccg = sculpt_session->subdiv_ccg;
288 if (subdiv_ccg == nullptr) {
289 return;
290 }
291
292 if (!subdiv_ccg->dirty.coords && !subdiv_ccg->dirty.hidden) {
293 return;
294 }
295
296 Mesh *mesh = static_cast<Mesh *>(object->data);
297
298 /* Check that the multires modifier still exists.
299 * Fixes crash when deleting multires modifier
300 * from within sculpt mode.
301 */
302 MultiresModifierData *mmd = nullptr;
303 VirtualModifierData virtual_modifier_data;
304
305 for (ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtual_modifier_data);
306 md;
307 md = md->next)
308 {
309 if (md->type == eModifierType_Multires) {
311 mmd = reinterpret_cast<MultiresModifierData *>(md);
312 }
313 }
314 }
315
316 if (!mmd) {
317 return;
318 }
319
321 sculpt_session->multires.modifier->totlvl, mesh, sculpt_session->subdiv_ccg);
322
323 subdiv_ccg->dirty.coords = false;
324 subdiv_ccg->dirty.hidden = false;
325}
326
328{
329 using namespace blender;
331
332 if (object == nullptr || object->sculpt == nullptr) {
333 return;
334 }
335
337}
338
346
347/* reset the multires levels to match the number of mdisps */
349{
350 Mesh *mesh = static_cast<Mesh *>(ob->data);
351 const blender::OffsetIndices faces = mesh->faces();
352 int totlvl = 0;
353
354 const MDisps *mdisp = static_cast<const MDisps *>(
356
357 for (const int i : faces.index_range()) {
358 for (const int corner : faces[i]) {
359 const MDisps *md = &mdisp[corner];
360 if (md->totdisp == 0) {
361 continue;
362 }
363
364 while (true) {
365 const int side = (1 << (totlvl - 1)) + 1;
366 const int lvl_totdisp = side * side;
367 if (md->totdisp == lvl_totdisp) {
368 break;
369 }
370 if (md->totdisp < lvl_totdisp) {
371 totlvl--;
372 }
373 else {
374 totlvl++;
375 }
376 }
377
378 break;
379 }
380 }
381
382 return totlvl;
383}
384
386{
387 Mesh *mesh = static_cast<Mesh *>(ob->data);
388 const MDisps *mdisp;
389
390 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
391 mdisp = static_cast<const MDisps *>(CustomData_get_layer(&em->bm->ldata, CD_MDISPS));
392 }
393 else {
394 mdisp = static_cast<const MDisps *>(CustomData_get_layer(&mesh->corner_data, CD_MDISPS));
395 }
396
397 if (mdisp) {
398 mmd->totlvl = get_levels_from_disps(ob);
399 mmd->lvl = std::min(mmd->lvl, mmd->totlvl);
400 mmd->sculptlvl = std::min(mmd->sculptlvl, mmd->totlvl);
401 mmd->renderlvl = std::min(mmd->renderlvl, mmd->totlvl);
402 }
403}
404
405static void multires_set_tot_mdisps(Mesh *mesh, const int lvl)
406{
407 MDisps *mdisps = static_cast<MDisps *>(
409
410 if (mdisps) {
411 for (int i = 0; i < mesh->corners_num; i++, mdisps++) {
412 mdisps->totdisp = multires_grid_tot[lvl];
413 mdisps->level = lvl;
414 }
415 }
416}
417
418static void multires_copy_grid(float (*gridA)[3],
419 float (*gridB)[3],
420 const int sizeA,
421 const int sizeB)
422{
423 int x, y, j, skip;
424
425 if (sizeA > sizeB) {
426 skip = (sizeA - 1) / (sizeB - 1);
427
428 for (j = 0, y = 0; y < sizeB; y++) {
429 for (x = 0; x < sizeB; x++, j++) {
430 copy_v3_v3(gridA[y * skip * sizeA + x * skip], gridB[j]);
431 }
432 }
433 }
434 else {
435 skip = (sizeB - 1) / (sizeA - 1);
436
437 for (j = 0, y = 0; y < sizeA; y++) {
438 for (x = 0; x < sizeA; x++, j++) {
439 copy_v3_v3(gridA[j], gridB[y * skip * sizeB + x * skip]);
440 }
441 }
442 }
443}
444
445/* Reallocate gpm->data at a lower resolution and copy values over
446 * from the original high-resolution data */
447static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, const int level)
448{
449 if (level < gpm->level) {
450 const int gridsize = CCG_grid_size(level);
451 float *data = MEM_calloc_arrayN<float>(size_t(square_i(gridsize)), __func__);
452
453 for (int y = 0; y < gridsize; y++) {
454 for (int x = 0; x < gridsize; x++) {
455 data[y * gridsize + x] = paint_grid_paint_mask(gpm, level, x, y);
456 }
457 }
458
459 MEM_freeN(gpm->data);
460 gpm->data = data;
461 gpm->level = level;
462 }
463}
464
465static void multires_del_higher(MultiresModifierData *mmd, Object *ob, const int lvl)
466{
467 Mesh *mesh = (Mesh *)ob->data;
468 const blender::OffsetIndices faces = mesh->faces();
469 const int levels = mmd->totlvl - lvl;
470 MDisps *mdisps;
471 GridPaintMask *gpm;
472
475 mdisps = static_cast<MDisps *>(
477 gpm = static_cast<GridPaintMask *>(
479
481
482 if (mdisps && levels > 0) {
483 if (lvl > 0) {
484 const int nsize = multires_side_tot[lvl];
485 const int hsize = multires_side_tot[mmd->totlvl];
486
487 for (const int i : faces.index_range()) {
488 for (const int corner : faces[i]) {
489 MDisps *mdisp = &mdisps[corner];
490 const int totdisp = multires_grid_tot[lvl];
491
492 float (*disps)[3] = MEM_calloc_arrayN<float[3]>(totdisp, "multires disps");
493
494 if (mdisp->disps != nullptr) {
495 float (*ndisps)[3] = disps;
496 float (*hdisps)[3] = mdisp->disps;
497
498 multires_copy_grid(ndisps, hdisps, nsize, hsize);
499 if (mdisp->hidden) {
500 BLI_bitmap *gh = multires_mdisps_downsample_hidden(mdisp->hidden, mdisp->level, lvl);
501 MEM_freeN(mdisp->hidden);
502 mdisp->hidden = gh;
503 }
504
505 MEM_freeN(mdisp->disps);
506 }
507
508 mdisp->disps = disps;
509 mdisp->totdisp = totdisp;
510 mdisp->level = lvl;
511
512 if (gpm) {
513 multires_grid_paint_mask_downsample(&gpm[corner], lvl);
514 }
515 }
516 }
517 }
518 else {
520 }
521 }
522
523 multires_set_tot_level(ob, mmd, lvl);
524}
525
527 Scene *scene,
528 Object *ob,
529 const int direction)
530{
531 Mesh *mesh = BKE_mesh_from_object(ob);
532 const int lvl = multires_get_level(scene, ob, mmd, false, true);
533 const int levels = mmd->totlvl - lvl;
534
537 MDisps *mdisps = static_cast<MDisps *>(
539
541
542 if (mdisps && levels > 0 && direction == 1) {
543 multires_del_higher(mmd, ob, lvl);
544 }
545
546 multires_set_tot_level(ob, mmd, lvl);
547}
548
550{
551 using namespace blender;
552 if (ob == nullptr) {
553 return;
554 }
555 SculptSession *sculpt_session = ob->sculpt;
556 if (sculpt_session == nullptr) {
557 return;
558 }
559 SubdivCCG *subdiv_ccg = sculpt_session->subdiv_ccg;
560 if (subdiv_ccg == nullptr) {
561 return;
562 }
565 BKE_subdiv_ccg_average_stitch_faces(*subdiv_ccg, IndexMask(subdiv_ccg->faces.size()));
566}
567
568void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v)
569{
570 const int st_max = st - 1;
571 float d[4][3], d2[2][3];
572
573 if (!disps || isnan(u) || isnan(v)) {
574 return;
575 }
576
577 if (u < 0) {
578 u = 0;
579 }
580 else if (u >= st) {
581 u = st_max;
582 }
583 if (v < 0) {
584 v = 0;
585 }
586 else if (v >= st) {
587 v = st_max;
588 }
589
590 const int x = floor(u);
591 const int y = floor(v);
592 int x2 = x + 1;
593 int y2 = y + 1;
594
595 if (x2 >= st) {
596 x2 = st_max;
597 }
598 if (y2 >= st) {
599 y2 = st_max;
600 }
601
602 const float urat = u - x;
603 const float vrat = v - y;
604 const float uopp = 1 - urat;
605
606 mul_v3_v3fl(d[0], disps[y * st + x], uopp);
607 mul_v3_v3fl(d[1], disps[y * st + x2], urat);
608 mul_v3_v3fl(d[2], disps[y2 * st + x], uopp);
609 mul_v3_v3fl(d[3], disps[y2 * st + x2], urat);
610
611 add_v3_v3v3(d2[0], d[0], d[1]);
612 add_v3_v3v3(d2[1], d[2], d[3]);
613 mul_v3_fl(d2[0], 1 - vrat);
614 mul_v3_fl(d2[1], vrat);
615
616 add_v3_v3v3(out, d2[0], d2[1]);
617}
618
620 const MultiresModifierData *mmd_src,
621 MultiresModifierData *mmd_dst)
622{
623 if (mmd_src->totlvl == mmd_dst->totlvl) {
624 return;
625 }
626
627 if (mmd_src->totlvl > mmd_dst->totlvl) {
629 ob_dst, mmd_dst, mmd_src->totlvl, MultiresSubdivideModeType::CatmullClark);
630 }
631 else {
632 multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl);
633 }
634}
635
636static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
637{
638 MultiresModifierData *mmd_src = get_multires_modifier(scene, ob_src, true);
639 MultiresModifierData *mmd_dst = get_multires_modifier(scene, ob_dst, true);
640
641 if (!mmd_src) {
642 /* NOTE(@sergey): object could have MDISP even when there is no multires modifier
643 * this could lead to troubles due to I've got no idea how mdisp could be
644 * up-sampled correct without modifier data. Just remove mdisps if no multires present. */
645 multires_customdata_delete(static_cast<Mesh *>(ob_src->data));
646 }
647
648 if (mmd_src && mmd_dst) {
649 multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst);
650 }
651}
652
653static void multires_apply_uniform_scale(Object *object, const float scale)
654{
655 Mesh *mesh = static_cast<Mesh *>(object->data);
656 MDisps *mdisps = static_cast<MDisps *>(
658 for (int i = 0; i < mesh->corners_num; i++) {
659 MDisps *grid = &mdisps[i];
660 for (int j = 0; j < grid->totdisp; j++) {
661 mul_v3_fl(grid->disps[j], scale);
662 }
663 }
664}
665
666static void multires_apply_smat(Depsgraph * /*depsgraph*/,
667 Scene *scene,
668 Object *object,
669 const float smat[3][3])
670{
671 const MultiresModifierData *mmd = get_multires_modifier(scene, object, true);
672 if (mmd == nullptr || mmd->totlvl == 0) {
673 return;
674 }
675 /* Make sure layer present. */
676 Mesh *mesh = static_cast<Mesh *>(object->data);
679 return;
680 }
681 if (is_uniform_scaled_m3(smat)) {
682 const float scale = mat3_to_scale(smat);
683 multires_apply_uniform_scale(object, scale);
684 }
685 else {
686 /* TODO(@sergey): This branch of code actually requires more work to
687 * preserve all the details. */
688 const float scale = mat3_to_scale(smat);
689 multires_apply_uniform_scale(object, scale);
690 }
691}
692
694{
695 int lvl = 13;
696
697 while (lvl > 0) {
698 const int side = (1 << (lvl - 1)) + 1;
699 if ((s->totdisp % (side * side)) == 0) {
700 return s->totdisp / (side * side);
701 }
702 lvl--;
703 }
704
705 return 0;
706}
707
709{
710 float smat[3][3];
711
712 /* object's scale matrix */
713 BKE_object_scale_to_mat3(ob, smat);
714
715 multires_apply_smat(depsgraph, scene, ob, smat);
716}
717
718void multiresModifier_prepare_join(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *to_ob)
719{
720 float smat[3][3], tmat[3][3], mat[3][3];
721 multires_sync_levels(scene, to_ob, ob);
722
723 /* construct scale matrix for displacement */
724 BKE_object_scale_to_mat3(to_ob, tmat);
725 invert_m3(tmat);
726 BKE_object_scale_to_mat3(ob, smat);
727 mul_m3_m3m3(mat, smat, tmat);
728
729 multires_apply_smat(depsgraph, scene, ob, mat);
730}
731
733{
734
736 MDisps *mdisp = static_cast<MDisps *>(
738
739 if (!mdisp) {
740 return;
741 }
742
743 MDisps *cur = mdisp;
744 int grid = 0;
745 for (int i = 0; i < mesh->corners_num; i++, cur++) {
746 if (cur->totdisp) {
747 grid = mdisp->totdisp;
748
749 break;
750 }
751 }
752
753 for (int i = 0; i < mesh->corners_num; i++, mdisp++) {
754 /* allocate memory for mdisp, the whole disp layer would be erased otherwise */
755 if (!mdisp->totdisp || !mdisp->disps) {
756 if (grid) {
757 mdisp->totdisp = grid;
758 mdisp->disps = MEM_calloc_arrayN<float[3]>(mdisp->totdisp, "mdisp topology");
759 }
760
761 continue;
762 }
763 }
764}
765
766void multires_ensure_external_read(Mesh *mesh, const int top_level)
767{
769 return;
770 }
771
772 /* Modify the data array from the original mesh, not the evaluated mesh.
773 * When multiple objects share the same mesh, this can lead to memory leaks. */
774 MDisps *mdisps = const_cast<MDisps *>(
775 static_cast<const MDisps *>(CustomData_get_layer(&mesh->corner_data, CD_MDISPS)));
776 if (mdisps == nullptr) {
777 mdisps = static_cast<MDisps *>(
779 }
780
781 const int totloop = mesh->corners_num;
782
783 for (int i = 0; i < totloop; ++i) {
784 if (mdisps[i].level != top_level) {
785 MEM_SAFE_FREE(mdisps[i].disps);
786 }
787
788 /* NOTE: CustomData_external_read will take care of allocation of displacement vectors if
789 * they are missing. */
790
791 const int totdisp = multires_grid_tot[top_level];
792 mdisps[i].totdisp = totdisp;
793 mdisps[i].level = top_level;
794 }
795
797}
int CCG_grid_factor(int low_level, int high_level)
Definition BKE_ccg.hh:110
int CCG_grid_size(const int level)
Definition BKE_ccg.hh:104
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
void CustomData_external_remove(CustomData *data, ID *id, eCustomDataType type, int totelem)
@ CD_SET_DEFAULT
void CustomData_external_read(CustomData *data, ID *id, eCustomDataMask mask, int totelem)
const CustomData_MeshMasks CD_MASK_BAREMESH
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
void CustomData_external_reload(CustomData *data, ID *id, eCustomDataMask mask, int totelem)
bool CustomData_external_test(CustomData *data, eCustomDataType type)
bool CustomData_free_layer_active(CustomData *data, eCustomDataType type)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
Mesh * BKE_mesh_from_object(Object *ob)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
bool BKE_modifier_deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data)
ModifierApplyFlag
@ MOD_APPLY_USECACHE
@ MOD_APPLY_RENDER
@ MOD_APPLY_IGNORE_SIMPLIFY
MultiresModifiedFlags
@ MULTIRES_HIDDEN_MODIFIED
@ MULTIRES_COORDS_MODIFIED
void multiresModifier_subdivide_to_level(Object *object, MultiresModifierData *mmd, int top_level, MultiresSubdivideModeType mode)
bool multiresModifier_reshapeFromCCG(int tot_level, Mesh *coarse_mesh, SubdivCCG *subdiv_ccg)
General operations, lookup, etc. for blender objects.
void BKE_object_scale_to_mat3(const Object *ob, float r_mat[3][3])
float paint_grid_paint_mask(const GridPaintMask *gpm, uint level, uint x, uint y)
Definition paint.cc:2155
void BKE_sculptsession_free_pbvh(Object &object)
Definition paint.cc:2286
A BVH for high poly meshes.
int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
Definition scene.cc:2753
void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG &subdiv_ccg, const blender::IndexMask &face_mask)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:37
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:61
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition BLI_bitmap.h:99
unsigned int BLI_bitmap
Definition BLI_bitmap.h:13
#define LISTBASE_FOREACH(type, var, list)
MINLINE int square_i(int a)
float mat3_to_scale(const float mat[3][3])
bool is_uniform_scaled_m3(const float m[3][3])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
bool invert_m3(float mat[3][3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
@ DAG_EVAL_RENDER
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ CD_GRID_PAINT_MASK
#define CD_MASK_MDISPS
@ eModifierMode_Render
@ eModifierMode_Realtime
@ eModifierType_Multires
@ OB_MODE_SCULPT
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
nullptr float
#define out
#define isnan
#define floor
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static char faces[256]
static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, const int level)
Definition multires.cc:447
void multires_topology_changed(Mesh *mesh)
Definition multires.cc:732
void multires_force_external_reload(Object *object)
Definition multires.cc:339
void multires_customdata_delete(Mesh *mesh)
Definition multires.cc:53
static const int multires_grid_tot[]
Definition multires.cc:46
void multiresModifier_prepare_join(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *to_ob)
Definition multires.cc:718
blender::Array< blender::float3 > BKE_multires_create_deformed_base_mesh_vert_coords(Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
Definition multires.cc:119
static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
Definition multires.cc:636
void multires_ensure_external_read(Mesh *mesh, const int top_level)
Definition multires.cc:766
void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, const MultiresModifiedFlags flags)
Definition multires.cc:247
MultiresModifierData * find_multires_modifier_before(Scene *scene, ModifierData *lastmd)
Definition multires.cc:164
static void multires_apply_smat(Depsgraph *, Scene *scene, Object *object, const float smat[3][3])
Definition multires.cc:666
void multires_flush_sculpt_updates(Object *object)
Definition multires.cc:270
Mesh * BKE_multires_create_mesh(Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
Definition multires.cc:99
static void multires_set_tot_mdisps(Mesh *mesh, const int lvl)
Definition multires.cc:405
void multiresModifier_scale_disp(Depsgraph *depsgraph, Scene *scene, Object *ob)
Definition multires.cc:708
void old_mdisps_bilinear(float out[3], float(*disps)[3], const int st, float u, float v)
Definition multires.cc:568
void multiresModifier_sync_levels_ex(Object *ob_dst, const MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst)
Definition multires.cc:619
static const int multires_side_tot[]
Definition multires.cc:48
void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, const int lvl)
Definition multires.cc:225
static void multires_del_higher(MultiresModifierData *mmd, Object *ob, const int lvl)
Definition multires.cc:465
static int get_levels_from_disps(Object *ob)
Definition multires.cc:348
void multires_stitch_grids(Object *ob)
Definition multires.cc:549
static void multires_apply_uniform_scale(Object *object, const float scale)
Definition multires.cc:653
void multiresModifier_del_levels(MultiresModifierData *mmd, Scene *scene, Object *ob, const int direction)
Definition multires.cc:526
void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
Definition multires.cc:385
static void multires_copy_grid(float(*gridA)[3], float(*gridB)[3], const int sizeA, const int sizeB)
Definition multires.cc:418
int multires_mdisp_corners(const MDisps *s)
Definition multires.cc:693
void multires_force_sculpt_rebuild(Object *object)
Definition multires.cc:327
static void multires_ccg_mark_as_modified(SubdivCCG *subdiv_ccg, const MultiresModifiedFlags flags)
Definition multires.cc:237
static BLI_bitmap * multires_mdisps_downsample_hidden(const BLI_bitmap *old_hidden, const int old_level, const int new_level)
Definition multires.cc:77
void multiresModifier_ensure_external_read(Mesh *mesh, const MultiresModifierData *mmd)
Definition multires.cc:798
MultiresModifierData * get_multires_modifier(Scene *scene, Object *ob, const bool use_first)
Definition multires.cc:178
int multires_get_level(const Scene *scene, const Object *ob, const MultiresModifierData *mmd, const bool render, const bool ignore_simplify)
Definition multires.cc:205
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
Mesh * mesh_get_eval_deform(Depsgraph *depsgraph, const Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
float(* disps)[3]
unsigned int * hidden
int corners_num
MeshRuntimeHandle * runtime
CustomData corner_data
struct ModifierData * next
struct ModifierData * prev
ModifierApplyFlag flag
ModifierTypeType type
Mesh *(* modify_mesh)(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
ObjectRuntimeHandle * runtime
ListBase modifiers
struct SculptSession * sculpt
struct RenderData r
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
struct SculptSession::@300305335361021334214041350300054316061376210174 multires
MultiresModifierData * modifier
Definition BKE_paint.hh:373
blender::OffsetIndices< int > faces
struct SubdivCCG::@013326174356303061066227044362260371376134015325 dirty
i
Definition text_draw.cc:230