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:
authorSergey Sharybin <sergey.vfx@gmail.com>2019-02-22 18:56:54 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-02-22 19:02:51 +0300
commit3b132778deaac733baa78653685471e344b6b7c8 (patch)
tree568e05c772008ef3e1d3149c55dfb0e20719d950 /source/blender/blenkernel/intern/subdiv_ccg.c
parentb6c61945aed51d86dc474df616761f9a25d71d09 (diff)
Multires: Support smooth shading when sculpting
On CCG side it is done similar to displacement, where we have a dedicated functor which evaluates displacement. Might be seemed as an overkill, but allows to decouple SubdivCCG from mesh entirely, and maybe even free up coarse mesh in order to save some memory. Some weak-looking aspect is the call to update normals from the draw manager. Ideally, the manager will only draw what is already evaluated. But it's a bit tricky to find a best place for this since we avoid dependency graph updates during sculpt as much as possible. The new code mimics the old code, this is how it was in 2.7. Fix shading part of T58307.
Diffstat (limited to 'source/blender/blenkernel/intern/subdiv_ccg.c')
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c148
1 files changed, 131 insertions, 17 deletions
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.
*/