[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