diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-09-10 19:15:07 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-09-10 19:33:51 +0300 |
commit | 37f46606374f37dbe73c3555dc04c96a56e90bf3 (patch) | |
tree | 85a0e0234aa9e9ae1b9cc20c18ff74f3150ba389 /source | |
parent | 84c44e026e09a6817f604af1f115c1ebc3297d0b (diff) |
Fix T44344: paint bleed fails in perspective view
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_proj.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index cf13c9c1d83..7108b2bda6f 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -298,6 +298,7 @@ typedef struct ProjPaintState { float cloneOffset[2]; float projectMat[4][4]; /* Projection matrix, use for getting screen coords */ + float projectMatInv[4][4]; /* inverse of projectMat */ float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */ float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */ float clipsta, clipend; @@ -1247,6 +1248,55 @@ static void screen_px_from_persp( } +/** + * Set a direction vector based on a screen location. + * (use for perspective view, else we can simply use `ps->viewDir`) + * + * Similar functionality to #ED_view3d_win_to_vector + * + * \param r_dir: Resulting direction (length is undefined). + */ +static void screen_px_to_vector_persp( + int winx, int winy, const float projmat_inv[4][4], const float view_pos[3], + const float co_px[2], + float r_dir[3]) +{ + r_dir[0] = 2.0f * (co_px[0] / winx) - 1.0f; + r_dir[1] = 2.0f * (co_px[1] / winy) - 1.0f; + r_dir[2] = -0.5f; + mul_project_m4_v3((float(*)[4])projmat_inv, r_dir); + sub_v3_v3(r_dir, view_pos); +} + +/** + * Special function to return the factor fo a point along a line in pixel space. + * + * This is needed since we can't use #line_point_factor_v2 for perspective screen-space coords. + * + * \param p: 2D screen-space location. + * \param v1, v2: 3D object-space locations. + */ +static float screen_px_line_point_factor_v2_persp( + const ProjPaintState *ps, + const float p[2], + const float v1[3], const float v2[3]) +{ + const float zero[3] = {0}; + float v1_proj[3], v2_proj[3]; + float dir[3]; + + screen_px_to_vector_persp(ps->winx, ps->winy, ps->projectMatInv, ps->viewPos, p, dir); + + sub_v3_v3v3(v1_proj, v1, ps->viewPos); + sub_v3_v3v3(v2_proj, v2, ps->viewPos); + + project_plane_v3_v3v3(v1_proj, v1_proj, dir); + project_plane_v3_v3v3(v2_proj, v2_proj, dir); + + return line_point_factor_v2(zero, v1_proj, v2_proj); +} + + static void project_face_pixel( const float *lt_tri_uv[3], ImBuf *ibuf_other, const float w[3], unsigned char rgba_ub[4], float rgba_f[4]) @@ -2680,8 +2730,15 @@ static void project_paint_face_init( line_clip_rect2f(clip_rect, bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1])) { if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) { /* avoid div by zero */ - fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]); - fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]); + + if (is_ortho) { + fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]); + fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]); + } + else { + fac1 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[0], vCo[fidx1], vCo[fidx2]); + fac2 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[1], vCo[fidx1], vCo[fidx2]); + } interp_v2_v2v2(seam_subsection[0], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac1); interp_v2_v2v2(seam_subsection[1], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac2); @@ -3104,6 +3161,7 @@ static void proj_paint_state_viewport_init( mul_m4_m4m4(ps->projectMat, winmat, vmat); } + invert_m4_m4(ps->projectMatInv, ps->projectMat); /* viewDir - object relative */ copy_m3_m4(mat, viewinv); |