[Bf-blender-cvs] [9bf3e0299b1] blender2.8: Subdiv: CCG, initial grids stitching implementation

Sergey Sharybin noreply at git.blender.org
Tue Sep 18 17:50:40 CEST 2018


Commit: 9bf3e0299b18d65cf0da77a7a0a8a907055a3328
Author: Sergey Sharybin
Date:   Tue Sep 18 17:09:08 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB9bf3e0299b18d65cf0da77a7a0a8a907055a3328

Subdiv: CCG, initial grids stitching implementation

Currently is only working on an "inner" grid boundaries.
Need to implement averaging across face edges.

===================================================================

M	source/blender/blenkernel/BKE_subdiv_ccg.h
M	source/blender/blenkernel/intern/multires.c
M	source/blender/blenkernel/intern/paint.c
M	source/blender/blenkernel/intern/subdiv_ccg.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index ed5ef0e19f5..99037a25a64 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -55,6 +55,18 @@ typedef struct SubdivToCCGSettings {
 	bool need_mask;
 } SubdivToCCGSettings;
 
+/* This is actually a coarse face, which consists of multiple CCG grids. */
+typedef struct SubdivCCGFace {
+	/* Total number of grids in this face.
+	 *
+	 * This 1:1 corresponds to a number of corners (or loops) from a coarse
+	 * face.
+	 */
+	int num_grids;
+	/* Index of first grid from this face in SubdivCCG->grids array. */
+	int start_grid_index;
+} SubdivCCGFace;
+
 /* Representation of subdivision surface which uses CCG grids. */
 typedef struct SubdivCCG {
 	/* This is a subdivision surface this CCG was created for.
@@ -104,6 +116,12 @@ typedef struct SubdivCCG {
 	int normal_offset;
 	int mask_offset;
 
+	/* Faces from which grids are emitted. */
+	int num_faces;
+	SubdivCCGFace *faces;
+	/* Indexed by grid index, points to corresponding face from `faces`. */
+	SubdivCCGFace **grid_faces;
+
 	struct DMFlagMat *grid_flag_mats;
 	BLI_bitmap **grid_hidden;
 
@@ -161,4 +179,7 @@ void BKE_subdiv_ccg_key_top_level(
 /* Recalculate all normals based on grid element coordinates. */
 void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg);
 
+/* Average grid coordinates and normals along the grid boundatries. */
+void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg);
+
 #endif  /* __BKE_SUBDIV_CCG_H__ */
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 4dd64e3d8b2..e8b1a5faa67 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -1338,20 +1338,29 @@ void multires_modifier_update_hidden(DerivedMesh *dm)
 
 void multires_stitch_grids(Object *ob)
 {
-	/* utility for smooth brush */
-	if (ob && ob->derivedFinal) {
-		CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)ob->derivedFinal;
-		CCGFace **faces;
-		int totface;
-
-		if (ccgdm->pbvh) {
-			BKE_pbvh_get_grid_updates(ccgdm->pbvh, false, (void ***)&faces, &totface);
-
-			if (totface) {
-				ccgSubSurf_stitchFaces(ccgdm->ss, 0, faces, totface);
-				MEM_freeN(faces);
-			}
-		}
+	if (ob == NULL) {
+		return;
+	}
+	SculptSession *sculpt_session = ob->sculpt;
+	if (sculpt_session == NULL) {
+		return;
+	}
+	PBVH *pbvh = sculpt_session->pbvh;
+	SubdivCCG *subdiv_ccg = sculpt_session->subdiv_ccg;
+	if (pbvh == NULL || subdiv_ccg == NULL) {
+		return;
+	}
+	BLI_assert(BKE_pbvh_type(pbvh) == PBVH_GRIDS);
+	/* NOTE: Currently CCG does not keep track of faces, making it impossible
+	 * to use BKE_pbvh_get_grid_updates().
+	 */
+	CCGFace **faces;
+	int num_faces;
+	BKE_pbvh_get_grid_updates(pbvh, false, (void ***)&faces, &num_faces);
+	if (num_faces) {
+		/* TODO(sergey): Only aveerage actually affected faces. */
+		BKE_subdiv_ccg_average_grids(subdiv_ccg);
+		MEM_freeN(faces);
 	}
 }
 
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 926ef6a7a54..d843ae5173f 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1197,7 +1197,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
 	        pbvh,
 	        subdiv_ccg->grids, subdiv_ccg->num_grids,
 	        &key,
-	        NULL,
+	        (void **)subdiv_ccg->grid_faces,
 	        subdiv_ccg->grid_flag_mats,
 	        subdiv_ccg->grid_hidden);
 	pbvh_show_diffuse_color_set(pbvh, ob->sculpt->show_diffuse_color);
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index d9c0c721cd5..c6554203cf8 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -44,6 +44,8 @@
 #include "BKE_subdiv.h"
 #include "BKE_subdiv_eval.h"
 
+#include "opensubdiv_topology_refiner_capi.h"
+
 /* =============================================================================
  * Generally useful internal helpers.
  */
@@ -122,6 +124,7 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg,
 {
 	const int element_size = element_size_bytes_get(subdiv_ccg);
 	/* Allocate memory for surface grids. */
+	const int num_faces = coarse_mesh->totpoly;
 	const int num_grids = coarse_mesh->totloop;
 	const int grid_size = grid_size_for_level_get(
 	        subdiv_ccg, subdiv_ccg->level);
@@ -149,6 +152,14 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg,
 		        BLI_BITMAP_NEW(grid_area, "ccg grid hidden");
 	}
 	/* TOOD(sergey): Allocate memory for loose elements. */
+	/* Allocate memory for faces. */
+	subdiv_ccg->num_faces = num_faces;
+	if (num_faces) {
+		subdiv_ccg->faces = MEM_calloc_arrayN(
+		        num_faces, sizeof(SubdivCCGFace), "Subdiv CCG faces");
+		subdiv_ccg->grid_faces = MEM_calloc_arrayN(
+		        num_grids, sizeof(SubdivCCGFace*), "Subdiv CCG grid faces");
+	}
 }
 
 /* =============================================================================
@@ -219,9 +230,11 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data,
 	const int grid_size = subdiv_ccg->grid_size;
 	const float grid_size_1_inv = 1.0f / (float)(grid_size - 1);
 	const int element_size = element_size_bytes_get(subdiv_ccg);
+	SubdivCCGFace *faces = subdiv_ccg->faces;
+	SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces;
 	for (int corner = 0; corner < coarse_poly->totloop; corner++) {
-		unsigned char *grid = (unsigned char *)subdiv_ccg->grids[
-		        coarse_poly->loopstart + corner];
+		const int grid_index = coarse_poly->loopstart + corner;
+		unsigned char *grid = (unsigned char *)subdiv_ccg->grids[grid_index];
 		for (int y = 0; y < grid_size; y++) {
 			const float grid_v = (float)y * grid_size_1_inv;
 			for (int x = 0; x < grid_size; x++) {
@@ -237,6 +250,8 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data,
 				        &grid[grid_element_offset]);
 			}
 		}
+		/* Assign grid's face. */
+		grid_faces[grid_index] = &faces[coarse_poly_index];
 	}
 }
 
@@ -248,9 +263,11 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data,
 	const int grid_size = subdiv_ccg->grid_size;
 	const float grid_size_1_inv = 1.0f / (float)(grid_size - 1);
 	const int element_size = element_size_bytes_get(subdiv_ccg);
+	SubdivCCGFace *faces = subdiv_ccg->faces;
+	SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces;
 	for (int corner = 0; corner < coarse_poly->totloop; corner++) {
-		unsigned char *grid = (unsigned char *)subdiv_ccg->grids[
-		        coarse_poly->loopstart + corner];
+		const int grid_index = coarse_poly->loopstart + 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++) {
@@ -266,6 +283,8 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data,
 				        &grid[grid_element_offset]);
 			}
 		}
+		/* Assign grid's face. */
+		grid_faces[grid_index] = &faces[coarse_poly_index];
 	}
 }
 
@@ -275,6 +294,7 @@ static void subdiv_ccg_eval_grids_task(
         const ParallelRangeTLS *__restrict UNUSED(tls))
 {
 	CCGEvalGridsData *data = userdata_v;
+	SubdivCCG *subdiv_ccg = data->subdiv_ccg;
 	const Mesh *coarse_mesh = data->coarse_mesh;
 	const MPoly *coarse_mpoly = coarse_mesh->mpoly;
 	const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
@@ -284,6 +304,10 @@ static void subdiv_ccg_eval_grids_task(
 	else {
 		subdiv_ccg_eval_special_grid(data, coarse_poly);
 	}
+	/* Assign information in the faces. */
+	subdiv_ccg->faces[coarse_poly_index].num_grids = coarse_poly->totloop;
+	subdiv_ccg->faces[coarse_poly_index].start_grid_index =
+	        coarse_poly->loopstart;
 }
 
 static bool subdiv_ccg_evaluate_grids(
@@ -330,6 +354,7 @@ SubdivCCG *BKE_subdiv_to_ccg(
 {
 	BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_CCG);
 	SubdivCCG *subdiv_ccg = MEM_callocN(sizeof(SubdivCCG), "subdiv ccg");
+	subdiv_ccg->subdiv = subdiv;
 	subdiv_ccg->level = bitscan_forward_i(settings->resolution - 1);
 	subdiv_ccg->grid_size =
 	        grid_size_for_level_get(subdiv_ccg, subdiv_ccg->level);
@@ -341,7 +366,6 @@ SubdivCCG *BKE_subdiv_to_ccg(
 		return NULL;
 	}
 	BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_CCG);
-	subdiv_ccg->subdiv = subdiv;
 	return subdiv_ccg;
 }
 
@@ -378,6 +402,7 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg)
 	if (subdiv_ccg->subdiv != NULL) {
 		BKE_subdiv_free(subdiv_ccg->subdiv);
 	}
+	MEM_SAFE_FREE(subdiv_ccg->faces);
 	MEM_freeN(subdiv_ccg);
 }
 
@@ -528,7 +553,8 @@ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG *subdiv_ccg)
 	BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
 	RecalcInnerNormalsData data = {
 	        .subdiv_ccg = subdiv_ccg,
-	        .key = &key};
+	        .key = &key
+	};
 	RecalcInnerNormalsTLSData tls_data = {NULL};
 	ParallelRangeSettings parallel_range_settings;
 	BLI_parallel_range_settings_defaults(&parallel_range_settings);
@@ -549,4 +575,76 @@ void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg)
 		return;
 	}
 	subdiv_ccg_recalc_inner_grid_normals(subdiv_ccg);
+	BKE_subdiv_ccg_average_grids(subdiv_ccg);
+}
+
+/* =============================================================================
+ * Boundary averaging/stitching.
+ */
+
+typedef struct AverageInnerGridsData {
+	SubdivCCG *subdiv_ccg;
+	CCGKey *key;
+} AverageInnerGridsData;
+
+static void average_grid_element_value_v3(float a[3], float b[3])
+{
+	add_v3_v3(a, b);
+	mul_v3_fl(a, 0.5f);
+	copy_v3_v3(b, a);
+}
+
+static void average_grid_element(SubdivCCG *subdiv_ccg,
+                                 CCGKey *key,
+                                 CCGElem *grid_element_a,
+                                 CCGElem *grid_element_b)
+{
+	average_grid_element_value_v3(CCG_elem_co(key, grid_element_a),
+	                              CCG_elem_co(key, grid_element_b));
+	if (subdiv_ccg->has_normal) {
+		average_grid_element_value_v3(CCG_elem_no(key, grid_element_a),
+		                              CCG_elem_no(key, grid_element_b));
+	}
+}
+
+stat

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list