[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17305] branches/projection-paint/source/ blender/src/imagepaint.c: made scanling creation into its own function project_face_scanline,

Campbell Barton ideasman42 at gmail.com
Mon Nov 3 10:59:08 CET 2008


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

Log Message:
-----------
made scanling creation into its own function project_face_scanline,
speedup adding ProjectPixel's by interpolating the screen coords rather then getting the pixels worldcoord and projecting it into screenspace.

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-03 08:26:43 UTC (rev 17304)
+++ branches/projection-paint/source/blender/src/imagepaint.c	2008-11-03 09:59:08 UTC (rev 17305)
@@ -513,6 +513,73 @@
 	}
 }
 
+static int project_face_scanline(ProjectScanline *sc, float y_level, float *v1, float *v2, float *v3, float *v4)
+{	
+	/* Create a scanlines for the face at this Y level 
+	 * triangles will only ever have 1 scanline, quads may have 2 */
+	int totscanlines = 0;
+	
+	if (v4) { /* This is a quad?*/
+		short i1,i2,i3,i4, i_mid;
+		float xi1, xi2, xi3, xi4, xi_mid;
+		
+		
+		i1 = project_scanline_isect(v1, v2, y_level, &xi1);
+		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 {
+			i3 = project_scanline_isect(v3, v4, y_level, &xi3);
+			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 {
+		if (project_uv_scanline(v1, v2, v3, y_level, sc->x_limits)) {
+			sc->v[0] = 0;
+			sc->v[1] = 1;
+			sc->v[2] = 2;
+			totscanlines = 1;
+		}
+	}
+	/* done setting up scanlines */
+	return totscanlines;
+}
 
 static void project_paint_face_init(ProjectPaintState *ps, int face_index, ImBuf *ibuf)
 {
@@ -521,9 +588,6 @@
 	MFace *mf = ps->dm_mface + face_index;
 	MTFace *tf = ps->dm_mtface + face_index;
 	
-	float pxWorldCo[3];
-	float pxProjCo[4];
-	
 	/* UV/pixel seeking data */
 	int x; /* Image X-Pixel */
 	int y;/* Image Y-Pixel */
@@ -540,9 +604,6 @@
 	ProjectScanline *sc;
 	int totscanlines; /* can only be 1 or 2, oh well */
 	
-	float xi1, xi2, xi3, xi4, xi_mid, xi; /* scanline intersecton location */
-	int i1,i2,i3,i4,i_mid; /* scanline intersection results */
-	
 	float pixelScreenCo[3]; /* for testing occlusion we need the depth too, but not for saving into ProjectPixel */
 	int bucket_index;
 	
@@ -574,80 +635,19 @@
 	for (y = ymini; y < ymaxi; y++) {
 		uv[1] = (((float)y)+0.5) / (float)ibuf->y;
 		
-		/* Create a scanlines for the face at this Y level 
-		 * triangles will only ever have 1 scanline, quads may have 2 */
-		totscanlines = 0;
-		sc = scanlines;
+		totscanlines = project_face_scanline(scanlines, uv[1], tf->uv[0], tf->uv[1], tf->uv[2], mf->v4 ? tf->uv[3]:NULL);
 		
-		if (mf->v4) {
-			totscanlines = 0;
-			
-			i1 = project_scanline_isect(tf->uv[0], tf->uv[1], uv[1], &xi1);
-			i2 = project_scanline_isect(tf->uv[1], tf->uv[2], uv[1], &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 {
-				i3 = project_scanline_isect(tf->uv[2], tf->uv[3], uv[1], &xi3);
-				i4 = project_scanline_isect(tf->uv[3], tf->uv[0], uv[1], &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(tf->uv[0], tf->uv[2], uv[1], &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 {
-			if (project_uv_scanline(tf->uv[0], tf->uv[1], tf->uv[2], uv[1], scanlines[0].x_limits)) {
-				sc->v[0] = 0;
-				sc->v[1] = 1;
-				sc->v[2] = 2;
-				totscanlines = 1;
-			}
-		}
-		/* done setting up scanlines */
-		
-		/* Loop over scanlines a bit silly since there can only be 1 or 2, but its easier then having */
+		/* Loop over scanlines a bit silly since there can only be 1 or 2, but its easier then having tri/quad spesific functions */
 		for (j=0, sc=scanlines; j<totscanlines; j++, sc++) {
 			
-			xmini = (int)((ibuf->x * scanlines[j].x_limits[0])+0.5);
-			xmaxi = (int)((ibuf->x * scanlines[j].x_limits[1])+0.5);
+			xmini = (int)((ibuf->x * sc->x_limits[0])+0.5);
+			xmaxi = (int)((ibuf->x * sc->x_limits[1])+0.5);
 			CLAMP(xmini, 0, ibuf->x);
 			CLAMP(xmaxi, 0, ibuf->x);
 			
-			v1co = ps->dm_mvert[ (*(&mf->v1 + sc->v[0])) ].co;
-			v2co = ps->dm_mvert[ (*(&mf->v1 + sc->v[1])) ].co;
-			v3co = ps->dm_mvert[ (*(&mf->v1 + sc->v[2])) ].co;
+			v1co = ps->projectVertScreenCos[ (*(&mf->v1 + sc->v[0])) ];
+			v2co = ps->projectVertScreenCos[ (*(&mf->v1 + sc->v[1])) ];
+			v3co = ps->projectVertScreenCos[ (*(&mf->v1 + sc->v[2])) ];
 			
 			for (x = xmini; x < xmaxi; x++) {
 				uv[0] = (((float)x)+0.5) / (float)ibuf->x;
@@ -662,47 +662,37 @@
 				
 				i=2;
 				do {
-					pxWorldCo[i] = v1co[i]*w1 + v2co[i]*w2 + v3co[i]*w3;
+					pixelScreenCo[i] = v1co[i]*w1 + v2co[i]*w2 + v3co[i]*w3;
+					/* incase we want the world pixel coords */
+					/* pixelWorldCo[i] = ps->dm_mvert[ (*(&mf->v1 + sc->v[0])) ].co[i][0] * w1 ....; */
 				} while (i--);
 				/* Done building the world coord for this UV */
 				
-				/* Inline project from view is a bit faster, also added own tweaks */
-				VECCOPY(pxProjCo, pxWorldCo);
-				pxProjCo[3] = 1.0;
+				bucket_index = project_paint_BucketOffset(ps, pixelScreenCo);
 				
-				Mat4MulVec4fl(ps->projectMat, pxProjCo);
-
-				if( pxProjCo[3] > 0.001 ) {
-					pixelScreenCo[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*pxProjCo[0]/pxProjCo[3];
-					pixelScreenCo[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*pxProjCo[1]/pxProjCo[3];
-					pixelScreenCo[2] = pxProjCo[2]/pxProjCo[3]; /* Only for depth test */
+				/* Use viewMin2D to make (0,0) the bottom left of the bounds 
+				 * Then this can be used to index the bucket array */
+				
+				/* Is this UV visible from the view? - raytrace */
+				if (ps->projectOcclude==0 || !project_bucket_point_occluded(ps, bucket_index, face_index, pixelScreenCo)) {
 					
-					bucket_index = project_paint_BucketOffset(ps, pixelScreenCo);
+					/* done with view3d_project_float inline */
+					projPixel = (ProjectPixel *)BLI_memarena_alloc( ps->projectArena, sizeof(ProjectPixel) );
 					
-					/* Use viewMin2D to make (0,0) the bottom left of the bounds 
-					 * Then this can be used to index the bucket array */
+					/* screenspace unclamped */
+					VECCOPY2D(projPixel->projCo2D, pixelScreenCo);
 					
-					/* Is this UV visible from the view? - raytrace */
-					if (ps->projectOcclude==0 || !project_bucket_point_occluded(ps, bucket_index, face_index, pixelScreenCo)) {
-						
-						/* done with view3d_project_float inline */
-						projPixel = (ProjectPixel *)BLI_memarena_alloc( ps->projectArena, sizeof(ProjectPixel) );
-						
-						/* screenspace unclamped */
-						VECCOPY2D(projPixel->projCo2D, pixelScreenCo);
-						
-						projPixel->pixel = (( char * ) ibuf->rect) + (( x + y * ibuf->x ) * pixel_size);
+					projPixel->pixel = (( char * ) ibuf->rect) + (( x + y * ibuf->x ) * pixel_size);
 #ifdef PROJ_DEBUG_PAINT
-						projPixel->pixel[1] = 0;
+					projPixel->pixel[1] = 0;
 #endif
-						projPixel->image_index = ps->image_index;
-						
-						BLI_linklist_prepend_arena(
-							&ps->projectBuckets[ bucket_index ],
-							projPixel,
-							ps->projectArena
-						);
-					}
+					projPixel->image_index = ps->image_index;
+					
+					BLI_linklist_prepend_arena(
+						&ps->projectBuckets[ bucket_index ],
+						projPixel,
+						ps->projectArena
+					);
 				}
 			}
 		}





More information about the Bf-blender-cvs mailing list