[Bf-blender-cvs] [4c723eb] master: Reshuffle applying of solver results a bit to ensure it works exactly as complicated as before cloth solver changes.

Lukas Tönne noreply at git.blender.org
Mon Mar 2 11:47:46 CET 2015


Commit: 4c723eb80e299eb6ca11ad72b5fcbe8746c4a854
Author: Lukas Tönne
Date:   Mon Mar 2 11:46:10 2015 +0100
Branches: master
https://developer.blender.org/rB4c723eb80e299eb6ca11ad72b5fcbe8746c4a854

Reshuffle applying of solver results a bit to ensure it works exactly
as complicated as before cloth solver changes.

Still doesn't solve the collapsing cloth cube issue mentioned in T43406,
probably the bending springs work somewhat differently now.

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

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/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 1387f63..830f346 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -1,3 +1,4 @@
+<<<<<<< master
 /*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -1115,3 +1116,1095 @@ bool BPH_cloth_solver_get_texture_data(Object *UNUSED(ob), ClothModifierData *cl
 	
 	return true;
 }
+=======
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/physics/intern/BPH_mass_spring.cpp
+ *  \ingroup bph
+ */
+
+extern "C" {
+#include "MEM_guardedalloc.h"
+
+#include "DNA_cloth_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_force.h"
+#include "DNA_object_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BLI_math.h"
+#include "BLI_linklist.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_cloth.h"
+#include "BKE_collision.h"
+#include "BKE_effect.h"
+}
+
+#include "BPH_mass_spring.h"
+#include "implicit.h"
+
+static float I3[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
+
+/* Number of off-diagonal non-zero matrix blocks.
+ * Basically there is one of these for each vertex-vertex interaction.
+ */
+static int cloth_count_nondiag_blocks(Cloth *cloth)
+{
+	LinkNode *link;
+	int nondiag = 0;
+	
+	for (link = cloth->springs; link; link = link->next) {
+		ClothSpring *spring = (ClothSpring *)link->link;
+		
+		switch (spring->type) {
+			case CLOTH_SPRING_TYPE_BENDING_ANG:
+				/* angular bending combines 3 vertices */
+				nondiag += 3;
+				break;
+				
+			default:
+				/* all other springs depend on 2 vertices only */
+				nondiag += 1;
+				break;
+		}
+	}
+	
+	return nondiag;
+}
+
+static struct Implicit_Data *cloth_solver_init_data(Cloth *cloth)
+{
+	int totvert = cloth->numverts;
+	
+	if (cloth->implicit && totvert != BPH_mass_spring_solver_numvert(cloth->implicit)) {
+		BPH_mass_spring_solver_free(cloth->implicit);
+		cloth->implicit = NULL;
+	}
+	
+	if (!cloth->implicit) {
+		int nondiag = cloth_count_nondiag_blocks(cloth);
+		cloth->implicit = BPH_mass_spring_solver_create(totvert, nondiag);
+	}
+	
+	return cloth->implicit;
+}
+
+int BPH_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd)
+{
+	Cloth *cloth = clmd->clothObject;
+	ClothVertex *vert;
+	const float ZERO[3] = {0.0f, 0.0f, 0.0f};
+	Implicit_Data *id = cloth_solver_init_data(cloth);
+	unsigned int i;
+	
+	vert = cloth->verts;
+	for (i = 0; i < cloth->numverts; ++i, ++vert) {
+		BPH_mass_spring_set_vertex_mass(id, i, vert->mass);
+		BPH_mass_spring_set_motion_state(id, i, vert->x, ZERO);
+	}
+	
+	return 1;
+}
+
+void BPH_cloth_solver_free(ClothModifierData *clmd)
+{
+	Cloth *cloth = clmd->clothObject;
+	
+	if (cloth->implicit) {
+		BPH_mass_spring_solver_free(cloth->implicit);
+		cloth->implicit = NULL;
+	}
+}
+
+void BPH_cloth_solver_set_positions(ClothModifierData *clmd)
+{
+	Cloth *cloth = clmd->clothObject;
+	ClothVertex *vert;
+	unsigned int numverts = cloth->numverts, i;
+	ClothHairData *cloth_hairdata = clmd->hairdata;
+	Implicit_Data *id = cloth_solver_init_data(cloth);
+	
+	vert = cloth->verts;
+	for (i = 0; i < numverts; ++i, ++vert) {
+		if (cloth_hairdata) {
+			ClothHairData *root = &cloth_hairdata[i];
+			BPH_mass_spring_set_rest_transform(id, i, root->rot);
+		}
+		else
+			BPH_mass_spring_set_rest_transform(id, i, I3);
+		
+		BPH_mass_spring_set_motion_state(id, i, vert->x, vert->v);
+	}
+}
+
+static bool collision_response(ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, float dt, float restitution, float r_impulse[3])
+{
+	Cloth *cloth = clmd->clothObject;
+	int index = collpair->ap1;
+	bool result = false;
+	
+	float v1[3], v2_old[3], v2_new[3], v_rel_old[3], v_rel_new[3];
+	float epsilon2 = BLI_bvhtree_getepsilon(collmd->bvhtree);
+
+	float margin_distance = collpair->distance - epsilon2;
+	float mag_v_rel;
+	
+	zero_v3(r_impulse);
+	
+	if (margin_distance > 0.0f)
+		return false; /* XXX tested before already? */
+	
+	/* only handle static collisions here */
+	if ( collpair->flag & COLLISION_IN_FUTURE )
+		return false;
+	
+	/* velocity */
+	copy_v3_v3(v1, cloth->verts[index].v);
+	collision_get_collider_velocity(v2_old, v2_new, collmd, collpair);
+	/* relative velocity = velocity of the cloth point relative to the collider */
+	sub_v3_v3v3(v_rel_old, v1, v2_old);
+	sub_v3_v3v3(v_rel_new, v1, v2_new);
+	/* normal component of the relative velocity */
+	mag_v_rel = dot_v3v3(v_rel_old, collpair->normal);
+	
+	/* only valid when moving toward the collider */
+	if (mag_v_rel < -ALMOST_ZERO) {
+		float v_nor_old, v_nor_new;
+		float v_tan_old[3], v_tan_new[3];
+		float bounce, repulse;
+		
+		/* Collision response based on
+		 * "Simulating Complex Hair with Robust Collision Handling" (Choe, Choi, Ko, ACM SIGGRAPH 2005)
+		 * http://graphics.snu.ac.kr/publications/2005-choe-HairSim/Choe_2005_SCA.pdf
+		 */
+		
+		v_nor_old = mag_v_rel;
+		v_nor_new = dot_v3v3(v_rel_new, collpair->normal);
+		
+		madd_v3_v3v3fl(v_tan_old, v_rel_old, collpair->normal, -v_nor_old);
+		madd_v3_v3v3fl(v_tan_new, v_rel_new, collpair->normal, -v_nor_new);
+		
+		bounce = -v_nor_old * restitution;
+		
+		repulse = -margin_distance / dt; /* base repulsion velocity in normal direction */
+		/* XXX this clamping factor is quite arbitrary ...
+		 * not sure if there is a more scientific approach, but seems to give good results
+		 */
+		CLAMP(repulse, 0.0f, 4.0f * bounce);
+		
+		if (margin_distance < -epsilon2) {
+			mul_v3_v3fl(r_impulse, collpair->normal, max_ff(repulse, bounce) - v_nor_new);
+		}
+		else {
+			bounce = 0.0f;
+			mul_v3_v3fl(r_impulse, collpair->normal, repulse - v_nor_new);
+		}
+		
+		result = true;
+	}
+	
+	return result;
+}
+
+/* Init constraint matrix
+ * This is part of the modified CG method suggested by Baraff/Witkin in
+ * "Large Steps in Cloth Simulation" (Siggraph 1998)
+ */
+static void cloth_setup_constraints(ClothModifierData *clmd, ColliderContacts *contacts, int totcolliders, float dt)
+{
+	Cloth *cloth = clmd->clothObject;
+	Implicit_Data *data = cloth->implicit;
+	ClothVertex *vert;
+	int numverts = cloth->numverts;
+	int i, j, v;
+	
+	const float ZERO[3] = {0.0f, 0.0f, 0.0f};
+	
+	BPH_mass_spring_clear_constraints(data);
+	
+	vert = cloth->verts;
+	for (v = 0; v < numverts; ++v, ++vert) {
+		if (vert->flags & CLOTH_VERT_FLAG_PINNED) {
+			/* pinned vertex constraints */
+			BPH_mass_spring_add_constraint_ndof0(data, v, ZERO); /* velocity is defined externally */
+		}
+		
+		vert->impulse_count = 0;
+	}
+
+	for (i = 0; i < totcolliders; ++i) {
+		ColliderContacts *ct = &contacts[i];
+		for (j = 0; j < ct->totcollisions; ++j) {
+			CollPair *collpair = &ct->collisions[j];
+			int v = collpair->face1;
+			float impulse[3];
+			
+//			float restitution = (1.0f - clmd->coll_parms->damping) * (1.0f - ct->ob->pd->pdef_sbdamp);
+			float restitution = 0.0f;
+			
+			vert = &cloth->verts[v];
+			/* pinned verts handled separately */
+			if (vert->flags & CLOTH_VERT_FLAG_PINNED)
+				continue;
+			
+			/* XXX cheap way of avoiding instability from multiple collisions in the same step
+			 * this should eventually be supported ...
+			 */
+			if (vert->impulse_count > 0)
+				continue;
+			
+			/* calculate collision response */
+			if (!collision_response(clmd, ct->collmd, collpair, dt, restitution, impulse))
+				continue;
+			
+			BPH_mass_spring_add_constraint_ndof2(data, i, collpair->normal, impulse);
+			++vert->impulse_count;
+		}
+	}
+}
+
+/* computes where the cloth would be if it were subject to perfectly stiff edges
+ * (edge distance constraints) in a lagrangian solver.  then add forces to help
+ * guide the implicit solver to that state.  this function is called after
+ * collisions*/
+static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothModifierData *clmd, float (*initial_cos)[3], float UNUSED(step), float dt)
+{
+	Cloth *cloth= clmd->clothObject;
+	float (*cos)[3] = (float (*)[3])MEM_callocN(sizeof(float)*3*cloth->numverts, "cos cloth_calc_helper_forces");
+	float *masses = (float *)MEM_callocN(sizeof(float)*cloth->numverts, "cos cloth_calc_helper_forces");
+	LinkNode *node;
+	ClothSpring *spring;
+	ClothVertex *vert;
+	int i, steps;
+	
+	vert = cloth->verts;
+	for (i=0; i<cloth->numverts; i++, vert++) {
+		copy_v3_v3(cos[i], vert->tx);
+		
+		if (vert->goal == 1.0f || len_squared_v3v3(initial_cos[i], vert->tx) != 0.0f) {
+			masses[i] = 1e+10;
+		}
+		else {
+			masses[i] = vert->mass;
+		}
+	}
+	
+	steps = 55;
+	for (i=0; i<steps; i++) {
+		for (node=cloth->springs; node; node=node->next) {
+			/* ClothVertex *cv1, *cv2; */ /* UNUSED */
+			int v1, v2;
+			float len, c, l, vec[3];
+			
+			spring = (ClothSpring *)node->link;
+			if (spring->type != CLOTH_SPRING_TYPE_STRUCTURAL && spring->type != CLOTH_SPRING_TYPE_SHEAR) 
+				continue;
+			
+			v1 = spring->ij; v2 = spring->kl;
+			/* cv1 = cloth->verts + v1; */ /* UNUSED */
+			/* cv2 = cloth->verts + v2; */ /* UNUSED */
+			len = len_v3v3(cos[v1], cos[v2]);
+			
+			sub_v3_v3v3(vec, cos[v1], cos[v2]);
+			normalize_v3(vec);
+			
+			c = (len - spring->restlen);
+			if (c == 0.0f)
+				continue;
+			
+			l = c / ((1.0f / masses[v1]) + (1.0f / masses[v2]));


@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list