[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17488] branches/projection-paint/source/ blender: * Added buttons for accessing options "occlude", "backface cull" and "bleed", note that bleed is 0.0 by default, before it was always 2.0;

Campbell Barton ideasman42 at gmail.com
Tue Nov 18 01:17:13 CET 2008


Revision: 17488
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17488
Author:   campbellbarton
Date:     2008-11-18 01:17:13 +0100 (Tue, 18 Nov 2008)

Log Message:
-----------
* Added buttons for accessing options "occlude", "backface cull" and "bleed", note that bleed is 0.0 by default, before it was always 2.0;
* use a faster method of getting a pixels screenspace location.
* check if its possible to break out of pixel to bucket/face intersection early - ~7% overall speedup (ignoring redraw time).
* removed scanline intersection function (added back incase they were needed but it looks like there not)
* speedup for painting with only 1 image (use a loop without context switching checks)
* more commenting + cleanup

Modified Paths:
--------------
    branches/projection-paint/source/blender/makesdna/DNA_scene_types.h
    branches/projection-paint/source/blender/src/buttons_editing.c
    branches/projection-paint/source/blender/src/imagepaint.c

Modified: branches/projection-paint/source/blender/makesdna/DNA_scene_types.h
===================================================================
--- branches/projection-paint/source/blender/makesdna/DNA_scene_types.h	2008-11-17 23:02:53 UTC (rev 17487)
+++ branches/projection-paint/source/blender/makesdna/DNA_scene_types.h	2008-11-18 00:17:13 UTC (rev 17488)
@@ -346,6 +346,10 @@
 	struct Brush *brush;
 	short flag, tool;
 	int pad3;
+	
+	/* for projection painting only */
+	short xray, backface;
+	float seam_bleed;
 } ImagePaintSettings;
 
 typedef struct ParticleBrushData {

Modified: branches/projection-paint/source/blender/src/buttons_editing.c
===================================================================
--- branches/projection-paint/source/blender/src/buttons_editing.c	2008-11-17 23:02:53 UTC (rev 17487)
+++ branches/projection-paint/source/blender/src/buttons_editing.c	2008-11-18 00:17:13 UTC (rev 17488)
@@ -6367,8 +6367,15 @@
 			uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, B_BRUSHCHANGE, "Airbrush",	xco+10,yco-50,butw,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)");
 			uiDefButF(block, NUM, B_NOP, "Rate ", xco+10,yco-70,butw,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush");
 			uiBlockEndAlign(block);
-
+			
 			yco -= 25;
+			
+			/* Projection Painting */
+			uiBlockBeginAlign(block);
+			uiDefButBitS(block, TOGN|BIT, 1, B_NOP, "Occlude",	xco+10,yco-70,butw,19, &settings->imapaint.xray, 0, 0, 0, 0, "Only paint onto the faces directly under the brush");
+			uiDefButBitS(block, TOGN|BIT, 1, B_NOP, "Backface Cull",	xco+10,yco-90,butw,19, &settings->imapaint.backface, 0, 0, 0, 0, "Ignore faces pointing away from the view");
+			uiDefButF(block, NUM, B_NOP, "Bleed ", xco+10,yco-110,butw,19, &settings->imapaint.seam_bleed, 0.0, 8.0, 0, 0, "Extend paint beyond the faces UVs to reduce seams");
+			uiBlockEndAlign(block);
 
 			uiBlockBeginAlign(block);
 			uiDefButF(block, COL, B_VPCOLSLI, "",					0,yco,200,19, brush->rgb, 0, 0, 0, 0, "");

Modified: branches/projection-paint/source/blender/src/imagepaint.c
===================================================================
--- branches/projection-paint/source/blender/src/imagepaint.c	2008-11-17 23:02:53 UTC (rev 17487)
+++ branches/projection-paint/source/blender/src/imagepaint.c	2008-11-18 00:17:13 UTC (rev 17488)
@@ -139,8 +139,9 @@
 	int enabled;
 } ImagePaintPartialRedraw;
 
-/* testing options */
 
+/* ProjectionPaint defines */
+
 /* approx the number of buckets to have under the brush,
  * used with the brush size to set the ps->buckets_x and ps->buckets_y value.
  * 
@@ -152,12 +153,10 @@
 #define PROJ_BUCKET_RECT_MIN 4
 #define PROJ_BUCKET_RECT_MAX 256
 
-
-#define PROJ_BOUNDBOX_DIV 6 /* TODO - test other values, this is a guess, seems ok */
+#define PROJ_BOUNDBOX_DIV 8
 #define PROJ_BOUNDBOX_SQUARED  (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
 
 //#define PROJ_DEBUG_PAINT 1
-#define PROJ_DEBUG_NOSCANLINE 1
 //#define PROJ_DEBUG_NOSEAMBLEED 1
 //#define PROJ_DEBUG_PRINT_THREADS 1
 #define PROJ_DEBUG_WINCLIP 1
@@ -185,6 +184,9 @@
 #define PROJ_BUCKET_BOTTOM	2
 #define PROJ_BUCKET_TOP		3
 
+/* This is mainly a convenience struct used so we can keep an array of images we use
+ * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
+ * because 'partRedrawRect' and 'touch' values would not be thread safe */
 typedef struct ProjectPaintImage {
 	Image *ima;
 	ImBuf *ibuf;
@@ -193,6 +195,7 @@
 	int touch;
 } ProjectPaintImage;
 
+/* Main projection painting struct passed to all projection painting functions */
 typedef struct ProjectPaintState {
 	Brush *brush;
 	short tool, blend;
@@ -254,13 +257,6 @@
 	int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */
 } ProjectPaintState;
 
-#ifndef PROJ_DEBUG_NOSCANLINE
-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;
-#endif
-
 typedef struct ProjectPixel {
 	float projCo2D[2]; /* the floating point screen projection of this pixel */
 	char origColor[4];
@@ -461,7 +457,7 @@
 	}
 }
 
-
+/* fast projection bucket array lookup, use the safe version for bound checking  */
 static int project_paint_BucketOffset(ProjectPaintState *ps, float projCo2D[2])
 {
 	/* If we were not dealing with screenspace 2D coords we could simple do...
@@ -567,8 +563,7 @@
 }
 
 
-/* return the topmost face  in screen coords index or -1
- * bucket_index can be -1 if we dont know it to begin with */
+/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */
 static int project_paint_PickFace(ProjectPaintState *ps, float pt[2], float w[3], int *side) {
 	LinkNode *node;
 	float w_tmp[3];
@@ -626,6 +621,8 @@
 	return best_face_index; /* will be -1 or a valid face */
 }
 
+/* TODO move to "source/blender/imbuf/intern/imageprocess.c" - also try bilinear weight which is faster */
+
 /**************************************************************************
 *                            INTERPOLATIONS 
 *
@@ -714,8 +711,7 @@
 	}
 }
 
-/* bucket_index is optional, since in some cases we know it */
-/* TODO FLOAT */ /* add a function that does this for float buffers */
+/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */
 static int project_paint_PickColor(ProjectPaintState *ps, float pt[2], float *rgba_fp, char *rgba, int interp)
 {
 	float w[3], uv[2];
@@ -806,10 +802,11 @@
 	return 1;
 }
 
-/* return...
- * 0	: no occlusion
+/* Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test)
+ * return...
+ *  0	: no occlusion
  * -1	: no occlusion but 2D intersection is true (avoid testing the other half of a quad)
- * 1	: occluded */
+ *  1	: occluded */
 
 static int project_paint_PointOcclude(float pt[3], float v1[3], float v2[3], float v3[3])
 {
@@ -837,7 +834,9 @@
 }
 
 
-/* check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison */
+/* Check if a screenspace location is occluded by any other faces
+ * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison
+ * and dosn't need to be correct in relation to X and Y coords (this is the case in perspective view) */
 static int project_bucket_point_occluded(ProjectPaintState *ps, int bucket_index, int orig_face, float pixelScreenCo[4])
 {
 	LinkNode *node = ps->bucketFaces[bucket_index];
@@ -871,23 +870,8 @@
 			}
 			
 			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
-				 * the next ~5 to ~200 runs will can hit the first face each time. */
-				if (ps->bucketFaces[bucket_index] != node) {
-					/* SWAP(void *, ps->bucketFaces[bucket_index]->link, node->link); */
-					
-					/* dont need to use swap since we alredy have face_index */
-					node->link = ps->bucketFaces[bucket_index]->link; /* move the value item to the current value */
-					ps->bucketFaces[bucket_index]->link = (void *) face_index;
-					
-					/*printf("swapping %d %d\n", (int)node->link, face_index);*/
-				} /*else {
-					printf("first hit %d\n", face_index);
-				}*/
-#endif
+				/* TODO - we may want to cache the first hit,
+				 * it is not possible to swap the face order in the list anymore */
 				return 1; 
 			}
 		}
@@ -946,111 +930,16 @@
 	}
 }
 
-#ifndef PROJ_DEBUG_NOSCANLINE
-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;
-	
-	if (v4) { /* This is a quad?*/
-		int i4=0, i_mid=0;
-		float xi1, xi2, xi3, xi4, xi_mid;
-				
-		i1 = line_isect_y(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 = line_isect_y(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 = line_isect_y(v3, v4, y_level, &xi3);
-			if (i1 != ISECT_TRUE_P1 && i3 != ISECT_TRUE_P2) 
-				i4 = line_isect_y(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 = line_isect_y(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[1PROJ_DEBUG_NOSEAMBLEED] = MAX2((i3?xi3:xi4), xi_mid);
-					
-					totscanlines = 2;
-				}
-			}
-		}
-	} else { /* triangle */
-		int i = 0;
-		
-		i1 = line_isect_y(v1, v2, y_level, &sc->x_limits[0]);
-		if (i1) i++;
-		
-		if (i1 != ISECT_TRUE_P2) {
-			i2 = line_isect_y(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 = line_isect_y(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;
-}
-#endif // PROJ_DEBUG_NOSCANLINE
-

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list