diff options
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_project.c')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_project.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 0afa44b6f4f..58538fc3ecb 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -633,6 +633,48 @@ bool ED_view3d_win_to_3d_on_plane_int(const ARegion *region, } /** + * A wrapper for #ED_view3d_win_to_3d_on_plane that projects onto \a plane_fallback + * then maps this back to \a plane. + * + * This is intended to be used when \a plane is orthogonal to the views Z axis where + * projecting the \a mval doesn't work well (or fail completely when exactly aligned). + */ +bool ED_view3d_win_to_3d_on_plane_with_fallback(const ARegion *region, + const float plane[4], + const float mval[2], + const bool do_clip, + const float plane_fallback[4], + float r_out[3]) +{ + float isect_co[3], isect_no[3]; + if (!isect_plane_plane_v3(plane, plane_fallback, isect_co, isect_no)) { + return false; + } + normalize_v3(isect_no); + + /* Construct matrix to transform `plane_fallback` onto `plane`. */ + float mat4[4][4]; + { + float mat3[3][3]; + rotation_between_vecs_to_mat3(mat3, plane, plane_fallback); + copy_m4_m3(mat4, mat3); + transform_pivot_set_m4(mat4, isect_co); + } + + float co[3]; + if (!ED_view3d_win_to_3d_on_plane(region, plane_fallback, mval, do_clip, co)) { + return false; + } + mul_m4_v3(mat4, co); + + /* While the point is already on the plane, there may be some small in-precision + * so ensure the point is exactly on the plane. */ + closest_to_plane_v3(r_out, plane, co); + + return true; +} + +/** * Calculate a 3d difference vector from 2d window offset. * note that #ED_view3d_calc_zfac() must be called first to determine * the depth used to calculate the delta. |