Revision: 17329
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17329
Author:   campbellbarton
Date:     2008-11-05 04:12:59 +0100 (Wed, 05 Nov 2008)

Log Message:
-----------
fix for pixels not being drawn in 2 cases.

1 issue was caused by detecting 2d horizontal line intersections for lines that 
had points equal to the horizontal Y value -  solved by detecting point on line 
cases.
Another was because the 2D bounding box for painting could have faces edges 
running along it - solved by adding a small margin to the bounding box.

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-11-04 
23:46:01 UTC (rev 17328)
+++ branches/projection-paint/source/blender/src/imagepaint.c   2008-11-05 
03:12:59 UTC (rev 17329)
@@ -119,7 +119,6 @@
        ImBuf *canvas;
        ImBuf *clonecanvas;
        short clonefreefloat;
-       short project;                  /* is projection texture painting 
enabled */
        char *warnpackedfile;
        char *warnmultifile;
 
@@ -135,6 +134,7 @@
 #define PROJ_BUCKET_DIV 128 /* TODO - test other values, this is a guess, 
seems ok */
 
 // #define PROJ_DEBUG_PAINT 1
+// #define PROJ_DEBUG_NOSCANLINE 1
 
 /* projectFaceFlags options */
 #define PROJ_FACE_IGNORE       1<<0    /* When the face is hidden, backfacing 
or occluded */
@@ -155,6 +155,10 @@
 #define PROJ_BUCKET_TOP                3
 
 typedef struct ProjectPaintState {
+       Brush *brush;
+       short tool, blend;
+       Object *ob;
+       /* end similarities with ImagePaintState */
        
        DerivedMesh    *dm;
        int                     dm_totface;
@@ -479,40 +483,28 @@
        return 0;
 }
 
-/* basic line intersection, could move to arithb.c, 2 points with a horiz line 
*/
-static int project_scanline_isect(float *p1, float *p2, float y_level, float 
*y_isect)
+/* basic line intersection, could move to arithb.c, 2 points with a horiz line
+ * 1 for an intersection, 2 if the first point is aligned, 3 if the second 
point is aligned */
+#define ISECT_TRUE 1
+#define ISECT_TRUE_P1 2
+#define ISECT_TRUE_P2 3
+static int project_scanline_isect(float *p1, float *p2, float y_level, float 
*x_isect)
 {
-       if (p1[1] > y_level && p2[1] < y_level) {
-               *y_isect = (p2[0]*(p1[1]-y_level) + p1[0]*(y_level-p2[1])) / 
(p1[1]-p2[1]);
-               return 1;
-       } else if (p1[1] < y_level && p2[1] > y_level) {
-               *y_isect = (p2[0]*(y_level-p1[1]) + p1[0]*(p2[1]-y_level)) / 
(p2[1]-p1[1]);
-               return 1;
-       } else {
-               return 0;
+       if (y_level==p1[1]) {
+               *x_isect = p1[0];
+               return ISECT_TRUE_P1;
        }
-}
-
-/* take 3 uv coords, a horizontal x_limits and set the min|max intersections 
points here */
-static int project_uv_scanline(float *uv1, float *uv2, float *uv3, float 
y_level, float x_limits[2])
-{
-       int i = 0;
-       
-       if (project_scanline_isect(uv1, uv2, y_level, &x_limits[0])) i++;
-       if (project_scanline_isect(uv2, uv3, y_level, &x_limits[i])) i++;
-       /* if the triangle intersects then the first 2 lines must */
-       if (i==0) {
-               return 0;
-       } else if (i!=2) {
-               /* if we are here then this really should not fail since 2 
edges MUST intersect  */
-               if (project_scanline_isect(uv3, uv1, y_level, &x_limits[i])) 
i++;
+       if (y_level==p2[1]) {
+               *x_isect = p2[0];
+               return ISECT_TRUE_P2;
        }
        
-       if (i==2) {
-               if (x_limits[0] > x_limits[1]) {
-                       SWAP(float, x_limits[0], x_limits[1]);
-               }
-               return 1;
+       if (p1[1] > y_level && p2[1] < y_level) {
+               *x_isect = (p2[0]*(p1[1]-y_level) + p1[0]*(y_level-p2[1])) / 
(p1[1]-p2[1]);
+               return ISECT_TRUE;
+       } else if (p1[1] < y_level && p2[1] > y_level) {
+               *x_isect = (p2[0]*(y_level-p1[1]) + p1[0]*(p2[1]-y_level)) / 
(p2[1]-p1[1]);
+               return ISECT_TRUE;
        } else {
                return 0;
        }
@@ -523,14 +515,15 @@
        /* Create a scanlines for the face at this Y level 
         * triangles will only ever have 1 scanline, quads may have 2 */
        int totscanlines = 0;
+       short i1=0,i2=0,i3=0;
        
        if (v4) { /* This is a quad?*/
-               short i1,i2,i3,i4, i_mid;
+               int i4=0, i_mid=0;
                float xi1, xi2, xi3, xi4, xi_mid;
-               
-               
+                               
                i1 = project_scanline_isect(v1, v2, y_level, &xi1);
-               i2 = project_scanline_isect(v2, v3, y_level, &xi2);
+               if (i1 != ISECT_TRUE_P2) /* rare cases we could be on the line, 
in these cases we dont want to intersect with the same point twice */
+                       i2 = project_scanline_isect(v2, v3, y_level, &xi2);
                
                if (i1 && i2) { /* both the first 2 edges intersect, this means 
the second half of the quad wont intersect */
                        sc->v[0] = 0;
@@ -540,8 +533,10 @@
                        sc->x_limits[1] = MAX2(xi1, xi2);
                        totscanlines = 1;
                } else {
-                       i3 = project_scanline_isect(v3, v4, y_level, &xi3);
-                       i4 = project_scanline_isect(v4, v1, y_level, &xi4);
+                       if (i2 != ISECT_TRUE_P2) 
+                               i3 = project_scanline_isect(v3, v4, y_level, 
&xi3);
+                       if (i1 != ISECT_TRUE_P1 && i3 != ISECT_TRUE_P2) 
+                               i4 = project_scanline_isect(v4, v1, y_level, 
&xi4);
                        
                        if (i3 && i4) { /* second 2 edges only intersect, same 
as above */
                                sc->v[0] = 0;
@@ -573,14 +568,38 @@
                                }
                        }
                }
+       } else { /* triangle */
+               int i = 0;
                
-       } else {
-               if (project_uv_scanline(v1, v2, v3, y_level, sc->x_limits)) {
-                       sc->v[0] = 0;
-                       sc->v[1] = 1;
-                       sc->v[2] = 2;
-                       totscanlines = 1;
+               i1 = project_scanline_isect(v1, v2, y_level, &sc->x_limits[0]);
+               if (i1) i++;
+               
+               if (i1 != ISECT_TRUE_P2) {
+                       i2 = project_scanline_isect(v2, v3, y_level, 
&sc->x_limits[i]);
+                       if (i2) i++;
                }
+               
+               /* if the triangle intersects then the first 2 lines must */
+               if (i!=0) {
+                       if (i!=2) {
+                               /* if we are here then this really should not 
fail since 2 edges MUST intersect  */
+                               if (i1 != ISECT_TRUE_P1 && i2 != ISECT_TRUE_P2) 
{
+                                       i3 = project_scanline_isect(v3, v1, 
y_level, &sc->x_limits[i]);
+                                       if (i3) i++;
+                                       
+                               }
+                       }
+                       
+                       if (i==2) {
+                               if (sc->x_limits[0] > sc->x_limits[1]) {
+                                       SWAP(float, sc->x_limits[0], 
sc->x_limits[1]);
+                               }
+                               sc->v[0] = 0;
+                               sc->v[1] = 1;
+                               sc->v[2] = 2;
+                               totscanlines = 1;
+                       }
+               }
        }
        /* done setting up scanlines */
        return totscanlines;
@@ -883,10 +902,12 @@
 /* can provide own own coords, use for seams when we want to bleed our from 
the original location */
 
 #define pixel_size 4
-static void project_paint_uvpixel_init(ProjectPaintState *ps, ProjectScanline 
*sc, ImBuf *ibuf, float *uv,     int x, int y, int face_index, float 
*pixelScreenCo)
+static void project_paint_uvpixel_init(ProjectPaintState *ps, ImBuf *ibuf, 
float *uv,  int x, int y, int face_index, float *pixelScreenCo)
 {
        int bucket_index;
        
+       // printf("adding px (%d %d), (%f %f)\n", x,y,uv[0],uv[1]);
+       
        ProjectPixel *projPixel;
        
        bucket_index = project_paint_BucketOffset(ps, pixelScreenCo);
@@ -940,10 +961,12 @@
        int i, j;
        
        /* scanlines since quads can have 2 triangles intersecting the same 
vertical location */
+#ifndef PROJ_DEBUG_NOSCANLINE 
        ProjectScanline scanlines[2];
        ProjectScanline *sc;
        int totscanlines; /* can only be 1 or 2, oh well */
-       
+#endif
+
        if (!uv_image_rect(tf->uv[0], tf->uv[1], tf->uv[2], tf->uv[3], min_px, 
max_px, ibuf->x, ibuf->y, mf->v4))
                return;
        
@@ -951,15 +974,16 @@
        if (ps->projectSeamBleed > 0.0)
                project_face_seams_init(ps, face_index, mf->v4);
        
-       for (y = min_px[1]-2; y < max_px[1]+2; y++) {
+       for (y = min_px[1]; y < max_px[1]; y++) {
                uv[1] = (((float)y)+0.5) / (float)ibuf->y; /* TODO - this is 
not pixel aligned correctly */
-               
+
+#ifndef PROJ_DEBUG_NOSCANLINE 
                totscanlines = project_face_scanline(scanlines, uv[1], 
tf->uv[0], tf->uv[1], tf->uv[2], mf->v4 ? tf->uv[3]:NULL);
                
                /* Loop over scanlines a bit silly since there can only be 1 or 
2, but its easier then having tri/quad spesific functions */
                for (j=0, sc=scanlines; j<totscanlines; j++, sc++) {
                        
-                       min_px[0] = (int)((ibuf->x * sc->x_limits[0])+0.5);
+                       min_px[0] = (int)((ibuf->x * sc->x_limits[0])-0.5);
                        max_px[0] = (int)((ibuf->x * sc->x_limits[1])+0.5);
                        CLAMP(min_px[0], 0, ibuf->x);
                        CLAMP(max_px[0], 0, ibuf->x);
@@ -976,26 +1000,8 @@
                                for (x = min_px[0]; x < max_px[0]; x++) {
                                        uv[0] = (((float)x)+0.5) / 
(float)ibuf->x;
                                        screen_px_from_ortho(ps, uv, 
v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
-                                       project_paint_uvpixel_init(ps, sc, 
ibuf, uv, x,y,face_index, pixelScreenCo);
+                                       project_paint_uvpixel_init(ps, ibuf, 
uv, x,y,face_index, pixelScreenCo);
                                }
-                               
-                               /* interpolation is faster - no workies :( */
-                               /*
-                               x = min_px[0];
-                               uv[0] = (((float)x)+0.5) / (float)ibuf->x;
-                               screen_px_from_ortho(ps, uv, v1co,v2co,v3co, 
uv1co,uv2co,uv3co, pixelScreenCoXMin);
-                               
-                               x = max_px[0]-1;
-                               uv[0] = (((float)x)+0.5) / (float)ibuf->x;
-                               screen_px_from_ortho(ps, uv, v1co,v2co,v3co, 
uv1co,uv2co,uv3co, pixelScreenCoXMax);
-                               
-                               for (x = min_px[0]; x < max_px[0]; x++) {
-                                       uv[0] = (((float)x)+0.5) / 
(float)ibuf->x;
-                                       VecLerpf(pixelScreenCo, 
pixelScreenCoXMin, pixelScreenCoXMax, ((float)x) / 
((float)(max_px[0]-min_px[0])) );
-                                       project_paint_uvpixel_init(ps, sc, 
ibuf, uv, x,y, face_index, pixelScreenCo);
-                               }
-                               */
-                               
                        } else {
                                v1co = ps->dm_mvert[ (*(&mf->v1 + sc->v[0])) 
].co;
                                v2co = ps->dm_mvert[ (*(&mf->v1 + sc->v[1])) 
].co;
@@ -1004,31 +1010,49 @@
                                for (x = min_px[0]; x < max_px[0]; x++) {
                                        uv[0] = (((float)x)+0.5) / 
(float)ibuf->x;
                                        screen_px_from_persp(ps, uv, 
v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
-                                       project_paint_uvpixel_init(ps, sc, 
ibuf, uv, x,y,face_index, pixelScreenCo);
+                                       project_paint_uvpixel_init(ps, ibuf, 
uv, x,y,face_index, pixelScreenCo);
                                }
-                               
-                               
-                               /* interpolation is faster */
-                               /*
-                               x = min_px[0];
+                       }
+               }
+#else  /* slow, non scanline method */
+               
+               /* mainly for debuggung scanline, use point-in-tri for every 
x/y test */
+               /* at the moment only works with ortho triangles */
+               uv1co = tf->uv[0];
+               uv2co = tf->uv[1];
+               uv3co = tf->uv[2];
+               
+               if (ps->projectIsOrtho) {
+                       v1co = ps->projectVertScreenCos[ mf->v1 ];
+                       v2co = ps->projectVertScreenCos[ mf->v2 ];
+                       v3co = ps->projectVertScreenCos[ mf->v3 ];
+                       
+                       for (x = min_px[0]; x < max_px[0]; x++) {
                                uv[0] = (((float)x)+0.5) / (float)ibuf->x;
-                               screen_px_from_persp(ps, uv, v1co,v2co,v3co, 
uv1co,uv2co,uv3co, pixelScreenCoXMin);
-                               
-                               x = max_px[0]-1;
-                               uv[0] = (((float)x)+0.5) / (float)ibuf->x;
-                               screen_px_from_persp(ps, uv, v1co,v2co,v3co, 
uv1co,uv2co,uv3co, pixelScreenCoXMax);
-                               
-                               for (x = min_px[0]; x < max_px[0]; x++) {
-                                       uv[0] = (((float)x)+0.5) / 
(float)ibuf->x;
-                                       VecLerpf(pixelScreenCo, 
pixelScreenCoXMin, pixelScreenCoXMax, ((float)x) / 
((float)(max_px[0]-min_px[0])) );
-                                       project_paint_uvpixel_init(ps, sc, 
ibuf, uv, x,y, face_index, pixelScreenCo);
+                               if (IsectPT2Df(uv, uv1co, uv2co, uv3co)) {
+                                       screen_px_from_ortho(ps, uv, 
v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
+                                       project_paint_uvpixel_init(ps, ibuf, 
uv, x,y,face_index, pixelScreenCo);
                                }
-                               */
+
                        }
+               } else {
+                       /*
+                       v1co = ps->dm_mvert[ (*(&mf->v1 + sc->v[0])) ].co;
+                       v2co = ps->dm_mvert[ (*(&mf->v1 + sc->v[1])) ].co;
+                       v3co = ps->dm_mvert[ (*(&mf->v1 + sc->v[2])) ].co;
                        

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to