[Bf-blender-cvs] [9efef3c] master: Fix T37177, sculpting can act on opposite side of mesh in orthographic camera.

Antony Riakiotakis noreply at git.blender.org
Wed Dec 18 17:34:05 CET 2013


Commit: 9efef3c2515bef9cd2928834ab7e29cf32c20593
Author: Antony Riakiotakis
Date:   Wed Dec 18 18:34:02 2013 +0200
http://developer.blender.org/rB9efef3c2515bef9cd2928834ab7e29cf32c20593

Fix T37177, sculpting can act on opposite side of mesh in orthographic camera.

Summary:
Issue here most probably is that the start point in ray-casting is too
far away from the mesh. As a result the triangle intersection code can
sometimes miss the ray intersection. To solve this, we project the ray
segment to the boundary of the root node.

Reviewers: brecht, sergey, campbellbarton

Reviewed By: brecht

Maniphest Tasks: T37177

Differential Revision: http://developer.blender.org/D115

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

M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/editors/sculpt_paint/sculpt.c

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

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index f8c21a1..7ef120e 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -97,6 +97,12 @@ 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);
 
+/* for orthographic cameras, project the far away ray segment points to the root node so
+ * we can have better precision. Warning, this function assumes that ray begins and ends outside
+ * bounding box! */
+void BKE_pbvh_raycast_project_ray_root(PBVH *bvh, bool original, float ray_start[3],
+                                       float ray_end[3], float ray_normal[3]);
+
 /* Drawing */
 
 void BKE_pbvh_node_draw(PBVHNode *node, void *data);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index c982260..061a54d 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1541,6 +1541,49 @@ int BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use
 	return hit;
 }
 
+void BKE_pbvh_raycast_project_ray_root (PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
+{
+	if (bvh->nodes) {
+		float rootmin_start, rootmin_end;
+		float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3];
+		IsectRayAABBData ray;
+		float ray_normal_inv[3];
+		float offset = 1.0f + 1e-3f;
+		float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f};
+
+		if (original)
+			BKE_pbvh_node_get_original_BB(bvh->nodes, bb_min_root, bb_max_root);
+		else
+			BKE_pbvh_node_get_BB(bvh->nodes, bb_min_root, bb_max_root);
+
+		/* slightly offset min and max in case we have a zero width node (due to a plane mesh for instance),
+		 * or faces very close to the bounding box boundary. */
+		mid_v3_v3v3(bb_center, bb_max_root, bb_min_root);
+		/* diff should be same for both min/max since it's calculated from center */
+		sub_v3_v3v3(bb_diff, bb_max_root, bb_center);
+		/* handles case of zero width bb */
+		add_v3_v3(bb_diff, offset_vec);
+		madd_v3_v3v3fl(bb_max_root, bb_center, bb_diff, offset);
+		madd_v3_v3v3fl(bb_min_root, bb_center, bb_diff, -offset);
+
+		/* first project start ray */
+		isect_ray_aabb_initialize(&ray, ray_start, ray_normal);
+		if (!isect_ray_aabb(&ray, bb_min_root, bb_max_root, &rootmin_start))
+			return;
+
+		/* then the end ray */
+		mul_v3_v3fl(ray_normal_inv, ray_normal, -1.0);
+		isect_ray_aabb_initialize(&ray, ray_end, ray_normal_inv);
+		/* unlikely to fail exiting if entering succeeded, still keep this here */
+		if (!isect_ray_aabb(&ray, bb_min_root, bb_max_root, &rootmin_end))
+			return;
+
+		madd_v3_v3v3fl(ray_start, ray_start, ray_normal, rootmin_start);
+		madd_v3_v3v3fl(ray_end, ray_end, ray_normal_inv, rootmin_end);
+	}
+}
+
+
 //#include <GL/glew.h>
 
 typedef struct {
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 74776d6..74afda7 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4290,12 +4290,16 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
 	float ray_start[3], ray_end[3], ray_normal[3], dist;
 	float obimat[4][4];
 	SculptRaycastData srd;
+	bool original;
+	RegionView3D *rv3d;
 
 	view3d_set_viewcontext(C, &vc);
 	
+	rv3d = vc.ar->regiondata;
 	ob = vc.obact;
 	ss = ob->sculpt;
 	cache = ss->cache;
+	original = (cache) ? cache->original : 0;
 
 	sculpt_stroke_modifiers_check(C, ob);
 
@@ -4309,15 +4313,24 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
 	sub_v3_v3v3(ray_normal, ray_end, ray_start);
 	dist = normalize_v3(ray_normal);
 
+	if (!rv3d->is_persp) {
+		BKE_pbvh_raycast_project_ray_root(ss->pbvh, srd.original, ray_start, ray_end, ray_normal);
+
+		/* recalculate the normal */
+		sub_v3_v3v3(ray_normal, ray_end, ray_start);
+		dist = normalize_v3(ray_normal);
+	}
+
+	srd.original = original;
 	srd.ss = vc.obact->sculpt;
+	srd.hit = 0;
 	srd.ray_start = ray_start;
 	srd.ray_normal = ray_normal;
 	srd.dist = dist;
-	srd.hit = 0;
-	srd.original = (cache) ? cache->original : 0;
+
 	BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
 	                 ray_start, ray_normal, srd.original);
-	
+
 	copy_v3_v3(out, ray_normal);
 	mul_v3_fl(out, srd.dist);
 	add_v3_v3(out, ray_start);




More information about the Bf-blender-cvs mailing list