Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2014-09-26 01:19:20 +0400
committerLukas Tönne <lukas.toenne@gmail.com>2015-01-20 11:30:03 +0300
commit577150c635f4f9339819b1ca9d3587d6809e01e9 (patch)
tree4f6f97132d9e6287df1c64fda225ab73985cc9c0 /source/blender/blenkernel/intern/cloth.c
parent520922876a1f7618319038728ca14a18276287d3 (diff)
Completed the implementation of bent rest shapes for hair.
Basically follows the Pixar approach from "Artistic Simulation of Curly Hair".
Diffstat (limited to 'source/blender/blenkernel/intern/cloth.c')
-rw-r--r--source/blender/blenkernel/intern/cloth.c99
1 files changed, 76 insertions, 23 deletions
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index a6df9942158..7768149bc12 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 */