Commit: c0c8df3f2cf3ab03cec1f660619b0fe2290caf2a Author: Lukas Tönne Date: Sun Apr 15 09:30:15 2018 +0100 Branches: hair_guides https://developer.blender.org/rBc0c8df3f2cf3ab03cec1f660619b0fe2290caf2a
Initial system for generating guide curves from groom. =================================================================== M source/blender/blenkernel/BKE_groom.h M source/blender/blenkernel/BKE_hair.h M source/blender/blenkernel/intern/groom.c M source/blender/blenkernel/intern/hair.c M source/blender/editors/groom/groom_hair.c M source/blender/editors/object/object_modifier.c M source/blender/makesdna/DNA_hair_types.h =================================================================== diff --git a/source/blender/blenkernel/BKE_groom.h b/source/blender/blenkernel/BKE_groom.h index aa5b9fb53a0..e88513b5480 100644 --- a/source/blender/blenkernel/BKE_groom.h +++ b/source/blender/blenkernel/BKE_groom.h @@ -71,7 +71,11 @@ void BKE_groom_bundle_unbind(struct GroomBundle *bundle); /* === Hair System === */ -void BKE_groom_distribute_follicles(struct Groom *groom, unsigned int seed, int count); +/* Create follicles and guide curve origins on the scalp surface for hair fiber rendering */ +void BKE_groom_hair_distribute(struct Groom *groom, unsigned int seed, int hair_count, int guide_curve_count); + +/* Calculate guide curve shapes based on groom bundle deformation */ +void BKE_groom_hair_update_guide_curves(struct Groom *groom); /* === Depsgraph evaluation === */ diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h index 42a09dd756a..01e4d3e0abe 100644 --- a/source/blender/blenkernel/BKE_hair.h +++ b/source/blender/blenkernel/BKE_hair.h @@ -53,11 +53,28 @@ void BKE_hair_free(struct HairSystem *hsys); /* === Guide Strands === */ -void BKE_hair_guide_curves_begin(struct HairSystem *hsys, int totcurves, int totverts); +/* Allocate buffers for defining guide curves + * \param totcurves Number of guide curves to allocate + */ +void BKE_hair_guide_curves_begin(struct HairSystem *hsys, int totcurves); + +/* Set properties of a guide curve + * \param index Index of the guide guide curve + * \param mesh_sample Origin of the guide curve on the scalp mesh. + * \param numverts Number of vertices in this guide curve + */ void BKE_hair_set_guide_curve(struct HairSystem *hsys, int index, const struct MeshSample *mesh_sample, int numverts); -void BKE_hair_set_guide_vertex(struct HairSystem *hsys, int index, int flag, const float co[3]); + +/* Finalize guide curve update */ void BKE_hair_guide_curves_end(struct HairSystem *hsys); +/* Set properties of a guide curve vertex + * \param index Index of the guide curve vertex. + * \param flag Flags to set on the vertex. + * \param co Location of the vertex in object space. + */ +void BKE_hair_set_guide_vertex(struct HairSystem *hsys, int index, int flag, const float co[3]); + /* === Follicles === */ /* Calculate surface area of a scalp mesh */ diff --git a/source/blender/blenkernel/intern/groom.c b/source/blender/blenkernel/intern/groom.c index eae4724f047..e64fd5ca297 100644 --- a/source/blender/blenkernel/intern/groom.c +++ b/source/blender/blenkernel/intern/groom.c @@ -495,8 +495,61 @@ void BKE_groom_bundle_unbind(GroomBundle *bundle) /* === Hair System === */ -void BKE_groom_distribute_follicles(Groom *groom, unsigned int seed, int count) +/* Distribute points on the scalp to use as guide curve origins, + * then interpolate guide curves from bundles + */ +static void groom_generate_guide_curves( + Groom *groom, + DerivedMesh *scalp, + unsigned int seed, + int guide_curve_count) +{ + struct HairSystem *hsys = groom->hair_system; + + MeshSample *guide_samples = MEM_mallocN(sizeof(*guide_samples) * guide_curve_count, "guide samples"); + int num_guides; + { + /* Random distribution of points on the scalp mesh */ + + float scalp_area = BKE_hair_calc_surface_area(scalp); + float density = BKE_hair_calc_density_from_count(scalp_area, guide_curve_count); + float min_distance = BKE_hair_calc_min_distance_from_density(density); + MeshSampleGenerator *gen = BKE_mesh_sample_gen_surface_poissondisk( + seed, + min_distance, + guide_curve_count, + NULL, + NULL); + + BKE_mesh_sample_generator_bind(gen, scalp); + + static const bool use_threads = false; + num_guides = BKE_mesh_sample_generate_batch_ex( + gen, + guide_samples, + sizeof(MeshSample), + guide_curve_count, + use_threads); + + BKE_mesh_sample_free_generator(gen); + } + + BKE_hair_guide_curves_begin(hsys, num_guides); + + for (int i = 0; i < num_guides; ++i) + { + BKE_hair_set_guide_curve(hsys, i, &guide_samples[i], ); + } + + BKE_hair_guide_curves_end(hsys); + + MEM_freeN(guide_samples); +} + +void BKE_groom_hair_distribute(Groom *groom, unsigned int seed, int hair_count, int guide_curve_count) { + struct HairSystem *hsys = groom->hair_system; + BLI_assert(groom->scalp_object); DerivedMesh *scalp = object_get_derived_final(groom->scalp_object, false); if (!scalp) @@ -504,7 +557,10 @@ void BKE_groom_distribute_follicles(Groom *groom, unsigned int seed, int count) return; } - BKE_hair_generate_follicles(groom->hair_system, scalp, seed, count); + BKE_hair_generate_follicles(hsys, scalp, seed, hair_count); + + unsigned int guide_seed = BLI_ghashutil_combine_hash(seed, BLI_ghashutil_strhash("groom guide curves")); + groom_bundle_generate_guide_curves(groom, scalp, guide_seed, guide_curve_count); } @@ -768,8 +824,12 @@ void BKE_groom_eval_geometry(const EvaluationContext *UNUSED(eval_ctx), Groom *g printf("%s on %s\n", __func__, groom->id.name); } + /* calculate curves for interpolating shapes */ BKE_groom_curve_cache_update(groom); + /* generate actual guide curves for hair */ + BKE_groom_hair_update_guide_curves(groom); + if (groom->bb == NULL || (groom->bb->flag & BOUNDBOX_DIRTY)) { BKE_groom_boundbox_calc(groom, NULL, NULL); } diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 588bd167f41..5a9af8aba58 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -204,21 +204,14 @@ void BKE_hair_generate_follicles( /* ================================= */ -void BKE_hair_guide_curves_begin(HairSystem *hsys, int totcurves, int totverts) +void BKE_hair_guide_curves_begin(HairSystem *hsys, int totcurves) { if (totcurves != hsys->totcurves) { hsys->curves = MEM_reallocN(hsys->curves, sizeof(HairGuideCurve) * totcurves); hsys->totcurves = totcurves; - hsys->flag |= HAIR_SYSTEM_UPDATE_GUIDE_VERT_OFFSET | HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING; - BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL); - } - if (totverts != hsys->totverts) - { - hsys->verts = MEM_reallocN(hsys->verts, sizeof(HairGuideVertex) * totverts); - hsys->totverts = totverts; - + hsys->flag |= HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING; BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL); } } @@ -231,10 +224,29 @@ void BKE_hair_set_guide_curve(HairSystem *hsys, int index, const MeshSample *mes memcpy(&curve->mesh_sample, mesh_sample, sizeof(MeshSample)); curve->numverts = numverts; - hsys->flag |= HAIR_SYSTEM_UPDATE_GUIDE_VERT_OFFSET | HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING; + hsys->flag |= HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING; BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL); } +void BKE_hair_guide_curves_end(HairSystem *hsys) +{ + /* Recalculate vertex count and start offsets in curves */ + int vertstart = 0; + for (int i = 0; i < hsys->totcurves; ++i) + { + hsys->curves[i].vertstart = vertstart; + vertstart += hsys->curves[i].numverts; + } + + if (vertstart != hsys->totverts) + { + hsys->verts = MEM_reallocN(hsys->verts, sizeof(HairGuideVertex) * vertstart); + hsys->totverts = vertstart; + + BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL); + } +} + void BKE_hair_set_guide_vertex(HairSystem *hsys, int index, int flag, const float co[3]) { BLI_assert(index <= hsys->totverts); @@ -246,23 +258,6 @@ void BKE_hair_set_guide_vertex(HairSystem *hsys, int index, int flag, const floa BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL); } -void BKE_hair_guide_curves_end(HairSystem *hsys) -{ - /* Recalculate vertex offsets */ - if (!(hsys->flag & HAIR_SYSTEM_UPDATE_GUIDE_VERT_OFFSET)) - { - return; - } - hsys->flag &= ~HAIR_SYSTEM_UPDATE_GUIDE_VERT_OFFSET; - - int vertstart = 0; - for (int i = 0; i < hsys->totcurves; ++i) - { - hsys->curves[i].vertstart = vertstart; - vertstart += hsys->curves[i].numverts; - } -} - /* ================================= */ BLI_INLINE void hair_fiber_verify_weights(HairFollicle *follicle) diff --git a/source/blender/editors/groom/groom_hair.c b/source/blender/editors/groom/groom_hair.c index 22664361639..0a179a9b20e 100644 --- a/source/blender/editors/groom/groom_hair.c +++ b/source/blender/editors/groom/groom_hair.c @@ -72,7 +72,8 @@ static int hair_distribute_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); Groom *groom = ob->data; - int count = RNA_int_get(op->ptr, "count"); + int hair_count = RNA_int_get(op->ptr, "hair_count"); + int guide_curve_count = RNA_int_get(op->ptr, "guide_curve_count"); unsigned int seed = (unsigned int)RNA_int_get(op->ptr, "seed"); if (!groom->scalp_object) @@ -81,7 +82,7 @@ static int hair_distribute_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_groom_distribute_follicles(groom, seed, count); + BKE_groom_hair_distribute(groom, seed, hair_count, guide_curve_count); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); DEG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -104,8 +105,10 @@ void GROOM_OT_hair_distribute(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "count", 1000, 0, INT_MAX, - "Count", "Number of follicles to generate", 1, 1e6); + RNA_def_int(ot->srna, "hair_count", 1000, 0, INT_MAX, + "Hair Count", "Number of hairs to generate", 1, 1e6); + RNA_def_int(ot->srna, "guide_curve_count", 10, 0, INT_MAX, + "Guide Curve Count", "Number of guide curves to generate", 1, 1e4); RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Seed", "Seed value for randomized follicle distribution", 0, INT_MAX); } diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index bd88330498a..2099ceaa10b 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -2387,29 +2387,34 @@ static void fur_create_guide_curves(struct HairSystem *hsys, unsigned int seed, { MeshSample *buffer = MEM_mallocN(sizeof @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs