[Bf-blender-cvs] [950c2ea] master: Transform Snap: Replace pixel limit w/ 'dist_to_ray_sq'

Germano Cavalcante noreply at git.blender.org
Wed Jul 6 03:42:36 CEST 2016


Commit: 950c2eaf614e895f5856d08faa8e86024b75ef85
Author: Germano Cavalcante
Date:   Wed Jul 6 11:34:28 2016 +1000
Branches: master
https://developer.blender.org/rB950c2eaf614e895f5856d08faa8e86024b75ef85

Transform Snap: Replace pixel limit w/ 'dist_to_ray_sq'

When snapping to edge/vert, check the distance to the ray
instead of the screen-space pixel projection.

This also corrects the conversion of `dist_to_ray_sq` to `dist_px` which was being done incorrectly.

While this change was planned, it fixes T48791, caused by error in b01a56ee.

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

M	source/blender/editors/transform/transform_snap_object.c

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

diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index e85b686..c703b87 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -221,170 +221,115 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
 /** \name Internal Object Snapping API
  * \{ */
 
-static bool snapEdge(
-        const ARegion *ar, const float v1co[3], const short v1no[3], const float v2co[3], const short v2no[3],
-        float obmat[4][4], float timat[3][3], const float mval_fl[2],
-        const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3],
+#define V3_MUL_ELEM(a, b) \
+	(a)[0] * (b)[0], \
+	(a)[1] * (b)[1], \
+	(a)[2] * (b)[2]
+
+static bool test_vert(
+        const float vco[3], const float vno[3], const float ray_co[3], const float ray_dir[3],
+        const float ray_depth_range[2], const float scale[3], const bool is_persp,
         /* read/write args */
-        float *ray_depth, float *dist_px,
+        float *ray_depth, float *dist_to_ray_sq,
         /* return args */
-        float r_loc[3], float r_no[3])
+        float r_co[3], float r_no[3])
 {
-	float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
-	int result;
-	bool retval = false;
-
-	copy_v3_v3(ray_end, ray_normal_local);
-	mul_v3_fl(ray_end, 2000);
-	add_v3_v3v3(ray_end, ray_start_local, ray_end);
+	const float vco_sc[3]   = {V3_MUL_ELEM(vco, scale)};
+	const float co_sc[3]    = {V3_MUL_ELEM(ray_co, scale)};
+	const float dir_sc[3]   = {V3_MUL_ELEM(ray_dir, scale)};
 
-	/* dvec used but we don't care about result */
-	result = isect_line_line_v3(v1co, v2co, ray_start_local, ray_end, intersect, dvec);
+	float depth;
+	float dist_sq = dist_squared_to_ray_v3(co_sc, dir_sc, vco_sc, &depth);
 
-	if (result) {
-		float edge_loc[3], vec[3];
-		float mul;
+	if (depth < ray_depth_range[0]) {
+		return false;
+	}
 
-		/* check for behind ray_start */
-		sub_v3_v3v3(dvec, intersect, ray_start_local);
+	if (is_persp) {
+		dist_sq /= SQUARE(depth);
+	}
 
-		sub_v3_v3v3(edge_loc, v1co, v2co);
-		sub_v3_v3v3(vec, intersect, v2co);
+	if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
+		*dist_to_ray_sq = dist_sq;
 
-		mul = dot_v3v3(vec, edge_loc) / dot_v3v3(edge_loc, edge_loc);
+		copy_v3_v3(r_co, vco);
 
-		if (mul > 1) {
-			mul = 1;
-			copy_v3_v3(intersect, v1co);
-		}
-		else if (mul < 0) {
-			mul = 0;
-			copy_v3_v3(intersect, v2co);
+		if (vno) {
+			copy_v3_v3(r_no, vno);
 		}
 
-		if (dot_v3v3(ray_normal_local, dvec) > 0) {
-			float location[3];
-			float new_depth;
-			float screen_loc[2];
-			float new_dist;
-
-			copy_v3_v3(location, intersect);
-
-			mul_m4_v3(obmat, location);
-
-			new_depth = len_v3v3(location, ray_start);
-
-			if (ED_view3d_project_float_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
-				new_dist = len_manhattan_v2v2(mval_fl, screen_loc);
-			}
-			else {
-				new_dist = TRANSFORM_DIST_MAX_PX;
-			}
-
-			/* 10% threshold if edge is closer but a bit further
-			 * this takes care of series of connected edges a bit slanted w.r.t the viewport
-			 * otherwise, it would stick to the verts of the closest edge and not slide along merrily
-			 * */
-			if (new_dist <= *dist_px && new_depth < *ray_depth * 1.001f) {
-				float n1[3], n2[3];
-
-				*ray_depth = new_depth;
-				retval = true;
-
-				sub_v3_v3v3(edge_loc, v1co, v2co);
-				sub_v3_v3v3(vec, intersect, v2co);
-
-				mul = dot_v3v3(vec, edge_loc) / dot_v3v3(edge_loc, edge_loc);
-
-				if (r_no) {
-					normal_short_to_float_v3(n1, v1no);
-					normal_short_to_float_v3(n2, v2no);
-					interp_v3_v3v3(r_no, n2, n1, mul);
-					mul_m3_v3(timat, r_no);
-					normalize_v3(r_no);
-				}
-
-				copy_v3_v3(r_loc, location);
-
-				*dist_px = new_dist;
-			}
-		}
+		*ray_depth = depth;
+		return true;
 	}
-
-	return retval;
+	return false;
 }
 
-static bool snapVertex(
-        const ARegion *ar, const float vco[3], const float vno[3],
-        float obmat[4][4], float timat[3][3], const float mval_fl[2],
-        const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3],
+static bool test_edge(
+        const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3],
+        const float ray_depth_range[2], const float scale[3], const bool is_persp,
         /* read/write args */
-        float *ray_depth, float *dist_px,
+        float *ray_depth, float *dist_to_ray_sq,
         /* return args */
-        float r_loc[3], float r_no[3])
+        float r_co[3], float r_no[3])
 {
-	bool retval = false;
-	float dvec[3];
-
-	sub_v3_v3v3(dvec, vco, ray_start_local);
+	const float v1_sc[3]    = {V3_MUL_ELEM(v1, scale)};
+	const float v2_sc[3]    = {V3_MUL_ELEM(v2, scale)};
+	const float co_sc[3]    = {V3_MUL_ELEM(ray_co, scale)};
+	const float dir_sc[3]   = {V3_MUL_ELEM(ray_dir, scale)};
 
-	if (dot_v3v3(ray_normal_local, dvec) > 0) {
-		float location[3];
-		float new_depth;
-		float screen_loc[2];
-		float new_dist;
-
-		copy_v3_v3(location, vco);
-
-		mul_m4_v3(obmat, location);
-
-		new_depth = len_v3v3(location, ray_start);
+	float tmp_co[3], depth;
+	float dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth);
 
-		if (ED_view3d_project_float_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
-			new_dist = len_manhattan_v2v2(mval_fl, screen_loc);
-		}
-		else {
-			new_dist = TRANSFORM_DIST_MAX_PX;
-		}
+	if (depth < ray_depth_range[0]) {
+		return false;
+	}
 
+	if (is_persp) {
+		dist_sq /= SQUARE(depth);
+	}
 
-		if (new_dist <= *dist_px && new_depth < *ray_depth) {
-			*ray_depth = new_depth;
-			retval = true;
+	if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
+		*dist_to_ray_sq = dist_sq;
 
-			copy_v3_v3(r_loc, location);
+		tmp_co[0] /= scale[0];
+		tmp_co[1] /= scale[1];
+		tmp_co[2] /= scale[2];
 
-			if (r_no) {
-				copy_v3_v3(r_no, vno);
-				mul_m3_v3(timat, r_no);
-				normalize_v3(r_no);
-			}
+		copy_v3_v3(r_co, tmp_co);
 
-			*dist_px = new_dist;
+		if (r_no) {
+			sub_v3_v3v3(r_no, v1, v2);
 		}
-	}
 
-	return retval;
+		*ray_depth = depth;
+		return true;
+	}
+	return false;
 }
 
+#undef V3_MUL_ELEM
+
 static bool snapArmature(
-        const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
-        const float mval[2], const short snap_to,
-        const float ray_start[3], const float ray_normal[3],
+        Object *ob, bArmature *arm, float obmat[4][4],
+        const short snap_to, const bool is_persp,
+        const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
         /* read/write args */
-        float *ray_depth, float *dist_px,
+        float *ray_depth, float *dist_to_ray_sq,
         /* return args */
         float r_loc[3], float *UNUSED(r_no))
 {
 	float imat[4][4];
-	float ray_start_local[3], ray_normal_local[3];
+	float ray_origin_local[3], ray_normal_local[3];
 	bool retval = false;
 
 	invert_m4_m4(imat, obmat);
 
-	mul_v3_m4v3(ray_start_local, imat, ray_start);
+	mul_v3_m4v3(ray_origin_local, imat, ray_origin);
 	mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
 
+	float ob_scale[3];
+	mat4_to_size(ob_scale, obmat);
+
 	if (arm->edbo) {
 		EditBone *eBone;
 
@@ -394,21 +339,20 @@ static bool snapArmature(
 				if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
 					switch (snap_to) {
 						case SCE_SNAP_MODE_VERTEX:
-							retval |= snapVertex(
-							        ar, eBone->head, NULL, obmat, NULL, mval, dist_px,
-							        ray_start, ray_start_local, ray_normal_local, ray_depth,
+							retval |= test_vert(
+							        eBone->head, NULL, ray_origin_local, ray_normal_local,
+							        ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
 							        r_loc, NULL);
-							retval |= snapVertex(
-							        ar, eBone->tail, NULL, obmat, NULL, mval, dist_px,
-							        ray_start, ray_start_local, ray_normal_local, ray_depth,
+							retval |= test_vert(
+							        eBone->tail, NULL, ray_origin_local, ray_normal_local,
+							        ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
 							        r_loc, NULL);
 							break;
 						case SCE_SNAP_MODE_EDGE:
-							retval |= snapEdge(
-							        ar, eBone->head, NULL, eBone->tail, NULL,
-							        obmat, NULL, mval, dist_px,
-							        ray_start, ray_start_local, ray_normal_local,
-							        ray_depth, r_loc, NULL);
+							retval |= test_edge(
+							        eBone->head, eBone->tail, ray_origin_local, ray_normal_local,
+							        ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
+							        r_loc, NULL);
 							break;
 					}
 				}
@@ -428,41 +372,43 @@ static bool snapArmature(
 
 				switch (snap_to) {
 					case SCE_SNAP_MODE_VERTEX:
-						retval |= snapVertex(
-						        ar, head_vec, NULL, obmat, NULL, mval, dist_px,
-						        ray_start, ray_start_local, ray_normal_local,
-						        ray_depth, r_loc, NULL);
-						retval |= snapVertex(
-						        ar, tail_vec, NULL, obmat, NULL, mval, dist_px,
-						        ray_start, ray_start_local, ray_normal_local, ray_depth,
+						retval |= test_vert(
+						        head_vec, NULL, ray_origin_local, ray_normal_local,
+						        ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
+						        r_loc, NULL);
+						retval |= test_vert(
+						        tail_vec, NULL, ray_origin_local, ray_normal_local,
+						        ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
 						        r_loc, NULL);
 						break;
 					case SCE_SNAP_MODE_EDGE:
-						retval |= snapEdge(
-						        ar, head_vec, NULL, tail_vec, NULL,
-						        obmat, NULL, mval, dist_px,
-						        ray_start, ray_start_local, ray_normal_local,
-						        ray_depth, r_loc, NULL);
+						retval |= test_edge(
+						        head_vec, tail_vec, ray_origin_local, ray_normal_local,
+						        ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
+						        r_loc, NULL);
 						break;
 				}
 			}
 		}
 	}
-
-	return retval;
+

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list