[Bf-blender-cvs] [a85c9b2] strand_editmode: Corrected implementation of the strand relaxation method ported from particles.

Lukas Tönne noreply at git.blender.org
Sun Apr 17 15:10:00 CEST 2016


Commit: a85c9b241af2c37905072caa77b0f17f941a233d
Author: Lukas Tönne
Date:   Sun Apr 17 15:08:46 2016 +0200
Branches: strand_editmode
https://developer.blender.org/rBa85c9b241af2c37905072caa77b0f17f941a233d

Corrected implementation of the strand relaxation method ported from particles.

This is still the same algorithm as in particle edit mode, but cleaned up
some unnecessary complications and use much more meaningful variable names.

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

M	source/blender/bmesh/intern/bmesh_strands.c
M	source/blender/bmesh/intern/bmesh_strands.h
M	source/blender/physics/intern/strands.cpp

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

diff --git a/source/blender/bmesh/intern/bmesh_strands.c b/source/blender/bmesh/intern/bmesh_strands.c
index ec1b778..8747771 100644
--- a/source/blender/bmesh/intern/bmesh_strands.c
+++ b/source/blender/bmesh/intern/bmesh_strands.c
@@ -116,6 +116,19 @@ int BM_strands_keys_count(BMVert *root)
 	return count;
 }
 
+int BM_strands_keys_count_max(BMesh *bm)
+{
+	BMVert *v;
+	BMIter iter;
+	int maxkeys = 0;
+	BM_ITER_STRANDS(v, &iter, bm, BM_STRANDS_OF_MESH) {
+		int n = BM_strands_keys_count(v);
+		if (n > maxkeys)
+			maxkeys = n;
+	}
+	return maxkeys;
+}
+
 /* ------------------------------------------------------------------------- */
 
 /* Create a new strand */
diff --git a/source/blender/bmesh/intern/bmesh_strands.h b/source/blender/bmesh/intern/bmesh_strands.h
index cd4267f..1f060fa 100644
--- a/source/blender/bmesh/intern/bmesh_strands.h
+++ b/source/blender/bmesh/intern/bmesh_strands.h
@@ -111,6 +111,7 @@ BLI_INLINE BMVert *BM_strands_vert_prev(BMVert *v)
 
 int BM_strands_count(BMesh *bm);
 int BM_strands_keys_count(BMVert *root);
+int BM_strands_keys_count_max(BMesh *bm);
 
 /* Create a new strand */
 struct BMVert *BM_strands_create(struct BMesh *bm, int len, bool set_defaults);
diff --git a/source/blender/physics/intern/strands.cpp b/source/blender/physics/intern/strands.cpp
index d3c3192..d1e01ce 100644
--- a/source/blender/physics/intern/strands.cpp
+++ b/source/blender/physics/intern/strands.cpp
@@ -139,54 +139,55 @@ static void strands_adjust_segment_lengths(BMesh *bm)
 static void strands_solve_edge_relaxation(BMEditStrands *edit)
 {
 	BMesh *bm = edit->bm;
+	const int Nmax = BM_strands_keys_count_max(bm);
+	/* cache for vertex positions and segment lengths, for easier indexing */
+	float **co = (float **)MEM_mallocN(sizeof(float*) * Nmax, "strand positions");
+	float *target_length = (float *)MEM_mallocN(sizeof(float) * Nmax, "strand segment lengths");
+	
 	BMVert *root;
 	BMIter iter;
-	
-	if (!edit)
-		return;
-//	if (!(pset->flag & PE_KEEP_LENGTHS)) // XXX TODO
-//		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;
+		const int S = 1; /* TODO particles use PE_LOCK_FIRST option */
+		const int N = BM_strands_keys_count(root);
+		const float divN = 1.0f / (float)N;
 		
-		BM_ITER_STRANDS_ELEM_INDEX(vj, &iterj, root, BM_VERTS_OF_STRAND, j) {
-			BMVert *vk, *vk_prev;
-			float lenk, lenk_prev;
-			BMIter iterk;
+		/* setup positions cache */
+		{
+			BMVert *v;
+			BMIter viter;
 			int k;
-			bool skip_first;
-			
-			if (j == 0)
-				continue;
-			
-			if (true /* XXX particles use PE_LOCK_FIRST option */)
-				skip_first = true;
-			else
-				skip_first = false;
+			BM_ITER_STRANDS_ELEM_INDEX(v, &viter, root, BM_VERTS_OF_STRAND, k) {
+				co[k] = v->co;
+				target_length[k] = BM_elem_float_data_named_get(&bm->vdata, v, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
+			}
+		}
+		
+		for (int iter = 1; iter < N; iter++) {
+			float correct_first[3] = {0.0f, 0.0f, 0.0f};
+			float correct_second[3] = {0.0f, 0.0f, 0.0f};
 			
-			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);
-				
+			for (int k = S; k < N; k++) {
 				if (k > 0) {
-					sub_v3_v3v3(dir, vk->co, vk_prev->co);
-					tlen = normalize_v3(dir);
-					relax = relax_factor * (tlen - lenk_prev);
+					/* calculate correction for the first vertex */
+					float dir[3];
+					sub_v3_v3v3(dir, co[k-1], co[k]);
+					float length = normalize_v3(dir);
+					
+					mul_v3_v3fl(correct_first, dir, divN * (length - target_length[k]));
+				}
+				
+				if (k < N-1) {
+					/* calculate correction for the second vertex */
+					float dir[3];
+					sub_v3_v3v3(dir, co[k+1], co[k]);
+					float length_next = normalize_v3(dir);
 					
-					if (!(k == 1 && skip_first))
-						madd_v3_v3fl(vk_prev->co, dir, relax);
-					madd_v3_v3fl(vk->co, dir, -relax);
+					mul_v3_v3fl(correct_second, dir, divN * (length_next - target_length[k+1]));
 				}
 				
-				vk_prev = vk;
-				lenk_prev = lenk;
+				/* apply both corrections (try to satisfy both sides equally) */
+				add_v3_v3(co[k], correct_first);
+				add_v3_v3(co[k], correct_second);
 			}
 		}
 	}




More information about the Bf-blender-cvs mailing list