diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-01-01 18:05:31 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-01-01 18:05:31 +0300 |
commit | 30aff3b830ac222bae90bea02fef0d41fd9d197c (patch) | |
tree | 0b798790b22d728dd8f1c06d55b6f21e47d2afb5 /source/blender | |
parent | c58f2dfc9d27a5635360a96116fb3a887c35b890 (diff) |
- grease pencil mode for drawing onto geometry (using the z-buffer), access in the 3D view panel.
- account for parts of the line going off into infinity by making the stroke stretch between the last valid depth values (like an elastic band), if the endpoints are not over any geometry then use the closest valid depth.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_buttons.c | 8 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_paint.c | 110 | ||||
-rw-r--r-- | source/blender/editors/include/ED_view3d.h | 3 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_edit.c | 34 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_gpencil_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_gpencil.c | 13 |
6 files changed, 143 insertions, 27 deletions
diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c index 5deffbabb77..54dd43160a6 100644 --- a/source/blender/editors/gpencil/gpencil_buttons.c +++ b/source/blender/editors/gpencil/gpencil_buttons.c @@ -229,7 +229,7 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi { PointerRNA gpd_ptr; bGPDlayer *gpl; - uiLayout *col; + uiLayout *col, *row; /* make new PointerRNA for Grease Pencil block */ RNA_id_pointer_create((ID *)gpd, &gpd_ptr); @@ -259,7 +259,11 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi uiItemL(col, "Drawing Settings:", 0); /* 'stick to view' option */ - uiItemR(col, NULL, 0, &gpd_ptr, "view_space_draw", 0); + //uiItemR(col, NULL, 0, &gpd_ptr, "draw_mode", 0); + row= uiLayoutRow(layout, 1); + uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "VIEW"); + uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "CURSOR"); + uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "DEPTH"); } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 3f9e3e04411..86ca69f6cf6 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -155,15 +155,7 @@ static int gpencil_draw_poll (bContext *C) static int gpencil_project_check (tGPsdata *p) { bGPdata *gpd= p->gpd; - - if( (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) && - (p->scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE) && - (p->scene->toolsettings->snap_flag & SCE_SNAP_PROJECT) ) - { - return 1; - } - - return 0; + return ((gpd->sbuffer_sflag & GP_STROKE_3DSPACE) && (p->gpd->flag & GP_DATA_VIEWDEPTH)) ? 1:0; } /* ******************************************* */ @@ -220,13 +212,13 @@ static short gp_stroke_filtermval (tGPsdata *p, int mval[2], int pmval[2]) /* convert screen-coordinates to buffer-coordinates */ // XXX this method needs a total overhaul! -static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) +static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[], float *depth) { bGPdata *gpd= p->gpd; /* 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))) { + if(gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out, depth))) { /* projecting onto 3D-Geometry * - nothing more needs to be done here, since view_autodist_simple() has already done it */ @@ -501,7 +493,7 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) ptc= gpd->sbuffer; /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* copy pressure */ pt->pressure= ptc->pressure; @@ -514,23 +506,107 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1); /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* copy pressure */ pt->pressure= ptc->pressure; } } else { + float *depth_arr= NULL; + + /* get an array of depths, far depths are blended */ + if(gpencil_project_check(p)) { + short mval[2]; + int interp_depth = 0; + int found_depth = 0; + + depth_arr= MEM_mallocN(sizeof(float) * gpd->sbuffer_size, "depth_points"); + + 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) + interp_depth= TRUE; + else + found_depth= TRUE; + } + + if(found_depth==FALSE) { + /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */ + for (i=gpd->sbuffer_size-1; i >= 0; i--) + depth_arr[i] = 0.9999f; + } + else if(interp_depth) { + /* found invalid depths, interpolate */ + float valid_last= FLT_MAX; + int valid_ofs= 0; + + float *depth_arr_up= MEM_callocN(sizeof(float) * gpd->sbuffer_size, "depth_points_up"); + float *depth_arr_down= MEM_callocN(sizeof(float) * gpd->sbuffer_size, "depth_points_down"); + + int *depth_tot_up= MEM_callocN(sizeof(int) * gpd->sbuffer_size, "depth_tot_up"); + int *depth_tot_down= MEM_callocN(sizeof(int) * gpd->sbuffer_size, "depth_tot_down"); + + for (i=0; i < gpd->sbuffer_size; i++) { + if(depth_arr[i] == FLT_MAX) { + depth_arr_up[i]= valid_last; + depth_tot_up[i]= ++valid_ofs; + } + else { + valid_last= depth_arr[i]; + valid_ofs= 0; + } + } + + valid_last= FLT_MAX; + valid_ofs= 0; + + for (i=gpd->sbuffer_size-1; i >= 0; i--) { + if(depth_arr[i] == FLT_MAX) { + depth_arr_down[i]= valid_last; + depth_tot_down[i]= ++valid_ofs; + } + else { + valid_last= depth_arr[i]; + valid_ofs= 0; + } + } + + /* now blend */ + for (i=0; i < gpd->sbuffer_size; i++) { + if(depth_arr[i] == FLT_MAX) { + if(depth_arr_up[i] != FLT_MAX && depth_arr_down[i] != FLT_MAX) { + depth_arr[i]= ((depth_arr_up[i] * depth_tot_down[i]) + (depth_arr_down[i] * depth_tot_up[i])) / (float)(depth_tot_down[i] + depth_tot_up[i]); + } else if (depth_arr_up[i] != FLT_MAX) { + depth_arr[i]= depth_arr_up[i]; + } else if (depth_arr_down[i] != FLT_MAX) { + depth_arr[i]= depth_arr_down[i]; + } + } + } + + MEM_freeN(depth_arr_up); + MEM_freeN(depth_arr_down); + + MEM_freeN(depth_tot_up); + MEM_freeN(depth_tot_down); + } + } + + + pt= gps->points; + /* convert all points (normal behaviour) */ - for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { + for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++, pt++) { /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr+i:NULL); /* copy pressure */ pt->pressure= ptc->pressure; - - pt++; } + + if(depth_arr) + MEM_freeN(depth_arr); } /* add stroke to frame */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index de5a9fe4e07..2e439f8fdef 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -128,7 +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 view_autodist_simple(struct ARegion *ar, short *mval, float mouse_worldloc[3]); +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); /* 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 9b0712ac255..bfd2ecb4939 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2282,7 +2282,7 @@ int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d) //, float *autodi } // no 4x4 sampling, run view_autodist_init first -int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3] ) //, float *autodist ) +int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], float *force_depth) //, float *autodist ) { RegionView3D *rv3d= ar->regiondata; bglMats mats; /* ZBuffer depth vars, could cache? */ @@ -2295,15 +2295,18 @@ int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3] ) //, if (mval[1] >= rv3d->depths->h) return 0; /* Get Z Depths, needed for perspective, nice for ortho */ - bgl_get_mats(&mats); - depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]]; + if(force_depth) + depth= *force_depth; + else + depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]]; - if (depth==MAXFLOAT) + if (depth==FLT_MAX) return 0; cent[0] = (double)mval[0]; cent[1] = (double)mval[1]; + bgl_get_mats(&mats); if (!gluUnProject(cent[0], cent[1], depth, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) return 0; @@ -2313,6 +2316,29 @@ int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3] ) //, return 1; } +int view_autodist_depth(struct ARegion *ar, short *mval, 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; + } + + return (*depth==FLT_MAX) ? 0:1; + return 0; +} + /* ********************* NDOF ************************ */ /* note: this code is confusing and unclear... (ton) */ /* **************************************************** */ diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 4bae9935ea7..9ba3c243d20 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -146,5 +146,7 @@ typedef struct bGPdata { #define GP_DATA_EDITPAINT (1<<3) /* new strokes are added in viewport space */ #define GP_DATA_VIEWALIGN (1<<4) + /* Project into the screens Z values */ +#define GP_DATA_VIEWDEPTH (1<<5) #endif /* DNA_GPENCIL_TYPES_H */ diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 129fad4e98c..d55f5f21e72 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -220,6 +220,12 @@ static void rna_def_gpencil_data(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static EnumPropertyItem draw_mode_items[] = { + {GP_DATA_VIEWALIGN, "CURSOR", 0, "Cursor", ""}, + {0, "VIEW", 0, "View", ""}, /* weired, GP_DATA_VIEWALIGN is inverted */ + {GP_DATA_VIEWALIGN|GP_DATA_VIEWDEPTH, "DEPTH", 0, "Depth", ""}, + {0, NULL, 0, NULL, NULL}}; + srna= RNA_def_struct(brna, "GreasePencil", "ID"); RNA_def_struct_sdna(srna, "bGPdata"); RNA_def_struct_ui_text(srna, "Grease Pencil", "Freehand annotation sketchbook."); @@ -232,9 +238,10 @@ static void rna_def_gpencil_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layers", "Similar to layers in Photoshop."); /* Flags */ - prop= RNA_def_property(srna, "view_space_draw", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_DATA_VIEWALIGN); - RNA_def_property_ui_text(prop, "Stick to View", "Newly drawn strokes get added in view space (i.e. sketches stick to data when view is manipulated)."); + prop= RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE); + 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", ""); } /* --- */ |