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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to