[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17730] branches/projection-paint/source/ blender/src/imagepaint.c: * fixed crash when a mesh with no UVs was painted .

Campbell Barton ideasman42 at gmail.com
Sat Dec 6 18:53:08 CET 2008


Revision: 17730
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17730
Author:   campbellbarton
Date:     2008-12-06 18:53:08 +0100 (Sat, 06 Dec 2008)

Log Message:
-----------
* fixed crash when a mesh with no UVs was painted.
* fixed more bugs in face clipping, clip_line wasnt working when the line was horiz/vertical. unning exactly on the clipping rectangle bounds.
* testing if a point was inside a triangle didnt work if the point was touching the triangles edge, added IsectPT2Df_limit(...) for this rather then using 3 point/line intersection checks.
...Cant find anymore bugs in face clipping now :)

Modified Paths:
--------------
    branches/projection-paint/source/blender/src/imagepaint.c

Modified: branches/projection-paint/source/blender/src/imagepaint.c
===================================================================
--- branches/projection-paint/source/blender/src/imagepaint.c	2008-12-06 16:22:21 UTC (rev 17729)
+++ branches/projection-paint/source/blender/src/imagepaint.c	2008-12-06 17:53:08 UTC (rev 17730)
@@ -159,7 +159,7 @@
 
 //#define PROJ_DEBUG_PAINT 1
 //#define PROJ_DEBUG_NOSEAMBLEED 1
-//#define PROJ_DEBUG_PRINT_CLIP 1
+#define PROJ_DEBUG_PRINT_CLIP 1
 #define PROJ_DEBUG_WINCLIP 1
 
 /* projectFaceSeamFlags options */
@@ -184,6 +184,9 @@
 #define PROJ_BUCKET_INIT		1<<0
 // #define PROJ_BUCKET_CLONE_INIT	1<<1
 
+/* used for testing doubles, if a point is on a line etc */
+#define PROJ_GEOM_TOLERANCE 0.00001f
+
 /* vert flags */
 #define PROJ_VERT_CULL 1
 
@@ -885,7 +888,7 @@
 	
 	y_diff= fabs(p1[1]-p2[1]); /* yuck, horizontal line, we cant do much here */
 	
-	if (y_diff < 0.000001) {
+	if (y_diff < 0.000001f) {
 		*x_isect = (p1[0]+p2[0]) * 0.5f;
 		return ISECT_TRUE;		
 	}
@@ -1239,6 +1242,7 @@
 	return(Inp2f(u, h)/Inp2f(u, u));
 }
 
+
 /* Converts a UV location to a 3D screenspace location
  * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo
  * 
@@ -1527,92 +1531,156 @@
 }
 
 static int line_clip_rect2f(
-		const rctf *rect,
+		rctf *rect,
 		const float l1[2], const float l2[2],
 		float l1_clip[2], float l2_clip[2])
 {
-	float isect;
-	short ok1 = 0;
-	short ok2 = 0;
-	
-	/* are either of the points inside the rectangle ? */
-	if (	l1[1] >= rect->ymin &&	l1[1] <= rect->ymax &&
-			l1[0] >= rect->xmin &&		l1[0] <= rect->xmax
-	) {
+	/* first account for horizontal, then vertical lines */
+	/* horiz */
+	if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) {
+		/* is the line out of range on its Y axis? */
+		if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
+			return 0;
+		}
+		/* line is out of range on its X axis */
+		if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) {
+			return 0;
+		}
+		
+		
+		if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point  (or close to)*/
+			if (BLI_in_rctf(rect, l1[0], l1[1])) {
+				VECCOPY2D(l1_clip, l1);
+				VECCOPY2D(l2_clip, l2);
+				return 1;
+			}
+			else {
+				return 0;
+			}
+		}
+		
 		VECCOPY2D(l1_clip, l1);
-		ok1 = 1;
-	}
-	
-	if (	l2[1] >= rect->ymin &&	l2[1] <= rect->ymax &&
-			l2[0] >= rect->xmin &&		l2[0] <= rect->xmax
-	) {
 		VECCOPY2D(l2_clip, l2);
-		ok2 = 1;
-	}
-	
-	/* line inside rect */
-	if (ok1 && ok2) {
+		CLAMP(l1_clip[0], rect->xmin, rect->xmax);
+		CLAMP(l2_clip[0], rect->xmin, rect->xmax);
 		return 1;
 	}
-	
-	/* top/bottom */
-	if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
-		if (l1[1] < l2[1]) { /* line 1 is outside */
-			l1_clip[0] = isect;
-			l1_clip[1] = rect->ymin;
-			ok1 = 1;
+	else if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) {
+		/* is the line out of range on its X axis? */
+		if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
+			return 0;
 		}
-		else {
-			l2_clip[0] = isect;
-			l2_clip[1] = rect->ymin;
-			ok2 = 2;
+		
+		/* line is out of range on its Y axis */
+		if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) {
+			return 0;
 		}
+		
+		if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point  (or close to)*/
+			if (BLI_in_rctf(rect, l1[0], l1[1])) {
+				VECCOPY2D(l1_clip, l1);
+				VECCOPY2D(l2_clip, l2);
+				return 1;
+			}
+			else {
+				return 0;
+			}
+		}
+		
+		VECCOPY2D(l1_clip, l1);
+		VECCOPY2D(l2_clip, l2);
+		CLAMP(l1_clip[1], rect->ymin, rect->ymax);
+		CLAMP(l2_clip[1], rect->ymin, rect->ymax);
+		return 1;
 	}
-	if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
-		if (l1[1] > l2[1]) { /* line 1 is outside */
-			l1_clip[0] = isect;
-			l1_clip[1] = rect->ymax;
+	else {
+		float isect;
+		short ok1 = 0;
+		short ok2 = 0;
+		
+		/* Done with vertical lines */
+		
+		/* are either of the points inside the rectangle ? */
+		if (BLI_in_rctf(rect, l1[0], l1[1])) {
+			VECCOPY2D(l1_clip, l1);
 			ok1 = 1;
 		}
-		else {
-			l2_clip[0] = isect;
-			l2_clip[1] = rect->ymax;
-			ok2 = 2;
+		
+		if (BLI_in_rctf(rect, l2[0], l2[1])) {
+			VECCOPY2D(l2_clip, l2);
+			ok2 = 1;
 		}
-	}
+		
+		/* line inside rect */
+		if (ok1 && ok2) return 1;
+		
+		/* top/bottom */
+		if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
+			if (l1[1] < l2[1]) { /* line 1 is outside */
+				l1_clip[0] = isect;
+				l1_clip[1] = rect->ymin;
+				ok1 = 1;
+			}
+			else {
+				l2_clip[0] = isect;
+				l2_clip[1] = rect->ymin;
+				ok2 = 2;
+			}
+		}
+		
+		if (ok1 && ok2) return 1;
+		
+		if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
+			if (l1[1] > l2[1]) { /* line 1 is outside */
+				l1_clip[0] = isect;
+				l1_clip[1] = rect->ymax;
+				ok1 = 1;
+			}
+			else {
+				l2_clip[0] = isect;
+				l2_clip[1] = rect->ymax;
+				ok2 = 2;
+			}
+		}
+		
+		if (ok1 && ok2) return 1;
+		
+		/* left/right */
+		if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
+			if (l1[0] < l2[0]) { /* line 1 is outside */
+				l1_clip[0] = rect->xmin;
+				l1_clip[1] = isect;
+				ok1 = 1;
+			}
+			else {
+				l2_clip[0] = rect->xmin;
+				l2_clip[1] = isect;
+				ok2 = 2;
+			}
+		}
 	
-	/* left/right */
-	if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
-		if (l1[0] < l2[0]) { /* line 1 is outside */
-			l1_clip[0] = rect->xmin;
-			l1_clip[1] = isect;
-			ok1 = 1;
+		if (ok1 && ok2) return 1;
+		
+		if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
+			if (l1[0] > l2[0]) { /* line 1 is outside */
+				l1_clip[0] = rect->xmax;
+				l1_clip[1] = isect;
+				ok1 = 1;
+			}
+			else {
+				l2_clip[0] = rect->xmax;
+				l2_clip[1] = isect;
+				ok2 = 2;
+			}
 		}
-		else {
-			l2_clip[0] = rect->xmin;
-			l2_clip[1] = isect;
-			ok2 = 2;
+		
+		if (ok1 && ok2) {
+			return 1;
 		}
-	}
-	if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
-		if (l1[0] > l2[0]) { /* line 1 is outside */
-			l1_clip[0] = rect->xmax;
-			l1_clip[1] = isect;
-			ok1 = 1;
-		}
 		else {
-			l2_clip[0] = rect->xmax;
-			l2_clip[1] = isect;
-			ok2 = 2;
+			return 0;
 		}
 	}
-	
-	if (ok1 && ok2) {
-		return 1;
-	}
-	else {
-		return 0;
-	}
 }
 
 
@@ -1819,8 +1887,12 @@
 #define ISECT_4 (1<<3)
 #define ISECT_ALL3 ((1<<3)-1)
 #define ISECT_ALL4 ((1<<4)-1)
-#define ISECT_TOLERANCE 0.0001f
 
+static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit)
+{
+	return (AreaF2Dfl(v1,v2,v3) + limit) > (AreaF2Dfl(pt,v1,v2) + AreaF2Dfl(pt,v2,v3) + AreaF2Dfl(pt,v3,v1)) ? 1 : 0;
+}
+
 static void project_bucket_clip_face(
 		const int is_ortho,
 		rctf *bucket_bounds,
@@ -1829,7 +1901,6 @@
 		float bucket_bounds_uv[8][2],
 		int *tot)
 {
-	int quad_idx= 0;
 	int inside_bucket_flag = 0;
 	int inside_face_flag = 0;
 	const int flip = ((SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) > 0.0f) != (SIDE_OF_LINE(uv1co, uv2co, uv3co) > 0.0f));
@@ -1861,80 +1932,22 @@
 	}
 	
 	/* get the UV space bounding box */
+	/* use IsectPT2Df_limit here so we catch points are are touching the tri edge (or a small fraction over) */
 	bucket_bounds_ss[0][0] = bucket_bounds->xmax;
 	bucket_bounds_ss[0][1] = bucket_bounds->ymin;
-	inside_face_flag |= (IsectPT2Df(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS) ? ISECT_1 : 0);
+	inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 0.001f) ? ISECT_1 : 0);
 	bucket_bounds_ss[1][0] = bucket_bounds->xmax;
 	bucket_bounds_ss[1][1] = bucket_bounds->ymax;
-	inside_face_flag |= (IsectPT2Df(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS) ? ISECT_2 : 0);
+	inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 0.001f) ? ISECT_2 : 0);
 
 	bucket_bounds_ss[2][0] = bucket_bounds->xmin;
 	bucket_bounds_ss[2][1] = bucket_bounds->ymax;
-	inside_face_flag |= (IsectPT2Df(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS) ? ISECT_3 : 0);
+	inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 0.001f) ? ISECT_3 : 0);
 
 	bucket_bounds_ss[3][0] = bucket_bounds->xmin;
 	bucket_bounds_ss[3][1] = bucket_bounds->ymin;
-	inside_face_flag |= (IsectPT2Df(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS) ? ISECT_4 : 0);
+	inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 0.001f) ? ISECT_4 : 0);
 	
-	
-	/* todo - make into a loop */
-	quad_idx = 0;
-	if ((inside_face_flag & ISECT_1)==0) {
-		if (fabs((Vec2Lenf(bucket_bounds_ss[quad_idx], v1coSS) + Vec2Lenf(bucket_bounds_ss[quad_idx], v2coSS)) - Vec2Lenf(v1coSS, v2coSS)) < ISECT_TOLERANCE) {
-			inside_face_flag |= ISECT_1;
-		}
-		else if (fabs((Vec2Lenf(bucket_bounds_ss[quad_idx], v2coSS) + Vec2Lenf(bucket_bounds_ss[quad_idx], v3coSS)) - Vec2Lenf(v2coSS, v3coSS)) < ISECT_TOLERANCE) {
-			inside_face_flag |= ISECT_1;
-		}
-		else if (fabs((Vec2Lenf(bucket_bounds_ss[quad_idx], v3coSS) + Vec2Lenf(bucket_bounds_ss[quad_idx], v1coSS)) - Vec2Lenf(v3coSS, v1coSS)) < ISECT_TOLERANCE) {
-			inside_face_flag |= ISECT_1;
-		}
-	}
-	
-	quad_idx = 1;
-	if ((inside_face_flag & ISECT_2)==0) {
-		if (fabs((Vec2Lenf(bucket_bounds_ss[quad_idx], v1coSS) + Vec2Lenf(bucket_bounds_ss[quad_idx], v2coSS)) - Vec2Lenf(v1coSS, v2coSS)) < ISECT_TOLERANCE) {
-			inside_face_flag |= ISECT_2;
-		}
-		else if (fabs((Vec2Lenf(bucket_bounds_ss[quad_idx], v2coSS) + Vec2Lenf(bucket_bounds_ss[quad_idx], v3coSS)) - Vec2Lenf(v2coSS, v3coSS)) < ISECT_TOLERANCE) {
-			inside_face_flag |= ISECT_2;
-		}
-		else if (fabs((Vec2Lenf(bucket_bounds_ss[quad_idx], v3coSS) + Vec2Lenf(bucket_bounds_ss[quad_idx], v1coSS)) - Vec2Lenf(v3coSS, v1coSS)) < ISECT_TOLERANCE) {
-			inside_face_flag |= ISECT_2;
-		}
-	}
-	
-	quad_idx = 2;
-	
-	if ((inside_face_flag & ISECT_3)==0) {
-		if (fabs((Vec2Lenf(bucket_bounds_ss[quad_idx], v1coSS) + Vec2Lenf(bucket_bounds_ss[quad_idx], v2coSS)) - Vec2Lenf(v1coSS, v2coSS)) < ISECT_TOLERANCE) {
-			inside_face_flag |= ISECT_3;
-		}
-		else if (fabs((Vec2Lenf(bucket_bounds_ss[quad_idx], v2coSS) + Vec2Lenf(bucket_bounds_ss[quad_idx], v3coSS)) - Vec2Lenf(v2coSS, v3coSS)) < ISECT_TOLERANCE) {
-			inside_face_flag |= ISECT_3;
-		}

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list