[Bf-blender-cvs] [5fd5d3c] alembic: Improved relaxation code for strand lengths in hair edit mode.

Lukas Tönne noreply at git.blender.org
Tue May 19 12:01:08 CEST 2015


Commit: 5fd5d3c8b29e6c70d0bede0ca6a001a94c4a3499
Author: Lukas Tönne
Date:   Tue May 19 12:00:35 2015 +0200
Branches: alembic
https://developer.blender.org/rB5fd5d3c8b29e6c70d0bede0ca6a001a94c4a3499

Improved relaxation code for strand lengths in hair edit mode.

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

M	source/blender/blenkernel/intern/editstrands.c
M	source/blender/physics/intern/strands.cpp

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

diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c
index 03871bc..fcf98df 100644
--- a/source/blender/blenkernel/intern/editstrands.c
+++ b/source/blender/blenkernel/intern/editstrands.c
@@ -169,10 +169,14 @@ static void editstrands_calc_segment_lengths(BMesh *bm)
 		BM_ITER_STRANDS_ELEM(v, &iter_strand, root, BM_VERTS_OF_STRAND) {
 			if (vprev) {
 				float length = len_v3v3(v->co, vprev->co);
-				BM_elem_float_data_named_set(&bm->vdata, v, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH, length);
+				BM_elem_float_data_named_set(&bm->vdata, vprev, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH, length);
 			}
 			vprev = v;
 		}
+		if (vprev) {
+			/* set last to 0 */
+			BM_elem_float_data_named_set(&bm->vdata, vprev, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH, 0.0f);
+		}
 	}
 }
 
diff --git a/source/blender/physics/intern/strands.cpp b/source/blender/physics/intern/strands.cpp
index f494856..f8bba6a 100644
--- a/source/blender/physics/intern/strands.cpp
+++ b/source/blender/physics/intern/strands.cpp
@@ -116,11 +116,11 @@ static void strands_adjust_segment_lengths(BMesh *bm)
 	BMIter iter;
 	
 	BM_ITER_STRANDS(root, &iter, bm, BM_STRANDS_OF_MESH) {
-				float base_length = BM_elem_float_data_named_get(&bm->vdata, v, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
 		BMVert *v, *vprev = NULL;
 		BMIter iter_strand;
 		BM_ITER_STRANDS_ELEM(v, &iter_strand, root, BM_VERTS_OF_STRAND) {
 			if (vprev) {
+				float base_length = BM_elem_float_data_named_get(&bm->vdata, vprev, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
 				float dist[3];
 				float length;
 				
@@ -134,10 +134,79 @@ static void strands_adjust_segment_lengths(BMesh *bm)
 	}
 }
 
+static void strands_vertex_relax(BMesh *bm, float relax_factor, const BMVert *vprev, const BMVert *v, const BMVert *vnext, float relax[3])
+{
+	float D_pos[3], D_neg[3];
+	
+	if (vprev) {
+		sub_v3_v3v3(D_neg, vprev->co, v->co);
+		float len = len_v3(D_neg);
+		if (len > 0.0f) {
+			float Lprev = BM_elem_float_data_named_get(&bm->vdata, (void *)vprev, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
+			mul_v3_fl(D_neg, (1.0f - Lprev / len) * relax_factor);
+		}
+		else
+			zero_v3(D_neg);
+	}
+	else
+		zero_v3(D_neg);
+	
+	if (vnext) {
+		sub_v3_v3v3(D_pos, vnext->co, v->co);
+		float len = len_v3(D_pos);
+		if (len > 0.0f) {
+			float L = BM_elem_float_data_named_get(&bm->vdata, (void *)v, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
+			mul_v3_fl(D_pos, (1.0f - L / len) * relax_factor);
+		}
+		else
+			zero_v3(D_pos);
+	}
+	else
+		zero_v3(D_pos);
+	
+	add_v3_v3v3(relax, D_neg, D_pos);
+}
+
+/* single relaxation iteration, must be repeated totkey times for complete relaxation */
+static void strands_relax(BMesh *bm, BMVert *root, bool skip_first)
+{
+	const int numvert = BM_strands_keys_count(root);
+	const float relax_factor = numvert > 0 ? 1.0f / numvert : 0.0f;
+	
+	BMVert *vert_next, *vert = NULL, *vert_prev = NULL;
+	float relax_prev[3], relax[3];
+	BMIter iter;
+	
+	BM_ITER_STRANDS_ELEM(vert_next, &iter, root, BM_VERTS_OF_STRAND) {
+		
+		if (vert) {
+			/* note: relaxation is applied *after* calculating the next segment, so vertex location can be modified safely */
+			strands_vertex_relax(bm, relax_factor, vert_prev, vert, vert_next, relax);
+			
+			/* don't modify fixed root */
+			if (vert_prev && !(skip_first && vert_prev == root)) {
+				add_v3_v3(vert_prev->co, relax_prev);
+			}
+		}
+		
+		vert_prev = vert;
+		vert = vert_next;
+		copy_v3_v3(relax_prev, relax);
+	}
+	
+	/* last segment */
+	{
+		/* don't modify fixed root */
+		if (vert_prev && !(skip_first && vert_prev == root)) {
+			add_v3_v3(vert_prev->co, relax_prev);
+		}
+	}
+}
+
 /* try to find a nice solution to keep distances between neighboring keys */
 /* XXX Stub implementation ported from particles:
  * Successively relax each segment starting from the root,
- * repeat this for every vertex (O(n^2) !!)
+ * repeat this for every vertex (O(n^2))
  * This should be replaced by a more advanced method using a least-squares
  * error metric with length and root location constraints (IK solver)
  */
@@ -153,46 +222,19 @@ static void strands_solve_edge_relaxation(BMEditStrands *edit)
 //		return;
 	
 	BM_ITER_STRANDS(root, &iter, bm, BM_STRANDS_OF_MESH) {
-		const int numvert = BM_strands_keys_count(root);
-		float relax_factor = numvert > 0 ? 1.0f / numvert : 0.0f;
-		
 		BMVert *vj;
 		BMIter iterj;
 		int j;
 		
 		BM_ITER_STRANDS_ELEM_INDEX(vj, &iterj, root, BM_VERTS_OF_STRAND, j) {
-			BMVert *vk, *vk_prev;
-			float lenk, lenk_prev;
-			BMIter iterk;
-			int k;
-			bool skip_first;
 			
-			if (j == 0)
+			if (j < 1)
 				continue;
 			
-			if (true /* XXX particles use PE_LOCK_FIRST option */)
-				skip_first = true;
-			else
-				skip_first = false;
+			/* XXX particles use PE_LOCK_FIRST option */
+			bool skip_first = true;
 			
-			BM_ITER_STRANDS_ELEM_INDEX(vk, &iterk, root, BM_VERTS_OF_STRAND, k) {
-				float dir[3], tlen, relax;
-				
-				lenk = BM_elem_float_data_named_get(&bm->vdata, vk, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
-				
-				if (k > 0) {
-					sub_v3_v3v3(dir, vk->co, vk_prev->co);
-					tlen = normalize_v3(dir);
-					relax = relax_factor * (tlen - lenk_prev);
-					
-					if (!(k == 1 && skip_first))
-						madd_v3_v3fl(vk_prev->co, dir, relax);
-					madd_v3_v3fl(vk->co, dir, -relax);
-				}
-				
-				vk_prev = vk;
-				lenk_prev = lenk;
-			}
+			strands_relax(bm, root, skip_first);
 		}
 	}
 }




More information about the Bf-blender-cvs mailing list