[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17371] branches/projection-paint/source/ blender/src/imagepaint.c: changes to projection painting
Campbell Barton
ideasman42 at gmail.com
Sun Nov 9 03:47:33 CET 2008
Revision: 17371
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17371
Author: campbellbarton
Date: 2008-11-09 03:47:30 +0100 (Sun, 09 Nov 2008)
Log Message:
-----------
changes to projection painting
* initializing a bucket only initializes pixels from that bucket (was initializing all pixels in intersecting faces before which made large faces slow to paint onto)
* removed scanline functions, they are not as useful when initializing small areas.
* UV seam checking also sets the seam flag on the adjacent face to avoid double lookups.
TODO - uv seam bleed doesn't work in perspective mode.
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-09 01:16:12 UTC (rev 17370)
+++ branches/projection-paint/source/blender/src/imagepaint.c 2008-11-09 02:47:30 UTC (rev 17371)
@@ -133,18 +133,22 @@
/* testing options */
#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
+//#define PROJ_DEBUG_PAINT 1
//#define PROJ_DEBUG_NOSEAMBLEED 1
-/* projectFaceFlags options */
-#define PROJ_FACE_IGNORE 1<<0 /* When the face is hidden, backfacing or occluded */
-#define PROJ_FACE_INIT 1<<1 /* When we have initialized the faces data */
-#define PROJ_FACE_SEAM1 1<<2 /* If this face has a seam on any of its edges */
-#define PROJ_FACE_SEAM2 1<<3
-#define PROJ_FACE_SEAM3 1<<4
-#define PROJ_FACE_SEAM4 1<<5
+/* projectFaceSeamFlags options */
+//#define PROJ_FACE_IGNORE 1<<0 /* When the face is hidden, backfacing or occluded */
+//#define PROJ_FACE_INIT 1<<1 /* When we have initialized the faces data */
+#define PROJ_FACE_SEAM1 1<<0 /* If this face has a seam on any of its edges */
+#define PROJ_FACE_SEAM2 1<<1
+#define PROJ_FACE_SEAM3 1<<2
+#define PROJ_FACE_SEAM4 1<<3
+#define PROJ_FACE_NOSEAM1 1<<4
+#define PROJ_FACE_NOSEAM2 1<<5
+#define PROJ_FACE_NOSEAM3 1<<6
+#define PROJ_FACE_NOSEAM4 1<<7
+
#define PROJ_BUCKET_NULL 0
#define PROJ_BUCKET_INIT 1<<0
// #define PROJ_BUCKET_CLONE_INIT 1<<1
@@ -170,25 +174,26 @@
MTFace *dm_mtface;
/* projection painting only */
- MemArena *projectArena; /* use for alocating many pixel structs and link-lists */
- LinkNode **projectBuckets; /* screen sized 2D array, each pixel has a linked list of ProjectPixel's */
- LinkNode **projectFaces; /* projectBuckets alligned array linkList of faces overlapping each bucket */
- char *projectBucketFlags; /* store if the bucks have been initialized */
- char *projectFaceFlags; /* store info about faces, if they are initialized etc*/
- LinkNode **projectVertFaces;/* Only needed for when projectIsSeamBleed is enabled, use to find UV seams */
+ MemArena *projectArena; /* use for alocating many pixel structs and link-lists */
+ LinkNode **projectBuckets; /* screen sized 2D array, each pixel has a linked list of ProjectPixel's */
+ LinkNode **projectFaces; /* projectBuckets alligned array linkList of faces overlapping each bucket */
+ char *projectBucketFlags; /* store if the bucks have been initialized */
+ char *projectFaceSeamFlags; /* store info about faces, if they are initialized etc*/
+ float (*projectFaceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */
+ LinkNode **projectVertFaces; /* Only needed for when projectSeamBleed is enabled, use to find UV seams */
- int bucketsX; /* The size of the bucket grid, the grid span's viewMin2D/viewMax2D so you can paint outsize the screen or with 2 brushes at once */
+ int bucketsX; /* The size of the bucket grid, the grid span's viewMin2D/viewMax2D so you can paint outsize the screen or with 2 brushes at once */
int bucketsY;
- Image **projectImages; /* array of images we are painting onto while, use so we can tag for updates */
+ Image **projectImages; /* array of images we are painting onto while, use so we can tag for updates */
- int projectImageTotal; /* size of projectImages array */
- int imaContextIndex; /* current image, use for context switching */
+ int projectImageTotal; /* size of projectImages array */
+ int imaContextIndex; /* current image, use for context switching */
float (*projectVertScreenCos)[3]; /* verts projected into floating point screen space */
/* options for projection painting */
- short projectIsOcclude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
+ short projectIsOcclude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
short projectIsBackfaceCull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
short projectIsOrtho;
#ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -208,11 +213,6 @@
float viewHeight;
} ProjectPaintState;
-typedef struct ProjectScanline {
- int v[3]; /* verts for this scanline, 0,1,2 or 0,2,3 */
- float x_limits[2]; /* UV min|max for this scanline */
-} ProjectScanline;
-
typedef struct ProjectPixel {
float projCo2D[2]; /* the floating point screen projection of this pixel */
char *pixel;
@@ -424,6 +424,7 @@
w[1]/=wtot;
w[2]/=wtot;
} else {
+ printf("WATCH oUT ZAREA FACE\n");
w[0] = w[1] = w[2] = 1.0/3.0; /* dummy values for zero area face */
}
}
@@ -624,6 +625,7 @@
}
if (isect_ret==1) {
+#if 0
/* Cheap Optimization!
* This function runs for every UV Screen pixel,
* therefor swapping the swapping the faces for this buckets list helps because
@@ -639,7 +641,7 @@
} /*else {
printf("first hit %d\n", face_index);
}*/
-
+#endif
return 1;
}
}
@@ -654,7 +656,7 @@
#define ISECT_TRUE 1
#define ISECT_TRUE_P1 2
#define ISECT_TRUE_P2 3
-static int project_scanline_isect(float p1[2], float p2[2], float y_level, float *x_isect)
+static int line_isect_y(float p1[2], float p2[2], float y_level, float *x_isect)
{
if (y_level==p1[1]) {
*x_isect = p1[0];
@@ -676,99 +678,26 @@
}
}
-static int project_face_scanline(ProjectScanline *sc, float y_level, float v1[2], float v2[2], float v3[2], float v4[2])
-{
- /* 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;
+static int line_isect_x(float p1[2], float p2[2], float x_level, float *y_isect)
+{
+ if (x_level==p1[0]) {
+ *y_isect = p1[1];
+ return ISECT_TRUE_P1;
+ }
+ if (x_level==p2[0]) {
+ *y_isect = p2[1];
+ return ISECT_TRUE_P2;
+ }
- if (v4) { /* This is a quad?*/
- int i4=0, i_mid=0;
- float xi1, xi2, xi3, xi4, xi_mid;
-
- i1 = project_scanline_isect(v1, v2, y_level, &xi1);
- 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;
- sc->v[1] = 1;
- sc->v[2] = 2;
- sc->x_limits[0] = MIN2(xi1, xi2);
- sc->x_limits[1] = MAX2(xi1, xi2);
- totscanlines = 1;
- } else {
- 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;
- sc->v[1] = 2;
- sc->v[2] = 3;
- sc->x_limits[0] = MIN2(xi3, xi4);
- sc->x_limits[1] = MAX2(xi3, xi4);
- totscanlines = 1;
- } else {
- /* OK - we have a not-so-simple case, both sides of the quad intersect.
- * Will need to have 2 scanlines */
- if ((i1||i2) && (i3||i4)) {
- i_mid = project_scanline_isect(v1, v3, y_level, &xi_mid);
- /* it would be very rare this would be false, but possible */
- sc->v[0] = 0;
- sc->v[1] = 1;
- sc->v[2] = 2;
- sc->x_limits[0] = MIN2((i1?xi1:xi2), xi_mid);
- sc->x_limits[1] = MAX2((i1?xi1:xi2), xi_mid);
-
- sc++;
- sc->v[0] = 0;
- sc->v[1] = 2;
- sc->v[2] = 3;
- sc->x_limits[0] = MIN2((i3?xi3:xi4), xi_mid);
- sc->x_limits[1] = MAX2((i3?xi3:xi4), xi_mid);
-
- totscanlines = 2;
- }
- }
- }
- } else { /* triangle */
- int i = 0;
-
- 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;
- }
- }
+ if (p1[0] > x_level && p2[0] < x_level) {
+ *y_isect = (p2[1]*(p1[0]-x_level) + p1[1]*(x_level-p2[0])) / (p1[0]-p2[0]);
+ return ISECT_TRUE;
+ } else if (p1[0] < x_level && p2[0] > x_level) {
+ *y_isect = (p2[1]*(x_level-p1[0]) + p1[1]*(p2[0]-x_level)) / (p2[0]-p1[0]);
+ return ISECT_TRUE;
+ } else {
+ return 0;
}
- /* done setting up scanlines */
- return totscanlines;
}
static int cmp_uv(float vec2a[2], float vec2b[2])
@@ -778,7 +707,8 @@
#ifndef PROJ_DEBUG_NOSEAMBLEED
-static int check_seam(ProjectPaintState *ps, int orig_face, int orig_i1_fidx, int orig_i2_fidx)
+/* TODO - set the seam flag on the other face to avoid double lookups */
+static int check_seam(ProjectPaintState *ps, int orig_face, int orig_i1_fidx, int orig_i2_fidx, int *other_face, int *orig_fidx)
{
LinkNode *node;
int face_index;
@@ -814,15 +744,17 @@
if (i2_fidx != -1) {
/* This IS an adjacent face!, now lets check if the UVs are ok */
+
+
tf = ps->dm_mtface + face_index;
+ /* set up the other face */
+ *other_face = face_index;
+ *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx;
+
/* first test if they have the same image */
- if (orig_tf->tpage != tf->tpage) {
- // printf("SEAM (IMAGE DIFF)\n");
- return 1;
- }
-
- if ( cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) &&
+ if ( (orig_tf->tpage == tf->tpage) &&
+ cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) &&
cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) )
{
// printf("SEAM (NONE)\n");
@@ -836,25 +768,10 @@
}
}
// printf("SEAM (NO FACE)\n");
+ *other_face = -1;
return 1;
}
-static void project_face_seams_init(ProjectPaintState *ps, int face_index, int is_quad)
-{
- if (is_quad) {
- ps->projectFaceFlags[face_index] |=
- (check_seam(ps, face_index, 0,1) ? PROJ_FACE_SEAM1 : 0) |
- (check_seam(ps, face_index, 1,2) ? PROJ_FACE_SEAM2 : 0) |
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list