From d0ec3f428c5bafd46d7bd80dedff15c6c7f9f8e6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 Jan 2010 17:48:48 +0000 Subject: - grease pencil option to only use the endpoint depths. this makes drawing shapes in 3D easier since it wont stick to every depth the line passes through. - use a 8x8 area when finding stroke depths since thin lines can get ignored if the point is not close enough to them. --- source/blender/editors/gpencil/gpencil_buttons.c | 4 + source/blender/editors/gpencil/gpencil_paint.c | 26 ++++- source/blender/editors/include/ED_view3d.h | 4 +- source/blender/editors/space_view3d/view3d_edit.c | 117 ++++++++++++---------- source/blender/makesdna/DNA_gpencil_types.h | 2 + source/blender/makesrna/intern/rna_gpencil.c | 6 ++ 6 files changed, 100 insertions(+), 59 deletions(-) (limited to 'source') diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c index 4f12f072e72..e93788bc495 100644 --- a/source/blender/editors/gpencil/gpencil_buttons.c +++ b/source/blender/editors/gpencil/gpencil_buttons.c @@ -266,6 +266,10 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi row= uiLayoutRow(col, 1); uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "SURFACE"); uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "STROKE"); + + row= uiLayoutRow(col, 0); + uiLayoutSetActive(row, (gpd->flag & GP_DATA_DEPTH_STROKE) ? 1:0); + uiItemR(row, NULL, 0, &gpd_ptr, "use_stroke_endpoints", 0); } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index d48ff411f10..5efc9d916c1 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -218,7 +218,7 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[], flo /* in 3d-space - pt->x/y/z are 3 side-by-side floats */ if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) { - if(gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out, depth))) { + if(gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out, 0, depth))) { /* projecting onto 3D-Geometry * - nothing more needs to be done here, since view_autodist_simple() has already done it */ @@ -458,6 +458,8 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) bGPDspoint *pt; tGPspoint *ptc; int i, totelem; + /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */ + int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0; /* get total number of points to allocate space for * - drawing straight-lines only requires the endpoints @@ -525,7 +527,7 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size; i++, ptc++, pt++) { mval[0]= ptc->x; mval[1]= ptc->y; - if(view_autodist_depth(p->ar, mval, depth_arr+i) == 0) + if(view_autodist_depth(p->ar, mval, depth_margin, depth_arr+i) == 0) interp_depth= TRUE; else found_depth= TRUE; @@ -537,6 +539,26 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) depth_arr[i] = 0.9999f; } else if(interp_depth) { + if(p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) { + /* remove all info between the valid endpoints */ + int first_valid = 0; + int last_valid = 0; + + for (i=0; i < gpd->sbuffer_size; i++) + if(depth_arr[i] != FLT_MAX) + break; + first_valid= i; + + for (i=gpd->sbuffer_size-1; i >= 0; i--) + if(depth_arr[i] != FLT_MAX) + break; + last_valid= i; + + /* invalidate non-endpoints, so only blend between first and last */ + for (i=first_valid+1; i < last_valid; i++) + depth_arr[i]= FLT_MAX; + } + interp_sparse_array(depth_arr, gpd->sbuffer_size, FLT_MAX); } } diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index b087829d6b0..a7879c7b70d 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -128,8 +128,8 @@ int view_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, s /* only draw so view_autodist_simple can be called many times after */ int view_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode); -int view_autodist_simple(struct ARegion *ar, short *mval, float mouse_worldloc[3], float *force_depth); -int view_autodist_depth(struct ARegion *ar, short *mval, float *depth); +int view_autodist_simple(struct ARegion *ar, short *mval, float mouse_worldloc[3], int margin, float *force_depth); +int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *depth); /* select */ #define MAXPICKBUF 10000 diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 87219b16dd2..029bb84ca2f 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1474,7 +1474,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) /* ZBuffer depth vars */ bglMats mats; - float depth, depth_close= MAXFLOAT; + float depth, depth_close= FLT_MAX; int had_depth = 0; double cent[2], p[3]; int xs, ys; @@ -1531,7 +1531,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) double p_corner[3]; /* no depths to use, we cant do anything! */ - if (depth_close==MAXFLOAT){ + if (depth_close==FLT_MAX){ BKE_report(op->reports, RPT_ERROR, "Depth Too Large"); return OPERATOR_CANCELLED; } @@ -1559,7 +1559,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) new_dist = rv3d->dist; /* convert the drawn rectangle into 3d space */ - if (depth_close!=MAXFLOAT && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) { + if (depth_close!=FLT_MAX && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) { new_ofs[0] = -p[0]; new_ofs[1] = -p[1]; new_ofs[2] = -p[2]; @@ -2197,22 +2197,66 @@ void VIEW3D_OT_manipulator(wmOperatorType *ot) /* ************************* below the line! *********************** */ +static float view_autodist_depth_margin(ARegion *ar, short *mval, int margin) +{ + RegionView3D *rv3d= ar->regiondata; + float depth= FLT_MAX; + + 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; + } + } + 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; +} + /* 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 */ - rcti rect; - float depth, depth_close= MAXFLOAT; + float depth_close= FLT_MAX; int had_depth = 0; double cent[2], p[3]; - int xs, ys; - - rect.xmax = mval[0] + 4; - rect.ymax = mval[1] + 4; - - rect.xmin = mval[0] - 4; - rect.ymin = mval[1] - 4; /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); @@ -2226,25 +2270,9 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou view3d_update_depths(ar, v3d); - /* 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_close= view_autodist_depth_margin(ar, mval, 4); - if (depth_close==MAXFLOAT) + if (depth_close==FLT_MAX) return 0; if (had_depth==0) { @@ -2289,23 +2317,17 @@ int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, flo } // no 4x4 sampling, run view_autodist_init first -int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], float *force_depth) //, float *autodist ) +int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], int margin, float *force_depth) //, float *autodist ) { - RegionView3D *rv3d= ar->regiondata; bglMats mats; /* ZBuffer depth vars, could cache? */ float depth; double cent[2], p[3]; - 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 */ if(force_depth) depth= *force_depth; else - depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]]; + depth= view_autodist_depth_margin(ar, mval, margin); if (depth==FLT_MAX) return 0; @@ -2323,24 +2345,9 @@ int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], floa return 1; } -int view_autodist_depth(struct ARegion *ar, short *mval, float *depth) +int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *depth) { - RegionView3D *rv3d= ar->regiondata; - *depth= FLT_MAX; - - 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]]; - - /* float error means we need to shave off some */ - - if(*depth >= 1.0) { - *depth= FLT_MAX; - } + *depth= view_autodist_depth_margin(ar, mval, margin); return (*depth==FLT_MAX) ? 0:1; return 0; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 5755e23675a..332442b9f42 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -150,4 +150,6 @@ typedef struct bGPdata { #define GP_DATA_DEPTH_VIEW (1<<5) #define GP_DATA_DEPTH_STROKE (1<<6) +#define GP_DATA_DEPTH_STROKE_ENDPOINTS (1<<7) + #endif /* DNA_GPENCIL_TYPES_H */ diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 71c87fe9fa1..87cf9502c69 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -243,6 +243,12 @@ static void rna_def_gpencil_data(BlenderRNA *brna) RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, draw_mode_items); RNA_def_property_ui_text(prop, "Draw Mode", ""); + + prop= RNA_def_property(srna, "use_stroke_endpoints", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_DEPTH_STROKE_ENDPOINTS); + RNA_def_property_ui_text(prop, "Only Endpoints", "When snapping the stroke to existing lines, only use the first and last parts of the line."); + + } /* --- */ -- cgit v1.2.3