[Bf-blender-cvs] [e732c58] master: Detail sampling operator

Antony Riakiotakis noreply at git.blender.org
Sat Mar 22 22:35:53 CET 2014


Commit: e732c5809c2be01a0c622987bf9fbe7b37d3ed4c
Author: Antony Riakiotakis
Date:   Sat Mar 22 23:35:07 2014 +0200
https://developer.blender.org/rBe732c5809c2be01a0c622987bf9fbe7b37d3ed4c

Detail sampling operator

Located on topology panel.

To use just click on button and click on mesh.
Operator will just use the dimensions of the triangles below to set the
constant detail setting.

Also changed pair of scale/detail size with nice separate float
percentage value.

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

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/pbvh_bmesh.c
M	source/blender/blenkernel/intern/pbvh_intern.h
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_sculpt_paint.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 4dc4434..b67c8ef 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1240,9 +1240,7 @@ class VIEW3D_PT_sculpt_topology(Panel, View3DPaintPanel):
         sub = col.column(align=True)
         sub.active = brush and brush.sculpt_tool not in ('MASK')
         if (sculpt.detail_type_method == 'CONSTANT'):
-            row = sub.row(align=True)
-            row.prop(sculpt, "detail_size")
-            row.prop(sculpt, "constant_detail_scale")
+            sub.prop(sculpt, "constant_detail")
         else:
             sub.prop(sculpt, "detail_size")
         sub.prop(sculpt, "detail_refine_method", text="")
@@ -1251,6 +1249,7 @@ class VIEW3D_PT_sculpt_topology(Panel, View3DPaintPanel):
         col.prop(sculpt, "use_smooth_shading")
         col.operator("sculpt.optimize")
         if (sculpt.detail_type_method == 'CONSTANT'):
+           col.operator("sculpt.sample_detail_size")
            col.operator("sculpt.detail_flood_fill")
         col.separator()
         col.prop(sculpt, "symmetrize_direction")
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 0828ea5..3601ff1 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -98,6 +98,9 @@ int BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use
                           const float ray_start[3], const float ray_normal[3],
                           float *dist);
 
+int BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node, const float ray_start[3],
+							const float ray_normal[3], float *detail, float *dist);
+
 /* for orthographic cameras, project the far away ray segment points to the root node so
  * we can have better precision. */
 void BKE_pbvh_raycast_project_ray_root(PBVH *bvh, bool original, float ray_start[3],
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 3fae446..808b3fa 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1035,6 +1035,50 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
 	return hit;
 }
 
+int BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node, const float ray_start[3],
+							const float ray_normal[3], float *detail, float *dist)
+{
+	GHashIterator gh_iter;
+	int hit = 0;
+	BMFace *f_hit = NULL;
+
+	if (node->flag & PBVH_FullyHidden)
+		return 0;
+
+	GHASH_ITER (gh_iter, node->bm_faces) {
+		BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+		BLI_assert(f->len == 3);
+		if (f->len == 3 && !paint_is_bmesh_face_hidden(f)) {
+			BMVert *v_tri[3];
+			int hit_local;
+			BM_face_as_array_vert_tri(f, v_tri);
+			hit_local = ray_face_intersection(ray_start, ray_normal,
+										 v_tri[0]->co,
+										 v_tri[1]->co,
+										 v_tri[2]->co,
+										 NULL, dist);
+			if (hit_local) {
+				f_hit = f;
+			}
+			hit |= hit_local;
+		}
+	}
+
+	if (hit) {
+		float len1, len2, len3;
+		BMVert *v_tri[3];
+		BM_face_as_array_vert_tri(f_hit, v_tri);
+		len1 = len_v3v3(v_tri[0]->co, v_tri[1]->co);
+		len2 = len_v3v3(v_tri[1]->co, v_tri[2]->co);
+		len3 = len_v3v3(v_tri[2]->co, v_tri[0]->co);
+
+		*detail = (len1 + len2 + len3)/3.0f;
+	}
+
+	return hit;
+}
+
 
 void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
 {
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index d4cd6bc..75d2a83 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -185,6 +185,9 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
 							const float ray_normal[3], float *dist,
 							int use_original);
 
+int pbvh_bmesh_node_raycast_detail(PBVHNode *node, const float ray_start[3],
+							const float ray_normal[3], float *detail, float *dist);
+
 void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
 
 #endif
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index c6f8007..9ef5852 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4261,6 +4261,13 @@ typedef struct {
 	int original;
 } SculptRaycastData;
 
+typedef struct {
+	float *ray_start, *ray_normal;
+	int hit;
+	float dist;
+	float detail;
+} SculptDetailRaycastData;
+
 static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
 {
 	if (BKE_pbvh_node_get_tmin(node) < *tmin) {
@@ -4289,6 +4296,18 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
 	}
 }
 
+static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
+{
+	if (BKE_pbvh_node_get_tmin(node) < *tmin) {
+		SculptDetailRaycastData *srd = data_v;
+		if (BKE_pbvh_bmesh_node_raycast_detail(node, srd->ray_start, srd->ray_normal,
+											   &srd->detail, &srd->dist)) {
+			srd->hit = 1;
+			*tmin = srd->dist;
+		}
+	}
+}
+
 /* Do a raycast in the tree to find the 3d brush location
  * (This allows us to ignore the GL depth buffer)
  * Returns 0 if the ray doesn't hit the mesh, non-zero otherwise
@@ -4511,7 +4530,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
 
 	if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) {
 		BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
-			sd->constant_detail_scale * (float)sd->detail_size / 100.0f);
+			sd->constant_detail / 100.0f);
 	}
 	else {
 		BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
@@ -5169,8 +5188,8 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
 			ts->sculpt->detail_size = 30;
 		}
 
-		if (ts->sculpt->constant_detail_scale == 0.0)
-			ts->sculpt->constant_detail_scale = 1.0f;
+		if (ts->sculpt->constant_detail == 0.0f)
+			ts->sculpt->constant_detail = 30.0f;
 
 		/* Create sculpt mode session data */
 		if (ob->sculpt)
@@ -5244,7 +5263,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
 
 	/* update topology size */
 	BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
-			sd->constant_detail_scale * (float)sd->detail_size / 100.0f);
+			sd->constant_detail/ 100.0f);
 
 	sculpt_undo_push_begin("Dynamic topology flood fill");
 	sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS);
@@ -5268,7 +5287,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
 static void SCULPT_OT_detail_flood_fill(wmOperatorType *ot)
 {
 	/* identifiers */
-	ot->name = "Flood Fill";
+	ot->name = "Detail Flood Fill";
 	ot->idname = "SCULPT_OT_detail_flood_fill";
 	ot->description = "Flood fill the mesh with the selected detail setting";
 
@@ -5279,6 +5298,123 @@ static void SCULPT_OT_detail_flood_fill(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+static void sample_detail(bContext *C, int ss_co[2])
+{
+	ViewContext vc;
+	Object *ob;
+	Sculpt *sd;
+	float ray_start[3], ray_end[3], ray_normal[3], dist;
+	float obimat[4][4];
+	SculptDetailRaycastData srd;
+	RegionView3D *rv3d;
+	float mouse[2] = {ss_co[0], ss_co[1]};
+	view3d_set_viewcontext(C, &vc);
+
+	rv3d = vc.ar->regiondata;
+	ob = vc.obact;
+
+	sd = CTX_data_tool_settings(C)->sculpt;
+
+	sculpt_stroke_modifiers_check(C, ob);
+
+	/* TODO: what if the segment is totally clipped? (return == 0) */
+	ED_view3d_win_to_segment(vc.ar, vc.v3d, mouse, ray_start, ray_end, true);
+
+	invert_m4_m4(obimat, ob->obmat);
+	mul_m4_v3(obimat, ray_start);
+	mul_m4_v3(obimat, ray_end);
+
+	sub_v3_v3v3(ray_normal, ray_end, ray_start);
+	dist = normalize_v3(ray_normal);
+
+	if (!rv3d->is_persp) {
+		BKE_pbvh_raycast_project_ray_root(ob->sculpt->pbvh, false, ray_start, ray_end, ray_normal);
+
+		/* recalculate the normal */
+		sub_v3_v3v3(ray_normal, ray_end, ray_start);
+		dist = normalize_v3(ray_normal);
+	}
+
+	srd.hit = 0;
+	srd.ray_start = ray_start;
+	srd.ray_normal = ray_normal;
+	srd.dist = dist;
+	srd.detail = sd->constant_detail;
+
+	BKE_pbvh_raycast(ob->sculpt->pbvh, sculpt_raycast_detail_cb, &srd,
+					 ray_start, ray_normal, false);
+
+	if (srd.hit)
+	{
+		sd->constant_detail = srd.detail * 100.0f;
+	}
+}
+
+static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op)
+{
+	int ss_co[2];
+	RNA_int_get_array(op->ptr, "location", ss_co);
+	sample_detail(C, ss_co);
+	return OPERATOR_FINISHED;
+}
+
+
+static int sculpt_sample_detail_size_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e)) {
+	ScrArea *sa = CTX_wm_area(C);
+	ED_area_headerprint(sa, "Click on the mesh to set the detail");
+	WM_event_add_modal_handler(C, op);
+	return OPERATOR_RUNNING_MODAL;
+}
+
+static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wmEvent *e) {
+
+	switch (e->type) {
+		case LEFTMOUSE:
+			if (e->val == KM_PRESS) {
+				ScrArea *sa = CTX_wm_area(C);
+				int ss_co[2] = {e->mval[0], e->mval[1]};
+
+				sample_detail(C, ss_co);
+
+				RNA_int_set_array(op->ptr, "location", ss_co);
+				ED_area_headerprint(sa, NULL);
+				WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+				return OPERATOR_FINISHED;
+			}
+			break;
+
+		case RIGHTMOUSE:
+		{
+			ScrArea *sa = CTX_wm_area(C);
+			ED_area_headerprint(sa, NULL);
+			return OPERATOR_CANCELLED;
+			break;
+		}
+	}
+
+	return OPERATOR_RUNNING_MODAL;
+}
+
+
+static void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Sample Detail Size";
+	ot->idname = "SCULPT_OT_sample_detail_size";
+	ot->description = "Sample the mesh detail on clicked point";
+
+	/* api callbacks */
+	ot->invoke = sculpt_sample_detail_size_invoke;
+	ot->exec = sculpt_sample_detail_size_exec;
+	ot->modal = sculpt_sample_detail_size_modal;
+	ot->poll = sculpt_and_dynamic_topology_constant_detail_poll;
+
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+	RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX, "Location", "Screen Coordinates of sampling", 0, SHRT_MAX);
+}
+
 void ED_operatortypes_sculpt(void)
 {
 	WM_operatortype_append(SCULPT_OT_brush_stroke);
@@ -5288,4 +5424,5 @@ void ED_operatortypes_sculpt(void)
 	WM_operatortype_append

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list