diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 928820f91fd..754b30b4afa 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3018,6 +3018,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc) v3d->bgpic= newdataadr(fd, v3d->bgpic); v3d->localvd= newdataadr(fd, v3d->localvd); v3d->afterdraw.first= v3d->afterdraw.last= NULL; + v3d->clipbb= newdataadr(fd, v3d->clipbb); } else if (sl->spacetype==SPACE_OOPS) { SpaceOops *soops= (SpaceOops*) sl; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 920d4ed634a..fc281a78f63 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1207,6 +1207,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "View3D", 1, v3d); if(v3d->bgpic) writestruct(wd, DATA, "BGpic", 1, v3d->bgpic); if(v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd); + if(v3d->clipbb) writestruct(wd, DATA, "BoundBox", 1, v3d->clipbb); } else if(sl->spacetype==SPACE_IPO) { writestruct(wd, DATA, "SpaceIpo", 1, sl); diff --git a/source/blender/include/BIF_editview.h b/source/blender/include/BIF_editview.h index 345f21cdb9e..ef4c417188f 100644 --- a/source/blender/include/BIF_editview.h +++ b/source/blender/include/BIF_editview.h @@ -36,6 +36,7 @@ struct Base; struct Object; struct Camera; +struct View3D; void arrows_move_cursor(unsigned short event); void borderselect(void); @@ -52,5 +53,7 @@ void set_active_base(struct Base *base); void set_active_object(struct Object *ob); void set_render_border(void); +void view3d_edit_clipping(struct View3D *v3d); + #endif diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index 946018a198e..b0e40699f42 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -57,6 +57,10 @@ void calc_viewborder(struct View3D *v3d, struct rcti *viewborder_r); void view3d_set_1_to_1_viewborder(struct View3D *v3d); void timestr(double time, char *str); +int view3d_test_clipping(struct View3D *v3d, float *vec); +void view3d_set_clipping(struct View3D *v3d); +void view3d_clr_clipping(void); + void sumo_callback(void *obp); void init_anim_sumo(void); void update_anim_sumo(void); diff --git a/source/blender/include/BSE_view.h b/source/blender/include/BSE_view.h index 94f5266c4e3..e241f92143b 100644 --- a/source/blender/include/BSE_view.h +++ b/source/blender/include/BSE_view.h @@ -46,9 +46,11 @@ struct ScrArea; void persp_general(int a); void persp(int a); -void view3d_get_object_project_mat(struct ScrArea *area, struct Object *ob, float mat[4][4]); +/* note, the define below is still used for shorts, to calc distances... */ +#define IS_CLIPPED 12000 +void view3d_get_object_project_mat(struct ScrArea *area, struct Object *ob, float pmat[4][4], float vmat[4][4]); void view3d_project_float(struct ScrArea *area, float *vec, float *adr, float mat[4][4]); -void view3d_project_short(struct ScrArea *area, float *vec, short *adr, float mat[4][4]); +void view3d_project_short_clip(struct ScrArea *area, float *vec, short *adr, float projmat[4][4], float viewmat[4][4]); void view3d_project_short_noclip(struct ScrArea *area, float *vec, short *adr, float mat[4][4]); void initgrabz(float x, float y, float z); @@ -57,6 +59,7 @@ void project_short(float *vec, short *adr); void project_short_noclip(float *vec, short *adr); void project_int(float *vec, int *adr); void project_float(float *vec, float *adr); + int boundbox_clip(float obmat[][4], struct BoundBox *bb); void fdrawline(float x1, float y1, float x2, float y2); void fdrawbox(float x1, float y1, float x2, float y2); diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index c42703b4b17..871d0e3f536 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -60,8 +60,6 @@ typedef struct bDeformGroup { char name[32]; } bDeformGroup; -# -# typedef struct BoundBox { float vec[8][3]; } BoundBox; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 6bd0a91fbdf..f0fe608035a 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -39,6 +39,7 @@ struct Image; struct Tex; struct SpaceLink; struct Base; +struct BoundBox; /* This is needed to not let VC choke on near and far... old * proprietary MS extensions... */ @@ -123,13 +124,17 @@ typedef struct View3D { short twtype, twmode, twflag, twpad; float twmat[4][4]; + /* user defined clipping planes */ + float clip[4][4]; + struct BoundBox *clipbb; + /* afterdraw, for xray & transparent */ struct ListBase afterdraw; /* drawflags, denoting state */ short zbuf, transp, xray, pad2; } View3D; -/* View3D->flag */ +/* View3D->flag (short) */ #define V3D_MODE (16+32+64+128+256+512) #define V3D_DISPIMAGE 1 #define V3D_DISPBGPIC 2 @@ -145,6 +150,7 @@ typedef struct View3D { #define V3D_SELECT_OUTLINE 2048 #define V3D_ZBUF_SELECT 4096 #define V3D_GLOBAL_STATS 8192 +#define V3D_CLIPPING 16384 /* View3D->around */ #define V3D_CENTRE 0 diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 6eed7ac91e0..eb264cf2e17 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -82,6 +82,7 @@ #include "BIF_screen.h" #include "BSE_trans_types.h" +#include "BSE_view.h" /* Modules used */ #include "mydevice.h" @@ -225,7 +226,7 @@ void uvco_to_areaco(float *vec, short *mval) { float x, y; - mval[0]= 3200; + mval[0]= IS_CLIPPED; x= (vec[0] - G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin); y= (vec[1] - G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin); @@ -242,7 +243,7 @@ void uvco_to_areaco_noclip(float *vec, short *mval) { float x, y; - mval[0]= 3200; + mval[0]= IS_CLIPPED; x= (vec[0] - G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin); y= (vec[1] - G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin); diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 0310cb477d9..26941b5d71d 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -337,7 +337,7 @@ void ipoco_to_areaco(View2D *v2d, float *vec, short *mval) { float x, y; - mval[0]= 3200; + mval[0]= IS_CLIPPED; x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin); y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin); @@ -639,7 +639,7 @@ static void draw_solution_line(View2D *v2d, float h) vec[0]= v2d->cur.xmin; vec[1]= h; ipoco_to_areaco(v2d, vec, mval); - if(mval[0]!=3200) { + if(mval[0]!=IS_CLIPPED) { glBegin(GL_LINES); glVertex2f(v2d->vert.xmin, mval[1]); glVertex2f(v2d->vert.xmax, mval[1]); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 77419925b30..7cc1443ce44 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -279,9 +279,14 @@ void init_draw_rects(void) static void draw_icon_centered(float *pos, unsigned int *rect, int rectsize) { float hsize= (float) rectsize/2.0f; +// float vals[4]; GLubyte dummy= 0; glRasterPos3fv(pos); +// glGetFloatv(GL_CURRENT_RASTER_POSITION_VALID, vals); +// printf("rasterpos %f\n", vals[0]); +// glGetFloatv(GL_CURRENT_RASTER_POSITION, vals); +// printf("pos %f %f %f %f\n", vals[0], vals[1], vals[2], vals[3]); /* use bitmap to shift rasterpos in pixels */ glBitmap(0, 0, 0.0, 0.0, -hsize, -hsize, &dummy); @@ -824,14 +829,14 @@ void lattice_foreachScreenVert(void (*func)(void *userData, BPoint *bp, int x, i DispList *dl = find_displist(&G.obedit->disp, DL_VERTS); float *co = dl?dl->verts:NULL; BPoint *bp = editLatt->def; - float mat[4][4]; + float pmat[4][4], vmat[4][4]; short s[2]; - view3d_get_object_project_mat(curarea, G.obedit, mat); + view3d_get_object_project_mat(curarea, G.obedit, pmat, vmat); for (i=0; ihide==0) { - view3d_project_short(curarea, dl?co:bp->vec, s, mat); + view3d_project_short_clip(curarea, dl?co:bp->vec, s, pmat, vmat); func(userData, bp, s[0], s[1]); } } @@ -898,15 +903,15 @@ static void drawlattice(Object *ob) static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { - struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float mat[4][4]; } *data = userData; + struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; EditVert *eve = EM_get_vert_for_index(index); short s[2]; if (eve->h==0) { if (data->clipVerts) { - view3d_project_short(curarea, co, s, data->mat); + view3d_project_short_clip(curarea, co, s, data->pmat, data->vmat); } else { - view3d_project_short_noclip(curarea, co, s, data->mat); + view3d_project_short_noclip(curarea, co, s, data->pmat); } data->func(data->userData, eve, s[0], s[1], index); @@ -914,7 +919,7 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co } void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts) { - struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float mat[4][4]; } data; + struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data; int dmNeedsFree; DerivedMesh *dm = editmesh_get_derived_cage(&dmNeedsFree); @@ -922,7 +927,7 @@ void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, i data.userData = userData; data.clipVerts = clipVerts; - view3d_get_object_project_mat(curarea, G.obedit, data.mat); + view3d_get_object_project_mat(curarea, G.obedit, data.pmat, data.vmat); EM_init_index_arrays(1, 0, 0); dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data); @@ -935,17 +940,17 @@ void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, i static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co) { - struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float mat[4][4]; } *data = userData; + struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; EditEdge *eed = EM_get_edge_for_index(index); short s[2][2]; if (eed->h==0) { if (data->clipVerts==1) { - view3d_project_short(curarea, v0co, s[0], data->mat); - view3d_project_short(curarea, v1co, s[1], data->mat); + view3d_project_short_clip(curarea, v0co, s[0], data->pmat, data->vmat); + view3d_project_short_clip(curarea, v1co, s[1], data->pmat, data->vmat); } else { - view3d_project_short_noclip(curarea, v0co, s[0], data->mat); - view3d_project_short_noclip(curarea, v1co, s[1], data->mat); + view3d_project_short_noclip(curarea, v0co, s[0], data->pmat); + view3d_project_short_noclip(curarea, v1co, s[1], data->pmat); if (data->clipVerts==2) { if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]winx && s[0][1]winy)) @@ -959,7 +964,7 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0 } void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts) { - struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float mat[4][4]; } data; + struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data; int dmNeedsFree; DerivedMesh *dm = editmesh_get_derived_cage(&dmNeedsFree); @@ -967,7 +972,7 @@ void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, data.userData = userData; data.clipVerts = clipVerts; - view3d_get_object_project_mat(curarea, G.obedit, data.mat); + view3d_get_object_project_mat(curarea, G.obedit, data.pmat, data.vmat); EM_init_index_arrays(0, 1, 0); dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data); @@ -980,26 +985,26 @@ void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no) { - struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float mat[4][4]; } *data = userData; + struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } *data = userData; EditFace *efa = EM_get_face_for_index(index); short s[2]; if (efa && efa->h==0 && efa->fgonf!=EM_FGON) { - view3d_project_short(curarea, cent, s, data->mat); + view3d_project_short_clip(curarea, cent, s, data->pmat, data->vmat); data->func(data->userData, efa, s[0], s[1], index); } } void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData) { - struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float mat[4][4]; } data; + struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } data; int dmNeedsFree; DerivedMesh *dm = editmesh_get_derived_cage(&dmNeedsFree); data.func = func; data.userData = userData; - view3d_get_object_project_mat(curarea, G.obedit, data.mat); + view3d_get_object_project_mat(curarea, G.obedit, data.pmat, data.vmat); EM_init_index_arrays(0, 0, 1); dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data); @@ -1012,12 +1017,12 @@ void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, i void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData) { - float mat[4][4]; + float pmat[4][4], vmat[4][4]; short s[2]; Nurb *nu; int i; - view3d_get_object_project_mat(curarea, G.obedit, mat); + view3d_get_object_project_mat(curarea, G.obedit, pmat, vmat); for (nu= editNurb.first; nu; nu=nu->next) { if((nu->type & 7)==CU_BEZIER) { @@ -1025,11 +1030,11 @@ void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt = &nu->bezt[i]; if(bezt->hide==0) { - view3d_project_short(curarea, bezt->vec[0], s, mat); + view3d_project_short_clip(curarea, bezt->vec[0], s, pmat, vmat); func(userData, nu, NULL, bezt, 0, s[0], s[1]); - view3d_project_short(curarea, bezt->vec[1], s, mat); + view3d_project_short_clip(curarea, bezt->vec[1], s, pmat, vmat); func(userData, nu, NULL, bezt, 1, s[0], s[1]); - view3d_project_short(curarea, bezt->vec[2], s, mat); + view3d_project_short_clip(curarea, bezt->vec[2], s, pmat, vmat); func(userData, nu, NULL, bezt, 2, s[0], s[1]); } } @@ -1039,7 +1044,7 @@ void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BPoint *bp = &nu->bp[i]; if(bp->hide==0) { - view3d_project_short(curarea, bp->vec, s, mat); + view3d_project_short_clip(curarea, bp->vec, s, pmat, vmat); func(userData, nu, bp, NULL, -1, s[0], s[1]); } } @@ -3646,8 +3651,7 @@ void draw_object(Base *base) if(zbufoff) glDisable(GL_DEPTH_TEST); if(warning_recursive) return; - if(base->flag & OB_FROMDUPLI) return; - if(base->flag & OB_RADIO) return; + if(base->flag & (OB_FROMDUPLI|OB_RADIO)) return; if(G.f & G_SIMULATION) return; if((G.f & (G_PICKSEL))==0) { @@ -3754,8 +3758,14 @@ void draw_object_ext(Base *base) glDrawBuffer(GL_FRONT); persp(PERSP_VIEW); + if(G.vd->flag & V3D_CLIPPING) + view3d_set_clipping(G.vd); + draw_object(base); + if(G.vd->flag & V3D_CLIPPING) + view3d_clr_clipping(); + G.f &= ~G_DRAW_EXT; glFlush(); /* reveil frontbuffer drawing */ @@ -3859,7 +3869,6 @@ static int bbs_mesh_solid_EM(DerivedMesh *dm, int facecol) static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmooth_r) { Mesh *me = userData; - MFace *mf = &me->mface[index]; if (!me->tface || !(me->tface[index].flag&TF_HIDE)) { set_framebuffer_index_color(index+1); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 25bd2442880..aee7c588b89 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -765,7 +765,7 @@ static void drawcursor(void) mx = co[0]; my = co[1]; - if(mx!=3200) { + if(mx!=IS_CLIPPED) { setlinestyle(0); cpack(0xFF); circ((float)mx, (float)my, 10.0); @@ -782,6 +782,66 @@ static void drawcursor(void) } } +/* ********* custom clipping *********** */ + +static void view3d_draw_clipping(View3D *v3d) +{ + BoundBox *bb= v3d->clipbb; + + BIF_ThemeColorShade(TH_BACK, -8); + + glBegin(GL_QUADS); + + glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[3]); + glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[1]); + glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[5]); + glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[3]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[6]); + glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[2]); + glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[3]); + + glEnd(); +} + +void view3d_set_clipping(View3D *v3d) +{ + double plane[4]; + int a; + + for(a=0; a<3; a++) { + QUATCOPY(plane, v3d->clip[a]); + glClipPlane(GL_CLIP_PLANE0+a, plane); + glEnable(GL_CLIP_PLANE0+a); + } +} + +void view3d_clr_clipping(void) +{ + int a; + + for(a=0; a<4; a++) { + glDisable(GL_CLIP_PLANE0+a); + } +} + +int view3d_test_clipping(View3D *v3d, float *vec) +{ + /* vec in world coordinates, returns 1 if clipped */ + float view[3]; + + VECCOPY(view, vec); + Mat4MulVecfl(v3d->viewmat, view); + + if(0.0f < v3d->clip[0][3] + INPR(view, v3d->clip[0])) + if(0.0f < v3d->clip[1][3] + INPR(view, v3d->clip[1])) + if(0.0f < v3d->clip[2][3] + INPR(view, v3d->clip[2])) + if(0.0f < v3d->clip[3][3] + INPR(view, v3d->clip[3])) + return 0; + + return 1; +} + +/* ********* end custom clipping *********** */ + static void view3d_get_viewborder_size(View3D *v3d, float size_r[2]) { float winmax= MAX2(v3d->area->winx, v3d->area->winy); @@ -949,6 +1009,9 @@ void backdrawview3d(int test) glDisable(GL_DEPTH_TEST); } + if(G.vd->flag & V3D_CLIPPING) + view3d_set_clipping(G.vd); + G.f |= G_BACKBUFSEL; base= (G.scene->basact); @@ -967,6 +1030,9 @@ void backdrawview3d(int test) glDrawBuffer(GL_BACK); /* we were in aux buffers */ #endif + if(G.vd->flag & V3D_CLIPPING) + view3d_clr_clipping(); + /* it is important to end a view in a transform compatible with buttons */ persp(PERSP_WIN); // set ortho bwin_scalematrix(curarea->win, G.vd->blockscale, G.vd->blockscale, G.vd->blockscale); @@ -1989,11 +2055,8 @@ void drawview3dspace(ScrArea *sa, void *spacedata) Mat4Invert(v3d->viewinv, v3d->viewmat); if(v3d->drawtype > OB_WIRE) { - v3d->zbuf= TRUE; - glEnable(GL_DEPTH_TEST); - if(G.f & G_SIMULATION) { + if(G.f & G_SIMULATION) glClearColor(0.0, 0.0, 0.0, 0.0); - } else { float col[3]; BIF_GetThemeColor3fv(TH_BACK, col); @@ -2013,6 +2076,15 @@ void drawview3dspace(ScrArea *sa, void *spacedata) myloadmatrix(v3d->viewmat); persp(PERSP_STORE); // store correct view for persp(PERSP_VIEW) calls + if(v3d->flag & V3D_CLIPPING) + view3d_draw_clipping(v3d); + + /* set zbuffer after we draw clipping region */ + if(v3d->drawtype > OB_WIRE) { + v3d->zbuf= TRUE; + glEnable(GL_DEPTH_TEST); + } + // needs to be done always, gridview is adjusted in drawgrid() now v3d->gridview= v3d->grid; @@ -2036,6 +2108,9 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } } + if(v3d->flag & V3D_CLIPPING) + view3d_set_clipping(v3d); + /* draw set first */ if(G.scene->set) { @@ -2131,6 +2206,9 @@ void drawview3dspace(ScrArea *sa, void *spacedata) view3d_draw_xray(v3d); // clears zbuffer if it is used! view3d_draw_transp(v3d); + if(v3d->flag & V3D_CLIPPING) + view3d_clr_clipping(); + BIF_draw_manipulator(sa); if(v3d->zbuf) { @@ -2212,6 +2290,9 @@ void drawview3d_render(struct View3D *v3d) glEnable(GL_DEPTH_TEST); } + if(v3d->flag & V3D_CLIPPING) + view3d_set_clipping(v3d); + if (v3d->drawtype==OB_TEXTURE && G.scene->world) { glClearColor(G.scene->world->horr, G.scene->world->horg, G.scene->world->horb, 0.0); } else { @@ -2325,6 +2406,9 @@ void drawview3d_render(struct View3D *v3d) view3d_draw_xray(v3d); // clears zbuffer if it is used! view3d_draw_transp(v3d); + if(v3d->flag & V3D_CLIPPING) + view3d_clr_clipping(); + if(v3d->zbuf) { v3d->zbuf= FALSE; glDisable(GL_DEPTH_TEST); diff --git a/source/blender/src/editlattice.c b/source/blender/src/editlattice.c index 2f7eec5149c..91d56a2ed16 100644 --- a/source/blender/src/editlattice.c +++ b/source/blender/src/editlattice.c @@ -214,7 +214,7 @@ void deselectall_Latt(void) static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, int y) { struct { BPoint *bp; short dist, select, mval[2]; } *data = userData; - short temp = abs(data->mval[0]-x) + abs(data->mval[1]-y); + float temp = abs(data->mval[0]-x) + abs(data->mval[1]-y); if ((bp->f1&1)==data->select) temp += 5; if (tempdist) { diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 11aabb263cd..fb3d8942ee9 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -705,6 +705,10 @@ static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa) glDrawBuffer(GL_FRONT); persp(PERSP_VIEW); + + if(G.vd->flag & V3D_CLIPPING) + view3d_set_clipping(G.vd); + glPushMatrix(); mymultmatrix(G.obedit->obmat); @@ -778,6 +782,9 @@ static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa) glFlush(); glDrawBuffer(GL_BACK); + if(G.vd->flag & V3D_CLIPPING) + view3d_clr_clipping(); + /* signal that frontbuf differs from back */ curarea->win_swap= WIN_FRONT_OK; diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index d51f2940b9c..80814b2f220 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -4293,13 +4293,13 @@ int EdgeSlide(short immediate, float imperc) LinkNode *edgelist = NULL, *vertlist=NULL, *look; GHash *vertgh; SlideVert *tempsv; - float perc = 0, percp = 0,vertdist, projectMat[4][4]; + float perc = 0, percp = 0,vertdist, projectMat[4][4], viewMat[4][4]; int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0; short event, draw=1; short mval[2], mvalo[2]; char str[128]; - view3d_get_object_project_mat(curarea, G.obedit, projectMat); + view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat); mvalo[0] = -1; mvalo[1] = -1; numsel =0; diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index c9e2a09c957..89a6e4f4339 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -826,7 +826,7 @@ void mouse_cursor(void) initgrabz(fp[0], fp[1], fp[2]); - if(mval[0]!=3200) { + if(mval[0]!=IS_CLIPPED) { window_to_3d(dvec, mval[0]-mx, mval[1]-my); VecSubf(fp, fp, dvec); @@ -2001,3 +2001,59 @@ void fly(void) } +void view3d_edit_clipping(View3D *v3d) +{ + + if(v3d->flag & V3D_CLIPPING) { + v3d->flag &= ~V3D_CLIPPING; + scrarea_queue_winredraw(curarea); + if(v3d->clipbb) MEM_freeN(v3d->clipbb); + v3d->clipbb= NULL; + } + else { + rcti rect; + double mvmatrix[16]; + double projmatrix[16]; + double xs, ys, p[3]; + GLint viewport[4]; + short val; + + /* get border in window coords */ + setlinestyle(2); + val= get_border(&rect, 3); + setlinestyle(0); + if(val==0) return; + + v3d->flag |= V3D_CLIPPING; + v3d->clipbb= MEM_mallocN(sizeof(BoundBox), "clipbb"); + + /* convert border to 3d coordinates */ + + /* Get the matrices needed for gluUnProject */ + glGetIntegerv(GL_VIEWPORT, viewport); + glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); + glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); + + /* Set up viewport so that gluUnProject will give correct values */ + viewport[0] = 0; + viewport[1] = 0; + + /* four clipping planes and bounding volume */ + for(val=0; val<4; val++) { + + xs= (val==0||val==3)?rect.xmin:rect.xmax; + ys= (val==0||val==1)?rect.ymin:rect.ymax; + gluUnProject(xs, ys, 0.0, mvmatrix, projmatrix, viewport, &p[0], &p[1], &p[2]); + VECCOPY(v3d->clipbb->vec[val], p); + + VECCOPY(v3d->clip[val], G.vd->viewinv[val & 1]); + if(val>1) VecMulf(v3d->clip[val], -1.0f); + v3d->clip[val][3]= - v3d->clip[val][0]*p[0] - v3d->clip[val][1]*p[1] - v3d->clip[val][2]*p[2]; + + gluUnProject(xs, ys, 1.0, mvmatrix, projmatrix, viewport, &p[0], &p[1], &p[2]); + VECCOPY(v3d->clipbb->vec[4+val], p); + } + + } +} + diff --git a/source/blender/src/space.c b/source/blender/src/space.c index eaa4faf9e62..ac8fd8081fd 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1128,9 +1128,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } break; case BKEY: - if((G.qual==LR_SHIFTKEY)) + if(G.qual==LR_ALTKEY) + view3d_edit_clipping(v3d); + else if(G.qual==LR_SHIFTKEY) set_render_border(); - else if((G.qual==0)) + else if(G.qual==0) borderselect(); break; case CKEY: @@ -4494,13 +4496,13 @@ void freespacelist(ListBase *lb) else if(sl->spacetype==SPACE_BUTS) { SpaceButs *buts= (SpaceButs*) sl; if(buts->rect) MEM_freeN(buts->rect); - if(G.buts==buts) G.buts= 0; + if(G.buts==buts) G.buts= NULL; } else if(sl->spacetype==SPACE_IPO) { SpaceIpo *si= (SpaceIpo*) sl; if(si->editipo) MEM_freeN(si->editipo); free_ipokey(&si->ipokey); - if(G.sipo==si) G.sipo= 0; + if(G.sipo==si) G.sipo= NULL; } else if(sl->spacetype==SPACE_VIEW3D) { View3D *vd= (View3D*) sl; @@ -4510,7 +4512,8 @@ void freespacelist(ListBase *lb) MEM_freeN(vd->bgpic); } if(vd->localvd) MEM_freeN(vd->localvd); - if(G.vd==vd) G.vd= 0; + if(vd->clipbb) MEM_freeN(vd->clipbb); + if(G.vd==vd) G.vd= NULL; } else if(sl->spacetype==SPACE_OOPS) { free_oopspace((SpaceOops *)sl); @@ -4544,7 +4547,7 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) duplicatelist(lb1, lb2); - /* lb1 is kopie from lb2, from lb2 we free the file list */ + /* lb1 is copy from lb2, from lb2 we free the file list */ sl= lb2->first; while(sl) { @@ -4583,20 +4586,21 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) if(sl->spacetype==SPACE_BUTS) { SpaceButs *buts= (SpaceButs *)sl; - buts->rect= 0; + buts->rect= NULL; } else if(sl->spacetype==SPACE_IPO) { SpaceIpo *si= (SpaceIpo *)sl; - si->editipo= 0; - si->ipokey.first= si->ipokey.last= 0; + si->editipo= NULL; + si->ipokey.first= si->ipokey.last= NULL; } else if(sl->spacetype==SPACE_VIEW3D) { View3D *vd= (View3D *)sl; if(vd->bgpic) { vd->bgpic= MEM_dupallocN(vd->bgpic); - vd->bgpic->rect= 0; + vd->bgpic->rect= NULL; if(vd->bgpic->ima) vd->bgpic->ima->id.us++; } + vd->clipbb= MEM_dupallocN(vd->clipbb); } sl= sl->next; } @@ -4608,7 +4612,7 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) View3D *v3d= (View3D*) sl; if(v3d->localvd) { restore_localviewdata(v3d); - v3d->localvd= 0; + v3d->localvd= NULL; v3d->localview= 0; v3d->lay &= 0xFFFFFF; } diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index ea11b17f26d..53d55c7b772 100755 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -117,7 +117,7 @@ static void helpline(TransInfo *t, float *vec) getmouseco_areawin(mval); project_float(vecrot, cent); // no overflow in extreme cases - if(cent[0]!=3200.0f) { + if(cent[0]!=IS_CLIPPED) { persp(PERSP_WIN); glDrawBuffer(GL_FRONT); diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 9b3eab557d0..aef0171bad6 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -173,12 +173,17 @@ void project_short(float *vec, short *adr) /* clips */ { float fx, fy, vec4[4]; - adr[0]= 3200; + adr[0]= IS_CLIPPED; + + if(G.vd->flag & V3D_CLIPPING) { + if(view3d_test_clipping(G.vd, vec)) + return; + } + VECCOPY(vec4, vec); vec4[3]= 1.0; - Mat4MulVec4fl(G.vd->persmat, vec4); - + if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */ fx= (curarea->winx/2)*(1 + vec4[0]/vec4[3]); @@ -222,7 +227,7 @@ void project_short_noclip(float *vec, short *adr) { float fx, fy, vec4[4]; - adr[0]= 3200; + adr[0]= IS_CLIPPED; VECCOPY(vec4, vec); vec4[3]= 1.0; @@ -247,7 +252,7 @@ void project_float(float *vec, float *adr) { float vec4[4]; - adr[0]= 3200.0; + adr[0]= IS_CLIPPED; VECCOPY(vec4, vec); vec4[3]= 1.0; @@ -259,29 +264,41 @@ void project_float(float *vec, float *adr) } } -void view3d_get_object_project_mat(ScrArea *area, Object *ob, float mat[4][4]) +void view3d_get_object_project_mat(ScrArea *area, Object *ob, float pmat[4][4], float vmat[4][4]) { if (area->spacetype!=SPACE_VIEW3D || !area->spacedata.first) { - Mat4One(mat); + Mat4One(pmat); + Mat4One(vmat); } else { View3D *vd = area->spacedata.first; - float tmp[4][4]; - Mat4MulMat4(tmp, ob->obmat, vd->viewmat); - Mat4MulMat4(mat, tmp, vd->winmat1); + Mat4MulMat4(vmat, ob->obmat, vd->viewmat); + Mat4MulMat4(pmat, vmat, vd->winmat1); } } -void view3d_project_short(ScrArea *area, float *vec, short *adr, float mat[4][4]) +/* projectmat brings it to window coords, viewmat to rotated view (eye space) */ +void view3d_project_short_clip(ScrArea *area, float *vec, short *adr, float projmat[4][4], float viewmat[4][4]) { + View3D *v3d= area->spacedata.first; float fx, fy, vec4[4]; - adr[0]= 3200; + adr[0]= IS_CLIPPED; + + /* clipplanes in eye space */ + if(v3d->flag & V3D_CLIPPING) { + VECCOPY(vec4, vec); + Mat4MulVecfl(viewmat, vec4); + if(view3d_test_clipping(v3d, vec4)) + return; + } + VECCOPY(vec4, vec); vec4[3]= 1.0; - Mat4MulVec4fl(mat, vec4); - + Mat4MulVec4fl(projmat, vec4); + + /* clipplanes in window space */ if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */ fx= (area->winx/2)*(1 + vec4[0]/vec4[3]); @@ -301,7 +318,8 @@ void view3d_project_short_noclip(ScrArea *area, float *vec, short *adr, float ma { float fx, fy, vec4[4]; - adr[0]= 3200; + adr[0]= IS_CLIPPED; + VECCOPY(vec4, vec); vec4[3]= 1.0; @@ -326,7 +344,7 @@ void view3d_project_float(ScrArea *area, float *vec, float *adr, float mat[4][4] { float vec4[4]; - adr[0]= 3200.0; + adr[0]= IS_CLIPPED; VECCOPY(vec4, vec); vec4[3]= 1.0; @@ -975,6 +993,9 @@ short view3d_opengl_select(unsigned int *buffer, unsigned int bufsize, short x1 glEnable(GL_DEPTH_TEST); } + if(G.vd->flag & V3D_CLIPPING) + view3d_set_clipping(G.vd); + glSelectBuffer( bufsize, (GLuint *)buffer); glRenderMode(GL_SELECT); glInitNames(); /* these two calls whatfor? It doesnt work otherwise */ @@ -1015,6 +1036,9 @@ short view3d_opengl_select(unsigned int *buffer, unsigned int bufsize, short x1 glDisable(GL_DEPTH_TEST); } persp(PERSP_WIN); + + if(G.vd->flag & V3D_CLIPPING) + view3d_clr_clipping(); return hits; }