refactor ED_view3d_project_short & ED_view3d_project_short_noclip,
authorCampbell Barton <ideasman42@gmail.com>
Thu, 4 Oct 2012 16:46:15 +0000 (16:46 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 4 Oct 2012 16:46:15 +0000 (16:46 +0000)
This is apart of a code cleanup to make  ED_view3d_project_short/ED_view3d_project_int/ED_view3d_project_float interchangeable. Currently they work very differently in a way thats quite confusing (and cause of bugs in blender that remain uncorrected) - fixes coming.

There are also cases where ED_view3d_project_short is used, then the values are converted from shorts into int's after because ED_view3d_project_int() behaves differently, will unify behavior of these functions after this commit.

- rather then clip/noclip versions, pass flags (for bound-box clip, window clip).
- rather then store the invalid clip-value, return success (or error value clip_near, clip_bb, clip_win, overflow).
- remove local copies of project functions from drawobject.c: view3d_project_short_clip, view3d_project_short_noclip, view3d_project_short_clip_persmat.

add functions:
- ED_view3d_project_short_global() global space projection
- ED_view3d_project_short_object() object space projection.
- ED_view3d_project_short_ex() take perspective matrix and local space option as args.
- ED_view3d_project_base() - special function to set the Object 'Base' screen coords (sx, sy), since this is a common enough operation.

source/blender/editors/armature/editarmature_sketch.c
source/blender/editors/include/ED_view3d.h
source/blender/editors/physics/particle_edit.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/space_view3d/view3d_view.c

index 8d8fa730360e815c874cccb67b7b86e4ac468fb9..b72fad08d1f142442a56b92b382ebf78c3f5e94e 100644 (file)
@@ -646,16 +646,17 @@ static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], in
                        short pval[2];
                        int pdist;
 
-                       ED_view3d_project_short_noclip(ar, stk->points[i].p, pval);
+                       if (ED_view3d_project_short_global(ar, stk->points[i].p, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) {
 
-                       pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+                               pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
 
-                       if (pdist < *dist) {
-                               *dist = pdist;
-                               pt = stk->points + i;
+                               if (pdist < *dist) {
+                                       *dist = pdist;
+                                       pt = stk->points + i;
 
-                               if (index != NULL) {
-                                       *index = i;
+                                       if (index != NULL) {
+                                               *index = i;
+                                       }
                                }
                        }
                }
@@ -681,32 +682,34 @@ static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones,
                {
                        copy_v3_v3(vec, bone->head);
                        mul_m4_v3(ob->obmat, vec);
-                       ED_view3d_project_short_noclip(ar, vec, pval);
+                       if (ED_view3d_project_short_noclip(ar, vec, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) {
 
-                       pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+                               pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
 
-                       if (pdist < *dist)
-                       {
-                               *dist = pdist;
-                               pt = &boneSnap;
-                               copy_v3_v3(pt->p, vec);
-                               pt->type = PT_EXACT;
+                               if (pdist < *dist)
+                               {
+                                       *dist = pdist;
+                                       pt = &boneSnap;
+                                       copy_v3_v3(pt->p, vec);
+                                       pt->type = PT_EXACT;
+                               }
                        }
                }
 
 
                copy_v3_v3(vec, bone->tail);
                mul_m4_v3(ob->obmat, vec);
-               ED_view3d_project_short_noclip(ar, vec, pval);
+               if (ED_view3d_project_short_noclip(ar, vec, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) {
 
-               pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+                       pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
 
-               if (pdist < *dist)
-               {
-                       *dist = pdist;
-                       pt = &boneSnap;
-                       copy_v3_v3(pt->p, vec);
-                       pt->type = PT_EXACT;
+                       if (pdist < *dist)
+                       {
+                               *dist = pdist;
+                               pt = &boneSnap;
+                               copy_v3_v3(pt->p, vec);
+                               pt->type = PT_EXACT;
+                       }
                }
        }
 
@@ -936,10 +939,14 @@ static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_Dr
        initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
 
        /* method taken from editview.c - mouse_cursor() */
-       ED_view3d_project_short_noclip(ar, fp, cval);
-       VECSUB2D(mval_f, cval, dd->mval);
-       ED_view3d_win_to_delta(ar, mval_f, dvec);
-       sub_v3_v3v3(vec, fp, dvec);
+       if (ED_view3d_project_short_global(ar, fp, cval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) {
+               VECSUB2D(mval_f, cval, dd->mval);
+               ED_view3d_win_to_delta(ar, mval_f, dvec);
+               sub_v3_v3v3(vec, fp, dvec);
+       }
+       else {
+               zero_v3(vec);
+       }
 }
 
 static int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *UNUSED(sketch), SK_Stroke *stk, SK_DrawData *dd)
@@ -1786,33 +1793,35 @@ int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *UNUSED(sketc
                short start_val[2], end_val[2];
                short dist;
 
-               ED_view3d_project_short_noclip(ar, gest->stk->points[0].p, start_val);
-               ED_view3d_project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
+               if ((ED_view3d_project_short_global(ar, gest->stk->points[0].p,           start_val, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) &&
+                   (ED_view3d_project_short_global(ar, sk_lastStrokePoint(gest->stk)->p, end_val,   V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS))
+               {
 
-               dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
+                       dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
 
-               /* if gesture is a circle */
-               if (dist <= 20) {
-                       SK_Intersection *isect;
+                       /* if gesture is a circle */
+                       if (dist <= 20) {
+                               SK_Intersection *isect;
 
-                       /* check if it circled around an exact point */
-                       for (isect = gest->intersections.first; isect; isect = isect->next) {
-                               /* only delete strokes that are crossed twice */
-                               if (isect->next && isect->next->stroke == isect->stroke) {
-                                       int start_index, end_index;
-                                       int i;
+                               /* check if it circled around an exact point */
+                               for (isect = gest->intersections.first; isect; isect = isect->next) {
+                                       /* only delete strokes that are crossed twice */
+                                       if (isect->next && isect->next->stroke == isect->stroke) {
+                                               int start_index, end_index;
+                                               int i;
 
-                                       start_index = MIN2(isect->after, isect->next->after);
-                                       end_index = MAX2(isect->before, isect->next->before);
+                                               start_index = MIN2(isect->after, isect->next->after);
+                                               end_index = MAX2(isect->before, isect->next->before);
 
-                                       for (i = start_index; i <= end_index; i++) {
-                                               if (isect->stroke->points[i].type == PT_EXACT) {
-                                                       return 1; /* at least one exact point found, stop detect here */
+                                               for (i = start_index; i <= end_index; i++) {
+                                                       if (isect->stroke->points[i].type == PT_EXACT) {
+                                                               return 1; /* at least one exact point found, stop detect here */
+                                                       }
                                                }
-                                       }
 
-                                       /* skip next */
-                                       isect = isect->next;
+                                               /* skip next */
+                                               isect = isect->next;
+                                       }
                                }
                        }
                }
index 9536dd765811a1957f6b9a45df861cbeb5393349..ca5d8691df7c4522b5098f3abbdab6cbae109ca4 100644 (file)
@@ -113,8 +113,31 @@ void  ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
 /* TODO, these functions work quite differently, we should make them behave in a uniform way
  * otherwise we can't be sure bugs are not added when we need to move from short->float types for eg
  * - Campbell */
-void ED_view3d_project_short(struct ARegion *ar, const float co[3], short r_co[2]);
-void ED_view3d_project_short_noclip(struct ARegion *ar, const float vec[3], short r_co[2]);
+
+
+/* return values for ED_view3d_project_...() */
+typedef enum {
+       V3D_PROJ_RET_SUCCESS   = 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) */
+} eV3DProjStatus;
+
+/* some clipping tests are optional */
+typedef enum {
+       V3D_PROJ_TEST_NOP        = 0,
+       V3D_PROJ_TEST_CLIP_BB    = (1 << 0),
+       V3D_PROJ_TEST_CLIP_WIN   = (1 << 1),
+} eV3DProjTest;
+
+
+eV3DProjStatus ED_view3d_project_short_ex(struct ARegion *ar, float perspmat[4][4], const int is_local,
+                                          const float co[3], short r_co[2], eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_short_global(struct ARegion *ar, const float co[3], short r_co[2], eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_short_object(struct ARegion *ar, const float co[3], short r_co[2], eV3DProjTest flag);
+void _ED_view3d_project_short(struct ARegion *ar, const float co[3], short r_co[2]); // V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN
+void _ED_view3d_project_short_noclip(struct ARegion *ar, const float vec[3], short r_co[2]); //
 void ED_view3d_project_int(struct ARegion *ar, const float co[3], int r_co[2]);
 void ED_view3d_project_int_noclip(struct ARegion *ar, const float co[3], int r_co[2]);
 void ED_view3d_project_float(struct ARegion *ar, const float co[3], float r_co[2]);
@@ -122,6 +145,9 @@ void ED_view3d_project_float_noclip(struct ARegion *ar, const float co[3], float
 void ED_view3d_project_float_v2_m4(const struct ARegion *a, const float co[3], float r_co[2], float mat[4][4]);
 void ED_view3d_project_float_v3_m4(struct ARegion *a, const float co[3], float r_co[3], float mat[4][4]);
 
+/* Base's get their own function since its a common operation */
+eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base);
+
 void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z);
 
 int  ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *clipsta, float *clipend);
index ea6f9d4cebbf21ca5174d60e4690d5609c498874..6d3f4b3858329e8c3b9fe56d8ee87305211f55ae 100644 (file)
@@ -408,11 +408,12 @@ static int key_test_depth(PEData *data, const float co[3])
        /* nothing to do */
        if ((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0)
                return 1;
-
-       ED_view3d_project_short(data->vc.ar, co, wco);
        
-       if (wco[0] == IS_CLIPPED)
+       if (ED_view3d_project_short_global(data->vc.ar, co, wco,
+                                          V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_SUCCESS)
+       {
                return 0;
+       }
 
        gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection,
                   (GLint *)data->mats.viewport, &ux, &uy, &uz);
index 7badca304c4a85ac277240a13026def30f825ddf..e368f06a35fad716d61d57195bda6e876ab0eb3f 100644 (file)
@@ -239,107 +239,6 @@ static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
        return 1;
 }
 
-/* ************* only use while object drawing **************
- * or after running ED_view3d_init_mats_rv3d
- * */
-static void view3d_project_short_clip(ARegion *ar, const float vec[3], short adr[2], int is_local)
-{
-       RegionView3D *rv3d = ar->regiondata;
-       float fx, fy, vec4[4];
-       
-       adr[0] = IS_CLIPPED;
-       
-       /* clipplanes in eye space */
-       if (rv3d->rflag & RV3D_CLIPPING) {
-               if (ED_view3d_clipping_test(rv3d, vec, is_local))
-                       return;
-       }
-       
-       copy_v3_v3(vec4, vec);
-       vec4[3] = 1.0;
-       
-       mul_m4_v4(rv3d->persmatob, vec4);
-       
-       /* clipplanes in window space */
-       if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
-               fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
-               
-               if (fx > 0 && fx < ar->winx) {
-                       
-                       fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
-                       
-                       if (fy > 0.0f && fy < (float)ar->winy) {
-                               adr[0] = (short)floorf(fx);
-                               adr[1] = (short)floorf(fy);
-                       }
-               }
-       }
-}
-
-/* BMESH NOTE: this function is unused in bmesh only */
-
-/* only use while object drawing */
-static void UNUSED_FUNCTION(view3d_project_short_noclip) (ARegion * ar, const float vec[3], short adr[2])
-{
-       RegionView3D *rv3d = ar->regiondata;
-       float fx, fy, vec4[4];
-       
-       adr[0] = IS_CLIPPED;
-       
-       copy_v3_v3(vec4, vec);
-       vec4[3] = 1.0;
-       
-       mul_m4_v4(rv3d->persmatob, vec4);
-       
-       if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
-               fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
-               
-               if (fx > -32700 && fx < 32700) {
-                       
-                       fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
-                       
-                       if (fy > -32700.0f && fy < 32700.0f) {
-                               adr[0] = (short)floorf(fx);
-                               adr[1] = (short)floorf(fy);
-                       }
-               }
-       }
-}
-
-/* same as view3d_project_short_clip but use persmat instead of persmatob for projection */
-static void view3d_project_short_clip_persmat(ARegion *ar, const float vec[3], short adr[2], int is_local)
-{
-       RegionView3D *rv3d = ar->regiondata;
-       float fx, fy, vec4[4];
-
-       adr[0] = IS_CLIPPED;
-
-       /* clipplanes in eye space */
-       if (rv3d->rflag & RV3D_CLIPPING) {
-               if (ED_view3d_clipping_test(rv3d, vec, is_local))
-                       return;
-       }
-
-       copy_v3_v3(vec4, vec);
-       vec4[3] = 1.0;
-
-       mul_m4_v4(rv3d->persmat, vec4);
-
-       /* clipplanes in window space */
-       if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
-               fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
-
-               if (fx > 0 && fx < ar->winx) {
-
-                       fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
-
-                       if (fy > 0.0f && fy < (float)ar->winy) {
-                               adr[0] = (short)floorf(fx);
-                               adr[1] = (short)floorf(fy);
-                       }
-               }
-       }
-}
 /* ************************ */
 
 /* check for glsl drawing */
@@ -883,13 +782,17 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa
                if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
                        mul_m4_v3(mat, vos->vec);
 
-               if (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE)
-                       view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
-               else
-                       view3d_project_short_clip(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
-
-               if (vos->sco[0] != IS_CLIPPED)
+               if (ED_view3d_project_short_ex(ar,
+                                          (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
+                                          (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0,
+                                          vos->vec, vos->sco,
+                                          V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+               {
                        tot++;
+               }
+               else {
+                       vos->sco[0] = IS_CLIPPED;
+               }
        }
 
        if (tot) {
@@ -1974,15 +1877,17 @@ void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPo
        DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS);
        float *co = dl ? dl->verts : NULL;
        int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
-       short s[2] = {IS_CLIPPED, 0};
+       short s[2];
 
        ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
 
        for (i = 0; i < N; i++, bp++, co += 3) {
                if (bp->hide == 0) {
-                       view3d_project_short_clip(vc->ar, dl ? co : bp->vec, s, TRUE);
-                       if (s[0] != IS_CLIPPED)
+                       if (ED_view3d_project_short_object(vc->ar, dl ? co : bp->vec, s,
+                                                          V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+                       {
                                func(userData, bp, s[0], s[1]);
+                       }
                }
        }
 }
@@ -2084,19 +1989,16 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const flo
        BMVert *eve = EDBM_vert_at_index(data->vc.em, index);
 
        if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
-               short s[2] = {IS_CLIPPED, 0};
+               const eV3DProjTest flag = (data->clipVerts == V3D_CLIP_TEST_OFF) ?
+                           V3D_PROJ_TEST_NOP :
+                           V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN;
+               short s[2];
 
-               if (data->clipVerts != V3D_CLIP_TEST_OFF) {
-                       view3d_project_short_clip(data->vc.ar, co, s, TRUE);
-               }
-               else {
-                       float co2[2];
-                       mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
-                       ED_view3d_project_short_noclip(data->vc.ar, co2, s);
+               if (ED_view3d_project_short_object(data->vc.ar, co, s, flag) != V3D_PROJ_RET_SUCCESS) {
+                       return;
                }
 
-               if (s[0] != IS_CLIPPED)
-                       data->func(data->userData, eve, s[0], s[1], index);
+               data->func(data->userData, eve, s[0], s[1], index);
        }
 }
 
@@ -2159,25 +2061,21 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const flo
        if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
                short s[2][2];
 
-               if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
-                       view3d_project_short_clip(data->vc.ar, v0co, s[0], TRUE);
-                       view3d_project_short_clip(data->vc.ar, v1co, s[1], TRUE);
+               const eV3DProjTest flag = (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) ?
+                           V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN :
+                           V3D_PROJ_TEST_NOP;
 
-                       if (s[0][0] == IS_CLIPPED || s[1][0] == IS_CLIPPED) {
-                               return;
-                       }
+               if (ED_view3d_project_short_object(data->vc.ar, v0co, s[0], flag) != V3D_PROJ_RET_SUCCESS) {
+                       return;
+               }
+               if (ED_view3d_project_short_object(data->vc.ar, v1co, s[1], flag) != V3D_PROJ_RET_SUCCESS) {
+                       return;
                }
-               else {
-                       float v1_co[3], v2_co[3];
-
-                       mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
-                       mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
-
-                       /* XXX, todo, use ED_view3d_project_int_noclip(...), however these functions work differently
-                        * and need to be cleaned up, Campbell */
-                       ED_view3d_project_short_noclip(data->vc.ar, v1_co, s[0]);
-                       ED_view3d_project_short_noclip(data->vc.ar, v2_co, s[1]);
 
+               if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
+                       /* pass */
+               }
+               else {
                        if (data->clipVerts == V3D_CLIP_TEST_REGION) {
                                /* make an int copy */
                                int s_int[2][2] = {{s[0][0], s[0][1]},
@@ -2230,10 +2128,12 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const flo
                float cent2[3];
                short s[2];
 
-               mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
-               ED_view3d_project_short(data->vc.ar, cent2, s);
+               /* TODO, use ED_view3d_project_short_object */
 
-               if (s[0] != IS_CLIPPED) {
+               mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
+               if (ED_view3d_project_short_global(data->vc.ar, cent2, s,
+                                                  V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+               {
                        data->func(data->userData, efa, s[0], s[1], index);
                }
        }
@@ -2267,7 +2167,7 @@ void nurbs_foreachScreenVert(
         void *userData)
 {
        Curve *cu = vc->obedit->data;
-       short s[2] = {IS_CLIPPED, 0};
+       short s[2];
        Nurb *nu;
        int i;
        ListBase *nurbs = BKE_curve_editNurbs_get(cu);
@@ -2282,20 +2182,28 @@ void nurbs_foreachScreenVert(
                                if (bezt->hide == 0) {
                                        
                                        if (cu->drawflag & CU_HIDE_HANDLES) {
-                                               view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
-                                               if (s[0] != IS_CLIPPED)
+                                               if (ED_view3d_project_short_object(vc->ar, bezt->vec[1], s,
+                                                                                  V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+                                               {
                                                        func(userData, nu, NULL, bezt, 1, s[0], s[1]);
+                                               }
                                        }
                                        else {
-                                               view3d_project_short_clip(vc->ar, bezt->vec[0], s, TRUE);
-                                               if (s[0] != IS_CLIPPED)
+                                               if (ED_view3d_project_short_object(vc->ar, bezt->vec[0], s,
+                                                                                  V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+                                               {
                                                        func(userData, nu, NULL, bezt, 0, s[0], s[1]);
-                                               view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
-                                               if (s[0] != IS_CLIPPED)
+                                               }
+                                               if (ED_view3d_project_short_object(vc->ar, bezt->vec[1], s,
+                                                                                  V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+                                               {
                                                        func(userData, nu, NULL, bezt, 1, s[0], s[1]);
-                                               view3d_project_short_clip(vc->ar, bezt->vec[2], s, TRUE);
-                                               if (s[0] != IS_CLIPPED)
+                                               }
+                                               if (ED_view3d_project_short_object(vc->ar, bezt->vec[2], s,
+                                                                                  V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+                                               {
                                                        func(userData, nu, NULL, bezt, 2, s[0], s[1]);
+                                               }
                                        }
                                }
                        }
@@ -2305,9 +2213,11 @@ void nurbs_foreachScreenVert(
                                BPoint *bp = &nu->bp[i];
 
                                if (bp->hide == 0) {
-                                       view3d_project_short_clip(vc->ar, bp->vec, s, TRUE);
-                                       if (s[0] != IS_CLIPPED)
+                                       if (ED_view3d_project_short_object(vc->ar, bp->vec, s,
+                                                                          V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+                                       {
                                                func(userData, nu, bp, NULL, -1, s[0], s[1]);
+                                       }
                                }
                        }
                }
@@ -6622,7 +6532,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        /* which wire color */
        if ((dflag & DRAW_CONSTCOLOR) == 0) {
 
-               ED_view3d_project_short(ar, ob->obmat[3], &base->sx);
+               ED_view3d_project_base(ar, base);
 
                draw_object_wire_color(scene, base, _ob_wire_col, warning_recursive);
                ob_wire_col = _ob_wire_col;
index a2ad54cb92e2cfcb0c5f26cd3507a06a28d7dbc8..b31b932d71f1b62fa4d1e21ea6000532c1562115 100644 (file)
@@ -371,7 +371,7 @@ static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short move
 
        for (base = vc->scene->base.first; base; base = base->next) {
                if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */
-                       ED_view3d_project_short(vc->ar, base->object->obmat[3], &base->sx);
+                       ED_view3d_project_base(vc->ar, base);
                        if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
                                
                                if (select) ED_base_object_select(base, BA_SELECT);
@@ -577,10 +577,14 @@ static void do_lasso_select_armature(ViewContext *vc, int mcords[][2], short mov
        
        for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
                if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) {
+
+                       /* XXX, TODO, use ED_view3d_project_short_object here */
+                       sco1[0] = sco2[0] = IS_CLIPPED;
+
                        mul_v3_m4v3(vec, vc->obedit->obmat, ebone->head);
-                       ED_view3d_project_short(vc->ar, vec, sco1);
+                       ED_view3d_project_short_global(vc->ar, vec, sco1, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN);
                        mul_v3_m4v3(vec, vc->obedit->obmat, ebone->tail);
-                       ED_view3d_project_short(vc->ar, vec, sco2);
+                       ED_view3d_project_short_global(vc->ar, vec, sco2, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN);
                        
                        didpoint = 0;
                        if (BLI_lasso_is_point_inside(mcords, moves, sco1[0], sco1[1], IS_CLIPPED)) {
@@ -631,12 +635,16 @@ static void do_lasso_select_meta(ViewContext *vc, int mcords[][2], short moves,
 
        for (ml = mb->editelems->first; ml; ml = ml->next) {
                
-               mul_v3_m4v3(vec, vc->obedit->obmat, &ml->x);
-               ED_view3d_project_short(vc->ar, vec, sco);
+               /* TODO, use ED_view3d_project_short_object */
 
-               if (BLI_lasso_is_point_inside(mcords, moves, sco[0], sco[1], IS_CLIPPED)) {
-                       if (select) ml->flag |= SELECT;
-                       else ml->flag &= ~SELECT;
+               mul_v3_m4v3(vec, vc->obedit->obmat, &ml->x);
+               if (ED_view3d_project_short_global(vc->ar, vec, sco,
+                                                  V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_SUCCESS)
+               {
+                       if (BLI_lasso_is_point_inside(mcords, moves, sco[0], sco[1], INT_MAX)) {
+                               if (select) ml->flag |= SELECT;
+                               else ml->flag &= ~SELECT;
+                       }
                }
        }
 }
@@ -1059,8 +1067,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
                }
                else {
                        int temp, dist = 15;
-
-                       ED_view3d_project_short(vc->ar, base->object->obmat[3], &base->sx);
+                       ED_view3d_project_base(vc->ar, base);
                        
                        temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]);
                        if (temp < dist)
@@ -1341,8 +1348,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
                        base = startbase;
                        while (base) {
                                if (BASE_SELECTABLE(v3d, base)) {
-                                       ED_view3d_project_short(ar, base->object->obmat[3], &base->sx);
-                                       
+                                       ED_view3d_project_base(ar, base);
                                        temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]);
                                        if (base == BASACT) temp += 10;
                                        if (temp < dist) {
@@ -2375,14 +2381,17 @@ static void pose_circle_select(ViewContext *vc, int select, const int mval[2], f
                /* skip invisible bones */
                if (PBONE_VISIBLE(arm, pchan->bone) == 0)
                        continue;
+
+               /* XXX, TODO, center check does not check for clipping! */
+               /* XXX, TODO, use ED_view3d_project_short_object here */
                
                /* project head location to screenspace */
                mul_v3_m4v3(vec, vc->obact->obmat, pchan->pose_head);
-               ED_view3d_project_short(vc->ar, vec, sco1);
+               ED_view3d_project_short_global(vc->ar, vec, sco1, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN);
                
                /* project tail location to screenspace */
                mul_v3_m4v3(vec, vc->obact->obmat, pchan->pose_tail);
-               ED_view3d_project_short(vc->ar, vec, sco2);
+               ED_view3d_project_short_global(vc->ar, vec, sco2, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN);
                
                /* check if the head and/or tail is in the circle 
                 *      - the call to check also does the selection already
@@ -2444,13 +2453,16 @@ static void armature_circle_select(ViewContext *vc, int select, const int mval[2
                short sco1[2], sco2[2], didpoint = 0;
                float vec[3];
                
+               /* XXX, TODO, center check does not check for clipping! */
+               /* XXX, TODO, use ED_view3d_project_short_object here */
+
                /* project head location to screenspace */
                mul_v3_m4v3(vec, vc->obedit->obmat, ebone->head);
-               ED_view3d_project_short(vc->ar, vec, sco1);
+               ED_view3d_project_short_global(vc->ar, vec, sco1, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN);
                
                /* project tail location to screenspace */
                mul_v3_m4v3(vec, vc->obedit->obmat, ebone->tail);
-               ED_view3d_project_short(vc->ar, vec, sco2);
+               ED_view3d_project_short_global(vc->ar, vec, sco2, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN);
                
                /* check if the head and/or tail is in the circle 
                 *      - the call to check also does the selection already
@@ -2556,7 +2568,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
                select = select ? BA_SELECT : BA_DESELECT;
                for (base = FIRSTBASE; base; base = base->next) {
                        if (BASE_SELECTABLE(v3d, base)) {
-                               ED_view3d_project_short(ar, base->object->obmat[3], &base->sx);
+                               ED_view3d_project_base(ar, base);
                                if (base->sx != IS_CLIPPED) {
                                        int dx = base->sx - x;
                                        int dy = base->sy - y;
index ff518e6ce5bfa1c2da91aaab76308ee15684cb10..2ed8048fee4f7ed6a41d126a5c91767626f2c625 100644 (file)
@@ -858,6 +858,19 @@ void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3
        }
 }
 
+eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base)
+{
+       eV3DProjStatus ret = ED_view3d_project_short_global(ar, base->object->obmat[3], &base->sx,
+                                                           V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN);
+
+       if (ret != V3D_PROJ_RET_SUCCESS) {
+               base->sx = IS_CLIPPED;
+               base->sy = 0;
+       }
+
+       return ret;
+}
+
 int ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[][4], BoundBox *bb)
 {
        /* return 1: draw */
@@ -893,36 +906,81 @@ int ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[][4], BoundBox *bb)
        return 0;
 }
 
-void ED_view3d_project_short(ARegion *ar, const float co[3], short r_co[2])   /* clips */
+/* perspmat is typically...
+ * - 'rv3d->perspmat',   is_local == FALSE
+ * - 'rv3d->perspmatob', is_local == TRUE
+ */
+static eV3DProjStatus ed_view3d_project__internal(ARegion *ar,
+                                                  float perspmat[4][4], const int is_local,  /* normally hidden */
+                                                  const float co[3], float r_co[2], eV3DProjTest flag)
 {
-       RegionView3D *rv3d = ar->regiondata;
        float fx, fy, vec4[4];
-       
-       r_co[0] = IS_CLIPPED;
-       
-       if (rv3d->rflag & RV3D_CLIPPING) {
-               if (ED_view3d_clipping_test(rv3d, co, FALSE)) {
-                       return;
+
+       if (flag & V3D_PROJ_TEST_CLIP_BB) {
+               RegionView3D *rv3d = ar->regiondata;
+               if (rv3d->rflag & RV3D_CLIPPING) {
+                       if (ED_view3d_clipping_test(rv3d, co, is_local)) {
+                               return V3D_PROJ_RET_CLIP_BB;
+                       }
                }
        }
-       
+
        copy_v3_v3(vec4, co);
        vec4[3] = 1.0;
-       mul_m4_v4(rv3d->persmat, vec4);
-       
+       mul_m4_v4(perspmat, vec4);
+
        if (vec4[3] > (float)BL_NEAR_CLIP) {
-               fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
-               
-               if (fx > 0 && fx < ar->winx) {
-                       
-                       fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
-                       
-                       if (fy > 0.0f && fy < (float)ar->winy) {
+               fx = ((float)ar->winx / 2.0f) * (1.0f + vec4[0] / vec4[3]);
+               if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0 && fx < ar->winx)) {
+                       fy = ((float)ar->winy / 2.0f) * (1.0f + vec4[1] / vec4[3]);
+                       if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) {
                                r_co[0] = (short)floor(fx);
                                r_co[1] = (short)floor(fy);
                        }
+                       else {
+                               return V3D_PROJ_RET_CLIP_WIN;
+                       }
                }
+               else {
+                       return V3D_PROJ_RET_CLIP_WIN;
+               }
+       }
+       else {
+               return V3D_PROJ_RET_CLIP_NEAR;
        }
+
+       return V3D_PROJ_RET_SUCCESS;
+}
+
+eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], const int is_local,
+                                          const float co[3], short r_co[2], eV3DProjTest flag)
+{
+       float tvec[2];
+       eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag);
+       if (ret == V3D_PROJ_RET_SUCCESS) {
+               if ((tvec[0] > -32700.0 && tvec[0] < 32700.0f) &&
+                   (tvec[1] > -32700.0 && tvec[1] < 32700.0f))
+               {
+                       r_co[0] = (short)floor(tvec[0]);
+                       r_co[1] = (short)floor(tvec[1]);
+               }
+               else {
+                       return V3D_PROJ_RET_OVERFLOW;
+               }
+       }
+       return ret;
+}
+
+eV3DProjStatus ED_view3d_project_short_global(ARegion *ar, const float co[3], short r_co[2], eV3DProjTest flag)
+{
+       RegionView3D *rv3d = ar->regiondata;
+       return ED_view3d_project_short_ex(ar, rv3d->persmat, FALSE, co, r_co, flag);
+}
+/* object space, use ED_view3d_init_mats_rv3d before calling */
+eV3DProjStatus ED_view3d_project_short_object(ARegion *ar, const float co[3], short r_co[2], eV3DProjTest flag)
+{
+       RegionView3D *rv3d = ar->regiondata;
+       return ED_view3d_project_short_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag);
 }
 
 void ED_view3d_project_int(ARegion *ar, const float co[3], int r_co[2])
@@ -973,32 +1031,6 @@ void ED_view3d_project_int_noclip(ARegion *ar, const float co[3], int r_co[2])
        }
 }
 
-void ED_view3d_project_short_noclip(ARegion *ar, const float co[3], short r_co[2])
-{
-       RegionView3D *rv3d = ar->regiondata;
-       float fx, fy, vec4[4];
-       
-       copy_v3_v3(vec4, co);
-       vec4[3] = 1.0;
-       r_co[0] = IS_CLIPPED;
-       
-       mul_m4_v4(rv3d->persmat, vec4);
-       
-       if (vec4[3] > (float)BL_NEAR_CLIP) {
-               fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
-               
-               if (fx > -32700 && fx < 32700) {
-                       
-                       fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
-                       
-                       if (fy > -32700.0f && fy < 32700.0f) {
-                               r_co[0] = (short)floor(fx);
-                               r_co[1] = (short)floor(fy);
-                       }
-               }
-       }
-}
-
 void ED_view3d_project_float(ARegion *ar, const float co[3], float r_co[2])
 {
        RegionView3D *rv3d = ar->regiondata;