diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2014-12-05 16:42:22 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2015-04-20 13:23:15 +0300 |
commit | 56a09434c533e5ca72d2f8ff6e144bfcdd88886c (patch) | |
tree | 9ca26e1fc412da4c3cd21fba2334af8a89103105 /source/blender/editors/hair | |
parent | 8672304e30a207767888b75ebe9015ad7f3210a3 (diff) |
Basic Add tool for creating new strands in hair edit mode.
Diffstat (limited to 'source/blender/editors/hair')
-rw-r--r-- | source/blender/editors/hair/hair_edit.c | 8 | ||||
-rw-r--r-- | source/blender/editors/hair/hair_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/hair/hair_stroke.c | 115 |
3 files changed, 113 insertions, 11 deletions
diff --git a/source/blender/editors/hair/hair_edit.c b/source/blender/editors/hair/hair_edit.c index fa7e914b5ee..4912adde524 100644 --- a/source/blender/editors/hair/hair_edit.c +++ b/source/blender/editors/hair/hair_edit.c @@ -308,7 +308,6 @@ static bool hair_stroke_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) HairEditSettings *settings = &scene->toolsettings->hair_edit; ARegion *ar = CTX_wm_region(C); - float imat[4][4]; float mouse[2], mdelta[2], zvec[3], delta_max; int totsteps, step; HairToolData tool_data; @@ -316,8 +315,6 @@ static bool hair_stroke_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) RNA_float_get_array(itemptr, "mouse", mouse); - invert_m4_m4(imat, ob->obmat); - if (stroke->first) { copy_v2_v2(stroke->lastmouse, mouse); stroke->first = false; @@ -338,6 +335,7 @@ static bool hair_stroke_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) tool_data.edit = edit; tool_data.settings = settings; + invert_m4_m4(tool_data.imat, ob->obmat); copy_v2_v2(tool_data.mval, mouse); tool_data.mdepth = stroke->zfac; @@ -345,8 +343,8 @@ static bool hair_stroke_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) ED_view3d_win_to_3d(ar, zvec, mouse, tool_data.loc); ED_view3d_win_to_delta(ar, mdelta, tool_data.delta, stroke->zfac); /* tools work in object space */ - mul_m4_v3(imat, tool_data.loc); - mul_mat3_m4_v3(imat, tool_data.delta); + mul_m4_v3(tool_data.imat, tool_data.loc); + mul_mat3_m4_v3(tool_data.imat, tool_data.delta); for (step = 0; step < totsteps; ++step) { bool step_updated = hair_brush_step(&tool_data); diff --git a/source/blender/editors/hair/hair_intern.h b/source/blender/editors/hair/hair_intern.h index 7218fa08483..92b40fd083f 100644 --- a/source/blender/editors/hair/hair_intern.h +++ b/source/blender/editors/hair/hair_intern.h @@ -73,6 +73,7 @@ typedef struct HairToolData { float mdepth; /* mouse z depth */ /* object space */ + float imat[4][4]; /* obmat inverse */ float loc[3]; /* start location */ float delta[3]; /* stroke step */ } HairToolData; diff --git a/source/blender/editors/hair/hair_stroke.c b/source/blender/editors/hair/hair_stroke.c index e7b095e9c85..ec34475fc94 100644 --- a/source/blender/editors/hair/hair_stroke.c +++ b/source/blender/editors/hair/hair_stroke.c @@ -37,12 +37,15 @@ #include "BLI_math.h" #include "DNA_brush_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_view3d_types.h" #include "BKE_brush.h" +#include "BKE_DerivedMesh.h" #include "BKE_edithair.h" +#include "BKE_mesh_sample.h" #include "bmesh.h" @@ -163,10 +166,102 @@ static void hair_vertex_comb(HairToolData *data, void *userdata, BMVert *v, floa madd_v3_v3fl(v->co, data->delta, combfactor); } + +BLI_INLINE void construct_m4_loc_nor_tan(float mat[4][4], const float loc[3], const float nor[3], const float tang[3]) +{ + float cotang[3]; + + cross_v3_v3v3(cotang, nor, tang); + + copy_v3_v3(mat[0], tang); + copy_v3_v3(mat[1], cotang); + copy_v3_v3(mat[2], nor); + copy_v3_v3(mat[3], loc); + mat[0][3] = 0.0f; + mat[1][3] = 0.0f; + mat[2][3] = 0.0f; + mat[3][3] = 1.0f; +} + +static void grow_hair(BMEditStrands *edit, MSurfaceSample *sample) +{ + DerivedMesh *dm = edit->root_dm; + const float len = 1.5f; + + float root_mat[4][4]; + BMVert *root, *v; + BMIter iter; + int i; + + { + float co[3], nor[3], tang[3]; + BKE_mesh_sample_eval(dm, sample, co, nor, tang); + construct_m4_loc_nor_tan(root_mat, co, nor, tang); + } + + root = BM_strands_create(edit->bm, 5, true); + + BM_elem_meshsample_data_named_set(&edit->bm->vdata, root, CD_MSURFACE_SAMPLE, CD_HAIR_ROOT_LOCATION, sample); + + BM_ITER_STRANDS_ELEM_INDEX(v, &iter, root, BM_VERTS_OF_STRAND, i) { + float co[3]; + + co[0] = co[1] = 0.0f; + co[2] = len * (float)i / (float)(len - 1); + + mul_m4_v3(root_mat, co); + + copy_v3_v3(v->co, co); + } + + BM_mesh_elem_index_ensure(edit->bm, BM_ALL); +} + +static bool hair_add_ray_cb(void *vdata, float ray_start[3], float ray_end[3]) +{ + HairToolData *data = vdata; + ViewContext *vc = &data->viewdata.vc; + + ED_view3d_win_to_segment(vc->ar, vc->v3d, data->mval, ray_start, ray_end, true); + + mul_m4_v3(data->imat, ray_start); + mul_m4_v3(data->imat, ray_end); + + return true; +} + +static bool hair_get_surface_sample(HairToolData *data, MSurfaceSample *sample) +{ + DerivedMesh *dm = data->edit->root_dm; + + MSurfaceSampleStorage dst; + int tot; + + BKE_mesh_sample_storage_single(&dst, sample); + tot = BKE_mesh_sample_generate_raycast(&dst, dm, hair_add_ray_cb, data, 1); + BKE_mesh_sample_storage_release(&dst); + + return tot > 0; +} + +static bool hair_add(HairToolData *data) +{ + MSurfaceSample sample; + + if (!hair_get_surface_sample(data, &sample)) + return false; + + grow_hair(data->edit, &sample); + + return true; +} + + bool hair_brush_step(HairToolData *data) { Brush *brush = data->settings->brush; BrushHairTool hair_tool = brush->hair_tool; + BMEditStrands *edit = data->edit; int tot = 0; switch (hair_tool) { @@ -181,12 +276,20 @@ bool hair_brush_step(HairToolData *data) tot = hair_tool_apply_vertex(data, hair_vertex_comb, &combdata); break; } - case HAIR_TOOL_CUT: break; - case HAIR_TOOL_LENGTH: break; - case HAIR_TOOL_PUFF: break; - case HAIR_TOOL_ADD: break; - case HAIR_TOOL_SMOOTH: break; - case HAIR_TOOL_WEIGHT: break; + case HAIR_TOOL_CUT: + break; + case HAIR_TOOL_LENGTH: + break; + case HAIR_TOOL_PUFF: + break; + case HAIR_TOOL_ADD: + if (hair_add(data)) + edit->flag |= BM_STRANDS_DIRTY_SEGLEN; + break; + case HAIR_TOOL_SMOOTH: + break; + case HAIR_TOOL_WEIGHT: + break; } return tot > 0; |