[Bf-blender-cvs] [fb6a0d2] master: Dyntopo: support for original normal access

Campbell Barton noreply at git.blender.org
Sun Apr 19 10:39:52 CEST 2015


Commit: fb6a0d24e1078574135ca1d083c2b933191d9bda
Author: Campbell Barton
Date:   Sun Apr 19 18:22:25 2015 +1000
Branches: master
https://developer.blender.org/rBfb6a0d24e1078574135ca1d083c2b933191d9bda

Dyntopo: support for original normal access

Rename calc_flatten_center to calc_area_center,
since theres no 'flatten' spesific logic there.

Also refactor calc_area_center, calc_area_normal, calc_area_normal_and_center
so they're next to eachother - they're almost the same,
having them scattered about isn't helpful.

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

M	source/blender/editors/sculpt_paint/sculpt.c

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

diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index a08ea2b..4e3d03f 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -729,6 +729,429 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
 	}
 }
 
+/** \name Calculate Normal and Center
+ *
+ * Calculate geometry surrounding the brush center.
+ * (optionally using original coordinates).
+ *
+ * Functions are:
+ * - #calc_area_center
+ * - #calc_area_normal
+ * - #calc_area_normal_and_center
+ *
+ * \note These are all _very_ similar, when changing one, check others.
+ * \{ */
+
+static void calc_area_center(
+        Sculpt *sd, Object *ob,
+        PBVHNode **nodes, int totnode,
+        float r_area_co[3])
+{
+	SculptSession *ss = ob->sculpt;
+	int n;
+
+	/* 0=towards view, 1=flipped */
+	float area_co[2][3] = {{0.0f}};
+
+	int count[2] = {0};
+
+	(void)sd; /* unused w/o openmp */
+
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
+	for (n = 0; n < totnode; n++) {
+		PBVHVertexIter vd;
+		SculptBrushTest test;
+		SculptUndoNode *unode;
+		float private_co[2][3] = {{0.0f}};
+		int   private_count[2] = {0};
+		bool use_original;
+
+		unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
+		sculpt_brush_test_init(ss, &test);
+
+		use_original = (ss->cache->original && (unode->co || unode->bm_entry));
+
+		/* when the mesh is edited we can't rely on original coords
+		 * (original mesh may not even have verts in brush radius) */
+		if (use_original && unode->bm_entry) {
+			float (*orco_coords)[3];
+			int   (*orco_tris)[3];
+			int     orco_tris_num;
+			int i;
+
+			BKE_pbvh_node_get_bm_orco_data(
+			        nodes[n],
+			        &orco_tris, &orco_tris_num, &orco_coords);
+
+			for (i = 0; i < orco_tris_num; i++) {
+				const float *co_tri[3] = {
+				    orco_coords[orco_tris[i][0]],
+				    orco_coords[orco_tris[i][1]],
+				    orco_coords[orco_tris[i][2]],
+				};
+				float co[3];
+
+				closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
+
+				if (sculpt_brush_test_fast(&test, co)) {
+					float no[3];
+					int flip_index;
+
+					cross_tri_v3(no, UNPACK3(co_tri));
+
+					flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+					add_v3_v3(private_co[flip_index], co);
+					private_count[flip_index] += 1;
+				}
+			}
+		}
+		else {
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			{
+				const float *co;
+
+				if (use_original) {
+					co = unode->co[vd.i];
+				}
+				else {
+					co = vd.co;
+				}
+
+				if (sculpt_brush_test_fast(&test, co)) {
+					float no_buf[3];
+					const float *no;
+					int flip_index;
+
+					if (use_original) {
+						normal_short_to_float_v3(no_buf, unode->no[vd.i]);
+						no = no_buf;
+					}
+					else {
+						if (vd.no) {
+							normal_short_to_float_v3(no_buf, vd.no);
+							no = no_buf;
+						}
+						else {
+							no = vd.fno;
+						}
+					}
+
+					flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+					add_v3_v3(private_co[flip_index], co);
+					private_count[flip_index] += 1;
+				}
+			}
+			BKE_pbvh_vertex_iter_end;
+		}
+
+#pragma omp critical
+		{
+			/* for flatten center */
+			add_v3_v3(area_co[0], private_co[0]);
+			add_v3_v3(area_co[1], private_co[1]);
+
+			/* weights */
+			count[0] += private_count[0];
+			count[1] += private_count[1];
+		}
+	}
+
+	/* for flatten center */
+	for (n = 0; n < ARRAY_SIZE(area_co); n++) {
+		if (count[n] != 0) {
+			mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]);
+			break;
+		}
+	}
+	if (n == 2) {
+		zero_v3(r_area_co);
+	}
+}
+
+
+static void calc_area_normal(
+        Sculpt *sd, Object *ob,
+        PBVHNode **nodes, int totnode,
+        float r_area_no[3])
+{
+	const Brush *brush = BKE_paint_brush(&sd->paint);
+	SculptSession *ss = ob->sculpt;
+	int n;
+
+	/* 0=towards view, 1=flipped */
+	float area_no[2][3] = {{0.0f}};
+
+	int count[2] = {0};
+
+	/* Grab brush requires to test on original data (see T25371) */
+	bool original;
+
+	original = (brush->sculpt_tool == SCULPT_TOOL_GRAB) ? true : ss->cache->original;
+	/* In general the original coords are not available with dynamic
+	 * topology
+	 *
+	 * Mask tool could not use undo nodes to get coordinates from
+	 * since the coordinates are not stored in those nodes.
+	 * And mask tool is not gonna to modify vertex coordinates,
+	 * so we don't actually need to use modified coords.
+	 */
+	if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
+		original = false;
+	}
+
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
+	for (n = 0; n < totnode; n++) {
+		PBVHVertexIter vd;
+		SculptBrushTest test;
+		SculptUndoNode *unode;
+		float private_no[2][3] = {{0.0f}};
+		int   private_count[2] = {0};
+		bool use_original;
+
+		unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
+		sculpt_brush_test_init(ss, &test);
+
+		use_original = (original && (unode->co || unode->bm_entry));
+
+		/* when the mesh is edited we can't rely on original coords
+		 * (original mesh may not even have verts in brush radius) */
+		if (use_original && unode->bm_entry) {
+			float (*orco_coords)[3];
+			int   (*orco_tris)[3];
+			int     orco_tris_num;
+			int i;
+
+			BKE_pbvh_node_get_bm_orco_data(
+			        nodes[n],
+			        &orco_tris, &orco_tris_num, &orco_coords);
+
+			for (i = 0; i < orco_tris_num; i++) {
+				const float *co_tri[3] = {
+				    orco_coords[orco_tris[i][0]],
+				    orco_coords[orco_tris[i][1]],
+				    orco_coords[orco_tris[i][2]],
+				};
+				float co[3];
+
+				closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
+
+				if (sculpt_brush_test_fast(&test, co)) {
+					float no[3];
+					int flip_index;
+
+					normal_tri_v3(no, UNPACK3(co_tri));
+
+					flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+					add_v3_v3(private_no[flip_index], no);
+					private_count[flip_index] += 1;
+				}
+			}
+		}
+		else {
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			{
+				const float *co;
+
+				if (use_original) {
+					co = unode->co[vd.i];
+				}
+				else {
+					co = vd.co;
+				}
+
+				if (sculpt_brush_test_fast(&test, co)) {
+					float no_buf[3];
+					const float *no;
+					int flip_index;
+
+					if (use_original) {
+						normal_short_to_float_v3(no_buf, unode->no[vd.i]);
+						no = no_buf;
+					}
+					else {
+						if (vd.no) {
+							normal_short_to_float_v3(no_buf, vd.no);
+							no = no_buf;
+						}
+						else {
+							no = vd.fno;
+						}
+					}
+
+					flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+					add_v3_v3(private_no[flip_index], no);
+					private_count[flip_index] += 1;
+				}
+			}
+			BKE_pbvh_vertex_iter_end;
+		}
+
+#pragma omp critical
+		{
+			/* for area normal */
+			add_v3_v3(area_no[0], private_no[0]);
+			add_v3_v3(area_no[1], private_no[1]);
+
+			/* weights */
+			count[0] += private_count[0];
+			count[1] += private_count[1];
+		}
+	}
+
+	/* for area normal */
+	for (n = 0; n < ARRAY_SIZE(area_no); n++) {
+		if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) {
+			break;
+		}
+	}
+}
+
+/* this calculates flatten center and area normal together,
+ * amortizing the memory bandwidth and loop overhead to calculate both at the same time */
+static void calc_area_normal_and_center(
+        Sculpt *sd, Object *ob,
+        PBVHNode **nodes, int totnode,
+        float r_area_no[3], float r_area_co[3])
+{
+	SculptSession *ss = ob->sculpt;
+	int n;
+
+	/* 0=towards view, 1=flipped */
+	float area_co[2][3] = {{0.0f}};
+	float area_no[2][3] = {{0.0f}};
+
+	int count[2] = {0};
+
+	(void)sd; /* unused w/o openmp */
+
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
+	for (n = 0; n < totnode; n++) {
+		PBVHVertexIter vd;
+		SculptBrushTest test;
+		SculptUndoNode *unode;
+		float private_co[2][3] = {{0.0f}};
+		float private_no[2][3] = {{0.0f}};
+		int   private_count[2] = {0};
+		bool use_original;
+
+		unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
+		sculpt_brush_test_init(ss, &test);
+
+		use_original = (ss->cache->original && (unode->co || unode->bm_entry));
+
+		/* when the mesh is edited we can't rely on original coords
+		 * (original mesh may not even have verts in brush radius) */
+		if (use_original && unode->bm_entry) {
+			float (*orco_coords)[3];
+			int   (*orco_tris)[3];
+			int     orco_tris_num;
+			int i;
+
+			BKE_pbvh_node_get_bm_orco_data(
+			        nodes[n],
+			        &orco_tris, &orco_tris_num, &orco_coords);
+
+			for (i = 0; i < orco_tris_num; i++) {
+				const float *co_tri[3] = {
+				    orco_coords[orco_tris[i][0]],
+				    orco_coords[orco_tris[i][1]],
+				    orco_coords[orco_tris[i][2]],
+				};
+				float co[3];
+
+				closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
+
+				if (sculpt_brush_test_fast(&test, co)) {
+					float no[3];
+					int flip_index;
+
+					normal_tri_v3(no, UNPACK3(co_tri));
+
+					flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+					add_v3_v3(private_co[flip_index], co);
+					add_v3_v3(private_no[flip_index], no);
+					private_count[flip_index] += 1;
+				}
+			}
+		}
+		else {
+			BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+			{
+				const float *co;
+
+				if (use_original) {
+					co = unode->co[vd.i];
+				}
+				else {
+					co = vd.co;
+				}
+
+				if (sculpt_brush_test_fast(&test, co)) {
+					float no_buf[3];
+					const float *no;
+					int flip_index;
+
+					if (use_original) {
+						normal_short_to_float_v3(no_buf, unode->no[vd.i]);
+						no = no_buf;
+					}
+					else {
+						if (vd.no) {
+							normal_short_to_float_v3(no_buf, vd.no);
+							no = no_buf;
+						}
+						else {
+							no = vd.fno;
+						}
+					}
+
+					flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+					add_v3_v3(private_co[flip_index], co);
+					add_v3_v3(private_no[flip_index], no);
+					private_count[flip_index] += 1;
+				}
+			}
+			BKE_pbvh_vertex_iter_end;
+		}
+
+#pragma omp critical
+		{
+			

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list