diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-10-04 20:46:15 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-10-04 20:46:15 +0400 |
commit | 709903c6bba4dca12a6f367000f99a83da2af034 (patch) | |
tree | d6b84b215f9b84eb4b6ac4a828af59683c03588e /source/blender/editors | |
parent | 794520a86a83a9eea230563e805480016c0479f0 (diff) |
refactor ED_view3d_project_short & ED_view3d_project_short_noclip,
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.
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/armature/editarmature_sketch.c | 103 | ||||
-rw-r--r-- | source/blender/editors/include/ED_view3d.h | 30 | ||||
-rw-r--r-- | source/blender/editors/physics/particle_edit.c | 7 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 212 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.c | 46 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_view.c | 120 |
6 files changed, 254 insertions, 264 deletions
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index 8d8fa730360..b72fad08d1f 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -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; + } } } } diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 9536dd76581..ca5d8691df7 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -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); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index ea6f9d4cebb..6d3f4b38583 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -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); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 7badca304c4..e368f06a35f 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -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; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index a2ad54cb92e..b31b932d71f 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -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; diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index ff518e6ce5b..2ed8048fee4 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -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; |