[Bf-blender-cvs] [2d4694678a3] hair_guides: Implementation for BKE_hair_get_scalp.

Lukas Tönne noreply at git.blender.org
Sat Nov 11 10:51:50 CET 2017


Commit: 2d4694678a3b7de2ef3986bd4c7c68aa85609320
Author: Lukas Tönne
Date:   Sat Nov 11 09:51:08 2017 +0000
Branches: hair_guides
https://developer.blender.org/rB2d4694678a3b7de2ef3986bd4c7c68aa85609320

Implementation for BKE_hair_get_scalp.

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

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/draw/engines/eevee/eevee_materials.c
M	source/blender/draw/intern/draw_cache_impl_hair.c

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

diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index bb94c7f8802..10eb7020206 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -38,7 +38,10 @@ static const unsigned int HAIR_STRAND_INDEX_NONE = 0xFFFFFFFF;
 
 struct HairFollicle;
 struct HairPattern;
+struct HairSystem;
 struct DerivedMesh;
+struct EvaluationContext;
+struct Scene;
 
 struct HairSystem* BKE_hair_new(void);
 struct HairSystem* BKE_hair_copy(struct HairSystem *hsys);
@@ -48,7 +51,7 @@ void BKE_hair_generate_follicles(struct HairSystem* hsys, unsigned int seed);
 
 /* === Guide Strands === */
 
-struct DerivedMesh* BKE_hair_get_scalp(const struct HairSystem *hsys);
+struct DerivedMesh* BKE_hair_get_scalp(const struct HairSystem *hsys, struct Scene *scene, const struct EvaluationContext *eval_ctx);
 int BKE_hair_get_num_strands(const struct HairSystem *hsys);
 int BKE_hair_get_num_strands_verts(const struct HairSystem *hsys);
 void BKE_hair_get_strand_lengths(const struct HairSystem *hsys, int *r_lengths);
@@ -67,6 +70,7 @@ void BKE_hair_batch_cache_free(struct HairSystem* hsys);
 int* BKE_hair_get_fiber_lengths(const struct HairSystem* hsys, int subdiv);
 void BKE_hair_get_texture_buffer_size(const struct HairSystem* hsys, int subdiv,
                                               int *r_size, int *r_strand_map_start, int *r_strand_vertex_start, int *r_fiber_start);
-void BKE_hair_get_texture_buffer(const struct HairSystem* hsys, int subdiv, void *texbuffer);
+void BKE_hair_get_texture_buffer(const struct HairSystem* hsys, struct Scene *scene,
+                                 struct EvaluationContext *eval_ctx, int subdiv, void *texbuffer);
 
 #endif
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index f904ff1e8c0..a268803fe25 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -43,6 +43,7 @@
 #include "BLI_string_utils.h"
 
 #include "DNA_hair_types.h"
+#include "DNA_object_types.h"
 
 #include "BKE_DerivedMesh.h"
 #include "BKE_mesh_sample.h"
@@ -135,4 +136,197 @@ void BKE_hair_follicles_generate(HairPattern *hair, DerivedMesh *scalp, int coun
 }
 #endif
 
+#if 0
+BLI_INLINE void verify_fiber_weights(HairFiber *fiber)
+{
+	const float *w = fiber->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];
+	float epsilon = 1.0e-2;
+	BLI_assert(sum > 1.0f - epsilon && sum < 1.0f + epsilon);
+	UNUSED_VARS(sum, epsilon);
+	
+	BLI_assert(w[0] >= w[1] && w[1] >= w[2] && w[2] >= w[3]);
+}
+
+static void sort_fiber_weights(HairFiber *fiber)
+{
+	unsigned int *idx = fiber->parent_index;
+	float *w = fiber->parent_weight;
+
+#define FIBERSWAP(a, b) \
+	SWAP(unsigned int, idx[a], idx[b]); \
+	SWAP(float, w[a], w[b]);
+
+	for (int k = 0; k < 3; ++k) {
+		int maxi = k;
+		float maxw = w[k];
+		for (int i = k+1; i < 4; ++i) {
+			if (w[i] > maxw) {
+				maxi = i;
+				maxw = w[i];
+			}
+		}
+		if (maxi != k)
+			FIBERSWAP(k, maxi);
+	}
+	
+#undef FIBERSWAP
+}
+
+static void strand_find_closest(HairFiber *fiber, 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
+	 * only look for a triangle with this method.
+	 */
+	KDTreeNearest nearest[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;
+		sloc[k] = strandloc[nearest[k].index];
+	}
+	for (; k < 4; ++k) {
+		fiber->parent_index[k] = STRAND_INDEX_NONE;
+		fiber->parent_weight[k] = 0.0f;
+	}
+	
+	/* calculate barycentric interpolation weights */
+	if (found == 3) {
+		float closest[3];
+		closest_on_tri_to_point_v3(closest, loc, sloc[0], sloc[1], sloc[2]);
+		
+		float w[3];
+		interp_weights_tri_v3(w, sloc[0], sloc[1], sloc[2], closest);
+		copy_v3_v3(fiber->parent_weight, w);
+		/* float precisions issues can cause slightly negative weights */
+		CLAMP3(fiber->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];
+		/* float precisions issues can cause slightly negative weights */
+		CLAMP2(fiber->parent_weight, 0.0f, 1.0f);
+	}
+	else if (found == 1) {
+		fiber->parent_weight[0] = 1.0f;
+	}
+	
+	sort_fiber_weights(fiber);
+}
+
+static void strand_calc_root_distance(HairFiber *fiber, const float loc[3], const float nor[3], const float tang[3],
+                                      const float (*strandloc)[3])
+{
+	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);
+	if (num_strands == 0)
+		return;
+	
+	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)) {
+				zero_v3(strandloc[i]);
+			}
+		}
+		MEM_freeN(roots);
+	}
+	
+	KDTree *tree = BLI_kdtree_new(num_strands);
+	for (int c = 0; c < num_strands; ++c) {
+		BLI_kdtree_insert(tree, c, strandloc[c]);
+	}
+	BLI_kdtree_balance(tree);
+	
+	HairFiber *fiber = fibers;
+	for (int i = 0; i < num_fibers; ++i, ++fiber) {
+		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);
+		}
+	}
+	
+	BLI_kdtree_free(tree);
+	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
+
 /* ================================= */
+
+DerivedMesh* BKE_hair_get_scalp(const HairSystem *hsys, struct Scene *scene, const struct EvaluationContext *eval_ctx)
+{
+	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;
+}
diff --git a/source/blender/blenkernel/intern/hair_draw.c b/source/blender/blenkernel/intern/hair_draw.c
index 352c444fabf..0b21612d539 100644
--- a/source/blender/blenkernel/intern/hair_draw.c
+++ b/source/blender/blenkernel/intern/hair_draw.c
@@ -43,221 +43,6 @@
 #include "BKE_mesh_sample.h"
 #include "BKE_hair.h"
 
-#if 0
-bool BKE_hair_fiber_get_location(const HairFiber *fiber, DerivedMesh *root_dm, float loc[3])
-{
-	float nor[3], tang[3];
-	if (BKE_mesh_sample_eval(root_dm, &fiber->root, loc, nor, tang)) {
-		return true;
-	}
-	else {
-		zero_v3(loc);
-		return false;
-	}
-}
-
-bool BKE_hair_fiber_get_vectors(const HairFiber *fiber, DerivedMesh *root_dm,
-                                float loc[3], float nor[3], float tang[3])
-{
-	if (BKE_mesh_sample_eval(root_dm, &fiber->root, loc, nor, tang)) {
-		return true;
-	}
-	else {
-		zero_v3(loc);
-		zero_v3(nor);
-		zero_v3(tang);
-		return false;
-	}
-}
-
-bool BKE_hair_fiber_get_matrix(const HairFiber *fiber, DerivedMesh *root_dm, float mat[4][4])
-{
-	if (BKE_mesh_sample_eval(root_dm, &fiber->root, mat[3], mat[2], mat[0])) {
-		cross_v3_v3v3(mat[1], mat[2], mat[0]);
-		mat[0][3] = 0.0f;
-		mat[1][3] = 0.0f;
-		mat[2][3] = 0.0f;
-		mat[3][3] = 1.0f;
-		return true;
-	}
-	else {
-		unit_m4(mat);
-		return false;
-	}
-}
-
-BLI_INLINE void verify_fiber_weights(HairFiber *fiber)
-{
-	const float *w = fiber->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];
-	float epsilon = 1.0e-2;
-	BLI_assert(sum > 1.0f - epsilon && sum < 1.0f + epsilon);
-	UNUSED_VARS(sum, epsilon);
-	
-	BLI_assert(w[0] >= w[1] && w[1] >= w[2] && w[2] >= w[3]);
-}
-
-static void sort_fiber_weights(HairFiber *fiber)
-{
-	unsigned int *idx = fiber->parent_index;
-	float *w = fiber->parent_weight;
-
-#define FIBERSWAP(a, b) \
-	SWAP(unsigned int, idx[a], idx[b]); \
-	SWAP(float, w[a], w[b]);
-
-	for (int k = 0; k < 3; ++k) {
-		int maxi = k;
-		float maxw = w[k];
-		for (int i = k+1; i < 4; ++i) {
-			if (w[i] > maxw) {
-				maxi = i;
-				maxw = w[i];
-			}
-		}
-		if (maxi != k)
-			FIBERSWAP(k, maxi);
-	}
-	
-#undef FIBERSWAP
-}
-
-static void strand_find_closest(HairFiber *fiber, 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
-	 * only look 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list