[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