[Bf-blender-cvs] [acda535] temp_hair_flow: Simple hair strand integration function for the flow operator.
Lukas Tönne
noreply at git.blender.org
Wed Jan 7 19:37:41 CET 2015
Commit: acda5357663fa18c01c40660ee457aa529558193
Author: Lukas Tönne
Date: Tue Jan 6 18:10:06 2015 +0100
Branches: temp_hair_flow
https://developer.blender.org/rBacda5357663fa18c01c40660ee457aa529558193
Simple hair strand integration function for the flow operator.
===================================================================
M source/blender/editors/hair/hair_flow.c
M source/blender/physics/BPH_strands.h
M source/blender/physics/intern/hair_flow.cpp
===================================================================
diff --git a/source/blender/editors/hair/hair_flow.c b/source/blender/editors/hair/hair_flow.c
index 1c34b1c..2185e3d 100644
--- a/source/blender/editors/hair/hair_flow.c
+++ b/source/blender/editors/hair/hair_flow.c
@@ -62,13 +62,21 @@ static int hair_solve_flow_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
BMEditStrands *edit = BKE_editstrands_from_object(ob);
-// HairEditSettings *settings = &scene->toolsettings->hair_edit;
- struct HairFlowData *data = BPH_strands_solve_hair_flow(scene, ob);
-
- BPH_strands_sample_hair_flow(ob, edit, data);
+ unsigned int seed = 111;
+ int max_strands = RNA_int_get(op->ptr, "max_strands");
+ float max_length = RNA_float_get(op->ptr, "max_length");
+ int segments = RNA_int_get(op->ptr, "segments");
- BPH_strands_free_hair_flow(data);
+ struct HairFlowData *data = BPH_strands_solve_hair_flow(scene, ob);
+ if (data) {
+ /* remove existing hair strands */
+ BM_mesh_clear(edit->bm);
+ /* generate new hair strands */
+ BPH_strands_sample_hair_flow(ob, edit, data, seed, max_strands, max_length, segments);
+
+ BPH_strands_free_hair_flow(data);
+ }
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | NA_SELECTED, ob);
@@ -88,4 +96,8 @@ void HAIR_OT_solve_flow(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "max_strands", 1, 1, INT_MAX, "Strands", "Maximum number of strands to generate", 1, 100000);
+ RNA_def_float(ot->srna, "max_length", 1.0f, 0.0f, FLT_MAX, "Length", "Maximum length of strands", 0.0001f, 10000.0f);
+ RNA_def_int(ot->srna, "segments", 5, 1, INT_MAX, "Segments", "Number of segments per strand", 1, 100);
}
diff --git a/source/blender/physics/BPH_strands.h b/source/blender/physics/BPH_strands.h
index 160df95..8c7c182 100644
--- a/source/blender/physics/BPH_strands.h
+++ b/source/blender/physics/BPH_strands.h
@@ -45,7 +45,8 @@ struct HairFlowData;
struct HairFlowData *BPH_strands_solve_hair_flow(struct Scene *scene, struct Object *ob);
void BPH_strands_free_hair_flow(struct HairFlowData *data);
-void BPH_strands_sample_hair_flow(struct Object *ob, struct BMEditStrands *edit, struct HairFlowData *data);
+void BPH_strands_sample_hair_flow(struct Object *ob, struct BMEditStrands *edit, struct HairFlowData *data,
+ unsigned int seed, int max_strands, float max_length, int segments);
#ifdef __cplusplus
}
diff --git a/source/blender/physics/intern/hair_flow.cpp b/source/blender/physics/intern/hair_flow.cpp
index f39b104..a0f76a3 100644
--- a/source/blender/physics/intern/hair_flow.cpp
+++ b/source/blender/physics/intern/hair_flow.cpp
@@ -35,10 +35,15 @@ extern "C" {
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_editstrands.h"
#include "BKE_effect.h"
+#include "BKE_mesh_sample.h"
+
+#include "bmesh.h"
}
#include "BPH_strands.h"
@@ -47,18 +52,128 @@ extern "C" {
#include "eigen_utils.h"
struct HairFlowData {
+ float cellsize;
};
HairFlowData *BPH_strands_solve_hair_flow(Scene *scene, Object *ob)
{
- return NULL;
+ /* XXX just a dummy for now ... */
+ HairFlowData *data = (HairFlowData *)MEM_callocN(sizeof(HairFlowData), "hair flow data");
+
+ data->cellsize = 100.0f;
+
+ return data;
}
void BPH_strands_free_hair_flow(HairFlowData *data)
{
+ MEM_freeN(data);
}
-void BPH_strands_sample_hair_flow(Object *ob, BMEditStrands *edit, HairFlowData *data)
+BLI_INLINE void construct_m4_loc_nor_tan(float mat[4][4], const float loc[3], const float nor[3], const float tang[3])
{
+ float cotang[3];
+
+ cross_v3_v3v3(cotang, nor, tang);
+
+ copy_v3_v3(mat[0], tang);
+ copy_v3_v3(mat[1], cotang);
+ copy_v3_v3(mat[2], nor);
+ copy_v3_v3(mat[3], loc);
+ mat[0][3] = 0.0f;
+ mat[1][3] = 0.0f;
+ mat[2][3] = 0.0f;
+ mat[3][3] = 1.0f;
+}
+
+static void sample_hair_strand(Object *UNUSED(ob), BMEditStrands *edit, HairFlowData *data,
+ MSurfaceSample *sample, float max_length, int segments,
+ float dt)
+{
+ DerivedMesh *dm = edit->root_dm;
+ const float inv_dt = 1.0f / dt;
+
+ float co[3], dir[3];
+ BMVert *root, *v;
+
+ const float seglen = max_length / (float)segments;
+ float t, tseg;
+ int numseg;
+
+ {
+ float tang[3];
+ BKE_mesh_sample_eval(dm, sample, co, dir, tang);
+ }
+
+ root = BM_strands_create(edit->bm, segments + 1, true);
+
+ BM_elem_meshsample_data_named_set(&edit->bm->vdata, root, CD_MSURFACE_SAMPLE, CD_HAIR_ROOT_LOCATION, sample);
+
+ t = 0.0f;
+ numseg = 0;
+ tseg = 0.0f;
+ v = root;
+
+ while (v && t < max_length) {
+ float nt = t + dt;
+ float prev_co[3];
+
+ /* TODO evaluate direction */
+ //dir = grid_dir(co);
+
+ /* forward integrate position */
+ copy_v3_v3(prev_co, co);
+ madd_v3_v3fl(co, dir, dt);
+
+ while (v && tseg <= nt) {
+ float vt;
+
+ /* interpolate vertex position */
+ vt = (tseg - t) * inv_dt;
+ interp_v3_v3v3(v->co, prev_co, co, vt);
+
+ tseg += seglen;
+ ++numseg;
+ v = BM_strands_vert_next(v);
+ }
+
+ t = nt;
+ }
+ /* make sure all potentially remaining verts have a valid location */
+ while (v) {
+ copy_v3_v3(v->co, co);
+
+ v = BM_strands_vert_next(v);
+ }
+}
+
+void BPH_strands_sample_hair_flow(Object *ob, BMEditStrands *edit, HairFlowData *data,
+ unsigned int seed, int max_strands, float max_length, int segments)
+{
+ MSurfaceSampleStorage storage;
+ MSurfaceSample *samples;
+ int tot, i;
+ float dt;
+
+ BLI_assert(segments >= 1);
+
+ if (!ob->derivedFinal)
+ return;
+
+ /* integration step size */
+ dt = min_ff(0.5f * data->cellsize, max_length / (float)segments);
+
+ samples = (MSurfaceSample *)MEM_mallocN(sizeof(MSurfaceSample) * max_strands, "hair flow sampling origins");
+ BKE_mesh_sample_storage_array(&storage, samples, max_strands);
+
+ tot = BKE_mesh_sample_generate_random(&storage, ob->derivedFinal, seed, max_strands);
+
+ for (i = 0; i < tot; ++i) {
+ sample_hair_strand(ob, edit, data, &samples[i], max_length, segments, dt);
+ }
+
+ BKE_mesh_sample_storage_release(&storage);
+ MEM_freeN(samples);
+ BM_mesh_elem_index_ensure(edit->bm, BM_ALL);
}
More information about the Bf-blender-cvs
mailing list