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
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-03-05 21:19:32 +0300
committerCampbell Barton <ideasman42@gmail.com>2010-03-05 21:19:32 +0300
commit94d5b31b9d33ec51c7b05bb57b2166df2919eaa9 (patch)
treeed1d44ae156ddd4baab5fb5478b2eb60f869c1a2 /source
parentd0c70ad1d581d69f650d604293c006b2e0023310 (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.c384
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c1
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c4
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);