[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