[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