diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2013-06-26 18:28:39 +0400 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2013-06-26 18:28:39 +0400 |
commit | 3b0328436f039a2274caf9c58588b3318a0eed44 (patch) | |
tree | 1f216ca5d82c1d5bd594151b274a514cbe22000f /source/blender/editors/sculpt_paint | |
parent | 42940807ee47cf27fc1b88e28b52439ff9488a25 (diff) |
Fix #35365 Texture cloning not behaving correctly in perspective view
This issue was caused by doing pespective interpolation of clone uv
coordinates in perspective view. To fix this we need to use perspective
correction for screen coordinates, but return regular barycentric
weights back for clone layer uv coordinate interpolation.
Diffstat (limited to 'source/blender/editors/sculpt_paint')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_proj.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index a24ee13e3bf..553a5cbe9ac 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -1121,6 +1121,44 @@ static void screen_px_from_persp( interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w); } + +/* same as screen_px_from_persp except we return ortho weights back to the caller. + * These weights will be used to determine correct interpolation of uvs in cloned uv layer */ +static void screen_px_from_persp_ortho_weights( + float uv[2], + float v1co[4], float v2co[4], float v3co[4], /* screenspace coords */ + float uv1co[2], float uv2co[2], float uv3co[2], + float pixelScreenCo[4], + float w[3]) +{ + float w_int[3]; + float wtot_inv, wtot; + barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w); + + /* re-weight from the 4th coord of each screen vert */ + w_int[0] = w[0] * v1co[3]; + w_int[1] = w[1] * v2co[3]; + w_int[2] = w[2] * v3co[3]; + + wtot = w_int[0] + w_int[1] + w_int[2]; + + if (wtot > 0.0f) { + wtot_inv = 1.0f / wtot; + w_int[0] *= wtot_inv; + w_int[1] *= wtot_inv; + w_int[2] *= wtot_inv; + } + else { + w[0] = w[1] = w[2] = + w_int[0] = w_int[1] = w_int[2] = 1.0f / 3.0f; /* dummy values for zero area face */ + } + /* done re-weighting */ + + /* do interpolation based on projected weight */ + interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w_int); +} + + static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], int side, unsigned char rgba_ub[4], float rgba_f[4]) { @@ -2168,6 +2206,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i float uv_clip[8][2]; int uv_clip_tot; const short is_ortho = ps->is_ortho; + const short is_clone_other = ((ps->brush->imagepaint_tool == PAINT_TOOL_CLONE) && ps->dm_mtface_clone); const short do_backfacecull = ps->do_backfacecull; const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; @@ -2191,8 +2230,6 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i * but since the first thing most people try is painting onto a quad- better make it work. */ - - tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx; tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx; @@ -2277,7 +2314,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i has_x_isect = has_isect = 1; if (is_ortho) screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); - else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); + else if (is_clone_other) screen_px_from_persp_ortho_weights(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); + else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); /* a pity we need to get the worldspace pixel location here */ if (do_clip || do_3d_mapping) { |