[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