[Bf-blender-cvs] [cb4d349] cloth-improvements: Initial implementation of angular bending springs
Luca Rood
noreply at git.blender.org
Fri Dec 9 17:38:56 CET 2016
Commit: cb4d349803cbe27f51be2a5ccca1c68ea42ba3d9
Author: Luca Rood
Date: Wed Dec 7 15:57:17 2016 -0200
Branches: cloth-improvements
https://developer.blender.org/rBcb4d349803cbe27f51be2a5ccca1c68ea42ba3d9
Initial implementation of angular bending springs
This implements bending resistant forces between adjacent polygons in
cloth simulation. Note that derivatives are not yet included in the
computations (and might not even be needed, as the simulation is already
quite stable). Angular damping is not yet implemented either.
===================================================================
M source/blender/blenkernel/BKE_cloth.h
M source/blender/blenkernel/intern/cloth.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 9f8a8e4..5514958 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -132,8 +132,13 @@ ClothVertex;
typedef struct ClothSpring {
int ij; /* Pij from the paper, one end of the spring. */
int kl; /* Pkl from the paper, one end of the spring. */
- int mn; /* Something related to angular hair springs. */
- float restlen; /* The original length of the spring. */
+ int mn; /* For hair springs: third vertex index; For bending springs: edge index */
+ int *pa; /* array of vert indices for poly a (for bending springs) */
+ int *pb; /* array of vert indices for poly b (for bending springs) */
+ int la; /* length of *pa */
+ int lb; /* length of *pb */
+ float restlen; /* The original length of the spring */
+ float restang; /* The original angle of the bending springs */
int type; /* types defined in BKE_cloth.h ("springType") */
int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */
float stiffness; /* stiffness factor from the vertex groups */
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 8485004..be5747a 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -35,6 +35,7 @@
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
+#include "BLI_alloca.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
@@ -63,6 +64,12 @@ static void cloth_update_spring_lengths( ClothModifierData *clmd, DerivedMesh *d
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm );
static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm );
+typedef struct BendSpringRef {
+ int set;
+ int index;
+ LinkNode **spring;
+} BendSpringRef;
+
/******************************************************************************
*
* External interface called by modifier.c clothModifier functions.
@@ -531,7 +538,12 @@ void cloth_free_modifier(ClothModifierData *clmd )
LinkNode *search = cloth->springs;
while (search) {
ClothSpring *spring = search->link;
-
+
+ if (spring->type == CLOTH_SPRING_TYPE_BENDING) {
+ MEM_freeN(spring->pa);
+ MEM_freeN(spring->pb);
+ }
+
MEM_freeN ( spring );
search = search->next;
}
@@ -598,6 +610,11 @@ void cloth_free_modifier_extern(ClothModifierData *clmd )
while (search) {
ClothSpring *spring = search->link;
+ if (spring->type == CLOTH_SPRING_TYPE_BENDING) {
+ MEM_freeN(spring->pa);
+ MEM_freeN(spring->pb);
+ }
+
MEM_freeN ( spring );
search = search->next;
}
@@ -959,7 +976,7 @@ int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int
Cloth *cloth = clmd->clothObject;
ClothSpring *spring = NULL;
- if (cloth) {
+ if (cloth && spring_type != CLOTH_SPRING_TYPE_BENDING) {
// TODO: look if this spring is already there
spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
@@ -1001,7 +1018,12 @@ static void cloth_free_errorsprings(Cloth *cloth, LinkNodePair *edgelist)
LinkNode *search = cloth->springs;
while (search) {
ClothSpring *spring = search->link;
-
+
+ if (spring->type == CLOTH_SPRING_TYPE_BENDING) {
+ MEM_freeN(spring->pa);
+ MEM_freeN(spring->pb);
+ }
+
MEM_freeN ( spring );
search = search->next;
}
@@ -1294,6 +1316,58 @@ void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3]
mul_m3_m3m3(mat, rot, mat);
}
+BLI_INLINE float spring_angle(ClothVertex *verts, int i, int j, int *i_a, int *i_b, int len_a, int len_b)
+{
+ float co_i[3], co_j[3], co_a[3], co_b[3];
+ float dir_a[3], dir_b[3];
+ float tmp1[3], tmp2[3], vec_e[3];
+ float sin, cos;
+ float (*array_a)[3] = BLI_array_alloca(array_a, len_a);
+ float (*array_b)[3] = BLI_array_alloca(array_b, len_b);
+ int x;
+
+ /* assign poly vert coords to arrays */
+ for (x = 0; x < len_a; x++) {
+ copy_v3_v3(array_a[x], verts[i_a[x]].xrest);
+ }
+
+ for (x = 0; x < len_b; x++) {
+ copy_v3_v3(array_b[x], verts[i_b[x]].xrest);
+ }
+
+ /* get edge vert coords and poly centroid coords. */
+ copy_v3_v3(co_i, verts[i].xrest);
+ copy_v3_v3(co_j, verts[j].xrest);
+ cent_poly_v3(co_a, array_a, len_a);
+ cent_poly_v3(co_b, array_b, len_b);
+
+ /* find dir for poly a */
+ sub_v3_v3v3(tmp1, co_j, co_a);
+ sub_v3_v3v3(tmp2, co_i, co_a);
+
+ cross_v3_v3v3(dir_a, tmp1, tmp2);
+ normalize_v3(dir_a);
+
+ /* find dir for poly b */
+ sub_v3_v3v3(tmp1, co_i, co_b);
+ sub_v3_v3v3(tmp2, co_j, co_b);
+
+ cross_v3_v3v3(dir_b, tmp1, tmp2);
+ normalize_v3(dir_b);
+
+ /* find parallel and perpendicular directions to edge */
+ sub_v3_v3v3(vec_e, co_i, co_j);
+ normalize_v3(vec_e);
+
+ /* calculate angle between polys */
+ cos = dot_v3v3(dir_a, dir_b);
+
+ cross_v3_v3v3(tmp1, dir_a, dir_b);
+ sin = dot_v3v3(tmp1, vec_e);
+
+ return atan2(sin, cos);
+}
+
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
{
Cloth *cloth = clmd->clothObject;
@@ -1307,6 +1381,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
const MEdge *medge = dm->getEdgeArray(dm);
const MPoly *mpoly = dm->getPolyArray(dm);
const MLoop *mloop = dm->getLoopArray(dm);
+ const MLoop *ml;
int index2 = 0; // our second vertex index
LinkNodePair *edgelist;
EdgeSet *edgeset = NULL;
@@ -1329,7 +1404,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
if (!edgelist)
return 0;
- // structural springs
+ /* structural springs */
for ( i = 0; i < numedges; i++ ) {
spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
@@ -1374,157 +1449,172 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f / ((float)cloth->verts[i].spring_count);
}
- // shear springs
- for (i = 0; i < numpolys; i++) {
- /* triangle faces already have shear springs due to structural geometry */
- if (mpoly[i].totloop == 4) {
- int j;
+ /* shear and bend springs */
+ if (numpolys) {
+ BendSpringRef *spring_ref = MEM_callocN(sizeof(*spring_ref) * numedges, "temp bend spring reference");
+ BendSpringRef *curr_ref;
+ int j;
- for (j = 0; j != 2; j++) {
- spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
+ if (!spring_ref) {
+ cloth_free_errorsprings(cloth, edgelist);
+ return 0;
+ }
- if (!spring) {
- cloth_free_errorsprings(cloth, edgelist);
- return 0;
- }
+ for (i = 0; i < numpolys; i++) {
+ /* shear spring */
+ /* triangle faces already have shear springs due to structural geometry */
+ /* TODO: Support ngons */
+ if (mpoly[i].totloop == 4) {
+ for (j = 0; j != 2; j++) {
+ spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
- spring_verts_ordered_set(
- spring,
- mloop[mpoly[i].loopstart + (j + 0)].v,
- mloop[mpoly[i].loopstart + (j + 2)].v);
+ if (!spring) {
+ cloth_free_errorsprings(cloth, edgelist);
+ return 0;
+ }
- shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
- spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor;
- spring->type = CLOTH_SPRING_TYPE_SHEAR;
- spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f;
+ spring_verts_ordered_set(
+ spring,
+ mloop[mpoly[i].loopstart + (j + 0)].v,
+ mloop[mpoly[i].loopstart + (j + 2)].v);
- BLI_linklist_append(&edgelist[spring->ij], spring);
- BLI_linklist_append(&edgelist[spring->kl], spring);
+ shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
+ spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor;
+ spring->type = CLOTH_SPRING_TYPE_SHEAR;
+ spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f;
+
+ BLI_linklist_append(&edgelist[spring->ij], spring);
+ BLI_linklist_append(&edgelist[spring->kl], spring);
- shear_springs++;
+ shear_springs++;
- BLI_linklist_prepend(&cloth->springs, spring);
+ BLI_linklist_prepend(&cloth->springs, spring);
+ }
}
- }
- }
- edgeset = BLI_edgeset_new_ex(__func__, numedges);
- cloth->edgeset = edgeset;
+ /* bending spring */
+ ml = mloop + mpoly[i].loopstart;
- if (numpolys) {
- // bending springs
- search2 = cloth->springs;
- for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) {
- if ( !search2 )
- break;
+ for (j = 0; j < mpoly[i].totloop; j++, ml++) {
+ curr_ref = &spring_ref[ml->e];
+ if (curr_ref->set == 1) {
+ /* Remove spring, because this is the third poly to use this edge */
+ if (curr_ref->spring) {
+ spring = BLI_linklist_pop(curr_ref->spring);
+ curr_ref->spring = NULL;
- tspring2 = search2->link;
- search = edgelist[tspring2->kl].list;
- while ( search ) {
- tspring = search->link;
- index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) );
-
- // check for existing spring
- // check also if startpoint is equal to endpoint
- if ((index2 != tspring2->ij) &&
- !BLI_edgeset_haskey(edgeset, tspring2->ij, index2))
- {
- spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+ MEM_freeN(spring->pa);
+ MEM_freeN(spring->pb);
+ MEM_freeN(spring);
+ curr_ref->set = -1;
- if (!spring) {
- cloth_free_errorsprings(cloth, edgelist);
- return 0;
+ bend_springs--;
}
+ /* Create spring, because this is the second poly to use this edge */
+ else {
+ int k;
+ MLoop *tmp_loop;
- spring_verts_ordered_set(spring, tspring2->ij, index2);
- shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
- spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest)
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list