[Bf-blender-cvs] [4276d302f6b] hair_guides: Follicle generation function for hair systems.

Lukas Tönne noreply at git.blender.org
Thu Nov 16 10:20:34 CET 2017


Commit: 4276d302f6b12c50c12d11dcb4b511ae2df6ac55
Author: Lukas Tönne
Date:   Thu Nov 16 09:20:14 2017 +0000
Branches: hair_guides
https://developer.blender.org/rB4276d302f6b12c50c12d11dcb4b511ae2df6ac55

Follicle generation function for hair systems.

===================================================================

M	source/blender/blenkernel/BKE_hair.h
M	source/blender/blenkernel/intern/hair.c
M	source/blender/makesrna/intern/rna_hair.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 5ed15566673..f321a168ef2 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -59,7 +59,20 @@ void BKE_hair_guide_curves_end(struct HairSystem *hsys);
 
 /* === Follicles === */
 
-void BKE_hair_generate_follicles(struct HairSystem* hsys, unsigned int seed);
+/* Calculate surface area of a scalp mesh */
+float BKE_hair_calc_surface_area(struct DerivedMesh *scalp);
+/* Calculate a density value based on surface area and count */
+float BKE_hair_calc_density_from_count(float area, int count);
+/* Calculate a density value based on a minimum distance */
+float BKE_hair_calc_density_from_min_distance(float min_distance);
+
+/* Distribute hair follicles on a scalp mesh */
+void BKE_hair_generate_follicles(
+        struct HairSystem* hsys,
+        struct DerivedMesh *scalp,
+        unsigned int seed,
+        float min_distance,
+        int max_count);
 
 void BKE_hair_bind_follicles(struct HairSystem *hsys, struct DerivedMesh *scalp);
 
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index ef45f4f3131..c2e9bbba0eb 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -46,8 +46,9 @@
 #include "DNA_object_types.h"
 
 #include "BKE_DerivedMesh.h"
-#include "BKE_mesh_sample.h"
 #include "BKE_hair.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_sample.h"
 
 #include "BLT_translation.h"
 
@@ -55,6 +56,8 @@ HairSystem* BKE_hair_new(void)
 {
 	HairSystem *hair = MEM_callocN(sizeof(HairSystem), "hair system");
 	
+	hair->pattern = MEM_callocN(sizeof(HairPattern), "hair pattern");
+	
 	return hair;
 }
 
@@ -141,6 +144,78 @@ void BKE_hair_follicles_generate(HairPattern *hair, DerivedMesh *scalp, int coun
 }
 #endif
 
+/* Calculate surface area of a scalp mesh */
+float BKE_hair_calc_surface_area(struct DerivedMesh *scalp)
+{
+	BLI_assert(scalp != NULL);
+	
+	int numpolys = scalp->getNumPolys(scalp);
+	MPoly *mpolys = scalp->getPolyArray(scalp);
+	MLoop *mloops = scalp->getLoopArray(scalp);
+	MVert *mverts = scalp->getVertArray(scalp);
+
+	float area = 0.0f;
+	for (int i = 0; i < numpolys; ++i)
+	{
+		area += BKE_mesh_calc_poly_area(&mpolys[i], mloops + mpolys[i].loopstart, mverts);
+	}
+	return area;
+}
+
+/* Calculate a density value based on surface area and count */
+float BKE_hair_calc_density_from_count(float area, int count)
+{
+	return area > 0.0f ? count / area : 0.0f;
+}
+
+/* Calculate a density value based on a minimum distance */
+float BKE_hair_calc_density_from_min_distance(float min_distance)
+{
+	// max. circle packing density (sans pi factor): 1 / (2 * sqrt(3))
+	static const float max_factor = 0.288675135;
+	
+	return min_distance > 0.0f ? max_factor / (min_distance * min_distance) : 0.0f;
+}
+
+/* Distribute hair follicles on a scalp mesh */
+void BKE_hair_generate_follicles(
+        HairSystem* hsys,
+        struct DerivedMesh *scalp,
+        unsigned int seed,
+        float min_distance,
+        int max_count)
+{
+	HairPattern *pattern = hsys->pattern;
+	
+	// Limit max_count to theoretical limit based on area
+	float scalp_area = BKE_hair_calc_surface_area(scalp);
+	float density = BKE_hair_calc_density_from_min_distance(min_distance);
+	max_count = min_ii(max_count, (int)(density * scalp_area));
+	
+	if (pattern->follicles)
+	{
+		MEM_freeN(pattern->follicles);
+	}
+	pattern->follicles = MEM_callocN(sizeof(HairFollicle) * max_count, "hair follicles");
+	
+	{
+		MeshSampleGenerator *gen = BKE_mesh_sample_gen_surface_poissondisk(seed, min_distance, max_count, NULL, NULL);
+		
+		BKE_mesh_sample_generator_bind(gen, scalp);
+		
+		pattern->num_follicles = BKE_mesh_sample_generate_batch_ex(
+		            gen,
+		            &pattern->follicles->mesh_sample,
+		            sizeof(HairFollicle),
+		            max_count,
+		            true);
+		
+		BKE_mesh_sample_free_generator(gen);
+	}
+	
+	BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL);
+}
+
 /* ================================= */
 
 void BKE_hair_guide_curves_begin(HairSystem *hsys, int totcurves, int totverts)
diff --git a/source/blender/makesrna/intern/rna_hair.c b/source/blender/makesrna/intern/rna_hair.c
index 559141c239d..0f9c38c4a6b 100644
--- a/source/blender/makesrna/intern/rna_hair.c
+++ b/source/blender/makesrna/intern/rna_hair.c
@@ -41,11 +41,13 @@
 
 #include "BLI_listbase.h"
 
-#include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 
+#include "BKE_context.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_hair.h"
 #include "BKE_main.h"
+
 #include "DEG_depsgraph.h"
 
 #include "RNA_access.h"
@@ -53,6 +55,29 @@
 #include "WM_api.h"
 #include "WM_types.h"
 
+static void rna_HairSystem_generate_follicles(
+        HairSystem *hsys,
+        struct bContext *C,
+        Object *scalp,
+        int seed,
+        float min_distance,
+        int max_count)
+{
+	if (!scalp)
+	{
+		return;
+	}
+	
+	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, scalp, datamask);
+	
+	BKE_hair_generate_follicles(hsys, dm, (unsigned int)seed, min_distance, max_count);
+}
+
 #else
 
 static void rna_def_hair_follicle(BlenderRNA *brna)
@@ -87,7 +112,8 @@ static void rna_def_hair_pattern(BlenderRNA *brna)
 static void rna_def_hair_system(BlenderRNA *brna)
 {
 	StructRNA *srna;
-	PropertyRNA *prop;
+	FunctionRNA *func;
+	PropertyRNA *prop, *parm;
 	
 	srna = RNA_def_struct(brna, "HairSystem", NULL);
 	RNA_def_struct_ui_text(srna, "Hair System", "Hair rendering and deformation data");
@@ -97,6 +123,15 @@ static void rna_def_hair_system(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "pattern", PROP_POINTER, PROP_NONE);
 	RNA_def_property_struct_type(prop, "HairPattern");
 	RNA_def_property_ui_text(prop, "Pattern", "Hair pattern");
+	
+	func = RNA_def_function(srna, "generate_follicles", "rna_HairSystem_generate_follicles");
+	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+	parm = RNA_def_pointer(func, "scalp", "Object", "Scalp", "Scalp object on which to place hair follicles");
+	RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+	parm = RNA_def_int(func, "seed", 0, 0, INT_MAX, "Seed", "Seed value for random numbers", 0, INT_MAX);
+	parm = RNA_def_float(func, "min_distance", 0.01f, 0.0f, FLT_MAX, "Min Distance", "Minimum distance between follicles", 1.0e-5f, 1.0f);
+	RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+	parm = RNA_def_int(func, "max_count", 0, 0, INT_MAX, "Max Count", "Maximum number of follicles to generate", 1, 1e5);
 }
 
 void RNA_def_hair(BlenderRNA *brna)



More information about the Bf-blender-cvs mailing list