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:
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.
*/