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:
authorCampbell Barton <ideasman42@gmail.com>2008-11-15 19:20:37 +0300
committerCampbell Barton <ideasman42@gmail.com>2008-11-15 19:20:37 +0300
commitdb434c3434806024e56e9b573adfbfcee3bd3304 (patch)
tree522b6fd1e30081666d99343fdce9b2e2386c46d3
parenta92969e8f1f6a72f129e46f95c296aebd9cace1c (diff)
* clone tool didnt work when the object was not at the center point.
* added clone button to the paint editbuttons (was only in the image window before) * ctrl+clicking to set the 3d cursor also sets its depth to the face its over (much more useful when cloning and rotating the view) * support for painting and cloning for tiled textures (for UV's outside 0-1) * more consistant veriable names, merged image arrays into a ProjectPaintImage type to be less confusing.
-rw-r--r--source/blender/src/buttons_editing.c12
-rw-r--r--source/blender/src/imagepaint.c661
2 files changed, 365 insertions, 308 deletions
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index b6dfd29d62a..1fd1538fb4b 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -6337,9 +6337,15 @@ static void editing_panel_mesh_paint(void)
yco= 160;
uiBlockBeginAlign(block);
- uiDefButS(block, ROW, B_BRUSHCHANGE, "Draw", 0 ,yco,108,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw 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, "Draw", 0 ,yco,108,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw 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_SIMABRUSHCHANGE, "Draw", 0 ,yco,80,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, "Smear", 160,yco,80,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");
+
uiBlockEndAlign(block);
yco -= 30;
diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c
index 64c4d6912d1..347e4cfb471 100644
--- a/source/blender/src/imagepaint.c
+++ b/source/blender/src/imagepaint.c
@@ -167,11 +167,19 @@ typedef struct ImagePaintPartialRedraw {
// #define PROJ_BUCKET_CLONE_INIT 1<<1
/* only for readability */
-#define PROJ_BUCKET_LEFT 0
+#define PROJ_BUCKET_LEFT 0
#define PROJ_BUCKET_RIGHT 1
#define PROJ_BUCKET_BOTTOM 2
#define PROJ_BUCKET_TOP 3
+typedef struct ProjectPaintImage {
+ Image *ima;
+ ImBuf *ibuf;
+ ImagePaintPartialRedraw *partRedrawRect;
+ struct UndoTile **undoRect; /* only used to build undo tiles after painting */
+ int touch;
+} ProjectPaintImage;
+
typedef struct ProjectPaintState {
Brush *brush;
short tool, blend;
@@ -187,51 +195,49 @@ typedef struct ProjectPaintState {
MTFace *dm_mtface;
/* projection painting only */
- MemArena *projectArena; /* use for alocating many pixel structs and link-lists */
- MemArena *projectArena_mt[BLENDER_MAX_THREADS]; /* Same as above but use for multithreading */
- LinkNode **projectBuckets; /* screen sized 2D array, each pixel has a linked list of ProjectPixel's */
- LinkNode **projectFaces; /* projectBuckets alligned array linkList of faces overlapping each bucket */
- char *projectBucketFlags; /* store if the bucks have been initialized */
+ 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 **bucketFaces; /* bucketRect alligned array linkList of faces overlapping each bucket */
+ char *bucketFlags; /* store if the bucks have been initialized */
#ifndef PROJ_DEBUG_NOSEAMBLEED
- char *projectFaceSeamFlags; /* store info about faces, if they are initialized etc*/
- float (*projectFaceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */
- LinkNode **projectVertFaces; /* Only needed for when projectSeamBleed is enabled, use to find UV seams */
+ 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 */
#endif
- int bucketsX; /* The size of the bucket grid, the grid span's viewMin2D/viewMax2D so you can paint outsize the screen or with 2 brushes at once */
- int bucketsY;
+ 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;
- Image **projectImages; /* array of images we are painting onto while, use so we can tag for updates */
- ImBuf **projectImBufs; /* array of imbufs we are painting onto while, use so we can get the rect and rect_float quickly */
- ImagePaintPartialRedraw *projectPartialRedraws[PROJ_BOUNDBOX_SQUARED]; /* array of partial redraws */
+ ProjectPaintImage *projImages;
- int projectImageTotal; /* size of projectImages array */
+ int image_tot; /* size of projectImages array */
- float (*projectVertScreenCos)[4]; /* verts projected into floating point screen space */
+ float (*screenCoords)[4]; /* verts projected into floating point screen space */
/* options for projection painting */
- short projectIsOcclude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
- short projectIsBackfaceCull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
- short projectIsOrtho;
+ 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;
#ifndef PROJ_DEBUG_NOSEAMBLEED
- float projectSeamBleed;
+ float seam_bleed_px;
#endif
/* clone vars */
- float cloneOfs[2];
+ float clone_offset[2];
float projectMat[4][4]; /* Projection matrix, use for getting screen coords */
float viewMat[4][4];
- float viewDir[3]; /* View vector, use for projectIsBackfaceCull and for ray casting with an ortho viewport */
+ float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */
- float viewMin2D[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */
- float viewMax2D[2];
- float viewWidth; /* Calculated from viewMin2D & viewMax2D */
- float viewHeight;
+ float screen_min[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */
+ float screen_max[2];
+ float screen_width; /* Calculated from screen_min & screen_max */
+ float screen_height;
/* threads */
int thread_tot;
- int min_bucket[2];
- int max_bucket[2];
+ int bucket_min[2];
+ int bucket_max[2];
int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */
} ProjectPaintState;
@@ -294,8 +300,11 @@ static void undo_copy_tile(UndoTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int rest
IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x*IMAPAINT_TILE_SIZE,
tile->y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
- if(ibuf->rect_float) SWAP(void*, tmpibuf->rect_float, tile->rect)
- else SWAP(void*, tmpibuf->rect, tile->rect)
+ if(ibuf->rect_float) {
+ SWAP(void*, tmpibuf->rect_float, tile->rect);
+ } else {
+ SWAP(void*, tmpibuf->rect, tile->rect);
+ }
if(restore)
IMB_rectcpy(ibuf, tmpibuf, tile->x*IMAPAINT_TILE_SIZE,
@@ -443,24 +452,24 @@ static void undo_imagepaint_push_end()
static int project_paint_BucketOffset(ProjectPaintState *ps, float projCo2D[2])
{
/* If we were not dealing with screenspace 2D coords we could simple do...
- * ps->projectBuckets[x + (y*ps->bucketsY)] */
+ * ps->bucketRect[x + (y*ps->buckets_y)] */
/* please explain?
- * projCo2D[0] - ps->viewMin2D[0] : zero origin
- * ... / ps->viewWidth : range from 0.0 to 1.0
- * ... * ps->bucketsX : use as a bucket index
+ * projCo2D[0] - ps->screen_min[0] : zero origin
+ * ... / ps->screen_width : range from 0.0 to 1.0
+ * ... * ps->buckets_x : use as a bucket index
*
* Second multiplication does similar but for vertical offset
*/
- return ( (int)(( (projCo2D[0] - ps->viewMin2D[0]) / ps->viewWidth) * ps->bucketsX)) +
- ( ( (int)(( (projCo2D[1] - ps->viewMin2D[1]) / ps->viewHeight) * ps->bucketsY)) * ps->bucketsX );
+ return ( (int)(( (projCo2D[0] - ps->screen_min[0]) / ps->screen_width) * ps->buckets_x)) +
+ ( ( (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])
{
int bucket_index = project_paint_BucketOffset(ps, projCo2D);
- if (bucket_index < 0 || bucket_index >= ps->bucketsX*ps->bucketsY) {
+ if (bucket_index < 0 || bucket_index >= ps->buckets_x*ps->buckets_y) {
return -1;
} else {
return bucket_index;
@@ -479,7 +488,6 @@ static void BarycentricWeightsSimple2f(float v1[2], float v2[2], float v3[2], fl
w[1]/=wtot;
w[2]/=wtot;
} else {
- printf("WATCH oUT ZAREA FACE\n");
w[0] = w[1] = w[2] = 1.0/3.0; /* dummy values for zero area face */
}
}
@@ -548,7 +556,7 @@ static float tri_depth_2d(float v1[3], float v2[3], float v3[3], float pt[2], fl
/* return the topmost face in screen coords index or -1
* bucket_index can be -1 if we dont know it to begin with */
-static int screenco_pickface(ProjectPaintState *ps, float pt[2], float w[3], int *side) {
+static int project_paint_PickFace(ProjectPaintState *ps, float pt[2], float w[3], int *side) {
LinkNode *node;
float w_tmp[3];
float *v1, *v2, *v3, *v4;
@@ -563,7 +571,7 @@ static int screenco_pickface(ProjectPaintState *ps, float pt[2], float w[3], int
if (bucket_index==-1)
return -1;
- node = ps->projectFaces[bucket_index];
+ node = ps->bucketFaces[bucket_index];
/* 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 */
@@ -572,9 +580,9 @@ static int screenco_pickface(ProjectPaintState *ps, float pt[2], float w[3], int
face_index = (int)node->link;
mf = ps->dm_mface + face_index;
- v1 = ps->projectVertScreenCos[mf->v1];
- v2 = ps->projectVertScreenCos[mf->v2];
- v3 = ps->projectVertScreenCos[mf->v3];
+ v1 = ps->screenCoords[mf->v1];
+ v2 = ps->screenCoords[mf->v2];
+ v3 = ps->screenCoords[mf->v3];
if ( IsectPT2Df(pt, v1, v2, v3) ) {
z_depth = tri_depth_2d(v1,v2,v3,pt,w_tmp);
@@ -585,7 +593,7 @@ static int screenco_pickface(ProjectPaintState *ps, float pt[2], float w[3], int
VECCOPY(w, w_tmp);
}
} else if (mf->v4) {
- v4 = ps->projectVertScreenCos[mf->v4];
+ v4 = ps->screenCoords[mf->v4];
if ( IsectPT2Df(pt, v1, v3, v4) ) {
z_depth = tri_depth_2d(v1,v3,v4,pt,w_tmp);
@@ -695,7 +703,7 @@ static void bicubic_interpolation_px(ImBuf *in, float x, float y, float rgba_fp[
/* bucket_index is optional, since in some cases we know it */
/* TODO FLOAT */ /* add a function that does this for float buffers */
-static int screenco_pickcol(ProjectPaintState *ps, float pt[2], float *rgba_fp, char *rgba, int interp)
+static int project_paint_PickColor(ProjectPaintState *ps, float pt[2], float *rgba_fp, char *rgba, int interp)
{
float w[3], uv[2];
int side;
@@ -705,7 +713,7 @@ static int screenco_pickcol(ProjectPaintState *ps, float pt[2], float *rgba_fp,
int xi,yi;
- face_index = screenco_pickface(ps,pt,w, &side);
+ face_index = project_paint_PickFace(ps,pt,w, &side);
if (face_index == -1)
return 0;
@@ -726,8 +734,16 @@ static int screenco_pickcol(ProjectPaintState *ps, float pt[2], float *rgba_fp,
if (interp) {
float x,y;
- x = uv[0]*ibuf->x;
- y = uv[1]*ibuf->y;
+ /* use */
+ x = (float)fmod(uv[0], 1.0);
+ y = (float)fmod(uv[1], 1.0);
+
+ if (x < 0.0) x += 1.0;
+ if (y < 0.0) y += 1.0;
+
+ x *= ibuf->x;
+ y *= ibuf->y;
+
if (ibuf->rect_float) {
if (rgba_fp) {
bicubic_interpolation_px(ibuf, x, y, rgba_fp, NULL);
@@ -749,7 +765,14 @@ static int screenco_pickcol(ProjectPaintState *ps, float pt[2], float *rgba_fp,
xi = uv[0]*ibuf->x;
yi = uv[1]*ibuf->y;
- if (xi<0 || xi>=ibuf->x || yi<0 || yi>=ibuf->y) return 0;
+ //if (xi<0 || xi>=ibuf->x || yi<0 || yi>=ibuf->y) return 0;
+
+ /* wrap */
+ xi = ((int)(uv[0]*ibuf->x)) % ibuf->x;
+ if (xi<0) xi += ibuf->x;
+ yi = ((int)(uv[1]*ibuf->y)) % ibuf->y;
+ if (yi<0) yi += ibuf->y;
+
if (rgba) {
if (ibuf->rect_float) {
@@ -775,7 +798,7 @@ static int screenco_pickcol(ProjectPaintState *ps, float pt[2], float *rgba_fp,
* -1 : no occlusion but 2D intersection is true (avoid testing the other half of a quad)
* 1 : occluded */
-static int screenco_tri_pt_occlude(float pt[3], float v1[3], float v2[3], float v3[3])
+static int project_paint_PointOcclude(float pt[3], float v1[3], float v2[3], float v3[3])
{
/* if all are behind us, return false */
if(v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
@@ -804,7 +827,7 @@ static int screenco_tri_pt_occlude(float pt[3], float v1[3], float v2[3], float
/* check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison */
static int project_bucket_point_occluded(ProjectPaintState *ps, int bucket_index, int orig_face, float pixelScreenCo[4])
{
- LinkNode *node = ps->projectFaces[bucket_index];
+ LinkNode *node = ps->bucketFaces[bucket_index];
MFace *mf;
int face_index;
int isect_ret;
@@ -819,19 +842,19 @@ static int project_bucket_point_occluded(ProjectPaintState *ps, int bucket_index
mf = ps->dm_mface + face_index;
- isect_ret = screenco_tri_pt_occlude(
+ isect_ret = project_paint_PointOcclude(
pixelScreenCo,
- ps->projectVertScreenCos[mf->v1],
- ps->projectVertScreenCos[mf->v2],
- ps->projectVertScreenCos[mf->v3]);
+ ps->screenCoords[mf->v1],
+ ps->screenCoords[mf->v2],
+ ps->screenCoords[mf->v3]);
/* Note, if isect_ret==-1 then we dont want to test the other side of the quad */
if (isect_ret==0 && mf->v4) {
- isect_ret = screenco_tri_pt_occlude(
+ isect_ret = project_paint_PointOcclude(
pixelScreenCo,
- ps->projectVertScreenCos[mf->v1],
- ps->projectVertScreenCos[mf->v3],
- ps->projectVertScreenCos[mf->v4]);
+ ps->screenCoords[mf->v1],
+ ps->screenCoords[mf->v3],
+ ps->screenCoords[mf->v4]);
}
if (isect_ret==1) {
@@ -840,12 +863,12 @@ static int project_bucket_point_occluded(ProjectPaintState *ps, int bucket_index
* This function runs for every UV Screen pixel,
* therefor swapping the swapping the faces for this buckets list helps because
* the next ~5 to ~200 runs will can hit the first face each time. */
- if (ps->projectFaces[bucket_index] != node) {
- /* SWAP(void *, ps->projectFaces[bucket_index]->link, node->link); */
+ if (ps->bucketFaces[bucket_index] != node) {
+ /* SWAP(void *, ps->bucketFaces[bucket_index]->link, node->link); */
/* dont need to use swap since we alredy have face_index */
- node->link = ps->projectFaces[bucket_index]->link; /* move the value item to the current value */
- ps->projectFaces[bucket_index]->link = (void *) face_index;
+ node->link = ps->bucketFaces[bucket_index]->link; /* move the value item to the current value */
+ ps->bucketFaces[bucket_index]->link = (void *) face_index;
/*printf("swapping %d %d\n", (int)node->link, face_index);*/
} /*else {
@@ -963,7 +986,7 @@ static int project_face_scanline(ProjectScanline *sc, float y_level, float v1[2]
sc->v[1] = 2;
sc->v[2] = 3;
sc->x_limits[0] = MIN2((i3?xi3:xi4), xi_mid);
- sc->x_limits[1] = MAX2((i3?xi3:xi4), xi_mid);
+ sc->x_limits[1PROJ_DEBUG_NOSEAMBLEED] = MAX2((i3?xi3:xi4), xi_mid);
totscanlines = 2;
}
@@ -1006,11 +1029,13 @@ static int project_face_scanline(ProjectScanline *sc, float y_level, float v1[2]
return totscanlines;
}
#endif // PROJ_DEBUG_NOSCANLINE
+
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 zero if there is no area in the returned rectangle */
static int uv_image_rect(float uv1[2], float uv2[2], float uv3[2], float uv4[2], int min_px[2], int max_px[2], int x_px, int y_px, int is_quad)
{
@@ -1031,11 +1056,6 @@ static int uv_image_rect(float uv1[2], float uv2[2], float uv3[2], float uv4[2],
max_px[1] = (int)(y_px * max_uv[1]) +1;
/*printf("%d %d %d %d \n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
- CLAMP(min_px[0], 0, x_px);
- CLAMP(max_px[0], 0, x_px);
-
- CLAMP(min_px[1], 0, y_px);
- CLAMP(max_px[1], 0, y_px);
/* face uses no UV area when quantized to pixels? */
return (min_px[0] == max_px[0] || min_px[1] == max_px[1]) ? 0 : 1;
@@ -1059,7 +1079,7 @@ static int check_seam(ProjectPaintState *ps, int orig_face, int orig_i1_fidx, in
i1 = (*(&orig_mf->v1 + orig_i1_fidx));
i2 = (*(&orig_mf->v1 + orig_i2_fidx));
- for (node = ps->projectVertFaces[i1]; node; node = node->next) {
+ for (node = ps->vertFaces[i1]; node; node = node->next) {
face_index = (int)node->link;
if (face_index != orig_face) {
mf = ps->dm_mface + face_index;
@@ -1255,15 +1275,15 @@ static void project_face_seams_init(ProjectPaintState *ps, int face_index, int i
else
fidx2 = (fidx1==2) ? 0 : fidx1+1; /* next fidx in the face (0,1,2) -> (1,2,0) */
- if ((ps->projectFaceSeamFlags[face_index] & (1<<fidx1|16<<fidx1)) == 0) {
+ if ((ps->faceSeamFlags[face_index] & (1<<fidx1|16<<fidx1)) == 0) {
if (check_seam(ps, face_index, fidx1,fidx2, &other_face, &other_fidx)) {
- ps->projectFaceSeamFlags[face_index] |= 1<<fidx1;
+ ps->faceSeamFlags[face_index] |= 1<<fidx1;
if (other_face != -1)
- ps->projectFaceSeamFlags[other_face] |= 1<<other_fidx;
+ ps->faceSeamFlags[other_face] |= 1<<other_fidx;
} else {
- ps->projectFaceSeamFlags[face_index] |= 16<<fidx1;
+ ps->faceSeamFlags[face_index] |= 16<<fidx1;
if (other_face != -1)
- ps->projectFaceSeamFlags[other_face] |= 16<<other_fidx; /* second 4 bits for disabled */
+ ps->faceSeamFlags[other_face] |= 16<<other_fidx; /* second 4 bits for disabled */
}
}
} while (fidx1--);
@@ -1329,13 +1349,22 @@ static void project_paint_uvpixel_init(ProjectPaintState *ps, int thread_index,
// printf("adding px (%d %d), (%f %f)\n", x,y,uv[0],uv[1]);
- /* Use viewMin2D to make (0,0) the bottom left of the bounds
+ /* 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 */
- /* screenco_pickface is less complex, use for testing */
- //if (screenco_pickface(ps, pixelScreenCo, w, &side) == face_index) {
- if (ps->projectIsOcclude==0 || !project_bucket_point_occluded(ps, bucket_index, face_index, pixelScreenCo)) {
+ /* 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)) {
+
+ /* wrap pixel location */
+ // printf(" %d %d", x, y);
+ x = x % ibuf->x;
+ if (x<0) x += ibuf->x;
+ y = y % ibuf->y;
+ if (y<0) y += ibuf->y;
+ // printf(" %d %d\n", x, y);
+
if (ps->tool==PAINT_TOOL_CLONE) {
if (ibuf->rect_float) {
@@ -1349,7 +1378,7 @@ static void project_paint_uvpixel_init(ProjectPaintState *ps, int thread_index,
size = sizeof(ProjectPixel);
}
- projPixel = (ProjectPixel *)BLI_memarena_alloc(ps->projectArena_mt[thread_index], size);
+ projPixel = (ProjectPixel *)BLI_memarena_alloc(ps->arena_mt[thread_index], size);
if (ibuf->rect_float) {
projPixel->pixel = (void *) ((( float * ) ibuf->rect_float) + (( x + y * ibuf->x ) * pixel_size));
@@ -1360,13 +1389,11 @@ static void project_paint_uvpixel_init(ProjectPaintState *ps, int thread_index,
}
VECCOPY2D(projPixel->projCo2D, pixelScreenCo);
+
projPixel->x_px = x;
projPixel->y_px = y;
/* which bounding box cell are we in? */
- //projPixel->x_bb = (char) ;
- //projPixel->y_bb = (char) (((float)y/(float)ibuf->y) * PROJ_BOUNDBOX_DIV);
-
projPixel->bb_cell_index = ((int)((((float)x)/((float)ibuf->x)) * PROJ_BOUNDBOX_DIV)) + ((int)((((float)y)/((float)ibuf->y)) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV ;
/* done with view3d_project_float inline */
@@ -1375,16 +1402,16 @@ static void project_paint_uvpixel_init(ProjectPaintState *ps, int thread_index,
/* Initialize clone pixels - note that this is a bit of a waste since some of these are being indirectly initialized :/ */
/* TODO - possibly only run this for directly ativated buckets when cloning */
- Vec2Subf(co, projPixel->projCo2D, ps->cloneOfs);
+ Vec2Subf(co, projPixel->projCo2D, ps->clone_offset);
/* no need to initialize the bucket, we're only checking buckets faces and for this
* the faces are alredy initialized in project_paint_delayed_face_init(...) */
if (ibuf->rect_float) {
- if (!screenco_pickcol(ps, co, ((ProjectPixelCloneFloat *)projPixel)->clonepx, NULL, 1)) {
+ if (!project_paint_PickColor(ps, co, ((ProjectPixelCloneFloat *)projPixel)->clonepx, NULL, 1)) {
((ProjectPixelCloneFloat *)projPixel)->clonepx[3] = 0; /* zero alpha - ignore */
}
} else {
- if (!screenco_pickcol(ps, co, NULL, ((ProjectPixelClone *)projPixel)->clonepx, 1)) {
+ if (!project_paint_PickColor(ps, co, NULL, ((ProjectPixelClone *)projPixel)->clonepx, 1)) {
((ProjectPixelClone *)projPixel)->clonepx[3] = 0; /* zero alpha - ignore */
}
}
@@ -1399,9 +1426,9 @@ static void project_paint_uvpixel_init(ProjectPaintState *ps, int thread_index,
projPixel->image_index = image_index;
BLI_linklist_prepend_arena(
- &ps->projectBuckets[ bucket_index ],
+ &ps->bucketRect[ bucket_index ],
projPixel,
- ps->projectArena_mt[thread_index]
+ ps->arena_mt[thread_index]
);
}
}
@@ -1557,14 +1584,14 @@ static void rect_to_uvspace(
/* get the UV space bounding box */
uv[0] = bucket_bounds[PROJ_BUCKET_RIGHT];
uv[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
- if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+ if (ps->is_ortho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
else BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
bucket_bounds_uv[0][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
bucket_bounds_uv[0][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
//uv[0] = bucket_bounds[PROJ_BUCKET_RIGHT]; // set above
uv[1] = bucket_bounds[PROJ_BUCKET_TOP];
- if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+ if (ps->is_ortho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
else BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
bucket_bounds_uv[1][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
bucket_bounds_uv[1][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
@@ -1572,14 +1599,14 @@ static void rect_to_uvspace(
uv[0] = bucket_bounds[PROJ_BUCKET_LEFT];
//uv[1] = bucket_bounds[PROJ_BUCKET_TOP]; // set above
- if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+ if (ps->is_ortho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
else BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
bucket_bounds_uv[2][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
bucket_bounds_uv[2][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
//uv[0] = bucket_bounds[PROJ_BUCKET_LEFT]; // set above
uv[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
- if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
+ if (ps->is_ortho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
else BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
bucket_bounds_uv[3][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
bucket_bounds_uv[3][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
@@ -1613,6 +1640,10 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
/* vars for getting uvspace bounds */
float bucket_bounds_uv[4][2]; /* bucket bounds in UV space so we can init pixels only for this face, */
+ float tf_uv_pxoffset[4][2]; /* bucket bounds in UV space so we can init pixels only for this face, */
+ float xhalfpx, yhalfpx;
+ float ibuf_xf = ibuf->x, ibuf_yf = ibuf->y;
+
int i1,i2,i3;
/* scanlines since quads can have 2 triangles intersecting the same vertical location */
@@ -1625,10 +1656,31 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
vCo[0] = ps->dm_mvert[ (*(&mf->v1 )) ].co;
vCo[1] = ps->dm_mvert[ (*(&mf->v1 + 1)) ].co;
vCo[2] = ps->dm_mvert[ (*(&mf->v1 + 2)) ].co;
- if (mf->v4)
- vCo[3] = ps->dm_mvert[ (*(&mf->v1 + 3)) ].co;
+
+
+
+ xhalfpx = 0.5 / ibuf_xf;
+ yhalfpx = 0.5 / ibuf_yf;
+
+ tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx;
+ tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx;
- i = mf->v4 ? 1:0;
+ tf_uv_pxoffset[1][0] = tf->uv[1][0] - xhalfpx;
+ tf_uv_pxoffset[1][1] = tf->uv[1][1] - yhalfpx;
+
+ tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx;
+ tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx;
+
+ if (mf->v4) {
+ vCo[3] = ps->dm_mvert[ (*(&mf->v1 + 3)) ].co;
+
+ tf_uv_pxoffset[3][0] = tf->uv[3][0] - xhalfpx;
+ tf_uv_pxoffset[3][1] = tf->uv[3][1] - yhalfpx;
+ i = 1;
+ } else {
+ i = 0;
+ }
+
do {
if (i==1) {
i1=0; i2=2; i3=3;
@@ -1636,13 +1688,13 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
i1=0; i2=1; i3=2;
}
- uv1co = tf->uv[i1];
- uv2co = tf->uv[i2];
- uv3co = tf->uv[i3];
+ uv1co = tf_uv_pxoffset[i1]; // was tf->uv[i1];
+ uv2co = tf_uv_pxoffset[i2]; // was tf->uv[i2];
+ uv3co = tf_uv_pxoffset[i3]; // was tf->uv[i3];
- v1coSS = ps->projectVertScreenCos[ (*(&mf->v1 + i1)) ];
- v2coSS = ps->projectVertScreenCos[ (*(&mf->v1 + i2)) ];
- v3coSS = ps->projectVertScreenCos[ (*(&mf->v1 + i3)) ];
+ v1coSS = ps->screenCoords[ (*(&mf->v1 + i1)) ];
+ v2coSS = ps->screenCoords[ (*(&mf->v1 + i2)) ];
+ v3coSS = ps->screenCoords[ (*(&mf->v1 + i3)) ];
rect_to_uvspace(ps, bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv);
@@ -1658,34 +1710,36 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
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 */
+ //uv[1] = (((float)y) + 0.5) / (float)ibuf->y;
+ uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */
for (x = min_px[0]; x < max_px[0]; x++) {
- uv[0] = (((float)x)+0.5) / (float)ibuf->x;
+ //uv[0] = (((float)x) + 0.5) / ibuf->x;
+ uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */
/* test we're inside uvspace bucket and triangle bounds */
if ( IsectPQ2Df(uv, bucket_bounds_uv[0], bucket_bounds_uv[1], bucket_bounds_uv[2], bucket_bounds_uv[3]) &&
IsectPT2Df(uv, uv1co, uv2co, uv3co) ) {
- if (ps->projectIsOrtho) {
+ if (ps->is_ortho) {
screen_px_from_ortho(ps, uv, v1coSS,v2coSS,v3coSS, uv1co,uv2co,uv3co, pixelScreenCo);
} else {
screen_px_from_persp(ps, uv, vCo[i1],vCo[i2],vCo[i3], uv1co,uv2co,uv3co, pixelScreenCo);
}
- project_paint_uvpixel_init(ps, thread_index, ibuf, x,y, bucket_index, face_index, image_index, pixelScreenCo);
+ project_paint_uvpixel_init(ps, thread_index, ibuf, x, y, bucket_index, face_index, image_index, pixelScreenCo);
}
}
}
}
} while(i--);
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->projectSeamBleed > 0.0) {
+ if (ps->seam_bleed_px > 0.0) {
int face_seam_flag;
if (ps->thread_tot > 1)
BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
- face_seam_flag = ps->projectFaceSeamFlags[face_index];
+ face_seam_flag = ps->faceSeamFlags[face_index];
/* are any of our edges un-initialized? */
if ((face_seam_flag & (PROJ_FACE_SEAM1|PROJ_FACE_NOSEAM1))==0 ||
@@ -1694,7 +1748,7 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
(face_seam_flag & (PROJ_FACE_SEAM4|PROJ_FACE_NOSEAM4))==0
) {
project_face_seams_init(ps, face_index, mf->v4);
- face_seam_flag = ps->projectFaceSeamFlags[face_index];
+ face_seam_flag = ps->faceSeamFlags[face_index];
//printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2, flag&PROJ_FACE_SEAM3, flag&PROJ_FACE_SEAM4);
}
@@ -1721,22 +1775,22 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
float seam_subsection[4][2];
float fac1, fac2, ftot;
- outset_uv = ps->projectFaceSeamUVs[face_index];
+ outset_uv = ps->faceSeamUVs[face_index];
if (outset_uv[0][0]==MAXFLOAT) /* first time initialize */
- uv_image_outset(tf->uv, outset_uv, ps->projectSeamBleed, ibuf->x, ibuf->y, mf->v4);
+ uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4);
- /* ps->projectFaceSeamUVs cant be modified when threading, now this is done we can unlock */
+ /* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
if (ps->thread_tot > 1)
BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
- vCoSS[0] = ps->projectVertScreenCos[ mf->v1 ];
- vCoSS[1] = ps->projectVertScreenCos[ mf->v2 ];
- vCoSS[2] = ps->projectVertScreenCos[ mf->v3 ];
+ vCoSS[0] = ps->screenCoords[ mf->v1 ];
+ vCoSS[1] = ps->screenCoords[ mf->v2 ];
+ vCoSS[2] = ps->screenCoords[ mf->v3 ];
if (mf->v4)
- vCoSS[3] = ps->projectVertScreenCos[ mf->v4 ];
+ vCoSS[3] = ps->screenCoords[ mf->v4 ];
- if (ps->projectIsOrtho) {
+ if (ps->is_ortho) {
if (mf->v4) scale_quad(vCoSS, insetCos, 0.99999);
else scale_tri(vCoSS, insetCos, 0.99999);
} else {
@@ -1759,8 +1813,8 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
fac1 = Vec2Lenf(vCoSS[fidx1], bucket_clip_edges[0]) / ftot;
fac2 = Vec2Lenf(vCoSS[fidx1], bucket_clip_edges[1]) / ftot;
- uv_seam_quad[0] = tf->uv[fidx1];
- uv_seam_quad[1] = tf->uv[fidx2];
+ 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];
@@ -1771,7 +1825,7 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
Vec2Lerpf(seam_subsection[3], uv_seam_quad[3], uv_seam_quad[2], fac1);
/* if the bucket_clip_edges values Z values was kept we could avoid this
- * Inset needs to be added so occlusiuon tests wont hit adjacent faces */
+ * Inset needs to be added so occlusion tests wont hit adjacent faces */
VecLerpf(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1);
VecLerpf(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2);
@@ -1780,21 +1834,21 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
/* bounds between the seam rect and the uvspace bucket pixels */
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 */
+ // uv[1] = (((float)y) + 0.5) / (float)ibuf->y;
+ uv[1] = (float)y / ibuf_yf; /* use offset uvs instead */
for (x = min_px[0]; x < max_px[0]; x++) {
-
- uv[0] = (((float)x)+0.5) / (float)ibuf->x;
+ //uv[0] = (((float)x) + 0.5) / (float)ibuf->x;
+ uv[0] = (float)x / ibuf_xf; /* use offset uvs instead */
/* test we're inside uvspace bucket and triangle bounds */
if ( IsectPQ2Df(uv, seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3]) ) {
- /* We need to find the closest point allong the face edge,
+ /* We need to find the closest point along the face edge,
* getting the screen_px_from_*** wont work because our actual location
* is not relevent, since we are outside the face, Use VecLerpf to find
* our location on the side of the face's UV */
/*
- if (ps->projectIsOrtho) screen_px_from_ortho(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
+ if (ps->is_ortho) screen_px_from_ortho(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
else screen_px_from_persp(ps, uv, v1co,v2co,v3co, uv1co,uv2co,uv3co, pixelScreenCo);
*/
@@ -1806,7 +1860,7 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
else if (fac > 1.0) { VECCOPY(pixelScreenCo, edge_verts_inset_clip[1]); }
else { VecLerpf(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); }
- if (!ps->projectIsOrtho) {
+ if (!ps->is_ortho) {
pixelScreenCo[3] = 1.0;
Mat4MulVec4fl(ps->projectMat, pixelScreenCo);
pixelScreenCo[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*pixelScreenCo[0]/pixelScreenCo[3];
@@ -1828,31 +1882,31 @@ static void project_paint_face_init(ProjectPaintState *ps, int thread_index, int
}
-/* takes floating point screenspace min/max and returns int min/max to be used as indicies for ps->projectBuckets, ps->projectBucketFlags */
+/* takes floating point screenspace min/max and returns int min/max to be used as indicies for ps->bucketRect, ps->bucketFlags */
static void project_paint_rect(ProjectPaintState *ps, float min[2], float max[2], int bucket_min[2], int bucket_max[2])
{
/* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
- bucket_min[0] = (int)(((float)(min[0] - ps->viewMin2D[0]) / ps->viewWidth) * ps->bucketsX) + 0.5; /* these offsets of 0.5 and 1.5 seem odd but they are correct */
- bucket_min[1] = (int)(((float)(min[1] - ps->viewMin2D[1]) / ps->viewHeight) * ps->bucketsY) + 0.5;
+ bucket_min[0] = (int)(((float)(min[0] - ps->screen_min[0]) / ps->screen_width) * ps->buckets_x) + 0.5; /* these offsets of 0.5 and 1.5 seem odd but they are correct */
+ bucket_min[1] = (int)(((float)(min[1] - ps->screen_min[1]) / ps->screen_height) * ps->buckets_y) + 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->screen_min[0]) / ps->screen_width) * ps->buckets_x) + 1.5;
+ bucket_max[1] = (int)(((float)(max[1] - ps->screen_min[1]) / ps->screen_height) * ps->buckets_y) + 1.5;
/* incase the rect is outside the mesh 2d bounds */
- CLAMP(bucket_min[0], 0, ps->bucketsX);
- CLAMP(bucket_min[1], 0, ps->bucketsY);
+ CLAMP(bucket_min[0], 0, ps->buckets_x);
+ CLAMP(bucket_min[1], 0, ps->buckets_y);
- CLAMP(bucket_max[0], 0, ps->bucketsX);
- CLAMP(bucket_max[1], 0, ps->bucketsY);
+ CLAMP(bucket_max[0], 0, ps->buckets_x);
+ CLAMP(bucket_max[1], 0, ps->buckets_y);
}
static void project_bucket_bounds(ProjectPaintState *ps, int bucket_x, int bucket_y, float bucket_bounds[4])
{
- bucket_bounds[ PROJ_BUCKET_LEFT ] = ps->viewMin2D[0]+((bucket_x)*(ps->viewWidth / ps->bucketsX)); /* left */
- bucket_bounds[ PROJ_BUCKET_RIGHT ] = ps->viewMin2D[0]+((bucket_x+1)*(ps->viewWidth / ps->bucketsX)); /* right */
+ bucket_bounds[ PROJ_BUCKET_LEFT ] = ps->screen_min[0]+((bucket_x)*(ps->screen_width / ps->buckets_x)); /* left */
+ bucket_bounds[ PROJ_BUCKET_RIGHT ] = ps->screen_min[0]+((bucket_x+1)*(ps->screen_width / ps->buckets_x)); /* right */
- bucket_bounds[ PROJ_BUCKET_BOTTOM ] = ps->viewMin2D[1]+((bucket_y)*(ps->viewHeight / ps->bucketsY)); /* bottom */
- bucket_bounds[ PROJ_BUCKET_TOP ] = ps->viewMin2D[1]+((bucket_y+1)*(ps->viewHeight / ps->bucketsY)); /* top */
+ bucket_bounds[ PROJ_BUCKET_BOTTOM ] = ps->screen_min[1]+((bucket_y)*(ps->screen_height / ps->buckets_y)); /* bottom */
+ bucket_bounds[ PROJ_BUCKET_TOP ] = ps->screen_min[1]+((bucket_y+1)*(ps->screen_height / ps->buckets_y)); /* top */
}
/* have bucket_bounds as an arg so we dont need to give bucket_x/y the rect function need */
@@ -1866,7 +1920,7 @@ static void project_paint_bucket_init(ProjectPaintState *ps, int thread_index, i
Image *tpage_last = NULL;
int tpage_index;
- if ((node = ps->projectFaces[bucket_index])) {
+ if ((node = ps->bucketFaces[bucket_index])) {
do {
face_index = (int)node->link;
@@ -1877,8 +1931,8 @@ static void project_paint_bucket_init(ProjectPaintState *ps, int thread_index, i
image_index = -1; /* sanity check */
- for (tpage_index=0; tpage_index < ps->projectImageTotal; tpage_index++) {
- if (ps->projectImages[tpage_index] == tpage_last) {
+ for (tpage_index=0; tpage_index < ps->image_tot; tpage_index++) {
+ if (ps->projImages[tpage_index].ima == tpage_last) {
image_index = tpage_index;
break;
}
@@ -1889,7 +1943,7 @@ static void project_paint_bucket_init(ProjectPaintState *ps, int thread_index, i
return;
}
- ibuf = BKE_image_get_ibuf(tpage_last, NULL); /* TODO - this may be slow */
+ ibuf = ps->projImages[image_index].ibuf;
}
project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf);
@@ -1897,7 +1951,7 @@ static void project_paint_bucket_init(ProjectPaintState *ps, int thread_index, i
} while (node);
}
- ps->projectBucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
+ ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
}
@@ -1909,7 +1963,7 @@ static void project_paint_bucket_init(ProjectPaintState *ps, int thread_index, i
static int project_bucket_face_isect(ProjectPaintState *ps, float min[2], float max[2], int bucket_x, int bucket_y, int bucket_index, MFace *mf)
{
- /* TODO - replace this with a tricker method that uses sideofline for all projectVertScreenCos's edges against the closest bucket corner */
+ /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */
float bucket_bounds[4];
float p1[2], p2[2], p3[2], p4[2];
float *v, *v1,*v2,*v3,*v4;
@@ -1921,7 +1975,7 @@ static int project_bucket_face_isect(ProjectPaintState *ps, float min[2], float
i = mf->v4 ? 3:2;
do {
- v = ps->projectVertScreenCos[ (*(&mf->v1 + i)) ];
+ v = ps->screenCoords[ (*(&mf->v1 + i)) ];
if ((v[0] > bucket_bounds[PROJ_BUCKET_LEFT]) &&
(v[0] < bucket_bounds[PROJ_BUCKET_RIGHT]) &&
@@ -1932,11 +1986,11 @@ static int project_bucket_face_isect(ProjectPaintState *ps, float min[2], float
}
} while (i--);
- v1 = ps->projectVertScreenCos[mf->v1];
- v2 = ps->projectVertScreenCos[mf->v2];
- v3 = ps->projectVertScreenCos[mf->v3];
+ v1 = ps->screenCoords[mf->v1];
+ v2 = ps->screenCoords[mf->v2];
+ v3 = ps->screenCoords[mf->v3];
if (mf->v4) {
- v4 = ps->projectVertScreenCos[mf->v4];
+ v4 = ps->screenCoords[mf->v4];
}
p1[0] = bucket_bounds[PROJ_BUCKET_LEFT]; p1[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
@@ -1972,7 +2026,7 @@ static int project_bucket_face_isect(ProjectPaintState *ps, float min[2], float
static void project_paint_delayed_face_init(ProjectPaintState *ps, MFace *mf, MTFace *tf, int face_index)
{
float min[2], max[2];
- int bucket_min[2], bucket_max[2]; /* for ps->projectBuckets indexing */
+ int bucket_min[2], bucket_max[2]; /* for ps->bucketRect indexing */
int i, a, bucket_x, bucket_y, bucket_index;
int has_x_isect = -1, has_isect = -1; /* for early loop exit */
@@ -1983,15 +2037,15 @@ static void project_paint_delayed_face_init(ProjectPaintState *ps, MFace *mf, MT
do {
a = (*(&mf->v1 + i)); /* vertex index */
- DO_MINMAX2(ps->projectVertScreenCos[ a ], min, max);
+ DO_MINMAX2(ps->screenCoords[ a ], min, max);
#ifndef PROJ_DEBUG_NOSEAMBLEED
/* add face user if we have bleed enabled, set the UV seam flags later */
- if (ps->projectSeamBleed > 0.0) {
+ if (ps->seam_bleed_px > 0.0) {
BLI_linklist_prepend_arena(
- &ps->projectVertFaces[ a ],
+ &ps->vertFaces[ a ],
(void *)face_index, /* cast to a pointer to shut up the compiler */
- ps->projectArena
+ ps->arena
);
}
#endif
@@ -2003,13 +2057,13 @@ static void project_paint_delayed_face_init(ProjectPaintState *ps, MFace *mf, MT
has_x_isect = 0;
for (bucket_x = bucket_min[0]; bucket_x < bucket_max[0]; bucket_x++) {
- bucket_index = bucket_x + (bucket_y * ps->bucketsX);
+ bucket_index = bucket_x + (bucket_y * ps->buckets_x);
if (project_bucket_face_isect(ps, min, max, bucket_x, bucket_y, bucket_index, mf)) {
BLI_linklist_prepend_arena(
- &ps->projectFaces[ bucket_index ],
+ &ps->bucketFaces[ bucket_index ],
(void *)face_index, /* cast to a pointer to shut up the compiler */
- ps->projectArena
+ ps->arena
);
has_x_isect = has_isect = 1;
@@ -2026,11 +2080,11 @@ static void project_paint_delayed_face_init(ProjectPaintState *ps, MFace *mf, MT
}
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->projectSeamBleed > 0.0) {
+ if (ps->seam_bleed_px > 0.0) {
if (!mf->v4) {
- ps->projectFaceSeamFlags[face_index] |= PROJ_FACE_NOSEAM4; /* so this wont show up as an untagged egde */
+ ps->faceSeamFlags[face_index] |= PROJ_FACE_NOSEAM4; /* so this wont show up as an untagged egde */
}
- **ps->projectFaceSeamUVs[face_index] = MAXFLOAT; /* set as uninitialized */
+ **ps->faceSeamUVs[face_index] = MAXFLOAT; /* set as uninitialized */
}
#endif
}
@@ -2048,6 +2102,7 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
LinkNode *image_LinkList = NULL;
LinkNode *node;
+ ProjectPaintImage *projIma;
Image *tpage_last = NULL;
ImBuf *ibuf = NULL;
@@ -2079,8 +2134,8 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
ps->dm_totvert = ps->dm->getNumVerts( ps->dm );
ps->dm_totface = ps->dm->getNumFaces( ps->dm );
- ps->bucketsX = G.rt ? G.rt : PROJ_BUCKET_DIV;
- ps->bucketsY = G.rt ? G.rt : PROJ_BUCKET_DIV;
+ ps->buckets_x = G.rt ? G.rt : PROJ_BUCKET_DIV;
+ ps->buckets_y = G.rt ? G.rt : PROJ_BUCKET_DIV;
ps->viewDir[0] = 0.0;
ps->viewDir[1] = 0.0;
@@ -2088,12 +2143,12 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
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;
+ tot_bucketMem = sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y;
+ tot_faceListMem = sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y;
- tot_bucketFlagMem = sizeof(char) * ps->bucketsX * ps->bucketsY;
+ tot_bucketFlagMem = sizeof(char) * ps->buckets_x * ps->buckets_y;
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->projectSeamBleed > 0.0) { /* UV Seams for bleeding */
+ if (ps->seam_bleed_px > 0.0) { /* UV Seams for bleeding */
tot_bucketVertFacesMem = sizeof(LinkNode *) * ps->dm_totvert;
tot_faceSeamFlagMem = sizeof(char) * ps->dm_totface;
tot_faceSeamUVMem = sizeof(float) * ps->dm_totface * 8;
@@ -2101,37 +2156,37 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
#endif
/* BLI_memarena_new uses calloc */
- ps->projectArena =
+ ps->arena =
BLI_memarena_new( tot_bucketMem +
tot_faceListMem +
tot_faceSeamFlagMem +
tot_faceSeamUVMem +
tot_bucketVertFacesMem + (1<<18));
- BLI_memarena_use_calloc(ps->projectArena);
+ BLI_memarena_use_calloc(ps->arena);
- ps->projectBuckets = (LinkNode **)BLI_memarena_alloc( ps->projectArena, tot_bucketMem);
- ps->projectFaces= (LinkNode **)BLI_memarena_alloc( ps->projectArena, tot_faceListMem);
+ ps->bucketRect = (LinkNode **)BLI_memarena_alloc( ps->arena, tot_bucketMem);
+ ps->bucketFaces= (LinkNode **)BLI_memarena_alloc( ps->arena, tot_faceListMem);
- ps->projectBucketFlags= (char *)BLI_memarena_alloc( ps->projectArena, tot_bucketFlagMem);
+ ps->bucketFlags= (char *)BLI_memarena_alloc( ps->arena, tot_bucketFlagMem);
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->projectSeamBleed > 0.0) {
- ps->projectVertFaces= (LinkNode **)BLI_memarena_alloc( ps->projectArena, tot_bucketVertFacesMem);
- ps->projectFaceSeamFlags = (char *)BLI_memarena_alloc( ps->projectArena, tot_faceSeamFlagMem);
- ps->projectFaceSeamUVs= BLI_memarena_alloc( ps->projectArena, tot_faceSeamUVMem);
+ if (ps->seam_bleed_px > 0.0) {
+ ps->vertFaces= (LinkNode **)BLI_memarena_alloc( ps->arena, tot_bucketVertFacesMem);
+ ps->faceSeamFlags = (char *)BLI_memarena_alloc( ps->arena, tot_faceSeamFlagMem);
+ ps->faceSeamUVs= BLI_memarena_alloc( ps->arena, tot_faceSeamUVMem);
}
#endif
- // calloced - memset(ps->projectBuckets, 0, tot_bucketMem);
- // calloced - memset(ps->projectFaces, 0, tot_faceListMem);
- // calloced - memset(ps->projectBucketFlags, 0, tot_bucketFlagMem);
+ // calloced - memset(ps->bucketRect, 0, tot_bucketMem);
+ // calloced - memset(ps->bucketFaces, 0, tot_faceListMem);
+ // calloced - memset(ps->bucketFlags, 0, tot_bucketFlagMem);
#ifndef PROJ_DEBUG_NOSEAMBLEED
- // calloced - memset(ps->projectFaceSeamFlags,0, tot_faceSeamFlagMem);
+ // calloced - memset(ps->faceSeamFlags,0, tot_faceSeamFlagMem);
- // calloced - if (ps->projectSeamBleed > 0.0) {
- // calloced - memset(ps->projectVertFaces, 0, tot_bucketVertFacesMem);
+ // calloced - if (ps->seam_bleed_px > 0.0) {
+ // calloced - memset(ps->vertFaces, 0, tot_bucketVertFacesMem);
/* TODO dosnt need zeroing? */
- // calloced - memset(ps->projectFaceSeamUVs, 0, tot_faceSeamUVMem);
+ // calloced - memset(ps->faceSeamUVs, 0, tot_faceSeamUVMem);
// calloced - }
#endif
@@ -2143,7 +2198,7 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
}
for (a=0; a<ps->thread_tot; a++) {
- ps->projectArena_mt[a] = BLI_memarena_new(1<<16);
+ ps->arena_mt[a] = BLI_memarena_new(1<<16);
}
Mat4Invert(ps->ob->imat, ps->ob->obmat);
@@ -2154,17 +2209,17 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
Mat3MulVecfl(mat, ps->viewDir);
/* calculate vert screen coords */
- ps->projectVertScreenCos = BLI_memarena_alloc( ps->projectArena, sizeof(float) * ps->dm_totvert * 4);
- projScreenCo = ps->projectVertScreenCos;
+ ps->screenCoords = BLI_memarena_alloc( ps->arena, sizeof(float) * ps->dm_totvert * 4);
+ projScreenCo = ps->screenCoords;
/* TODO - check cameras mode too */
if (G.vd->persp == V3D_ORTHO) {
- ps->projectIsOrtho = 1;
+ ps->is_ortho = 1;
}
- INIT_MINMAX2(ps->viewMin2D, ps->viewMax2D);
+ INIT_MINMAX2(ps->screen_min, ps->screen_max);
- if (ps->projectIsOrtho) {
+ if (ps->is_ortho) {
for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
VECCOPY((*projScreenCo), ps->dm_mvert[a].co);
Mat4MulVecfl(ps->projectMat, (*projScreenCo));
@@ -2172,7 +2227,7 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
/* screen space, not clamped */
(*projScreenCo)[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*(*projScreenCo)[0];
(*projScreenCo)[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*(*projScreenCo)[1];
- DO_MINMAX2((*projScreenCo), ps->viewMin2D, ps->viewMax2D);
+ DO_MINMAX2((*projScreenCo), ps->screen_min, ps->screen_max);
}
} else {
for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
@@ -2186,7 +2241,7 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
(*projScreenCo)[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*(*projScreenCo)[0]/(*projScreenCo)[3];
(*projScreenCo)[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*(*projScreenCo)[1]/(*projScreenCo)[3];
(*projScreenCo)[2] = (*projScreenCo)[2]/(*projScreenCo)[3]; /* Use the depth for bucket point occlusion */
- DO_MINMAX2((*projScreenCo), ps->viewMin2D, ps->viewMax2D);
+ DO_MINMAX2((*projScreenCo), ps->screen_min, ps->screen_max);
} else {
/* TODO - deal with cases where 1 side of a face goes behind the view ? */
(*projScreenCo)[0] = MAXFLOAT;
@@ -2200,32 +2255,32 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
float *curs= give_cursor();
VECCOPY(projCo, curs);
Mat4MulVecfl(ps->ob->imat, projCo);
- VecSubf(projCo, projCo, ps->ob->obmat[3]);
+
projCo[3] = 1.0;
Mat4MulVec4fl(ps->projectMat, projCo);
- ps->cloneOfs[0] = mval[0] - ((float)(curarea->winx/2.0)+(curarea->winx/2.0)*projCo[0]/projCo[3]);
- ps->cloneOfs[1] = mval[1] - ((float)(curarea->winy/2.0)+(curarea->winy/2.0)*projCo[1]/projCo[3]);
+ ps->clone_offset[0] = mval[0] - ((float)(curarea->winx/2.0)+(curarea->winx/2.0)*projCo[0]/projCo[3]);
+ ps->clone_offset[1] = mval[1] - ((float)(curarea->winy/2.0)+(curarea->winy/2.0)*projCo[1]/projCo[3]);
- // printf("%f %f %f %f %f\n", ps->cloneOfs[0], ps->cloneOfs[1], curs[0], curs[1], curs[2]);
+ // printf("%f %f %f %f %f\n", ps->clone_offset[0], ps->clone_offset[1], curs[0], curs[1], curs[2]);
}
/* 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;
+ projMargin = (ps->screen_max[0] - ps->screen_min[0]) * 0.000001;
+ ps->screen_max[0] += projMargin;
+ ps->screen_min[0] -= projMargin;
+ projMargin = (ps->screen_max[1] - ps->screen_min[1]) * 0.000001;
+ ps->screen_max[1] += projMargin;
+ ps->screen_min[1] -= projMargin;
/* only for convenience */
- ps->viewWidth = ps->viewMax2D[0] - ps->viewMin2D[0];
- ps->viewHeight = ps->viewMax2D[1] - ps->viewMin2D[1];
+ ps->screen_width = ps->screen_max[0] - ps->screen_min[0];
+ ps->screen_height = ps->screen_max[1] - ps->screen_min[1];
- if (!ps->projectIsOrtho) {
+ if (!ps->is_ortho) {
/* get the view direction relative to the objects matrix */
float imat[3][3];
VECCOPY(viewPos, G.vd->viewinv[3]);
@@ -2237,22 +2292,22 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
for( a = 0, tf = ps->dm_mtface, mf = ps->dm_mface; a < ps->dm_totface; mf++, tf++, a++ ) {
if (tf->tpage && ((G.f & G_FACESELECT)==0 || mf->flag & ME_FACE_SEL)) {
- if (!ps->projectIsOrtho) {
- if ( ps->projectVertScreenCos[mf->v1][0]==MAXFLOAT ||
- ps->projectVertScreenCos[mf->v2][0]==MAXFLOAT ||
- ps->projectVertScreenCos[mf->v3][0]==MAXFLOAT ||
- (mf->v4 && ps->projectVertScreenCos[mf->v4][0]==MAXFLOAT)
+ if (!ps->is_ortho) {
+ if ( ps->screenCoords[mf->v1][0]==MAXFLOAT ||
+ ps->screenCoords[mf->v2][0]==MAXFLOAT ||
+ ps->screenCoords[mf->v3][0]==MAXFLOAT ||
+ (mf->v4 && ps->screenCoords[mf->v4][0]==MAXFLOAT)
) {
continue;
}
}
- if (ps->projectIsBackfaceCull) {
+ if (ps->do_backfacecull) {
/* TODO - we dont really need the normal, just the direction, save a sqrt? */
if (mf->v4) CalcNormFloat4(ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, f_no);
else CalcNormFloat(ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, f_no);
- if (ps->projectIsOrtho) {
+ if (ps->is_ortho) {
if (Inpf(f_no, ps->viewDir) < 0) {
continue;
}
@@ -2287,8 +2342,8 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
if (image_index==-1) { /* MemArena dosnt have an append func */
BLI_linklist_append(&image_LinkList, tf->tpage);
- image_index = ps->projectImageTotal;
- ps->projectImageTotal++;
+ image_index = ps->image_tot;
+ ps->image_tot++;
}
}
@@ -2304,20 +2359,16 @@ static void project_paint_begin( ProjectPaintState *ps, short mval[2])
}
/* build an array of images we use*/
- ps->projectImages = BLI_memarena_alloc( ps->projectArena, sizeof(Image *) * ps->projectImageTotal);
- ps->projectImBufs = BLI_memarena_alloc( ps->projectArena, sizeof(ImBuf *) * ps->projectImageTotal);
- *(ps->projectPartialRedraws) = BLI_memarena_alloc( ps->projectArena, sizeof(ImagePaintPartialRedraw) * ps->projectImageTotal * PROJ_BOUNDBOX_SQUARED);
+ projIma = ps->projImages = (ProjectPaintImage *)BLI_memarena_alloc( ps->arena, sizeof(ProjectPaintImage) * ps->image_tot);
- for (node= image_LinkList, i=0; node; node= node->next, i++) {
- ps->projectImages[i] = node->link;
- ps->projectImages[i]->id.flag &= ~LIB_DOIT;
- ps->projectImBufs[i] = BKE_image_get_ibuf(ps->projectImages[i], NULL);
-
- ps->projectPartialRedraws[i] = *(ps->projectPartialRedraws) + (i * PROJ_BOUNDBOX_SQUARED);
+ for (node= image_LinkList, i=0; node; node= node->next, i++, projIma++) {
+ projIma->ima = node->link;
+ // calloced - projIma->touch = 0;
+ projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL);
+ projIma->partRedrawRect = BLI_memarena_alloc( ps->arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ // calloced - memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
}
- // calloced - memset(ps->projectPartialRedraws, 0, sizeof(ImagePaintPartialRedraw) * ps->projectImageTotal);
-
/* we have built the array, discard the linked list */
BLI_linklist_free(image_LinkList, NULL);
}
@@ -2329,32 +2380,27 @@ static void project_paint_end( ProjectPaintState *ps )
/* build undo data from original pixel colors */
if(U.uiflag & USER_GLOBALUNDO) {
ProjectPixel *projPixel;
- ImBuf *ibuf, *tmpibuf = NULL;
+ ImBuf *tmpibuf = NULL;
LinkNode *pixel_node;
UndoTile *tile;
- UndoTile ***image_undo_tiles = (UndoTile ***)BLI_memarena_alloc( ps->projectArena, sizeof(UndoTile ***) * ps->projectImageTotal);
- int bucket_index = (ps->bucketsX * ps->bucketsY) - 1; /* we could get an X/Y but easier to loop through all possible buckets */
+
+ int bucket_index = (ps->buckets_x * ps->buckets_y) - 1; /* we could get an X/Y but easier to loop through all possible buckets */
int tile_index;
int x_round, y_round;
int x_tile, y_tile;
/* context */
+ ProjectPaintImage *last_projIma;
int last_image_index = -1;
int last_tile_width;
- ImBuf *last_ibuf;
- Image *last_ima;
- UndoTile **last_undo_grid = NULL;
-
- for(a=0; a < ps->projectImageTotal; a++) {
- ibuf = ps->projectImBufs[a];
- image_undo_tiles[a] = (UndoTile **)BLI_memarena_alloc(
- ps->projectArena,
- sizeof(UndoTile **) * IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y) );
+ for(a=0, last_projIma=ps->projImages; a < ps->image_tot; a++, last_projIma++) {
+ last_projIma = &(ps->projImages[a]);
+ last_projIma->undoRect = (UndoTile **) BLI_memarena_alloc(ps->arena, sizeof(UndoTile **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y));
}
do {
- if ((pixel_node = ps->projectBuckets[bucket_index])) {
+ if ((pixel_node = ps->bucketRect[bucket_index])) {
/* loop through all pixels */
while (pixel_node) {
@@ -2367,10 +2413,8 @@ static void project_paint_end( ProjectPaintState *ps )
if (last_image_index != projPixel->image_index) {
/* set the context */
last_image_index = projPixel->image_index;
- last_ima = ps->projectImages[last_image_index];
- last_ibuf = ps->projectImBufs[last_image_index];
- last_tile_width = IMAPAINT_TILE_NUMBER(last_ibuf->x);
- last_undo_grid = image_undo_tiles[last_image_index];
+ last_projIma = ps->projImages + last_image_index;
+ last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x);
}
x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS;
@@ -2381,11 +2425,11 @@ static void project_paint_end( ProjectPaintState *ps )
tile_index = x_tile + y_tile * last_tile_width;
- if (last_undo_grid[tile_index]==NULL) {
+ if (last_projIma->undoRect[tile_index]==NULL) {
/* add the undo tile from the modified image, then write the original colors back into it */
- tile = last_undo_grid[tile_index] = undo_init_tile(&last_ima->id, last_ibuf, &tmpibuf, x_tile, y_tile);
+ tile = last_projIma->undoRect[tile_index] = undo_init_tile(&last_projIma->ima->id, last_projIma->ibuf, &tmpibuf, x_tile, y_tile);
} else {
- tile = last_undo_grid[tile_index];
+ tile = last_projIma->undoRect[tile_index];
}
/* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color
@@ -2404,10 +2448,11 @@ static void project_paint_end( ProjectPaintState *ps )
}
/* done calculating undo data */
- BLI_memarena_free(ps->projectArena);
+
+ BLI_memarena_free(ps->arena);
for (a=0; a<ps->thread_tot; a++) {
- BLI_memarena_free(ps->projectArena_mt[a]);
+ BLI_memarena_free(ps->arena_mt[a]);
}
ps->dm->release(ps->dm);
@@ -2902,8 +2947,9 @@ static int project_bucket_circle_isect(ProjectPaintState *ps, int bucket_x, int
return 0;
}
-static void partial_redraw_array_init(ImagePaintPartialRedraw *pr, int tot)
+static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
{
+ int tot = PROJ_BOUNDBOX_SQUARED;
while (tot--) {
pr->x1 = 10000000;
pr->y1 = 10000000;
@@ -2934,35 +2980,24 @@ static void partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPa
static int imapaint_refresh_tagged(ProjectPaintState *ps)
{
ImagePaintPartialRedraw *pr;
+ ProjectPaintImage *projIma;
int a,i;
int redraw = 0;
- for (a=0; a < ps->projectImageTotal; a++) {
- Image *ima = ps->projectImages[a];
- if (ima->id.flag & LIB_DOIT) {
+ for (a=0, projIma=ps->projImages; a < ps->image_tot; a++, projIma++) {
+ if (projIma->touch) {
/* look over each bound cell */
for (i=0; i<PROJ_BOUNDBOX_SQUARED; i++) {
- pr = &(ps->projectPartialRedraws[a][i]);
+ pr = &(projIma->partRedrawRect[i]);
if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
- /*
- if(U.uiflag & USER_GLOBALUNDO) {
- // Dont need to set "imapaintpartial" This is updated from imapaint_dirty_region args.
- imapaint_dirty_region(ima, ps->projectImBufs[a], pr->x1, pr->y1, pr->x2 - pr->x1, pr->y2 - pr->y1);
- } else {
- */
- imapaintpartial = *pr;
- /*
- }
- */
-
- imapaint_image_update(ima, ps->projectImBufs[a], 1 /*texpaint*/ );
-
+ imapaintpartial = *pr;
+ imapaint_image_update(projIma->ima, projIma->ibuf, 1 /*texpaint*/ );
redraw = 1;
}
}
- ima->id.flag &= ~LIB_DOIT; /* clear for reuse */
+ projIma->touch = 0; /* clear for reuse */
}
}
@@ -2980,17 +3015,17 @@ static int bucket_iter_init(ProjectPaintState *ps, float mval_f[2])
max_brush[1] = mval_f[1] + (ps->brush->size/2);
/* offset to make this a valid bucket index */
- project_paint_rect(ps, min_brush, max_brush, ps->min_bucket, ps->max_bucket);
+ project_paint_rect(ps, min_brush, max_brush, ps->bucket_min, ps->bucket_max);
/* mouse outside the model areas? */
- if (ps->min_bucket[0]==ps->max_bucket[0] || ps->min_bucket[1]==ps->max_bucket[1]) {
+ if (ps->bucket_min[0]==ps->bucket_max[0] || ps->bucket_min[1]==ps->bucket_max[1]) {
return 0;
}
- ps->context_bucket_x = ps->min_bucket[0];
- ps->context_bucket_y = ps->min_bucket[1];
+ ps->context_bucket_x = ps->bucket_min[0];
+ ps->context_bucket_y = ps->bucket_min[1];
#ifdef PROJ_DEBUG_PRINT_THREADS
- printf("Initializing Values %d %d!", ps->min_bucket[0], ps->min_bucket[1]);
+ printf("Initializing Values %d %d!", ps->bucket_min[0], ps->bucket_min[1]);
#endif
return 1;
}
@@ -3002,14 +3037,14 @@ static int bucket_iter_next(ProjectPaintState *ps, int *bucket_index, float buck
//printf("%d %d \n", ps->context_bucket_x, ps->context_bucket_y);
- for ( ; ps->context_bucket_y < ps->max_bucket[1]; ps->context_bucket_y++) {
- for ( ; ps->context_bucket_x < ps->max_bucket[0]; ps->context_bucket_x++) {
+ for ( ; ps->context_bucket_y < ps->bucket_max[1]; ps->context_bucket_y++) {
+ for ( ; ps->context_bucket_x < ps->bucket_max[0]; ps->context_bucket_x++) {
/* use bucket_bounds for project_bucket_circle_isect and project_paint_bucket_init*/
project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
if (project_bucket_circle_isect(ps, ps->context_bucket_x, ps->context_bucket_y, mval_f, ps->brush->size * ps->brush->size, bucket_bounds)) {
- *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->bucketsX);
+ *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
#ifdef PROJ_DEBUG_PRINT_THREADS
printf(" --- %d %d \n", ps->context_bucket_x, ps->context_bucket_y);
#endif
@@ -3021,7 +3056,7 @@ static int bucket_iter_next(ProjectPaintState *ps, int *bucket_index, float buck
return 1;
}
}
- ps->context_bucket_x = ps->min_bucket[0];
+ ps->context_bucket_x = ps->bucket_min[0];
}
if (ps->thread_tot > 1)
@@ -3036,7 +3071,7 @@ static int imapaint_paint_sub_stroke_project(
short mval[2],
double time,
float pressure,
- ImagePaintPartialRedraw *projectPartialRedraws[PROJ_BOUNDBOX_SQUARED],
+ ProjectPaintImage *projImages,
int thread_index)
{
LinkNode *node;
@@ -3045,7 +3080,8 @@ static int imapaint_paint_sub_stroke_project(
int redraw = 0;
int last_index = -1;
- ImagePaintPartialRedraw *last_partial_redraw;
+ ProjectPaintImage *last_projIma;
+ //ImagePaintPartialRedraw *last_partial_redraw;
ImagePaintPartialRedraw *last_partial_redraw_cell;
float rgba[4], alpha, dist, dist_nosqrt;
@@ -3086,13 +3122,13 @@ static int imapaint_paint_sub_stroke_project(
/* printf("brush bounds %d %d %d %d\n", bucket_min[0], bucket_min[1], bucket_max[0], bucket_max[1]); */
/* If there is ever problems with getting the bounds for the brush, set the bounds to include all */
- /*bucket_min[0] = 0; bucket_min[1] = 0; bucket_max[0] = ps->bucketsX; bucket_max[1] = ps->bucketsY;*/
+ /*bucket_min[0] = 0; bucket_min[1] = 0; bucket_max[0] = ps->buckets_x; bucket_max[1] = ps->buckets_y;*/
/* no clamping needed, dont use screen bounds, use vert bounds */
//for (bucket_y = bucket_min[1]; bucket_y < bucket_max[1]; bucket_y++) {
#ifdef PROJ_DEBUG_PRINT_THREADS
- printf("THREAD %d %d %d\n", ps->thread_tot, thread_index, (ps->max_bucket[0] - ps->min_bucket[0]) * (ps->max_bucket[1] - ps->min_bucket[1]) );
+ printf("THREAD %d %d %d\n", ps->thread_tot, thread_index, (ps->bucket_max[0] - ps->bucket_min[0]) * (ps->bucket_max[1] - ps->bucket_min[1]) );
#endif
while (bucket_iter_next(ps, &bucket_index, bucket_bounds, mval_f)) {
@@ -3101,7 +3137,7 @@ static int imapaint_paint_sub_stroke_project(
#endif
/* Check this bucket and its faces are initialized */
- if (ps->projectBucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
+ if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
/* No pixels initialized */
project_paint_bucket_init(ps, thread_index, bucket_index, bucket_bounds);
}
@@ -3109,7 +3145,7 @@ static int imapaint_paint_sub_stroke_project(
/* TODO - we may want to init clone data in a seperate to project_paint_bucket_init
* so we dont go overboard and init too many clone pixels */
- if ((node = ps->projectBuckets[bucket_index])) {
+ if ((node = ps->bucketRect[bucket_index])) {
do {
projPixel = (ProjectPixel *)node->link;
@@ -3122,13 +3158,13 @@ static int imapaint_paint_sub_stroke_project(
if (last_index != projPixel->image_index) {
last_index = projPixel->image_index;
- last_partial_redraw = projectPartialRedraws[last_index];
+ last_projIma = projImages + last_index;
- ps->projectImages[last_index]->id.flag |= LIB_DOIT; /* halgrind complains this is not threadsafe but probably ok? - we are only setting this flag anyway */
- is_floatbuf = ps->projectImBufs[last_index]->rect_float ? 1 : 0;
+ last_projIma->touch = 1;
+ is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
}
- last_partial_redraw_cell = last_partial_redraw + projPixel->bb_cell_index;
+ last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
last_partial_redraw_cell->x1 = MIN2( last_partial_redraw_cell->x1, projPixel->x_px );
last_partial_redraw_cell->y1 = MIN2( last_partial_redraw_cell->y1, projPixel->y_px );
@@ -3169,7 +3205,7 @@ static int imapaint_paint_sub_stroke_project(
break;
case PAINT_TOOL_SMEAR:
Vec2Subf(co, projPixel->projCo2D, mval_ofs);
- if (screenco_pickcol(ps, co, NULL, rgba_ub, 0)) { /* Note, no interpolation here, only needed for clone, nearest should be is OK */
+ if (project_paint_PickColor(ps, co, NULL, rgba_ub, 0)) { /* Note, no interpolation here, only needed for clone, nearest should be is OK */
brush_sample_tex(ps->brush, projPixel->projCo2D, rgba);
alpha = rgba[3]*brush_sample_falloff(ps->brush, dist);
/* drat! - this could almost be very simple if we ignore
@@ -3264,7 +3300,7 @@ typedef struct ProjectHandle {
float pressure;
/* annoying but we need to have image bounds per thread, then merge into ps->projectPartialRedraws */
- ImagePaintPartialRedraw *projectPartialRedraws[PROJ_BOUNDBOX_SQUARED]; /* array of partial redraws */
+ ProjectPaintImage *projImages; /* array of partial redraws */
/* thread settings */
int thread_tot;
@@ -3284,8 +3320,7 @@ static void *do_projectpaint_thread(void *ph_v)
ph->mval,
ph->time,
ph->pressure,
-
- ph->projectPartialRedraws,
+ ph->projImages,
ph->thread_index
);
@@ -3299,7 +3334,7 @@ static int imapaint_paint_sub_stroke_project_mt(ProjectPaintState *ps, BrushPain
{
ProjectHandle handles[BLENDER_MAX_THREADS];
ListBase threads;
- int a;
+ int a,i;
float mval_f[2];
mval_f[0] = mval[0]; mval_f[1] = mval[1];
@@ -3314,7 +3349,7 @@ static int imapaint_paint_sub_stroke_project_mt(ProjectPaintState *ps, BrushPain
/* get the threads running */
for(a=0; a < ps->thread_tot; a++) {
- int i;
+
#ifdef PROJ_DEBUG_PRINT_THREADS
printf("INIT THREAD %d\n", a);
@@ -3334,15 +3369,16 @@ static int imapaint_paint_sub_stroke_project_mt(ProjectPaintState *ps, BrushPain
handles[a].thread_index = a;
handles[a].ready = 0;
- *(handles[a].projectPartialRedraws) = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->projectArena, ps->projectImageTotal * sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ handles[a].projImages = (ProjectPaintImage *)BLI_memarena_alloc(ps->arena, ps->image_tot * sizeof(ProjectPaintImage));
+
+ memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjectPaintImage) );
/* image bounds */
- for (i=1; i< ps->projectImageTotal; i++) {
- handles[a].projectPartialRedraws[i] = *(handles[a].projectPartialRedraws) + (i * PROJ_BOUNDBOX_SQUARED);
+ for (i=1; i< ps->image_tot; i++) {
+ handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED );
}
- memcpy(*(handles[a].projectPartialRedraws), *(ps->projectPartialRedraws), ps->projectImageTotal * sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED );
-
BLI_insert_thread(&threads, &handles[a]);
}
@@ -3360,7 +3396,14 @@ static int imapaint_paint_sub_stroke_project_mt(ProjectPaintState *ps, BrushPain
/* move threaded bounds back into ps->projectPartialRedraws */
for(a=0; a < ps->thread_tot; a++) {
- partial_redraw_array_merge(*(ps->projectPartialRedraws), *(handles[a].projectPartialRedraws), ps->projectImageTotal * PROJ_BOUNDBOX_SQUARED);
+ for(i=0; i < ps->image_tot; i++) {
+ partial_redraw_array_merge( ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED );
+
+ if (handles[a].projImages[i].partRedrawRect) {
+ ps->projImages[i].touch = 1;
+ }
+
+ }
}
return imapaint_refresh_tagged(ps);
@@ -3451,8 +3494,11 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho
static void imapaint_paint_stroke_project(ProjectPaintState *ps, BrushPainter *painter, short *prevmval, short *mval, short redraw, double time, float pressure)
{
int redraw_flag = 0;
+ int a;
- partial_redraw_array_init(*ps->projectPartialRedraws, ps->projectImageTotal * PROJ_BOUNDBOX_SQUARED);
+ for (a=0; a<ps->image_tot; a++) {
+ partial_redraw_array_init(ps->projImages[a].partRedrawRect);
+ }
/* TODO - support more brush operations, airbrush etc */
if (ps->thread_tot > 1) {
@@ -3461,13 +3507,14 @@ static void imapaint_paint_stroke_project(ProjectPaintState *ps, BrushPainter *p
float mval_f[2];
mval_f[0] = mval[0]; mval_f[1] = mval[1];
if (bucket_iter_init(ps, mval_f)) {
- redraw_flag |= imapaint_paint_sub_stroke_project(ps, painter, prevmval, mval, time, pressure, ps->projectPartialRedraws, 0); /* no threads */
+ redraw_flag |= imapaint_paint_sub_stroke_project(ps, painter, prevmval, mval, time, pressure, ps->projImages, 0); /* no threads */
}
}
if (redraw && redraw_flag) {
- imapaint_redraw(0, 1/*texpaint*/, NULL);
- /*imapaint_clear_partial_redraw();*/ /* not needed since we use our own array */
+ force_draw(0); /* imapaint_redraw just calls this in viewport paint anyway */
+ /* imapaint_redraw(0, 1, NULL); */
+ /* imapaint_clear_partial_redraw(); */ /* not needed since we use our own array */
}
}
@@ -3551,6 +3598,8 @@ static int cmp_brush_spacing(short mval1[2], short mval2[2], float dist)
return dist < Vec2Length(vec) ? 1 : 0;
}
+extern int view_autodist( float mouse_worldloc[3] ); /* view.c */
+
void imagepaint_paint(short mousebutton, short texpaint)
{
ImagePaintState s;
@@ -3577,11 +3626,14 @@ void imagepaint_paint(short mousebutton, short texpaint)
if (G.qual & LR_CTRLKEY) {
+ float *curs;
mouse_cursor();
+ curs = give_cursor();
+ view_autodist(curs);
return;
}
- /* TODO - grease pencil stroke is verry basic now and only useful for benchmarking, should make this nicer */
+ /* TODO - grease pencil stroke is very basic now and only useful for benchmarking, should make this nicer */
//stroke_gp = 1;
/*
if (G.rt==123) {
@@ -3641,10 +3693,10 @@ void imagepaint_paint(short mousebutton, short texpaint)
if (project) {
/* setup projection painting data */
- ps.projectIsBackfaceCull = 1;
- ps.projectIsOcclude = 1;
+ ps.do_backfacecull = 1;
+ ps.do_occlude = 1;
#ifndef PROJ_DEBUG_NOSEAMBLEED
- ps.projectSeamBleed = 2.0; /* pixel num to bleed */
+ ps.seam_bleed_px = 2.0; /* pixel num to bleed */
#endif
project_paint_begin(&ps, mval);
@@ -3684,7 +3736,6 @@ void imagepaint_paint(short mousebutton, short texpaint)
if (stroke_gp==0)
BIF_wait_for_statechange();
}
-
init = 0;