diff options
Diffstat (limited to 'source/blender/editors/object/object_modifier.c')
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 04243660440..5458e4c173f 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -58,11 +58,13 @@ #include "BKE_DerivedMesh.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_hair.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" +#include "BKE_mesh_sample.h" #include "BKE_modifier.h" #include "BKE_multires.h" #include "BKE_report.h" @@ -2369,3 +2371,122 @@ void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); } + +/************************ Fur follicle generate operator *********************/ + +static void fur_create_guide_curves(struct HairSystem *hsys, unsigned int seed, DerivedMesh *scalp, int count) +{ + float area = BKE_hair_calc_surface_area(scalp); + float density = BKE_hair_calc_density_from_count(area, count); + float min_distance = BKE_hair_calc_min_distance_from_density(density); + MeshSampleGenerator *gen = BKE_mesh_sample_gen_surface_poissondisk(seed, min_distance, count, NULL, NULL); + + BKE_mesh_sample_generator_bind(gen, scalp); + + { + MeshSample *buffer = MEM_mallocN(sizeof(MeshSample) * count, "mesh sample buffer"); + int totguides = BKE_mesh_sample_generate_batch(gen, buffer, count); + + { + BKE_hair_guide_curves_begin(hsys, totguides); + + MeshSample *sample = buffer; + for (int i = 0; i < totguides; ++i, ++sample) + { + BKE_hair_set_guide_curve(hsys, i, sample, 2); + } + + BKE_hair_guide_curves_end(hsys); + } + + { + int vertstart = 0; + MeshSample *sample = buffer; + for (int i = 0; i < totguides; ++i, ++sample) + { + float co[3], nor[3], tang[3]; + BKE_mesh_sample_eval(scalp, sample, co, nor, tang); + BKE_hair_set_guide_vertex(hsys, vertstart, 0, co); + + madd_v3_v3fl(co, nor, 0.1f); + BKE_hair_set_guide_vertex(hsys, vertstart + 1, 0, co); + + vertstart += 2; + } + } + + MEM_freeN(buffer); + } + + BKE_mesh_sample_free_generator(gen); + + BKE_hair_bind_follicles(hsys, scalp); +} + +static int fur_generate_follicles_poll(bContext *C) +{ + return edit_modifier_poll_generic(C, &RNA_FurModifier, 0); +} + +static int fur_generate_follicles_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + FurModifierData *fmd = (FurModifierData *)edit_modifier_property_get(op, ob, eModifierType_Fur); + + if (!fmd) + return OPERATOR_CANCELLED; + + BLI_assert(fmd->hair_system != NULL); + + struct Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + + CustomDataMask datamask = CD_MASK_BAREMESH; + DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, scene, ob, datamask); + + BKE_hair_generate_follicles( + fmd->hair_system, + dm, + (unsigned int)fmd->follicle_seed, + fmd->follicle_count); + + { + unsigned int guides_seed = fmd->follicle_seed ^ 0xFFFF; + fur_create_guide_curves( + fmd->hair_system, + guides_seed, + dm, + fmd->guides_count); + } + + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +static int fur_generate_follicles_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (edit_modifier_invoke_properties(C, op)) + return fur_generate_follicles_exec(C, op); + else + return OPERATOR_CANCELLED; +} + +void OBJECT_OT_fur_generate_follicles(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Fur Follicles Generate"; + ot->description = "Generate hair follicles for a fur modifier"; + ot->idname = "OBJECT_OT_fur_generate_follicles"; + + /* api callbacks */ + ot->poll = fur_generate_follicles_poll; + ot->invoke = fur_generate_follicles_invoke; + ot->exec = fur_generate_follicles_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); +} |