Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_image.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c197
1 files changed, 124 insertions, 73 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 77cd06581fd..1effd8fd377 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -189,7 +189,7 @@ typedef struct ImagePaintPartialRedraw {
// #define PROJ_BUCKET_CLONE_INIT 1<<1
/* used for testing doubles, if a point is on a line etc */
-#define PROJ_GEOM_TOLERANCE 0.0002f
+#define PROJ_GEOM_TOLERANCE 0.00075f
/* vert flags */
#define PROJ_VERT_CULL 1
@@ -238,8 +238,8 @@ typedef struct ProjPaintState {
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
+ char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */
int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */
int buckets_y;
@@ -341,7 +341,7 @@ typedef struct UndoTile {
typedef struct UndoElem {
struct UndoElem *next, *prev;
char name[MAXUNDONAME];
- unsigned long undosize;
+ uintptr_t undosize;
ImBuf *ibuf;
ListBase tiles;
@@ -485,12 +485,12 @@ static void undo_imagepaint_push_begin(char *name)
static void undo_imagepaint_push_end()
{
UndoElem *uel;
- unsigned long totmem, maxmem;
+ uintptr_t totmem, maxmem;
if(U.undomemory != 0) {
/* limit to maximum memory (afterwards, we can't know in advance) */
totmem= 0;
- maxmem= ((unsigned long)U.undomemory)*1024*1024;
+ maxmem= ((uintptr_t)U.undomemory)*1024*1024;
uel= undobase.last;
while(uel) {
@@ -716,8 +716,8 @@ static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w
static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
{
/* use */
- *x = (float)fmod(uv[0], 1.0f);
- *y = (float)fmod(uv[1], 1.0f);
+ *x = (float)fmodf(uv[0], 1.0f);
+ *y = (float)fmodf(uv[1], 1.0f);
if (*x < 0.0f) *x += 1.0f;
if (*y < 0.0f) *y += 1.0f;
@@ -751,7 +751,7 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float
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, the only way around it is to have an ibuf index per face */
+ ibuf = tf->tpage->ibufs.first; /* we must have got the imbuf before getting here */
if (!ibuf) return 0;
if (interp) {
@@ -760,21 +760,21 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float
if (ibuf->rect_float) {
if (rgba_fp) {
- bilinear_interpolation_color(ibuf, NULL, rgba_fp, x, y);
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y);
}
else {
float rgba_tmp_f[4];
- bilinear_interpolation_color(ibuf, NULL, rgba_tmp_f, x, y);
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y);
IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f);
}
}
else {
if (rgba) {
- bilinear_interpolation_color(ibuf, rgba, NULL, x, y);
+ bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y);
}
else {
unsigned char rgba_tmp[4];
- bilinear_interpolation_color(ibuf, rgba_tmp, NULL, x, y);
+ bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp);
}
}
@@ -911,7 +911,7 @@ static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *buc
else
isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho);
}
- if (isect_ret==1) {
+ if (isect_ret>=1) {
/* TODO - we may want to cache the first hit,
* it is not possible to swap the face order in the list anymore */
return 1;
@@ -939,7 +939,7 @@ static int line_isect_y(const float p1[2], const float p2[2], const float y_leve
return ISECT_TRUE_P2;
}
- y_diff= fabs(p1[1]-p2[1]); /* yuck, horizontal line, we cant do much here */
+ y_diff= fabsf(p1[1]-p2[1]); /* yuck, horizontal line, we cant do much here */
if (y_diff < 0.000001f) {
*x_isect = (p1[0]+p2[0]) * 0.5f;
@@ -972,7 +972,7 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve
return ISECT_TRUE_P2;
}
- x_diff= fabs(p1[0]-p2[0]); /* yuck, horizontal line, we cant do much here */
+ x_diff= fabsf(p1[0]-p2[0]); /* yuck, horizontal line, we cant do much here */
if (x_diff < 0.000001) { /* yuck, vertical line, we cant do much here */
*y_isect = (p1[0]+p2[0]) * 0.5f;
@@ -996,14 +996,15 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve
* Its possible this gives incorrect results, when the UVs for 1 face go into the next
* tile, but do not do this for the adjacent face, it could return a false positive.
* This is so unlikely that Id not worry about it. */
+#ifndef PROJ_DEBUG_NOSEAMBLEED
static int cmp_uv(const float vec2a[2], const float vec2b[2])
{
/* if the UV's are not between 0.0 and 1.0 */
- float xa = (float)fmod(vec2a[0], 1.0f);
- float ya = (float)fmod(vec2a[1], 1.0f);
+ float xa = (float)fmodf(vec2a[0], 1.0f);
+ float ya = (float)fmodf(vec2a[1], 1.0f);
- float xb = (float)fmod(vec2b[0], 1.0f);
- float yb = (float)fmod(vec2b[1], 1.0f);
+ float xb = (float)fmodf(vec2b[0], 1.0f);
+ float yb = (float)fmodf(vec2b[1], 1.0f);
if (xa < 0.0f) xa += 1.0f;
if (ya < 0.0f) ya += 1.0f;
@@ -1011,12 +1012,13 @@ static int cmp_uv(const float vec2a[2], const float vec2b[2])
if (xb < 0.0f) xb += 1.0f;
if (yb < 0.0f) yb += 1.0f;
- return ((fabs(xa-xb) < PROJ_GEOM_TOLERANCE) && (fabs(ya-yb) < PROJ_GEOM_TOLERANCE)) ? 1:0;
+ return ((fabsf(xa-xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya-yb) < PROJ_GEOM_TOLERANCE)) ? 1:0;
}
-
+#endif
/* set min_px and max_px to the image space bounds of the UV coords
* return zero if there is no area in the returned rectangle */
+#ifndef PROJ_DEBUG_NOSEAMBLEED
static int pixel_bounds_uv(
const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2],
rcti *bounds_px,
@@ -1044,6 +1046,7 @@ static int pixel_bounds_uv(
/* face uses no UV area when quantized to pixels? */
return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
}
+#endif
static int pixel_bounds_array(float (* uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
{
@@ -1151,7 +1154,7 @@ static float angleToLength(float angle)
return 1.0f;
}
else {
- return fabs(1.0f / cos(angle * (M_PI/180.0f)));
+ return fabsf(1.0f / cosf(angle * (M_PI/180.0f)));
}
}
@@ -1384,10 +1387,10 @@ static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const
if (ibuf_other->rect_float) { /* from float to float */
- bilinear_interpolation_color(ibuf_other, NULL, rgba_f, x, y);
+ bilinear_interpolation_color_wrap(ibuf_other, NULL, rgba_f, x, y);
}
else { /* from char to float */
- bilinear_interpolation_color(ibuf_other, rgba_ub, NULL, x, y);
+ bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y);
}
}
@@ -1407,7 +1410,7 @@ float project_paint_uvpixel_mask(
ImBuf *ibuf_other;
const MTFace *tf_other = ps->dm_mtface_mask + face_index;
- if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) {
+ if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf(tf_other->tpage, NULL))) {
/* BKE_image_get_ibuf - TODO - this may be slow */
unsigned char rgba_ub[4];
float rgba_f[4];
@@ -1563,7 +1566,7 @@ static ProjPixel *project_paint_uvpixel_init(
ImBuf *ibuf_other;
const MTFace *tf_other = ps->dm_mtface_clone + face_index;
- if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) {
+ if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf(tf_other->tpage, NULL))) {
/* BKE_image_get_ibuf - TODO - this may be slow */
if (ibuf->rect_float) {
@@ -1632,7 +1635,7 @@ static int line_clip_rect2f(
{
/* first account for horizontal, then vertical lines */
/* horiz */
- if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) {
+ if (fabsf(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) {
/* is the line out of range on its Y axis? */
if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
return 0;
@@ -1643,7 +1646,7 @@ static int line_clip_rect2f(
}
- if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/
+ if (fabsf(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/
if (BLI_in_rctf(rect, l1[0], l1[1])) {
VECCOPY2D(l1_clip, l1);
VECCOPY2D(l2_clip, l2);
@@ -1660,7 +1663,7 @@ static int line_clip_rect2f(
CLAMP(l2_clip[0], rect->xmin, rect->xmax);
return 1;
}
- else if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) {
+ else if (fabsf(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) {
/* is the line out of range on its X axis? */
if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
return 0;
@@ -1671,7 +1674,7 @@ static int line_clip_rect2f(
return 0;
}
- if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/
+ if (fabsf(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/
if (BLI_in_rctf(rect, l1[0], l1[1])) {
VECCOPY2D(l1_clip, l1);
VECCOPY2D(l2_clip, l2);
@@ -2015,7 +2018,6 @@ static void project_bucket_clip_face(
const int flip = ((SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) > 0.0f) != (SIDE_OF_LINE(uv1co, uv2co, uv3co) > 0.0f));
float bucket_bounds_ss[4][2];
- float w[3];
/* get the UV space bounding box */
inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v1coSS[0], v1coSS[1]);
@@ -2086,6 +2088,7 @@ static void project_bucket_clip_face(
/* Maximum possible 6 intersections when using a rectangle and triangle */
float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
float v1_clipSS[2], v2_clipSS[2];
+ float w[3];
/* calc center*/
float cent[2] = {0.0f, 0.0f};
@@ -2128,6 +2131,7 @@ static void project_bucket_clip_face(
if ((*tot) < 3) { /* no intersections to speak of */
*tot = 0;
+ return;
}
/* now we have all points we need, collect their angles and sort them clockwise */
@@ -2156,16 +2160,15 @@ static void project_bucket_clip_face(
for(i=0; i<(*tot); i++) {
v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
- isectVCosSS[i][2] = atan2(v1_clipSS[0]*v2_clipSS[1] - v1_clipSS[1]*v2_clipSS[0], v1_clipSS[0]*v2_clipSS[0]+v1_clipSS[1]*v2_clipSS[1]);
+ isectVCosSS[i][2] = atan2f(v1_clipSS[0]*v2_clipSS[1] - v1_clipSS[1]*v2_clipSS[0], v1_clipSS[0]*v2_clipSS[0]+v1_clipSS[1]*v2_clipSS[1]);
}
if (flip) qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort_flip);
else qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort);
-
/* remove doubles */
/* first/last check */
- if (fabs(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < PROJ_GEOM_TOLERANCE && fabs(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < PROJ_GEOM_TOLERANCE) {
+ if (fabsf(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < PROJ_GEOM_TOLERANCE && fabsf(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < PROJ_GEOM_TOLERANCE) {
(*tot)--;
}
@@ -2180,8 +2183,8 @@ static void project_bucket_clip_face(
while (doubles==TRUE) {
doubles = FALSE;
for(i=1; i<(*tot); i++) {
- if (fabs(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE &&
- fabs(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE)
+ if (fabsf(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE &&
+ fabsf(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE)
{
int j;
for(j=i+1; j<(*tot); j++) {
@@ -2309,6 +2312,19 @@ int IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
return 1;
}
+static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot)
+{
+ int i;
+ int side = (SIDE_OF_LINE(uv[tot-1], uv[0], pt) > 0.0f);
+
+ for (i=1; i<tot; i++) {
+ if ((SIDE_OF_LINE(uv[i-1], uv[i], pt) > 0.0f) != side)
+ return 0;
+
+ }
+
+ return 1;
+}
/* One of the most important function for projectiopn painting, since it selects the pixels to be added into each bucket.
* initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
@@ -2352,6 +2368,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
float uv_clip[8][2];
int uv_clip_tot;
const short is_ortho = ps->is_ortho;
+ const short do_backfacecull = ps->do_backfacecull;
vCo[0] = ps->dm_mvert[mf->v1].co;
vCo[1] = ps->dm_mvert[mf->v2].co;
@@ -2361,9 +2378,20 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
/* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
* this is done so we can avoid offseting all the pixels by 0.5 which causes
* problems when wrapping negative coords */
- xhalfpx = 0.5f / ibuf_xf;
- yhalfpx = 0.5f / ibuf_yf;
-
+ xhalfpx = (0.5f+ (PROJ_GEOM_TOLERANCE/3.0f) ) / ibuf_xf;
+ yhalfpx = (0.5f+ (PROJ_GEOM_TOLERANCE/4.0f) ) / ibuf_yf;
+
+ /* Note about (PROJ_GEOM_TOLERANCE/x) above...
+ Needed to add this offset since UV coords are often quads aligned to pixels.
+ In this case pixels can be exactly between 2 triangles causing nasty
+ artifacts.
+
+ This workaround can be removed and painting will still work on most cases
+ but since the first thing most people try is painting onto a quad- better make it work.
+ */
+
+
+
tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx;
tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx;
@@ -2399,8 +2427,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
v1coSS = ps->screenCoords[ (*(&mf->v1 + i1)) ];
v2coSS = ps->screenCoords[ (*(&mf->v1 + i2)) ];
v3coSS = ps->screenCoords[ (*(&mf->v1 + i3)) ];
-
-
+
/* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
project_bucket_clip_face(
is_ortho, bucket_bounds,
@@ -2408,8 +2435,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
uv1co, uv2co, uv3co,
uv_clip, &uv_clip_tot
);
-
-
+
/* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
/*
if (uv_clip_tot>6) {
@@ -2431,7 +2457,10 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
//uv[0] = (((float)x) + 0.5f) / ibuf->x;
uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */
- if (IsectPoly2Df(uv, uv_clip, uv_clip_tot)) {
+ /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesnt work,
+ * could check the poly direction but better to do this */
+ if( (do_backfacecull && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) ||
+ (do_backfacecull==0 && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot))) {
has_x_isect = has_isect = 1;
@@ -2518,7 +2547,6 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
float (*outset_uv)[2] = ps->faceSeamUVs[face_index];
float insetCos[4][3]; /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in prespective view */
- float *uv_seam_quad[4];
float fac;
float *vCoSS[4]; /* vertex screenspace coords */
@@ -2574,16 +2602,11 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
fac1 = Vec2Lenf(vCoSS[fidx1], bucket_clip_edges[0]) / ftot;
fac2 = Vec2Lenf(vCoSS[fidx1], bucket_clip_edges[1]) / ftot;
- uv_seam_quad[0] = tf_uv_pxoffset[fidx1];
- uv_seam_quad[1] = tf_uv_pxoffset[fidx2];
- uv_seam_quad[2] = outset_uv[fidx2];
- uv_seam_quad[3] = outset_uv[fidx1];
-
- Vec2Lerpf(seam_subsection[0], uv_seam_quad[0], uv_seam_quad[1], fac1);
- Vec2Lerpf(seam_subsection[1], uv_seam_quad[0], uv_seam_quad[1], fac2);
-
- Vec2Lerpf(seam_subsection[2], uv_seam_quad[3], uv_seam_quad[2], fac2);
- Vec2Lerpf(seam_subsection[3], uv_seam_quad[3], uv_seam_quad[2], fac1);
+ Vec2Lerpf(seam_subsection[0], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac1);
+ Vec2Lerpf(seam_subsection[1], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac2);
+
+ Vec2Lerpf(seam_subsection[2], outset_uv[fidx1], outset_uv[fidx2], fac2);
+ Vec2Lerpf(seam_subsection[3], outset_uv[fidx1], outset_uv[fidx2], fac1);
/* if the bucket_clip_edges values Z values was kept we could avoid this
* Inset needs to be added so occlusion tests wont hit adjacent faces */
@@ -2636,14 +2659,28 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
/* Only bother calculating the weights if we intersect */
if (ps->do_mask_normal || ps->dm_mtface_clone) {
- /* TODO, this is not QUITE correct since UV is not inside the UV's but good enough for seams */
+#if 0
+ /* This is not QUITE correct since UV is not inside the UV's but good enough for seams */
if (side) {
BarycentricWeights2f(uv, tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], w);
}
else {
BarycentricWeights2f(uv, tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], w);
}
-
+#endif
+#if 1
+ /* Cheat, we know where we are along the edge so work out the weights from that */
+ fac = fac1 + (fac * (fac2-fac1));
+ w[0]=w[1]=w[2]= 0.0;
+ if (side) {
+ w[fidx1?fidx1-1:0] = fac;
+ w[fidx2?fidx2-1:0] = 1.0-fac;
+ }
+ else {
+ w[fidx1] = fac;
+ w[fidx2] = 1.0-fac;
+ }
+#endif
}
/* a pitty we need to get the worldspace pixel location here */
@@ -3076,7 +3113,7 @@ static void project_paint_begin(ProjPaintState *ps)
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);
+ /* 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 */
@@ -3232,7 +3269,7 @@ static void project_paint_begin(ProjPaintState *ps)
image_index = BLI_linklist_index(image_LinkList, tf->tpage);
- if (image_index==-1 && BKE_image_get_ibuf((Image *)tf->tpage, NULL)) { /* MemArena dosnt have an append func */
+ if (image_index==-1 && BKE_image_get_ibuf(tf->tpage, NULL)) { /* MemArena dosnt have an append func */
BLI_linklist_append(&image_LinkList, tf->tpage);
image_index = ps->image_tot;
ps->image_tot++;
@@ -3254,10 +3291,10 @@ static void project_paint_begin(ProjPaintState *ps)
for (node= image_LinkList, i=0; node; node= node->next, i++, projIma++) {
projIma->ima = node->link;
- // calloced - projIma->touch = 0;
+ projIma->touch = 0;
projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL);
projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- // calloced - memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
}
/* we have built the array, discard the linked list */
@@ -3308,6 +3345,7 @@ static void project_paint_end(ProjPaintState *ps)
int size = sizeof(UndoTile **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y);
last_projIma->undoRect = (UndoTile **) BLI_memarena_alloc(arena, size);
memset(last_projIma->undoRect, 0, size);
+ last_projIma->ibuf->userflags |= IB_BITMAPDIRTY;
}
for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
@@ -3375,15 +3413,16 @@ static void project_paint_end(ProjPaintState *ps)
MEM_freeN(ps->bucketFaces);
MEM_freeN(ps->bucketFlags);
+#ifndef PROJ_DEBUG_NOSEAMBLEED
if (ps->seam_bleed_px > 0.0f) {
MEM_freeN(ps->vertFaces);
MEM_freeN(ps->faceSeamFlags);
MEM_freeN(ps->faceSeamUVs);
}
+#endif
if (ps->vertFlags) MEM_freeN(ps->vertFlags);
-
for (a=0; a<ps->thread_tot; a++) {
BLI_memarena_free(ps->arena_mt[a]);
}
@@ -3411,7 +3450,7 @@ static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot)
{
- int touch;
+ int touch= 0;
while (tot--) {
pr->x1 = MIN2(pr->x1, pr_other->x1);
pr->y1 = MIN2(pr->y1, pr_other->y1);
@@ -3539,6 +3578,7 @@ static void blend_color_mix(unsigned char *cp, const unsigned char *cp1, const u
cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
+ cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
}
static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2, const float fac)
@@ -3547,6 +3587,7 @@ static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2,
cp[0]= mfac*cp1[0] + fac*cp2[0];
cp[1]= mfac*cp1[1] + fac*cp2[1];
cp[2]= mfac*cp1[2] + fac*cp2[2];
+ cp[3]= mfac*cp1[3] + fac*cp2[3];
}
static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask)
@@ -3583,8 +3624,8 @@ static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, floa
if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0)
return;
-
- ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend);
+ /* ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
+ blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha*mask*255));
BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
}
@@ -3597,7 +3638,8 @@ static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, fl
return;
IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_smear, projPixel->pixel.f_pt);
- ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend);
+ /* (ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
+ blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, rgba_smear, (rgba_ub), (int)(alpha*mask*255));
BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
}
@@ -3708,12 +3750,12 @@ static void *do_projectpaint_thread(void *ph_v)
projPixel = (ProjPixel *)node->link;
- /*dist = Vec2Lenf(projPixel->projCoSS, pos);*/ /* correct but uses a sqrt */
+ /*dist = Vec2Lenf(projPixel->projCoSS, pos);*/ /* correct but uses a sqrtf */
dist_nosqrt = Vec2Lenf_nosqrt(projPixel->projCoSS, pos);
- /*if (dist < s->brush->size) {*/ /* correct but uses a sqrt */
+ /*if (dist < s->brush->size) {*/ /* correct but uses a sqrtf */
if (dist_nosqrt < brush_size_sqared) {
- falloff = brush_sample_falloff_noalpha(ps->brush, sqrt(dist_nosqrt));
+ falloff = brush_sample_falloff_noalpha(ps->brush, sqrtf(dist_nosqrt));
if (falloff > 0.0f) {
if (ps->is_texbrush) {
brush_sample_tex(ps->brush, projPixel->projCoSS, rgba);
@@ -3802,10 +3844,9 @@ static void *do_projectpaint_thread(void *ph_v)
*projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
}
- for (node= smearPixels_f; node; node= node->next) { /* this wont run for a float image */
+ for (node= smearPixels_f; node; node= node->next) {
projPixel = node->link;
IMAPAINT_CHAR_RGBA_TO_FLOAT(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.ch);
- node = node->next;
}
BLI_memarena_free(smearArena);
@@ -4261,7 +4302,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint
) {
ImBuf *ibuf;
- newimage = (Image*)((s->me->mtface+newfaceindex)->tpage);
+ newimage = (s->me->mtface+newfaceindex)->tpage;
ibuf= BKE_image_get_ibuf(newimage, s->sima? &s->sima->iuser: NULL);
if(ibuf && ibuf->rect)
@@ -4399,6 +4440,7 @@ typedef struct PaintOperation {
int first;
int prevmouse[2];
+ int brush_size_orig;
double starttime;
ViewContext vc;
@@ -4485,6 +4527,8 @@ static int paint_init(bContext *C, wmOperator *op)
pop->ps.brush = pop->s.brush;
pop->ps.tool = pop->s.tool;
pop->ps.blend = pop->s.blend;
+
+ pop->brush_size_orig = pop->ps.brush->size; /* not nice hack because 1 size brushes always fail with projection paint */
}
if(pop->mode != PAINT_MODE_2D) {
@@ -4504,6 +4548,10 @@ static int paint_init(bContext *C, wmOperator *op)
return 0;
}
+
+ /* Dont allow brush size below 2 */
+ if (pop->ps.brush->size<=1)
+ pop->ps.brush->size = 2;
}
/* note, if we have no UVs on the derived mesh, then we must return here */
@@ -4602,8 +4650,10 @@ static void paint_exit(bContext *C, wmOperator *op)
imapaint_canvas_free(&pop->s);
brush_painter_free(pop->painter);
- if(pop->mode == PAINT_MODE_3D_PROJECT)
+ if(pop->mode == PAINT_MODE_3D_PROJECT) {
+ pop->ps.brush->size = pop->brush_size_orig;
project_paint_end(&pop->ps);
+ }
paint_redraw(C, &pop->s, 1);
undo_imagepaint_push_end();
@@ -5186,3 +5236,4 @@ void PAINT_OT_texture_paint_radial_control(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
+