[Bf-blender-cvs] [c0c8df3f2cf] hair_guides: Initial system for generating guide curves from groom.

Lukas Tönne noreply at git.blender.org
Sun Apr 15 10:30:43 CEST 2018


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. @@



More information about the Bf-blender-cvs mailing list