[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