Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_groom.h6
-rw-r--r--source/blender/blenkernel/BKE_hair.h21
-rw-r--r--source/blender/blenkernel/intern/groom.c64
-rw-r--r--source/blender/blenkernel/intern/hair.c49
-rw-r--r--source/blender/editors/groom/groom_hair.c11
-rw-r--r--source/blender/editors/object/object_modifier.c39
-rw-r--r--source/blender/makesdna/DNA_hair_types.h4
7 files changed, 138 insertions, 56 deletions
diff --git a/source/blender/blenkernel/BKE_groom.h b/source/blender/blenkernel/BKE_groom.h
index aa5b9fb53a0..e88513b5480 100644
--- a/source/blender/blenkernel/BKE_groom.h
+++ b/source/blender/blenkernel/BKE_groom.h
@@ -71,7 +71,11 @@ void BKE_groom_bundle_unbind(struct GroomBundle *bundle);
/* === Hair System === */
-void BKE_groom_distribute_follicles(struct Groom *groom, unsigned int seed, int count);
+/* Create follicles and guide curve origins on the scalp surface for hair fiber rendering */
+void BKE_groom_hair_distribute(struct Groom *groom, unsigned int seed, int hair_count, int guide_curve_count);
+
+/* Calculate guide curve shapes based on groom bundle deformation */
+void BKE_groom_hair_update_guide_curves(struct Groom *groom);
/* === Depsgraph evaluation === */
diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 42a09dd756a..01e4d3e0abe 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -53,11 +53,28 @@ void BKE_hair_free(struct HairSystem *hsys);
/* === Guide Strands === */
-void BKE_hair_guide_curves_begin(struct HairSystem *hsys, int totcurves, int totverts);
+/* Allocate buffers for defining guide curves
+ * \param totcurves Number of guide curves to allocate
+ */
+void BKE_hair_guide_curves_begin(struct HairSystem *hsys, int totcurves);
+
+/* Set properties of a guide curve
+ * \param index Index of the guide guide curve
+ * \param mesh_sample Origin of the guide curve on the scalp mesh.
+ * \param numverts Number of vertices in this guide curve
+ */
void BKE_hair_set_guide_curve(struct HairSystem *hsys, int index, const struct MeshSample *mesh_sample, int numverts);
-void BKE_hair_set_guide_vertex(struct HairSystem *hsys, int index, int flag, const float co[3]);
+
+/* Finalize guide curve update */
void BKE_hair_guide_curves_end(struct HairSystem *hsys);
+/* Set properties of a guide curve vertex
+ * \param index Index of the guide curve vertex.
+ * \param flag Flags to set on the vertex.
+ * \param co Location of the vertex in object space.
+ */
+void BKE_hair_set_guide_vertex(struct HairSystem *hsys, int index, int flag, const float co[3]);
+
/* === Follicles === */
/* Calculate surface area of a scalp mesh */
diff --git a/source/blender/blenkernel/intern/groom.c b/source/blender/blenkernel/intern/groom.c
index eae4724f047..e64fd5ca297 100644
--- a/source/blender/blenkernel/intern/groom.c
+++ b/source/blender/blenkernel/intern/groom.c
@@ -495,8 +495,61 @@ void BKE_groom_bundle_unbind(GroomBundle *bundle)
/* === Hair System === */
-void BKE_groom_distribute_follicles(Groom *groom, unsigned int seed, int count)
+/* Distribute points on the scalp to use as guide curve origins,
+ * then interpolate guide curves from bundles
+ */
+static void groom_generate_guide_curves(
+ Groom *groom,
+ DerivedMesh *scalp,
+ unsigned int seed,
+ int guide_curve_count)
+{
+ struct HairSystem *hsys = groom->hair_system;
+
+ MeshSample *guide_samples = MEM_mallocN(sizeof(*guide_samples) * guide_curve_count, "guide samples");
+ int num_guides;
+ {
+ /* Random distribution of points on the scalp mesh */
+
+ float scalp_area = BKE_hair_calc_surface_area(scalp);
+ float density = BKE_hair_calc_density_from_count(scalp_area, guide_curve_count);
+ float min_distance = BKE_hair_calc_min_distance_from_density(density);
+ MeshSampleGenerator *gen = BKE_mesh_sample_gen_surface_poissondisk(
+ seed,
+ min_distance,
+ guide_curve_count,
+ NULL,
+ NULL);
+
+ BKE_mesh_sample_generator_bind(gen, scalp);
+
+ static const bool use_threads = false;
+ num_guides = BKE_mesh_sample_generate_batch_ex(
+ gen,
+ guide_samples,
+ sizeof(MeshSample),
+ guide_curve_count,
+ use_threads);
+
+ BKE_mesh_sample_free_generator(gen);
+ }
+
+ BKE_hair_guide_curves_begin(hsys, num_guides);
+
+ for (int i = 0; i < num_guides; ++i)
+ {
+ BKE_hair_set_guide_curve(hsys, i, &guide_samples[i], );
+ }
+
+ BKE_hair_guide_curves_end(hsys);
+
+ MEM_freeN(guide_samples);
+}
+
+void BKE_groom_hair_distribute(Groom *groom, unsigned int seed, int hair_count, int guide_curve_count)
{
+ struct HairSystem *hsys = groom->hair_system;
+
BLI_assert(groom->scalp_object);
DerivedMesh *scalp = object_get_derived_final(groom->scalp_object, false);
if (!scalp)
@@ -504,7 +557,10 @@ void BKE_groom_distribute_follicles(Groom *groom, unsigned int seed, int count)
return;
}
- BKE_hair_generate_follicles(groom->hair_system, scalp, seed, count);
+ BKE_hair_generate_follicles(hsys, scalp, seed, hair_count);
+
+ unsigned int guide_seed = BLI_ghashutil_combine_hash(seed, BLI_ghashutil_strhash("groom guide curves"));
+ groom_bundle_generate_guide_curves(groom, scalp, guide_seed, guide_curve_count);
}
@@ -768,8 +824,12 @@ void BKE_groom_eval_geometry(const EvaluationContext *UNUSED(eval_ctx), Groom *g
printf("%s on %s\n", __func__, groom->id.name);
}
+ /* calculate curves for interpolating shapes */
BKE_groom_curve_cache_update(groom);
+ /* generate actual guide curves for hair */
+ BKE_groom_hair_update_guide_curves(groom);
+
if (groom->bb == NULL || (groom->bb->flag & BOUNDBOX_DIRTY)) {
BKE_groom_boundbox_calc(groom, NULL, NULL);
}
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 588bd167f41..5a9af8aba58 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -204,21 +204,14 @@ void BKE_hair_generate_follicles(
/* ================================= */
-void BKE_hair_guide_curves_begin(HairSystem *hsys, int totcurves, int totverts)
+void BKE_hair_guide_curves_begin(HairSystem *hsys, int totcurves)
{
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->verts, sizeof(HairGuideVertex) * totverts);
- hsys->totverts = totverts;
-
+ hsys->flag |= HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING;
BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL);
}
}
@@ -231,10 +224,29 @@ void BKE_hair_set_guide_curve(HairSystem *hsys, int index, const MeshSample *mes
memcpy(&curve->mesh_sample, mesh_sample, sizeof(MeshSample));
curve->numverts = numverts;
- hsys->flag |= HAIR_SYSTEM_UPDATE_GUIDE_VERT_OFFSET | HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING;
+ hsys->flag |= HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING;
BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL);
}
+void BKE_hair_guide_curves_end(HairSystem *hsys)
+{
+ /* Recalculate vertex count and start offsets in curves */
+ int vertstart = 0;
+ for (int i = 0; i < hsys->totcurves; ++i)
+ {
+ hsys->curves[i].vertstart = vertstart;
+ vertstart += hsys->curves[i].numverts;
+ }
+
+ if (vertstart != hsys->totverts)
+ {
+ hsys->verts = MEM_reallocN(hsys->verts, sizeof(HairGuideVertex) * vertstart);
+ hsys->totverts = vertstart;
+
+ BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL);
+ }
+}
+
void BKE_hair_set_guide_vertex(HairSystem *hsys, int index, int flag, const float co[3])
{
BLI_assert(index <= hsys->totverts);
@@ -246,23 +258,6 @@ void BKE_hair_set_guide_vertex(HairSystem *hsys, int index, int flag, const floa
BKE_hair_batch_cache_dirty(hsys, BKE_HAIR_BATCH_DIRTY_ALL);
}
-void BKE_hair_guide_curves_end(HairSystem *hsys)
-{
- /* Recalculate vertex offsets */
- if (!(hsys->flag & HAIR_SYSTEM_UPDATE_GUIDE_VERT_OFFSET))
- {
- return;
- }
- hsys->flag &= ~HAIR_SYSTEM_UPDATE_GUIDE_VERT_OFFSET;
-
- int vertstart = 0;
- for (int i = 0; i < hsys->totcurves; ++i)
- {
- hsys->curves[i].vertstart = vertstart;
- vertstart += hsys->curves[i].numverts;
- }
-}
-
/* ================================= */
BLI_INLINE void hair_fiber_verify_weights(HairFollicle *follicle)
diff --git a/source/blender/editors/groom/groom_hair.c b/source/blender/editors/groom/groom_hair.c
index 22664361639..0a179a9b20e 100644
--- a/source/blender/editors/groom/groom_hair.c
+++ b/source/blender/editors/groom/groom_hair.c
@@ -72,7 +72,8 @@ static int hair_distribute_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Groom *groom = ob->data;
- int count = RNA_int_get(op->ptr, "count");
+ int hair_count = RNA_int_get(op->ptr, "hair_count");
+ int guide_curve_count = RNA_int_get(op->ptr, "guide_curve_count");
unsigned int seed = (unsigned int)RNA_int_get(op->ptr, "seed");
if (!groom->scalp_object)
@@ -81,7 +82,7 @@ static int hair_distribute_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_groom_distribute_follicles(groom, seed, count);
+ BKE_groom_hair_distribute(groom, seed, hair_count, guide_curve_count);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -104,8 +105,10 @@ void GROOM_OT_hair_distribute(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "count", 1000, 0, INT_MAX,
- "Count", "Number of follicles to generate", 1, 1e6);
+ RNA_def_int(ot->srna, "hair_count", 1000, 0, INT_MAX,
+ "Hair Count", "Number of hairs to generate", 1, 1e6);
+ RNA_def_int(ot->srna, "guide_curve_count", 10, 0, INT_MAX,
+ "Guide Curve Count", "Number of guide curves to generate", 1, 1e4);
RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX,
"Seed", "Seed value for randomized follicle distribution", 0, INT_MAX);
}
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index bd88330498a..2099ceaa10b 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -2387,29 +2387,34 @@ static void fur_create_guide_curves(struct HairSystem *hsys, unsigned int seed,
{
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);
+ BKE_hair_guide_curves_begin(hsys, totguides);
- madd_v3_v3fl(co, nor, 0.1f);
- BKE_hair_set_guide_vertex(hsys, vertstart + 1, 0, co);
+ MeshSample *sample = buffer;
+ for (int i = 0; i < totguides; ++i, ++sample)
+ {
+ BKE_hair_set_guide_curve(hsys, i, sample, 2);
+ }
- vertstart += numverts;
+ BKE_hair_guide_curves_end(hsys);
}
- BKE_hair_guide_curves_end(hsys);
+ {
+ int vertstart = 0;
+ MeshSample *sample = buffer;
+ for (int i = 0; i < totguides; ++i, ++sample)
+ {
+ 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 += 2;
+ }
+ }
MEM_freeN(buffer);
}
diff --git a/source/blender/makesdna/DNA_hair_types.h b/source/blender/makesdna/DNA_hair_types.h
index 9a42259ec2d..8a95077c7f6 100644
--- a/source/blender/makesdna/DNA_hair_types.h
+++ b/source/blender/makesdna/DNA_hair_types.h
@@ -96,10 +96,8 @@ typedef struct HairSystem {
typedef enum eHairSystemFlag
{
- /* Guide curves vertices have been changed, recalc buffer offsets */
- HAIR_SYSTEM_UPDATE_GUIDE_VERT_OFFSET = (1 << 8),
/* Guide curve positions have changed, rebind hair follicles */
- HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING = (1 << 9),
+ HAIR_SYSTEM_UPDATE_FOLLICLE_BINDING = (1 << 8),
} eHairSystemFlag;
typedef struct HairDrawSettings