* Patch from Michael Fox to set the normal angle (was fixed at 80 before)

* Fixed another face clipping bug (some artifacts still when using screen aligned faces)
* Removed Soften and Warp buttons on the panit panel since they are not used for projection painting
* added do_versions to initialize bleed and normal values
This commit is contained in:
Campbell Barton 2008-12-06 13:42:55 +00:00
parent 5a5ae824ce
commit 2b7098820d
5 changed files with 69 additions and 50 deletions

@ -41,7 +41,7 @@ struct ListBase;
struct MemFile; struct MemFile;
#define BLENDER_VERSION 248 #define BLENDER_VERSION 248
#define BLENDER_SUBVERSION 1 #define BLENDER_SUBVERSION 2
#define BLENDER_MINVERSION 245 #define BLENDER_MINVERSION 245
#define BLENDER_MINSUBVERSION 15 #define BLENDER_MINSUBVERSION 15

@ -8007,6 +8007,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
} }
} }
if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 2)) {
Scene *sce;
/* Note, these will need to be added for painting */
for (sce= main->scene.first; sce; sce= sce->id.next) {
sce->toolsettings->imapaint.seam_bleed = 2;
sce->toolsettings->imapaint.normal_angle = 80;
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */

@ -347,8 +347,8 @@ typedef struct ImagePaintSettings {
short flag, tool; short flag, tool;
/* for projection painting only - todo - use flags */ /* for projection painting only - todo - use flags */
float seam_bleed; char seam_bleed,normal_angle;
int clone_layer, pad; short clone_layer;
} ImagePaintSettings; } ImagePaintSettings;
typedef struct ParticleBrushData { typedef struct ParticleBrushData {
@ -805,9 +805,8 @@ typedef struct Scene {
/* projection painting only */ /* projection painting only */
#define IMAGEPAINT_PROJECT_XRAY 8 #define IMAGEPAINT_PROJECT_XRAY 8
#define IMAGEPAINT_PROJECT_BACKFACE 16 #define IMAGEPAINT_PROJECT_BACKFACE 16
#define IMAGEPAINT_PROJECT_IGNORE_SEAMS 32 #define IMAGEPAINT_PROJECT_CLONE_LAYER 32
#define IMAGEPAINT_PROJECT_CLONE_LAYER 64 #define IMAGEPAINT_PROJECT_FLAT 64
#define IMAGEPAINT_PROJECT_FLAT 128
/* toolsettings->uvcalc_flag */ /* toolsettings->uvcalc_flag */
#define UVCALC_FILLHOLES 1 #define UVCALC_FILLHOLES 1

@ -6341,10 +6341,10 @@ static void editing_panel_mesh_paint(void)
//uiDefButS(block, ROW, B_BRUSHCHANGE, "Soften", 108 ,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush"); //uiDefButS(block, ROW, B_BRUSHCHANGE, "Soften", 108 ,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
//uiDefButS(block, ROW, B_BRUSHCHANGE, "Smear", 214,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush"); //uiDefButS(block, ROW, B_BRUSHCHANGE, "Smear", 214,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Draw", 0 ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush"); uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Draw", 0 ,yco,108,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Soften", 80 ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush"); //uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Soften", 80 ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Smear", 160,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush"); uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Smear", 108 ,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Clone", 240,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image"); uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Clone", 214,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image");
uiBlockEndAlign(block); uiBlockEndAlign(block);
yco -= 30; yco -= 30;
@ -6361,23 +6361,24 @@ static void editing_panel_mesh_paint(void)
uiDefButS(block, MENU, B_NOP, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes"); uiDefButS(block, MENU, B_NOP, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes");
uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, B_BRUSHCHANGE, "Wrap", xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping"); // uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, B_BRUSHCHANGE, "Wrap", xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping");
uiBlockBeginAlign(block); uiBlockBeginAlign(block);
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)"); uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, B_BRUSHCHANGE, "Airbrush", xco+10,yco-25,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"); uiDefButF(block, NUM, B_NOP, "Rate ", xco+10,yco-45,butw,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush");
uiBlockEndAlign(block); uiBlockEndAlign(block);
yco -= 25; yco -= 25;
/* Projection Painting */ /* Projection Painting */
uiBlockBeginAlign(block); 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_XRAY, B_NOP, "Occlude", xco+10,yco-45,butw/2,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, "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_BACKFACE, B_NOP, "Cull", xco+10+butw/2,yco-45,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, "Paint most on faces pointing towards teh view");
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)"); uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_FLAT, B_NOP, "Normal", xco+10,yco-65,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Paint most on faces pointing towards the view");
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)"); uiDefButC(block, NUM, B_NOP, "", xco+10 +(butw/2),yco-65,butw/2,19, &settings->imapaint.normal_angle, 10.0, 90.0, 0, 0, "Paint most on faces pointing towards the view acording to this angle)");
uiDefButC(block, NUM, B_NOP, "Bleed: ", xco+10,yco-85,butw,19, &settings->imapaint.seam_bleed, 0.0, 8.0, 0, 0, "Extend paint beyond the faces UVs to reduce seams (in pixels, slower)");
uiBlockEndAlign(block); uiBlockEndAlign(block);
uiBlockBeginAlign(block); uiBlockBeginAlign(block);

@ -159,6 +159,7 @@ typedef struct ImagePaintPartialRedraw {
//#define PROJ_DEBUG_PAINT 1 //#define PROJ_DEBUG_PAINT 1
//#define PROJ_DEBUG_NOSEAMBLEED 1 //#define PROJ_DEBUG_NOSEAMBLEED 1
//#define PROJ_DEBUG_PRINT_CLIP 1
#define PROJ_DEBUG_WINCLIP 1 #define PROJ_DEBUG_WINCLIP 1
/* projectFaceSeamFlags options */ /* projectFaceSeamFlags options */
@ -186,7 +187,6 @@ typedef struct ImagePaintPartialRedraw {
/* vert flags */ /* vert flags */
#define PROJ_VERT_CULL 1 #define PROJ_VERT_CULL 1
/* M_PI_2 is 90d, we want 80 though */
#define PI_80_DEG ((M_PI_2 / 9) * 8) #define PI_80_DEG ((M_PI_2 / 9) * 8)
/* This is mainly a convenience struct used so we can keep an array of images we use /* This is mainly a convenience struct used so we can keep an array of images we use
@ -245,6 +245,8 @@ typedef struct ProjPaintState {
short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/ 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 do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
short do_mask_normal; /* mask out pixels based on their normals */ short do_mask_normal; /* mask out pixels based on their normals */
float normal_angle; /* what angle to mask at*/
short is_ortho; short is_ortho;
short is_airbrush; /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */ short is_airbrush; /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */
short is_texbrush; /* only to avoid running */ short is_texbrush; /* only to avoid running */
@ -1293,7 +1295,7 @@ float project_paint_uvpixel_mask(
const int side, const int side,
const float w[3]) const float w[3])
{ {
float mask; float mask, mask_angle;
/* calculate mask */ /* calculate mask */
if (ps->do_mask_normal) { if (ps->do_mask_normal) {
@ -1340,22 +1342,28 @@ float project_paint_uvpixel_mask(
angle = NormalizedVecAngle2(viewDirPersp, no); angle = NormalizedVecAngle2(viewDirPersp, no);
} }
if (angle >= PI_80_DEG) { /*if (angle >= (M_PI_2 / 90) * ps->normal_angle) {
return 0.0f; return 0.0f;
} }
else { else {*/
#if 0 #if 0
mask = 1.0f - (angle / PI_80_DEG); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */ mask = 1.0f - (angle / PI_80_DEG); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */
#endif #endif
/* trickier method that clips the normal so its more useful */ /* trickier method that clips the normal so its more useful */
mask = (angle / PI_80_DEG); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */ /* M_PI_2 is 90d, we want 80 though */
mask_angle = ((M_PI_2 / 90) * ps->normal_angle);
/*printf("normal_angle : %f \n" ,ps->normal_angle);
printf("mask_angle : %f \n" ,mask_angle);*/
mask = (angle / mask_angle); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */
mask = (1.0f - (mask * mask * mask)) * 1.4f; mask = (1.0f - (mask * mask * mask)) * 1.4f;
if (mask > 1.0f) { if (mask > 1.0f) {
mask = 1.0f; mask = 1.0f;
} }
/*}*/
} }
}
else { else {
mask = 1.0f; mask = 1.0f;
} }
@ -1548,7 +1556,7 @@ static int line_clip_rect2f(
} }
/* top/bottom */ /* top/bottom */
if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect > rect->xmin) && (isect < rect->xmax)) { if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
if (l1[1] < l2[1]) { /* line 1 is outside */ if (l1[1] < l2[1]) { /* line 1 is outside */
l1_clip[0] = isect; l1_clip[0] = isect;
l1_clip[1] = rect->ymin; l1_clip[1] = rect->ymin;
@ -1560,7 +1568,7 @@ static int line_clip_rect2f(
ok2 = 2; ok2 = 2;
} }
} }
if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect > rect->xmin) && (isect < rect->xmax)) { if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
if (l1[1] > l2[1]) { /* line 1 is outside */ if (l1[1] > l2[1]) { /* line 1 is outside */
l1_clip[0] = isect; l1_clip[0] = isect;
l1_clip[1] = rect->ymax; l1_clip[1] = rect->ymax;
@ -1574,7 +1582,7 @@ static int line_clip_rect2f(
} }
/* left/right */ /* left/right */
if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect > rect->ymin) && (isect < rect->ymax)) { if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
if (l1[0] < l2[0]) { /* line 1 is outside */ if (l1[0] < l2[0]) { /* line 1 is outside */
l1_clip[0] = rect->xmin; l1_clip[0] = rect->xmin;
l1_clip[1] = isect; l1_clip[1] = isect;
@ -1586,7 +1594,7 @@ static int line_clip_rect2f(
ok2 = 2; ok2 = 2;
} }
} }
if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect > rect->ymin) && (isect < rect->ymax)) { if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
if (l1[0] > l2[0]) { /* line 1 is outside */ if (l1[0] > l2[0]) { /* line 1 is outside */
l1_clip[0] = rect->xmax; l1_clip[0] = rect->xmax;
l1_clip[1] = isect; l1_clip[1] = isect;
@ -1963,7 +1971,8 @@ static void project_bucket_clip_face(
float cent[2] = {0.0f, 0.0f}; float cent[2] = {0.0f, 0.0f};
/*float up[2] = {0.0f, 1.0f};*/ /*float up[2] = {0.0f, 1.0f};*/
float tmp_f; float tmp_f;
int i, unsorted; int i;
short unsorted, doubles;
(*tot) = 0; (*tot) = 0;
@ -2059,24 +2068,29 @@ static void project_bucket_clip_face(
} }
/* remove doubles */ /* remove doubles */
/* first/last check */ /* first/last check */
if (fabs(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < ISECT_TOLERANCE && fabs(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < ISECT_TOLERANCE) { if (fabs(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < ISECT_TOLERANCE && fabs(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < ISECT_TOLERANCE) {
(*tot)--; (*tot)--;
} }
unsorted = TRUE; /* its possible there is only a few left after remove doubles */
while (unsorted==TRUE) { if ((*tot) < 3) {
unsorted = FALSE; // printf("removed too many doubles A\n");
*tot = 0;
return;
}
doubles = TRUE;
while (doubles==TRUE) {
doubles = FALSE;
for(i=1; i<(*tot); i++) { for(i=1; i<(*tot); i++) {
if (fabs(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < ISECT_TOLERANCE && fabs(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < ISECT_TOLERANCE) { if (fabs(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < ISECT_TOLERANCE && fabs(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < ISECT_TOLERANCE) {
int j; int j;
for(j=i+1; j<(*tot); j++) { for(j=i+1; j<(*tot); j++) {
isectVCosSS[j-1][0] = isectVCosSS[j][0]; isectVCosSS[j-1][0] = isectVCosSS[j][0];
isectVCosSS[j-1][1] = isectVCosSS[j][1]; isectVCosSS[j-1][1] = isectVCosSS[j][1];
} }
unsorted = TRUE; /* keep looking for more doubles */ doubles = TRUE; /* keep looking for more doubles */
(*tot)--; (*tot)--;
} }
} }
@ -2084,6 +2098,7 @@ static void project_bucket_clip_face(
/* its possible there is only a few left after remove doubles */ /* its possible there is only a few left after remove doubles */
if ((*tot) < 3) { if ((*tot) < 3) {
// printf("removed too many doubles B\n");
*tot = 0; *tot = 0;
return; return;
} }
@ -2102,9 +2117,8 @@ static void project_bucket_clip_face(
} }
} }
} }
}
#if 0 #ifdef PROJ_DEBUG_PRINT_CLIP
/* include this at the bottom of the above function to debug the output */ /* include this at the bottom of the above function to debug the output */
{ {
@ -2123,7 +2137,9 @@ static void project_bucket_clip_face(
} }
printf("]),\\\n"); printf("]),\\\n");
} }
#endif
} }
/* /*
# This script creates faces in a blender scene from printed data above. # This script creates faces in a blender scene from printed data above.
@ -2170,7 +2186,6 @@ if __name__ == '__main__':
main() main()
*/ */
#endif
#undef ISECT_1 #undef ISECT_1
#undef ISECT_2 #undef ISECT_2
@ -2990,14 +3005,14 @@ static void project_paint_begin(ProjPaintState *ps, short mval[2])
no[2] = (float)(v->no[2] / 32767.0f); no[2] = (float)(v->no[2] / 32767.0f);
if (ps->is_ortho) { if (ps->is_ortho) {
if (NormalizedVecAngle2(ps->viewDir, no) >= PI_80_DEG) { /* 1 vert of this face is towards us */ if (NormalizedVecAngle2(ps->viewDir, no) >= (M_PI_2 / 90) * ps->normal_angle) { /* 1 vert of this face is towards us */
ps->vertFlags[a] |= PROJ_VERT_CULL; ps->vertFlags[a] |= PROJ_VERT_CULL;
} }
} }
else { else {
VecSubf(viewDirPersp, ps->viewPos, v->co); VecSubf(viewDirPersp, ps->viewPos, v->co);
Normalize(viewDirPersp); Normalize(viewDirPersp);
if (NormalizedVecAngle2(viewDirPersp, no) >= PI_80_DEG) { /* 1 vert of this face is towards us */ if (NormalizedVecAngle2(viewDirPersp, no) >= (M_PI_2 / 90) * ps->normal_angle) { /* 1 vert of this face is towards us */
ps->vertFlags[a] |= PROJ_VERT_CULL; ps->vertFlags[a] |= PROJ_VERT_CULL;
} }
} }
@ -4426,16 +4441,9 @@ void imagepaint_paint(short mousebutton, short texpaint)
} }
#ifndef PROJ_DEBUG_NOSEAMBLEED #ifndef PROJ_DEBUG_NOSEAMBLEED
if (settings->imapaint.flag & IMAGEPAINT_PROJECT_IGNORE_SEAMS) { ps.seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */
ps.seam_bleed_px = 0.0f;
}
else {
ps.seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */
if (ps.seam_bleed_px < 2.0f)
ps.seam_bleed_px = 2.0f;
}
#endif #endif
ps.normal_angle = settings->imapaint.normal_angle;
project_paint_begin(&ps, mval); project_paint_begin(&ps, mval);
if (stroke_gp) { if (stroke_gp) {