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:
-rw-r--r--source/blender/blenkernel/BKE_cloth.h9
-rw-r--r--source/blender/blenkernel/intern/cloth.c138
-rw-r--r--source/blender/blenkernel/intern/particle_system.c22
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp7
4 files changed, 175 insertions, 1 deletions
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index acda9e11265..8a2477aaa15 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -62,6 +62,7 @@ struct PartDeflect;
typedef struct ClothHairRoot {
float loc[3];
float rot[3][3];
+ float rest_target[3]; /* rest target direction for each segment */
} ClothHairRoot;
typedef struct ClothSolverResult {
@@ -145,6 +146,12 @@ typedef struct ClothSpring {
float f[3];
float stiffness; /* stiffness factor from the vertex groups */
float editrestlen;
+
+ /* 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;
@@ -244,6 +251,8 @@ 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]);
+
////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 284107ee4e8..a6df9942158 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -70,6 +70,35 @@ static void cloth_update_springs( ClothModifierData *clmd );
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm );
static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm );
+/* ==== hash functions for debugging ==== */
+BLI_INLINE unsigned int hash_int_2d(unsigned int kx, unsigned int ky)
+{
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+ unsigned int a, b, c;
+
+ a = b = c = 0xdeadbeef + (2 << 2) + 13;
+ a += kx;
+ b += ky;
+
+ c ^= b; c -= rot(b,14);
+ a ^= c; a -= rot(c,11);
+ b ^= a; b -= rot(a,25);
+ c ^= b; c -= rot(b,16);
+ a ^= c; a -= rot(c,4);
+ b ^= a; b -= rot(a,14);
+ c ^= b; c -= rot(b,24);
+
+ return c;
+
+#undef rot
+}
+
+BLI_INLINE int hash_vertex(int type, int vertex)
+{
+ return hash_int_2d((unsigned int)type, (unsigned int)vertex);
+}
+/* ================ */
/******************************************************************************
*
@@ -1072,6 +1101,72 @@ static void cloth_free_errorsprings(Cloth *cloth, LinkNode **edgelist)
}
}
+static void cloth_update_bending_targets(ClothModifierData *clmd)
+{
+ Cloth *cloth = clmd->clothObject;
+ ClothSpring *spring;
+ LinkNode *search = NULL;
+ float hair_frame[3][3], dir[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_info;
+
+ spring = search->link;
+ if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) {
+ is_root = true; /* next bending spring connects to root */
+ continue;
+ }
+
+ hair_info = &clmd->roots[spring->kl];
+ if (is_root) {
+ /* initial hair frame from root orientation */
+ copy_m3_m3(hair_frame, hair_info->rot);
+ /* surface normal is the initial direction,
+ * parallel transport then keeps it aligned to the hair direction
+ */
+ copy_v3_v3(dir, 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);
+
+ if (clmd->debug_data) {
+ float a[3], b[3];
+
+ copy_v3_v3(a, cloth->verts[spring->kl].x);
+// BKE_sim_debug_data_add_dot(clmd->debug_data, cloth_vert ? cloth_vert->x : key->co, 1, 1, 0, "frames", hash_vertex(8246, hash_int_2d(p, k)));
+
+ mul_v3_v3fl(b, hair_frame[0], clmd->sim_parms->avg_spring_len);
+ BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 1, 0, 0, "frames", hash_vertex(8247, hash_int_2d(spring->kl, spring->mn)));
+
+ mul_v3_v3fl(b, hair_frame[1], clmd->sim_parms->avg_spring_len);
+ BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 0, 1, 0, "frames", hash_vertex(8248, hash_int_2d(spring->kl, spring->mn)));
+
+ 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)));
+ }
+
+ /* 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);
+
+ is_root = false; /* next bending spring not connected to root */
+ }
+}
+
/* update stiffness if vertex group values are changing from frame to frame */
static void cloth_update_springs( ClothModifierData *clmd )
{
@@ -1109,8 +1204,51 @@ static void cloth_update_springs( ClothModifierData *clmd )
search = search->next;
}
+
+ cloth_update_bending_targets(clmd);
+}
+
+BLI_INLINE void cross_identity_v3(float r[3][3], const float v[3])
+{
+ zero_m3(r);
+ r[0][1] = v[2];
+ r[0][2] = -v[1];
+ r[1][0] = -v[2];
+ r[1][2] = v[0];
+ r[2][0] = v[1];
+ r[2][1] = -v[0];
+}
+BLI_INLINE void madd_m3_m3fl(float r[3][3], float m[3][3], float f)
+{
+ r[0][0] += m[0][0] * f;
+ r[0][1] += m[0][1] * f;
+ r[0][2] += m[0][2] * f;
+ r[1][0] += m[1][0] * f;
+ r[1][1] += m[1][1] * f;
+ r[1][2] += m[1][2] * f;
+ r[2][0] += m[2][0] * f;
+ r[2][1] += m[2][1] * 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])
+{
+ 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 )
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 8215c808c42..661e0c5c1be 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4083,7 +4083,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];
+ float root_mat[4][4], hair_frame[3][3], dir[3];
bool use_hair = psys_hair_use_simulation(pa, max_length);
if (p)
@@ -4091,6 +4091,14 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
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;
@@ -4103,6 +4111,10 @@ 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);
@@ -4121,6 +4133,14 @@ 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 56923b6603a..458a8f27ee7 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -426,6 +426,13 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
/* 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);
+
+ {
+ 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));
+ }
#endif
}
}