[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