[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17329] branches/projection-paint/source/ blender/src/imagepaint.c: fix for pixels not being drawn in 2 cases.
Campbell Barton
ideasman42 at gmail.com
Wed Nov 5 04:13:00 CET 2008
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. @@
More information about the Bf-blender-cvs
mailing list