[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17759] branches/projection-paint/source/ blender: * tablet pressure changing opacity while painting didnt work

Campbell Barton ideasman42 at gmail.com
Tue Dec 9 09:21:56 CET 2008


Revision: 17759
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17759
Author:   campbellbarton
Date:     2008-12-09 09:21:53 +0100 (Tue, 09 Dec 2008)

Log Message:
-----------
* tablet pressure changing opacity while painting didnt work
* pixels with <= the current opacity are not painted onto, speeds up painting especially with low spacing. (only when airbrush is disabled)
* use qsort rather then own crufty sorting function
* grouped projection painting functions together.

Modified Paths:
--------------
    branches/projection-paint/source/blender/blenkernel/intern/customdata.c
    branches/projection-paint/source/blender/src/buttons_editing.c
    branches/projection-paint/source/blender/src/imagepaint.c

Modified: branches/projection-paint/source/blender/blenkernel/intern/customdata.c
===================================================================
--- branches/projection-paint/source/blender/blenkernel/intern/customdata.c	2008-12-09 07:26:23 UTC (rev 17758)
+++ branches/projection-paint/source/blender/blenkernel/intern/customdata.c	2008-12-09 08:21:53 UTC (rev 17759)
@@ -964,9 +964,13 @@
 	if(index > 0 && data->layers[index-1].type == type) {
 		data->layers[index].active = data->layers[index-1].active;
 		data->layers[index].active_rnd = data->layers[index-1].active_rnd;
+		data->layers[index].active_clone = data->layers[index-1].active_clone;
+		data->layers[index].active_mask = data->layers[index-1].active_mask;
 	} else {
 		data->layers[index].active = 0;
 		data->layers[index].active_rnd = 0;
+		data->layers[index].active_clone = 0;
+		data->layers[index].active_mask = 0;
 	}
 	
 	customData_update_offsets(data);
@@ -1026,6 +1030,8 @@
 			for (; i < data->totlayer && data->layers[i].type == type; i++) {
 				data->layers[i].active--;
 				data->layers[i].active_rnd--;
+				data->layers[i].active_clone--;
+				data->layers[i].active_mask--;
 			}
 	}
 

Modified: branches/projection-paint/source/blender/src/buttons_editing.c
===================================================================
--- branches/projection-paint/source/blender/src/buttons_editing.c	2008-12-09 07:26:23 UTC (rev 17758)
+++ branches/projection-paint/source/blender/src/buttons_editing.c	2008-12-09 08:21:53 UTC (rev 17759)
@@ -722,10 +722,10 @@
 	Mesh *me= (Mesh*)data1;
 	CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata;
 	CustomDataLayer *layer= (CustomDataLayer*)data2;
-	void *actlayerdata, *rndlayerdata, *layerdata=layer->data;
+	void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data;
 	int type= layer->type;
 	int index= CustomData_get_layer_index(data, type);
-	int i, actindex, rndindex;
+	int i, actindex, rndindex, cloneindex, maskindex;
 	
 	/*ok, deleting a non-active layer needs to preserve the active layer indices.
 	  to do this, we store a pointer to the .data member of both layer and the active layer,
@@ -736,6 +736,8 @@
 	  layer. */
 	actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
 	rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
+	clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
+	masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data;
 	CustomData_set_layer_active(data, type, layer - &data->layers[index]);
 
 	/* Multires is handled seperately because the display data is separate
@@ -787,7 +789,34 @@
 		CustomData_set_layer_render(data, type, rndindex);
 	}
 	
+	if (clonelayerdata != layerdata) {
+		/*find index. . .*/
+		cloneindex = CustomData_get_layer_index(data, type);
+		for (i=cloneindex; i<data->totlayer; i++) {
+			if (data->layers[i].data == clonelayerdata) {
+				cloneindex = i - cloneindex;
+				break;
+			}
+		}
+		
+		/*set index. . .*/
+		CustomData_set_layer_clone(data, type, cloneindex);
+	}
 	
+	if (masklayerdata != layerdata) {
+		/*find index. . .*/
+		maskindex = CustomData_get_layer_index(data, type);
+		for (i=maskindex; i<data->totlayer; i++) {
+			if (data->layers[i].data == masklayerdata) {
+				maskindex = i - maskindex;
+				break;
+			}
+		}
+		
+		/*set index. . .*/
+		CustomData_set_layer_mask(data, type, maskindex);
+	}
+	
 	DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
 	
 	if(type == CD_MTFACE)

Modified: branches/projection-paint/source/blender/src/imagepaint.c
===================================================================
--- branches/projection-paint/source/blender/src/imagepaint.c	2008-12-09 07:26:23 UTC (rev 17758)
+++ branches/projection-paint/source/blender/src/imagepaint.c	2008-12-09 08:21:53 UTC (rev 17759)
@@ -118,6 +118,9 @@
 
 #define MAXUNDONAME	64
 
+static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint);
+
+
 typedef struct ImagePaintState {
 	Brush *brush;
 	short tool, blend;
@@ -293,8 +296,16 @@
 
 typedef struct ProjPixel {
 	float projCoSS[2]; /* the floating point screen projection of this pixel */
-	float mask;			/* for various reasons we may want to mask out painting onto this pixel */
 	
+	/* Only used when the airbrush is disabled.
+	 * Store the max mask value to avoid painting over an area with a lower opacity
+	 * with an advantage that we can avoid touching the pixel at all, if the 
+	 * new mask value is lower then mask_max */
+	unsigned short mask_max;
+	
+	/* for various reasons we may want to mask out painting onto this pixel */
+	unsigned short mask;
+	
 	short x_px, y_px;
 	
 	PixelStore origColor;
@@ -943,10 +954,26 @@
 	}
 }
 
-/* simple func use for comparing UV locations to check if there are seams */
+/* simple func use for comparing UV locations to check if there are seams.
+ * Its possible this gives incorrect results, when the UVs for 1 face go into the next 
+ * tile, but do not do this for the adjacent face, it could return a false positive.
+ * This is so unlikely that Id not worry about it. */
 static int cmp_uv(const float vec2a[2], const float vec2b[2])
 {
-	return ((fabs(vec2a[0]-vec2b[0]) < 0.0001f) && (fabs(vec2a[1]-vec2b[1]) < 0.0001f)) ? 1:0;
+	/* if the UV's are not between 0.0 and 1.0 */
+	float xa = (float)fmod(vec2a[0], 1.0f);
+	float ya = (float)fmod(vec2a[1], 1.0f);
+	
+	float xb = (float)fmod(vec2b[0], 1.0f);
+	float yb = (float)fmod(vec2b[1], 1.0f);	
+	
+	if (xa < 0.0f) xa += 1.0f;
+	if (ya < 0.0f) ya += 1.0f;
+	
+	if (xb < 0.0f) xb += 1.0f;
+	if (yb < 0.0f) yb += 1.0f;
+	
+	return ((fabs(xa-xb) < PROJ_GEOM_TOLERANCE) && (fabs(ya-yb) < PROJ_GEOM_TOLERANCE)) ? 1:0;
 }
 
 
@@ -1440,9 +1467,9 @@
 		}
 	}
 	
-	if (ps->is_airbrush==0) {
-		mask *= ps->brush->alpha;
-	}
+	// This only works when the opacity dosnt change while paintnig, stylus pressure messes with this
+	// so dont use it.
+	// if (ps->is_airbrush==0) mask *= ps->brush->alpha;
 	
 	return mask;
 }
@@ -1501,7 +1528,8 @@
 	projPixel->x_px = x_px;
 	projPixel->y_px = y_px;
 	
-	projPixel->mask = mask;
+	projPixel->mask = (unsigned short)(mask * 65535);
+	projPixel->mask_max = 0;
 	
 	/* which bounding box cell are we in?, needed for undo */
 	projPixel->bb_cell_index = ((int)(((float)x_px/(float)ibuf->x) * PROJ_BOUNDBOX_DIV)) + ((int)(((float)y_px/(float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV ;
@@ -1934,9 +1962,22 @@
 
 static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit)
 {
-	return (AreaF2Dfl(v1,v2,v3) + limit) > (AreaF2Dfl(pt,v1,v2) + AreaF2Dfl(pt,v2,v3) + AreaF2Dfl(pt,v3,v1)) ? 1 : 0;
+	return (AreaF2Dfl(v1,v2,v3) + limit) > (AreaF2Dfl(pt,v1,v2) + AreaF2Dfl(pt,v2,v3) + AreaF2Dfl(pt,v3,v1));
 }
 
+/* Clip the face by a bucket and set the uv-space bucket_bounds_uv
+ * so we have the clipped UV's to do pixel intersection tests with 
+ * */
+
+
+static int float_z_sort_flip(const void *p1, const void *p2) {
+	return (((float *)p1)[2] < ((float *)p2)[2] ? 1:-1);
+}
+
+static int float_z_sort(const void *p1, const void *p2) {
+	return (((float *)p1)[2] < ((float *)p2)[2] ?-1:1);
+}
+
 static void project_bucket_clip_face(
 		const int is_ortho,
 		rctf *bucket_bounds,
@@ -1949,7 +1990,6 @@
 	int inside_face_flag = 0;
 	const int flip = ((SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) > 0.0f) != (SIDE_OF_LINE(uv1co, uv2co, uv3co) > 0.0f));
 	
-	float uv[2];
 	float bucket_bounds_ss[4][2];
 	float w[3];
 
@@ -2019,17 +2059,14 @@
 		
 		
 		/* Maximum possible 6 intersections when using a rectangle and triangle */
-		float isectVCosSS[8][2];
-		float isectVAngles[8];
+		float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
+		float v1_clipSS[2], v2_clipSS[2];
 		
-		float vClipSS_A[2], vClipSS_B[2]; 
-		
 		/* calc center*/
 		float cent[2] = {0.0f, 0.0f};
 		/*float up[2] = {0.0f, 1.0f};*/
-		float tmp_f;
 		int i;
-		short unsorted, doubles;
+		short doubles;
 		
 		(*tot) = 0;
 		
@@ -2043,23 +2080,23 @@
 		if (inside_bucket_flag & ISECT_3) {	VECCOPY2D(isectVCosSS[*tot], v3coSS); (*tot)++; }
 		
 		if ((inside_bucket_flag & (ISECT_1|ISECT_2)) != (ISECT_1|ISECT_2)) {
-			if (line_clip_rect2f(bucket_bounds, v1coSS, v2coSS, vClipSS_A, vClipSS_B)) {
-				if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], vClipSS_A); (*tot)++; }
-				if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], vClipSS_B); (*tot)++; }
+			if (line_clip_rect2f(bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) {
+				if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
+				if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
 			}
 		}
 		
 		if ((inside_bucket_flag & (ISECT_2|ISECT_3)) != (ISECT_2|ISECT_3)) {
-			if (line_clip_rect2f(bucket_bounds, v2coSS, v3coSS, vClipSS_A, vClipSS_B)) {
-				if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], vClipSS_A); (*tot)++; }
-				if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], vClipSS_B); (*tot)++; }
+			if (line_clip_rect2f(bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) {
+				if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
+				if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
 			}
 		}	
 		
 		if ((inside_bucket_flag & (ISECT_3|ISECT_1)) != (ISECT_3|ISECT_1)) {
-			if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, vClipSS_A, vClipSS_B)) {
-				if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], vClipSS_A); (*tot)++; }
-				if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], vClipSS_B); (*tot)++; }
+			if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) {
+				if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
+				if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
 			}
 		}
 		
@@ -2081,49 +2118,26 @@
 		
 		/* Collect angles for every point around the center point */
 
-#if 1	/* starting not so pretty, slightly faster loop */
 		
-		vClipSS_A[0] = cent[0]; /* Abuse this var for the loop below */
-		vClipSS_A[1] = cent[1] + 1.0f;
-		
-		for(i=0; i<(*tot); i++) {
-			vClipSS_B[0] = isectVCosSS[i][0] - cent[0];

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list