Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_multires.h5
-rw-r--r--source/blender/blenkernel/BKE_paint.h4
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h2
-rw-r--r--source/blender/blenkernel/BKE_subdiv_ccg.h11
-rw-r--r--source/blender/blenkernel/intern/multires.c42
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.c285
-rw-r--r--source/blender/blenkernel/intern/paint.c2
-rw-r--r--source/blender/blenkernel/intern/pbvh.c5
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c9
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c7
10 files changed, 310 insertions, 62 deletions
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 92755477d5e..26173643cbf 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -33,6 +33,7 @@
*/
enum MultiresModifiedFlags;
+
struct Depsgraph;
struct DerivedMesh;
struct MDisps;
@@ -42,6 +43,7 @@ struct Multires;
struct MultiresModifierData;
struct Object;
struct Scene;
+struct SubdivCCG;
struct MLoop;
struct MVert;
@@ -126,6 +128,9 @@ bool multiresModifier_reshapeFromDeformModifier(
struct MultiresModifierData *mmd,
struct Object *ob,
struct ModifierData *md);
+bool multiresModifier_reshapeFromCCG(
+ struct Object *dst,
+ struct SubdivCCG *subdiv_ccg);
/* Subdivision integration, defined in multires_subdiv.c */
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index ade23a2a9ca..d2d09609221 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -56,6 +56,7 @@ struct Scene;
struct ViewLayer;
struct Sculpt;
struct StrokeCache;
+struct SubdivCCG;
struct Tex;
struct ImagePool;
struct UnifiedPaintSettings;
@@ -198,6 +199,9 @@ typedef struct SculptSession {
/* Undo/redo log for dynamic topology sculpting */
struct BMLog *bm_log;
+ /* Limit surface/grids. */
+ struct SubdivCCG *subdiv_ccg;
+
/* PBVH acceleration structure */
struct PBVH *pbvh;
bool show_diffuse_color;
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 3838474381c..47fedb565fc 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -155,6 +155,8 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
/* multires level, only valid for type == PBVH_GRIDS */
void BKE_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
+struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh, int *num_grids);
+
/* Only valid for type == PBVH_BMESH */
struct BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index 59a31e158cc..c760fb04fd3 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -114,6 +114,17 @@ typedef struct SubdivCCG {
/* TODO(sergey): Consider adding CD layers here, so we can draw final mesh
* from grids, and have UVs and such work.
*/
+
+ /* Integration with sculpting. */
+ /* TODO(sergey): Is this really best way to go? Kind of annoying to have
+ * such use-related flags in a more or less generic structure.
+ */
+ struct {
+ /* Corresponds to MULTIRES_COORDS_MODIFIED. */
+ bool coords;
+ /* Corresponds to MULTIRES_HIDDEN_MODIFIED. */
+ bool hidden;
+ } dirty;
} SubdivCCG;
/* Create real hi-res CCG from subdivision.
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 22a335c7fd4..4dd64e3d8b2 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -57,6 +57,7 @@
#include "BKE_multires.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
+#include "BKE_subdiv_ccg.h"
#include "BKE_subsurf.h"
#include "BKE_editmesh.h"
@@ -389,21 +390,46 @@ static void multires_dm_mark_as_modified(DerivedMesh *dm, MultiresModifiedFlags
ccgdm->multires.modified_flags |= flags;
}
+static void multires_ccg_mark_as_modified(SubdivCCG *subdiv_ccg,
+ MultiresModifiedFlags flags)
+{
+ if (flags & MULTIRES_COORDS_MODIFIED) {
+ subdiv_ccg->dirty.coords = true;
+ }
+ if (flags & MULTIRES_HIDDEN_MODIFIED) {
+ subdiv_ccg->dirty.hidden = true;
+ }
+}
+
void multires_mark_as_modified(Object *ob, MultiresModifiedFlags flags)
{
- if (ob && ob->derivedFinal)
- multires_dm_mark_as_modified(ob->derivedFinal, flags);
+ if (ob == NULL) {
+ return;
+ }
+ Mesh *mesh = ob->data;
+ SubdivCCG *subdiv_ccg = mesh->runtime.subsurf_ccg;
+ if (subdiv_ccg == NULL) {
+ return;
+ }
+ multires_ccg_mark_as_modified(subdiv_ccg, flags);
}
void multires_force_update(Object *ob)
{
- if (ob) {
- BKE_object_free_derived_caches(ob);
-
- if (ob->sculpt && ob->sculpt->pbvh) {
- BKE_pbvh_free(ob->sculpt->pbvh);
- ob->sculpt->pbvh = NULL;
+ if (ob == NULL) {
+ return;
+ }
+ if (ob->sculpt && ob->sculpt->pbvh) {
+ PBVH *pbvh = ob->sculpt->pbvh;
+ if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
+ multiresModifier_reshapeFromCCG(ob, ob->sculpt->subdiv_ccg);
+ }
+ else {
+ /* NOTE: Disabled for until OpenSubdiv is enabled by default. */
+ // BLI_assert(!"multires_force_update is used on non-grids PBVH");
}
+ BKE_pbvh_free(pbvh);
+ ob->sculpt->pbvh = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index bdd871b5d37..782c7638b58 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -35,13 +35,16 @@
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_task.h"
+#include "BKE_ccg.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_subdiv.h"
+#include "BKE_subdiv_ccg.h"
#include "BKE_subdiv_eval.h"
#include "BKE_subdiv_foreach.h"
#include "BKE_subdiv_mesh.h"
@@ -126,8 +129,23 @@ BLI_INLINE void construct_tangent_matrix(float tangent_matrix[3][3],
normalize_v3(tangent_matrix[2]);
}
+static void multires_reshape_init_mmd(
+ MultiresModifierData *reshape_mmd,
+ const MultiresModifierData *mmd)
+{
+ *reshape_mmd = *mmd;
+}
+
+static void multires_reshape_init_mmd_top_level(
+ MultiresModifierData *reshape_mmd,
+ const MultiresModifierData *mmd)
+{
+ *reshape_mmd = *mmd;
+ reshape_mmd->lvl = reshape_mmd->totlvl;
+}
+
/* =============================================================================
- * Reshape internal functionality.
+ * General reshape implementaiton, reused by all particular cases.
*/
typedef struct MultiresReshapeContext {
@@ -135,25 +153,10 @@ typedef struct MultiresReshapeContext {
Object *object;
const Mesh *coarse_mesh;
MDisps *mdisps;
- const float (*deformed_verts)[3];
- int num_deformed_verts;
+ /* NOTE: This is a grid size on th top level. */
int grid_size;
} MultiresReshapeContext;
-static bool multires_reshape_topology_info(
- const SubdivForeachContext *foreach_context,
- const int num_vertices,
- const int UNUSED(num_edges),
- const int UNUSED(num_loops),
- const int UNUSED(num_polygons))
-{
- MultiresReshapeContext *ctx = foreach_context->user_data;
- if (num_vertices != ctx->num_deformed_verts) {
- return false;
- }
- return true;
-}
-
static void multires_reshape_vertex_copy_to_next(
MultiresReshapeContext *ctx,
const MPoly *coarse_poly,
@@ -238,13 +241,13 @@ static void copy_boundary_displacement(
}
}
-static void multires_reshape_vertex(
+static void multires_reshape_vertex_from_final_coord(
MultiresReshapeContext *ctx,
const int ptex_face_index,
const float u, const float v,
const int coarse_poly_index,
const int coarse_corner,
- const int subdiv_vertex_index)
+ const float final_P[3])
{
Subdiv *subdiv = ctx->subdiv;
const int grid_size = ctx->grid_size;
@@ -273,7 +276,6 @@ static void multires_reshape_vertex(
ptex_uv_to_grid_uv(u, v, &grid_u, &grid_v);
}
/* Convert object coordinate to a tangent space of displacement grid. */
- const float *final_P = ctx->deformed_verts[subdiv_vertex_index];
float D[3];
sub_v3_v3v3(D, final_P, P);
float tangent_matrix[3][3];
@@ -292,6 +294,47 @@ static void multires_reshape_vertex(
ctx, coarse_poly, face_corner, grid_x, grid_y, displacement_grid);
}
+/* =============================================================================
+ * Reshape from deformed veretx coordinates.
+ */
+
+typedef struct MultiresReshapeFromDeformedVertsContext {
+ MultiresReshapeContext reshape_ctx;
+ const float (*deformed_verts)[3];
+ int num_deformed_verts;
+} MultiresReshapeFromDeformedVertsContext;
+
+static bool multires_reshape_topology_info(
+ const SubdivForeachContext *foreach_context,
+ const int num_vertices,
+ const int UNUSED(num_edges),
+ const int UNUSED(num_loops),
+ const int UNUSED(num_polygons))
+{
+ MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
+ if (num_vertices != ctx->num_deformed_verts) {
+ return false;
+ }
+ return true;
+}
+
+static void multires_reshape_vertex(
+ MultiresReshapeFromDeformedVertsContext *ctx,
+ const int ptex_face_index,
+ const float u, const float v,
+ const int coarse_poly_index,
+ const int coarse_corner,
+ const int subdiv_vertex_index)
+{
+ const float *final_P = ctx->deformed_verts[subdiv_vertex_index];
+ multires_reshape_vertex_from_final_coord(
+ &ctx->reshape_ctx,
+ ptex_face_index, u, v,
+ coarse_poly_index,
+ coarse_corner,
+ final_P);
+}
+
static void multires_reshape_vertex_inner(
const SubdivForeachContext *foreach_context,
void *UNUSED(tls_v),
@@ -301,7 +344,7 @@ static void multires_reshape_vertex_inner(
const int coarse_corner,
const int subdiv_vertex_index)
{
- MultiresReshapeContext *ctx = foreach_context->user_data;
+ MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
multires_reshape_vertex(
ctx,
ptex_face_index, u, v,
@@ -320,7 +363,7 @@ static void multires_reshape_vertex_every_corner(
const int coarse_corner,
const int subdiv_vertex_index)
{
- MultiresReshapeContext *ctx = foreach_context->user_data;
+ MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
multires_reshape_vertex(
ctx,
ptex_face_index, u, v,
@@ -339,7 +382,7 @@ static void multires_reshape_vertex_every_edge(
const int coarse_corner,
const int subdiv_vertex_index)
{
- MultiresReshapeContext *ctx = foreach_context->user_data;
+ MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
multires_reshape_vertex(
ctx,
ptex_face_index, u, v,
@@ -376,58 +419,46 @@ static bool multires_reshape_from_vertcos(
{
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Mesh *coarse_mesh = object->data;
- MultiresReshapeContext ctx = {
- .object = object,
- .coarse_mesh = coarse_mesh,
+ MDisps *mdisps = CustomData_get_layer(&coarse_mesh->ldata, CD_MDISPS);
+ MultiresReshapeFromDeformedVertsContext reshape_deformed_verts_ctx = {
+ .reshape_ctx = {
+ .object = object,
+ .coarse_mesh = coarse_mesh,
+ .mdisps = mdisps,
+ .grid_size = (1 << (mmd->totlvl - 1)) + 1,
+ },
.deformed_verts = deformed_verts,
- .mdisps = CustomData_get_layer(&coarse_mesh->ldata, CD_MDISPS),
.num_deformed_verts = num_deformed_verts,
- .grid_size = (1 << (mmd->totlvl - 1)) + 1,
};
SubdivForeachContext foreach_context = {
.topology_info = multires_reshape_topology_info,
.vertex_inner = multires_reshape_vertex_inner,
.vertex_every_edge = multires_reshape_vertex_every_edge,
.vertex_every_corner = multires_reshape_vertex_every_corner,
- .user_data = &ctx,
+ .user_data = &reshape_deformed_verts_ctx,
};
/* Initialize subdivision surface. */
- ctx.subdiv = multires_subdiv_for_reshape(depsgraph, object, mmd);
- if (ctx.subdiv == NULL) {
+ Subdiv *subdiv = multires_subdiv_for_reshape(depsgraph, object, mmd);
+ if (subdiv == NULL) {
return false;
}
+ reshape_deformed_verts_ctx.reshape_ctx.subdiv = subdiv;
/* Initialize mesh rasterization settings. */
SubdivToMeshSettings mesh_settings;
BKE_multires_subdiv_mesh_settings_init(
&mesh_settings, scene_eval, object, mmd, use_render_params, true);
/* Run all the callbacks. */
BKE_subdiv_foreach_subdiv_geometry(
- ctx.subdiv,
+ subdiv,
&foreach_context,
&mesh_settings,
coarse_mesh);
- BKE_subdiv_free(ctx.subdiv);
+ BKE_subdiv_free(subdiv);
return true;
}
-static void multires_reshape_init_mmd(MultiresModifierData *reshape_mmd,
- const MultiresModifierData *mmd)
-{
- /* It is possible that the current subdivision level of multires is lower
- * that it's maximum possible one (i.e., viewport is set to a lower level
- * for the performance purposes). But even then, we want all the multires
- * levels to be reshaped. Most accurate way to do so is to ignore all
- * simplifications and calculate deformation modifier for the highest
- * possible multires level.
- * Alternative would be propagate displacement from current level to a
- * higher ones, but that is likely to cause artifacts.
- */
- *reshape_mmd = *mmd;
- reshape_mmd->lvl = reshape_mmd->totlvl;
-}
-
/* =============================================================================
- * Public entry points.
+ * Reshape from object.
*/
/* Returns truth on success, false otherwise.
@@ -469,6 +500,10 @@ bool multiresModifier_reshapeFromObject(
return result;
}
+/* =============================================================================
+ * Reshape from modifier.
+ */
+
bool multiresModifier_reshapeFromDeformModifier(
struct Depsgraph *depsgraph,
MultiresModifierData *mmd,
@@ -476,7 +511,16 @@ bool multiresModifier_reshapeFromDeformModifier(
ModifierData *md)
{
MultiresModifierData highest_mmd;
- multires_reshape_init_mmd(&highest_mmd, mmd);
+ /* It is possible that the current subdivision level of multires is lower
+ * that it's maximum possible one (i.e., viewport is set to a lower level
+ * for the performance purposes). But even then, we want all the multires
+ * levels to be reshaped. Most accurate way to do so is to ignore all
+ * simplifications and calculate deformation modifier for the highest
+ * possible multires level.
+ * Alternative would be propagate displacement from current level to a
+ * higher ones, but that is likely to cause artifacts.
+ */
+ multires_reshape_init_mmd_top_level(&highest_mmd, mmd);
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
/* Perform sanity checks and early output. */
if (multires_get_level(
@@ -513,3 +557,142 @@ bool multiresModifier_reshapeFromDeformModifier(
MEM_freeN(deformed_verts);
return result;
}
+
+/* =============================================================================
+ * Reshape from grids.
+ */
+
+typedef struct ReshapeFromCCGTaskData {
+ MultiresReshapeContext reshape_ctx;
+ int *face_ptex_offset;
+ const CCGKey *key;
+ /*const*/ CCGElem **grids;
+} ReshapeFromCCGTaskData;
+
+static void reshape_from_ccg_regular_face(ReshapeFromCCGTaskData *data,
+ const MPoly *coarse_poly)
+{
+ const CCGKey *key = data->key;
+ /*const*/ CCGElem **grids = data->grids;
+ const Mesh *coarse_mesh = data->reshape_ctx.coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const int grid_size = data->reshape_ctx.grid_size;
+ const int grid_size_1 = grid_size - 1;
+ const int resolution = 2 * grid_size - 1;
+ const float resolution_1_inv = 1.0f / (float)(resolution - 1);
+ const int coarse_poly_index = coarse_poly - coarse_mpoly;
+ const int ptex_face_index = data->face_ptex_offset[coarse_poly_index];
+ for (int y = 0; y < resolution; y++) {
+ const float v = y * resolution_1_inv;
+ for (int x = 0; x < resolution; x++) {
+ const float u = x * resolution_1_inv;
+ float corner_u, corner_v;
+ float grid_u, grid_v;
+ const int face_corner = rotate_quad_to_corner(
+ u, v, &corner_u, &corner_v);
+ ptex_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
+ /*const*/ CCGElem *grid =
+ grids[coarse_poly->loopstart + face_corner];
+ /*const*/ CCGElem *grid_element = CCG_grid_elem(
+ key, grid, grid_size_1 * grid_u, grid_size_1 * grid_v);
+ const float *final_P = CCG_elem_co(key, grid_element);
+ multires_reshape_vertex_from_final_coord(
+ &data->reshape_ctx,
+ ptex_face_index,
+ u, v,
+ coarse_poly_index,
+ 0,
+ final_P);
+ }
+ }
+}
+
+static void reshape_from_ccg_special_face(ReshapeFromCCGTaskData *data,
+ const MPoly *coarse_poly)
+{
+ const CCGKey *key = data->key;
+ /*const*/ CCGElem **grids = data->grids;
+ const Mesh *coarse_mesh = data->reshape_ctx.coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const int grid_size = data->reshape_ctx.grid_size;
+ const int grid_size_1 = grid_size - 1;
+ const int resolution = grid_size;
+ const float resolution_1_inv = 1.0f / (float)(resolution - 1);
+ const int coarse_poly_index = coarse_poly - coarse_mpoly;
+ const int ptex_face_index = data->face_ptex_offset[coarse_poly_index];
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ for (int y = 0; y < resolution; y++) {
+ const float v = y * resolution_1_inv;
+ for (int x = 0; x < resolution; x++) {
+ const float u = x * resolution_1_inv;
+ float grid_u, grid_v;
+ ptex_uv_to_grid_uv(u, v, &grid_u, &grid_v);
+ /*const*/ CCGElem *grid =
+ grids[coarse_poly->loopstart + corner];
+ /*const*/ CCGElem *grid_element = CCG_grid_elem(
+ key, grid, grid_size_1 * grid_u, grid_size_1 * grid_v);
+ const float *final_P = CCG_elem_co(key, grid_element);
+ multires_reshape_vertex_from_final_coord(
+ &data->reshape_ctx,
+ ptex_face_index + corner,
+ u, v,
+ coarse_poly_index,
+ corner,
+ final_P);
+ }
+ }
+ }
+}
+
+static void reshape_from_ccg_task(
+ void *__restrict userdata,
+ const int coarse_poly_index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ ReshapeFromCCGTaskData *data = userdata;
+ const Mesh *coarse_mesh = data->reshape_ctx.coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
+ if (coarse_poly->totloop == 4) {
+ reshape_from_ccg_regular_face(data, coarse_poly);
+ }
+ else {
+ reshape_from_ccg_special_face(data, coarse_poly);
+ }
+}
+
+bool multiresModifier_reshapeFromCCG(
+ Object *dst, SubdivCCG *subdiv_ccg)
+{
+ Mesh *coarse_mesh = dst->data;
+ CCGKey key;
+ BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
+ /* Sanity checks. */
+ if (coarse_mesh->totloop != subdiv_ccg->num_grids) {
+ /* Grids are supposed to eb created for each face-cornder (aka loop). */
+ return false;
+ }
+ MDisps *mdisps = CustomData_get_layer(&coarse_mesh->ldata, CD_MDISPS);
+ /* XXX: Key has grid size for the current level. Need to access top
+ * top level somehow.
+ */
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+ ReshapeFromCCGTaskData data = {
+ .reshape_ctx = {
+ .subdiv = subdiv,
+ .object = dst,
+ .coarse_mesh = coarse_mesh,
+ .mdisps = mdisps,
+ .grid_size = key.grid_size},
+ .face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv),
+ .key = &key,
+ .grids = subdiv_ccg->grids};
+ /* Threaded grids iteration. */
+ ParallelRangeSettings parallel_range_settings;
+ BLI_parallel_range_settings_defaults(&parallel_range_settings);
+ BLI_task_parallel_range(0, coarse_mesh->totpoly,
+ &data,
+ reshape_from_ccg_task,
+ &parallel_range_settings);
+ return true;
+}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 443e7b242ad..926ef6a7a54 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -943,6 +943,8 @@ void BKE_sculpt_update_mesh_elements(
ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
}
+ ss->subdiv_ccg = me_eval->runtime.subsurf_ccg;
+
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
BLI_assert(pbvh == ss->pbvh);
UNUSED_VARS_NDEBUG(pbvh);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 65fc02c71c2..640fc194731 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1341,6 +1341,11 @@ void BKE_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
*key = bvh->gridkey;
}
+struct CCGElem **BKE_pbvh_get_grids(const PBVH *bvh, int *num_grids) {
+ BLI_assert(bvh->type == PBVH_GRIDS);
+ *num_grids = bvh->totgrid;
+ return bvh->grids;
+}
BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
{
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 45037cfddfa..ccba962a6f8 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -74,6 +74,7 @@
#include "BKE_colortools.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -4868,8 +4869,12 @@ static void sculpt_flush_update(bContext *C)
ARegion *ar = CTX_wm_region(C);
MultiresModifierData *mmd = ss->multires;
- if (mmd)
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ if (mmd != NULL) {
+ /* NOTE: SubdivCCG is living in the evaluated object. */
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ multires_mark_as_modified(ob_eval, MULTIRES_COORDS_MODIFIED);
+ }
DEG_id_tag_update(&ob->id, DEG_TAG_SHADING_UPDATE);
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index ca62560caa8..813ce830b04 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -200,6 +200,7 @@ static Mesh *multires_as_ccg(MultiresModifierData *mmd,
if (ccg_settings.resolution < 3) {
return result;
}
+ BKE_subdiv_displacement_attach_from_multires(subdiv, mesh, mmd);
result = BKE_subdiv_to_ccg_mesh(subdiv, &ccg_settings, mesh);
return result;
}
@@ -226,7 +227,11 @@ static Mesh *applyModifier_subdiv(ModifierData *md,
* a wrong impression that things do work, even though crucial areas are
* still missing in implementation.
*/
- if ((ctx->object->mode & OB_MODE_SCULPT) && G.debug_value == 128) {
+ const bool for_orco = (ctx->flag & MOD_APPLY_ORCO) != 0;
+ if ((ctx->object->mode & OB_MODE_SCULPT) &&
+ G.debug_value == 128 &&
+ !for_orco)
+ {
/* NOTE: CCG takes ownership over Subdiv. */
result = multires_as_ccg(mmd, ctx, mesh, subdiv);
// BKE_subdiv_stats_print(&subdiv->stats);