[Bf-blender-cvs] [2d241893698] hair_guides: Extend the fur generate modifier to also create guide curves.

Lukas Tönne noreply at git.blender.org
Thu Nov 23 21:29:31 CET 2017


Commit: 2d24189369815aff49c61c01faac3fe83d68d167
Author: Lukas Tönne
Date:   Thu Nov 23 20:29:08 2017 +0000
Branches: hair_guides
https://developer.blender.org/rB2d24189369815aff49c61c01faac3fe83d68d167

Extend the fur generate modifier to also create guide curves.

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

M	release/scripts/startup/bl_ui/properties_data_modifier.py
M	source/blender/blenkernel/BKE_hair.h
M	source/blender/blenkernel/intern/hair.c
M	source/blender/editors/object/object_modifier.c
M	source/blender/makesdna/DNA_modifier_types.h
M	source/blender/makesrna/intern/rna_modifier.c

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

diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 81338efc807..1fcd69983d0 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -1550,9 +1550,17 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
         col.prop(md, "follicle_seed")
         col.prop(md, "follicle_min_distance")
         col.prop(md, "follicle_max_count")
-        col.operator("object.fur_generate_follicles", text="Generate")
 
         col = split.column()
+        col.label("Guide Curves:")
+        col.prop(md, "guides_count")
+
+        col = layout.column()
+        col.operator("object.fur_generate_follicles", text="Generate")
+
+        col.separator()
+
+        col = layout.column()
         col.label("Drawing:")
         ds = md.draw_settings
         col.prop(ds, "follicle_mode", expand=True)
diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 48200a68dfb..4d57f7e5462 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -62,10 +62,16 @@ void BKE_hair_guide_curves_end(struct HairSystem *hsys);
 
 /* 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 */
+
+/* Calculate a density value based on surface area and sample count */
 float BKE_hair_calc_density_from_count(float area, int count);
+/* Calculate maximum sample count based on surface area and density */
+int BKE_hair_calc_max_count_from_density(float area, float density);
+
 /* Calculate a density value based on a minimum distance */
 float BKE_hair_calc_density_from_min_distance(float min_distance);
+/* Calculate a minimum distance based on density */
+float BKE_hair_calc_min_distance_from_density(float density);
 
 /* Distribute hair follicles on a scalp mesh */
 void BKE_hair_generate_follicles(
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 3df3a430a73..3785759eb57 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -71,6 +71,15 @@ HairSystem* BKE_hair_copy(HairSystem *hsys)
 		nhsys->pattern->follicles = MEM_dupallocN(hsys->pattern->follicles);
 	}
 	
+	if (hsys->curves)
+	{
+		nhsys->curves = MEM_dupallocN(hsys->curves);
+	}
+	if (hsys->verts)
+	{
+		nhsys->verts = MEM_dupallocN(hsys->verts);
+	}
+	
 	nhsys->draw_batch_cache = NULL;
 	nhsys->draw_texture_cache = NULL;
 	
@@ -81,6 +90,15 @@ void BKE_hair_free(HairSystem *hsys)
 {
 	BKE_hair_batch_cache_free(hsys);
 	
+	if (hsys->curves)
+	{
+		MEM_freeN(hsys->curves);
+	}
+	if (hsys->verts)
+	{
+		MEM_freeN(hsys->verts);
+	}
+	
 	if (hsys->pattern)
 	{
 		if (hsys->pattern->follicles)
@@ -111,12 +129,18 @@ float BKE_hair_calc_surface_area(struct DerivedMesh *scalp)
 	return area;
 }
 
-/* Calculate a density value based on surface area and count */
+/* Calculate a density value based on surface area and sample count */
 float BKE_hair_calc_density_from_count(float area, int count)
 {
 	return area > 0.0f ? count / area : 0.0f;
 }
 
+/* Calculate maximum sample count based on surface area and density */
+int BKE_hair_calc_max_count_from_density(float area, float density)
+{
+	return (int)(density * area);
+}
+
 /* Calculate a density value based on a minimum distance */
 float BKE_hair_calc_density_from_min_distance(float min_distance)
 {
@@ -126,6 +150,15 @@ float BKE_hair_calc_density_from_min_distance(float min_distance)
 	return min_distance > 0.0f ? max_factor / (min_distance * min_distance) : 0.0f;
 }
 
+/* Calculate a minimum distance based on density */
+float BKE_hair_calc_min_distance_from_density(float density)
+{
+	// max. circle packing density (sans pi factor): 1 / (2 * sqrt(3))
+	static const float max_factor = 0.288675135;
+	
+	return density > 0.0f ? sqrt(max_factor / density) : 0.0f;
+}
+
 /* Distribute hair follicles on a scalp mesh */
 void BKE_hair_generate_follicles(
         HairSystem* hsys,
@@ -174,13 +207,15 @@ void BKE_hair_guide_curves_begin(HairSystem *hsys, int totcurves, int totverts)
 	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->curves, sizeof(HairGuideCurve) * totverts);
+		hsys->verts = MEM_reallocN(hsys->verts, sizeof(HairGuideVertex) * totverts);
+		hsys->totverts = totverts;
 
 		BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL);
 	}
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 934120730bd..63226828853 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -64,6 +64,7 @@
 #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"
@@ -2374,6 +2375,50 @@ void OBJECT_OT_surfacedeform_bind(wmOperatorType *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);
+		int totverts = 2 * totguides; // TODO
+		
+		BKE_hair_guide_curves_begin(hsys, totguides, totverts);
+		
+		MeshSample *sample = buffer;
+		int vertstart = 0;
+		for (int i = 0; i < totguides; ++i, ++sample)
+		{
+			int numverts = 2; // TODO
+			
+			BKE_hair_set_guide_curve(hsys, i, sample, numverts);
+			
+			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 += numverts;
+		}
+		
+		BKE_hair_guide_curves_end(hsys);
+		
+		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);
@@ -2403,6 +2448,15 @@ static int fur_generate_follicles_exec(bContext *C, wmOperator *op)
 	            fmd->follicle_min_distance,
 	            fmd->follicle_max_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);
 
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 38270f47445..ebb5d5e0351 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -1641,7 +1641,8 @@ typedef struct FurModifierData {
 	int follicle_seed;
 	float follicle_min_distance;
 	int follicle_max_count;
-	int pad2;
+
+	int guides_count;
 } FurModifierData;
 
 #endif  /* __DNA_MODIFIER_TYPES_H__ */
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 43480f0d8f6..ae818c56e4b 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -4826,6 +4826,12 @@ static void rna_def_modifier_fur(BlenderRNA *brna)
 	RNA_def_property_ui_range(prop, 1, 1e5, 1, 1);
 	RNA_def_property_ui_text(prop, "Max Count", "Maximum follicle number");
 	
+	prop = RNA_def_property(srna, "guides_count", PROP_INT, PROP_NONE);
+	RNA_def_property_int_default(prop, 100);
+	RNA_def_property_range(prop, 0, INT_MAX);
+	RNA_def_property_ui_range(prop, 1, 1e3, 1, 1);
+	RNA_def_property_ui_text(prop, "Guides Count", "Number of guide curves");
+	
 	prop = RNA_def_property(srna, "draw_settings", PROP_POINTER, PROP_NONE);
 	RNA_def_property_ui_text(prop, "Draw Settings", "Hair draw settings");
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);



More information about the Bf-blender-cvs mailing list