[Bf-blender-cvs] [eacc24c] strand_editmode: Ported over the relaxation method for hair vertices from particle edit mode.

Lukas Tönne noreply at git.blender.org
Mon Apr 20 14:24:11 CEST 2015


Commit: eacc24ccf1f758597adbdd33c830229737e5839d
Author: Lukas Tönne
Date:   Thu Dec 11 17:40:05 2014 +0100
Branches: strand_editmode
https://developer.blender.org/rBeacc24ccf1f758597adbdd33c830229737e5839d

Ported over the relaxation method for hair vertices from particle edit
mode.

This method is simple, but not really very usable. It works by
successively relaxing segments that are too long or too short, moving
both vertices along the edge between them. This is repeated N^2 times
(N: number of vertices on the strand).

A true IK solver could give a lot better results, as well as providing
many opportunities to apply weighting for targets (e.g. preferring to
move non-selected over selected vertices). Many different methods for
simple IK solvers exist, so there should be one that works well for
large number of simple strands. See e.g.
http://www.math.ucsd.edu/~sbuss/ResearchWeb/ikmethods/iksurvey.pdf

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

M	source/blender/blenkernel/intern/editstrands.c
M	source/blender/editors/transform/transform_conversions.c

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

diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c
index 6227161..94aa9b9 100644
--- a/source/blender/blenkernel/intern/editstrands.c
+++ b/source/blender/blenkernel/intern/editstrands.c
@@ -141,17 +141,75 @@ static void editstrands_apply_root_locations(BMesh *bm, DerivedMesh *root_dm)
 	}
 }
 
-static void editstrands_solve_segment_lengths(BMesh *bm)
+/* 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) !!)
+ * This should be replaced by a more advanced method using a least-squares
+ * error metric with length and root location constraints (IK solver)
+ */
+static void editstrands_solve_targets(BMEditStrands *edit)
+{
+	BMesh *bm = edit->bm;
+	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;
+		
+		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)
+				continue;
+			
+			if (true /* XXX particles use PE_LOCK_FIRST option */)
+				skip_first = true;
+			else
+				skip_first = false;
+			
+			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;
+			}
+		}
+	}
+}
+
+static void editstrands_adjust_segment_lengths(BMesh *bm)
 {
 	BMVert *root, *v, *vprev;
 	BMIter iter, iter_strand;
 	int k;
 	
-	/* XXX Simplistic implementation from particles:
-	 * adjust segment lengths starting from the root.
-	 * This should be replaced by a more advanced method using a least-squares
-	 * error metric with length and root location constraints
-	 */
 	BM_ITER_STRANDS(root, &iter, bm, BM_STRANDS_OF_MESH) {
 		BM_ITER_STRANDS_ELEM_INDEX(v, &iter_strand, root, BM_VERTS_OF_STRAND, k) {
 			if (k > 0) {
@@ -174,7 +232,10 @@ void BKE_editstrands_solve_constraints(BMEditStrands *es)
 	BKE_editstrands_ensure(es);
 	
 	editstrands_apply_root_locations(es->bm, es->root_dm);
-	editstrands_solve_segment_lengths(es->bm);
+	
+	editstrands_solve_targets(es);
+	
+	editstrands_adjust_segment_lengths(es->bm);
 }
 
 void BKE_editstrands_ensure(BMEditStrands *es)
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index a88eead..34b002e 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2123,7 +2123,11 @@ cleanup:
 
 void flushTransStrands(TransInfo *t)
 {
-//	PE_update_object(scene, OBACT, 1);
+	Scene *scene = t->scene;
+	Object *ob = OBACT;
+	BMEditStrands *edit = BKE_editstrands_from_object(ob);
+	
+	BKE_editstrands_solve_constraints(edit);
 }
 
 /* ********************* mesh ****************** */




More information about the Bf-blender-cvs mailing list