diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-03-05 21:19:32 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-03-05 21:19:32 +0300 |
commit | 94d5b31b9d33ec51c7b05bb57b2166df2919eaa9 (patch) | |
tree | ed1d44ae156ddd4baab5fb5478b2eb60f869c1a2 /source | |
parent | d0c70ad1d581d69f650d604293c006b2e0023310 (diff) |
reproject operator, use to reproject edited renders back into textures.
- uses project paint options (UV bleed, normals, culling)
- bicubic interolation from the image
- multithraded
TODO.
project into multiple objects at once.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image.c | 384 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_ops.c | 1 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_enum_types.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 4 |
5 files changed, 291 insertions, 100 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 26eb07c4646..3e0d5fdb2fa 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -65,6 +65,7 @@ #include "DNA_windowmanager_types.h" #include "BKE_context.h" +#include "BKE_object.h" #include "BKE_brush.h" #include "BKE_global.h" #include "BKE_image.h" @@ -94,6 +95,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "GPU_draw.h" @@ -184,6 +186,9 @@ typedef struct ImagePaintRegion { #define PROJ_FACE_NOSEAM3 1<<6 #define PROJ_FACE_NOSEAM4 1<<7 +#define PROJ_SRC_VIEW 1 +#define PROJ_SRC_CAM 2 + /* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams * as this number approaches 1.0f the likelihood increases of float precision errors where * it is occluded by an adjacent face */ @@ -218,6 +223,7 @@ typedef struct ProjPaintState { RegionView3D *rv3d; ARegion *ar; Scene *scene; + int source; /* PROJ_SRC_**** */ Brush *brush; short tool, blend; @@ -259,6 +265,7 @@ typedef struct ProjPaintState { float screenMax[2]; float screen_width; /* Calculated from screenMin & screenMax */ float screen_height; + int winx, winy; /* from the carea or from the projection render */ /* options for projection painting */ int do_layer_clone; @@ -286,6 +293,10 @@ typedef struct ProjPaintState { float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */ float clipsta, clipend; + /* reproject vars */ + ImBuf *reproject_ibuf; + + /* threads */ int thread_tot; int bucketMin[2]; @@ -742,6 +753,7 @@ static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *buc int face_index; int isect_ret; float w[3]; /* not needed when clipping */ + const short do_clip= ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; /* 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 */ @@ -751,14 +763,14 @@ static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *buc if (orig_face != face_index) { mf = ps->dm_mface + face_index; - if(ps->rv3d->rflag & RV3D_CLIPPING) + if(do_clip) isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], 0); else isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho); /* Note, if isect_ret==-1 then we dont want to test the other side of the quad */ if (isect_ret==0 && mf->v4) { - if(ps->rv3d->rflag & RV3D_CLIPPING) + if(do_clip) isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1); else isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho); @@ -2199,6 +2211,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i int uv_clip_tot; const short is_ortho = ps->is_ortho; const short do_backfacecull = ps->do_backfacecull; + const short do_clip= ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; vCo[0] = ps->dm_mvert[mf->v1].co; vCo[1] = ps->dm_mvert[mf->v2].co; @@ -2298,7 +2311,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); /* a pitty we need to get the worldspace pixel location here */ - if(ps->rv3d->rflag & RV3D_CLIPPING) { + if(do_clip) { interp_v3_v3v3v3(wco, ps->dm_mvert[ (*(&mf->v1 + i1)) ].co, ps->dm_mvert[ (*(&mf->v1 + i2)) ].co, ps->dm_mvert[ (*(&mf->v1 + i3)) ].co, w); if(view3d_test_clipping(ps->rv3d, wco, 1)) { continue; /* Watch out that no code below this needs to run */ @@ -2479,8 +2492,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i if (!is_ortho) { pixelScreenCo[3] = 1.0f; mul_m4_v4((float(*)[4])ps->projectMat, pixelScreenCo); /* cast because of const */ - pixelScreenCo[0] = (float)(ps->ar->winx/2.0f)+(ps->ar->winx/2.0f)*pixelScreenCo[0]/pixelScreenCo[3]; - pixelScreenCo[1] = (float)(ps->ar->winy/2.0f)+(ps->ar->winy/2.0f)*pixelScreenCo[1]/pixelScreenCo[3]; + pixelScreenCo[0] = (float)(ps->winx/2.0f)+(ps->winx/2.0f)*pixelScreenCo[0]/pixelScreenCo[3]; + pixelScreenCo[1] = (float)(ps->winy/2.0f)+(ps->winy/2.0f)*pixelScreenCo[1]/pixelScreenCo[3]; pixelScreenCo[2] = pixelScreenCo[2]/pixelScreenCo[3]; /* Use the depth for bucket point occlusion */ } @@ -2513,7 +2526,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i } /* a pitty we need to get the worldspace pixel location here */ - if(ps->rv3d->rflag & RV3D_CLIPPING) { + if(do_clip) { if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); @@ -2768,6 +2781,7 @@ static void project_paint_begin(ProjPaintState *ps) float (*projScreenCo)[4]; /* Note, we could have 4D vectors are only needed for */ float projMargin; + /* Image Vars - keep track of images we have used */ LinkNode *image_LinkList = NULL; LinkNode *node; @@ -2786,7 +2800,8 @@ static void project_paint_begin(ProjPaintState *ps) /* ---- end defines ---- */ - ED_view3d_local_clipping(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */ + if(ps->source==PROJ_SRC_VIEW) + ED_view3d_local_clipping(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */ /* paint onto the derived mesh */ @@ -2796,7 +2811,7 @@ static void project_paint_begin(ProjPaintState *ps) ps->dm_release= FALSE; } else { - ps->dm = mesh_get_derived_final(ps->scene, ps->ob, ps->v3d->customdata_mask); + ps->dm = mesh_get_derived_final(ps->scene, ps->ob, ps->v3d->customdata_mask | CD_MASK_MTFACE); ps->dm_release= TRUE; } @@ -2861,44 +2876,81 @@ static void project_paint_begin(ProjPaintState *ps) ps->viewDir[1] = 0.0f; ps->viewDir[2] = 1.0f; - view3d_get_object_project_mat(ps->rv3d, ps->ob, ps->projectMat); - - /* viewDir - object relative */ - invert_m4_m4(ps->ob->imat, ps->ob->obmat); - copy_m3_m4(mat, ps->rv3d->viewinv); - mul_m3_v3(mat, ps->viewDir); - copy_m3_m4(mat, ps->ob->imat); - mul_m3_v3(mat, ps->viewDir); - normalize_v3(ps->viewDir); - - /* viewPos - object relative */ - VECCOPY(ps->viewPos, ps->rv3d->viewinv[3]); - copy_m3_m4(mat, ps->ob->imat); - mul_m3_v3(mat, ps->viewPos); - add_v3_v3v3(ps->viewPos, ps->viewPos, ps->ob->imat[3]); - - { /* only use these for running 'get_view3d_viewplane' */ + { rctf viewplane; - - ps->is_ortho = get_view3d_viewplane(ps->v3d, ps->rv3d, ps->ar->winx, ps->ar->winy, &viewplane, &ps->clipsta, &ps->clipend, NULL); - - //printf("%f %f\n", ps->clipsta, ps->clipend); - if (ps->is_ortho) { /* only needed for ortho */ - float fac = 2.0f / (ps->clipend - ps->clipsta); - ps->clipsta *= fac; - ps->clipend *= fac; + float viewmat[4][4]; + float viewinv[4][4]; + + invert_m4_m4(ps->ob->imat, ps->ob->obmat); + + if(ps->source==PROJ_SRC_VIEW) { + ps->winx= ps->ar->winx; + ps->winy= ps->ar->winy; + + copy_m4_m4(viewmat, ps->rv3d->viewmat); + copy_m4_m4(viewinv, ps->rv3d->viewinv); + + view3d_get_object_project_mat(ps->rv3d, ps->ob, ps->projectMat); + + ps->is_ortho= get_view3d_viewplane(ps->v3d, ps->rv3d, ps->winx, ps->winy, &viewplane, &ps->clipsta, &ps->clipend, NULL); + + //printf("%f %f\n", ps->clipsta, ps->clipend); + if (ps->is_ortho) { /* only needed for ortho */ + float fac = 2.0f / (ps->clipend - ps->clipsta); + ps->clipsta *= fac; + ps->clipend *= fac; + } + else { + /* TODO - can we even adjust for clip start/end? */ + } } - else { - /* TODO - can we even adjust for clip start/end? */ + else if (ps->source==PROJ_SRC_CAM) { + Object *camera= ps->scene->camera; + rctf viewplane; + float winmat[4][4]; + float vmat[4][4]; + + /* dont actually use these */ + float _viewdx, _viewdy, _ycor, _lens=0.0f; + + + ps->winx= ps->reproject_ibuf->x; + ps->winy= ps->reproject_ibuf->y; + + /* viewmat & viewinv */ + copy_m4_m4(viewinv, ps->scene->camera->obmat); + normalize_m4(viewinv); + invert_m4_m4(viewmat, viewinv); + + /* camera winmat */ + object_camera_matrix(&ps->scene->r, camera, ps->winx, ps->winy, 0, + winmat, &viewplane, &ps->clipsta, &ps->clipend, + &_lens, &_ycor, &_viewdx, &_viewdy); + + + /* same as view3d_get_object_project_mat */ + mul_m4_m4m4(vmat, ps->ob->obmat, viewmat); + mul_m4_m4m4(ps->projectMat, vmat, winmat); + + ps->is_ortho= (ps->scene->r.mode & R_ORTHO) ? 1 : 0; } + + + /* viewDir - object relative */ + invert_m4_m4(ps->ob->imat, ps->ob->obmat); + copy_m3_m4(mat, viewinv); + mul_m3_v3(mat, ps->viewDir); + copy_m3_m4(mat, ps->ob->imat); + mul_m3_v3(mat, ps->viewDir); + normalize_v3(ps->viewDir); + /* viewPos - object relative */ + VECCOPY(ps->viewPos, viewinv[3]); + copy_m3_m4(mat, ps->ob->imat); + mul_m3_v3(mat, ps->viewPos); + add_v3_v3v3(ps->viewPos, ps->viewPos, ps->ob->imat[3]); } - ps->is_airbrush = (ps->brush->flag & BRUSH_AIRBRUSH) ? 1 : 0; - - ps->is_texbrush = (ps->brush->mtex.tex) ? 1 : 0; - - /* calculate vert screen coords * run this early so we can calculate the x/y resolution of our bucket rect */ INIT_MINMAX2(ps->screenMin, ps->screenMax); @@ -2908,13 +2960,14 @@ static void project_paint_begin(ProjPaintState *ps) if (ps->is_ortho) { for(a=0; a < ps->dm_totvert; a++, projScreenCo++) { - VECCOPY((*projScreenCo), ps->dm_mvert[a].co); - mul_m4_v3(ps->projectMat, (*projScreenCo)); + mul_v3_m4v3((*projScreenCo), ps->projectMat, ps->dm_mvert[a].co); /* screen space, not clamped */ - (*projScreenCo)[0] = (float)(ps->ar->winx/2.0f)+(ps->ar->winx/2.0f)*(*projScreenCo)[0]; - (*projScreenCo)[1] = (float)(ps->ar->winy/2.0f)+(ps->ar->winy/2.0f)*(*projScreenCo)[1]; + (*projScreenCo)[0] = (float)(ps->winx/2.0f)+(ps->winx/2.0f)*(*projScreenCo)[0]; + (*projScreenCo)[1] = (float)(ps->winy/2.0f)+(ps->winy/2.0f)*(*projScreenCo)[1]; DO_MINMAX2((*projScreenCo), ps->screenMin, ps->screenMax); + + // VECCOPY(ps->dm_mvert[a].co, *projScreenCo) // HACK } } else { @@ -2927,8 +2980,8 @@ static void project_paint_begin(ProjPaintState *ps) if ((*projScreenCo)[3] > ps->clipsta) { /* screen space, not clamped */ - (*projScreenCo)[0] = (float)(ps->ar->winx/2.0f)+(ps->ar->winx/2.0f)*(*projScreenCo)[0]/(*projScreenCo)[3]; - (*projScreenCo)[1] = (float)(ps->ar->winy/2.0f)+(ps->ar->winy/2.0f)*(*projScreenCo)[1]/(*projScreenCo)[3]; + (*projScreenCo)[0] = (float)(ps->winx/2.0f)+(ps->winx/2.0f)*(*projScreenCo)[0]/(*projScreenCo)[3]; + (*projScreenCo)[1] = (float)(ps->winy/2.0f)+(ps->winy/2.0f)*(*projScreenCo)[1]/(*projScreenCo)[3]; (*projScreenCo)[2] = (*projScreenCo)[2]/(*projScreenCo)[3]; /* Use the depth for bucket point occlusion */ DO_MINMAX2((*projScreenCo), ps->screenMin, ps->screenMax); } @@ -2952,14 +3005,23 @@ static void project_paint_begin(ProjPaintState *ps) ps->screenMax[1] += projMargin; ps->screenMin[1] -= projMargin; + if(ps->source==PROJ_SRC_VIEW) { #ifdef PROJ_DEBUG_WINCLIP - CLAMP(ps->screenMin[0], -ps->brush->size, ps->ar->winx + ps->brush->size); - CLAMP(ps->screenMax[0], -ps->brush->size, ps->ar->winx + ps->brush->size); + CLAMP(ps->screenMin[0], -ps->brush->size, ps->winx + ps->brush->size); + CLAMP(ps->screenMax[0], -ps->brush->size, ps->winx + ps->brush->size); - CLAMP(ps->screenMin[1], -ps->brush->size, ps->ar->winy + ps->brush->size); - CLAMP(ps->screenMax[1], -ps->brush->size, ps->ar->winy + ps->brush->size); + CLAMP(ps->screenMin[1], -ps->brush->size, ps->winy + ps->brush->size); + CLAMP(ps->screenMax[1], -ps->brush->size, ps->winy + ps->brush->size); #endif - + } + else if (ps->source==PROJ_SRC_CAM) { + ps->screenMin[0]= 0; + ps->screenMax[0]= ps->winx; + + ps->screenMin[1]= 0; + ps->screenMax[1]= ps->winy; + } + /* only for convenience */ ps->screen_width = ps->screenMax[0] - ps->screenMin[0]; ps->screen_height = ps->screenMax[1] - ps->screenMin[1]; @@ -3166,8 +3228,8 @@ static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2]) projCo[3] = 1.0f; mul_m4_v4(ps->projectMat, projCo); - ps->cloneOffset[0] = mouse[0] - ((float)(ps->ar->winx/2.0f)+(ps->ar->winx/2.0f)*projCo[0]/projCo[3]); - ps->cloneOffset[1] = mouse[1] - ((float)(ps->ar->winy/2.0f)+(ps->ar->winy/2.0f)*projCo[1]/projCo[3]); + ps->cloneOffset[0] = mouse[0] - ((float)(ps->winx/2.0f)+(ps->winx/2.0f)*projCo[0]/projCo[3]); + ps->cloneOffset[1] = mouse[1] - ((float)(ps->winy/2.0f)+(ps->winy/2.0f)*projCo[1]/projCo[3]); } } @@ -3365,31 +3427,44 @@ static int project_image_refresh_tagged(ProjPaintState *ps) /* run this per painting onto each mouse location */ static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2]) { - float min_brush[2], max_brush[2]; - float size_half = ((float)ps->brush->size) * 0.5f; - - /* so we dont have a bucket bounds that is way too small to paint into */ - // if (size_half < 1.0f) size_half = 1.0f; // this dosnt work yet :/ - - min_brush[0] = mval_f[0] - size_half; - min_brush[1] = mval_f[1] - size_half; - - max_brush[0] = mval_f[0] + size_half; - max_brush[1] = mval_f[1] + size_half; - - /* offset to make this a valid bucket index */ - project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax); - - /* mouse outside the model areas? */ - if (ps->bucketMin[0]==ps->bucketMax[0] || ps->bucketMin[1]==ps->bucketMax[1]) { - return 0; + if(ps->source==PROJ_SRC_VIEW) { + float min_brush[2], max_brush[2]; + float size_half = ((float)ps->brush->size) * 0.5f; + + /* so we dont have a bucket bounds that is way too small to paint into */ + // if (size_half < 1.0f) size_half = 1.0f; // this dosnt work yet :/ + + min_brush[0] = mval_f[0] - size_half; + min_brush[1] = mval_f[1] - size_half; + + max_brush[0] = mval_f[0] + size_half; + max_brush[1] = mval_f[1] + size_half; + + /* offset to make this a valid bucket index */ + project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax); + + /* mouse outside the model areas? */ + if (ps->bucketMin[0]==ps->bucketMax[0] || ps->bucketMin[1]==ps->bucketMax[1]) { + return 0; + } + + ps->context_bucket_x = ps->bucketMin[0]; + ps->context_bucket_y = ps->bucketMin[1]; + } + else { /* PROJ_SRC_CAM */ + ps->bucketMin[0]= 0; + ps->bucketMin[1]= 0; + + ps->bucketMax[0]= ps->buckets_x; + ps->bucketMax[1]= ps->buckets_y; + + ps->context_bucket_x = 0; + ps->context_bucket_y = 0; } - - ps->context_bucket_x = ps->bucketMin[0]; - ps->context_bucket_y = ps->bucketMin[1]; return 1; } + static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2]) { if (ps->thread_tot > 1) @@ -3403,7 +3478,9 @@ static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/ project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds); - if (project_bucket_isect_circle(ps->context_bucket_x, ps->context_bucket_y, mval, ps->brush->size * ps->brush->size, bucket_bounds)) { + if ( (ps->source==PROJ_SRC_CAM) || + project_bucket_isect_circle(ps->context_bucket_x, ps->context_bucket_y, mval, ps->brush->size * ps->brush->size, bucket_bounds) + ) { *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x); ps->context_bucket_x++; @@ -3622,8 +3699,14 @@ static void *do_projectpaint_thread(void *ph_v) dist_nosqrt = Vec2Lenf_nosqrt(projPixel->projCoSS, pos); /*if (dist < s->brush->size) {*/ /* correct but uses a sqrtf */ - if (dist_nosqrt < brush_size_sqared && (dist=sqrtf(dist_nosqrt)) < size_half) { - falloff = brush_curve_strength_clamp(ps->brush, dist, size_half); + if ( ps->source==PROJ_SRC_CAM || + (dist_nosqrt < brush_size_sqared && (dist=sqrtf(dist_nosqrt)) < size_half)) { + + if(ps->source==PROJ_SRC_CAM) + falloff = 1.0f; + else + falloff = brush_curve_strength_clamp(ps->brush, dist, size_half); + if (falloff > 0.0f) { if (ps->is_texbrush) { brush_sample_tex(ps->brush, projPixel->projCoSS, rgba); @@ -3673,29 +3756,36 @@ static void *do_projectpaint_thread(void *ph_v) last_partial_redraw_cell->y2 = MAX2(last_partial_redraw_cell->y2, projPixel->y_px+1); - switch(tool) { - case PAINT_TOOL_CLONE: - if (is_floatbuf) { - if (((ProjPixelClone *)projPixel)->clonepx.f[3]) { - do_projectpaint_clone_f(ps, projPixel, rgba, alpha, mask); + if(ps->source==PROJ_SRC_VIEW) { + switch(tool) { + case PAINT_TOOL_CLONE: + if (is_floatbuf) { + if (((ProjPixelClone *)projPixel)->clonepx.f[3]) { + do_projectpaint_clone_f(ps, projPixel, rgba, alpha, mask); + } } - } - else { - if (((ProjPixelClone*)projPixel)->clonepx.ch[3]) { - do_projectpaint_clone(ps, projPixel, rgba, alpha, mask); + else { + if (((ProjPixelClone*)projPixel)->clonepx.ch[3]) { + do_projectpaint_clone(ps, projPixel, rgba, alpha, mask); + } } + break; + case PAINT_TOOL_SMEAR: + sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs); + + if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels_f, co); + else do_projectpaint_smear(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels, co); + break; + default: + if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask); + else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask); + break; } - break; - case PAINT_TOOL_SMEAR: - sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs); - - if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels_f, co); - else do_projectpaint_smear(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels, co); - break; - default: - if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask); - else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask); - break; + } + else { + /* reprojection! */ + bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL, projPixel->projCoSS[0], projPixel->projCoSS[1]); + blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*255)); } } /* done painting */ @@ -4434,18 +4524,18 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps) ToolSettings *settings= scene->toolsettings; Brush *brush; + /* these can be NULL */ ps->v3d= CTX_wm_view3d(C); ps->rv3d= CTX_wm_region_view3d(C); ps->ar= CTX_wm_region(C); - ps->scene= scene; + ps->scene= scene; ps->ob= ob; /* allow override of active object */ - /* setup projection painting data */ ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1; ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1; - ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1;; + ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1; if (ps->tool == PAINT_TOOL_CLONE) ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE); @@ -4479,6 +4569,9 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps) ps->brush = brush; ps->tool = brush->imagepaint_tool; ps->blend = brush->blend; + + ps->is_airbrush = (brush->flag & BRUSH_AIRBRUSH) ? 1 : 0; + ps->is_texbrush = (brush->mtex.tex) ? 1 : 0; } static int texture_paint_init(bContext *C, wmOperator *op) @@ -4539,6 +4632,8 @@ static int texture_paint_init(bContext *C, wmOperator *op) /* initialize all data from the context */ project_state_init(C, OBACT, &pop->ps); + pop->ps.source= PROJ_SRC_VIEW; + if (pop->ps.ob==NULL || !(pop->ps.ob->lay & pop->ps.v3d->lay)) return 0; @@ -5218,3 +5313,92 @@ int facemask_paint_poll(bContext *C) { return paint_facesel_test(CTX_data_active_object(C)); } + +/* use project paint to re-apply an image */ +static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) +{ + Image *image= BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image")); + + Scene *scene= CTX_data_scene(C); + ProjPaintState ps; + + memset(&ps, 0, sizeof(ps)); + + project_state_init(C, OBACT, &ps); + + if(scene->camera==NULL) { + BKE_report(op->reports, RPT_ERROR, "No active camera set."); + return OPERATOR_CANCELLED; + } + + if(image==NULL) { + BKE_report(op->reports, RPT_ERROR, "Image could not be found."); + return OPERATOR_CANCELLED; + } + + ps.reproject_ibuf= BKE_image_get_ibuf(image, NULL); + if(ps.reproject_ibuf==NULL || ps.reproject_ibuf->rect==NULL) { + BKE_report(op->reports, RPT_ERROR, "Image data could not be found."); + return OPERATOR_CANCELLED; + } + + /* override */ + ps.is_texbrush= 0; + ps.is_airbrush= 1; + ps.brush->alpha= 1.0; + ps.brush->size= 32; /* cover the whole image */ + + + ps.tool= PAINT_TOOL_DRAW; + + ps.source= PROJ_SRC_CAM; + + /* allocate and initialize spacial data structures */ + project_paint_begin(&ps); + + if(ps.dm==NULL) { + return OPERATOR_CANCELLED; + } + else { + float pos[2]= {0.0, 0.0}; + float lastpos[2]= {0.0, 0.0}; + int a; + + for (a=0; a < ps.image_tot; a++) + partial_redraw_array_init(ps.projImages[a].partRedrawRect); + + project_paint_op(&ps, NULL, lastpos, pos); + + project_image_refresh_tagged(&ps); + + for (a=0; a < ps.image_tot; a++) { + GPU_free_image(ps.projImages[a].ima); + WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, ps.projImages[a].ima); + } + } + + project_paint_end(&ps); + + return OPERATOR_FINISHED; +} + +void PAINT_OT_camera_project(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name= "Camera Project"; + ot->idname= "PAINT_OT_camera_project"; + ot->description= "Project an edited render from the active camera back onto the object"; + + /* api callbacks */ + ot->invoke= WM_enum_search_invoke; + ot->exec= texture_paint_camera_project_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + prop= RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", ""); + RNA_def_enum_funcs(prop, RNA_image_itemf); + ot->prop= prop; +} diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index b9b604480ec..1b4cf98626b 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -93,6 +93,7 @@ void PAINT_OT_sample_color(struct wmOperatorType *ot); void PAINT_OT_clone_cursor_set(struct wmOperatorType *ot); void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot); void PAINT_OT_texture_paint_radial_control(struct wmOperatorType *ot); +void PAINT_OT_camera_project(struct wmOperatorType *ot); /* paint_utils.c */ int imapaint_pick_face(struct ViewContext *vc, struct Mesh *me, int *mval, unsigned int *index); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index b43a78eb226..a225c871a5b 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -121,6 +121,7 @@ void ED_operatortypes_paint(void) WM_operatortype_append(PAINT_OT_sample_color); WM_operatortype_append(PAINT_OT_grab_clone); WM_operatortype_append(PAINT_OT_clone_cursor_set); + WM_operatortype_append(PAINT_OT_camera_project); /* weight */ WM_operatortype_append(PAINT_OT_weight_paint_toggle); diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index ddd6dfef653..5e93339dd64 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -90,6 +90,7 @@ EnumPropertyItem *rna_TransformOrientation_itemf(struct bContext *C, struct Poin * in the linked list can add more for different types as needed */ EnumPropertyItem *RNA_action_itemf(struct bContext *C, struct PointerRNA *ptr, int *free); EnumPropertyItem *RNA_group_itemf(struct bContext *C, struct PointerRNA *ptr, int *free); +EnumPropertyItem *RNA_image_itemf(struct bContext *C, struct PointerRNA *ptr, int *free); EnumPropertyItem *RNA_scene_itemf(struct bContext *C, struct PointerRNA *ptr, int *free); #endif /* RNA_ENUM_TYPES */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 29359b1ddb9..189181486ef 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3023,6 +3023,10 @@ EnumPropertyItem *RNA_group_itemf(bContext *C, PointerRNA *ptr, int *free) { return rna_id_itemf(C, ptr, free, C ? (ID *)CTX_data_main(C)->group.first : NULL); } +EnumPropertyItem *RNA_image_itemf(bContext *C, PointerRNA *ptr, int *free) +{ + return rna_id_itemf(C, ptr, free, C ? (ID *)CTX_data_main(C)->image.first : NULL); +} EnumPropertyItem *RNA_scene_itemf(bContext *C, PointerRNA *ptr, int *free) { return rna_id_itemf(C, ptr, free, C ? (ID *)CTX_data_main(C)->scene.first : NULL); |