Revision: 17526 http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17526 Author: campbellbarton Date: 2008-11-21 04:09:48 +0100 (Fri, 21 Nov 2008)
Log Message: ----------- * added option "Normal", same as the vpaint option, gives more natural looking brush strokes. * faces that were ignored were also not taken into acount when checking UV seams - causng bleed not to work properly in some cases. * commented early pixel filling loop exit that fails in some cases. 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-21 02:23:46 UTC (rev 17525) +++ branches/projection-paint/source/blender/makesdna/DNA_scene_types.h 2008-11-21 03:09:48 UTC (rev 17526) @@ -803,10 +803,11 @@ #define IMAGEPAINT_DRAW_TOOL_DRAWING 4 /* projection painting only */ -#define IMAGEPAINT_PROJECT_XRAY 8 -#define IMAGEPAINT_PROJECT_BACKFACE 16 +#define IMAGEPAINT_PROJECT_XRAY 8 +#define IMAGEPAINT_PROJECT_BACKFACE 16 #define IMAGEPAINT_PROJECT_IGNORE_SEAMS 32 #define IMAGEPAINT_PROJECT_CLONE_LAYER 64 +#define IMAGEPAINT_PROJECT_FLAT 128 /* toolsettings->uvcalc_flag */ #define UVCALC_FILLHOLES 1 Modified: branches/projection-paint/source/blender/src/buttons_editing.c =================================================================== --- branches/projection-paint/source/blender/src/buttons_editing.c 2008-11-21 02:23:46 UTC (rev 17525) +++ branches/projection-paint/source/blender/src/buttons_editing.c 2008-11-21 03:09:48 UTC (rev 17526) @@ -6373,7 +6373,9 @@ /* Projection Painting */ uiBlockBeginAlign(block); uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_XRAY, B_NOP, "Occlude", xco+10,yco-70,butw,19, &settings->imapaint.flag, 0, 0, 0, 0, "Only paint onto the faces directly under the brush (slower)"); - uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_BACKFACE, B_NOP, "Backface Cull", xco+10,yco-90,butw,19, &settings->imapaint.flag, 0, 0, 0, 0, "Ignore faces pointing away from the view (faster)"); + uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_BACKFACE, B_NOP, "Cull", xco+10,yco-90,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Ignore faces pointing away from the view (faster)"); + uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_FLAT, B_NOP, "Normal", xco+10+butw/2,yco-90,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Ignore faces pointing away from the view (faster)"); + uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_IGNORE_SEAMS, B_NOP, "Bleed", xco+10,yco-110,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Extend paint beyond the faces UVs to reduce seams (in pixels, slower)"); uiDefButF(block, NUM, B_NOP, "", xco+10 + (butw/2),yco-110,butw/2,19, &settings->imapaint.seam_bleed, 2.0, 8.0, 0, 0, "Extend paint beyond the faces UVs to reduce seams (in pixels, slower)"); uiBlockEndAlign(block); Modified: branches/projection-paint/source/blender/src/imagepaint.c =================================================================== --- branches/projection-paint/source/blender/src/imagepaint.c 2008-11-21 02:23:46 UTC (rev 17525) +++ branches/projection-paint/source/blender/src/imagepaint.c 2008-11-21 03:09:48 UTC (rev 17526) @@ -178,6 +178,9 @@ #define PROJ_BUCKET_INIT 1<<0 // #define PROJ_BUCKET_CLONE_INIT 1<<1 +/* vert flags */ +#define PROJ_VERT_CULL 1 + /* only for readability */ #define PROJ_BUCKET_LEFT 0 #define PROJ_BUCKET_RIGHT 1 @@ -221,6 +224,7 @@ char *faceSeamFlags; /* store info about faces, if they are initialized etc*/ float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */ LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */ + char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */ #endif 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; @@ -235,6 +239,7 @@ short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/ short do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */ short is_ortho; + short do_mask_normal; /* mask out pixels based on their normals */ #ifndef PROJ_DEBUG_NOSEAMBLEED float seam_bleed_px; #endif @@ -245,6 +250,7 @@ float projectMat[4][4]; /* Projection matrix, use for getting screen coords */ float viewMat[4][4]; float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */ + float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */ float screen_min[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */ float screen_max[2]; @@ -278,8 +284,10 @@ 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; + float mask; /* for various reasons we may want to mask out painting onto this pixel */ + + short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */ + unsigned char bb_cell_index; } ProjPixel; typedef struct ProjPixelClone { @@ -583,6 +591,19 @@ } } +static VecWeightf(float p[3], float v1[3], float v2[3], float v3[3], float w[3]) +{ + p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2]; + p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2]; + p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2]; +} + +static Vec2Weightf(float p[3], float v1[3], float v2[3], float v3[3], float w[3]) +{ + p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2]; + p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2]; +} + 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); @@ -666,12 +687,10 @@ tf = ps->dm_mtface + face_index; - if (side==0) { - uv[0] = tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[2][0]*w[2]; - uv[1] = tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[2][1]*w[2]; + if (side == 0) { + Vec2Weightf(uv, tf->uv[0], tf->uv[1], tf->uv[2], w); } else { /* QUAD */ - uv[0] = tf->uv[0][0]*w[0] + tf->uv[2][0]*w[1] + tf->uv[3][0]*w[2]; - uv[1] = tf->uv[0][1]*w[0] + tf->uv[2][1]*w[1] + tf->uv[3][1]*w[2]; + Vec2Weightf(uv, tf->uv[0], tf->uv[2], tf->uv[3], w); } ibuf = BKE_image_get_ibuf((Image *)tf->tpage, NULL); /* TODO - this may be slow */ @@ -774,9 +793,8 @@ /* 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(ProjPaintState *ps, int bucket_index, int orig_face, float pixelScreenCo[4]) +static int project_bucket_point_occluded(ProjPaintState *ps, LinkNode *bucketFace, int orig_face, float pixelScreenCo[4]) { - LinkNode *node = ps->bucketFaces[bucket_index]; MFace *mf; int face_index; int isect_ret; @@ -784,8 +802,8 @@ /* we could return 0 for 1 face buckets, as long as this function assumes * that the point its testing is only every originated from an existing face */ - while (node) { - face_index = (int)node->link; + while (bucketFace) { + face_index = (int)bucketFace->link; if (orig_face != face_index) { @@ -812,7 +830,7 @@ return 1; } } - node = node->next; + bucketFace = bucketFace->next; } return 0; @@ -1151,20 +1169,19 @@ float w[3]) { 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]; + VecWeightf(pixelScreenCo, v1co, v2co, v3co, w); } /* same as screen_px_from_ortho except we need to take into account * the perspective W coord for each vert */ static void screen_px_from_persp( ProjPaintState *ps, float uv[2], - float v1co[3], float v2co[3], float v3co[3], /* Worldspace coords */ + float v1co[3], float v2co[3], float v3co[3], /* screenspace coords */ float uv1co[2], float uv2co[2], float uv3co[2], float pixelScreenCo[4], float w[3]) { + float wtot_inv, wtot; BarycentricWeightsSimple2f(uv1co,uv2co,uv3co,uv,w); @@ -1185,149 +1202,230 @@ } /* done re-weighting */ + VecWeightf(pixelScreenCo, v1co, v2co, v3co, w); +} + +#if 0 +static void screen_px_from_persp( + ProjPaintState *ps, float uv[2], + float v1co[3], float v2co[3], float v3co[3], /* Worldspace coords */ + float uv1co[2], float uv2co[2], float uv3co[2], + float pixelScreenCo[4], + float w[3]) +{ + 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]; + pixelScreenCo[2] = v1co[2]*w[0] + v2co[2]*w[1] + v3co[2]*w[2]; + pixelScreenCo[3] = 1.0; + + Mat4MulVec4fl(ps->projectMat, pixelScreenCo); + + // if( pixelScreenCo[3] > 0.001 ) { ??? TODO + /* screen space, not clamped */ + pixelScreenCo[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*pixelScreenCo[0]/pixelScreenCo[3]; + pixelScreenCo[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*pixelScreenCo[1]/pixelScreenCo[3]; + pixelScreenCo[2] = pixelScreenCo[2]/pixelScreenCo[3]; /* Use the depth for bucket point occlusion */ } +#endif /* Only run this function once for new ProjPixelClone's */ #define IMA_CHAR_PX_SIZE 4 -/* run this function when we know a bucket's, face's pixel can be initialized, - * adding to the LinkList 'ps->bucketRect' */ -static void project_paint_uvpixel_init(ProjPaintState *ps, int thread_index, ImBuf *ibuf, short x, short y, int bucket_index, int face_index, int image_index, float pixelScreenCo[4], int side, float w[3]) -{ - ProjPixel *projPixel; - short size; - - // printf("adding px (%d %d), (%f %f)\n", x,y,uv[0],uv[1]); - - - /* Use screen_min 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 */ - /* project_paint_PickFace is less complex, use for testing */ - //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == face_index) { - if (ps->do_occlude==0 || !project_bucket_point_occluded(ps, bucket_index, face_index, pixelScreenCo)) { + +/* run this outside project_paint_uvpixel_init since pixels with mask 0 dont need init */ +float project_paint_uvpixel_mask( + ProjPaintState *ps, + int face_index, + int side, + float w[3] +) { + float mask; + /* calculate mask */ + if (ps->do_mask_normal) { @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs