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

Lukas Tönne noreply at git.blender.org
Thu Dec 11 17:45:00 CET 2014


Commit: 7247a2b366d32a38d445a56501ea39da5cf8ceb6
Author: Lukas Tönne
Date:   Thu Dec 11 17:40:05 2014 +0100
Branches: hair_immediate_fixes
https://developer.blender.org/rB7247a2b366d32a38d445a56501ea39da5cf8ceb6

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 e54de09..b88b123 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2122,7 +2122,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