[#19930] Nurb CV select is failing because of view clipping
authorCampbell Barton <ideasman42@gmail.com>
Sat, 21 Nov 2009 16:44:05 +0000 (16:44 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 21 Nov 2009 16:44:05 +0000 (16:44 +0000)
- the clipping test function was using the rv3d->viewmatob where it needed to use the object matrix.
- added a local clipping member to rv3d, the clipping planes in object-space, avoids many matrix multiplications when testing verts or clipping pixels when projection painting.

source/blender/editors/include/ED_view3d.h
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/makesdna/DNA_view3d_types.h

index 2ec9ddf6c5280f3f9df2c59804389e4353f46a88..ecd2d69b7fbcf14ba9f80bfe574673ef0b93c9b4 100644 (file)
@@ -104,7 +104,8 @@ void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData,
 void nurbs_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt, int beztindex, int x, int y), void *userData);
 void lattice_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BPoint *bp, int x, int y), void *userData);
 
-int view3d_test_clipping(struct RegionView3D *rv3d, float *vec);
+void ED_view3d_local_clipping(struct RegionView3D *rv3d, float mat[][4]);
+int view3d_test_clipping(struct RegionView3D *rv3d, float *vec, int local);
 void view3d_align_axis_to_vector(struct View3D *v3d, struct RegionView3D *rv3d, int axisidx, float vec[3]);
 
 void drawcircball(int mode, float *cent, float rad, float tmat[][4]);
@@ -143,5 +144,7 @@ int ED_view3d_context_activate(struct bContext *C);
 void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
        int winx, int winy, float viewmat[][4], float winmat[][4]);
 
+void view3d_clipping_local(struct RegionView3D *rv3d, float mat[][4]);
+
 #endif /* ED_VIEW3D_H */
 
index a0df4cb1211e0d914bd80d988c3a1fbbdbc84421..e14dedf6002f92f590c0c1cc5b11cabbbf707bfe 100644 (file)
@@ -482,14 +482,17 @@ static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, in
        struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } *data = userData;
        float v1[2], v2[2];
        int distance;
-               
+
+       ED_view3d_local_clipping(data->vc.rv3d, data->vc.obedit->obmat); /* for local clipping lookups */
+
        v1[0] = x0;
        v1[1] = y0;
        v2[0] = x1;
        v2[1] = y1;
-               
+
        distance= dist_to_line_segment_v2(data->mval, v1, v2);
-               
+
+
        if(eed->f & SELECT) distance+=5;
        if(distance < data->dist) {
                if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
@@ -499,9 +502,8 @@ static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, in
                        vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
                        vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
                        vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
-                       mul_m4_v3(data->vc.obedit->obmat, vec);
 
-                       if(view3d_test_clipping(data->vc.rv3d, vec)==0) {
+                       if(view3d_test_clipping(data->vc.rv3d, vec, 1)==0) {
                                data->dist = distance;
                                data->closest = eed;
                        }
index ef036da6d7b0cefd962eaed9cd452df8a1befecf..55f7a6a23b9395cd763a6557562212d42cf1c315 100644 (file)
@@ -861,8 +861,7 @@ static int project_paint_occlude_ptv_clip(
        if (side)       interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
        else            interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
        
-       mul_m4_v3(ps->ob->obmat, wco);
-       if(!view3d_test_clipping(ps->rv3d, wco)) {
+       if(!view3d_test_clipping(ps->rv3d, wco, 1)) {
                return 1;
        }
        
@@ -2446,8 +2445,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
                                                /* a pitty we need to get the worldspace pixel location here */
                                                if(ps->rv3d->rflag & RV3D_CLIPPING) {
                                                        interp_v3_v3v3v3(wco, ps->dm_mvert[ (*(&mf->v1 + i1)) ].co, ps->dm_mvert[ (*(&mf->v1 + i2)) ].co, ps->dm_mvert[ (*(&mf->v1 + i3)) ].co, w);
-                                                       mul_m4_v3(ps->ob->obmat, wco);
-                                                       if(view3d_test_clipping(ps->rv3d, wco)) {
+                                                       if(view3d_test_clipping(ps->rv3d, wco, 1)) {
                                                                continue; /* Watch out that no code below this needs to run */
                                                        }
                                                }
@@ -2663,9 +2661,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
                                                                                        if(ps->rv3d->rflag & RV3D_CLIPPING) {
                                                                                                if (side)       interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
                                                                                                else            interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
-                                                                                               
-                                                                                               mul_m4_v3(ps->ob->obmat, wco);
-                                                                                               if(view3d_test_clipping(ps->rv3d, wco)) {
+
+                                                                                               if(view3d_test_clipping(ps->rv3d, wco, 1)) {
                                                                                                        continue; /* Watch out that no code below this needs to run */
                                                                                                }
                                                                                        }
@@ -2934,6 +2931,8 @@ static void project_paint_begin(ProjPaintState *ps)
        
        /* ---- end defines ---- */
        
+       ED_view3d_local_clipping(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
+
        /* paint onto the derived mesh */
        
        /* Workaround for subsurf selection, try the display mesh first */
index 23cd6f0c7d9846e53c94a5a35c0a010c39dc472b..a0c13b6d6eebd0ce908575a7f48f865990063582 100644 (file)
@@ -142,7 +142,7 @@ static void draw_empty_cone(float size);
 /* ************* only use while object drawing **************
  * or after running ED_view3d_init_mats_rv3d
  * */
-static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
+static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
 {
        RegionView3D *rv3d= ar->regiondata;
        float fx, fy, vec4[4];
@@ -151,9 +151,7 @@ static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
        
        /* clipplanes in eye space */
        if(rv3d->rflag & RV3D_CLIPPING) {
-               VECCOPY(vec4, vec);
-               mul_m4_v3(rv3d->viewmatob, vec4);
-               if(view3d_test_clipping(rv3d, vec4))
+               if(view3d_test_clipping(rv3d, vec, local))
                        return;
        }
        
@@ -545,7 +543,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa
        for(vos= strings->first; vos; vos= vos->next) {
                if(mat)
                        mul_m4_v3(mat, vos->vec);
-               view3d_project_short_clip(ar, vos->vec, vos->mval);
+               view3d_project_short_clip(ar, vos->vec, vos->mval, 0);
                if(vos->mval[0]!=IS_CLIPPED)
                        tot++;
        }
@@ -1207,9 +1205,11 @@ void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPo
        int i, N = lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
        short s[2] = {IS_CLIPPED, 0};
 
+       ED_view3d_local_clipping(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);
+                       view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
                        if (s[0] != IS_CLIPPED)
                                func(userData, bp, s[0], s[1]);
                }
@@ -1314,7 +1314,7 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co
                short s[2]= {IS_CLIPPED, 0};
 
                if (data->clipVerts) {
-                       view3d_project_short_clip(data->vc.ar, co, s);
+                       view3d_project_short_clip(data->vc.ar, co, s, 1);
                } else {
                        view3d_project_short_noclip(data->vc.ar, co, s);
                }
@@ -1334,6 +1334,9 @@ void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVe
        data.userData = userData;
        data.clipVerts = clipVerts;
 
+       if(clipVerts)
+               ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+
        EM_init_index_arrays(vc->em, 1, 0, 0);
        dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
        EM_free_index_arrays();
@@ -1349,8 +1352,8 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0
 
        if (eed->h==0) {
                if (data->clipVerts==1) {
-                       view3d_project_short_clip(data->vc.ar, v0co, s[0]);
-                       view3d_project_short_clip(data->vc.ar, v1co, s[1]);
+                       view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
+                       view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
                } else {
                        view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
                        view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
@@ -1376,6 +1379,9 @@ void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEd
        data.userData = userData;
        data.clipVerts = clipVerts;
 
+       if(clipVerts)
+               ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+
        EM_init_index_arrays(vc->em, 0, 1, 0);
        dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
        EM_free_index_arrays();
@@ -1390,7 +1396,7 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *ce
        short s[2];
 
        if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
-               view3d_project_short_clip(data->vc.ar, cent, s);
+               view3d_project_short_clip(data->vc.ar, cent, s, 1);
 
                data->func(data->userData, efa, s[0], s[1], index);
        }
@@ -1405,6 +1411,9 @@ void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFa
        data.func = func;
        data.userData = userData;
 
+       //if(clipVerts)
+       ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+
        EM_init_index_arrays(vc->em, 0, 0, 1);
        dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
        EM_free_index_arrays();
@@ -1419,6 +1428,8 @@ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb
        Nurb *nu;
        int i;
 
+       ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+
        for (nu= cu->editnurb->first; nu; nu=nu->next) {
                if(nu->type == CU_BEZIER) {
                        for (i=0; i<nu->pntsu; i++) {
@@ -1427,17 +1438,17 @@ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb
                                if(bezt->hide==0) {
                                        
                                        if(cu->drawflag & CU_HIDE_HANDLES) {
-                                               view3d_project_short_clip(vc->ar, bezt->vec[1], s);
+                                               view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
                                                if (s[0] != IS_CLIPPED)
                                                        func(userData, nu, NULL, bezt, 1, s[0], s[1]);
                                        } else {
-                                               view3d_project_short_clip(vc->ar, bezt->vec[0], s);
+                                               view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
                                                if (s[0] != IS_CLIPPED)
                                                        func(userData, nu, NULL, bezt, 0, s[0], s[1]);
-                                               view3d_project_short_clip(vc->ar, bezt->vec[1], s);
+                                               view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
                                                if (s[0] != IS_CLIPPED)
                                                        func(userData, nu, NULL, bezt, 1, s[0], s[1]);
-                                               view3d_project_short_clip(vc->ar, bezt->vec[2], s);
+                                               view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
                                                if (s[0] != IS_CLIPPED)
                                                        func(userData, nu, NULL, bezt, 2, s[0], s[1]);
                                        }
@@ -1449,7 +1460,7 @@ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb
                                BPoint *bp = &nu->bp[i];
 
                                if(bp->hide==0) {
-                                       view3d_project_short_clip(vc->ar, bp->vec, s);
+                                       view3d_project_short_clip(vc->ar, bp->vec, s, 1);
                                        if (s[0] != IS_CLIPPED)
                                                func(userData, nu, bp, NULL, -1, s[0], s[1]);
                                }
index ebd1ab6dbfff7421f8b8d2679fb9bbf55686f3f7..d11eee466ed3925ad0c6ee61c7991f6eb8cf2c3b 100644 (file)
@@ -175,6 +175,9 @@ void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
        /* local viewmat and persmat, to calculate projections */
        wmGetMatrix(rv3d->viewmatob);
        wmGetSingleMatrix(rv3d->persmatob);
+
+       /* initializes object space clipping, speeds up clip tests */
+       ED_view3d_local_clipping(rv3d, ob->obmat);
 }
 
 /* ******************** default callbacks for view3d space ***************** */
index 8aa63518e96b196c576251a57bc8124ec4a0a034..ec8fc869d72a7dd2bd3c73d4604fd0afd8921d56 100644 (file)
@@ -193,22 +193,27 @@ void view3d_clr_clipping(void)
        }
 }
 
-int view3d_test_clipping(RegionView3D *rv3d, float *vec)
+static test_clipping(float *vec, float clip[][4])
 {
-       /* vec in world coordinates, returns 1 if clipped */
        float view[3];
-       
        VECCOPY(view, vec);
        
-       if(0.0f < rv3d->clip[0][3] + INPR(view, rv3d->clip[0]))
-               if(0.0f < rv3d->clip[1][3] + INPR(view, rv3d->clip[1]))
-                       if(0.0f < rv3d->clip[2][3] + INPR(view, rv3d->clip[2]))
-                               if(0.0f < rv3d->clip[3][3] + INPR(view, rv3d->clip[3]))
+       if(0.0f < clip[0][3] + INPR(view, clip[0]))
+               if(0.0f < clip[1][3] + INPR(view, clip[1]))
+                       if(0.0f < clip[2][3] + INPR(view, clip[2]))
+                               if(0.0f < clip[3][3] + INPR(view, clip[3]))
                                        return 0;
-       
+
        return 1;
 }
 
+/* for 'local' ED_view3d_local_clipping must run first
+ * then all comparisons can be done in localspace */
+int view3d_test_clipping(RegionView3D *rv3d, float *vec, int local)
+{
+       return test_clipping(vec, local ? rv3d->clip_local : rv3d->clip);
+}
+
 /* ********* end custom clipping *********** */
 
 
index a545d200e878a01cf6619e4d171fed89e556ef10..8597f0be88d70e958c10f8a01d5ca86e66dc5017 100644 (file)
@@ -1829,6 +1829,42 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
 
 /* ********************* set clipping operator ****************** */
 
+static void calc_clipping_plane(float clip[6][4], BoundBox *clipbb)
+{
+       int val;
+
+       for(val=0; val<4; val++) {
+
+               normal_tri_v3( clip[val],clipbb->vec[val], clipbb->vec[val==3?0:val+1], clipbb->vec[val+4]);
+
+               clip[val][3]=
+                       - clip[val][0]*clipbb->vec[val][0]
+                       - clip[val][1]*clipbb->vec[val][1]
+                       - clip[val][2]*clipbb->vec[val][2];
+       }
+}
+
+static void calc_local_clipping(float clip_local[][4], BoundBox *clipbb, float mat[][4])
+{
+       BoundBox clipbb_local;
+       float imat[4][4];
+       int i;
+
+       invert_m4_m4(imat, mat);
+
+       for(i=0; i<8; i++) {
+               mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]);
+       }
+
+       calc_clipping_plane(clip_local, &clipbb_local);
+}
+
+void ED_view3d_local_clipping(RegionView3D *rv3d, float mat[][4])
+{
+       if(rv3d->rflag & RV3D_CLIPPING)
+               calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat);
+}
+
 static int view3d_clipping_exec(bContext *C, wmOperator *op)
 {
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
@@ -1879,14 +1915,8 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
        }
 
        /* then plane equations */
-       for(val=0; val<4; val++) {
+       calc_clipping_plane(rv3d->clip, rv3d->clipbb);
 
-               normal_tri_v3( rv3d->clip[val],rv3d->clipbb->vec[val], rv3d->clipbb->vec[val==3?0:val+1], rv3d->clipbb->vec[val+4]);
-
-               rv3d->clip[val][3]= - rv3d->clip[val][0]*rv3d->clipbb->vec[val][0]
-                       - rv3d->clip[val][1]*rv3d->clipbb->vec[val][1]
-                       - rv3d->clip[val][2]*rv3d->clipbb->vec[val][2];
-       }
        return OPERATOR_FINISHED;
 }
 
index ded9b44afd491517f9680ad3346a11548de8e00c..82b5730daa28191566a17021d8d74c4ae70ec728 100644 (file)
@@ -680,7 +680,7 @@ void project_short(ARegion *ar, float *vec, short *adr)     /* clips */
        adr[0]= IS_CLIPPED;
        
        if(rv3d->rflag & RV3D_CLIPPING) {
-               if(view3d_test_clipping(rv3d, vec))
+               if(view3d_test_clipping(rv3d, vec, 0))
                        return;
        }
        
index 422c56fe4c1218fac0b367ccacedfd2fbaf06986..74d9fa59e5051caa84e37cf3a09b20222909a856 100644 (file)
@@ -97,6 +97,7 @@ typedef struct RegionView3D {
        
        /* user defined clipping planes */
        float clip[6][4];
+       float clip_local[6][4]; /* clip in object space, means we can test for clipping in editmode without first going into worldspace */
        struct BoundBox *clipbb;        
        
        struct bGPdata *gpd;            /* Grease-Pencil Data (annotation layers) */