Revision: 17473
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17473
Author:   campbellbarton
Date:     2008-11-16 16:26:15 +0100 (Sun, 16 Nov 2008)

Log Message:
-----------
* fix "dot drawing" problem - draw lines inbetween updates when redrawing the 
view like how existing painting works. (this means slow systems wont have the 
problems when they would only see dots as they dragged their mouse around)
* bucket resolution is now set from the brush size so there is around 9 buckets 
under the brush - (previously was fixed to 128x128).
* brush sizes below 40 disable multithreading, since threads only speeds up 
cases where each bucket has enough pixels in it for each core to spend some 
time.
* make smear use bicubic pixel lookups so a low Spacing value works as expected.
* smear tool was darkening pixels a tiny bit.
* fix for simple mistake causing ProjectPaintImage arrays not to be thread safe.

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-16 
11:13:19 UTC (rev 17472)
+++ branches/projection-paint/source/blender/src/imagepaint.c   2008-11-16 
15:26:15 UTC (rev 17473)
@@ -140,7 +140,19 @@
 } ImagePaintPartialRedraw;
 
 /* testing options */
-#define PROJ_BUCKET_DIV 128 /* TODO - test other values, this is a guess, 
seems ok */
+
+/* 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.
+ * 
+ * When 3 - a brush should have ~9 buckets under it at once
+ * ...this helps for threading while painting as well as
+ * avoiding initializing pixels that wont touch the brush */
+#define PROJ_BUCKET_BRUSH_DIV 3
+
+#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_SQUARED  (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
 
@@ -741,8 +753,8 @@
                if (x < 0.0) x += 1.0;
                if (y < 0.0) y += 1.0;
                
-               x *= ibuf->x;
-               y *= ibuf->y;
+               x = x * ibuf->x - 0.5;
+               y = y * ibuf->y - 0.5;
                
                if (ibuf->rect_float) {
                        if (rgba_fp) {
@@ -762,8 +774,8 @@
                        }
                }
        } else {
-               xi = uv[0]*ibuf->x;
-               yi = uv[1]*ibuf->y;
+               xi = (uv[0]*ibuf->x) + 0.5;
+               yi = (uv[1]*ibuf->y) + 0.5;
                
                //if (xi<0 || xi>=ibuf->x  ||  yi<0 || yi>=ibuf->y) return 0;
                
@@ -2134,15 +2146,89 @@
        ps->dm_totvert = ps->dm->getNumVerts( ps->dm );
        ps->dm_totface = ps->dm->getNumFaces( ps->dm );
        
-       ps->buckets_x = G.rt ? G.rt : PROJ_BUCKET_DIV;
-       ps->buckets_y = G.rt ? G.rt : PROJ_BUCKET_DIV;
-       
        ps->viewDir[0] = 0.0;
        ps->viewDir[1] = 0.0;
        ps->viewDir[2] = 1.0;
        
        view3d_get_object_project_mat(curarea, ps->ob, ps->projectMat, 
ps->viewMat);
        
+       
+       /* calculate vert screen coords
+        * run this early so we can calculate the x/y resolution of our bucket 
rect */
+       
+       /* since we now run this before the memarena is allocated, this will 
need its own memory */
+       /*ps->screenCoords = BLI_memarena_alloc( ps->arena, sizeof(float) * 
ps->dm_totvert * 4);*/
+       
+       ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, 
"ProjectPaint ScreenVerts");
+       projScreenCo = ps->screenCoords;
+       
+       /* TODO - check cameras mode too */
+       if (G.vd->persp == V3D_ORTHO) {
+               ps->is_ortho = 1;
+       }
+       
+       INIT_MINMAX2(ps->screen_min, ps->screen_max);
+
+       if (ps->is_ortho) {
+               for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
+                       VECCOPY((*projScreenCo), ps->dm_mvert[a].co);
+                       Mat4MulVecfl(ps->projectMat, (*projScreenCo));
+
+                       /* screen space, not clamped */
+                       (*projScreenCo)[0] = 
(float)(curarea->winx/2.0)+(curarea->winx/2.0)*(*projScreenCo)[0];
+                       (*projScreenCo)[1] = 
(float)(curarea->winy/2.0)+(curarea->winy/2.0)*(*projScreenCo)[1];
+                       DO_MINMAX2((*projScreenCo), ps->screen_min, 
ps->screen_max);
+               }
+       } else {
+               for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
+                       VECCOPY((*projScreenCo), ps->dm_mvert[a].co);
+                       (*projScreenCo)[3] = 1.0;
+
+                       Mat4MulVec4fl(ps->projectMat, (*projScreenCo));
+
+                       if( (*projScreenCo)[3] > 0.001 ) {
+                               /* screen space, not clamped */
+                               (*projScreenCo)[0] = 
(float)(curarea->winx/2.0)+(curarea->winx/2.0)*(*projScreenCo)[0]/(*projScreenCo)[3];
+                               (*projScreenCo)[1] = 
(float)(curarea->winy/2.0)+(curarea->winy/2.0)*(*projScreenCo)[1]/(*projScreenCo)[3];
+                               (*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 ? */
+                               (*projScreenCo)[0] = MAXFLOAT;
+                       }
+               }
+       }
+       
+       /* If this border is not added we get artifacts for faces that
+        * have a parallel edge and at the bounds of the the 2D projected verts 
eg
+        * - a single screen aligned quad */
+       projMargin = (ps->screen_max[0] - ps->screen_min[0]) * 0.000001;
+       ps->screen_max[0] += projMargin;
+       ps->screen_min[0] -= projMargin;
+       projMargin = (ps->screen_max[1] - ps->screen_min[1]) * 0.000001;
+       ps->screen_max[1] += projMargin;
+       ps->screen_min[1] -= projMargin;
+       
+       
+       /* only for convenience */
+       ps->screen_width  = ps->screen_max[0] - ps->screen_min[0];
+       ps->screen_height = ps->screen_max[1] - ps->screen_min[1];
+       
+       /* done with screen coords */
+       
+       //ps->buckets_x = G.rt ? G.rt : PROJ_BUCKET_BRUSH_DIV;
+       //ps->buckets_y = G.rt ? G.rt : PROJ_BUCKET_BRUSH_DIV;
+
+       ps->buckets_x = (int)(ps->screen_width / (((float)ps->brush->size) / 
PROJ_BUCKET_BRUSH_DIV));
+       ps->buckets_y = (int)(ps->screen_height / (((float)ps->brush->size) / 
PROJ_BUCKET_BRUSH_DIV));
+       
+       printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, 
ps->buckets_y);
+       
+       /* really high values could cause problems since it has to allocate a 
few
+        * (ps->buckets_x*ps->buckets_y) sized arrays  */
+       CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+       CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+       
        tot_bucketMem =                         sizeof(LinkNode *) * 
ps->buckets_x * ps->buckets_y;
        tot_faceListMem =                       sizeof(LinkNode *) * 
ps->buckets_x * ps->buckets_y;
        
@@ -2190,13 +2276,21 @@
        // calloced - }
 #endif
        
-       /* Thread stuff */
-       if (G.scene->r.mode & R_FIXED_THREADS) {
-               ps->thread_tot = G.scene->r.threads;
+       /* Thread stuff
+        * 
+        * very small brushes run a lot slower multithreaded since the 
advantage with
+        * threads is being able to fill in multiple buckets at once.
+        * Only use threads for bigger brushes. */
+       
+       if (ps->brush->size < 40) {
+               ps->thread_tot = 1;
        } else {
-               ps->thread_tot = BLI_system_thread_count();
+               if (G.scene->r.mode & R_FIXED_THREADS) {
+                       ps->thread_tot = G.scene->r.threads;
+               } else {
+                       ps->thread_tot = BLI_system_thread_count();
+               }
        }
-       
        for (a=0; a<ps->thread_tot; a++) {
                ps->arena_mt[a] = BLI_memarena_new(1<<16);
        }
@@ -2207,48 +2301,7 @@
        Mat3MulVecfl(mat, ps->viewDir);
        Mat3CpyMat4(mat, ps->ob->imat);
        Mat3MulVecfl(mat, ps->viewDir);
-       
-       /* calculate vert screen coords */
-       ps->screenCoords = BLI_memarena_alloc( ps->arena, sizeof(float) * 
ps->dm_totvert * 4);
-       projScreenCo = ps->screenCoords;
-       
-       /* TODO - check cameras mode too */
-       if (G.vd->persp == V3D_ORTHO) {
-               ps->is_ortho = 1;
-       }
-       
-       INIT_MINMAX2(ps->screen_min, ps->screen_max);
 
-       if (ps->is_ortho) {
-               for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
-                       VECCOPY((*projScreenCo), ps->dm_mvert[a].co);
-                       Mat4MulVecfl(ps->projectMat, (*projScreenCo));
-
-                       /* screen space, not clamped */
-                       (*projScreenCo)[0] = 
(float)(curarea->winx/2.0)+(curarea->winx/2.0)*(*projScreenCo)[0];
-                       (*projScreenCo)[1] = 
(float)(curarea->winy/2.0)+(curarea->winy/2.0)*(*projScreenCo)[1];
-                       DO_MINMAX2((*projScreenCo), ps->screen_min, 
ps->screen_max);
-               }
-       } else {
-               for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
-                       VECCOPY((*projScreenCo), ps->dm_mvert[a].co);
-                       (*projScreenCo)[3] = 1.0;
-
-                       Mat4MulVec4fl(ps->projectMat, (*projScreenCo));
-
-                       if( (*projScreenCo)[3] > 0.001 ) {
-                               /* screen space, not clamped */
-                               (*projScreenCo)[0] = 
(float)(curarea->winx/2.0)+(curarea->winx/2.0)*(*projScreenCo)[0]/(*projScreenCo)[3];
-                               (*projScreenCo)[1] = 
(float)(curarea->winy/2.0)+(curarea->winy/2.0)*(*projScreenCo)[1]/(*projScreenCo)[3];
-                               (*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 ? */
-                               (*projScreenCo)[0] = MAXFLOAT;
-                       }
-               }
-       }
-
        /* setup clone offset */
        if (ps->tool == PAINT_TOOL_CLONE) {
                float projCo[4];
@@ -2265,21 +2318,6 @@
                
        }
        
-       /* If this border is not added we get artifacts for faces that
-        * have a paralelle edge and at the bounds of the the 2D projected 
verts eg
-        * - a simgle screen aligned quad */
-       projMargin = (ps->screen_max[0] - ps->screen_min[0]) * 0.000001;
-       ps->screen_max[0] += projMargin;
-       ps->screen_min[0] -= projMargin;
-       projMargin = (ps->screen_max[1] - ps->screen_min[1]) * 0.000001;
-       ps->screen_max[1] += projMargin;
-       ps->screen_min[1] -= projMargin;
-       
-       
-       /* only for convenience */
-       ps->screen_width  = ps->screen_max[0] - ps->screen_min[0];
-       ps->screen_height = ps->screen_max[1] - ps->screen_min[1];
-       
        if (!ps->is_ortho) {
                /* get the view direction relative to the objects matrix */
                float imat[3][3];
@@ -2448,6 +2486,7 @@
        }
        /* done calculating undo data */
        
+       MEM_freeN(ps->screenCoords);
        
        BLI_memarena_free(ps->arena);
        
@@ -3004,16 +3043,21 @@
        return redraw;
 }
 
+/* run this per painting onto each mouse location */
 static int bucket_iter_init(ProjectPaintState *ps, float mval_f[2])
 {
        float min_brush[2], max_brush[2];
+       float size_half = ((float)ps->brush->size)/2.0;
        
-       min_brush[0] = mval_f[0] - (ps->brush->size/2);
-       min_brush[1] = mval_f[1] - (ps->brush->size/2);
+       /* so we dont have a bucket bounds that is way too small to paint into 
*/
+       // if (size_half < 1.0) size_half = 1.0; // this dosnt work yet :/
        
-       max_brush[0] = mval_f[0] + (ps->brush->size/2);
-       max_brush[1] = mval_f[1] + (ps->brush->size/2);
+       min_brush[0] = mval_f[0] - size_half;
+       min_brush[1] = mval_f[1] - size_half;
        
+       max_brush[0] = mval_f[0] + size_half;
+       max_brush[1] = mval_f[1] + size_half;
+       
        /* offset to make this a valid bucket index */
        project_paint_rect(ps, min_brush, max_brush, ps->bucket_min, 
ps->bucket_max);
        
@@ -3030,7 +3074,7 @@
        return 1;
 }
 
-static int bucket_iter_next(ProjectPaintState *ps, int *bucket_index, float 
bucket_bounds[4], float mval_f[2])
+static int bucket_iter_next(ProjectPaintState *ps, int *bucket_index, float 
bucket_bounds[4], float mval[2])
 {
        if (ps->thread_tot > 1)
                BLI_lock_thread(LOCK_CUSTOM1);
@@ -3043,7 +3087,7 @@
                        /* use bucket_bounds for project_bucket_circle_isect 
and project_paint_bucket_init*/
                        project_bucket_bounds(ps, ps->context_bucket_x, 
ps->context_bucket_y, bucket_bounds);
                        
-                       if (project_bucket_circle_isect(ps, 
ps->context_bucket_x, ps->context_bucket_y, mval_f, ps->brush->size * 
ps->brush->size, bucket_bounds)) {
+                       if (project_bucket_circle_isect(ps, 
ps->context_bucket_x, ps->context_bucket_y, mval, ps->brush->size * 
ps->brush->size, bucket_bounds)) {
                                *bucket_index = ps->context_bucket_x + 
(ps->context_bucket_y * ps->buckets_x);

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to