[Bf-blender-cvs] [e421ba71442] hair_guides: Parent indices and weights for hair follicles and a binding function.

Lukas Tönne noreply at git.blender.org
Sat Nov 11 16:57:55 CET 2017


Commit: e421ba714424347aafce96b37bce4caffc9a03bf
Author: Lukas Tönne
Date:   Sat Nov 11 15:57:31 2017 +0000
Branches: hair_guides
https://developer.blender.org/rBe421ba714424347aafce96b37bce4caffc9a03bf

Parent indices and weights for hair follicles and a binding function.

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

M	source/blender/blenkernel/BKE_hair.h
M	source/blender/blenkernel/intern/hair.c
M	source/blender/blenkernel/intern/hair_draw.c
M	source/blender/makesdna/DNA_hair_types.h

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

diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 986cbc3a71b..dc3cc5a1651 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -48,8 +48,6 @@ struct HairSystem* BKE_hair_new(void);
 struct HairSystem* BKE_hair_copy(struct HairSystem *hsys);
 void BKE_hair_free(struct HairSystem *hsys);
 
-void BKE_hair_generate_follicles(struct HairSystem* hsys, unsigned int seed);
-
 /* === Guide Strands === */
 
 void BKE_hair_guide_curves_begin(struct HairSystem *hsys, int totcurves, int totverts);
@@ -59,6 +57,12 @@ void BKE_hair_guide_curves_end(struct HairSystem *hsys);
 
 struct DerivedMesh* BKE_hair_get_scalp(const struct HairSystem *hsys, struct Scene *scene, const struct EvaluationContext *eval_ctx);
 
+/* === Follicles === */
+
+void BKE_hair_generate_follicles(struct HairSystem* hsys, unsigned int seed);
+
+void BKE_hair_bind_follicles(struct HairSystem *hsys, struct Scene *scene);
+
 /* === Draw Cache === */
 
 enum {
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 49c72cd9f8d..3412a0fd805 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -49,6 +49,8 @@
 #include "BKE_mesh_sample.h"
 #include "BKE_hair.h"
 
+#include "DEG_depsgraph.h"
+
 #include "BLT_translation.h"
 
 HairSystem* BKE_hair_new(void)
@@ -136,10 +138,83 @@ void BKE_hair_follicles_generate(HairPattern *hair, DerivedMesh *scalp, int coun
 }
 #endif
 
-#if 0
-BLI_INLINE void verify_fiber_weights(HairFiber *fiber)
+/* ================================= */
+
+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->flag |= HAIR_GUIDE_CURVES_DIRTY;
+	}
+	if (totverts != hsys->totverts)
+	{
+		hsys->verts = MEM_reallocN(hsys->curves, sizeof(HairGuideCurve) * totverts);
+		hsys->flag |= HAIR_GUIDE_VERTS_DIRTY;
+	}
+}
+
+void BKE_hair_set_guide_curve(HairSystem *hsys, int index, const MeshSample *mesh_sample, int numverts)
+{
+	BLI_assert(index <= hsys->totcurves);
+	
+	HairGuideCurve *curve = &hsys->curves[index];
+	memcpy(&curve->mesh_sample, mesh_sample, sizeof(MeshSample));
+	curve->numverts = numverts;
+	
+	hsys->flag |= HAIR_GUIDE_CURVES_DIRTY;
+}
+
+void BKE_hair_set_guide_vertex(HairSystem *hsys, int index, int flag, const float co[3])
+{
+	BLI_assert(index <= hsys->totverts);
+	
+	HairGuideVertex *vertex = &hsys->verts[index];
+	vertex->flag = flag;
+	copy_v3_v3(vertex->co, co);
+	
+	hsys->flag |= HAIR_GUIDE_VERTS_DIRTY;
+}
+
+void BKE_hair_guide_curves_end(HairSystem *hsys)
+{
+	/* Recalculate vertex offsets */
+	if (hsys->flag & HAIR_GUIDE_CURVES_DIRTY)
+	{
+		int vertstart = 0;
+		for (int i = 0; i < hsys->totcurves; ++i)
+		{
+			hsys->curves[i].vertstart = vertstart;
+			vertstart += hsys->curves[i].numverts;
+		}
+	}
+}
+
+DerivedMesh* BKE_hair_get_scalp(const HairSystem *hsys, struct Scene *scene, const struct EvaluationContext *eval_ctx)
 {
-	const float *w = fiber->parent_weight;
+	Object *ob = hsys->guide_object;
+	
+	if (ob)
+	{
+		if (eval_ctx)
+		{
+			CustomDataMask datamask = CD_MASK_BAREMESH;
+			return mesh_get_derived_final(eval_ctx, scene, ob, datamask);
+		}
+		else
+		{
+			return ob->derivedFinal;
+		}
+	}
+	
+	return NULL;
+}
+
+/* ================================= */
+
+BLI_INLINE void hair_fiber_verify_weights(HairFollicle *follicle)
+{
+	const float *w = follicle->parent_weight;
 	
 	BLI_assert(w[0] >= 0.0f && w[1] >= 0.0f && w[2] >= 0.0f && w[3] >= 0.0f);
 	float sum = w[0] + w[1] + w[2] + w[3];
@@ -150,10 +225,10 @@ BLI_INLINE void verify_fiber_weights(HairFiber *fiber)
 	BLI_assert(w[0] >= w[1] && w[1] >= w[2] && w[2] >= w[3]);
 }
 
-static void sort_fiber_weights(HairFiber *fiber)
+static void hair_fiber_sort_weights(HairFollicle *follicle)
 {
-	unsigned int *idx = fiber->parent_index;
-	float *w = fiber->parent_weight;
+	unsigned int *idx = follicle->parent_index;
+	float *w = follicle->parent_weight;
 
 #define FIBERSWAP(a, b) \
 	SWAP(unsigned int, idx[a], idx[b]); \
@@ -175,8 +250,11 @@ static void sort_fiber_weights(HairFiber *fiber)
 #undef FIBERSWAP
 }
 
-static void strand_find_closest(HairFiber *fiber, const float loc[3],
-                                const KDTree *tree, const float (*strandloc)[3])
+static void hair_fiber_find_closest_strand(
+        HairFollicle *follicle,
+        const float loc[3],
+        const KDTree *tree,
+        const float (*strandloc)[3])
 {
 	/* Use the 3 closest strands for interpolation.
 	 * Note that we have up to 4 possible weights, but we
@@ -186,12 +264,12 @@ static void strand_find_closest(HairFiber *fiber, const float loc[3],
 	const float *sloc[3] = {NULL};
 	int k, found = BLI_kdtree_find_nearest_n(tree, loc, nearest, 3);
 	for (k = 0; k < found; ++k) {
-		fiber->parent_index[k] = nearest[k].index;
+		follicle->parent_index[k] = (unsigned int)nearest[k].index;
 		sloc[k] = strandloc[nearest[k].index];
 	}
 	for (; k < 4; ++k) {
-		fiber->parent_index[k] = STRAND_INDEX_NONE;
-		fiber->parent_weight[k] = 0.0f;
+		follicle->parent_index[k] = HAIR_STRAND_INDEX_NONE;
+		follicle->parent_weight[k] = 0.0f;
 	}
 	
 	/* calculate barycentric interpolation weights */
@@ -201,56 +279,42 @@ static void strand_find_closest(HairFiber *fiber, const float loc[3],
 		
 		float w[3];
 		interp_weights_tri_v3(w, sloc[0], sloc[1], sloc[2], closest);
-		copy_v3_v3(fiber->parent_weight, w);
+		copy_v3_v3(follicle->parent_weight, w);
 		/* float precisions issues can cause slightly negative weights */
-		CLAMP3(fiber->parent_weight, 0.0f, 1.0f);
+		CLAMP3(follicle->parent_weight, 0.0f, 1.0f);
 	}
 	else if (found == 2) {
-		fiber->parent_weight[1] = line_point_factor_v3(loc, sloc[0], sloc[1]);
-		fiber->parent_weight[0] = 1.0f - fiber->parent_weight[1];
+		follicle->parent_weight[1] = line_point_factor_v3(loc, sloc[0], sloc[1]);
+		follicle->parent_weight[0] = 1.0f - follicle->parent_weight[1];
 		/* float precisions issues can cause slightly negative weights */
-		CLAMP2(fiber->parent_weight, 0.0f, 1.0f);
+		CLAMP2(follicle->parent_weight, 0.0f, 1.0f);
 	}
 	else if (found == 1) {
-		fiber->parent_weight[0] = 1.0f;
+		follicle->parent_weight[0] = 1.0f;
 	}
 	
-	sort_fiber_weights(fiber);
+	hair_fiber_sort_weights(follicle);
 }
 
-static void strand_calc_root_distance(HairFiber *fiber, const float loc[3], const float nor[3], const float tang[3],
-                                      const float (*strandloc)[3])
+void BKE_hair_bind_follicles(HairSystem *hsys, struct Scene *scene)
 {
-	if (fiber->parent_index[0] == STRAND_INDEX_NONE)
-		return;
-	
-	float cotang[3];
-	cross_v3_v3v3(cotang, nor, tang);
-	
-	const float *sloc0 = strandloc[fiber->parent_index[0]];
-	float dist[3];
-	sub_v3_v3v3(dist, loc, sloc0);
-	fiber->root_distance[0] = dot_v3v3(dist, tang);
-	fiber->root_distance[1] = dot_v3v3(dist, cotang);
-}
-
-static void strands_calc_weights(const HairDrawDataInterface *hairdata, struct DerivedMesh *scalp, HairFiber *fibers, int num_fibers)
-{
-	const int num_strands = hairdata->get_num_strands(hairdata);
+	HairPattern *pattern = hsys->pattern;
+	const int num_strands = hsys->totcurves;
 	if (num_strands == 0)
 		return;
 	
+	EvaluationContext eval_ctx = {0};
+	DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_VIEWPORT);
+	DerivedMesh *scalp = BKE_hair_get_scalp(hsys, scene, &eval_ctx);
+	
 	float (*strandloc)[3] = MEM_mallocN(sizeof(float) * 3 * num_strands, "strand locations");
 	{
-		MeshSample *roots = MEM_mallocN(sizeof(MeshSample) * num_strands, "strand roots");
-		hairdata->get_strand_roots(hairdata, roots);
 		for (int i = 0; i < num_strands; ++i) {
 			float nor[3], tang[3];
-			if (!BKE_mesh_sample_eval(scalp, &roots[i], strandloc[i], nor, tang)) {
+			if (!BKE_mesh_sample_eval(scalp, &hsys->curves[i].mesh_sample, strandloc[i], nor, tang)) {
 				zero_v3(strandloc[i]);
 			}
 		}
-		MEM_freeN(roots);
 	}
 	
 	KDTree *tree = BLI_kdtree_new(num_strands);
@@ -259,15 +323,12 @@ static void strands_calc_weights(const HairDrawDataInterface *hairdata, struct D
 	}
 	BLI_kdtree_balance(tree);
 	
-	HairFiber *fiber = fibers;
-	for (int i = 0; i < num_fibers; ++i, ++fiber) {
+	HairFollicle *follicle = pattern->follicles;
+	for (int i = 0; i < pattern->num_follicles; ++i, ++follicle) {
 		float loc[3], nor[3], tang[3];
-		if (BKE_mesh_sample_eval(scalp, &fiber->root, loc, nor, tang)) {
-			
-			strand_find_closest(fiber, loc, tree, strandloc);
-			verify_fiber_weights(fiber);
-			
-			strand_calc_root_distance(fiber, loc, nor, tang, strandloc);
+		if (BKE_mesh_sample_eval(scalp, &follicle->mesh_sample, loc, nor, tang)) {
+			hair_fiber_find_closest_strand(follicle, loc, tree, strandloc);
+			hair_fiber_verify_weights(follicle);
 		}
 	}
 	
@@ -275,108 +336,3 @@ static void strands_calc_weights(const HairDrawDataInterface *hairdata, struct D
 	MEM_freeN(strandloc);
 }
 
-HairFiber* BKE_hair_fibers_create(const HairDrawDataInterface *hairdata,
-                                  struct DerivedMesh *scalp, unsigned int amount,
-                                  unsigned int seed)
-{
-	MeshSampleGenerator *gen = BKE_mesh_sample_gen_surface_random(scalp, seed);
-	unsigned int i;
-	
-	HairFiber *fibers = MEM_mallocN(sizeof(HairFiber) * amount, "HairFiber");
-	HairFiber *fiber;
-	
-	for (i = 0, fiber = fibers; i < amount; ++i, ++fiber) {
-		if (BKE_mesh_sample_generate(gen, &fiber->root)) {
-			int k;
-			/* influencing control strands are determined later */
-			for (k = 0; k < 4; ++k) {
-				fiber->parent_index[k] = STRAND_INDEX_NONE;
-				fiber->parent_weight[k] = 0.0f;
-			}
-		}
-		else {
-			/* clear remaining samples */
-			memset(fiber, 0, sizeof(HairFiber) * (amount - i));
-			break;
-		}
-	}
-	
-	BKE_mesh_sample_free_generator(gen);
-	
-	strands_calc_weights(hairdata, scalp, fibers, amount);
-	
-	return fibers;
-}
-#endif
-
-/* ================================= */
-
-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);
-		hs

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list