Blender V4.3
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
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_math_matrix.h"
21#include "BLI_task.h"
22#include "BLI_utildefines.h"
23
24#include "BKE_ccg.hh"
25#include "BKE_editmesh.hh"
26#include "BKE_mesh.hh"
28#include "BKE_mesh_runtime.hh"
29#include "BKE_modifier.hh"
30#include "BKE_multires.hh"
31#include "BKE_paint.hh"
32#include "BKE_pbvh_api.hh"
33#include "BKE_scene.hh"
34#include "BKE_subdiv_ccg.hh"
35#include "BKE_subsurf.hh"
36
37#include "BKE_object.hh"
38
39#include "CCGSubSurf.h"
40
42
43#include <cmath>
44#include <cstring>
45
46/* MULTIRES MODIFIER */
47static const int multires_grid_tot[] = {
48 0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409};
49static const int multires_side_tot[] = {
50 0, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097};
51
52/* See multiresModifier_disp_run for description of each operation */
58
60 DerivedMesh *dm, Mesh *mesh, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl);
61
65{
66 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
67 /* CustomData_external_remove is used here only to mark layer
68 * as non-external for further freeing, so zero element count
69 * looks safer than `em->bm->totface`. */
70 CustomData_external_remove(&em->bm->ldata, &mesh->id, CD_MDISPS, 0);
71
72 if (CustomData_has_layer(&em->bm->ldata, CD_MDISPS)) {
73 BM_data_layer_free(em->bm, &em->bm->ldata, CD_MDISPS);
74 }
75
76 if (CustomData_has_layer(&em->bm->ldata, CD_GRID_PAINT_MASK)) {
77 BM_data_layer_free(em->bm, &em->bm->ldata, CD_GRID_PAINT_MASK);
78 }
79 }
80 else {
81 CustomData_external_remove(&mesh->corner_data, &mesh->id, CD_MDISPS, mesh->corners_num);
82 CustomData_free_layer_active(&mesh->corner_data, CD_MDISPS, mesh->corners_num);
83
84 CustomData_free_layer_active(&mesh->corner_data, CD_GRID_PAINT_MASK, mesh->corners_num);
85 }
86}
87
90 int lo_level,
91 int hi_level,
92
93 /* assumed to be at hi_level (or null) */
94 const BLI_bitmap *prev_hidden)
95{
96 BLI_bitmap *subd;
97 int hi_gridsize = BKE_ccg_gridsize(hi_level);
98 int lo_gridsize = BKE_ccg_gridsize(lo_level);
99 int yh, xh, xl, yl, xo, yo, hi_ndx;
100 int offset, factor;
101
102 BLI_assert(lo_level <= hi_level);
103
104 /* fast case */
105 if (lo_level == hi_level) {
106 return static_cast<BLI_bitmap *>(MEM_dupallocN(lo_hidden));
107 }
108
109 subd = BLI_BITMAP_NEW(square_i(hi_gridsize), "MDisps.hidden upsample");
110
111 factor = BKE_ccg_factor(lo_level, hi_level);
112 offset = 1 << (hi_level - lo_level - 1);
113
114 /* low-res blocks */
115 for (yl = 0; yl < lo_gridsize; yl++) {
116 for (xl = 0; xl < lo_gridsize; xl++) {
117 int lo_val = BLI_BITMAP_TEST(lo_hidden, yl * lo_gridsize + xl);
118
119 /* high-res blocks */
120 for (yo = -offset; yo <= offset; yo++) {
121 yh = yl * factor + yo;
122 if (yh < 0 || yh >= hi_gridsize) {
123 continue;
124 }
125
126 for (xo = -offset; xo <= offset; xo++) {
127 xh = xl * factor + xo;
128 if (xh < 0 || xh >= hi_gridsize) {
129 continue;
130 }
131
132 hi_ndx = yh * hi_gridsize + xh;
133
134 if (prev_hidden) {
135 /* If prev_hidden is available, copy it to
136 * subd, except when the equivalent element in
137 * lo_hidden is different */
138 if (lo_val != prev_hidden[hi_ndx]) {
139 BLI_BITMAP_SET(subd, hi_ndx, lo_val);
140 }
141 else {
142 BLI_BITMAP_SET(subd, hi_ndx, prev_hidden[hi_ndx]);
143 }
144 }
145 else {
146 BLI_BITMAP_SET(subd, hi_ndx, lo_val);
147 }
148 }
149 }
150 }
151 }
152
153 return subd;
154}
155
157 int old_level,
158 int new_level)
159{
160 BLI_bitmap *new_hidden;
161 int new_gridsize = BKE_ccg_gridsize(new_level);
162 int old_gridsize = BKE_ccg_gridsize(old_level);
163 int x, y, factor, old_value;
164
165 BLI_assert(new_level <= old_level);
166 factor = BKE_ccg_factor(new_level, old_level);
167 new_hidden = BLI_BITMAP_NEW(square_i(new_gridsize), "downsample hidden");
168
169 for (y = 0; y < new_gridsize; y++) {
170 for (x = 0; x < new_gridsize; x++) {
171 old_value = BLI_BITMAP_TEST(old_hidden, factor * y * old_gridsize + x * factor);
172
173 BLI_BITMAP_SET(new_hidden, y * new_gridsize + x, old_value);
174 }
175 }
176
177 return new_hidden;
178}
179
180static void multires_output_hidden_to_ccgdm(CCGDerivedMesh *ccgdm, Mesh *mesh, int level)
181{
182 const blender::OffsetIndices faces = mesh->faces();
183 const MDisps *mdisps = static_cast<const MDisps *>(
184 CustomData_get_layer(&mesh->corner_data, CD_MDISPS));
185 BLI_bitmap **grid_hidden = ccgdm->gridHidden;
186 int *gridOffset;
187 int j;
188
189 gridOffset = ccgdm->dm.getGridOffset(&ccgdm->dm);
190
191 for (const int i : faces.index_range()) {
192 for (j = 0; j < faces[i].size(); j++) {
193 int g = gridOffset[i] + j;
194 const MDisps *md = &mdisps[g];
195 BLI_bitmap *gh = md->hidden;
196
197 if (gh) {
198 grid_hidden[g] = multires_mdisps_downsample_hidden(gh, md->level, level);
199 }
200 }
201 }
202}
203
204/* subdivide mdisps.hidden if needed (assumes that md.level reflects
205 * the current level of md.hidden) */
206static void multires_mdisps_subdivide_hidden(MDisps *md, int new_level)
207{
208 BLI_bitmap *subd;
209
210 BLI_assert(md->hidden);
211
212 /* nothing to do if already subdivided enough */
213 if (md->level >= new_level) {
214 return;
215 }
216
217 subd = multires_mdisps_upsample_hidden(md->hidden, md->level, new_level, nullptr);
218
219 /* swap in the subdivided data */
220 MEM_freeN(md->hidden);
221 md->hidden = subd;
222}
223
225{
226 Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
229 depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
230 ModifierEvalContext modifier_ctx{};
231 modifier_ctx.depsgraph = depsgraph;
232 modifier_ctx.object = object_eval;
234
236 Mesh *result = mti->modify_mesh(&mmd->modifier, &modifier_ctx, deformed_mesh);
237
238 if (result == deformed_mesh) {
239 result = BKE_mesh_copy_for_eval(*deformed_mesh);
240 }
241 return result;
242}
243
245 Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
246{
248 Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
249
250 Object object_for_eval = blender::dna::shallow_copy(*object_eval);
251 blender::bke::ObjectRuntime runtime = *object_eval->runtime;
252 object_for_eval.runtime = &runtime;
253
254 object_for_eval.data = object->data;
255 object_for_eval.sculpt = nullptr;
256
257 const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
258 ModifierEvalContext mesh_eval_context = {depsgraph, &object_for_eval, ModifierApplyFlag(0)};
259 if (use_render) {
260 mesh_eval_context.flag |= MOD_APPLY_RENDER;
261 }
262 const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
263
264 VirtualModifierData virtual_modifier_data;
265 ModifierData *first_md = BKE_modifiers_get_virtual_modifierlist(&object_for_eval,
266 &virtual_modifier_data);
267
268 Mesh *base_mesh = static_cast<Mesh *>(object->data);
269
270 blender::Array<blender::float3> deformed_verts(base_mesh->vert_positions());
271
272 for (ModifierData *md = first_md; md != nullptr; md = md->next) {
274 if (md == &mmd->modifier) {
275 break;
276 }
277 if (!BKE_modifier_is_enabled(scene_eval, md, required_mode)) {
278 continue;
279 }
281 break;
282 }
283 BKE_modifier_deform_verts(md, &mesh_eval_context, base_mesh, deformed_verts);
284 }
285
286 return deformed_verts;
287}
288
290{
291 ModifierData *md;
292
293 for (md = lastmd; md; md = md->prev) {
294 if (md->type == eModifierType_Multires) {
296 return (MultiresModifierData *)md;
297 }
298 }
299 }
300
301 return nullptr;
302}
303
305{
306 MultiresModifierData *mmd = nullptr, *firstmmd = nullptr;
307
308 /* find first active multires modifier */
310 if (md->type == eModifierType_Multires) {
311 if (!firstmmd) {
312 firstmmd = (MultiresModifierData *)md;
313 }
314
316 mmd = (MultiresModifierData *)md;
317 break;
318 }
319 }
320 }
321
322 if (!mmd && use_first) {
323 /* active multires have not been found
324 * try to use first one */
325 return firstmmd;
326 }
327
328 return mmd;
329}
330
331int multires_get_level(const Scene *scene,
332 const Object *ob,
333 const MultiresModifierData *mmd,
334 bool render,
335 bool ignore_simplify)
336{
337 if (render) {
338 return (scene != nullptr) ? get_render_subsurf_level(&scene->r, mmd->renderlvl, true) :
339 mmd->renderlvl;
340 }
341 if (ob->mode == OB_MODE_SCULPT) {
342 return mmd->sculptlvl;
343 }
344 if (ignore_simplify) {
345 return mmd->lvl;
346 }
347
348 return (scene != nullptr) ? get_render_subsurf_level(&scene->r, mmd->lvl, false) : mmd->lvl;
349}
350
352{
353 mmd->totlvl = lvl;
354
355 if (ob->mode != OB_MODE_SCULPT) {
356 mmd->lvl = std::clamp<char>(std::max<char>(mmd->lvl, lvl), 0, mmd->totlvl);
357 }
358
359 mmd->sculptlvl = std::clamp<char>(std::max<char>(mmd->sculptlvl, lvl), 0, mmd->totlvl);
360 mmd->renderlvl = std::clamp<char>(std::max<char>(mmd->renderlvl, lvl), 0, mmd->totlvl);
361}
362
364{
365 if (flags & MULTIRES_COORDS_MODIFIED) {
366 subdiv_ccg->dirty.coords = true;
367 }
368 if (flags & MULTIRES_HIDDEN_MODIFIED) {
369 subdiv_ccg->dirty.hidden = true;
370 }
371}
372
374{
375 if (object == nullptr) {
376 return;
377 }
378 /* NOTE: CCG live inside of evaluated object.
379 *
380 * While this is a bit weird to tag the only one, this is how other areas were built
381 * historically: they are tagging multires for update and then rely on object re-evaluation to
382 * do an actual update.
383 *
384 * In a longer term maybe special dependency graph tag can help sanitizing this a bit. */
385 Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
386 Mesh *mesh = static_cast<Mesh *>(object_eval->data);
387 SubdivCCG *subdiv_ccg = mesh->runtime->subdiv_ccg.get();
388 if (subdiv_ccg == nullptr) {
389 return;
390 }
391 multires_ccg_mark_as_modified(subdiv_ccg, flags);
392}
393
395{
396 if (object == nullptr || object->sculpt == nullptr) {
397 return;
398 }
400 if (!pbvh) {
401 return;
402 }
403
404 SculptSession *sculpt_session = object->sculpt;
405 if (pbvh->type() != blender::bke::pbvh::Type::Grids || !sculpt_session->multires.active ||
406 sculpt_session->multires.modifier == nullptr)
407 {
408 return;
409 }
410
411 SubdivCCG *subdiv_ccg = sculpt_session->subdiv_ccg;
412 if (subdiv_ccg == nullptr) {
413 return;
414 }
415
416 if (!subdiv_ccg->dirty.coords && !subdiv_ccg->dirty.hidden) {
417 return;
418 }
419
420 Mesh *mesh = static_cast<Mesh *>(object->data);
421
422 /* Check that the multires modifier still exists.
423 * Fixes crash when deleting multires modifier
424 * from within sculpt mode.
425 */
426 ModifierData *md;
427 MultiresModifierData *mmd = nullptr;
428 VirtualModifierData virtual_modifier_data;
429
430 for (md = BKE_modifiers_get_virtual_modifierlist(object, &virtual_modifier_data); md;
431 md = md->next)
432 {
433 if (md->type == eModifierType_Multires) {
435 mmd = (MultiresModifierData *)md;
436 }
437 }
438 }
439
440 if (!mmd) {
441 return;
442 }
443
445 sculpt_session->multires.modifier->totlvl, mesh, sculpt_session->subdiv_ccg);
446
447 subdiv_ccg->dirty.coords = false;
448 subdiv_ccg->dirty.hidden = false;
449}
450
452{
453 using namespace blender;
455
456 if (object == nullptr || object->sculpt == nullptr) {
457 return;
458 }
459
461}
462
464{
465 Mesh *mesh = BKE_mesh_from_object(object);
466
467 CustomData_external_reload(&mesh->corner_data, &mesh->id, CD_MASK_MDISPS, mesh->corners_num);
469}
470
471/* reset the multires levels to match the number of mdisps */
473{
474 Mesh *mesh = static_cast<Mesh *>(ob->data);
475 const blender::OffsetIndices faces = mesh->faces();
476 int totlvl = 0;
477
478 const MDisps *mdisp = static_cast<const MDisps *>(
479 CustomData_get_layer(&mesh->corner_data, CD_MDISPS));
480
481 for (const int i : faces.index_range()) {
482 for (const int corner : faces[i]) {
483 const MDisps *md = &mdisp[corner];
484 if (md->totdisp == 0) {
485 continue;
486 }
487
488 while (true) {
489 int side = (1 << (totlvl - 1)) + 1;
490 int lvl_totdisp = side * side;
491 if (md->totdisp == lvl_totdisp) {
492 break;
493 }
494 if (md->totdisp < lvl_totdisp) {
495 totlvl--;
496 }
497 else {
498 totlvl++;
499 }
500 }
501
502 break;
503 }
504 }
505
506 return totlvl;
507}
508
510{
511 Mesh *mesh = static_cast<Mesh *>(ob->data);
512 const MDisps *mdisp;
513
514 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
515 mdisp = static_cast<const MDisps *>(CustomData_get_layer(&em->bm->ldata, CD_MDISPS));
516 }
517 else {
518 mdisp = static_cast<const MDisps *>(CustomData_get_layer(&mesh->corner_data, CD_MDISPS));
519 }
520
521 if (mdisp) {
522 mmd->totlvl = get_levels_from_disps(ob);
523 mmd->lvl = std::min(mmd->lvl, mmd->totlvl);
524 mmd->sculptlvl = std::min(mmd->sculptlvl, mmd->totlvl);
525 mmd->renderlvl = std::min(mmd->renderlvl, mmd->totlvl);
526 }
527}
528
529static void multires_set_tot_mdisps(Mesh *mesh, int lvl)
530{
531 MDisps *mdisps = static_cast<MDisps *>(
532 CustomData_get_layer_for_write(&mesh->corner_data, CD_MDISPS, mesh->corners_num));
533 int i;
534
535 if (mdisps) {
536 for (i = 0; i < mesh->corners_num; i++, mdisps++) {
537 mdisps->totdisp = multires_grid_tot[lvl];
538 mdisps->level = lvl;
539 }
540 }
541}
542
543static void multires_reallocate_mdisps(int totloop, MDisps *mdisps, int lvl)
544{
545 int i;
546
547 /* reallocate displacements to be filled in */
548 for (i = 0; i < totloop; i++) {
549 int totdisp = multires_grid_tot[lvl];
550 float(*disps)[3] = static_cast<float(*)[3]>(
551 MEM_calloc_arrayN(totdisp, sizeof(float[3]), __func__));
552
553 if (mdisps[i].disps) {
554 MEM_freeN(mdisps[i].disps);
555 }
556
557 if (mdisps[i].level && mdisps[i].hidden) {
558 multires_mdisps_subdivide_hidden(&mdisps[i], lvl);
559 }
560
561 mdisps[i].disps = disps;
562 mdisps[i].totdisp = totdisp;
563 mdisps[i].level = lvl;
564 }
565}
566
567static void multires_copy_grid(float (*gridA)[3], float (*gridB)[3], int sizeA, int sizeB)
568{
569 int x, y, j, skip;
570
571 if (sizeA > sizeB) {
572 skip = (sizeA - 1) / (sizeB - 1);
573
574 for (j = 0, y = 0; y < sizeB; y++) {
575 for (x = 0; x < sizeB; x++, j++) {
576 copy_v3_v3(gridA[y * skip * sizeA + x * skip], gridB[j]);
577 }
578 }
579 }
580 else {
581 skip = (sizeB - 1) / (sizeA - 1);
582
583 for (j = 0, y = 0; y < sizeA; y++) {
584 for (x = 0; x < sizeA; x++, j++) {
585 copy_v3_v3(gridA[j], gridB[y * skip * sizeB + x * skip]);
586 }
587 }
588 }
589}
590
591static void multires_copy_dm_grid(CCGElem *gridA, CCGElem *gridB, CCGKey *keyA, CCGKey *keyB)
592{
593 int x, y, j, skip;
594
595 if (keyA->grid_size > keyB->grid_size) {
596 skip = (keyA->grid_size - 1) / (keyB->grid_size - 1);
597
598 for (j = 0, y = 0; y < keyB->grid_size; y++) {
599 for (x = 0; x < keyB->grid_size; x++, j++) {
600 memcpy(CCG_elem_offset_co(*keyA, gridA, y * skip * keyA->grid_size + x * skip),
601 CCG_elem_offset_co(*keyB, gridB, j),
602 keyA->elem_size);
603 }
604 }
605 }
606 else {
607 skip = (keyB->grid_size - 1) / (keyA->grid_size - 1);
608
609 for (j = 0, y = 0; y < keyA->grid_size; y++) {
610 for (x = 0; x < keyA->grid_size; x++, j++) {
611 memcpy(CCG_elem_offset_co(*keyA, gridA, j),
612 CCG_elem_offset_co(*keyB, gridB, y * skip * keyB->grid_size + x * skip),
613 keyA->elem_size);
614 }
615 }
616 }
617}
618
619/* Reallocate gpm->data at a lower resolution and copy values over
620 * from the original high-resolution data */
622{
623 if (level < gpm->level) {
624 int gridsize = BKE_ccg_gridsize(level);
625 float *data = static_cast<float *>(
626 MEM_calloc_arrayN(square_i(gridsize), sizeof(float), __func__));
627 int x, y;
628
629 for (y = 0; y < gridsize; y++) {
630 for (x = 0; x < gridsize; x++) {
631 data[y * gridsize + x] = paint_grid_paint_mask(gpm, level, x, y);
632 }
633 }
634
635 MEM_freeN(gpm->data);
636 gpm->data = data;
637 gpm->level = level;
638 }
639}
640
641static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
642{
643 Mesh *mesh = (Mesh *)ob->data;
644 const blender::OffsetIndices faces = mesh->faces();
645 int levels = mmd->totlvl - lvl;
646 MDisps *mdisps;
647 GridPaintMask *gpm;
648
651 mdisps = static_cast<MDisps *>(
652 CustomData_get_layer_for_write(&mesh->corner_data, CD_MDISPS, mesh->corners_num));
653 gpm = static_cast<GridPaintMask *>(
654 CustomData_get_layer_for_write(&mesh->corner_data, CD_GRID_PAINT_MASK, mesh->corners_num));
655
657
658 if (mdisps && levels > 0) {
659 if (lvl > 0) {
660 int nsize = multires_side_tot[lvl];
661 int hsize = multires_side_tot[mmd->totlvl];
662
663 for (const int i : faces.index_range()) {
664 for (const int corner : faces[i]) {
665 MDisps *mdisp = &mdisps[corner];
666 float(*disps)[3], (*ndisps)[3], (*hdisps)[3];
667 int totdisp = multires_grid_tot[lvl];
668
669 disps = static_cast<float(*)[3]>(
670 MEM_calloc_arrayN(totdisp, sizeof(float[3]), "multires disps"));
671
672 if (mdisp->disps != nullptr) {
673 ndisps = disps;
674 hdisps = mdisp->disps;
675
676 multires_copy_grid(ndisps, hdisps, nsize, hsize);
677 if (mdisp->hidden) {
678 BLI_bitmap *gh = multires_mdisps_downsample_hidden(mdisp->hidden, mdisp->level, lvl);
679 MEM_freeN(mdisp->hidden);
680 mdisp->hidden = gh;
681 }
682
683 MEM_freeN(mdisp->disps);
684 }
685
686 mdisp->disps = disps;
687 mdisp->totdisp = totdisp;
688 mdisp->level = lvl;
689
690 if (gpm) {
691 multires_grid_paint_mask_downsample(&gpm[corner], lvl);
692 }
693 }
694 }
695 }
696 else {
698 }
699 }
700
701 multires_set_tot_level(ob, mmd, lvl);
702}
703
705 Scene *scene,
706 Object *ob,
707 int direction)
708{
709 Mesh *mesh = BKE_mesh_from_object(ob);
710 int lvl = multires_get_level(scene, ob, mmd, false, true);
711 int levels = mmd->totlvl - lvl;
712
715 MDisps *mdisps = static_cast<MDisps *>(
716 CustomData_get_layer_for_write(&mesh->corner_data, CD_MDISPS, mesh->corners_num));
717
719
720 if (mdisps && levels > 0 && direction == 1) {
721 multires_del_higher(mmd, ob, lvl);
722 }
723
724 multires_set_tot_level(ob, mmd, lvl);
725}
726
728 Object *ob,
729 DerivedMesh *dm,
730 int lvl,
731 int totlvl,
732 bool alloc_paint_mask,
733 MultiresFlags flags)
734{
736
737 mmd.lvl = lvl;
738 mmd.sculptlvl = lvl;
739 mmd.renderlvl = lvl;
740 mmd.totlvl = totlvl;
741
742 flags |= MULTIRES_USE_LOCAL_MMD;
743 if (alloc_paint_mask) {
745 }
746
747 return multires_make_derived_from_derived(dm, &mmd, scene, ob, flags);
748}
749
751 Object *ob,
752 DerivedMesh *dm,
753 int lvl,
754 bool is_simple,
755 bool is_optimal,
756 bool is_plain_uv,
757 bool alloc_paint_mask,
758 bool for_render,
759 SubsurfFlags flags)
760{
761 SubsurfModifierData smd = {{nullptr}};
762
763 smd.levels = smd.renderLevels = lvl;
764 smd.quality = 3;
765 if (!is_plain_uv) {
767 }
768 else {
770 }
771 if (is_simple) {
773 }
774 if (is_optimal) {
776 }
777
778 if (ob->mode & OB_MODE_EDIT) {
779 flags |= SUBSURF_IN_EDIT_MODE;
780 }
781 if (alloc_paint_mask) {
783 }
784 if (for_render) {
786 }
787
788 return subsurf_make_derived_from_derived(dm, &smd, scene, nullptr, flags);
789}
790
791static void grid_tangent(const CCGKey &key, int x, int y, int axis, CCGElem *grid, float t[3])
792{
793 if (axis == 0) {
794 if (x == key.grid_size - 1) {
795 if (y == key.grid_size - 1) {
797 t, CCG_grid_elem_co(key, grid, x, y - 1), CCG_grid_elem_co(key, grid, x - 1, y - 1));
798 }
799 else {
800 sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, y), CCG_grid_elem_co(key, grid, x - 1, y));
801 }
802 }
803 else {
804 sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x + 1, y), CCG_grid_elem_co(key, grid, x, y));
805 }
806 }
807 else if (axis == 1) {
808 if (y == key.grid_size - 1) {
809 if (x == key.grid_size - 1) {
811 t, CCG_grid_elem_co(key, grid, x - 1, y), CCG_grid_elem_co(key, grid, x - 1, (y - 1)));
812 }
813 else {
814 sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, y), CCG_grid_elem_co(key, grid, x, (y - 1)));
815 }
816 }
817 else {
818 sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, (y + 1)), CCG_grid_elem_co(key, grid, x, y));
819 }
820 }
821}
822
823/* Construct 3x3 tangent-space matrix in 'mat' */
824static void grid_tangent_matrix(float mat[3][3], const CCGKey &key, int x, int y, CCGElem *grid)
825{
826 grid_tangent(key, x, y, 0, grid, mat[0]);
827 normalize_v3(mat[0]);
828
829 grid_tangent(key, x, y, 1, grid, mat[1]);
830 normalize_v3(mat[1]);
831
832 copy_v3_v3(mat[2], CCG_grid_elem_no(key, grid, x, y));
833}
834
847
848static void multires_disp_run_cb(void *__restrict userdata,
849 const int pidx,
850 const TaskParallelTLS *__restrict /*tls*/)
851{
852 MultiresThreadedData *tdata = static_cast<MultiresThreadedData *>(userdata);
853
854 DispOp op = tdata->op;
855 CCGElem **gridData = tdata->gridData;
856 CCGElem **subGridData = tdata->subGridData;
857 CCGKey key = *tdata->key;
858 blender::OffsetIndices<int> faces = tdata->faces;
859 MDisps *mdisps = tdata->mdisps;
860 GridPaintMask *grid_paint_mask = tdata->grid_paint_mask;
861 int *gridOffset = tdata->gridOffset;
862 int gridSize = tdata->gridSize;
863 int dGridSize = tdata->dGridSize;
864 int dSkip = tdata->dSkip;
865
866 const int numVerts = faces[pidx].size();
867 int S, x, y, gIndex = gridOffset[pidx];
868
869 for (S = 0; S < numVerts; S++, gIndex++) {
870 GridPaintMask *gpm = grid_paint_mask ? &grid_paint_mask[gIndex] : nullptr;
871 MDisps *mdisp = &mdisps[faces[pidx][S]];
872 CCGElem *grid = gridData[gIndex];
873 CCGElem *subgrid = subGridData[gIndex];
874 float(*dispgrid)[3] = nullptr;
875
876 dispgrid = mdisp->disps;
877
878 /* if needed, reallocate multires paint mask */
879 if (gpm && gpm->level < key.level) {
880 gpm->level = key.level;
881 if (gpm->data) {
882 MEM_freeN(gpm->data);
883 }
884 gpm->data = static_cast<float *>(
885 MEM_calloc_arrayN(key.grid_area, sizeof(float), "gpm.data"));
886 }
887
888 for (y = 0; y < gridSize; y++) {
889 for (x = 0; x < gridSize; x++) {
890 float *co = CCG_grid_elem_co(key, grid, x, y);
891 float *sco = CCG_grid_elem_co(key, subgrid, x, y);
892 float *data = dispgrid[dGridSize * y * dSkip + x * dSkip];
893 float mat[3][3], disp[3], d[3], mask;
894
895 /* construct tangent space matrix */
896 grid_tangent_matrix(mat, key, x, y, subgrid);
897
898 switch (op) {
900 /* Convert displacement to object space
901 * and add to grid points */
902 mul_v3_m3v3(disp, mat, data);
903 add_v3_v3v3(co, sco, disp);
904 break;
906 /* Calculate displacement between new and old
907 * grid points and convert to tangent space */
908 sub_v3_v3v3(disp, co, sco);
909 invert_m3(mat);
910 mul_v3_m3v3(data, mat, disp);
911 break;
913 /* Convert subdivided displacements to tangent
914 * space and add to the original displacements */
915 invert_m3(mat);
916 mul_v3_m3v3(d, mat, co);
917 add_v3_v3(data, d);
918 break;
919 }
920
921 if (gpm) {
922 switch (op) {
924 /* Copy mask from gpm to DM */
925 CCG_grid_elem_mask(key, grid, x, y) = paint_grid_paint_mask(gpm, key.level, x, y);
926 break;
928 /* Copy mask from DM to gpm */
929 mask = CCG_grid_elem_mask(key, grid, x, y);
930 gpm->data[y * gridSize + x] = std::clamp(mask, 0.0f, 1.0f);
931 break;
933 /* Add mask displacement to gpm */
934 gpm->data[y * gridSize + x] += CCG_grid_elem_mask(key, grid, x, y);
935 break;
936 }
937 }
938 }
939 }
940 }
941}
942
943/* XXX WARNING: subsurf elements from dm and oldGridData *must* be of the same format (size),
944 * because this code uses CCGKey's info from dm to access oldGridData's normals
945 * (through the call to grid_tangent_matrix())! */
947 DerivedMesh *dm, Mesh *mesh, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl)
948{
949 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
950 CCGElem **gridData, **subGridData;
951 CCGKey key;
952 blender::OffsetIndices faces = mesh->faces();
953 MDisps *mdisps = static_cast<MDisps *>(
954 CustomData_get_layer_for_write(&mesh->corner_data, CD_MDISPS, mesh->corners_num));
955 GridPaintMask *grid_paint_mask = nullptr;
956 int *gridOffset;
957 int i, gridSize, dGridSize, dSkip;
958 int totloop, faces_num;
959
960 /* this happens in the dm made by bmesh_mdisps_space_set */
961 if (dm2 && CustomData_has_layer(&dm2->loopData, CD_MDISPS)) {
963 blender::Span(dm2->getPolyArray(dm2), dm2->getNumPolys(dm2) + 1));
964 mdisps = static_cast<MDisps *>(
966 totloop = dm2->numLoopData;
967 faces_num = dm2->numPolyData;
968 }
969 else {
970 totloop = mesh->corners_num;
971 faces_num = mesh->faces_num;
972 }
973
974 if (!mdisps) {
975 if (op == CALC_DISPLACEMENTS) {
976 mdisps = static_cast<MDisps *>(
977 CustomData_add_layer(&mesh->corner_data, CD_MDISPS, CD_SET_DEFAULT, mesh->corners_num));
978 }
979 else {
980 return;
981 }
982 }
983
984 // numGrids = dm->getNumGrids(dm); /* UNUSED */
985 gridSize = dm->getGridSize(dm);
986 gridData = dm->getGridData(dm);
987 gridOffset = dm->getGridOffset(dm);
988 dm->getGridKey(dm, &key);
989 subGridData = (oldGridData) ? oldGridData : gridData;
990
991 dGridSize = multires_side_tot[totlvl];
992 dSkip = (dGridSize - 1) / (gridSize - 1);
993
994 /* multires paint masks */
995 if (key.has_mask) {
996 grid_paint_mask = static_cast<GridPaintMask *>(
997 CustomData_get_layer_for_write(&mesh->corner_data, CD_GRID_PAINT_MASK, mesh->corners_num));
998 }
999
1000 /* when adding new faces in edit mode, need to allocate disps */
1001 for (i = 0; i < totloop; i++) {
1002 if (mdisps[i].disps == nullptr) {
1003 multires_reallocate_mdisps(totloop, mdisps, totlvl);
1004 break;
1005 }
1006 }
1007
1008 TaskParallelSettings settings;
1010 settings.min_iter_per_thread = CCG_TASK_LIMIT;
1011
1012 MultiresThreadedData data{};
1013 data.op = op;
1014 data.gridData = gridData;
1015 data.subGridData = subGridData;
1016 data.key = &key;
1017 data.faces = faces;
1018 data.mdisps = mdisps;
1019 data.grid_paint_mask = grid_paint_mask;
1020 data.gridOffset = gridOffset;
1021 data.gridSize = gridSize;
1022 data.dGridSize = dGridSize;
1023 data.dSkip = dSkip;
1024
1025 BLI_task_parallel_range(0, faces_num, &data, multires_disp_run_cb, &settings);
1026
1027 if (op == APPLY_DISPLACEMENTS) {
1028 ccgSubSurf_stitchFaces(ccgdm->ss, 0, nullptr, 0);
1029 ccgSubSurf_updateNormals(ccgdm->ss, nullptr, 0);
1030 }
1031}
1032
1034{
1035 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1036 Object *ob;
1037 Mesh *mesh;
1038 const MDisps *mdisps;
1040
1041 ob = ccgdm->multires.ob;
1042 mesh = static_cast<Mesh *>(ccgdm->multires.ob->data);
1043 mmd = ccgdm->multires.mmd;
1044 multires_set_tot_mdisps(mesh, mmd->totlvl);
1046 mdisps = static_cast<const MDisps *>(CustomData_get_layer(&mesh->corner_data, CD_MDISPS));
1047
1048 if (mdisps) {
1049 int lvl = ccgdm->multires.lvl;
1050 int totlvl = ccgdm->multires.totlvl;
1051
1052 if (lvl < totlvl) {
1053 DerivedMesh *lowdm, *cddm, *highdm;
1054 CCGElem **highGridData, **lowGridData, **subGridData, **gridData, *diffGrid;
1055 CCGKey highGridKey, lowGridKey;
1056 CCGSubSurf *ss;
1057 int i, j, numGrids, highGridSize, lowGridSize;
1058 const bool has_mask = CustomData_has_layer(&mesh->corner_data, CD_GRID_PAINT_MASK);
1059
1060 /* Create subsurf DM from original mesh at high level. */
1061 /* TODO: use mesh_deform_eval when sculpting on deformed mesh. */
1062 cddm = CDDM_from_mesh(mesh);
1064
1065 highdm = subsurf_dm_create_local(scene,
1066 ob,
1067 cddm,
1068 totlvl,
1069 false,
1070 false,
1072 has_mask,
1073 false,
1075 ss = ((CCGDerivedMesh *)highdm)->ss;
1076
1077 /* create multires DM from original mesh and displacements */
1079 scene, ob, cddm, lvl, totlvl, has_mask, MULTIRES_IGNORE_SIMPLIFY);
1080 cddm->release(cddm);
1081
1082 /* gather grid data */
1083 numGrids = highdm->getNumGrids(highdm);
1084 highGridSize = highdm->getGridSize(highdm);
1085 highGridData = highdm->getGridData(highdm);
1086 highdm->getGridKey(highdm, &highGridKey);
1087 lowGridSize = lowdm->getGridSize(lowdm);
1088 lowGridData = lowdm->getGridData(lowdm);
1089 lowdm->getGridKey(lowdm, &lowGridKey);
1090 gridData = dm->getGridData(dm);
1091
1092 BLI_assert(highGridKey.elem_size == lowGridKey.elem_size);
1093
1094 subGridData = static_cast<CCGElem **>(
1095 MEM_calloc_arrayN(numGrids, sizeof(CCGElem *), "subGridData*"));
1096 diffGrid = static_cast<CCGElem *>(
1097 MEM_calloc_arrayN(lowGridKey.elem_size, lowGridSize * lowGridSize, "diff"));
1098
1099 for (i = 0; i < numGrids; i++) {
1100 /* backup subsurf grids */
1101 subGridData[i] = static_cast<CCGElem *>(
1102 MEM_calloc_arrayN(highGridKey.elem_size, highGridSize * highGridSize, "subGridData"));
1103 memcpy(
1104 subGridData[i], highGridData[i], highGridKey.elem_size * highGridSize * highGridSize);
1105
1106 /* write difference of subsurf and displaced low level into high subsurf */
1107 for (j = 0; j < lowGridSize * lowGridSize; j++) {
1108 sub_v4_v4v4(CCG_elem_offset_co(lowGridKey, diffGrid, j),
1109 CCG_elem_offset_co(lowGridKey, gridData[i], j),
1110 CCG_elem_offset_co(lowGridKey, lowGridData[i], j));
1111 }
1112
1113 multires_copy_dm_grid(highGridData[i], diffGrid, &highGridKey, &lowGridKey);
1114 }
1115
1116 /* lower level dm no longer needed at this point */
1117 MEM_freeN(diffGrid);
1118 lowdm->release(lowdm);
1119
1120 /* subsurf higher levels again with difference of coordinates */
1121 ccgSubSurf_updateFromFaces(ss, lvl, nullptr, 0);
1122 ccgSubSurf_updateLevels(ss, lvl, nullptr, 0);
1123
1124 /* add to displacements */
1126 highdm, mesh, nullptr, ADD_DISPLACEMENTS, subGridData, mmd->totlvl);
1127
1128 /* free */
1129 highdm->release(highdm);
1130 for (i = 0; i < numGrids; i++) {
1131 MEM_freeN(subGridData[i]);
1132 }
1133 MEM_freeN(subGridData);
1134 }
1135 else {
1136 DerivedMesh *cddm, *subdm;
1137 const bool has_mask = CustomData_has_layer(&mesh->corner_data, CD_GRID_PAINT_MASK);
1138
1139 /* TODO: use mesh_deform_eval when sculpting on deformed mesh. */
1140 cddm = CDDM_from_mesh(mesh);
1142
1143 subdm = subsurf_dm_create_local(scene,
1144 ob,
1145 cddm,
1146 mmd->totlvl,
1147 false,
1148 false,
1150 has_mask,
1151 false,
1153 cddm->release(cddm);
1154
1156 dm, mesh, nullptr, CALC_DISPLACEMENTS, subdm->getGridData(subdm), mmd->totlvl);
1157
1158 subdm->release(subdm);
1159 }
1160 }
1161}
1162
1164{
1165 CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
1166 BLI_bitmap **grid_hidden = ccgdm->gridHidden;
1167 Mesh *mesh = static_cast<Mesh *>(ccgdm->multires.ob->data);
1168 MDisps *mdisps = static_cast<MDisps *>(
1169 CustomData_get_layer_for_write(&mesh->corner_data, CD_MDISPS, mesh->corners_num));
1170 int totlvl = ccgdm->multires.totlvl;
1171 int lvl = ccgdm->multires.lvl;
1172
1173 if (mdisps) {
1174 int i;
1175
1176 for (i = 0; i < mesh->corners_num; i++) {
1177 MDisps *md = &mdisps[i];
1178 BLI_bitmap *gh = grid_hidden[i];
1179
1180 if (!gh && md->hidden) {
1181 MEM_freeN(md->hidden);
1182 md->hidden = nullptr;
1183 }
1184 else if (gh) {
1185 gh = multires_mdisps_upsample_hidden(gh, lvl, totlvl, md->hidden);
1186 if (md->hidden) {
1187 MEM_freeN(md->hidden);
1188 }
1189
1190 md->hidden = gh;
1191 }
1192 }
1193 }
1194}
1195
1197{
1198 using namespace blender;
1199 if (ob == nullptr) {
1200 return;
1201 }
1202 SculptSession *sculpt_session = ob->sculpt;
1203 if (sculpt_session == nullptr) {
1204 return;
1205 }
1206 SubdivCCG *subdiv_ccg = sculpt_session->subdiv_ccg;
1207 if (subdiv_ccg == nullptr) {
1208 return;
1209 }
1210 BLI_assert(bke::object::pbvh_get(*ob) &&
1211 bke::object::pbvh_get(*ob)->type() == blender::bke::pbvh::Type::Grids);
1212 BKE_subdiv_ccg_average_stitch_faces(*subdiv_ccg, IndexMask(subdiv_ccg->faces.size()));
1213}
1214
1216 DerivedMesh *dm, MultiresModifierData *mmd, Scene *scene, Object *ob, MultiresFlags flags)
1217{
1218 Mesh *mesh = static_cast<Mesh *>(ob->data);
1220 CCGDerivedMesh *ccgdm = nullptr;
1221 CCGElem **gridData, **subGridData;
1222 CCGKey key;
1223 const bool render = (flags & MULTIRES_USE_RENDER_PARAMS) != 0;
1224 const bool ignore_simplify = (flags & MULTIRES_IGNORE_SIMPLIFY) != 0;
1225 int lvl = multires_get_level(scene, ob, mmd, render, ignore_simplify);
1226 int i, gridSize, numGrids;
1227
1228 if (lvl == 0) {
1229 return dm;
1230 }
1231
1232 const SubsurfFlags subsurf_flags = ignore_simplify ? SUBSURF_IGNORE_SIMPLIFY : SubsurfFlags(0);
1233
1234 result = subsurf_dm_create_local(scene,
1235 ob,
1236 dm,
1237 lvl,
1238 false,
1242 render,
1243 subsurf_flags);
1244
1245 if (!(flags & MULTIRES_USE_LOCAL_MMD)) {
1246 ccgdm = (CCGDerivedMesh *)result;
1247
1248 ccgdm->multires.ob = ob;
1249 ccgdm->multires.mmd = mmd;
1250 ccgdm->multires.local_mmd = 0;
1251 ccgdm->multires.lvl = lvl;
1252 ccgdm->multires.totlvl = mmd->totlvl;
1254 }
1255
1256 numGrids = result->getNumGrids(result);
1257 gridSize = result->getGridSize(result);
1258 gridData = result->getGridData(result);
1259 result->getGridKey(result, &key);
1260
1261 subGridData = static_cast<CCGElem **>(
1262 MEM_malloc_arrayN(numGrids, sizeof(CCGElem *), "subGridData*"));
1263
1264 for (i = 0; i < numGrids; i++) {
1265 subGridData[i] = static_cast<CCGElem *>(
1266 MEM_malloc_arrayN(key.elem_size, gridSize * gridSize, "subGridData"));
1267 memcpy(subGridData[i], gridData[i], key.elem_size * gridSize * gridSize);
1268 }
1269
1270 multires_set_tot_mdisps(mesh, mmd->totlvl);
1272
1273 /* Run displacement. */
1275 result, static_cast<Mesh *>(ob->data), dm, APPLY_DISPLACEMENTS, subGridData, mmd->totlvl);
1276
1277 /* copy hidden elements for this level */
1278 if (ccgdm) {
1279 multires_output_hidden_to_ccgdm(ccgdm, mesh, lvl);
1280 }
1281
1282 for (i = 0; i < numGrids; i++) {
1283 MEM_freeN(subGridData[i]);
1284 }
1285 MEM_freeN(subGridData);
1286
1287 return result;
1288}
1289
1290void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v)
1291{
1292 int x, y, x2, y2;
1293 const int st_max = st - 1;
1294 float urat, vrat, uopp;
1295 float d[4][3], d2[2][3];
1296
1297 if (!disps || isnan(u) || isnan(v)) {
1298 return;
1299 }
1300
1301 if (u < 0) {
1302 u = 0;
1303 }
1304 else if (u >= st) {
1305 u = st_max;
1306 }
1307 if (v < 0) {
1308 v = 0;
1309 }
1310 else if (v >= st) {
1311 v = st_max;
1312 }
1313
1314 x = floor(u);
1315 y = floor(v);
1316 x2 = x + 1;
1317 y2 = y + 1;
1318
1319 if (x2 >= st) {
1320 x2 = st_max;
1321 }
1322 if (y2 >= st) {
1323 y2 = st_max;
1324 }
1325
1326 urat = u - x;
1327 vrat = v - y;
1328 uopp = 1 - urat;
1329
1330 mul_v3_v3fl(d[0], disps[y * st + x], uopp);
1331 mul_v3_v3fl(d[1], disps[y * st + x2], urat);
1332 mul_v3_v3fl(d[2], disps[y2 * st + x], uopp);
1333 mul_v3_v3fl(d[3], disps[y2 * st + x2], urat);
1334
1335 add_v3_v3v3(d2[0], d[0], d[1]);
1336 add_v3_v3v3(d2[1], d[2], d[3]);
1337 mul_v3_fl(d2[0], 1 - vrat);
1338 mul_v3_fl(d2[1], vrat);
1339
1340 add_v3_v3v3(out, d2[0], d2[1]);
1341}
1342
1344 const MultiresModifierData *mmd_src,
1345 MultiresModifierData *mmd_dst)
1346{
1347 if (mmd_src->totlvl == mmd_dst->totlvl) {
1348 return;
1349 }
1350
1351 if (mmd_src->totlvl > mmd_dst->totlvl) {
1353 ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_CATMULL_CLARK);
1354 }
1355 else {
1356 multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl);
1357 }
1358}
1359
1360static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
1361{
1362 MultiresModifierData *mmd_src = get_multires_modifier(scene, ob_src, true);
1363 MultiresModifierData *mmd_dst = get_multires_modifier(scene, ob_dst, true);
1364
1365 if (!mmd_src) {
1366 /* NOTE(@sergey): object could have MDISP even when there is no multires modifier
1367 * this could lead to troubles due to I've got no idea how mdisp could be
1368 * up-sampled correct without modifier data. Just remove mdisps if no multires present. */
1369 multires_customdata_delete(static_cast<Mesh *>(ob_src->data));
1370 }
1371
1372 if (mmd_src && mmd_dst) {
1373 multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst);
1374 }
1375}
1376
1377static void multires_apply_uniform_scale(Object *object, const float scale)
1378{
1379 Mesh *mesh = (Mesh *)object->data;
1380 MDisps *mdisps = static_cast<MDisps *>(
1381 CustomData_get_layer_for_write(&mesh->corner_data, CD_MDISPS, mesh->corners_num));
1382 for (int i = 0; i < mesh->corners_num; i++) {
1383 MDisps *grid = &mdisps[i];
1384 for (int j = 0; j < grid->totdisp; j++) {
1385 mul_v3_fl(grid->disps[j], scale);
1386 }
1387 }
1388}
1389
1390static void multires_apply_smat(Depsgraph * /*depsgraph*/,
1391 Scene *scene,
1392 Object *object,
1393 const float smat[3][3])
1394{
1395 const MultiresModifierData *mmd = get_multires_modifier(scene, object, true);
1396 if (mmd == nullptr || mmd->totlvl == 0) {
1397 return;
1398 }
1399 /* Make sure layer present. */
1400 Mesh *mesh = (Mesh *)object->data;
1402 if (!CustomData_get_layer(&mesh->corner_data, CD_MDISPS)) {
1403 return;
1404 }
1405 if (is_uniform_scaled_m3(smat)) {
1406 const float scale = mat3_to_scale(smat);
1407 multires_apply_uniform_scale(object, scale);
1408 }
1409 else {
1410 /* TODO(@sergey): This branch of code actually requires more work to
1411 * preserve all the details. */
1412 const float scale = mat3_to_scale(smat);
1413 multires_apply_uniform_scale(object, scale);
1414 }
1415}
1416
1418{
1419 int lvl = 13;
1420
1421 while (lvl > 0) {
1422 int side = (1 << (lvl - 1)) + 1;
1423 if ((s->totdisp % (side * side)) == 0) {
1424 return s->totdisp / (side * side);
1425 }
1426 lvl--;
1427 }
1428
1429 return 0;
1430}
1431
1433{
1434 float smat[3][3];
1435
1436 /* object's scale matrix */
1437 BKE_object_scale_to_mat3(ob, smat);
1438
1439 multires_apply_smat(depsgraph, scene, ob, smat);
1440}
1441
1442void multiresModifier_prepare_join(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *to_ob)
1443{
1444 float smat[3][3], tmat[3][3], mat[3][3];
1445 multires_sync_levels(scene, to_ob, ob);
1446
1447 /* construct scale matrix for displacement */
1448 BKE_object_scale_to_mat3(to_ob, tmat);
1449 invert_m3(tmat);
1450 BKE_object_scale_to_mat3(ob, smat);
1451 mul_m3_m3m3(mat, smat, tmat);
1452
1453 multires_apply_smat(depsgraph, scene, ob, mat);
1454}
1455
1457{
1458 MDisps *mdisp = nullptr, *cur = nullptr;
1459 int i, grid = 0;
1460
1461 CustomData_external_read(&mesh->corner_data, &mesh->id, CD_MASK_MDISPS, mesh->corners_num);
1462 mdisp = static_cast<MDisps *>(
1463 CustomData_get_layer_for_write(&mesh->corner_data, CD_MDISPS, mesh->corners_num));
1464
1465 if (!mdisp) {
1466 return;
1467 }
1468
1469 cur = mdisp;
1470 for (i = 0; i < mesh->corners_num; i++, cur++) {
1471 if (cur->totdisp) {
1472 grid = mdisp->totdisp;
1473
1474 break;
1475 }
1476 }
1477
1478 for (i = 0; i < mesh->corners_num; i++, mdisp++) {
1479 /* allocate memory for mdisp, the whole disp layer would be erased otherwise */
1480 if (!mdisp->totdisp || !mdisp->disps) {
1481 if (grid) {
1482 mdisp->totdisp = grid;
1483 mdisp->disps = static_cast<float(*)[3]>(
1484 MEM_calloc_arrayN(mdisp->totdisp, sizeof(float[3]), "mdisp topology"));
1485 }
1486
1487 continue;
1488 }
1489 }
1490}
1491
1492void multires_ensure_external_read(Mesh *mesh, int top_level)
1493{
1494 if (!CustomData_external_test(&mesh->corner_data, CD_MDISPS)) {
1495 return;
1496 }
1497
1498 /* Modify the data array from the original mesh, not the evaluated mesh.
1499 * When multiple objects share the same mesh, this can lead to memory leaks. */
1500 MDisps *mdisps = const_cast<MDisps *>(
1501 static_cast<const MDisps *>(CustomData_get_layer(&mesh->corner_data, CD_MDISPS)));
1502 if (mdisps == nullptr) {
1503 mdisps = static_cast<MDisps *>(
1504 CustomData_add_layer(&mesh->corner_data, CD_MDISPS, CD_SET_DEFAULT, mesh->corners_num));
1505 }
1506
1507 const int totloop = mesh->corners_num;
1508
1509 for (int i = 0; i < totloop; ++i) {
1510 if (mdisps[i].level != top_level) {
1511 MEM_SAFE_FREE(mdisps[i].disps);
1512 }
1513
1514 /* NOTE: CustomData_external_read will take care of allocation of displacement vectors if
1515 * they are missing. */
1516
1517 const int totdisp = multires_grid_tot[top_level];
1518 mdisps[i].totdisp = totdisp;
1519 mdisps[i].level = top_level;
1520 }
1521
1522 CustomData_external_read(&mesh->corner_data, &mesh->id, CD_MASK_MDISPS, mesh->corners_num);
1523}
1528
1529/***************** Multires interpolation stuff *****************/
1530
1532 const int face_size, const int face_side, const float u, const float v, float *x, float *y)
1533{
1534 const float offset = face_side * 0.5f - 0.5f;
1535 int S = 0;
1536
1537 if (face_size == 4) {
1538 if (u <= offset && v <= offset) {
1539 S = 0;
1540 }
1541 else if (u > offset && v <= offset) {
1542 S = 1;
1543 }
1544 else if (u > offset && v > offset) {
1545 S = 2;
1546 }
1547 else if (u <= offset && v >= offset) {
1548 S = 3;
1549 }
1550
1551 if (S == 0) {
1552 *y = offset - u;
1553 *x = offset - v;
1554 }
1555 else if (S == 1) {
1556 *x = u - offset;
1557 *y = offset - v;
1558 }
1559 else if (S == 2) {
1560 *y = u - offset;
1561 *x = v - offset;
1562 }
1563 else if (S == 3) {
1564 *x = offset - u;
1565 *y = v - offset;
1566 }
1567 }
1568 else if (face_size == 3) {
1569 int grid_size = offset;
1570 float w = (face_side - 1) - u - v;
1571 float W1, W2;
1572
1573 if (u >= v && u >= w) {
1574 S = 0;
1575 W1 = w;
1576 W2 = v;
1577 }
1578 else if (v >= u && v >= w) {
1579 S = 1;
1580 W1 = u;
1581 W2 = w;
1582 }
1583 else {
1584 S = 2;
1585 W1 = v;
1586 W2 = u;
1587 }
1588
1589 W1 /= (face_side - 1);
1590 W2 /= (face_side - 1);
1591
1592 *x = (1 - (2 * W1) / (1 - W2)) * grid_size;
1593 *y = (1 - (2 * W2) / (1 - W1)) * grid_size;
1594 }
1595 else {
1596 /* the complicated ngon case: find the actual coordinate from
1597 * the barycentric coordinates and finally find the closest vertex
1598 * should work reliably for convex cases only but better than nothing */
1599
1600#if 0
1601 int minS, i;
1602 float mindist = FLT_MAX;
1603
1604 for (i = 0; i < poly->totloop; i++) {
1605 float len = len_v3v3(nullptr, positions[corner_verts[poly->loopstart + i]]);
1606 if (len < mindist) {
1607 mindist = len;
1608 minS = i;
1609 }
1610 }
1611 S = minS;
1612#endif
1613 /* temp not implemented yet and also not working properly in current master.
1614 * (was worked around by subdividing once) */
1615 S = 0;
1616 *x = 0;
1617 *y = 0;
1618 }
1619
1620 return S;
1621}
blender::float3 & CCG_grid_elem_no(const CCGKey &key, CCGElem *elem, int x, int y)
Definition BKE_ccg.hh:93
blender::float3 & CCG_grid_elem_co(const CCGKey &key, CCGElem *elem, int x, int y)
Definition BKE_ccg.hh:88
blender::float3 & CCG_elem_offset_co(const CCGKey &key, CCGElem *elem, int offset)
Definition BKE_ccg.hh:103
float & CCG_grid_elem_mask(const CCGKey &key, CCGElem *elem, int x, int y)
Definition BKE_ccg.hh:98
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)
bool CustomData_free_layer_active(CustomData *data, eCustomDataType type, 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)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
Mesh * BKE_mesh_from_object(Object *ob)
DerivedMesh * CDDM_from_mesh(Mesh *mesh)
void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data)
ModifierApplyFlag
@ MOD_APPLY_USECACHE
@ MOD_APPLY_RENDER
@ MOD_APPLY_IGNORE_SIMPLIFY
void BKE_modifier_deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
void multiresModifier_subdivide_to_level(Object *object, MultiresModifierData *mmd, int top_level, eMultiresSubdivideModeType mode)
MultiresFlags
@ MULTIRES_USE_RENDER_PARAMS
@ MULTIRES_ALLOC_PAINT_MASK
@ MULTIRES_USE_LOCAL_MMD
@ MULTIRES_IGNORE_SIMPLIFY
bool multiresModifier_reshapeFromCCG(int tot_level, Mesh *coarse_mesh, SubdivCCG *subdiv_ccg)
@ MULTIRES_SUBDIVIDE_CATMULL_CLARK
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:1966
void BKE_sculptsession_free_pbvh(Object &object)
Definition paint.cc:2099
A BVH for high poly meshes.
int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
Definition scene.cc:2700
void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG &subdiv_ccg, const blender::IndexMask &face_mask)
int BKE_ccg_gridsize(int level)
Definition CCGSubSurf.cc:25
MultiresModifiedFlags
@ MULTIRES_HIDDEN_MODIFIED
@ MULTIRES_COORDS_MODIFIED
SubsurfFlags
@ SUBSURF_IN_EDIT_MODE
@ SUBSURF_ALLOC_PAINT_MASK
@ SUBSURF_USE_RENDER_PARAMS
@ SUBSURF_IGNORE_SIMPLIFY
DerivedMesh * subsurf_make_derived_from_derived(DerivedMesh *dm, SubsurfModifierData *smd, const Scene *scene, float(*vertCos)[3], SubsurfFlags flags)
int BKE_ccg_factor(int low_level, int high_level)
Definition CCGSubSurf.cc:30
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:41
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:65
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition BLI_bitmap.h:103
unsigned int BLI_bitmap
Definition BLI_bitmap.h:17
#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_v3_m3v3(float r[3], const float M[3][3], const float a[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 float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[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)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE void sub_v4_v4v4(float r[4], const float a[4], const float b[4])
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:230
CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF)
#define CCG_TASK_LIMIT
Definition CCGSubSurf.h:62
CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
@ DAG_EVAL_RENDER
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ CD_GRID_PAINT_MASK
#define CD_MASK_MDISPS
@ ME_SIMPLE_SUBSURF
@ eMultiresModifierFlag_ControlEdges
@ eModifierMode_Render
@ eModifierMode_Realtime
@ eModifierType_Multires
@ eSubsurfModifierFlag_ControlEdges
@ SUBSURF_UV_SMOOTH_NONE
@ SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES
@ OB_MODE_EDIT
@ 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)
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
const Depsgraph * depsgraph
int len
draw_view in_light_buf[] float
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:43
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static char faces[256]
static BLI_bitmap * multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, int lo_level, int hi_level, const BLI_bitmap *prev_hidden)
Definition multires.cc:89
static void multires_copy_grid(float(*gridA)[3], float(*gridB)[3], int sizeA, int sizeB)
Definition multires.cc:567
void multires_topology_changed(Mesh *mesh)
Definition multires.cc:1456
void multires_force_external_reload(Object *object)
Definition multires.cc:463
static void multires_set_tot_mdisps(Mesh *mesh, int lvl)
Definition multires.cc:529
void multires_customdata_delete(Mesh *mesh)
Definition multires.cc:64
static void grid_tangent(const CCGKey &key, int x, int y, int axis, CCGElem *grid, float t[3])
Definition multires.cc:791
static void grid_tangent_matrix(float mat[3][3], const CCGKey &key, int x, int y, CCGElem *grid)
Definition multires.cc:824
static const int multires_grid_tot[]
Definition multires.cc:47
static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level)
Definition multires.cc:621
void multiresModifier_prepare_join(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *to_ob)
Definition multires.cc:1442
blender::Array< blender::float3 > BKE_multires_create_deformed_base_mesh_vert_coords(Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
Definition multires.cc:244
static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
Definition multires.cc:1360
void multires_modifier_update_mdisps(DerivedMesh *dm, Scene *scene)
Definition multires.cc:1033
MultiresModifierData * find_multires_modifier_before(Scene *scene, ModifierData *lastmd)
Definition multires.cc:289
static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
Definition multires.cc:641
void multiresModifier_del_levels(MultiresModifierData *mmd, Scene *scene, Object *ob, int direction)
Definition multires.cc:704
static void multires_ccg_mark_as_modified(SubdivCCG *subdiv_ccg, MultiresModifiedFlags flags)
Definition multires.cc:363
static void multires_apply_smat(Depsgraph *, Scene *scene, Object *object, const float smat[3][3])
Definition multires.cc:1390
static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *mesh, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl)
Definition multires.cc:946
static void multires_mdisps_subdivide_hidden(MDisps *md, int new_level)
Definition multires.cc:206
static BLI_bitmap * multires_mdisps_downsample_hidden(const BLI_bitmap *old_hidden, int old_level, int new_level)
Definition multires.cc:156
MultiresModifierData * get_multires_modifier(Scene *scene, Object *ob, bool use_first)
Definition multires.cc:304
void multires_flush_sculpt_updates(Object *object)
Definition multires.cc:394
static DerivedMesh * subsurf_dm_create_local(Scene *scene, Object *ob, DerivedMesh *dm, int lvl, bool is_simple, bool is_optimal, bool is_plain_uv, bool alloc_paint_mask, bool for_render, SubsurfFlags flags)
Definition multires.cc:750
Mesh * BKE_multires_create_mesh(Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
Definition multires.cc:224
void multiresModifier_scale_disp(Depsgraph *depsgraph, Scene *scene, Object *ob)
Definition multires.cc:1432
void old_mdisps_bilinear(float out[3], float(*disps)[3], const int st, float u, float v)
Definition multires.cc:1290
void multiresModifier_sync_levels_ex(Object *ob_dst, const MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst)
Definition multires.cc:1343
static const int multires_side_tot[]
Definition multires.cc:49
static void multires_output_hidden_to_ccgdm(CCGDerivedMesh *ccgdm, Mesh *mesh, int level)
Definition multires.cc:180
DispOp
Definition multires.cc:53
@ APPLY_DISPLACEMENTS
Definition multires.cc:54
@ CALC_DISPLACEMENTS
Definition multires.cc:55
@ ADD_DISPLACEMENTS
Definition multires.cc:56
static int get_levels_from_disps(Object *ob)
Definition multires.cc:472
void multires_stitch_grids(Object *ob)
Definition multires.cc:1196
DerivedMesh * multires_make_derived_from_derived(DerivedMesh *dm, MultiresModifierData *mmd, Scene *scene, Object *ob, MultiresFlags flags)
Definition multires.cc:1215
static void multires_apply_uniform_scale(Object *object, const float scale)
Definition multires.cc:1377
int mdisp_rot_face_to_crn(const int face_size, const int face_side, const float u, const float v, float *x, float *y)
Definition multires.cc:1531
void multires_ensure_external_read(Mesh *mesh, int top_level)
Definition multires.cc:1492
void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresModifiedFlags flags)
Definition multires.cc:373
void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
Definition multires.cc:509
static void multires_disp_run_cb(void *__restrict userdata, const int pidx, const TaskParallelTLS *__restrict)
Definition multires.cc:848
static DerivedMesh * multires_dm_create_local(Scene *scene, Object *ob, DerivedMesh *dm, int lvl, int totlvl, bool alloc_paint_mask, MultiresFlags flags)
Definition multires.cc:727
int multires_mdisp_corners(const MDisps *s)
Definition multires.cc:1417
void multires_force_sculpt_rebuild(Object *object)
Definition multires.cc:451
void multires_modifier_update_hidden(DerivedMesh *dm)
Definition multires.cc:1163
void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl)
Definition multires.cc:351
static void multires_copy_dm_grid(CCGElem *gridA, CCGElem *gridB, CCGKey *keyA, CCGKey *keyB)
Definition multires.cc:591
void multiresModifier_ensure_external_read(Mesh *mesh, const MultiresModifierData *mmd)
Definition multires.cc:1524
static void multires_reallocate_mdisps(int totloop, MDisps *mdisps, int lvl)
Definition multires.cc:543
int multires_get_level(const Scene *scene, const Object *ob, const MultiresModifierData *mmd, bool render, bool ignore_simplify)
Definition multires.cc:331
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
Mesh * mesh_get_eval_deform(Depsgraph *depsgraph, const Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
#define FLT_MAX
Definition stdcycles.h:14
MultiresModifierData * mmd
MultiresModifiedFlags modified_flags
unsigned int ** gridHidden
DerivedMesh dm
CCGSubSurf * ss
struct CCGDerivedMesh::@69 multires
int has_mask
Definition BKE_ccg.hh:48
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
int level
Definition BKE_ccg.hh:26
int elem_size
Definition BKE_ccg.hh:30
int(* getGridSize)(DerivedMesh *dm)
int *(* getPolyArray)(DerivedMesh *dm)
int(* getNumPolys)(DerivedMesh *dm)
int(* getNumGrids)(DerivedMesh *dm)
int *(* getGridOffset)(DerivedMesh *dm)
CCGElem **(* getGridData)(DerivedMesh *dm)
void(* release)(DerivedMesh *dm)
void(* getGridKey)(DerivedMesh *dm, CCGKey *key)
int(* getNumLoops)(DerivedMesh *dm)
float(* disps)[3]
unsigned int * hidden
struct ModifierData * next
struct ModifierData * prev
ModifierApplyFlag flag
ModifierTypeType type
Mesh *(* modify_mesh)(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
GridPaintMask * grid_paint_mask
Definition multires.cc:842
CCGElem ** subGridData
Definition multires.cc:837
blender::OffsetIndices< int > faces
Definition multires.cc:840
CCGElem ** gridData
Definition multires.cc:837
ObjectRuntimeHandle * runtime
ListBase modifiers
struct SculptSession * sculpt
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
struct SculptSession::@48 multires
MultiresModifierData * modifier
Definition BKE_paint.hh:383
struct SubdivCCG::@64 dirty
blender::OffsetIndices< int > faces