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_subdiv.h5
-rw-r--r--source/blender/blenkernel/BKE_subdiv_ccg.h40
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c148
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg_mask.c15
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg_material.c67
-rw-r--r--source/blender/draw/modes/sculpt_mode.c19
7 files changed, 262 insertions, 33 deletions
diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h
index 4fddb3d5188..1ade8a0e44d 100644
--- a/source/blender/blenkernel/BKE_subdiv.h
+++ b/source/blender/blenkernel/BKE_subdiv.h
@@ -145,8 +145,7 @@ typedef struct SubdivDisplacement {
typedef struct Subdiv {
/* Settings this subdivision surface is created for.
*
- * It is read-only after assignment in BKE_subdiv_new_from_FOO().
- */
+ * It is read-only after assignment in BKE_subdiv_new_from_FOO(). */
SubdivSettings settings;
/* Topology refiner includes all the glue logic to feed Blender side
* topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
@@ -162,7 +161,7 @@ typedef struct Subdiv {
/* Cached values, are not supposed to be accessed directly. */
struct {
/* Indexed by base face index, element indicates total number of ptex
- *faces created for preceding base faces. */
+ * faces created for preceding base faces. */
int *face_ptex_offset;
} cache_;
} Subdiv;
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index 804a5d0b500..822f4906bae 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -25,6 +25,7 @@
#define __BKE_SUBDIV_CCG_H__
#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
#include "BLI_bitmap.h"
#include "BLI_sys_types.h"
@@ -40,20 +41,41 @@ struct Subdiv;
*/
/* Functor which evaluates mask value at a given (u, v) of given ptex face. */
-typedef struct SubdivCCGMask {
- float (*eval_mask)(struct SubdivCCGMask *mask,
+typedef struct SubdivCCGMaskEvaluator {
+ float (*eval_mask)(struct SubdivCCGMaskEvaluator *mask_evaluator,
const int ptex_face_index,
const float u, const float v);
/* Free the data, not the evaluator itself. */
- void (*free)(struct SubdivCCGMask *mask);
+ void (*free)(struct SubdivCCGMaskEvaluator *mask_evaluator);
void *user_data;
-} SubdivCCGMask;
+} SubdivCCGMaskEvaluator;
/* Return true if mesh has mask and evaluator can be used. */
bool BKE_subdiv_ccg_mask_init_from_paint(
- SubdivCCGMask *mask_evaluator,
+ SubdivCCGMaskEvaluator *mask_evaluator,
+ const struct Mesh *mesh);
+
+/* =============================================================================
+ * Materials.
+ */
+
+/* Functor which evaluates material and flags of a given coarse face. */
+typedef struct SubdivCCGMaterialFlagsEvaluator {
+ DMFlagMat (*eval_material_flags)(
+ struct SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator,
+ const int coarse_face_index);
+
+ /* Free the data, not the evaluator itself. */
+ void (*free)(
+ struct SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator);
+
+ void *user_data;
+} SubdivCCGMaterialFlagsEvaluator;
+
+void BKE_subdiv_ccg_material_flags_init_from_mesh(
+ SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator,
const struct Mesh *mesh);
/* =============================================================================
@@ -196,7 +218,8 @@ typedef struct SubdivCCG {
struct SubdivCCG *BKE_subdiv_to_ccg(
struct Subdiv *subdiv,
const SubdivToCCGSettings *settings,
- SubdivCCGMask *mask_evaluator);
+ SubdivCCGMaskEvaluator *mask_evaluator,
+ SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator);
/* Destroy CCG representation of subdivision surface. */
void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg);
@@ -218,6 +241,11 @@ void BKE_subdiv_ccg_key_top_level(
/* Recalculate all normals based on grid element coordinates. */
void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg);
+/* Update normals of affected faces. */
+void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg,
+ struct CCGFace **effected_faces,
+ int num_effected_faces);
+
/* Average grid coordinates and normals along the grid boundatries. */
void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index b30acbcae24..e3afbc507bf 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -194,6 +194,7 @@ set(SRC
intern/subdiv.c
intern/subdiv_ccg.c
intern/subdiv_ccg_mask.c
+ intern/subdiv_ccg_material.c
intern/subdiv_converter.c
intern/subdiv_converter_mesh.c
intern/subdiv_displacement.c
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index bfcd4b8d52d..c35b38b4184 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -41,6 +41,19 @@
#include "opensubdiv_topology_refiner_capi.h"
/* =============================================================================
+ * Various forward declarations.
+ */
+
+static void subdiv_ccg_average_all_boundaries_and_corners(
+ SubdivCCG *subdiv_ccg,
+ CCGKey *key);
+
+static void subdiv_ccg_average_inner_face_grids(
+ SubdivCCG *subdiv_ccg,
+ CCGKey *key,
+ SubdivCCGFace *face);
+
+/* =============================================================================
* Generally useful internal helpers.
*/
@@ -163,7 +176,8 @@ typedef struct CCGEvalGridsData {
SubdivCCG *subdiv_ccg;
Subdiv *subdiv;
int *face_ptex_offset;
- SubdivCCGMask *mask_evaluator;
+ SubdivCCGMaskEvaluator *mask_evaluator;
+ SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator;
} CCGEvalGridsData;
static void subdiv_ccg_eval_grid_element(
@@ -232,6 +246,10 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data,
}
/* Assign grid's face. */
grid_faces[grid_index] = &faces[face_index];
+ /* Assign material flags. */
+ subdiv_ccg->grid_flag_mats[grid_index] =
+ data->material_flags_evaluator->eval_material_flags(
+ data->material_flags_evaluator, face_index);
}
}
@@ -247,13 +265,13 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data,
const SubdivCCGFace *face = &faces[face_index];
for (int corner = 0; corner < face->num_grids; corner++) {
const int grid_index = face->start_grid_index + corner;
+ const int ptex_face_index =
+ data->face_ptex_offset[face_index] + corner;
unsigned char *grid = (unsigned char *)subdiv_ccg->grids[grid_index];
for (int y = 0; y < grid_size; y++) {
const float u = 1.0f - ((float)y * grid_size_1_inv);
for (int x = 0; x < grid_size; x++) {
const float v = 1.0f - ((float)x * grid_size_1_inv);
- const int ptex_face_index =
- data->face_ptex_offset[face_index] + corner;
const size_t grid_element_index = (size_t)y * grid_size + x;
const size_t grid_element_offset =
grid_element_index * element_size;
@@ -265,6 +283,10 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data,
}
/* Assign grid's face. */
grid_faces[grid_index] = &faces[face_index];
+ /* Assign material flags. */
+ subdiv_ccg->grid_flag_mats[grid_index] =
+ data->material_flags_evaluator->eval_material_flags(
+ data->material_flags_evaluator, face_index);
}
}
@@ -287,7 +309,8 @@ static void subdiv_ccg_eval_grids_task(
static bool subdiv_ccg_evaluate_grids(
SubdivCCG *subdiv_ccg,
Subdiv *subdiv,
- SubdivCCGMask *mask_evaluator)
+ SubdivCCGMaskEvaluator *mask_evaluator,
+ SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator)
{
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
const int num_faces = topology_refiner->getNumFaces(topology_refiner);
@@ -297,6 +320,7 @@ static bool subdiv_ccg_evaluate_grids(
data.subdiv = subdiv;
data.face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
data.mask_evaluator = mask_evaluator;
+ data.material_flags_evaluator = material_flags_evaluator;
/* Threaded grids evaluation. */
ParallelRangeSettings parallel_range_settings;
BLI_parallel_range_settings_defaults(&parallel_range_settings);
@@ -591,7 +615,8 @@ static void subdiv_ccg_init_faces_neighborhood(SubdivCCG *subdiv_ccg)
SubdivCCG *BKE_subdiv_to_ccg(
Subdiv *subdiv,
const SubdivToCCGSettings *settings,
- SubdivCCGMask *mask_evaluator)
+ SubdivCCGMaskEvaluator *mask_evaluator,
+ SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator)
{
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_CCG);
SubdivCCG *subdiv_ccg = MEM_callocN(sizeof(SubdivCCG), "subdiv ccg");
@@ -602,7 +627,8 @@ SubdivCCG *BKE_subdiv_to_ccg(
subdiv_ccg_alloc_elements(subdiv_ccg, subdiv);
subdiv_ccg_init_faces(subdiv_ccg);
subdiv_ccg_init_faces_neighborhood(subdiv_ccg);
- if (!subdiv_ccg_evaluate_grids(subdiv_ccg, subdiv, mask_evaluator)) {
+ if (!subdiv_ccg_evaluate_grids(
+ subdiv_ccg, subdiv, mask_evaluator, material_flags_evaluator)) {
BKE_subdiv_ccg_destroy(subdiv_ccg);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_CCG);
return NULL;
@@ -624,11 +650,17 @@ Mesh *BKE_subdiv_to_ccg_mesh(
}
}
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_CCG);
- SubdivCCGMask mask_evaluator;
+ SubdivCCGMaskEvaluator mask_evaluator;
bool has_mask = BKE_subdiv_ccg_mask_init_from_paint(
- &mask_evaluator, coarse_mesh);
+ &mask_evaluator, coarse_mesh);
+ SubdivCCGMaterialFlagsEvaluator material_flags_evaluator;
+ BKE_subdiv_ccg_material_flags_init_from_mesh(
+ &material_flags_evaluator, coarse_mesh);
SubdivCCG *subdiv_ccg = BKE_subdiv_to_ccg(
- subdiv, settings, has_mask ? &mask_evaluator : NULL);
+ subdiv,
+ settings,
+ has_mask ? &mask_evaluator : NULL,
+ &material_flags_evaluator);
if (has_mask) {
mask_evaluator.free(&mask_evaluator);
}
@@ -723,12 +755,11 @@ typedef struct RecalcInnerNormalsTLSData {
*
* The result is stored in normals storage from TLS. */
static void subdiv_ccg_recalc_inner_face_normals(
- RecalcInnerNormalsData *data,
+ SubdivCCG *subdiv_ccg,
+ CCGKey *key,
RecalcInnerNormalsTLSData *tls,
const int grid_index)
{
- SubdivCCG *subdiv_ccg = data->subdiv_ccg;
- CCGKey *key = data->key;
const int grid_size = subdiv_ccg->grid_size;
const int grid_size_1 = grid_size - 1;
CCGElem *grid = subdiv_ccg->grids[grid_index];
@@ -761,12 +792,11 @@ static void subdiv_ccg_recalc_inner_face_normals(
/* Average normals at every grid element, using adjacent faces normals. */
static void subdiv_ccg_average_inner_face_normals(
- RecalcInnerNormalsData *data,
+ SubdivCCG *subdiv_ccg,
+ CCGKey *key,
RecalcInnerNormalsTLSData *tls,
const int grid_index)
{
- SubdivCCG *subdiv_ccg = data->subdiv_ccg;
- CCGKey *key = data->key;
const int grid_size = subdiv_ccg->grid_size;
const int grid_size_1 = grid_size - 1;
CCGElem *grid = subdiv_ccg->grids[grid_index];
@@ -811,8 +841,10 @@ static void subdiv_ccg_recalc_inner_normal_task(
{
RecalcInnerNormalsData *data = userdata_v;
RecalcInnerNormalsTLSData *tls = tls_v->userdata_chunk;
- subdiv_ccg_recalc_inner_face_normals(data, tls, grid_index);
- subdiv_ccg_average_inner_face_normals(data, tls, grid_index);
+ subdiv_ccg_recalc_inner_face_normals(
+ data->subdiv_ccg, data->key, tls, grid_index);
+ subdiv_ccg_average_inner_face_normals(
+ data->subdiv_ccg, data->key, tls, grid_index);
}
static void subdiv_ccg_recalc_inner_normal_finalize(
@@ -855,6 +887,88 @@ void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg)
BKE_subdiv_ccg_average_grids(subdiv_ccg);
}
+typedef struct RecalcModifiedInnerNormalsData {
+ SubdivCCG *subdiv_ccg;
+ CCGKey *key;
+ SubdivCCGFace **effected_ccg_faces;
+} RecalcModifiedInnerNormalsData;
+
+static void subdiv_ccg_recalc_modified_inner_normal_task(
+ void *__restrict userdata_v,
+ const int face_index,
+ const ParallelRangeTLS *__restrict tls_v)
+{
+ RecalcModifiedInnerNormalsData *data = userdata_v;
+ SubdivCCG *subdiv_ccg = data->subdiv_ccg;
+ CCGKey *key = data->key;
+ RecalcInnerNormalsTLSData *tls = tls_v->userdata_chunk;
+ SubdivCCGFace **faces = data->effected_ccg_faces;
+ SubdivCCGFace *face = faces[face_index];
+ const int num_face_grids = face->num_grids;
+ for (int i = 0; i < num_face_grids; i++) {
+ const int grid_index = face->start_grid_index + i;
+ subdiv_ccg_recalc_inner_face_normals(
+ data->subdiv_ccg, data->key, tls, grid_index);
+ subdiv_ccg_average_inner_face_normals(
+ data->subdiv_ccg, data->key, tls, grid_index);
+ }
+ subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face);
+}
+
+static void subdiv_ccg_recalc_modified_inner_normal_finalize(
+ void *__restrict UNUSED(userdata),
+ void *__restrict tls_v)
+{
+ RecalcInnerNormalsTLSData *tls = tls_v;
+ MEM_SAFE_FREE(tls->face_normals);
+}
+
+static void subdiv_ccg_recalc_modified_inner_grid_normals(
+ SubdivCCG *subdiv_ccg,
+ struct CCGFace **effected_faces,
+ int num_effected_faces)
+{
+ CCGKey key;
+ BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
+ RecalcModifiedInnerNormalsData data = {
+ .subdiv_ccg = subdiv_ccg,
+ .key = &key,
+ .effected_ccg_faces = (SubdivCCGFace **)effected_faces,
+ };
+ RecalcInnerNormalsTLSData tls_data = {NULL};
+ ParallelRangeSettings parallel_range_settings;
+ BLI_parallel_range_settings_defaults(&parallel_range_settings);
+ parallel_range_settings.userdata_chunk = &tls_data;
+ parallel_range_settings.userdata_chunk_size = sizeof(tls_data);
+ parallel_range_settings.func_finalize =
+ subdiv_ccg_recalc_modified_inner_normal_finalize;
+ BLI_task_parallel_range(0, num_effected_faces,
+ &data,
+ subdiv_ccg_recalc_modified_inner_normal_task,
+ &parallel_range_settings);
+}
+
+void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg,
+ struct CCGFace **effected_faces,
+ int num_effected_faces)
+{
+ if (!subdiv_ccg->has_normal) {
+ /* Grids don't have normals, can do early output. */
+ return;
+ }
+ if (num_effected_faces == 0) {
+ /* No faces changed, so nothing to do here. */
+ return;
+ }
+ subdiv_ccg_recalc_modified_inner_grid_normals(
+ subdiv_ccg, effected_faces, num_effected_faces);
+ /* TODO(sergey): Only average elements which are adjacent to modified
+ * faces. */
+ CCGKey key;
+ BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
+ subdiv_ccg_average_all_boundaries_and_corners(subdiv_ccg, &key);
+}
+
/* =============================================================================
* Boundary averaging/stitching.
*/
diff --git a/source/blender/blenkernel/intern/subdiv_ccg_mask.c b/source/blender/blenkernel/intern/subdiv_ccg_mask.c
index e90d5df3774..ec9dfd30f16 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg_mask.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg_mask.c
@@ -54,7 +54,7 @@ typedef struct GridPaintMaskData {
} GridPaintMaskData;
static int mask_get_grid_and_coord(
- SubdivCCGMask *mask_evaluator,
+ SubdivCCGMaskEvaluator *mask_evaluator,
const int ptex_face_index, const float u, const float v,
const GridPaintMask **r_mask_grid,
float *grid_u, float *grid_v)
@@ -92,7 +92,7 @@ BLI_INLINE float read_mask_grid(const GridPaintMask *mask_grid,
return mask_grid->data[y * grid_size + x];
}
-static float eval_mask(SubdivCCGMask *mask_evaluator,
+static float eval_mask(SubdivCCGMaskEvaluator *mask_evaluator,
const int ptex_face_index,
const float u, const float v)
{
@@ -105,7 +105,7 @@ static float eval_mask(SubdivCCGMask *mask_evaluator,
return read_mask_grid(mask_grid, grid_u, grid_v);
}
-static void free_mask_data(SubdivCCGMask *mask_evaluator)
+static void free_mask_data(SubdivCCGMaskEvaluator *mask_evaluator)
{
GridPaintMaskData *data = mask_evaluator->user_data;
MEM_freeN(data->ptex_poly_corner);
@@ -126,7 +126,7 @@ static int count_num_ptex_faces(const Mesh *mesh)
return num_ptex_faces;
}
-static void mask_data_init_mapping(SubdivCCGMask *mask_evaluator,
+static void mask_data_init_mapping(SubdivCCGMaskEvaluator *mask_evaluator,
const Mesh *mesh)
{
GridPaintMaskData *data = mask_evaluator->user_data;
@@ -156,7 +156,8 @@ static void mask_data_init_mapping(SubdivCCGMask *mask_evaluator,
}
}
-static void mask_init_data(SubdivCCGMask *mask_evaluator, const Mesh *mesh)
+static void mask_init_data(SubdivCCGMaskEvaluator *mask_evaluator,
+ const Mesh *mesh)
{
GridPaintMaskData *data = mask_evaluator->user_data;
data->mpoly = mesh->mpoly;
@@ -165,14 +166,14 @@ static void mask_init_data(SubdivCCGMask *mask_evaluator, const Mesh *mesh)
mask_data_init_mapping(mask_evaluator, mesh);
}
-static void mask_init_functions(SubdivCCGMask *mask_evaluator)
+static void mask_init_functions(SubdivCCGMaskEvaluator *mask_evaluator)
{
mask_evaluator->eval_mask = eval_mask;
mask_evaluator->free = free_mask_data;
}
bool BKE_subdiv_ccg_mask_init_from_paint(
- SubdivCCGMask *mask_evaluator,
+ SubdivCCGMaskEvaluator *mask_evaluator,
const struct Mesh *mesh)
{
GridPaintMask *grid_paint_mask =
diff --git a/source/blender/blenkernel/intern/subdiv_ccg_material.c b/source/blender/blenkernel/intern/subdiv_ccg_material.c
new file mode 100644
index 00000000000..0dc86095cff
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv_ccg_material.c
@@ -0,0 +1,67 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2018 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BKE_subdiv_ccg.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+
+typedef struct CCGMaterialFromMeshData {
+ const Mesh *mesh;
+} CCGMaterialFromMeshData;
+
+static DMFlagMat subdiv_ccg_material_flags_eval(
+ SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator,
+ const int coarse_face_index)
+{
+ CCGMaterialFromMeshData *data =
+ (CCGMaterialFromMeshData *)material_flags_evaluator->user_data;
+ const Mesh *mesh = data->mesh;
+ BLI_assert(coarse_face_index < mesh->totpoly);
+ const MPoly *mpoly = mesh->mpoly;
+ const MPoly *poly = &mpoly[coarse_face_index];
+ DMFlagMat material_flags;
+ material_flags.flag = poly->flag;
+ material_flags.mat_nr = poly->mat_nr;
+ return material_flags;
+}
+
+static void subdiv_ccg_material_flags_free(
+ SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator)
+{
+ MEM_freeN(material_flags_evaluator->user_data);
+}
+
+void BKE_subdiv_ccg_material_flags_init_from_mesh(
+ SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator,
+ const Mesh *mesh)
+{
+ CCGMaterialFromMeshData *data = MEM_mallocN(
+ sizeof(CCGMaterialFromMeshData), "ccg material eval");
+ data->mesh = mesh;
+ material_flags_evaluator->eval_material_flags =
+ subdiv_ccg_material_flags_eval;
+ material_flags_evaluator->free = subdiv_ccg_material_flags_free;
+ material_flags_evaluator->user_data = data;
+} \ No newline at end of file
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
index 5d008a35a61..bb13cb36c01 100644
--- a/source/blender/draw/modes/sculpt_mode.c
+++ b/source/blender/draw/modes/sculpt_mode.c
@@ -29,6 +29,7 @@
#include "BKE_pbvh.h"
#include "BKE_paint.h"
+#include "BKE_subdiv_ccg.h"
/* If builtin shaders are needed */
#include "GPU_shader.h"
@@ -154,6 +155,22 @@ static void sculpt_draw_mask_cb(
}
}
+static void sculpt_update_pbvh_normals(Object *object)
+{
+ Mesh *mesh = object->data;
+ PBVH *pbvh = object->sculpt->pbvh;
+ SubdivCCG *subdiv_ccg = mesh->runtime.subdiv_ccg;
+ if (pbvh == NULL || subdiv_ccg == NULL) {
+ return;
+ }
+ struct CCGFace **faces;
+ int num_faces;
+ BKE_pbvh_get_grid_updates(pbvh, 1, (void ***)&faces, &num_faces);
+ if (num_faces > 0) {
+ BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces);
+ }
+}
+
/* Add geometry to shadingGroups. Execute for each objects */
static void SCULPT_cache_populate(void *vedata, Object *ob)
{
@@ -166,6 +183,8 @@ static void SCULPT_cache_populate(void *vedata, Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
if (ob->sculpt && (ob == draw_ctx->obact)) {
+ sculpt_update_pbvh_normals(ob);
+
/* XXX, needed for dyntopo-undo (which clears).
* probably depsgraph should handlle? in 2.7x getting derived-mesh does this (mesh_build_data) */
if (ob->sculpt->pbvh == NULL) {