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