fix for harmless glitch rotating the camera in camera mode, having the center point...
authorCampbell Barton <ideasman42@gmail.com>
Thu, 28 Feb 2013 11:29:27 +0000 (11:29 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 28 Feb 2013 11:29:27 +0000 (11:29 +0000)
source/blender/editors/include/ED_view3d.h
source/blender/editors/space_view3d/view3d_project.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h

index 46f4515..d89d66d 100644 (file)
@@ -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 */
index c428cb0..bc1656f 100644 (file)
@@ -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;
index 5314224..c8874d1 100644 (file)
@@ -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();
 
index 9c57c74..dbf56f6 100644 (file)
@@ -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);