fix for pixels not being drawn in 2 cases.
1 issue was caused by detecting 2d horizontal line intersections for lines that had points equal to the horizontal Y value - solved by detecting point on line cases. Another was because the 2D bounding box for painting could have faces edges running along it - solved by adding a small margin to the bounding box.
This commit is contained in:
parent
aa7357b692
commit
b1653b5f98
@ -119,7 +119,6 @@ typedef struct ImagePaintState {
|
||||
ImBuf *canvas;
|
||||
ImBuf *clonecanvas;
|
||||
short clonefreefloat;
|
||||
short project; /* is projection texture painting enabled */
|
||||
char *warnpackedfile;
|
||||
char *warnmultifile;
|
||||
|
||||
@ -135,6 +134,7 @@ typedef struct ImagePaintState {
|
||||
#define PROJ_BUCKET_DIV 128 /* TODO - test other values, this is a guess, seems ok */
|
||||
|
||||
// #define PROJ_DEBUG_PAINT 1
|
||||
// #define PROJ_DEBUG_NOSCANLINE 1
|
||||
|
||||
/* projectFaceFlags options */
|
||||
#define PROJ_FACE_IGNORE 1<<0 /* When the face is hidden, backfacing or occluded */
|
||||
@ -155,6 +155,10 @@ typedef struct ImagePaintState {
|
||||
#define PROJ_BUCKET_TOP 3
|
||||
|
||||
typedef struct ProjectPaintState {
|
||||
Brush *brush;
|
||||
short tool, blend;
|
||||
Object *ob;
|
||||
/* end similarities with ImagePaintState */
|
||||
|
||||
DerivedMesh *dm;
|
||||
int dm_totface;
|
||||
@ -479,40 +483,28 @@ static int project_bucket_point_occluded(ProjectPaintState *ps, int bucket_index
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* basic line intersection, could move to arithb.c, 2 points with a horiz line */
|
||||
static int project_scanline_isect(float *p1, float *p2, float y_level, float *y_isect)
|
||||
/* basic line intersection, could move to arithb.c, 2 points with a horiz line
|
||||
* 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned */
|
||||
#define ISECT_TRUE 1
|
||||
#define ISECT_TRUE_P1 2
|
||||
#define ISECT_TRUE_P2 3
|
||||
static int project_scanline_isect(float *p1, float *p2, float y_level, float *x_isect)
|
||||
{
|
||||
if (y_level==p1[1]) {
|
||||
*x_isect = p1[0];
|
||||
return ISECT_TRUE_P1;
|
||||
}
|
||||
if (y_level==p2[1]) {
|
||||
*x_isect = p2[0];
|
||||
return ISECT_TRUE_P2;
|
||||
}
|
||||
|
||||
if (p1[1] > y_level && p2[1] < y_level) {
|
||||
*y_isect = (p2[0]*(p1[1]-y_level) + p1[0]*(y_level-p2[1])) / (p1[1]-p2[1]);
|
||||
return 1;
|
||||
*x_isect = (p2[0]*(p1[1]-y_level) + p1[0]*(y_level-p2[1])) / (p1[1]-p2[1]);
|
||||
return ISECT_TRUE;
|
||||
} else if (p1[1] < y_level && p2[1] > y_level) {
|
||||
*y_isect = (p2[0]*(y_level-p1[1]) + p1[0]*(p2[1]-y_level)) / (p2[1]-p1[1]);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* take 3 uv coords, a horizontal x_limits and set the min|max intersections points here */
|
||||
static int project_uv_scanline(float *uv1, float *uv2, float *uv3, float y_level, float x_limits[2])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (project_scanline_isect(uv1, uv2, y_level, &x_limits[0])) i++;
|
||||
if (project_scanline_isect(uv2, uv3, y_level, &x_limits[i])) i++;
|
||||
/* if the triangle intersects then the first 2 lines must */
|
||||
if (i==0) {
|
||||
return 0;
|
||||
} else if (i!=2) {
|
||||
/* if we are here then this really should not fail since 2 edges MUST intersect */
|
||||
if (project_scanline_isect(uv3, uv1, y_level, &x_limits[i])) i++;
|
||||
}
|
||||
|
||||
if (i==2) {
|
||||
if (x_limits[0] > x_limits[1]) {
|
||||
SWAP(float, x_limits[0], x_limits[1]);
|
||||
}
|
||||
return 1;
|
||||
*x_isect = (p2[0]*(y_level-p1[1]) + p1[0]*(p2[1]-y_level)) / (p2[1]-p1[1]);
|
||||
return ISECT_TRUE;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -523,14 +515,15 @@ static int project_face_scanline(ProjectScanline *sc, float y_level, float *v1,
|
||||
/* 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?*/
|
||||
short i1,i2,i3,i4, i_mid;
|
||||
int i4=0, i_mid=0;
|
||||
float xi1, xi2, xi3, xi4, xi_mid;
|
||||
|
||||
|
||||
|
||||
i1 = project_scanline_isect(v1, v2, y_level, &xi1);
|
||||
i2 = project_scanline_isect(v2, v3, y_level, &xi2);
|
||||
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 = project_scanline_isect(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;
|
||||
@ -540,8 +533,10 @@ static int project_face_scanline(ProjectScanline *sc, float y_level, float *v1,
|
||||
sc->x_limits[1] = MAX2(xi1, xi2);
|
||||
totscanlines = 1;
|
||||
} else {
|
||||
i3 = project_scanline_isect(v3, v4, y_level, &xi3);
|
||||
i4 = project_scanline_isect(v4, v1, y_level, &xi4);
|
||||
if (i2 != ISECT_TRUE_P2)
|
||||
i3 = project_scanline_isect(v3, v4, y_level, &xi3);
|
||||
if (i1 != ISECT_TRUE_P1 && i3 != ISECT_TRUE_P2)
|
||||
i4 = project_scanline_isect(v4, v1, y_level, &xi4);
|
||||
|
||||
if (i3 && i4) { /* second 2 edges only intersect, same as above */
|
||||
sc->v[0] = 0;
|
||||
@ -573,13 +568,37 @@ static int project_face_scanline(ProjectScanline *sc, float y_level, float *v1,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { /* triangle */
|
||||
int i = 0;
|
||||
|
||||
} else {
|
||||
if (project_uv_scanline(v1, v2, v3, y_level, sc->x_limits)) {
|
||||
sc->v[0] = 0;
|
||||
sc->v[1] = 1;
|
||||
sc->v[2] = 2;
|
||||
totscanlines = 1;
|
||||
i1 = project_scanline_isect(v1, v2, y_level, &sc->x_limits[0]);
|
||||
if (i1) i++;
|
||||
|
||||
if (i1 != ISECT_TRUE_P2) {
|
||||
i2 = project_scanline_isect(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 = project_scanline_isect(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 */
|
||||
@ -883,10 +902,12 @@ static screen_px_from_persp(
|
||||
/* can provide own own coords, use for seams when we want to bleed our from the original location */
|
||||
|
||||
#define pixel_size 4
|
||||
static void project_paint_uvpixel_init(ProjectPaintState *ps, ProjectScanline *sc, ImBuf *ibuf, float *uv, int x, int y, int face_index, float *pixelScreenCo)
|
||||
static void project_paint_uvpixel_init(ProjectPaintState *ps, ImBuf *ibuf, float *uv, int x, int y, int face_index, float *pixelScreenCo)
|
||||
{
|
||||
int bucket_index;
|
||||
|
||||
// printf("adding px (%d %d), (%f %f)\n", x,y,uv[0],uv[1]);
|
||||
|
||||
ProjectPixel *projPixel;
|
||||
|
||||
bucket_index = project_paint_BucketOffset(ps, pixelScreenCo);
|
||||
@ -940,10 +961,12 @@ static void project_paint_face_init(ProjectPaintState *ps, int face_index, ImBuf
|
||||
int i, j;
|
||||
|
||||
/* scanlines since quads can have 2 triangles intersecting the same vertical location */
|
||||
#ifndef PROJ_DEBUG_NOSCANLINE
|
||||
ProjectScanline scanlines[2];
|
||||
ProjectScanline *sc;
|
||||
int totscanlines; /* can only be 1 or 2, oh well */
|
||||
|
||||
#endif
|
||||
|
||||
if (!uv_image_rect(tf->uv[0], tf->uv[1], tf->uv[2], tf->uv[3], min_px, max_px, ibuf->x, ibuf->y, mf->v4))
|
||||
return;
|
||||
|
||||
@ -951,15 +974,16 @@ static void project_paint_face_init(ProjectPaintState *ps, int face_index, ImBuf
|
||||
if (ps->projectSeamBleed > 0.0)
|
||||
project_face_seams_init(ps, face_index, mf->v4);
|
||||
|
||||
for (y = min_px[1]-2; y < max_px[1]+2; y++) {
|
||||
for (y = min_px[1]; y < max_px[1]; y++) {
|
||||
uv[1] = (((float)y)+0.5) / (float)ibuf->y; /* TODO - this is not pixel aligned correctly */
|
||||
|
||||
|
||||
#ifndef PROJ_DEBUG_NOSCANLINE
|
||||
totscanlines = project_face_scanline(scanlines, uv[1], tf->uv[0], tf->uv[1], tf->uv[2], mf->v4 ? tf->uv[3]:NULL);
|
||||
|
||||
/* Loop over scanlines a bit silly since there can only be 1 or 2, but its easier then having tri/quad spesific functions */
|
||||
for (j=0, sc=scanlines; j<totscanlines; j++, sc++) {
|
||||
|
||||
min_px[0] = (int)((ibuf->x * sc->x_limits[0])+0.5);
|
||||
min_px[0] = (int)((ibuf->x * sc->x_limits[0])-0.5);
|
||||
max_px[0] = (int)((ibuf->x * sc->x_limits[1])+0.5);
|
||||
CLAMP(min_px[0], 0, ibuf->x);
|
||||
CLAMP(max_px[0], 0, ibuf->x);
|
||||
@ -976,26 +1000,8 @@ static void project_paint_face_init(ProjectPaintState *ps, int face_index, ImBuf
|
||||
for (x = min_px[0]; x < max_px[0]; x++) {
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
screen_px_from_ortho(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
|
||||
project_paint_uvpixel_init(ps, sc, ibuf, uv, x,y,face_index, pixelScreenCo);
|
||||
project_paint_uvpixel_init(ps, ibuf, uv, x,y,face_index, pixelScreenCo);
|
||||
}
|
||||
|
||||
/* interpolation is faster - no workies :( */
|
||||
/*
|
||||
x = min_px[0];
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
screen_px_from_ortho(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCoXMin);
|
||||
|
||||
x = max_px[0]-1;
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
screen_px_from_ortho(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCoXMax);
|
||||
|
||||
for (x = min_px[0]; x < max_px[0]; x++) {
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
VecLerpf(pixelScreenCo, pixelScreenCoXMin, pixelScreenCoXMax, ((float)x) / ((float)(max_px[0]-min_px[0])) );
|
||||
project_paint_uvpixel_init(ps, sc, ibuf, uv, x,y, face_index, pixelScreenCo);
|
||||
}
|
||||
*/
|
||||
|
||||
} else {
|
||||
v1co = ps->dm_mvert[ (*(&mf->v1 + sc->v[0])) ].co;
|
||||
v2co = ps->dm_mvert[ (*(&mf->v1 + sc->v[1])) ].co;
|
||||
@ -1004,31 +1010,49 @@ static void project_paint_face_init(ProjectPaintState *ps, int face_index, ImBuf
|
||||
for (x = min_px[0]; x < max_px[0]; x++) {
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
screen_px_from_persp(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
|
||||
project_paint_uvpixel_init(ps, sc, ibuf, uv, x,y,face_index, pixelScreenCo);
|
||||
project_paint_uvpixel_init(ps, ibuf, uv, x,y,face_index, pixelScreenCo);
|
||||
}
|
||||
|
||||
|
||||
/* interpolation is faster */
|
||||
/*
|
||||
x = min_px[0];
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
screen_px_from_persp(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCoXMin);
|
||||
|
||||
x = max_px[0]-1;
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
screen_px_from_persp(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCoXMax);
|
||||
|
||||
for (x = min_px[0]; x < max_px[0]; x++) {
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
VecLerpf(pixelScreenCo, pixelScreenCoXMin, pixelScreenCoXMax, ((float)x) / ((float)(max_px[0]-min_px[0])) );
|
||||
project_paint_uvpixel_init(ps, sc, ibuf, uv, x,y, face_index, pixelScreenCo);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
#else /* slow, non scanline method */
|
||||
|
||||
/* mainly for debuggung scanline, use point-in-tri for every x/y test */
|
||||
/* at the moment only works with ortho triangles */
|
||||
uv1co = tf->uv[0];
|
||||
uv2co = tf->uv[1];
|
||||
uv3co = tf->uv[2];
|
||||
|
||||
if (ps->projectIsOrtho) {
|
||||
v1co = ps->projectVertScreenCos[ mf->v1 ];
|
||||
v2co = ps->projectVertScreenCos[ mf->v2 ];
|
||||
v3co = ps->projectVertScreenCos[ mf->v3 ];
|
||||
|
||||
for (x = min_px[0]; x < max_px[0]; x++) {
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
if (IsectPT2Df(uv, uv1co, uv2co, uv3co)) {
|
||||
screen_px_from_ortho(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
|
||||
project_paint_uvpixel_init(ps, ibuf, uv, x,y,face_index, pixelScreenCo);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
v1co = ps->dm_mvert[ (*(&mf->v1 + sc->v[0])) ].co;
|
||||
v2co = ps->dm_mvert[ (*(&mf->v1 + sc->v[1])) ].co;
|
||||
v3co = ps->dm_mvert[ (*(&mf->v1 + sc->v[2])) ].co;
|
||||
|
||||
for (x = min_px[0]; x < max_px[0]; x++) {
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
screen_px_from_persp(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
|
||||
project_paint_uvpixel_init(ps, sc, ibuf, uv, x,y,face_index, pixelScreenCo);
|
||||
}
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef PROJ_DEBUG_NOSCANLINE
|
||||
/* Pretty much a copy of above, except fill in seams if we have any */
|
||||
if (ps->projectFaceFlags[face_index] & (PROJ_FACE_SEAM1|PROJ_FACE_SEAM2|PROJ_FACE_SEAM3|PROJ_FACE_SEAM4)) {
|
||||
float outset_uv[4][2]; /* expanded UV's */
|
||||
@ -1184,13 +1208,14 @@ static void project_paint_face_init(ProjectPaintState *ps, int face_index, ImBuf
|
||||
pixelScreenCo[2] = pixelScreenCo[2]/pixelScreenCo[3]; /* Use the depth for bucket point occlusion */
|
||||
}
|
||||
|
||||
project_paint_uvpixel_init(ps, sc, ibuf, uv, x, y, face_index, pixelScreenCo);
|
||||
project_paint_uvpixel_init(ps, ibuf, uv, x, y, face_index, pixelScreenCo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1204,15 +1229,15 @@ static void project_paint_rect(ProjectPaintState *ps, float min[2], float max[2]
|
||||
bucket_min[0] = (int)(((float)(min[0] - ps->viewMin2D[0]) / ps->viewWidth) * ps->bucketsX) + 0.5;
|
||||
bucket_min[1] = (int)(((float)(min[1] - ps->viewMin2D[1]) / ps->viewHeight) * ps->bucketsY) + 0.5;
|
||||
|
||||
bucket_max[0] = (int)(((float)(max[0] - ps->viewMin2D[0]) / ps->viewWidth) * ps->bucketsX) + 1.5;
|
||||
bucket_max[1] = (int)(((float)(max[1] - ps->viewMin2D[1]) / ps->viewHeight) * ps->bucketsY) + 1.5;
|
||||
bucket_max[0] = (int)(((float)(max[0] - ps->viewMin2D[0]) / ps->viewWidth) * ps->bucketsX) + 0.5;
|
||||
bucket_max[1] = (int)(((float)(max[1] - ps->viewMin2D[1]) / ps->viewHeight) * ps->bucketsY) + 0.5;
|
||||
|
||||
/* incase the rect is outside the mesh 2d bounds */
|
||||
CLAMP(bucket_min[0], 0, ps->bucketsX-1);
|
||||
CLAMP(bucket_min[1], 0, ps->bucketsY-1);
|
||||
CLAMP(bucket_min[0], 0, ps->bucketsX);
|
||||
CLAMP(bucket_min[1], 0, ps->bucketsY);
|
||||
|
||||
CLAMP(bucket_max[0], 0, ps->bucketsX-1);
|
||||
CLAMP(bucket_max[1], 0, ps->bucketsY-1);
|
||||
CLAMP(bucket_max[0], 0, ps->bucketsX);
|
||||
CLAMP(bucket_max[1], 0, ps->bucketsY);
|
||||
}
|
||||
|
||||
static void project_bucket_bounds(ProjectPaintState *ps, int bucket_x, int bucket_y, float bucket_bounds[4])
|
||||
@ -1364,7 +1389,7 @@ static void project_paint_begin_face_delayed_init(ProjectPaintState *ps, MFace *
|
||||
}
|
||||
}
|
||||
|
||||
static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
static void project_paint_begin( ProjectPaintState *ps )
|
||||
{
|
||||
/* Viewport vars */
|
||||
float mat[3][3];
|
||||
@ -1372,7 +1397,7 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
|
||||
float projCo[4];
|
||||
float (*projScreenCo)[3];
|
||||
|
||||
float projMargin;
|
||||
/* Image Vars - keep track of images we have used */
|
||||
LinkNode *image_LinkList = NULL;
|
||||
LinkNode *node;
|
||||
@ -1397,7 +1422,7 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
|
||||
/* paint onto the derived mesh
|
||||
* note get_viewedit_datamask checks for paint mode and will always give UVs */
|
||||
ps->dm = mesh_get_derived_final(s->ob, get_viewedit_datamask());
|
||||
ps->dm = mesh_get_derived_final(ps->ob, get_viewedit_datamask());
|
||||
|
||||
ps->dm_mvert = ps->dm->getVertArray( ps->dm );
|
||||
ps->dm_mface = ps->dm->getFaceArray( ps->dm );
|
||||
@ -1415,7 +1440,7 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
ps->viewDir[1] = 0.0;
|
||||
ps->viewDir[2] = 1.0;
|
||||
|
||||
view3d_get_object_project_mat(curarea, s->ob, ps->projectMat, ps->viewMat);
|
||||
view3d_get_object_project_mat(curarea, ps->ob, ps->projectMat, ps->viewMat);
|
||||
|
||||
tot_bucketMem = sizeof(LinkNode *) * ps->bucketsX * ps->bucketsY;
|
||||
tot_faceListMem = sizeof(LinkNode *) * ps->bucketsX * ps->bucketsY;
|
||||
@ -1445,11 +1470,11 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
if (ps->projectSeamBleed > 0.0)
|
||||
memset(ps->projectVertFaces, 0, tot_bucketVertFacesMem);
|
||||
|
||||
Mat4Invert(s->ob->imat, s->ob->obmat);
|
||||
Mat4Invert(ps->ob->imat, ps->ob->obmat);
|
||||
|
||||
Mat3CpyMat4(mat, G.vd->viewinv);
|
||||
Mat3MulVecfl(mat, ps->viewDir);
|
||||
Mat3CpyMat4(mat, s->ob->imat);
|
||||
Mat3CpyMat4(mat, ps->ob->imat);
|
||||
Mat3MulVecfl(mat, ps->viewDir);
|
||||
|
||||
/* calculate vert screen coords */
|
||||
@ -1481,6 +1506,17 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
}
|
||||
}
|
||||
|
||||
/* 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->viewMax2D[0] - ps->viewMin2D[0]) * 0.000001;
|
||||
ps->viewMax2D[0] += projMargin;
|
||||
ps->viewMin2D[0] -= projMargin;
|
||||
projMargin = (ps->viewMax2D[1] - ps->viewMin2D[1]) * 0.000001;
|
||||
ps->viewMax2D[1] += projMargin;
|
||||
ps->viewMin2D[1] -= projMargin;
|
||||
|
||||
|
||||
/* only for convenience */
|
||||
ps->viewWidth = ps->viewMax2D[0] - ps->viewMin2D[0];
|
||||
ps->viewHeight = ps->viewMax2D[1] - ps->viewMin2D[1];
|
||||
@ -2051,7 +2087,7 @@ static int project_bucket_circle_isect(ProjectPaintState *ps, int bucket_x, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imapaint_paint_sub_stroke_project(ImagePaintState *s, ProjectPaintState *ps, BrushPainter *painter, short texpaint, short mval[2], double time, int update, float pressure)
|
||||
static int imapaint_paint_sub_stroke_project(ProjectPaintState *ps, BrushPainter *painter, short mval[2], double time, int update, float pressure)
|
||||
{
|
||||
/* TODO - texpaint option : is there any use in projection painting from the image window??? - could be interesting */
|
||||
/* TODO - floating point images */
|
||||
@ -2074,11 +2110,11 @@ static int imapaint_paint_sub_stroke_project(ImagePaintState *s, ProjectPaintSta
|
||||
|
||||
mval_f[0] = mval[0]; mval_f[1] = mval[1];
|
||||
|
||||
min[0] = mval_f[0] - (s->brush->size/2);
|
||||
min[1] = mval_f[1] - (s->brush->size/2);
|
||||
min[0] = mval_f[0] - (ps->brush->size/2);
|
||||
min[1] = mval_f[1] - (ps->brush->size/2);
|
||||
|
||||
max[0] = mval_f[0] + (s->brush->size/2);
|
||||
max[1] = mval_f[1] + (s->brush->size/2);
|
||||
max[0] = mval_f[0] + (ps->brush->size/2);
|
||||
max[1] = mval_f[1] + (ps->brush->size/2);
|
||||
|
||||
/* offset to make this a valid bucket index */
|
||||
project_paint_rect(ps, min, max, bucket_min, bucket_max);
|
||||
@ -2089,7 +2125,7 @@ static int imapaint_paint_sub_stroke_project(ImagePaintState *s, ProjectPaintSta
|
||||
}
|
||||
|
||||
/* avoid a square root with every dist comparison */
|
||||
brush_size_sqared = s->brush->size * s->brush->size;
|
||||
brush_size_sqared = ps->brush->size * ps->brush->size;
|
||||
|
||||
/* printf("brush bounds %d %d %d %d\n", bucket_min[0], bucket_min[1], bucket_max[0], bucket_max[1]); */
|
||||
|
||||
@ -2125,23 +2161,23 @@ static int imapaint_paint_sub_stroke_project(ImagePaintState *s, ProjectPaintSta
|
||||
/*if (dist < s->brush->size) {*/ /* correct but uses a sqrt */
|
||||
if (dist_nosqrt < brush_size_sqared) {
|
||||
|
||||
brush_sample_tex(s->brush, projPixel->projCo2D, rgba);
|
||||
brush_sample_tex(ps->brush, projPixel->projCo2D, rgba);
|
||||
|
||||
dist = (float)sqrt(dist_nosqrt);
|
||||
|
||||
alpha = rgba[3]*brush_sample_falloff(s->brush, dist);
|
||||
alpha = rgba[3]*brush_sample_falloff(ps->brush, dist);
|
||||
|
||||
if (alpha <= 0.0) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
if (alpha >= 1.0) {
|
||||
projPixel->pixel[0] = FTOCHAR(rgba[0]*s->brush->rgb[0]);
|
||||
projPixel->pixel[1] = FTOCHAR(rgba[1]*s->brush->rgb[1]);
|
||||
projPixel->pixel[2] = FTOCHAR(rgba[2]*s->brush->rgb[2]);
|
||||
projPixel->pixel[0] = FTOCHAR(rgba[0]*ps->brush->rgb[0]);
|
||||
projPixel->pixel[1] = FTOCHAR(rgba[1]*ps->brush->rgb[1]);
|
||||
projPixel->pixel[2] = FTOCHAR(rgba[2]*ps->brush->rgb[2]);
|
||||
} else {
|
||||
projPixel->pixel[0] = FTOCHAR(((rgba[0]*s->brush->rgb[0])*alpha) + (((projPixel->pixel[0])/255.0)*(1.0-alpha)));
|
||||
projPixel->pixel[1] = FTOCHAR(((rgba[1]*s->brush->rgb[1])*alpha) + (((projPixel->pixel[1])/255.0)*(1.0-alpha)));
|
||||
projPixel->pixel[2] = FTOCHAR(((rgba[2]*s->brush->rgb[2])*alpha) + (((projPixel->pixel[2])/255.0)*(1.0-alpha)));
|
||||
projPixel->pixel[0] = FTOCHAR(((rgba[0]*ps->brush->rgb[0])*alpha) + (((projPixel->pixel[0])/255.0)*(1.0-alpha)));
|
||||
projPixel->pixel[1] = FTOCHAR(((rgba[1]*ps->brush->rgb[1])*alpha) + (((projPixel->pixel[1])/255.0)*(1.0-alpha)));
|
||||
projPixel->pixel[2] = FTOCHAR(((rgba[2]*ps->brush->rgb[2])*alpha) + (((projPixel->pixel[2])/255.0)*(1.0-alpha)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2163,7 +2199,7 @@ static int imapaint_paint_sub_stroke_project(ImagePaintState *s, ProjectPaintSta
|
||||
for (a=0; a < ps->projectImageTotal; a++) {
|
||||
Image *ima = ps->projectImages[a];
|
||||
if (ima->id.flag & LIB_DOIT) {
|
||||
imapaint_image_update(ima, BKE_image_get_ibuf(ima, NULL), texpaint);
|
||||
imapaint_image_update(ima, BKE_image_get_ibuf(ima, NULL), 1 /*texpaint*/ );
|
||||
redraw = 1;
|
||||
|
||||
ima->id.flag &= ~LIB_DOIT; /* clear for reuse */
|
||||
@ -2254,17 +2290,17 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho
|
||||
}
|
||||
}
|
||||
|
||||
static void imapaint_paint_stroke_project(ImagePaintState *s, ProjectPaintState *ps, BrushPainter *painter, short texpaint, short *prevmval, short *mval, double time, float pressure)
|
||||
static void imapaint_paint_stroke_project(ProjectPaintState *ps, BrushPainter *painter, short *prevmval, short *mval, double time, float pressure)
|
||||
{
|
||||
int redraw = 0;
|
||||
|
||||
/* TODO - support more brush operations, airbrush etc */
|
||||
{
|
||||
redraw |= imapaint_paint_sub_stroke_project(s, ps, painter, texpaint, mval, time, 1, pressure);
|
||||
redraw |= imapaint_paint_sub_stroke_project(ps, painter, mval, time, 1, pressure);
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
imapaint_redraw(0, texpaint, NULL);
|
||||
imapaint_redraw(0, 1/*texpaint*/, NULL);
|
||||
imapaint_clear_partial_redraw();
|
||||
}
|
||||
}
|
||||
@ -2275,7 +2311,7 @@ void imagepaint_paint(short mousebutton, short texpaint)
|
||||
ProjectPaintState ps;
|
||||
BrushPainter *painter;
|
||||
ToolSettings *settings= G.scene->toolsettings;
|
||||
short prevmval[2], mval[2];
|
||||
short prevmval[2], mval[2], project = 0;
|
||||
double time;
|
||||
float pressure;
|
||||
|
||||
@ -2284,17 +2320,24 @@ void imagepaint_paint(short mousebutton, short texpaint)
|
||||
|
||||
/* initialize state */
|
||||
memset(&s, 0, sizeof(s));
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
|
||||
project = texpaint;
|
||||
|
||||
s.brush = settings->imapaint.brush;
|
||||
s.tool = settings->imapaint.tool;
|
||||
if(texpaint && (s.tool == PAINT_TOOL_CLONE))
|
||||
s.tool = PAINT_TOOL_DRAW;
|
||||
s.blend = s.brush->blend;
|
||||
|
||||
if (texpaint) /* TODO - make an option */
|
||||
s.project = 1;
|
||||
|
||||
if (project) {
|
||||
ps.brush = s.brush;
|
||||
ps.tool = s.tool;
|
||||
ps.blend = s.blend;
|
||||
}
|
||||
|
||||
if(texpaint) {
|
||||
s.ob = OBACT;
|
||||
ps.ob = s.ob = OBACT;
|
||||
if (!s.ob || !(s.ob->lay & G.vd->lay)) return;
|
||||
s.me = get_mesh(s.ob);
|
||||
if (!s.me) return;
|
||||
@ -2328,15 +2371,13 @@ void imagepaint_paint(short mousebutton, short texpaint)
|
||||
prevmval[0]= mval[0];
|
||||
prevmval[1]= mval[1];
|
||||
|
||||
if (s.project) {
|
||||
if (project) {
|
||||
/* setup projection painting data */
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
|
||||
ps.projectIsBackfaceCull = 1;
|
||||
ps.projectIsOcclude = 1;
|
||||
ps.projectSeamBleed = 2.0; /* pixel num to bleed */
|
||||
|
||||
project_paint_begin(&s, &ps);
|
||||
project_paint_begin(&ps);
|
||||
|
||||
} else {
|
||||
if (!((s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE|
|
||||
@ -2352,9 +2393,9 @@ void imagepaint_paint(short mousebutton, short texpaint)
|
||||
|
||||
time= PIL_check_seconds_timer();
|
||||
|
||||
if (s.project) { /* Projection Painting */
|
||||
if (project) { /* Projection Painting */
|
||||
if((mval[0] != prevmval[0]) || (mval[1] != prevmval[1])) {
|
||||
imapaint_paint_stroke_project(&s, &ps, painter, 1, prevmval, mval, time, pressure);
|
||||
imapaint_paint_stroke_project(&ps, painter, prevmval, mval, time, pressure);
|
||||
prevmval[0]= mval[0];
|
||||
prevmval[1]= mval[1];
|
||||
} else
|
||||
@ -2379,7 +2420,7 @@ void imagepaint_paint(short mousebutton, short texpaint)
|
||||
imapaint_canvas_free(&s);
|
||||
brush_painter_free(painter);
|
||||
|
||||
if (s.project) {
|
||||
if (project) {
|
||||
project_paint_end(&ps);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user