[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17545] branches/projection-paint/source/ blender: * brush and airbrush match The Gimp, where the total color applied to a pixel during a stroke is limited by the brush opacity .

Campbell Barton ideasman42 at gmail.com
Mon Nov 24 03:13:32 CET 2008


Revision: 17545
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17545
Author:   campbellbarton
Date:     2008-11-24 03:13:24 +0100 (Mon, 24 Nov 2008)

Log Message:
-----------
* brush and airbrush match The Gimp, where the total color applied to a pixel during a stroke is limited by the brush opacity. With the airbrush option enabled it will accumulation over the opacity level (as it did before, irrespective of the settings).
* float buffer support for all painting operation and undo.
* only run brush_sample_tex() for textures brushes.
* redraw the brush outline even when nothing is painted.

Modified Paths:
--------------
    branches/projection-paint/source/blender/blenkernel/BKE_brush.h
    branches/projection-paint/source/blender/blenkernel/intern/brush.c
    branches/projection-paint/source/blender/src/imagepaint.c

Modified: branches/projection-paint/source/blender/blenkernel/BKE_brush.h
===================================================================
--- branches/projection-paint/source/blender/blenkernel/BKE_brush.h	2008-11-23 20:06:47 UTC (rev 17544)
+++ branches/projection-paint/source/blender/blenkernel/BKE_brush.h	2008-11-24 02:13:24 UTC (rev 17545)
@@ -53,6 +53,7 @@
 
 /* sampling */
 float brush_sample_falloff(struct Brush *brush, float dist);
+float brush_sample_falloff_noalpha(struct Brush *brush, float dist);
 void brush_sample_tex(struct Brush *brush, float *xy, float *rgba);
 void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size,
 	struct ImBuf **imbuf);

Modified: branches/projection-paint/source/blender/blenkernel/intern/brush.c
===================================================================
--- branches/projection-paint/source/blender/blenkernel/intern/brush.c	2008-11-23 20:06:47 UTC (rev 17544)
+++ branches/projection-paint/source/blender/blenkernel/intern/brush.c	2008-11-24 02:13:24 UTC (rev 17545)
@@ -328,6 +328,23 @@
 		return 0.0f;
 }
 
+float brush_sample_falloff_noalpha(Brush *brush, float dist)
+{
+	float outer, inner;
+
+	outer = brush->size >> 1;
+	inner = outer*brush->innerradius;
+
+	if (dist <= inner) {
+		return 1.0f;
+	}
+	else if ((dist < outer) && (inner < outer)) {
+		return 1.0f - sqrt((dist - inner)/(outer - inner));
+	}
+	else 
+		return 0.0f;
+}
+
 void brush_sample_tex(Brush *brush, float *xy, float *rgba)
 {
 	MTex *mtex= brush->mtex[brush->texact];

Modified: branches/projection-paint/source/blender/src/imagepaint.c
===================================================================
--- branches/projection-paint/source/blender/src/imagepaint.c	2008-11-23 20:06:47 UTC (rev 17544)
+++ branches/projection-paint/source/blender/src/imagepaint.c	2008-11-24 02:13:24 UTC (rev 17545)
@@ -239,8 +239,10 @@
 	/* options for projection painting */
 	short do_occlude;			/* Use raytraced occlusion? - ortherwise will paint right through to the back*/
 	short do_backfacecull;	/* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
+	short do_mask_normal;			/* mask out pixels based on their normals */
 	short is_ortho;
-	short do_mask_normal;			/* mask out pixels based on their normals */
+	short is_airbrush;					/* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */
+	short is_texbrush;					/* only to avoid running  */
 #ifndef PROJ_DEBUG_NOSEAMBLEED
 	float seam_bleed_px;
 #endif
@@ -277,6 +279,7 @@
 {
 	unsigned char ch[4];
 	unsigned int uint;
+	float f[4];
 } PixelStore;
 
 typedef struct ProjPixel {
@@ -286,6 +289,7 @@
 	short x_px, y_px;
 	
 	PixelStore origColor;
+	PixelStore newColor;
 	PixelPointer pixel;
 	
 	short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */
@@ -297,11 +301,6 @@
 	PixelStore clonepx;
 } ProjPixelClone;
 
-typedef struct ProjPixelCloneFloat {
-	struct ProjPixel __pp;
-	float clonepx_f[4];
-} ProjPixelCloneFloat;
-
 /* Finish projection painting structs */
 
 
@@ -695,7 +694,7 @@
 		Vec2Weightf(uv, tf->uv[0], tf->uv[2], tf->uv[3], w);
 	}
 	
-	ibuf = BKE_image_get_ibuf((Image *)tf->tpage, NULL); /* TODO - this may be slow */
+	ibuf = BKE_image_get_ibuf((Image *)tf->tpage, NULL); /* TODO - this may be slow, the only way around it is to have an ibuf index per face */
 	
 
 	
@@ -1272,31 +1271,6 @@
 	VecWeightf(pixelScreenCo, v1co, v2co, v3co, w);
 }
 
-#if 0
-static void screen_px_from_persp(
-		ProjPaintState *ps, float uv[2],
-		float v1co[3], float v2co[3], float v3co[3], /* Worldspace coords */
-		float uv1co[2], float uv2co[2], float uv3co[2],
-		float pixelScreenCo[4],
-		float w[3])
-{
-	BarycentricWeightsSimple2f(uv1co,uv2co,uv3co,uv,w);
-	pixelScreenCo[0] = v1co[0]*w[0] + v2co[0]*w[1] + v3co[0]*w[2];
-	pixelScreenCo[1] = v1co[1]*w[0] + v2co[1]*w[1] + v3co[1]*w[2];
-	pixelScreenCo[2] = v1co[2]*w[0] + v2co[2]*w[1] + v3co[2]*w[2];
-	pixelScreenCo[3] = 1.0;
-	
-	Mat4MulVec4fl(ps->projectMat, pixelScreenCo);
-	
-	// if( pixelScreenCo[3] > 0.001 ) { ??? TODO
-	/* screen space, not clamped */
-	pixelScreenCo[0] = (float)(curarea->winx/2.0f)+(curarea->winx/2.0f)*pixelScreenCo[0]/pixelScreenCo[3];	
-	pixelScreenCo[1] = (float)(curarea->winy/2.0f)+(curarea->winy/2.0f)*pixelScreenCo[1]/pixelScreenCo[3];
-	pixelScreenCo[2] = pixelScreenCo[2]/pixelScreenCo[3]; /* Use the depth for bucket point occlusion */
-}
-#endif
-
-
 /* Only run this function once for new ProjPixelClone's */
 #define IMA_CHAR_PX_SIZE 4
 
@@ -1309,6 +1283,7 @@
 		float w[3]
 ) {
 	float mask;
+	
 	/* calculate mask */
 	if (ps->do_mask_normal) {
 		MFace *mf = ps->dm_mface + face_index;
@@ -1352,17 +1327,20 @@
 		}
 		
 		if (angle >= M_PI_2) {
-			mask = 0.0f;
+			return 0.0f;
 		} else {
-			angle = 1.0f - (angle / M_PI_2); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */
-			mask = ((angle*angle) + angle) * 0.5f; /* nice mix of normal value and power of 2 */
+			mask = 1.0f - (angle / M_PI_2); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */
+			
 		}
 		
-		
 	} else {
 		mask = 1.0f;
 	}
 	
+	if (ps->is_airbrush==0) {
+		mask *= ps->brush->alpha;
+	}
+	
 	return mask;
 }
 
@@ -1390,11 +1368,7 @@
 	if (y<0) y += ibuf->y;
 	
 	if (ps->tool==PAINT_TOOL_CLONE) {
-		if (ibuf->rect_float) {
-			size = sizeof(ProjPixelCloneFloat);
-		} else {
-			size = sizeof(ProjPixelClone);
-		}
+		size = sizeof(ProjPixelClone);
 	} else if (ps->tool==PAINT_TOOL_SMEAR) {
 		size = sizeof(ProjPixelClone);
 	} else {
@@ -1405,10 +1379,13 @@
 	
 	if (ibuf->rect_float) {
 		projPixel->pixel.f_pt = ((( float * ) ibuf->rect_float) + (( x + y * ibuf->x ) * IMA_CHAR_PX_SIZE));
-		/* TODO float support for origColor */
+		projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0];  
+		projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1];  
+		projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2];  
+		projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3];  
 	} else {
 		projPixel->pixel.ch_pt = ((( unsigned char * ) ibuf->rect) + (( x + y * ibuf->x ) * IMA_CHAR_PX_SIZE));
-		projPixel->origColor.uint = *projPixel->pixel.uint_pt;
+		projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt;
 	}
 	
 	/* screenspace unclamped, we could keep its z and w values but dont need them at the moment */
@@ -1426,7 +1403,6 @@
 	/* done with view3d_project_float inline */
 	if (ps->tool==PAINT_TOOL_CLONE) {
 		if (ps->dm_mtface_clone) {
-			/* TODO - float buffer */
 			ImBuf *ibuf_other;
 			MTFace *tf_other = ps->dm_mtface_clone + face_index;
 			float *uvCo1, *uvCo2, *uvCo3;
@@ -1440,8 +1416,6 @@
 				uvCo3 =  tf_other->uv[2];
 			}
 			
-			((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
-			
 			if (tf_other->tpage && ( ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL) )) {
 				/* BKE_image_get_ibuf - TODO - this may be slow */
 					
@@ -1459,24 +1433,41 @@
 				x = x * ibuf_other->x - 0.5f;
 				y = y * ibuf_other->y - 0.5f;
 				
-				/* TODO - float buffer check */
-				bilinear_interpolation_color(ibuf_other, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL, x, y);
+				if (ibuf->rect_float) {
+					if (ibuf_other->rect_float) { /* from float to float */
+						bilinear_interpolation_color(ibuf_other, NULL, ((ProjPixelClone *)projPixel)->clonepx.f, x, y);
+					} else { /* from char to float */
+						unsigned char rgba_ub[4];
+						bilinear_interpolation_color(ibuf_other, rgba_ub, NULL, x, y);
+						IMAPAINT_CHAR_RGBA_TO_FLOAT(((ProjPixelClone *)projPixel)->clonepx.f, rgba_ub);
+					}
+				} else {
+					if (ibuf_other->rect_float) { /* float to char */
+						float rgba[4];
+						bilinear_interpolation_color(ibuf_other, NULL, rgba, x, y);
+						IMAPAINT_FLOAT_RGBA_TO_CHAR(((ProjPixelClone *)projPixel)->clonepx.ch, rgba)
+					} else { /* char to char */
+						bilinear_interpolation_color(ibuf_other, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL, x, y);
+					}
+				}
+				
 			} else {
-				((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
+				if (ibuf->rect_float) {
+					((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
+				} else {
+					((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
+				}
 			}
 			
 		} else {
 			float co[2];
-			
-			/* Initialize clone pixels - note that this is a bit of a waste since some of these are being indirectly initialized :/ */
-			/* TODO - possibly only run this for directly ativated buckets when cloning */
 			Vec2Subf(co, projPixel->projCoSS, ps->clone_offset);
 			
 			/* no need to initialize the bucket, we're only checking buckets faces and for this
 			 * the faces are alredy initialized in project_paint_delayed_face_init(...) */
 			if (ibuf->rect_float) {
-				if (!project_paint_PickColor(ps, co, ((ProjPixelCloneFloat *)projPixel)->clonepx_f, NULL, 1)) {
-					((ProjPixelCloneFloat *)projPixel)->clonepx_f[3] = 0; /* zero alpha - ignore */
+				if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) {
+					((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; /* zero alpha - ignore */
 				}
 			} else {
 				if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) {
@@ -2777,7 +2768,12 @@
 		}
 		
 	}
+	
+	ps->is_airbrush = (ps->brush->flag & BRUSH_AIRBRUSH) ? 1 : 0;
+	
+	ps->is_texbrush = (ps->brush->mtex[ps->brush->texact] && ps->brush->mtex[ps->brush->texact]->tex) ? 1 : 0;
 
+	
 	/* calculate vert screen coords
 	 * run this early so we can calculate the x/y resolution of our bucket rect */
 	
@@ -2814,7 +2810,10 @@
 				(*projScreenCo)[2] = (*projScreenCo)[2]/(*projScreenCo)[3]; /* Use the depth for bucket point occlusion */
 				DO_MINMAX2((*projScreenCo), ps->screen_min, ps->screen_max);
 			} else {
-				/* TODO - deal with cases where 1 side of a face goes behind the view ? */
+				/* TODO - deal with cases where 1 side of a face goes behind the view ?
+				 * 
+				 * After some research this is actually very tricky, only option is to
+				 * clip the derived mesh before painting, which is a Pain */
 				(*projScreenCo)[0] = MAXFLOAT;
 			}
 		}
@@ -3095,7 +3094,7 @@
 	/* build undo data from original pixel colors */
 	if(U.uiflag & USER_GLOBALUNDO) {
 		ProjPixel *projPixel;
-		ImBuf *tmpibuf = NULL;
+		ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL;
 		LinkNode *pixel_node;
 		UndoTile *tile;
 		

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list