Revision: 17496
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17496
Author:   campbellbarton
Date:     2008-11-18 14:51:51 +0100 (Tue, 18 Nov 2008)

Log Message:
-----------
Some improvements brecht suggested, only noticable change is faster 
multithreading

General optimizations
* Precompute 1/x when dividing by x multiple times.
* Use float constants like 0.0f instead of 0.0, avoids conversions from float 
to doubles and back.

ProjectPixel
* make pixel (and similar pointers elsewhere) a union with a float and unsigned 
int pointer to reduce the number of casts a little. generally there are a lot 
of casts going on in the code, makes it hard to read.

project_paint_begin()
* the perspective case checks with (*projScreenCo)[3] > 0.001) for faces behind 
the view. - Changed to use the clip start from get_view3d_viewplane 
* removed arbitrary check for brush size to disable threads.

imapaint_paint_sub_stroke_project()
* Make clone tool use IMB_blend_color to reduce the code and support blend 
modes.

imapaint_paint_sub_stroke_project_mt()
* Make threaded and non threaded mode use same function (just dont start 
threads when its set to 1)
* removed PIL_sleep_ms, was not needed and slowed down threading (my bad!, was 
copied from bake code).

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-18 
13:51:02 UTC (rev 17495)
+++ branches/projection-paint/source/blender/src/imagepaint.c   2008-11-18 
13:51:51 UTC (rev 17496)
@@ -148,7 +148,7 @@
  * 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_BRUSH_DIV 4
 
 #define PROJ_BUCKET_RECT_MIN 4
 #define PROJ_BUCKET_RECT_MAX 256
@@ -187,16 +187,16 @@
 /* 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 {
+typedef struct ProjPaintImage {
        Image *ima;
        ImBuf *ibuf;
        ImagePaintPartialRedraw *partRedrawRect;
        struct UndoTile **undoRect; /* only used to build undo tiles after 
painting */
        int touch;
-} ProjectPaintImage;
+} ProjPaintImage;
 
 /* Main projection painting struct passed to all projection painting functions 
*/
-typedef struct ProjectPaintState {
+typedef struct ProjPaintState {
        Brush *brush;
        short tool, blend;
        Object *ob;
@@ -214,7 +214,7 @@
        /* projection painting only */
        MemArena *arena;                        /* use for alocating many pixel 
structs and link-lists */
        MemArena *arena_mt[BLENDER_MAX_THREADS];                /* Same as 
above but use for multithreading */
-       LinkNode **bucketRect;                          /* screen sized 2D 
array, each pixel has a linked list of ProjectPixel's */
+       LinkNode **bucketRect;                          /* screen sized 2D 
array, each pixel has a linked list of ProjPixel's */
        LinkNode **bucketFaces;                         /* bucketRect alligned 
array linkList of faces overlapping each bucket */
        char *bucketFlags;                                      /* store if the 
bucks have been initialized  */
 #ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -225,7 +225,7 @@
        int buckets_x;                                          /* The size of 
the bucket grid, the grid span's screen_min/screen_max so you can paint outsize 
the screen or with 2 brushes at once */
        int buckets_y;
        
-       ProjectPaintImage *projImages;
+       ProjPaintImage *projImages;
        
        int image_tot;                          /* size of projectImages array 
*/
        
@@ -256,26 +256,41 @@
        int bucket_min[2];
        int bucket_max[2];
        int context_bucket_x, context_bucket_y; /* must lock threads while 
accessing these */
-} ProjectPaintState;
+} ProjPaintState;
 
-typedef struct ProjectPixel {
+typedef union pixelPointer
+{
+       float *f_pt;                    /* float buffer */
+       unsigned int *uint_pt; /* 2 ways to access a char buffer */
+       char *ch_pt;
+} PixelPointer;
+
+typedef union pixelStore
+{
+       char ch[4];
+       int uint;
+} PixelStore;
+
+typedef struct ProjPixel {
        float projCo2D[2]; /* the floating point screen projection of this 
pixel */
-       char origColor[4];
        short x_px, y_px;
-       void *pixel;
+       
+       PixelStore origColor;
+       PixelPointer pixel;
+       
        short image_index; /* if anyone wants to paint onto more then 32000 
images they can bite me */
        short bb_cell_index;
-} ProjectPixel;
+} ProjPixel;
 
-typedef struct ProjectPixelClone {
-       struct ProjectPixel __pp;
-       char clonepx[4];
-} ProjectPixelClone;
+typedef struct ProjPixelClone {
+       struct ProjPixel __pp;
+       PixelStore clonepx;
+} ProjPixelClone;
 
-typedef struct ProjectPixelCloneFloat {
-       struct ProjectPixel __pp;
-       float clonepx[4];
-} ProjectPixelCloneFloat;
+typedef struct ProjPixelCloneFloat {
+       struct ProjPixel __pp;
+       float clonepx_f[4];
+} ProjPixelCloneFloat;
 
 /* Finish projection painting structs */
 
@@ -459,7 +474,7 @@
 }
 
 /* fast projection bucket array lookup, use the safe version for bound 
checking  */
-static int project_paint_BucketOffset(ProjectPaintState *ps, float projCo2D[2])
+static int project_paint_BucketOffset(ProjPaintState *ps, float projCo2D[2])
 {
        /* If we were not dealing with screenspace 2D coords we could simple 
do...
         * ps->bucketRect[x + (y*ps->buckets_y)] */
@@ -475,7 +490,7 @@
                (       (       (int)(( (projCo2D[1] - ps->screen_min[1])  / 
ps->screen_height) * ps->buckets_y)) * ps->buckets_x );
 }
 
-static int project_paint_BucketOffsetSafe(ProjectPaintState *ps, float 
projCo2D[2])
+static int project_paint_BucketOffsetSafe(ProjPaintState *ps, float 
projCo2D[2])
 {
        int bucket_index = project_paint_BucketOffset(ps, projCo2D);
        
@@ -488,15 +503,16 @@
 
 /* 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]) {
-       float wtot;
+       float wtot, wtot_inv;
        w[0] = AreaF2Dfl(v2, v3, pt);
        w[1] = AreaF2Dfl(v3, v1, pt);
        w[2] = AreaF2Dfl(v1, v2, pt);
        wtot = w[0]+w[1]+w[2];
-       if (wtot > 0.0) { /* just incase */
-               w[0]/=wtot;
-               w[1]/=wtot;
-               w[2]/=wtot;
+       if (wtot > 0.0f) { /* just incase */
+               wtot_inv = 1.0f / wtot; 
+               w[0]*=wtot_inv;
+               w[1]*=wtot_inv;
+               w[2]*=wtot_inv;
        } else {
                w[0] = w[1] = w[2] = 1.0/3.0; /* dummy values for zero area 
face */
        }
@@ -505,30 +521,31 @@
 /* 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]) {
-       float wtot = AreaF2Dfl(v1, v2, v3);
+       float wtot_inv, wtot = AreaF2Dfl(v1, v2, v3);
        if (wtot > 0.0) {
+               wtot_inv = 1.0f / wtot;
                w[0] = AreaF2Dfl(v2, v3, pt);
                w[1] = AreaF2Dfl(v3, v1, pt);
                w[2] = AreaF2Dfl(v1, v2, pt);
                
                /* negate weights when 'pt' is on the outer side of the the 
triangles edge */
-               if ((SIDE_OF_LINE(v2,v3, pt)>0.0) != (SIDE_OF_LINE(v2,v3, 
v1)>0.0))     w[0]/= -wtot;
-               else                                                            
                                                                w[0]/=  wtot;
+               if ((SIDE_OF_LINE(v2,v3, pt)>0.0) != (SIDE_OF_LINE(v2,v3, 
v1)>0.0))     w[0]*= -wtot_inv;
+               else                                                            
                                                                w[0]*=  
wtot_inv;
 
-               if ((SIDE_OF_LINE(v3,v1, pt)>0.0) != (SIDE_OF_LINE(v3,v1, 
v2)>0.0))     w[1]/= -wtot;
-               else                                                            
                                                                w[1]/=  wtot;
+               if ((SIDE_OF_LINE(v3,v1, pt)>0.0) != (SIDE_OF_LINE(v3,v1, 
v2)>0.0))     w[1]*= -wtot_inv;
+               else                                                            
                                                                w[1]*=  
wtot_inv;
 
-               if ((SIDE_OF_LINE(v1,v2, pt)>0.0) != (SIDE_OF_LINE(v1,v2, 
v3)>0.0))     w[2]/= -wtot;
-               else                                                            
                                                                w[2]/=  wtot;
+               if ((SIDE_OF_LINE(v1,v2, pt)>0.0) != (SIDE_OF_LINE(v1,v2, 
v3)>0.0))     w[2]*= -wtot_inv;
+               else                                                            
                                                                w[2]*=  
wtot_inv;
        } else {
-               w[0] = w[1] = w[2] = 1.0/3.0; /* dummy values for zero area 
face */
+               w[0] = w[1] = w[2] = 1.0f/3.0f; /* dummy values for zero area 
face */
        }
 }
 
 /* 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;
+       float persp_tot, persp_tot_inv;
        BarycentricWeights2f(v1,v2,v3,pt,w);
        
        w[0] /= v1[3];
@@ -536,14 +553,19 @@
        w[2] /= v3[3];
        
        persp_tot = w[0]+w[1]+w[2];
-       
-       w[0] /= persp_tot;
-       w[1] /= persp_tot;
-       w[2] /= persp_tot;
+       if (persp_tot > 0.0f) {
+               persp_tot_inv = 1.0f / persp_tot;
+               w[0] *= persp_tot_inv;
+               w[1] *= persp_tot_inv;
+               w[2] *= persp_tot_inv;
+       } else {
+               w[0] = w[1] = w[2] = 1.0f/3.0f; /* dummy values for zero area 
face */
+       }
 }
 
-static void BarycentricWeightsSimplePersp2f(float v1[4], float v2[4], float 
v3[4], float pt[2], float w[3]) {
-       float persp_tot;
+static void BarycentricWeightsSimplePersp2f(float v1[4], float v2[4], float 
v3[4], float pt[2], float w[3])
+{
+       float persp_tot_inv, persp_tot;
        BarycentricWeightsSimple2f(v1,v2,v3,pt,w);
        
        w[0] /= v1[3];
@@ -551,10 +573,14 @@
        w[2] /= v3[3];
        
        persp_tot = w[0]+w[1]+w[2];
-       
-       w[0] /= persp_tot;
-       w[1] /= persp_tot;
-       w[2] /= persp_tot;
+       if (persp_tot > 0.0f) {
+               persp_tot_inv = 1.0f / persp_tot;
+               w[0] *= persp_tot_inv;
+               w[1] *= persp_tot_inv;
+               w[2] *= persp_tot_inv;
+       } else {
+               w[0] = w[1] = w[2] = 1.0f/3.0f; /* dummy values for zero area 
face */
+       }
 }
 
 static float tri_depth_2d(float v1[3], float v2[3], float v3[3], float pt[2], 
float w[3])
@@ -565,7 +591,7 @@
 
 
 /* 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) {
+static int project_paint_PickFace(ProjPaintState *ps, float pt[2], float w[3], 
int *side) {
        LinkNode *node;
        float w_tmp[3];
        float *v1, *v2, *v3, *v4;
@@ -713,7 +739,7 @@
 }
 
 /* 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)
+static int project_paint_PickColor(ProjPaintState *ps, float pt[2], float 
*rgba_fp, char *rgba, int interp)
 {
        float w[3], uv[2];
        int side;
@@ -745,14 +771,14 @@
        if (interp) {
                float x,y;
                /* use */
-               x = (float)fmod(uv[0], 1.0);
-               y = (float)fmod(uv[1], 1.0);
+               x = (float)fmod(uv[0], 1.0f);
+               y = (float)fmod(uv[1], 1.0f);
                
-               if (x < 0.0) x += 1.0;
-               if (y < 0.0) y += 1.0;
+               if (x < 0.0f) x += 1.0f;
+               if (y < 0.0f) y += 1.0f;
                
-               x = x * ibuf->x - 0.5;
-               y = y * ibuf->y - 0.5;
+               x = x * ibuf->x - 0.5f;
+               y = y * ibuf->y - 0.5f;
                
                if (ibuf->rect_float) {
                        if (rgba_fp) {
@@ -772,8 +798,8 @@
                        }
                }
        } else {
-               xi = (uv[0]*ibuf->x) + 0.5;
-               yi = (uv[1]*ibuf->y) + 0.5;
+               xi = (uv[0]*ibuf->x) + 0.5f;
+               yi = (uv[1]*ibuf->y) + 0.5f;
                
                //if (xi<0 || xi>=ibuf->x  ||  yi<0 || yi>=ibuf->y) return 0;
                
@@ -838,7 +864,7 @@
 /* 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])
+static int project_bucket_point_occluded(ProjPaintState *ps, int bucket_index, 
int orig_face, float pixelScreenCo[4])
 {
        LinkNode *node = ps->bucketFaces[bucket_index];
        MFace *mf;
@@ -934,7 +960,7 @@
 /* simple func use for comparing UV locations to check if there are seams */
 static int cmp_uv(float vec2a[2], float vec2b[2])
 {
-       return ((fabs(vec2a[0]-vec2b[0]) < 0.0001) && (fabs(vec2a[1]-vec2b[1]) 
< 0.0001)) ? 1:0;
+       return ((fabs(vec2a[0]-vec2b[0]) < 0.0001f) && (fabs(vec2a[1]-vec2b[1]) 
< 0.0001f)) ? 1:0;
 }
 
 
@@ -968,7 +994,7 @@
 

@@ 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