[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17377] branches/projection-paint/source/ blender/src/imagepaint.c: Perspective mode painting works again

Campbell Barton ideasman42 at gmail.com
Sun Nov 9 13:59:01 CET 2008


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

Log Message:
-----------
Perspective mode painting works again
SeamBleed in perspective mode mostly working (some small artifacts but generally looks ok)

Added BarycentricWeightsPersp2f and BarycentricWeightsSimplePersp2f for getting weights from verts with perspective matrix applied.

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 09:51:24 UTC (rev 17376)
+++ branches/projection-paint/source/blender/src/imagepaint.c	2008-11-09 12:59:01 UTC (rev 17377)
@@ -191,7 +191,7 @@
 	int projectImageTotal;			/* size of projectImages array */
 	int imaContextIndex;			/* current image, use for context switching */
 	
-	float (*projectVertScreenCos)[3];	/* verts projected into floating point screen space */
+	float (*projectVertScreenCos)[4];	/* verts projected into floating point screen space */
 	
 	/* options for projection painting */
 	short projectIsOcclude;			/* Use raytraced occlusion? - ortherwise will paint right through to the back*/
@@ -419,7 +419,7 @@
 }
 
 /* The point must be inside the triangle */
-static void BaryCentricWeightsSimple2f(float v1[2], float v2[2], float v3[2], float pt[2], float w[3]) {
+static void BarycentricWeightsSimple2f(float v1[2], float v2[2], float v3[2], float pt[2], float w[3]) {
 	float wtot;
 	w[0] = AreaF2Dfl(v2, v3, pt);
 	w[1] = AreaF2Dfl(v3, v1, pt);
@@ -437,7 +437,7 @@
 
 /* also works for points outside the triangle */
 #define SIDE_OF_LINE(pa,pb,pp)	((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
-static void BaryCentricWeights2f(float v1[2], float v2[2], float v3[2], float pt[2], float w[3]) {
+static void BarycentricWeights2f(float v1[2], float v2[2], float v3[2], float pt[2], float w[3]) {
 	float wtot = AreaF2Dfl(v1, v2, v3);
 	if (wtot > 0.0) {
 		w[0] = AreaF2Dfl(v2, v3, pt);
@@ -458,9 +458,41 @@
 	}
 }
 
+/* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */
+
+static void BarycentricWeightsPersp2f(float v1[4], float v2[4], float v3[4], float pt[2], float w[3]) {
+	float persp_tot;
+	BarycentricWeights2f(v1,v2,v3,pt,w);
+	
+	w[0] /= v1[3];
+	w[1] /= v2[3];
+	w[2] /= v3[3];
+	
+	persp_tot = w[0]+w[1]+w[2];
+	
+	w[0] /= persp_tot;
+	w[1] /= persp_tot;
+	w[2] /= persp_tot;
+}
+
+static void BarycentricWeightsSimplePersp2f(float v1[4], float v2[4], float v3[4], float pt[2], float w[3]) {
+	float persp_tot;
+	BarycentricWeightsSimple2f(v1,v2,v3,pt,w);
+	
+	w[0] /= v1[3];
+	w[1] /= v2[3];
+	w[2] /= v3[3];
+	
+	persp_tot = w[0]+w[1]+w[2];
+	
+	w[0] /= persp_tot;
+	w[1] /= persp_tot;
+	w[2] /= persp_tot;
+}
+
 static float tri_depth_2d(float v1[3], float v2[3], float v3[3], float pt[2], float w[3])
 {
-	BaryCentricWeightsSimple2f(v1,v2,v3,pt,w);
+	BarycentricWeightsSimple2f(v1,v2,v3,pt,w);
 	return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]);
 }
 
@@ -1084,7 +1116,7 @@
 		float pixelScreenCo[4] )
 {
 	float w[3];
-	BaryCentricWeightsSimple2f(uv1co,uv2co,uv3co,uv,w);
+	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];	
@@ -1097,7 +1129,7 @@
 		float pixelScreenCo[4])
 {
 	float w[3];
-	BaryCentricWeightsSimple2f(uv1co,uv2co,uv3co,uv,w);
+	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];
@@ -1330,6 +1362,8 @@
 	int min_px_bucket[2][2], max_px_bucket[2][2]; /* Bucket Bounds converted to int's for pixel */
 	float *v1coSS, *v2coSS, *v3coSS, *v4coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
 	float *v1co, *v2co, *v3co; /* vert co */
+	float *vCo[4]; /* vertex screenspace coords */
+	
 	float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */
 	float pixelScreenCo[4], pixelScreenCoXMin[4], pixelScreenCoXMax[4];
 	int i, j;
@@ -1346,6 +1380,12 @@
 	int totscanlines; /* can only be 1 or 2, oh well */
 #endif
 
+	vCo[0] = ps->dm_mvert[ (*(&mf->v1    )) ].co;
+	vCo[1] = ps->dm_mvert[ (*(&mf->v1 + 1)) ].co;
+	vCo[2] = ps->dm_mvert[ (*(&mf->v1 + 2)) ].co;
+	if (mf->v4)
+		vCo[3] = ps->dm_mvert[ (*(&mf->v1 + 3)) ].co;
+
 	i = mf->v4 ? 1:0;
 	do {
 		if (i==1) {
@@ -1362,35 +1402,33 @@
 		v2coSS = ps->projectVertScreenCos[ (*(&mf->v1 + i2)) ];
 		v3coSS = ps->projectVertScreenCos[ (*(&mf->v1 + i3)) ];
 		
-		if (ps->projectIsOrtho==0) {
-			v1co = ps->dm_mvert[ (*(&mf->v1 + i1)) ].co;
-			v2co = ps->dm_mvert[ (*(&mf->v1 + i2)) ].co;
-			v3co = ps->dm_mvert[ (*(&mf->v1 + i3)) ].co;
-		}
-		
 		/* get the UV space bounding box */
 		uv[0] = bucket_bounds[PROJ_BUCKET_RIGHT];
 		uv[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
-		BaryCentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+		if (ps->projectIsOrtho)	BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);	
+		else					BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);	
 		bucket_bounds_uv[0][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
 		bucket_bounds_uv[0][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
 		
 		//uv[0] = bucket_bounds[PROJ_BUCKET_RIGHT]; // set above
 		uv[1] = bucket_bounds[PROJ_BUCKET_TOP];
-		BaryCentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+		if (ps->projectIsOrtho)	BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+		else					BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
 		bucket_bounds_uv[1][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
 		bucket_bounds_uv[1][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
 		
 		
 		uv[0] = bucket_bounds[PROJ_BUCKET_LEFT];
 		//uv[1] = bucket_bounds[PROJ_BUCKET_TOP]; // set above
-		BaryCentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+		if (ps->projectIsOrtho)	BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+		else			BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
 		bucket_bounds_uv[2][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
 		bucket_bounds_uv[2][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
 		
 		//uv[0] = bucket_bounds[PROJ_BUCKET_LEFT]; // set above
 		uv[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
-		BaryCentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+		if (ps->projectIsOrtho)	BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+		else					BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
 		bucket_bounds_uv[3][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
 		bucket_bounds_uv[3][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
 		
@@ -1417,7 +1455,7 @@
 						if (ps->projectIsOrtho) {
 							screen_px_from_ortho(ps, uv, v1coSS,v2coSS,v3coSS, uv1co,uv2co,uv3co, pixelScreenCo);
 						} else {
-							screen_px_from_persp(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
+							screen_px_from_persp(ps, uv, vCo[i1],vCo[i2],vCo[i3], uv1co,uv2co,uv3co, pixelScreenCo);
 						}
 						
 						project_paint_uvpixel_init(ps, ibuf, x,y, bucket_index, face_index, pixelScreenCo);
@@ -1447,18 +1485,19 @@
 			
 			/* Now create new UV's for the seam face */
 			float (*outset_uv)[2];
-			float insetCos[4][3]; /* expanded UV's */
+			float insetCos[4][3]; /* inset face coords.  NOTE!!! ScreenSace for ortho, Worldspace in prespective view */
 			float cent[3];
-			float *uv_seam_quads[4][4];
-			float *edge_verts_inset[4][2];
-			float *edge_verts[4][2];
+			float *uv_seam_quad[4];
 			float fac;
 			float *vCoSS[4]; /* vertex screenspace coords */
 			
-			float bucket_clip_edges[4][2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */
-			int totuvseamquads = 0;
+			float bucket_clip_edges[2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */
+			float edge_verts_inset_clip[2][3];
 			int fidx1, fidx2; /* face edge pairs - loop throuh these ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */
 			
+			float seam_subsection[4][2];
+			float fac1, fac2, ftot;
+			
 			outset_uv = ps->projectFaceSeamUVs[face_index];
 			
 			if (outset_uv[0][0]==MAXFLOAT) /* first time initialize */
@@ -1467,11 +1506,15 @@
 			vCoSS[0] = ps->projectVertScreenCos[ mf->v1 ];
 			vCoSS[1] = ps->projectVertScreenCos[ mf->v2 ];
 			vCoSS[2] = ps->projectVertScreenCos[ mf->v3 ];
-			if (mf->v4) {
+			if (mf->v4)
 				vCoSS[3] = ps->projectVertScreenCos[ mf->v4 ];
-				scale_quad(vCoSS, insetCos, 0.99999);
-			} else { 
-				scale_tri(vCoSS, insetCos, 0.99999);
+			
+			if (ps->projectIsOrtho) {
+				if (mf->v4)	scale_quad(vCoSS, insetCos, 0.99999);
+				else		scale_tri(vCoSS, insetCos, 0.99999);
+			} else {
+				if (mf->v4)	scale_quad(vCo, insetCos, 0.99999);
+				else		scale_tri(vCo, insetCos, 0.99999);
 			}
 			
 			for (fidx1 = 0; fidx1 < (mf->v4 ? 4 : 3); fidx1++) {
@@ -1479,86 +1522,74 @@
 				else			fidx2 = (fidx1==2) ? 0 : fidx1+1; /* next fidx in the face (0,1,2) -> (1,2,0) */
 				
 				if (	(ps->projectFaceSeamFlags[face_index] & (1<<fidx1) ) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */
-						line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[totuvseamquads][0], bucket_clip_edges[totuvseamquads][1])
+						line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1])
 				) {
-					uv_seam_quads[totuvseamquads][0] = tf->uv[fidx1];
-					uv_seam_quads[totuvseamquads][1] = tf->uv[fidx2];
-					uv_seam_quads[totuvseamquads][2] = outset_uv[fidx2];
-					uv_seam_quads[totuvseamquads][3] = outset_uv[fidx1];
-					edge_verts_inset[totuvseamquads][0] = insetCos[fidx1]; //ps->projectVertScreenCos[ mf->v3 ];
-					edge_verts_inset[totuvseamquads][1] = insetCos[fidx2]; //ps->projectVertScreenCos[ mf->v1 ];
-					edge_verts[totuvseamquads][0] = vCoSS[fidx1];
-					edge_verts[totuvseamquads][1] = vCoSS[fidx2];
-					totuvseamquads++;
-				}
-			}
-			
-			
-			for (i=0; i< totuvseamquads; i++) { /* loop over our seams */
-				
-			
-				/* make a quad spanning the subsection of the face the bucket intersects with */
-				float seam_subsection[4][2];
-				float fac1, fac2, ftot;
-				float edge_verts_inset_clip[2][3];
 
-				ftot = Vec2Lenf(edge_verts[i][0], edge_verts[i][1]);
-				fac1 = Vec2Lenf(edge_verts[i][0], bucket_clip_edges[i][0]) / ftot;
-				fac2 = Vec2Lenf(edge_verts[i][0], bucket_clip_edges[i][1]) / ftot;
-				
-				Vec2Lerpf(seam_subsection[0], uv_seam_quads[i][0], uv_seam_quads[i][1], fac1);

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list