diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index f5a84aa4c19..fe024be29e0 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -63,6 +63,7 @@ typedef struct ViewContext { typedef struct ViewDepths { unsigned short w, h; + short x, y; /* only for temp use for sub-rects, added to ar->winx/y */ float *depths; double depth_range[2]; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 1d18f484ae0..7722ca5605b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1569,7 +1569,51 @@ static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *bas draw_dupli_objects_color(scene, ar, v3d, base, color); } +void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) +{ + int x, y, w, h; + /* clamp rect by area */ + + /* Constrain rect to depth bounds */ + if (rect->xmin < 0) rect->xmin = 0; + if (rect->ymin < 0) rect->ymin = 0; + if (rect->xmax >= ar->winx) rect->xmax = ar->winx-1; + if (rect->ymax >= ar->winy) rect->ymax = ar->winy-1; + /* assign values to compare with the ViewDepths */ + x= ar->winrct.xmin + rect->xmin; + y= ar->winrct.ymin + rect->ymin; + + w= rect->xmax - rect->xmin; + h= rect->ymax - rect->ymin; + + if( d->w != w || + d->h != h || + d->x != x || + d->y != y || + d->depths==NULL + ) { + d->x= x; + d->y= y; + d->w= w; + d->h= h; + + if(d->depths) + MEM_freeN(d->depths); + + d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths Subset"); + + d->damaged= 1; + } + + if(d->damaged) { + glReadPixels(ar->winrct.xmin+d->x,ar->winrct.ymin+d->y, d->w,d->h, GL_DEPTH_COMPONENT,GL_FLOAT, d->depths); + glGetDoublev(GL_DEPTH_RANGE,d->depth_range); + d->damaged= 0; + } +} + +/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ void view3d_update_depths(ARegion *ar) { RegionView3D *rv3d= ar->regiondata; @@ -1600,6 +1644,30 @@ void view3d_update_depths(ARegion *ar) } } +/* utility function to find the closest Z value, use for autodepth */ +float view3d_depth_near(ViewDepths *d) +{ + /* convert to float for comparisons */ + const float near= (float)d->depth_range[0]; + const float far_real= (float)d->depth_range[1]; + float far= far_real; + + const float *depths= d->depths; + float depth= FLT_MAX; + int i= d->w * d->h; + + /* far is both the starting 'far' value + * and the closest value found. */ + while(i--) { + depth= *depths++; + if((depth < far) && (depth > near)) { + far= depth; + } + } + + return far == far_real ? FLT_MAX : far; +} + void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) { short zbuf= v3d->zbuf; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index dc75efcc5ca..a5cca6341f6 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -63,6 +63,7 @@ #include "ED_screen.h" #include "ED_transform.h" #include "ED_mesh.h" +#include "ED_view3d.h" #include "PIL_time.h" /* smoothview */ @@ -1667,10 +1668,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) /* ZBuffer depth vars */ bglMats mats; - float depth, depth_close= FLT_MAX; - int had_depth = 0; + float depth_close= FLT_MAX; double cent[2], p[3]; - int xs, ys; /* note; otherwise opengl won't work */ view3d_operator_needs_opengl(C); @@ -1684,39 +1683,20 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); draw_depth(scene, ar, v3d, NULL); + + { + /* avoid allocating the whole depth buffer */ + ViewDepths depth_temp= {0}; - /* force updating */ - if (rv3d->depths) { - had_depth = 1; - rv3d->depths->damaged = 1; + /* avoid view3d_update_depths() for speed. */ + view3d_update_depths_rect(ar, &depth_temp, &rect); + + /* find the closest Z pixel */ + depth_close= view3d_depth_near(&depth_temp); + + MEM_freeN(depth_temp.depths); } - view3d_update_depths(ar); - - /* Constrain rect to depth bounds */ - if (rect.xmin < 0) rect.xmin = 0; - if (rect.ymin < 0) rect.ymin = 0; - if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1; - if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1; - - /* Find the closest Z pixel */ - for (xs=rect.xmin; xs < rect.xmax; xs++) { - for (ys=rect.ymin; ys < rect.ymax; ys++) { - depth= rv3d->depths->depths[ys*rv3d->depths->w+xs]; - if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) { - if (depth_close > depth) { - depth_close = depth; - } - } - } - } - - if (had_depth==0) { - MEM_freeN(rv3d->depths->depths); - rv3d->depths->depths = NULL; - } - rv3d->depths->damaged = 1; - cent[0] = (((double)rect.xmin)+((double)rect.xmax)) / 2; cent[1] = (((double)rect.ymin)+((double)rect.ymax)) / 2; @@ -2574,88 +2554,49 @@ void VIEW3D_OT_enable_manipulator(wmOperatorType *ot) static float view_autodist_depth_margin(ARegion *ar, short *mval, int margin) { - RegionView3D *rv3d= ar->regiondata; - float depth= FLT_MAX; + ViewDepths depth_temp= {0}; + rcti rect; + float depth_close; if(margin==0) { - if (mval[0] < 0) return 0; - if (mval[1] < 0) return 0; - if (mval[0] >= rv3d->depths->w) return 0; - if (mval[1] >= rv3d->depths->h) return 0; - /* Get Z Depths, needed for perspective, nice for ortho */ - depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]]; - if(depth >= rv3d->depths->depth_range[1] || depth <= rv3d->depths->depth_range[0]) { - depth= FLT_MAX; - } + rect.xmin= mval[0]; + rect.ymin= mval[1]; + rect.xmax= mval[0] + 1; + rect.ymax= mval[1] + 1; } else { - rcti rect; - float depth_close= FLT_MAX; - int xs, ys; - rect.xmax = mval[0] + margin; rect.ymax = mval[1] + margin; rect.xmin = mval[0] - margin; rect.ymin = mval[1] - margin; - - /* Constrain rect to depth bounds */ - if (rect.xmin < 0) rect.xmin = 0; - if (rect.ymin < 0) rect.ymin = 0; - if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1; - if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1; - - /* Find the closest Z pixel */ - for (xs=rect.xmin; xs < rect.xmax; xs++) { - for (ys=rect.ymin; ys < rect.ymax; ys++) { - depth= rv3d->depths->depths[ys*rv3d->depths->w+xs]; - if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) { - if (depth_close > depth) { - depth_close = depth; - } - } - } - } - - depth= depth_close; } - return depth; + view3d_update_depths_rect(ar, &depth_temp, &rect); + depth_close= view3d_depth_near(&depth_temp); + + MEM_freeN(depth_temp.depths); + + return depth_close; } /* XXX todo Zooms in on a border drawn by the user */ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist ) { - RegionView3D *rv3d= ar->regiondata; bglMats mats; /* ZBuffer depth vars */ float depth_close= FLT_MAX; - int had_depth = 0; double cent[2], p[3]; /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); draw_depth(scene, ar, v3d, NULL); - /* force updating */ - if (rv3d->depths) { - had_depth = 1; - rv3d->depths->damaged = 1; - } - - view3d_update_depths(ar); - depth_close= view_autodist_depth_margin(ar, mval, 4); if (depth_close==FLT_MAX) return 0; - if (had_depth==0) { - MEM_freeN(rv3d->depths->depths); - rv3d->depths->depths = NULL; - } - rv3d->depths->damaged = 1; - cent[0] = (double)mval[0]; cent[1] = (double)mval[1]; @@ -2670,8 +2611,6 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, float *autodist ) { - RegionView3D *rv3d= ar->regiondata; - /* Get Z Depths, needed for perspective, nice for ortho */ switch(mode) { case 0: @@ -2682,12 +2621,6 @@ int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, flo break; } - /* force updating */ - if (rv3d->depths) { - rv3d->depths->damaged = 1; - } - - view3d_update_depths(ar); return 1; } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index d6d8fddd442..e81d0b87589 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -131,6 +131,8 @@ void add_view3d_after(ListBase *lb, Base *base, int flag); void circf(float x, float y, float rad); void circ(float x, float y, float rad); void view3d_update_depths(struct ARegion *ar); +void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect); +float view3d_depth_near(struct ViewDepths *d); /* view3d_select.c */ void VIEW3D_OT_select(struct wmOperatorType *ot);