diff options
-rw-r--r-- | source/blender/editors/include/ED_view3d.h | 14 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_project.c | 36 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 18 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 3 |
4 files changed, 47 insertions, 24 deletions
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 46f4515e0ca..d89d66dd62c 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -105,9 +105,10 @@ void ED_view3d_depth_tag_update(struct RegionView3D *rv3d); typedef enum { V3D_PROJ_RET_OK = 0, V3D_PROJ_RET_CLIP_NEAR = 1, /* can't avoid this when in perspective mode, (can't avoid) */ - V3D_PROJ_RET_CLIP_BB = 2, /* bounding box clip - RV3D_CLIPPING */ - V3D_PROJ_RET_CLIP_WIN = 3, /* outside window bounds */ - V3D_PROJ_RET_OVERFLOW = 4 /* outside range (mainly for short), (can't avoid) */ + V3D_PROJ_RET_CLIP_ZERO = 2, /* so close to zero we can't apply a perspective matrix usefully */ + V3D_PROJ_RET_CLIP_BB = 3, /* bounding box clip - RV3D_CLIPPING */ + V3D_PROJ_RET_CLIP_WIN = 4, /* outside window bounds */ + V3D_PROJ_RET_OVERFLOW = 5 /* outside range (mainly for short), (can't avoid) */ } eV3DProjStatus; /* some clipping tests are optional */ @@ -116,10 +117,13 @@ typedef enum { V3D_PROJ_TEST_CLIP_BB = (1 << 0), V3D_PROJ_TEST_CLIP_WIN = (1 << 1), V3D_PROJ_TEST_CLIP_NEAR = (1 << 2), + V3D_PROJ_TEST_CLIP_ZERO = (1 << 3) } eV3DProjTest; -#define V3D_PROJ_TEST_CLIP_DEFAULT (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) -#define V3D_PROJ_TEST_ALL (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) +#define V3D_PROJ_TEST_CLIP_DEFAULT \ + (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) +#define V3D_PROJ_TEST_ALL \ + (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_ZERO) /* view3d_iterators.c */ diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index c428cb02236..bc1656ff7c6 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -43,6 +43,7 @@ #include "ED_view3d.h" /* own include */ #define BL_NEAR_CLIP 0.001 +#define BL_ZERO_CLIP 0.001 /* Non Clipping Projection Functions * ********************************* */ @@ -134,18 +135,25 @@ static eV3DProjStatus ed_view3d_project__internal(ARegion *ar, vec4[3] = 1.0; mul_m4_v4(perspmat, vec4); - if (((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) || (vec4[3] > (float)BL_NEAR_CLIP)) { - const float scalar = (vec4[3] != 0.0f) ? (1.0f / vec4[3]): 0.0f; - const float fx = ((float)ar->winx / 2.0f) * (1.0f + (vec4[0] * scalar)); - if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0.0f && fx < (float)ar->winx)) { - const float fy = ((float)ar->winy / 2.0f) * (1.0f + (vec4[1] * scalar)); - if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) { - r_co[0] = floorf(fx); - r_co[1] = floorf(fy); - - /* check if the point is behind the view, we need to flip in this case */ - if (UNLIKELY((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) && (vec4[3] < 0.0f)) { - negate_v2(r_co); + + + if (((flag & V3D_PROJ_TEST_CLIP_ZERO) == 0) || (fabsf(vec4[3]) > (float)BL_ZERO_CLIP)) { + if (((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) || (vec4[3] > (float)BL_NEAR_CLIP)) { + const float scalar = (vec4[3] != 0.0f) ? (1.0f / vec4[3]): 0.0f; + const float fx = ((float)ar->winx / 2.0f) * (1.0f + (vec4[0] * scalar)); + if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0.0f && fx < (float)ar->winx)) { + const float fy = ((float)ar->winy / 2.0f) * (1.0f + (vec4[1] * scalar)); + if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) { + r_co[0] = floorf(fx); + r_co[1] = floorf(fy); + + /* check if the point is behind the view, we need to flip in this case */ + if (UNLIKELY((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) && (vec4[3] < 0.0f)) { + negate_v2(r_co); + } + } + else { + return V3D_PROJ_RET_CLIP_WIN; } } else { @@ -153,11 +161,11 @@ static eV3DProjStatus ed_view3d_project__internal(ARegion *ar, } } else { - return V3D_PROJ_RET_CLIP_WIN; + return V3D_PROJ_RET_CLIP_NEAR; } } else { - return V3D_PROJ_RET_CLIP_NEAR; + return V3D_PROJ_RET_CLIP_ZERO; } return V3D_PROJ_RET_OK; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 53142243f4f..c8874d13cac 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -239,11 +239,11 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) } } -void projectIntView(TransInfo *t, const float vec[3], int adr[2]) +void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag) { if (t->spacetype == SPACE_VIEW3D) { if (t->ar->regiontype == RGN_TYPE_WINDOW) { - if (ED_view3d_project_int_global(t->ar, vec, adr, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + if (ED_view3d_project_int_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) { adr[0] = (int)2140000000.0f; /* this is what was done in 2.64, perhaps we can be smarter? */ adr[1] = (int)2140000000.0f; } @@ -361,15 +361,19 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], adr, adr + 1); } } +void projectIntView(TransInfo *t, const float vec[3], int adr[2]) +{ + projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); +} -void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) +void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag) { switch (t->spacetype) { case SPACE_VIEW3D: { if (t->ar->regiontype == RGN_TYPE_WINDOW) { /* allow points behind the view [#33643] */ - if (ED_view3d_project_float_global(t->ar, vec, adr, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) { /* XXX, 2.64 and prior did this, weak! */ adr[0] = t->ar->winx / 2.0f; adr[1] = t->ar->winy / 2.0f; @@ -393,6 +397,10 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) zero_v2(adr); } +void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) +{ + projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); +} void applyAspectRatio(TransInfo *t, float vec[2]) { @@ -1543,7 +1551,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) if (ob) mul_m4_v3(ob->obmat, vecrot); } - projectFloatView(t, vecrot, cent); // no overflow in extreme cases + projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO); glPushMatrix(); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 9c57c74a26d..dbf56f658ac 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -35,6 +35,7 @@ #include "ED_transform.h" #include "ED_numinput.h" +#include "ED_view3d.h" #include "DNA_listBase.h" @@ -481,7 +482,9 @@ int transformEnd(struct bContext *C, TransInfo *t); void setTransformViewMatrices(TransInfo *t); void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy); +void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag); void projectIntView(TransInfo *t, const float vec[3], int adr[2]); +void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag); void projectFloatView(TransInfo *t, const float vec[3], float adr[2]); void applyAspectRatio(TransInfo *t, float *vec); |