[Bf-blender-cvs] [3ab49cae0e8] soc-2017-sculpting_improvements: First version calculating the inside and outside vertices. Needs multiple ring support. Holes from earlier misscalculations break the "floodfill" algorithm.

Sebastian Witt noreply at git.blender.org
Mon Aug 14 13:04:11 CEST 2017


Commit: 3ab49cae0e8c5e86c7e23a5a81ee322a1ef599bd
Author: Sebastian Witt
Date:   Mon Aug 14 13:01:54 2017 +0200
Branches: soc-2017-sculpting_improvements
https://developer.blender.org/rB3ab49cae0e8c5e86c7e23a5a81ee322a1ef599bd

First version calculating the inside and outside vertices. Needs multiple ring support. Holes from earlier misscalculations break the "floodfill" algorithm.

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

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/makesdna/DNA_scene_types.h

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

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 0fe8499a3e7..06c7007c9a8 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1672,6 +1672,12 @@ class VIEW3D_PT_sculpt_silhouette(Panel, View3DPaintPanel):
         col.prop(sculpt, "silhouette_smoothness", text="Smoothness", slider=True)
         col.prop(sculpt, "silhouette_depth", text="Depth")
         col.prop(sculpt, "silhouette_resolution", text="Resolution")
+        sub = col.column()
+
+        sub.row().prop(sculpt, "silhouette_add", text="Add")
+        sub.row().prop(sculpt, "silhouette_subtract", text="Subtract")
+
+        col.separator()
 
 
 class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 196300664b3..5f1e595a226 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -234,9 +234,16 @@ typedef struct IntersectionData {
 	float *intersection_points;		/* exact positions where the two shapes connect */
 	GHash *edge_hash;
 	int num_intersection_points;	/* 3 times intersection point count*/
+	int first_e;
+	bool flip;
 } IntersectionData;
 
 typedef enum {
+	SILHOUETTE_DEFAULT = 0,
+	SILHOUETTE_DO_SUBTRACT = 1
+} SilhouetteToolFlags;
+
+typedef enum {
 	SIL_INIT = 0,
 	SIL_DRAWING = 1,
 	SIL_OP = 2
@@ -259,6 +266,7 @@ typedef struct SilhouetteData {
 	float depth;					/* Depth or thickness of the generated shape */
 	float smoothness;				/* Smoothness of the generated shape */
 	int resolution;					/* Subdivision of the shape*/
+	bool do_subtract;				/* Is in subtractive mode? Clipping brush functionality */
 	float anchor[3];				/* Origin point of the reference plane */
 	float z_vec[3];					/* Orientation of the reference plane */
 	MeshElemMap *emap;				/* Original Mesh vert -> edges map */
@@ -5242,7 +5250,8 @@ static SilhouetteData *silhouette_data_new(bContext *C)
 	/*Load RNA Data if present */
 	sil->smoothness = sd->silhouette_smoothness / 100.0f;
 	sil->depth = sd->silhouette_depth;
-	sil->resolution = sd->silhouette_resolution;
+	sil->resolution = sd->silhouette_resolution;;
+	sil->do_subtract = sd->silhouette_flags & SILHOUETTE_DO_SUBTRACT;
 
 	copy_v3_v3(sil->anchor, fp);
 
@@ -5253,6 +5262,12 @@ static SilhouetteData *silhouette_data_new(bContext *C)
 	sil->fillet_ring_orig_start = NULL;
 	sil->inter_edges = NULL;
 	sil->fillet_ring_bbs = NULL;
+	sil->isect_chunk = NULL;
+	sil->fillet_ring_new = NULL;
+	sil->fillet_ring_new_start = NULL;
+	sil->inter_tris = NULL;
+	sil->tri_nodebind = NULL;
+	sil->v_to_rm = NULL;
 
 	sil->scene = scene;
 	sil->ob = obedit;
@@ -5285,6 +5300,19 @@ static void silhouette_data_free(struct wmOperator *op)
 		if (data->fillet_ring_bbs) {
 			MEM_freeN(data->fillet_ring_bbs);
 		}
+		if (data->inter_tris) {
+			MEM_freeN(data->inter_tris);
+		}
+		if (data->tri_nodebind) {
+			MEM_freeN(data->tri_nodebind);
+		}
+		if (data->v_to_rm) {
+			MEM_freeN(data->v_to_rm);
+		}
+		if (data->isect_chunk) {
+			/*TODO: Free Intersection Data first! */
+			MEM_freeN(data->isect_chunk);
+		}
 		MEM_SAFE_FREE(data);
 	}
 }
@@ -7133,6 +7161,7 @@ static IntersectionData *add_isect_chunk(SilhouetteData *sil)
 	return &sil->isect_chunk[sil->num_isect_data - 1];
 }
 
+#if 0
 static void prep_float_shared_mem(float **mem, int *r_num, int *r_start, int len, const char *str)
 {
 	if (!mem) {
@@ -7145,6 +7174,7 @@ static void prep_float_shared_mem(float **mem, int *r_num, int *r_start, int len
 		*mem = MEM_reallocN(*mem, sizeof(float) * (*r_num));
 	}
 }
+#endif
 
 static void prep_int_shared_mem(int **mem, int *r_num, int *r_start, int len, const char *str)
 {
@@ -7159,6 +7189,18 @@ static void prep_int_shared_mem(int **mem, int *r_num, int *r_start, int len, co
 	}
 }
 
+/*TODO: Maybe add real normal calc */
+static bool shared_dir_normal(float e1[3], float e2[3], float v1[3], float v2[3], float v3[3])
+{
+	float d1[3], d2[3], n[3], e[3];
+	sub_v3_v3v3(d1, v2, v1);
+	sub_v3_v3v3(d2, v3, v1);
+	sub_v3_v3v3(e, e2, e1);
+	cross_v3_v3v3(n, d1, d2);
+
+	return dot_v3v3(n, e) > 0;
+}
+
 static void do_calc_sil_intersect_task_cb_ex(void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
 {
 	SculptThreadedTaskData *data = userdata;
@@ -7179,7 +7221,8 @@ static void do_calc_sil_intersect_task_cb_ex(void *userdata, void *UNUSED(userda
 	BKE_pbvh_get_tri(bvh, &ltris);
 	GHash *edge_hash = BLI_ghash_int_new("edges within intersection");
 	float *int_points = NULL;
-	int int_points_shared_start;
+	bool first_e_flip;
+	int first_e;
 	IntersectionData *i_data;
 	BLI_array_declare(int_points);
 
@@ -7199,19 +7242,24 @@ static void do_calc_sil_intersect_task_cb_ex(void *userdata, void *UNUSED(userda
 					copy_v3_v3(p2, me->mvert[me->medge[e_start + e].v2].co);
 					for (int tri_i = 0; tri_i < tri_node_bind_tot; tri_i ++) {
 						lt = ltris[sil->inter_tris[tri_node_bind + tri_i]];
+						/* Maybe isect with epsilon flexibility needed? */
 						if (isect_line_segment_tri_v3(p1, p2,
 													  me->mvert[me->mloop[lt.tri[0]].v].co, me->mvert[me->mloop[lt.tri[1]].v].co, me->mvert[me->mloop[lt.tri[2]].v].co,
 													  &t_lambda, NULL))
 						{
+							if (BLI_array_count(int_points) == 0) {
+								first_e_flip = shared_dir_normal(p1, p2, me->mvert[me->mloop[lt.tri[0]].v].co, me->mvert[me->mloop[lt.tri[1]].v].co, me->mvert[me->mloop[lt.tri[2]].v].co);
+								first_e = e_start + e;
+							}
 							BLI_ghash_insert(edge_hash, SET_INT_IN_POINTER(e_start + e), SET_INT_IN_POINTER(BLI_array_count(int_points)));
 							BLI_array_grow_items(int_points, 3);
 							interp_v3_v3v3(&int_points[BLI_array_count(int_points) - 3], p1, p2, t_lambda);
 #ifdef DEBUG_DRAW
-							/*bl_debug_color_set(0x0000ff);
+							bl_debug_color_set(0x0000ff);
 							bl_debug_draw_point(&int_points[BLI_array_count(int_points) - 3], 0.05f);
 							bl_debug_color_set(0x000000);
 							bl_debug_draw_edge_add(p1, p2);
-							bl_debug_color_set(0x000000);*/
+							bl_debug_color_set(0x000000);
 #endif
 							break;
 						}
@@ -7221,6 +7269,8 @@ static void do_calc_sil_intersect_task_cb_ex(void *userdata, void *UNUSED(userda
 			BLI_mutex_lock(&data->mutex);
 			if (BLI_array_count(int_points) > 0) {
 				i_data = add_isect_chunk(sil);
+				i_data->flip = first_e_flip;
+				i_data->first_e = first_e;
 				i_data->edge_hash = edge_hash;
 				i_data->intersection_points = MEM_callocN(sizeof(float) * BLI_array_count(int_points), "exact intersecting points");
 				i_data->num_intersection_points = BLI_array_count(int_points);
@@ -7263,32 +7313,59 @@ static void check_preceding_intersecting_edges(Object *ob, SilhouetteData *sil,
 #endif
 }
 
+static void crawl_mesh_rec (Mesh *me, MeshElemMap *emap, GHash *vert_hash, IntersectionData *i_sect_data, int num_isect_data, int orig)
+{
+	int v_c;
+	for(int e = 0; e < emap[orig].count; e++) {
+		for (int i = 0; i < num_isect_data; i++) {
+			if (BLI_ghash_haskey(i_sect_data[i].edge_hash, SET_INT_IN_POINTER(emap[orig].indices[e]))) {
+				goto next_edge;
+			}
+		}
+		v_c = me->medge[emap[orig].indices[e]].v1 == orig ? me->medge[emap[orig].indices[e]].v2 : me->medge[emap[orig].indices[e]].v1;
+		if (BLI_ghash_reinsert(vert_hash, SET_INT_IN_POINTER(v_c), SET_INT_IN_POINTER(v_c), NULL, NULL)) {
+			crawl_mesh_rec(me, emap, vert_hash, i_sect_data, num_isect_data, v_c);
+		}
+	next_edge:;
+	}
+}
+
 static void combine_intersection_data(Mesh *me, SilhouetteData *sil)
 {
 	IntersectionData *data = sil->isect_chunk;
+	MeshElemMap *emap;
+	GHash *vert_hash = BLI_ghash_int_new("vertices within intersection");
+	int *emap_mem;
 	MEdge *first_e = NULL;
-	GHashIterator gh_iter;
+	int inside_vert;
 
-	if (sil->num_isect_data > 0) {
-		for (int i = 0; i < sil->num_isect_data; i++) {
-			if (BLI_ghash_size(data[i].edge_hash) > 0) {
-				GHASH_ITER (gh_iter, data[i].edge_hash) {
-					first_e = &me->medge[(int)BLI_ghashIterator_getKey(&gh_iter)];
-#ifdef DEBUG_DRAW
-					bl_debug_color_set(0xffffff);
-					bl_debug_draw_medge_add(me, (int)BLI_ghashIterator_getKey(&gh_iter));
-					bl_debug_color_set(0x000000);
-#endif
-					break;
-				}
-			}
-			if(first_e) {
-				break;
-			}
-		}
+	if (!data) {
+		return;
 	}
 
-	/*TODO: detect which side is inside and which is outside of first_e ...*/
+	/* TODO: Maybe only generate partial map with only the silhouette inside? */
+	BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
+
+	first_e = &me->medge[data->first_e];
+
+	/*TODO: Invert for clipping functionality!*/
+	inside_vert = !data->flip ^ sil->do_subtract ? first_e->v2 : first_e->v1;
+
+	BLI_ghash_insert(vert_hash, SET_INT_IN_POINTER(inside_vert), SET_INT_IN_POINTER(inside_vert));
+
+	crawl_mesh_rec(me, emap, vert_hash, data, sil->num_isect_data, inside_vert);
+
+	GHashIterator gh_iter;
+	GHASH_ITER (gh_iter, vert_hash) {
+		int v_c = BLI_ghashIterator_getKey(&gh_iter);
+		bl_debug_color_set(0xffff00);
+		bl_debug_draw_point(me->mvert[v_c].co, 0.025f);
+		bl_debug_color_set(0x000000);
+	}
+
+
+	MEM_freeN(emap);
+	MEM_freeN(emap_mem);
 }
 
 /* Generates a 3D shape from a stroke. */
@@ -7354,9 +7431,10 @@ static void silhouette_create_shape_mesh(bContext *C, Mesh *me, SilhouetteData *
 
 	e_start = me->totedge;
 	bridge_all_parts(me, spine, v_steps * 2 + w_steps, n_ori);
-	check_preceding_intersecting_edges(ob, sil, NULL, nodes, me->totedge - e_start);
-
-	combine_intersection_data(me, sil);
+	if (sil->num_inter_nodes) {
+		check_preceding_intersecting_edges(ob, sil, NULL, nodes, me->totedge - e_start);
+		combine_intersection_data(me, sil);
+	}
 	/*printf("Joining %i isect data.\n", sil->num_isect_data);
 	for (int i = 0; i < sil->num_isect_data; i++) {
 		IntersectionData *isect_data = &sil->isect_chunk[i];
@@ -8072,7 +8150,7 @@ static void do_calc_fillet_line_task_cb_ex(void *userdata, void *UNUSED(userdata
 
 	/*TODO: merge rings from multiple threads / nodes*/
 #ifdef DEBUG_DRAW
-	/*for(int r = 0; r < BLI_array_count(ring_start); r++) {
+	for(int r = 0; r < BLI_array_

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list