[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [53730] trunk/blender/source/blender/ editors/mesh/editmesh_knife.c: Fix knife angle constraint bug #33813 by changing knife mvals to floats.

Howard Trickey howard.trickey at gmail.com
Fri Jan 11 15:13:26 CET 2013


Revision: 53730
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53730
Author:   howardt
Date:     2013-01-11 14:13:22 +0000 (Fri, 11 Jan 2013)
Log Message:
-----------
Fix knife angle constraint bug #33813 by changing knife mvals to floats.

The problem was that by snapping the integer mouse values to
lines through the previous point, the angle was slightly off.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/mesh/editmesh_knife.c

Modified: trunk/blender/source/blender/editors/mesh/editmesh_knife.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_knife.c	2013-01-11 04:34:15 UTC (rev 53729)
+++ trunk/blender/source/blender/editors/mesh/editmesh_knife.c	2013-01-11 14:13:22 UTC (rev 53730)
@@ -128,7 +128,7 @@
 	BMFace *bmface;
 	int is_space;
 
-	int mval[2]; /* mouse screen position */
+	float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */
 } KnifePosData;
 
 /* struct for properties used while drawing */
@@ -204,10 +204,10 @@
 static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f);
 
 #if 0
-static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2],
+static void knife_input_ray_cast(KnifeTool_OpData *kcd, const float mval[2],
                                  float r_origin[3], float r_ray[3]);
 #endif
-static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs,
+static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
                                     float r_origin[3], float r_dest[3]);
 
 static void knife_update_header(bContext *C, KnifeTool_OpData *kcd)
@@ -225,6 +225,10 @@
 	ED_area_headerprint(CTX_wm_area(C), header);
 }
 
+static inline int round_ftoi(float x)
+{
+	return x > 0.0f ?  (int)(x + 0.5f) : (int)(x - 0.5f);
+}
 
 static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3])
 {
@@ -238,8 +242,8 @@
 	kpd->vert = NULL;
 	kpd->edge = NULL;
 	kpd->bmface = NULL;
-	kpd->mval[0] = 0;
-	kpd->mval[1] = 0;
+	kpd->mval[0] = 0.0f;
+	kpd->mval[1] = 0.0f;
 }
 
 static ListBase *knife_empty_list(KnifeTool_OpData *kcd)
@@ -1420,17 +1424,14 @@
 
 /* this works but gives numeric problems [#33400] */
 #if 0
-static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2],
+static void knife_input_ray_cast(KnifeTool_OpData *kcd, const float mval[2],
                                  float r_origin[3], float r_ray[3])
 {
 	bglMats mats;
-	float mval[2], imat[3][3];
+	float imat[3][3];
 
 	knife_bgl_get_mats(kcd, &mats);
 
-	mval[0] = (float)mval_i[0];
-	mval[1] = (float)mval_i[1];
-
 	/* unproject to find view ray */
 	ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f);
 
@@ -1452,23 +1453,19 @@
 }
 #endif
 
-static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs,
+static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
                                     float r_origin[3], float r_origin_ofs[3])
 {
 	bglMats mats;
-	float mval[2];
 
 	knife_bgl_get_mats(kcd, &mats);
 
-	mval[0] = (float)mval_i[0];
-	mval[1] = (float)mval_i[1];
-
 	/* unproject to find view ray */
 	ED_view3d_unproject(&mats, r_origin,     mval[0], mval[1], 0.0f);
 	ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs);
 
 	/* transform into object space */
-	invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+	invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); 
 
 	mul_m4_v3(kcd->ob->imat, r_origin);
 	mul_m4_v3(kcd->ob->imat, r_origin_ofs);
@@ -1483,7 +1480,7 @@
 	float ray[3];
 
 	/* unproject to find view ray */
-	knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs);
+	knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
 	sub_v3_v3v3(ray, origin_ofs, origin);
 
 	f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco);
@@ -1641,8 +1638,8 @@
 				/* update mouse coordinates to the snapped-to edge's screen coordinates
 				 * this is important for angle snap, which uses the previous mouse position */
 				edgesnap = new_knife_vert(kcd, p, cagep);
-				kcd->curr.mval[0] = (int)edgesnap->sco[0];
-				kcd->curr.mval[1] = (int)edgesnap->sco[1];
+				kcd->curr.mval[0] = edgesnap->sco[0];
+				kcd->curr.mval[1] = edgesnap->sco[1];
 
 			}
 			else {
@@ -1720,8 +1717,8 @@
 
 				/* update mouse coordinates to the snapped-to vertex's screen coordinates
 				 * this is important for angle snap, which uses the previous mouse position */
-				kcd->curr.mval[0] = (int)curv->sco[0];
-				kcd->curr.mval[1] = (int)curv->sco[1];
+				kcd->curr.mval[0] = curv->sco[0];
+				kcd->curr.mval[1] = curv->sco[1];
 			}
 
 			return curv;
@@ -1740,48 +1737,56 @@
 	return NULL;
 }
 
+/* update both kcd->curr.mval and kcd->vc.mval to snap to required angle */
 static void knife_snap_angle(KnifeTool_OpData *kcd)
 {
-	int dx, dy;
+	float dx, dy;
 	float w, abs_tan;
 
-	dx = kcd->vc.mval[0] - kcd->prev.mval[0];
-	dy = kcd->vc.mval[1] - kcd->prev.mval[1];
-	if (dx == 0 || dy == 0)
+	dx = kcd->curr.mval[0] - kcd->prev.mval[0];
+	dy = kcd->curr.mval[1] - kcd->prev.mval[1];
+	if (dx == 0.0f && dy == 0.0f)
 		return;
 
-	w = (float)dy / (float)dx;
+	if (dx == 0.0f) {
+		kcd->angle_snapping = ANGLE_90;
+		kcd->curr.mval[0] =kcd->prev.mval[0];
+	}
+
+	w = dy / dx;
 	abs_tan = fabsf(w);
 	if (abs_tan <= 0.4142f) { /* tan(22.5 degrees) = 0.4142 */
 		kcd->angle_snapping = ANGLE_0;
-		kcd->vc.mval[1] = kcd->prev.mval[1];
+		kcd->curr.mval[1] = kcd->prev.mval[1];
 	}
 	else if (abs_tan < 2.4142f) { /* tan(67.5 degrees) = 2.4142 */
 		if (w > 0) {
 			kcd->angle_snapping = ANGLE_45;
-			kcd->vc.mval[1] = kcd->prev.mval[1] + dx;
+			kcd->curr.mval[1] = kcd->prev.mval[1] + dx;
 		}
 		else {
 			kcd->angle_snapping = ANGLE_135;
-			kcd->vc.mval[1] = kcd->prev.mval[1] - dx;
+			kcd->curr.mval[1] = kcd->prev.mval[1] - dx;
 		}
 	}
 	else {
 		kcd->angle_snapping = ANGLE_90;
-		kcd->vc.mval[0] = kcd->prev.mval[0];
+		kcd->curr.mval[0] = kcd->prev.mval[0];
 	}
+
+	kcd->vc.mval[0] = round_ftoi(kcd->curr.mval[0]);
+	kcd->vc.mval[1] = round_ftoi(kcd->curr.mval[1]);
 }
 
 /* update active knife edge/vert pointers */
 static int knife_update_active(KnifeTool_OpData *kcd)
 {
+	knife_pos_data_clear(&kcd->curr);
+	kcd->curr.mval[0] = (float)kcd->vc.mval[0];
+	kcd->curr.mval[1] = (float)kcd->vc.mval[1];
 	if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING)
 		knife_snap_angle(kcd);
 
-	knife_pos_data_clear(&kcd->curr);
-	kcd->curr.mval[0] = kcd->vc.mval[0];
-	kcd->curr.mval[1] = kcd->vc.mval[1];
-
 	/* XXX knife_snap_angle updates the view coordinate mouse values to constrained angles,
 	 * which current mouse values are set to current mouse values are then used
 	 * for vertex and edge snap detection, without regard to the exact angle constraint */
@@ -1799,7 +1804,7 @@
 		float origin[3];
 		float origin_ofs[3];
 
-		knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs);
+		knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
 
 		closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, origin_ofs, origin);
 	}
@@ -2929,11 +2934,11 @@
 	}
 }
 
-static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval[2])
+static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval_i[2])
 {
 	knife_recalc_projmat(kcd);
-	kcd->vc.mval[0] = mval[0];
-	kcd->vc.mval[1] = mval[1];
+	kcd->vc.mval[0] = mval_i[0];
+	kcd->vc.mval[1] = mval_i[1];
 
 	if (knife_update_active(kcd)) {
 		ED_region_tag_redraw(kcd->ar);




More information about the Bf-blender-cvs mailing list