[Bf-blender-cvs] [2682ea8] hair_immediate_fixes: Completed the implementation of bent rest shapes for hair.

Lukas Tönne noreply at git.blender.org
Thu Sep 25 23:20:38 CEST 2014


Commit: 2682ea830a9c138ca013dbd2b2bff17b05726b73
Author: Lukas Tönne
Date:   Thu Sep 25 23:19:20 2014 +0200
Branches: hair_immediate_fixes
https://developer.blender.org/rB2682ea830a9c138ca013dbd2b2bff17b05726b73

Completed the implementation of bent rest shapes for hair.

Basically follows the Pixar approach from "Artistic Simulation of Curly
Hair".

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

M	source/blender/blenkernel/BKE_cloth.h
M	source/blender/blenkernel/intern/cloth.c
M	source/blender/blenkernel/intern/particle_system.c
M	source/blender/physics/intern/BPH_mass_spring.cpp
M	source/blender/physics/intern/implicit.h
M	source/blender/physics/intern/implicit_blender.c

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

diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 8a2477a..2a1741d 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -149,9 +149,6 @@ typedef struct ClothSpring {
 	
 	/* angular bending spring target and derivatives */
 	float target[3];
-	float dtarget_dxij[3][3];
-	float dtarget_dxkl[3][3];
-	float dtarget_dxmn[3][3];
 }
 ClothSpring;
 
@@ -251,7 +248,7 @@ void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float
 // needed for cloth.c
 int cloth_add_spring (struct ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type);
 
-void cloth_parallel_transport_hair_frame(float mat[3][3], float dir_old[3], const float x_cur[3], const float x_new[3]);
+void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]);
 
 ////////////////////////////////////////////////
 
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index d8d42cd..7d563ea 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -1106,7 +1106,7 @@ static void cloth_update_bending_targets(ClothModifierData *clmd)
 	Cloth *cloth = clmd->clothObject;
 	ClothSpring *spring;
 	LinkNode *search = NULL;
-	float hair_frame[3][3], dir[3];
+	float hair_frame[3][3], dir_old[3], dir_new[3];
 	bool is_root;
 	
 	/* XXX Note: we need to propagate frames from the root up,
@@ -1119,7 +1119,7 @@ static void cloth_update_bending_targets(ClothModifierData *clmd)
 	
 	is_root = true;
 	for (search = cloth->springs; search; search = search->next) {
-		ClothHairRoot *hair_info;
+		ClothHairRoot *hair_ij, *hair_kl;
 		
 		spring = search->link;
 		if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) {
@@ -1127,20 +1127,23 @@ static void cloth_update_bending_targets(ClothModifierData *clmd)
 			continue;
 		}
 		
-		hair_info = &clmd->roots[spring->kl];
+		hair_ij = &clmd->roots[spring->ij];
+		hair_kl = &clmd->roots[spring->kl];
 		if (is_root) {
 			/* initial hair frame from root orientation */
-			copy_m3_m3(hair_frame, hair_info->rot);
+			copy_m3_m3(hair_frame, hair_ij->rot);
 			/* surface normal is the initial direction,
 			 * parallel transport then keeps it aligned to the hair direction
 			 */
-			copy_v3_v3(dir, hair_frame[2]);
+			copy_v3_v3(dir_new, hair_frame[2]);
 		}
 		
-		/* move frame to next hair segment */
-		cloth_parallel_transport_hair_frame(hair_frame, dir, cloth->verts[spring->kl].x, cloth->verts[spring->mn].x);
+		copy_v3_v3(dir_old, dir_new);
+		sub_v3_v3v3(dir_new, cloth->verts[spring->mn].x, cloth->verts[spring->kl].x);
+		normalize_v3(dir_new);
 		
-		if (clmd->debug_data) {
+#if 1
+		if (clmd->debug_data && (spring->ij == 0 || spring->ij == 1)) {
 			float a[3], b[3];
 			
 			copy_v3_v3(a, cloth->verts[spring->kl].x);
@@ -1155,13 +1158,69 @@ static void cloth_update_bending_targets(ClothModifierData *clmd)
 			mul_v3_v3fl(b, hair_frame[2], clmd->sim_parms->avg_spring_len);
 			BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 0, 0, 1, "frames", hash_vertex(8249, hash_int_2d(spring->kl, spring->mn)));
 		}
+#endif
+		
+		/* get local targets for kl/mn vertices by putting rest targets into the current frame,
+		 * then multiply with the rest length to get the actual goals
+		 */
+		
+		mul_v3_m3v3(spring->target, hair_frame, hair_kl->rest_target);
+		mul_v3_fl(spring->target, spring->restlen);
+		
+		/* move frame to next hair segment */
+		cloth_parallel_transport_hair_frame(hair_frame, dir_old, dir_new);
+		
+		is_root = false; /* next bending spring not connected to root */
+	}
+}
+
+static void cloth_update_bending_rest_targets(ClothModifierData *clmd)
+{
+	Cloth *cloth = clmd->clothObject;
+	ClothSpring *spring;
+	LinkNode *search = NULL;
+	float hair_frame[3][3], dir_old[3], dir_new[3];
+	bool is_root;
+	
+	/* XXX Note: we need to propagate frames from the root up,
+	 * but structural hair springs are stored in reverse order.
+	 * The bending springs however are then inserted in the same
+	 * order as vertices again ...
+	 * This messy situation can be resolved when solver data is
+	 * generated directly from a dedicated hair system.
+	 */
+	
+	is_root = true;
+	for (search = cloth->springs; search; search = search->next) {
+		ClothHairRoot *hair_ij, *hair_kl;
+		
+		spring = search->link;
+		if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) {
+			is_root = true; /* next bending spring connects to root */
+			continue;
+		}
 		
-		/* get target direction by putting rest target into the current frame */
-		mul_v3_m3v3(spring->target, hair_frame, hair_info->rest_target);
-		/* XXX TODO */
-		zero_m3(spring->dtarget_dxij);
-		zero_m3(spring->dtarget_dxkl);
-		zero_m3(spring->dtarget_dxmn);
+		hair_ij = &clmd->roots[spring->ij];
+		hair_kl = &clmd->roots[spring->kl];
+		if (is_root) {
+			/* initial hair frame from root orientation */
+			copy_m3_m3(hair_frame, hair_ij->rot);
+			/* surface normal is the initial direction,
+			 * parallel transport then keeps it aligned to the hair direction
+			 */
+			copy_v3_v3(dir_new, hair_frame[2]);
+		}
+		
+		copy_v3_v3(dir_old, dir_new);
+		sub_v3_v3v3(dir_new, cloth->verts[spring->mn].xrest, cloth->verts[spring->kl].xrest);
+		normalize_v3(dir_new);
+		
+		/* dir expressed in the hair frame defines the rest target direction */
+		copy_v3_v3(hair_kl->rest_target, dir_new);
+		mul_transposed_m3_v3(hair_frame, hair_kl->rest_target);
+		
+		/* move frame to next hair segment */
+		cloth_parallel_transport_hair_frame(hair_frame, dir_old, dir_new);
 		
 		is_root = false; /* next bending spring not connected to root */
 	}
@@ -1232,23 +1291,15 @@ BLI_INLINE void madd_m3_m3fl(float r[3][3], float m[3][3], float f)
 	r[2][2] += m[2][2] * f;
 }
 
-void cloth_parallel_transport_hair_frame(float mat[3][3], float dir_old[3], const float x_cur[3], const float x_new[3])
+void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3])
 {
-	float dir_new[3];
 	float rot[3][3];
 	
-	/* next segment direction */
-	sub_v3_v3v3(dir_new, x_new, x_cur);
-	normalize_v3(dir_new);
-	
 	/* rotation between segments */
 	rotation_between_vecs_to_mat3(rot, dir_old, dir_new);
 	
 	/* rotate the frame */
 	mul_m3_m3m3(mat, rot, mat);
-	
-	/* advance old variables */
-	copy_v3_v3(dir_old, dir_new);
 }
 
 static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
@@ -1491,6 +1542,8 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
 				search2 = search2->next;
 			}
 		}
+		
+		cloth_update_bending_rest_targets(clmd);
 	}
 	
 	/* note: the edges may already exist so run reinsert */
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 35ef25d..9f34c74 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4101,7 +4101,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
 	/* make vgroup for pin roots etc.. */
 	psys->particles->hair_index = 1;
 	LOOP_PARTICLES {
-		float root_mat[4][4], hair_frame[3][3], dir[3];
+		float root_mat[4][4];
 		bool use_hair = psys_hair_use_simulation(pa, max_length);
 
 		if (p)
@@ -4111,13 +4111,6 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
 		mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
 		normalize_m4(root_mat);
 
-		/* initial hair frame from root orientation */
-		copy_m3_m4(hair_frame, root_mat);
-		/* surface normal is the initial direction,
-		 * parallel transport then keeps it aligned to the hair direction
-		 */
-		copy_v3_v3(dir, hair_frame[2]);
-
 		for (k=0, key=pa->hair; k<pa->totkey; k++,key++) {
 			ClothHairRoot *root;
 			
@@ -4129,10 +4122,6 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
 				copy_v3_v3(root->loc, root_mat[3]);
 				copy_m3_m4(root->rot, root_mat);
 				
-				/* dir expressed in the hair frame defines the rest target direction */
-				copy_v3_v3(root->rest_target, dir);
-				mul_transposed_m3_v3(hair_frame, root->rest_target);
-				
 				sub_v3_v3v3(temp, key->co, (key+1)->co);
 				copy_v3_v3(mvert->co, key->co);
 				add_v3_v3v3(mvert->co, mvert->co, temp);
@@ -4151,14 +4140,6 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
 			copy_v3_v3(root->loc, root_mat[3]);
 			copy_m3_m4(root->rot, root_mat);
 
-			if (k < pa->totkey-1)
-				/* move frame to next hair segment */
-				cloth_parallel_transport_hair_frame(hair_frame, dir, key->co, (key+1)->co);
-			
-			/* dir expressed in the hair frame defines the rest target direction */
-			copy_v3_v3(root->rest_target, dir);
-			mul_transposed_m3_v3(hair_frame, root->rest_target);
-
 			copy_v3_v3(mvert->co, key->co);
 			mul_m4_v3(hairmat, mvert->co);
 			mvert++;
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 458a8f2..89e9447 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -425,13 +425,18 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
 		cb = kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
 		
 		/* XXX assuming same restlen for ij and jk segments here, this can be done correctly for hair later */
-		BPH_mass_spring_force_spring_bending_angular(data, s->ij, s->kl, s->mn, s->matrix_ij_kl, s->matrix_kl_mn, s->matrix_ij_mn, s->restlen, s->restlen, kb, cb);
+		BPH_mass_spring_force_spring_bending_angular(data, s->ij, s->kl, s->mn, s->matrix_ij_kl, s->matrix_kl_mn, s->matrix_ij_mn, s->target, kb, cb);
 		
 		{
 			float x[3], v[3], d[3];
+			
 			BPH_mass_spring_get_motion_state(data, s->kl, x, v);
-			mul_v3_v3fl(d, s->target, clmd->sim_parms->avg_spring_len);
-			BKE_sim_debug_data_add_vector(clmd->debug_data, x, d, 0.4, 0.4, 1, "target", hash_vertex(7982, s->kl));
+			
+			copy_v3_v3(d, s->target);
+			BKE_sim_debug_data_add_vector(clmd->debug_data, x, d, 0.8, 0.8, 0.2, "target", hash_vertex(7982, s->kl));
+			
+//			copy_v3_v3(d, s->target_ij);
+//			BKE_sim_debug_data_add_vec

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list