1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 ///btSoftBody implementation by Nathanael Presson
16 
17 #include "btSoftBodyInternals.h"
18 #include "BulletSoftBody/btSoftBodySolvers.h"
19 #include "btSoftBodyData.h"
20 #include "LinearMath/btSerializer.h"
21 
22 
23 //
btSoftBody(btSoftBodyWorldInfo * worldInfo,int node_count,const btVector3 * x,const btScalar * m)24 btSoftBody::btSoftBody(btSoftBodyWorldInfo*	worldInfo,int node_count,  const btVector3* x,  const btScalar* m)
25 :m_softBodySolver(0),m_worldInfo(worldInfo)
26 {
27 	/* Init		*/
28 	initDefaults();
29 
30 	/* Default material	*/
31 	Material*	pm=appendMaterial();
32 	pm->m_kLST	=	1;
33 	pm->m_kAST	=	1;
34 	pm->m_kVST	=	1;
35 	pm->m_flags	=	fMaterial::Default;
36 
37 	/* Nodes			*/
38 	const btScalar		margin=getCollisionShape()->getMargin();
39 	m_nodes.resize(node_count);
40 	for(int i=0,ni=node_count;i<ni;++i)
41 	{
42 		Node&	n=m_nodes[i];
43 		ZeroInitialize(n);
44 		n.m_x		=	x?*x++:btVector3(0,0,0);
45 		n.m_q		=	n.m_x;
46 		n.m_im		=	m?*m++:1;
47 		n.m_im		=	n.m_im>0?1/n.m_im:0;
48 		n.m_leaf	=	m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
49 		n.m_material=	pm;
50 	}
51 	updateBounds();
52 
53 }
54 
btSoftBody(btSoftBodyWorldInfo * worldInfo)55 btSoftBody::btSoftBody(btSoftBodyWorldInfo*	worldInfo)
56 :m_worldInfo(worldInfo)
57 {
58 	initDefaults();
59 }
60 
61 
initDefaults()62 void	btSoftBody::initDefaults()
63 {
64 	m_internalType		=	CO_SOFT_BODY;
65 	m_cfg.aeromodel		=	eAeroModel::V_Point;
66 	m_cfg.kVCF			=	1;
67 	m_cfg.kDG			=	0;
68 	m_cfg.kLF			=	0;
69 	m_cfg.kDP			=	0;
70 	m_cfg.kPR			=	0;
71 	m_cfg.kVC			=	0;
72 	m_cfg.kDF			=	(btScalar)0.2;
73 	m_cfg.kMT			=	0;
74 	m_cfg.kCHR			=	(btScalar)1.0;
75 	m_cfg.kKHR			=	(btScalar)0.1;
76 	m_cfg.kSHR			=	(btScalar)1.0;
77 	m_cfg.kAHR			=	(btScalar)0.7;
78 	m_cfg.kSRHR_CL		=	(btScalar)0.1;
79 	m_cfg.kSKHR_CL		=	(btScalar)1;
80 	m_cfg.kSSHR_CL		=	(btScalar)0.5;
81 	m_cfg.kSR_SPLT_CL	=	(btScalar)0.5;
82 	m_cfg.kSK_SPLT_CL	=	(btScalar)0.5;
83 	m_cfg.kSS_SPLT_CL	=	(btScalar)0.5;
84 	m_cfg.maxvolume		=	(btScalar)1;
85 	m_cfg.timescale		=	1;
86 	m_cfg.viterations	=	0;
87 	m_cfg.piterations	=	1;
88 	m_cfg.diterations	=	0;
89 	m_cfg.citerations	=	4;
90 	m_cfg.collisions	=	fCollision::Default;
91 	m_pose.m_bvolume	=	false;
92 	m_pose.m_bframe		=	false;
93 	m_pose.m_volume		=	0;
94 	m_pose.m_com		=	btVector3(0,0,0);
95 	m_pose.m_rot.setIdentity();
96 	m_pose.m_scl.setIdentity();
97 	m_tag				=	0;
98 	m_timeacc			=	0;
99 	m_bUpdateRtCst		=	true;
100 	m_bounds[0]			=	btVector3(0,0,0);
101 	m_bounds[1]			=	btVector3(0,0,0);
102 	m_worldTransform.setIdentity();
103 	setSolver(eSolverPresets::Positions);
104 
105 	/* Collision shape	*/
106 	///for now, create a collision shape internally
107 	m_collisionShape = new btSoftBodyCollisionShape(this);
108 	m_collisionShape->setMargin(0.25f);
109 
110 	m_initialWorldTransform.setIdentity();
111 
112 	m_windVelocity = btVector3(0,0,0);
113 	m_restLengthScale = btScalar(1.0);
114 }
115 
116 //
~btSoftBody()117 btSoftBody::~btSoftBody()
118 {
119 	//for now, delete the internal shape
120 	delete m_collisionShape;
121 	int i;
122 
123 	releaseClusters();
124 	for(i=0;i<m_materials.size();++i)
125 		btAlignedFree(m_materials[i]);
126 	for(i=0;i<m_joints.size();++i)
127 		btAlignedFree(m_joints[i]);
128 }
129 
130 //
checkLink(int node0,int node1) const131 bool			btSoftBody::checkLink(int node0,int node1) const
132 {
133 	return(checkLink(&m_nodes[node0],&m_nodes[node1]));
134 }
135 
136 //
checkLink(const Node * node0,const Node * node1) const137 bool			btSoftBody::checkLink(const Node* node0,const Node* node1) const
138 {
139 	const Node*	n[]={node0,node1};
140 	for(int i=0,ni=m_links.size();i<ni;++i)
141 	{
142 		const Link&	l=m_links[i];
143 		if(	(l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
144 			(l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
145 		{
146 			return(true);
147 		}
148 	}
149 	return(false);
150 }
151 
152 //
checkFace(int node0,int node1,int node2) const153 bool			btSoftBody::checkFace(int node0,int node1,int node2) const
154 {
155 	const Node*	n[]={	&m_nodes[node0],
156 		&m_nodes[node1],
157 		&m_nodes[node2]};
158 	for(int i=0,ni=m_faces.size();i<ni;++i)
159 	{
160 		const Face&	f=m_faces[i];
161 		int			c=0;
162 		for(int j=0;j<3;++j)
163 		{
164 			if(	(f.m_n[j]==n[0])||
165 				(f.m_n[j]==n[1])||
166 				(f.m_n[j]==n[2])) c|=1<<j; else break;
167 		}
168 		if(c==7) return(true);
169 	}
170 	return(false);
171 }
172 
173 //
appendMaterial()174 btSoftBody::Material*		btSoftBody::appendMaterial()
175 {
176 	Material*	pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
177 	if(m_materials.size()>0)
178 		*pm=*m_materials[0];
179 	else
180 		ZeroInitialize(*pm);
181 	m_materials.push_back(pm);
182 	return(pm);
183 }
184 
185 //
appendNote(const char * text,const btVector3 & o,const btVector4 & c,Node * n0,Node * n1,Node * n2,Node * n3)186 void			btSoftBody::appendNote(	const char* text,
187 									   const btVector3& o,
188 									   const btVector4& c,
189 									   Node* n0,
190 									   Node* n1,
191 									   Node* n2,
192 									   Node* n3)
193 {
194 	Note	n;
195 	ZeroInitialize(n);
196 	n.m_rank		=	0;
197 	n.m_text		=	text;
198 	n.m_offset		=	o;
199 	n.m_coords[0]	=	c.x();
200 	n.m_coords[1]	=	c.y();
201 	n.m_coords[2]	=	c.z();
202 	n.m_coords[3]	=	c.w();
203 	n.m_nodes[0]	=	n0;n.m_rank+=n0?1:0;
204 	n.m_nodes[1]	=	n1;n.m_rank+=n1?1:0;
205 	n.m_nodes[2]	=	n2;n.m_rank+=n2?1:0;
206 	n.m_nodes[3]	=	n3;n.m_rank+=n3?1:0;
207 	m_notes.push_back(n);
208 }
209 
210 //
appendNote(const char * text,const btVector3 & o,Node * feature)211 void			btSoftBody::appendNote(	const char* text,
212 									   const btVector3& o,
213 									   Node* feature)
214 {
215 	appendNote(text,o,btVector4(1,0,0,0),feature);
216 }
217 
218 //
appendNote(const char * text,const btVector3 & o,Link * feature)219 void			btSoftBody::appendNote(	const char* text,
220 									   const btVector3& o,
221 									   Link* feature)
222 {
223 	static const btScalar	w=1/(btScalar)2;
224 	appendNote(text,o,btVector4(w,w,0,0),	feature->m_n[0],
225 		feature->m_n[1]);
226 }
227 
228 //
appendNote(const char * text,const btVector3 & o,Face * feature)229 void			btSoftBody::appendNote(	const char* text,
230 									   const btVector3& o,
231 									   Face* feature)
232 {
233 	static const btScalar	w=1/(btScalar)3;
234 	appendNote(text,o,btVector4(w,w,w,0),	feature->m_n[0],
235 		feature->m_n[1],
236 		feature->m_n[2]);
237 }
238 
239 //
appendNode(const btVector3 & x,btScalar m)240 void			btSoftBody::appendNode(	const btVector3& x,btScalar m)
241 {
242 	if(m_nodes.capacity()==m_nodes.size())
243 	{
244 		pointersToIndices();
245 		m_nodes.reserve(m_nodes.size()*2+1);
246 		indicesToPointers();
247 	}
248 	const btScalar	margin=getCollisionShape()->getMargin();
249 	m_nodes.push_back(Node());
250 	Node&			n=m_nodes[m_nodes.size()-1];
251 	ZeroInitialize(n);
252 	n.m_x			=	x;
253 	n.m_q			=	n.m_x;
254 	n.m_im			=	m>0?1/m:0;
255 	n.m_material	=	m_materials[0];
256 	n.m_leaf		=	m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
257 }
258 
259 //
appendLink(int model,Material * mat)260 void			btSoftBody::appendLink(int model,Material* mat)
261 {
262 	Link	l;
263 	if(model>=0)
264 		l=m_links[model];
265 	else
266 	{ ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; }
267 	m_links.push_back(l);
268 }
269 
270 //
appendLink(int node0,int node1,Material * mat,bool bcheckexist)271 void			btSoftBody::appendLink(	int node0,
272 									   int node1,
273 									   Material* mat,
274 									   bool bcheckexist)
275 {
276 	appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist);
277 }
278 
279 //
appendLink(Node * node0,Node * node1,Material * mat,bool bcheckexist)280 void			btSoftBody::appendLink(	Node* node0,
281 									   Node* node1,
282 									   Material* mat,
283 									   bool bcheckexist)
284 {
285 	if((!bcheckexist)||(!checkLink(node0,node1)))
286 	{
287 		appendLink(-1,mat);
288 		Link&	l=m_links[m_links.size()-1];
289 		l.m_n[0]		=	node0;
290 		l.m_n[1]		=	node1;
291 		l.m_rl			=	(l.m_n[0]->m_x-l.m_n[1]->m_x).length();
292 		m_bUpdateRtCst=true;
293 	}
294 }
295 
296 //
appendFace(int model,Material * mat)297 void			btSoftBody::appendFace(int model,Material* mat)
298 {
299 	Face	f;
300 	if(model>=0)
301 	{ f=m_faces[model]; }
302 	else
303 	{ ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; }
304 	m_faces.push_back(f);
305 }
306 
307 //
appendFace(int node0,int node1,int node2,Material * mat)308 void			btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
309 {
310 	if (node0==node1)
311 		return;
312 	if (node1==node2)
313 		return;
314 	if (node2==node0)
315 		return;
316 
317 	appendFace(-1,mat);
318 	Face&	f=m_faces[m_faces.size()-1];
319 	btAssert(node0!=node1);
320 	btAssert(node1!=node2);
321 	btAssert(node2!=node0);
322 	f.m_n[0]	=	&m_nodes[node0];
323 	f.m_n[1]	=	&m_nodes[node1];
324 	f.m_n[2]	=	&m_nodes[node2];
325 	f.m_ra		=	AreaOf(	f.m_n[0]->m_x,
326 		f.m_n[1]->m_x,
327 		f.m_n[2]->m_x);
328 	m_bUpdateRtCst=true;
329 }
330 
331 //
appendTetra(int model,Material * mat)332 void			btSoftBody::appendTetra(int model,Material* mat)
333 {
334 Tetra	t;
335 if(model>=0)
336 	t=m_tetras[model];
337 	else
338 	{ ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; }
339 m_tetras.push_back(t);
340 }
341 
342 //
appendTetra(int node0,int node1,int node2,int node3,Material * mat)343 void			btSoftBody::appendTetra(int node0,
344 										int node1,
345 										int node2,
346 										int node3,
347 										Material* mat)
348 {
349 	appendTetra(-1,mat);
350 	Tetra&	t=m_tetras[m_tetras.size()-1];
351 	t.m_n[0]	=	&m_nodes[node0];
352 	t.m_n[1]	=	&m_nodes[node1];
353 	t.m_n[2]	=	&m_nodes[node2];
354 	t.m_n[3]	=	&m_nodes[node3];
355 	t.m_rv		=	VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x);
356 	m_bUpdateRtCst=true;
357 }
358 
359 //
360 
appendAnchor(int node,btRigidBody * body,bool disableCollisionBetweenLinkedBodies,btScalar influence)361 void			btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies,btScalar influence)
362 {
363 	btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x;
364 	appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies,influence);
365 }
366 
367 //
appendAnchor(int node,btRigidBody * body,const btVector3 & localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence)368 void			btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence)
369 {
370 	if (disableCollisionBetweenLinkedBodies)
371 	{
372 		if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size())
373 		{
374 			m_collisionDisabledObjects.push_back(body);
375 		}
376 	}
377 
378 	Anchor	a;
379 	a.m_node			=	&m_nodes[node];
380 	a.m_body			=	body;
381 	a.m_local			=	localPivot;
382 	a.m_node->m_battach	=	1;
383 	a.m_influence = influence;
384 	m_anchors.push_back(a);
385 }
386 
387 //
appendLinearJoint(const LJoint::Specs & specs,Cluster * body0,Body body1)388 void			btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
389 {
390 	LJoint*		pj	=	new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
391 	pj->m_bodies[0]	=	body0;
392 	pj->m_bodies[1]	=	body1;
393 	pj->m_refs[0]	=	pj->m_bodies[0].xform().inverse()*specs.position;
394 	pj->m_refs[1]	=	pj->m_bodies[1].xform().inverse()*specs.position;
395 	pj->m_cfm		=	specs.cfm;
396 	pj->m_erp		=	specs.erp;
397 	pj->m_split		=	specs.split;
398 	m_joints.push_back(pj);
399 }
400 
401 //
appendLinearJoint(const LJoint::Specs & specs,Body body)402 void			btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
403 {
404 	appendLinearJoint(specs,m_clusters[0],body);
405 }
406 
407 //
appendLinearJoint(const LJoint::Specs & specs,btSoftBody * body)408 void			btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
409 {
410 	appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
411 }
412 
413 //
appendAngularJoint(const AJoint::Specs & specs,Cluster * body0,Body body1)414 void			btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
415 {
416 	AJoint*		pj	=	new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
417 	pj->m_bodies[0]	=	body0;
418 	pj->m_bodies[1]	=	body1;
419 	pj->m_refs[0]	=	pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
420 	pj->m_refs[1]	=	pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
421 	pj->m_cfm		=	specs.cfm;
422 	pj->m_erp		=	specs.erp;
423 	pj->m_split		=	specs.split;
424 	pj->m_icontrol	=	specs.icontrol;
425 	m_joints.push_back(pj);
426 }
427 
428 //
appendAngularJoint(const AJoint::Specs & specs,Body body)429 void			btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
430 {
431 	appendAngularJoint(specs,m_clusters[0],body);
432 }
433 
434 //
appendAngularJoint(const AJoint::Specs & specs,btSoftBody * body)435 void			btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
436 {
437 	appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
438 }
439 
440 //
addForce(const btVector3 & force)441 void			btSoftBody::addForce(const btVector3& force)
442 {
443 	for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
444 }
445 
446 //
addForce(const btVector3 & force,int node)447 void			btSoftBody::addForce(const btVector3& force,int node)
448 {
449 	Node&	n=m_nodes[node];
450 	if(n.m_im>0)
451 	{
452 		n.m_f	+=	force;
453 	}
454 }
455 
addAeroForceToNode(const btVector3 & windVelocity,int nodeIndex)456 void			btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeIndex)
457 {
458 	btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size());
459 
460 	const btScalar dt = m_sst.sdt;
461 	const btScalar kLF = m_cfg.kLF;
462 	const btScalar kDG = m_cfg.kDG;
463 	//const btScalar kPR = m_cfg.kPR;
464 	//const btScalar kVC = m_cfg.kVC;
465 	const bool as_lift = kLF>0;
466 	const bool as_drag = kDG>0;
467 	const bool as_aero = as_lift || as_drag;
468 	const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
469 
470 	Node& n = m_nodes[nodeIndex];
471 
472 	if( n.m_im>0 )
473 	{
474 		btSoftBody::sMedium	medium;
475 
476 		EvaluateMedium(m_worldInfo, n.m_x, medium);
477 		medium.m_velocity = windVelocity;
478 		medium.m_density = m_worldInfo->air_density;
479 
480 		/* Aerodynamics			*/
481 		if(as_vaero)
482 		{
483 			const btVector3	rel_v = n.m_v - medium.m_velocity;
484 			const btScalar rel_v_len = rel_v.length();
485 			const btScalar	rel_v2 = rel_v.length2();
486 
487 			if(rel_v2>SIMD_EPSILON)
488 			{
489 				const btVector3 rel_v_nrm = rel_v.normalized();
490 				btVector3	nrm = n.m_n;
491 
492 				if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag)
493 				{
494 					nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
495 					btVector3 fDrag(0, 0, 0);
496 					btVector3 fLift(0, 0, 0);
497 
498 					btScalar n_dot_v = nrm.dot(rel_v_nrm);
499 					btScalar tri_area = 0.5f * n.m_area;
500 
501 					fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
502 
503 					// Check angle of attack
504 					// cos(10�) = 0.98480
505 					if ( 0 < n_dot_v && n_dot_v < 0.98480f)
506 						fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
507 
508 					// Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
509 					btVector3 del_v_by_fDrag = fDrag*n.m_im*m_sst.sdt;
510 					btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
511 					btScalar v_len2 = n.m_v.length2();
512 
513 					if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
514 					{
515 						btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
516 						btScalar v_len = n.m_v.length();
517 						fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
518 					}
519 
520 					n.m_f += fDrag;
521 					n.m_f += fLift;
522 				}
523 				else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
524 				{
525 					if (btSoftBody::eAeroModel::V_TwoSided)
526 						nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
527 
528 					const btScalar dvn = btDot(rel_v,nrm);
529 					/* Compute forces	*/
530 					if(dvn>0)
531 					{
532 						btVector3		force(0,0,0);
533 						const btScalar	c0	=	n.m_area * dvn * rel_v2/2;
534 						const btScalar	c1	=	c0 * medium.m_density;
535 						force	+=	nrm*(-c1*kLF);
536 						force	+=	rel_v.normalized() * (-c1 * kDG);
537 						ApplyClampedForce(n, force, dt);
538 					}
539 				}
540 			}
541 		}
542 	}
543 }
544 
addAeroForceToFace(const btVector3 & windVelocity,int faceIndex)545 void			btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceIndex)
546 {
547 	const btScalar dt = m_sst.sdt;
548 	const btScalar kLF = m_cfg.kLF;
549 	const btScalar kDG = m_cfg.kDG;
550 //	const btScalar kPR = m_cfg.kPR;
551 //	const btScalar kVC = m_cfg.kVC;
552 	const bool as_lift = kLF>0;
553 	const bool as_drag = kDG>0;
554 	const bool as_aero = as_lift || as_drag;
555 	const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
556 
557 	if(as_faero)
558 	{
559 		btSoftBody::Face&	f=m_faces[faceIndex];
560 
561 		btSoftBody::sMedium	medium;
562 
563 		const btVector3	v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
564 		const btVector3	x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
565 		EvaluateMedium(m_worldInfo,x,medium);
566 		medium.m_velocity = windVelocity;
567 		medium.m_density = m_worldInfo->air_density;
568 		const btVector3	rel_v=v-medium.m_velocity;
569 		const btScalar rel_v_len = rel_v.length();
570 		const btScalar	rel_v2=rel_v.length2();
571 
572 		if(rel_v2>SIMD_EPSILON)
573 		{
574 			const btVector3 rel_v_nrm = rel_v.normalized();
575 			btVector3	nrm = f.m_normal;
576 
577 			if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag)
578 			{
579 				nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
580 
581 				btVector3 fDrag(0, 0, 0);
582 				btVector3 fLift(0, 0, 0);
583 
584 				btScalar n_dot_v = nrm.dot(rel_v_nrm);
585 				btScalar tri_area = 0.5f * f.m_ra;
586 
587 				fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
588 
589 				// Check angle of attack
590 				// cos(10�) = 0.98480
591 				if ( 0 < n_dot_v && n_dot_v < 0.98480f)
592 					fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
593 
594 				fDrag /= 3;
595 				fLift /= 3;
596 
597 				for(int j=0;j<3;++j)
598 				{
599 					if (f.m_n[j]->m_im>0)
600 					{
601 						// Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
602 						btVector3 del_v_by_fDrag = fDrag*f.m_n[j]->m_im*m_sst.sdt;
603 						btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
604 						btScalar v_len2 = f.m_n[j]->m_v.length2();
605 
606 						if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
607 						{
608 							btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
609 							btScalar v_len = f.m_n[j]->m_v.length();
610 							fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
611 						}
612 
613 						f.m_n[j]->m_f += fDrag;
614 						f.m_n[j]->m_f += fLift;
615 					}
616 				}
617 			}
618 			else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
619 			{
620 				if (btSoftBody::eAeroModel::F_TwoSided)
621 					nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
622 
623 				const btScalar	dvn=btDot(rel_v,nrm);
624 				/* Compute forces	*/
625 				if(dvn>0)
626 				{
627 					btVector3		force(0,0,0);
628 					const btScalar	c0	=	f.m_ra*dvn*rel_v2;
629 					const btScalar	c1	=	c0*medium.m_density;
630 					force	+=	nrm*(-c1*kLF);
631 					force	+=	rel_v.normalized()*(-c1*kDG);
632 					force	/=	3;
633 					for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
634 				}
635 			}
636 		}
637 	}
638 
639 }
640 
641 //
addVelocity(const btVector3 & velocity)642 void			btSoftBody::addVelocity(const btVector3& velocity)
643 {
644 	for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
645 }
646 
647 /* Set velocity for the entire body										*/
setVelocity(const btVector3 & velocity)648 void				btSoftBody::setVelocity(	const btVector3& velocity)
649 {
650 	for(int i=0,ni=m_nodes.size();i<ni;++i)
651 	{
652 		Node&	n=m_nodes[i];
653 		if(n.m_im>0)
654 		{
655 			n.m_v	=	velocity;
656 		}
657 	}
658 }
659 
660 
661 //
addVelocity(const btVector3 & velocity,int node)662 void			btSoftBody::addVelocity(const btVector3& velocity,int node)
663 {
664 	Node&	n=m_nodes[node];
665 	if(n.m_im>0)
666 	{
667 		n.m_v	+=	velocity;
668 	}
669 }
670 
671 //
setMass(int node,btScalar mass)672 void			btSoftBody::setMass(int node,btScalar mass)
673 {
674 	m_nodes[node].m_im=mass>0?1/mass:0;
675 	m_bUpdateRtCst=true;
676 }
677 
678 //
getMass(int node) const679 btScalar		btSoftBody::getMass(int node) const
680 {
681 	return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
682 }
683 
684 //
getTotalMass() const685 btScalar		btSoftBody::getTotalMass() const
686 {
687 	btScalar	mass=0;
688 	for(int i=0;i<m_nodes.size();++i)
689 	{
690 		mass+=getMass(i);
691 	}
692 	return(mass);
693 }
694 
695 //
setTotalMass(btScalar mass,bool fromfaces)696 void			btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
697 {
698 	int i;
699 
700 	if(fromfaces)
701 	{
702 
703 		for(i=0;i<m_nodes.size();++i)
704 		{
705 			m_nodes[i].m_im=0;
706 		}
707 		for(i=0;i<m_faces.size();++i)
708 		{
709 			const Face&		f=m_faces[i];
710 			const btScalar	twicearea=AreaOf(	f.m_n[0]->m_x,
711 				f.m_n[1]->m_x,
712 				f.m_n[2]->m_x);
713 			for(int j=0;j<3;++j)
714 			{
715 				f.m_n[j]->m_im+=twicearea;
716 			}
717 		}
718 		for( i=0;i<m_nodes.size();++i)
719 		{
720 			m_nodes[i].m_im=1/m_nodes[i].m_im;
721 		}
722 	}
723 	const btScalar	tm=getTotalMass();
724 	const btScalar	itm=1/tm;
725 	for( i=0;i<m_nodes.size();++i)
726 	{
727 		m_nodes[i].m_im/=itm*mass;
728 	}
729 	m_bUpdateRtCst=true;
730 }
731 
732 //
setTotalDensity(btScalar density)733 void			btSoftBody::setTotalDensity(btScalar density)
734 {
735 	setTotalMass(getVolume()*density,true);
736 }
737 
738 //
setVolumeMass(btScalar mass)739 void			btSoftBody::setVolumeMass(btScalar mass)
740 {
741 btAlignedObjectArray<btScalar>	ranks;
742 ranks.resize(m_nodes.size(),0);
743 int i;
744 
745 for(i=0;i<m_nodes.size();++i)
746 	{
747 	m_nodes[i].m_im=0;
748 	}
749 for(i=0;i<m_tetras.size();++i)
750 	{
751 	const Tetra& t=m_tetras[i];
752 	for(int j=0;j<4;++j)
753 		{
754 		t.m_n[j]->m_im+=btFabs(t.m_rv);
755 		ranks[int(t.m_n[j]-&m_nodes[0])]+=1;
756 		}
757 	}
758 for( i=0;i<m_nodes.size();++i)
759 	{
760 	if(m_nodes[i].m_im>0)
761 		{
762 		m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im;
763 		}
764 	}
765 setTotalMass(mass,false);
766 }
767 
768 //
setVolumeDensity(btScalar density)769 void			btSoftBody::setVolumeDensity(btScalar density)
770 {
771 btScalar	volume=0;
772 for(int i=0;i<m_tetras.size();++i)
773 	{
774 	const Tetra& t=m_tetras[i];
775 	for(int j=0;j<4;++j)
776 		{
777 		volume+=btFabs(t.m_rv);
778 		}
779 	}
780 setVolumeMass(volume*density/6);
781 }
782 
783 //
transform(const btTransform & trs)784 void			btSoftBody::transform(const btTransform& trs)
785 {
786 	const btScalar	margin=getCollisionShape()->getMargin();
787 	ATTRIBUTE_ALIGNED16(btDbvtVolume)	vol;
788 
789 	for(int i=0,ni=m_nodes.size();i<ni;++i)
790 	{
791 		Node&	n=m_nodes[i];
792 		n.m_x=trs*n.m_x;
793 		n.m_q=trs*n.m_q;
794 		n.m_n=trs.getBasis()*n.m_n;
795 		vol = btDbvtVolume::FromCR(n.m_x,margin);
796 
797 		m_ndbvt.update(n.m_leaf,vol);
798 	}
799 	updateNormals();
800 	updateBounds();
801 	updateConstants();
802 	m_initialWorldTransform = trs;
803 }
804 
805 //
translate(const btVector3 & trs)806 void			btSoftBody::translate(const btVector3& trs)
807 {
808 	btTransform	t;
809 	t.setIdentity();
810 	t.setOrigin(trs);
811 	transform(t);
812 }
813 
814 //
rotate(const btQuaternion & rot)815 void			btSoftBody::rotate(	const btQuaternion& rot)
816 {
817 	btTransform	t;
818 	t.setIdentity();
819 	t.setRotation(rot);
820 	transform(t);
821 }
822 
823 //
scale(const btVector3 & scl)824 void			btSoftBody::scale(const btVector3& scl)
825 {
826 
827 	const btScalar	margin=getCollisionShape()->getMargin();
828 	ATTRIBUTE_ALIGNED16(btDbvtVolume)	vol;
829 
830 	for(int i=0,ni=m_nodes.size();i<ni;++i)
831 	{
832 		Node&	n=m_nodes[i];
833 		n.m_x*=scl;
834 		n.m_q*=scl;
835 		vol = btDbvtVolume::FromCR(n.m_x,margin);
836 		m_ndbvt.update(n.m_leaf,vol);
837 	}
838 	updateNormals();
839 	updateBounds();
840 	updateConstants();
841 }
842 
843 //
getRestLengthScale()844 btScalar btSoftBody::getRestLengthScale()
845 {
846 	return m_restLengthScale;
847 }
848 
849 //
setRestLengthScale(btScalar restLengthScale)850 void btSoftBody::setRestLengthScale(btScalar restLengthScale)
851 {
852 	for(int i=0, ni=m_links.size(); i<ni; ++i)
853 	{
854 		Link&		l=m_links[i];
855 		l.m_rl	=	l.m_rl / m_restLengthScale * restLengthScale;
856 		l.m_c1	=	l.m_rl*l.m_rl;
857 	}
858 	m_restLengthScale = restLengthScale;
859 
860 	if (getActivationState() == ISLAND_SLEEPING)
861 		activate();
862 }
863 
864 //
setPose(bool bvolume,bool bframe)865 void			btSoftBody::setPose(bool bvolume,bool bframe)
866 {
867 	m_pose.m_bvolume	=	bvolume;
868 	m_pose.m_bframe		=	bframe;
869 	int i,ni;
870 
871 	/* Weights		*/
872 	const btScalar	omass=getTotalMass();
873 	const btScalar	kmass=omass*m_nodes.size()*1000;
874 	btScalar		tmass=omass;
875 	m_pose.m_wgh.resize(m_nodes.size());
876 	for(i=0,ni=m_nodes.size();i<ni;++i)
877 	{
878 		if(m_nodes[i].m_im<=0) tmass+=kmass;
879 	}
880 	for( i=0,ni=m_nodes.size();i<ni;++i)
881 	{
882 		Node&	n=m_nodes[i];
883 		m_pose.m_wgh[i]=	n.m_im>0					?
884 			1/(m_nodes[i].m_im*tmass)	:
885 		kmass/tmass;
886 	}
887 	/* Pos		*/
888 	const btVector3	com=evaluateCom();
889 	m_pose.m_pos.resize(m_nodes.size());
890 	for( i=0,ni=m_nodes.size();i<ni;++i)
891 	{
892 		m_pose.m_pos[i]=m_nodes[i].m_x-com;
893 	}
894 	m_pose.m_volume	=	bvolume?getVolume():0;
895 	m_pose.m_com	=	com;
896 	m_pose.m_rot.setIdentity();
897 	m_pose.m_scl.setIdentity();
898 	/* Aqq		*/
899 	m_pose.m_aqq[0]	=
900 		m_pose.m_aqq[1]	=
901 		m_pose.m_aqq[2]	=	btVector3(0,0,0);
902 	for( i=0,ni=m_nodes.size();i<ni;++i)
903 	{
904 		const btVector3&	q=m_pose.m_pos[i];
905 		const btVector3		mq=m_pose.m_wgh[i]*q;
906 		m_pose.m_aqq[0]+=mq.x()*q;
907 		m_pose.m_aqq[1]+=mq.y()*q;
908 		m_pose.m_aqq[2]+=mq.z()*q;
909 	}
910 	m_pose.m_aqq=m_pose.m_aqq.inverse();
911 
912 	updateConstants();
913 }
914 
resetLinkRestLengths()915 void				btSoftBody::resetLinkRestLengths()
916 {
917 	for(int i=0, ni=m_links.size();i<ni;++i)
918 	{
919 		Link& l =	m_links[i];
920 		l.m_rl	=	(l.m_n[0]->m_x-l.m_n[1]->m_x).length();
921 		l.m_c1	=	l.m_rl*l.m_rl;
922 	}
923 }
924 
925 //
getVolume() const926 btScalar		btSoftBody::getVolume() const
927 {
928 	btScalar	vol=0;
929 	if(m_nodes.size()>0)
930 	{
931 		int i,ni;
932 
933 		const btVector3	org=m_nodes[0].m_x;
934 		for(i=0,ni=m_faces.size();i<ni;++i)
935 		{
936 			const Face&	f=m_faces[i];
937 			vol+=btDot(f.m_n[0]->m_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
938 		}
939 		vol/=(btScalar)6;
940 	}
941 	return(vol);
942 }
943 
944 //
clusterCount() const945 int				btSoftBody::clusterCount() const
946 {
947 	return(m_clusters.size());
948 }
949 
950 //
clusterCom(const Cluster * cluster)951 btVector3		btSoftBody::clusterCom(const Cluster* cluster)
952 {
953 	btVector3		com(0,0,0);
954 	for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
955 	{
956 		com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
957 	}
958 	return(com*cluster->m_imass);
959 }
960 
961 //
clusterCom(int cluster) const962 btVector3		btSoftBody::clusterCom(int cluster) const
963 {
964 	return(clusterCom(m_clusters[cluster]));
965 }
966 
967 //
clusterVelocity(const Cluster * cluster,const btVector3 & rpos)968 btVector3		btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
969 {
970 	return(cluster->m_lv+btCross(cluster->m_av,rpos));
971 }
972 
973 //
clusterVImpulse(Cluster * cluster,const btVector3 & rpos,const btVector3 & impulse)974 void			btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
975 {
976 	const btVector3	li=cluster->m_imass*impulse;
977 	const btVector3	ai=cluster->m_invwi*btCross(rpos,impulse);
978 	cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
979 	cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
980 	cluster->m_nvimpulses++;
981 }
982 
983 //
clusterDImpulse(Cluster * cluster,const btVector3 & rpos,const btVector3 & impulse)984 void			btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
985 {
986 	const btVector3	li=cluster->m_imass*impulse;
987 	const btVector3	ai=cluster->m_invwi*btCross(rpos,impulse);
988 	cluster->m_dimpulses[0]+=li;
989 	cluster->m_dimpulses[1]+=ai;
990 	cluster->m_ndimpulses++;
991 }
992 
993 //
clusterImpulse(Cluster * cluster,const btVector3 & rpos,const Impulse & impulse)994 void			btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
995 {
996 	if(impulse.m_asVelocity)	clusterVImpulse(cluster,rpos,impulse.m_velocity);
997 	if(impulse.m_asDrift)		clusterDImpulse(cluster,rpos,impulse.m_drift);
998 }
999 
1000 //
clusterVAImpulse(Cluster * cluster,const btVector3 & impulse)1001 void			btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
1002 {
1003 	const btVector3	ai=cluster->m_invwi*impulse;
1004 	cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
1005 	cluster->m_nvimpulses++;
1006 }
1007 
1008 //
clusterDAImpulse(Cluster * cluster,const btVector3 & impulse)1009 void			btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
1010 {
1011 	const btVector3	ai=cluster->m_invwi*impulse;
1012 	cluster->m_dimpulses[1]+=ai;
1013 	cluster->m_ndimpulses++;
1014 }
1015 
1016 //
clusterAImpulse(Cluster * cluster,const Impulse & impulse)1017 void			btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
1018 {
1019 	if(impulse.m_asVelocity)	clusterVAImpulse(cluster,impulse.m_velocity);
1020 	if(impulse.m_asDrift)		clusterDAImpulse(cluster,impulse.m_drift);
1021 }
1022 
1023 //
clusterDCImpulse(Cluster * cluster,const btVector3 & impulse)1024 void			btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
1025 {
1026 	cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
1027 	cluster->m_ndimpulses++;
1028 }
1029 
1030 struct NodeLinks
1031 {
1032     btAlignedObjectArray<int> m_links;
1033 };
1034 
1035 
1036 
1037 //
generateBendingConstraints(int distance,Material * mat)1038 int				btSoftBody::generateBendingConstraints(int distance,Material* mat)
1039 {
1040 	int i,j;
1041 
1042 	if(distance>1)
1043 	{
1044 		/* Build graph	*/
1045 		const int		n=m_nodes.size();
1046 		const unsigned	inf=(~(unsigned)0)>>1;
1047 		unsigned*		adj=new unsigned[n*n];
1048 
1049 
1050 #define IDX(_x_,_y_)	((_y_)*n+(_x_))
1051 		for(j=0;j<n;++j)
1052 		{
1053 			for(i=0;i<n;++i)
1054 			{
1055 				if(i!=j)
1056 				{
1057 					adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
1058 				}
1059 				else
1060 				{
1061 					adj[IDX(i,j)]=adj[IDX(j,i)]=0;
1062 				}
1063 			}
1064 		}
1065 		for( i=0;i<m_links.size();++i)
1066 		{
1067 			const int	ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
1068 			const int	ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
1069 			adj[IDX(ia,ib)]=1;
1070 			adj[IDX(ib,ia)]=1;
1071 		}
1072 
1073 
1074 		//special optimized case for distance == 2
1075 		if (distance == 2)
1076 		{
1077 
1078 			btAlignedObjectArray<NodeLinks> nodeLinks;
1079 
1080 
1081 			/* Build node links */
1082 			nodeLinks.resize(m_nodes.size());
1083 
1084 			for( i=0;i<m_links.size();++i)
1085 			{
1086 				const int	ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
1087 				const int	ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
1088 				if (nodeLinks[ia].m_links.findLinearSearch(ib)==nodeLinks[ia].m_links.size())
1089 					nodeLinks[ia].m_links.push_back(ib);
1090 
1091 				if (nodeLinks[ib].m_links.findLinearSearch(ia)==nodeLinks[ib].m_links.size())
1092 					nodeLinks[ib].m_links.push_back(ia);
1093 			}
1094 			for (int ii=0;ii<nodeLinks.size();ii++)
1095 			{
1096 				int i=ii;
1097 
1098 				for (int jj=0;jj<nodeLinks[ii].m_links.size();jj++)
1099 				{
1100 					int k = nodeLinks[ii].m_links[jj];
1101 					for (int kk=0;kk<nodeLinks[k].m_links.size();kk++)
1102 					{
1103 						int j = nodeLinks[k].m_links[kk];
1104 						if (i!=j)
1105 						{
1106 							const unsigned	sum=adj[IDX(i,k)]+adj[IDX(k,j)];
1107 							btAssert(sum==2);
1108 							if(adj[IDX(i,j)]>sum)
1109 							{
1110 								adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
1111 							}
1112 						}
1113 
1114 					}
1115 				}
1116 			}
1117 		} else
1118 		{
1119 			///generic Floyd's algorithm
1120 			for(int k=0;k<n;++k)
1121 			{
1122 				for(j=0;j<n;++j)
1123 				{
1124 					for(i=j+1;i<n;++i)
1125 					{
1126 						const unsigned	sum=adj[IDX(i,k)]+adj[IDX(k,j)];
1127 						if(adj[IDX(i,j)]>sum)
1128 						{
1129 							adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
1130 						}
1131 					}
1132 				}
1133 			}
1134 		}
1135 
1136 
1137 		/* Build links	*/
1138 		int	nlinks=0;
1139 		for(j=0;j<n;++j)
1140 		{
1141 			for(i=j+1;i<n;++i)
1142 			{
1143 				if(adj[IDX(i,j)]==(unsigned)distance)
1144 				{
1145 					appendLink(i,j,mat);
1146 					m_links[m_links.size()-1].m_bbending=1;
1147 					++nlinks;
1148 				}
1149 			}
1150 		}
1151 		delete[] adj;
1152 		return(nlinks);
1153 	}
1154 	return(0);
1155 }
1156 
1157 //
randomizeConstraints()1158 void			btSoftBody::randomizeConstraints()
1159 {
1160 	unsigned long	seed=243703;
1161 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
1162 	int i,ni;
1163 
1164 	for(i=0,ni=m_links.size();i<ni;++i)
1165 	{
1166 		btSwap(m_links[i],m_links[NEXTRAND%ni]);
1167 	}
1168 	for(i=0,ni=m_faces.size();i<ni;++i)
1169 	{
1170 		btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
1171 	}
1172 #undef NEXTRAND
1173 }
1174 
1175 //
releaseCluster(int index)1176 void			btSoftBody::releaseCluster(int index)
1177 {
1178 	Cluster*	c=m_clusters[index];
1179 	if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
1180 	c->~Cluster();
1181 	btAlignedFree(c);
1182 	m_clusters.remove(c);
1183 }
1184 
1185 //
releaseClusters()1186 void			btSoftBody::releaseClusters()
1187 {
1188 	while(m_clusters.size()>0) releaseCluster(0);
1189 }
1190 
1191 //
generateClusters(int k,int maxiterations)1192 int				btSoftBody::generateClusters(int k,int maxiterations)
1193 {
1194 	int i;
1195 	releaseClusters();
1196 	m_clusters.resize(btMin(k,m_nodes.size()));
1197 	for(i=0;i<m_clusters.size();++i)
1198 	{
1199 		m_clusters[i]			=	new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1200 		m_clusters[i]->m_collide=	true;
1201 	}
1202 	k=m_clusters.size();
1203 	if(k>0)
1204 	{
1205 		/* Initialize		*/
1206 		btAlignedObjectArray<btVector3>	centers;
1207 		btVector3						cog(0,0,0);
1208 		int								i;
1209 		for(i=0;i<m_nodes.size();++i)
1210 		{
1211 			cog+=m_nodes[i].m_x;
1212 			m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
1213 		}
1214 		cog/=(btScalar)m_nodes.size();
1215 		centers.resize(k,cog);
1216 		/* Iterate			*/
1217 		const btScalar	slope=16;
1218 		bool			changed;
1219 		int				iterations=0;
1220 		do	{
1221 			const btScalar	w=2-btMin<btScalar>(1,iterations/slope);
1222 			changed=false;
1223 			iterations++;
1224 			int i;
1225 
1226 			for(i=0;i<k;++i)
1227 			{
1228 				btVector3	c(0,0,0);
1229 				for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
1230 				{
1231 					c+=m_clusters[i]->m_nodes[j]->m_x;
1232 				}
1233 				if(m_clusters[i]->m_nodes.size())
1234 				{
1235 					c			/=	(btScalar)m_clusters[i]->m_nodes.size();
1236 					c			=	centers[i]+(c-centers[i])*w;
1237 					changed		|=	((c-centers[i]).length2()>SIMD_EPSILON);
1238 					centers[i]	=	c;
1239 					m_clusters[i]->m_nodes.resize(0);
1240 				}
1241 			}
1242 			for(i=0;i<m_nodes.size();++i)
1243 			{
1244 				const btVector3	nx=m_nodes[i].m_x;
1245 				int				kbest=0;
1246 				btScalar		kdist=ClusterMetric(centers[0],nx);
1247 				for(int j=1;j<k;++j)
1248 				{
1249 					const btScalar	d=ClusterMetric(centers[j],nx);
1250 					if(d<kdist)
1251 					{
1252 						kbest=j;
1253 						kdist=d;
1254 					}
1255 				}
1256 				m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
1257 			}
1258 		} while(changed&&(iterations<maxiterations));
1259 		/* Merge		*/
1260 		btAlignedObjectArray<int>	cids;
1261 		cids.resize(m_nodes.size(),-1);
1262 		for(i=0;i<m_clusters.size();++i)
1263 		{
1264 			for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
1265 			{
1266 				cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
1267 			}
1268 		}
1269 		for(i=0;i<m_faces.size();++i)
1270 		{
1271 			const int idx[]={	int(m_faces[i].m_n[0]-&m_nodes[0]),
1272 				int(m_faces[i].m_n[1]-&m_nodes[0]),
1273 				int(m_faces[i].m_n[2]-&m_nodes[0])};
1274 			for(int j=0;j<3;++j)
1275 			{
1276 				const int cid=cids[idx[j]];
1277 				for(int q=1;q<3;++q)
1278 				{
1279 					const int kid=idx[(j+q)%3];
1280 					if(cids[kid]!=cid)
1281 					{
1282 						if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
1283 						{
1284 							m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
1285 						}
1286 					}
1287 				}
1288 			}
1289 		}
1290 		/* Master		*/
1291 		if(m_clusters.size()>1)
1292 		{
1293 			Cluster*	pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1294 			pmaster->m_collide	=	false;
1295 			pmaster->m_nodes.reserve(m_nodes.size());
1296 			for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
1297 			m_clusters.push_back(pmaster);
1298 			btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
1299 		}
1300 		/* Terminate	*/
1301 		for(i=0;i<m_clusters.size();++i)
1302 		{
1303 			if(m_clusters[i]->m_nodes.size()==0)
1304 			{
1305 				releaseCluster(i--);
1306 			}
1307 		}
1308 	} else
1309 	{
1310 		//create a cluster for each tetrahedron (if tetrahedra exist) or each face
1311 		if (m_tetras.size())
1312 		{
1313 			m_clusters.resize(m_tetras.size());
1314 			for(i=0;i<m_clusters.size();++i)
1315 			{
1316 				m_clusters[i]			=	new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1317 				m_clusters[i]->m_collide=	true;
1318 			}
1319 			for (i=0;i<m_tetras.size();i++)
1320 			{
1321 				for (int j=0;j<4;j++)
1322 				{
1323 					m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
1324 				}
1325 			}
1326 
1327 		} else
1328 		{
1329 			m_clusters.resize(m_faces.size());
1330 			for(i=0;i<m_clusters.size();++i)
1331 			{
1332 				m_clusters[i]			=	new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1333 				m_clusters[i]->m_collide=	true;
1334 			}
1335 
1336 			for(i=0;i<m_faces.size();++i)
1337 			{
1338 				for(int j=0;j<3;++j)
1339 				{
1340 					m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
1341 				}
1342 			}
1343 		}
1344 	}
1345 
1346 	if (m_clusters.size())
1347 	{
1348 		initializeClusters();
1349 		updateClusters();
1350 
1351 
1352 		//for self-collision
1353 		m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size());
1354 		{
1355 			for (int c0=0;c0<m_clusters.size();c0++)
1356 			{
1357 				m_clusters[c0]->m_clusterIndex=c0;
1358 				for (int c1=0;c1<m_clusters.size();c1++)
1359 				{
1360 
1361 					bool connected=false;
1362 					Cluster* cla = m_clusters[c0];
1363 					Cluster* clb = m_clusters[c1];
1364 					for (int i=0;!connected&&i<cla->m_nodes.size();i++)
1365 					{
1366 						for (int j=0;j<clb->m_nodes.size();j++)
1367 						{
1368 							if (cla->m_nodes[i] == clb->m_nodes[j])
1369 							{
1370 								connected=true;
1371 								break;
1372 							}
1373 						}
1374 					}
1375 					m_clusterConnectivity[c0+c1*m_clusters.size()]=connected;
1376 				}
1377 			}
1378 		}
1379 	}
1380 
1381 	return(m_clusters.size());
1382 }
1383 
1384 //
refine(ImplicitFn * ifn,btScalar accurary,bool cut)1385 void			btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
1386 {
1387 	const Node*			nbase = &m_nodes[0];
1388 	int					ncount = m_nodes.size();
1389 	btSymMatrix<int>	edges(ncount,-2);
1390 	int					newnodes=0;
1391 	int i,j,k,ni;
1392 
1393 	/* Filter out		*/
1394 	for(i=0;i<m_links.size();++i)
1395 	{
1396 		Link&	l=m_links[i];
1397 		if(l.m_bbending)
1398 		{
1399 			if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
1400 			{
1401 				btSwap(m_links[i],m_links[m_links.size()-1]);
1402 				m_links.pop_back();--i;
1403 			}
1404 		}
1405 	}
1406 	/* Fill edges		*/
1407 	for(i=0;i<m_links.size();++i)
1408 	{
1409 		Link&	l=m_links[i];
1410 		edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
1411 	}
1412 	for(i=0;i<m_faces.size();++i)
1413 	{
1414 		Face&	f=m_faces[i];
1415 		edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
1416 		edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
1417 		edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
1418 	}
1419 	/* Intersect		*/
1420 	for(i=0;i<ncount;++i)
1421 	{
1422 		for(j=i+1;j<ncount;++j)
1423 		{
1424 			if(edges(i,j)==-1)
1425 			{
1426 				Node&			a=m_nodes[i];
1427 				Node&			b=m_nodes[j];
1428 				const btScalar	t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
1429 				if(t>0)
1430 				{
1431 					const btVector3	x=Lerp(a.m_x,b.m_x,t);
1432 					const btVector3	v=Lerp(a.m_v,b.m_v,t);
1433 					btScalar		m=0;
1434 					if(a.m_im>0)
1435 					{
1436 						if(b.m_im>0)
1437 						{
1438 							const btScalar	ma=1/a.m_im;
1439 							const btScalar	mb=1/b.m_im;
1440 							const btScalar	mc=Lerp(ma,mb,t);
1441 							const btScalar	f=(ma+mb)/(ma+mb+mc);
1442 							a.m_im=1/(ma*f);
1443 							b.m_im=1/(mb*f);
1444 							m=mc*f;
1445 						}
1446 						else
1447 						{ a.m_im/=0.5f;m=1/a.m_im; }
1448 					}
1449 					else
1450 					{
1451 						if(b.m_im>0)
1452 						{ b.m_im/=0.5f;m=1/b.m_im; }
1453 						else
1454 							m=0;
1455 					}
1456 					appendNode(x,m);
1457 					edges(i,j)=m_nodes.size()-1;
1458 					m_nodes[edges(i,j)].m_v=v;
1459 					++newnodes;
1460 				}
1461 			}
1462 		}
1463 	}
1464 	nbase=&m_nodes[0];
1465 	/* Refine links		*/
1466 	for(i=0,ni=m_links.size();i<ni;++i)
1467 	{
1468 		Link&		feat=m_links[i];
1469 		const int	idx[]={	int(feat.m_n[0]-nbase),
1470 			int(feat.m_n[1]-nbase)};
1471 		if((idx[0]<ncount)&&(idx[1]<ncount))
1472 		{
1473 			const int ni=edges(idx[0],idx[1]);
1474 			if(ni>0)
1475 			{
1476 				appendLink(i);
1477 				Link*		pft[]={	&m_links[i],
1478 					&m_links[m_links.size()-1]};
1479 				pft[0]->m_n[0]=&m_nodes[idx[0]];
1480 				pft[0]->m_n[1]=&m_nodes[ni];
1481 				pft[1]->m_n[0]=&m_nodes[ni];
1482 				pft[1]->m_n[1]=&m_nodes[idx[1]];
1483 			}
1484 		}
1485 	}
1486 	/* Refine faces		*/
1487 	for(i=0;i<m_faces.size();++i)
1488 	{
1489 		const Face&	feat=m_faces[i];
1490 		const int	idx[]={	int(feat.m_n[0]-nbase),
1491 			int(feat.m_n[1]-nbase),
1492 			int(feat.m_n[2]-nbase)};
1493 		for(j=2,k=0;k<3;j=k++)
1494 		{
1495 			if((idx[j]<ncount)&&(idx[k]<ncount))
1496 			{
1497 				const int ni=edges(idx[j],idx[k]);
1498 				if(ni>0)
1499 				{
1500 					appendFace(i);
1501 					const int	l=(k+1)%3;
1502 					Face*		pft[]={	&m_faces[i],
1503 						&m_faces[m_faces.size()-1]};
1504 					pft[0]->m_n[0]=&m_nodes[idx[l]];
1505 					pft[0]->m_n[1]=&m_nodes[idx[j]];
1506 					pft[0]->m_n[2]=&m_nodes[ni];
1507 					pft[1]->m_n[0]=&m_nodes[ni];
1508 					pft[1]->m_n[1]=&m_nodes[idx[k]];
1509 					pft[1]->m_n[2]=&m_nodes[idx[l]];
1510 					appendLink(ni,idx[l],pft[0]->m_material);
1511 					--i;break;
1512 				}
1513 			}
1514 		}
1515 	}
1516 	/* Cut				*/
1517 	if(cut)
1518 	{
1519 		btAlignedObjectArray<int>	cnodes;
1520 		const int					pcount=ncount;
1521 		int							i;
1522 		ncount=m_nodes.size();
1523 		cnodes.resize(ncount,0);
1524 		/* Nodes		*/
1525 		for(i=0;i<ncount;++i)
1526 		{
1527 			const btVector3	x=m_nodes[i].m_x;
1528 			if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
1529 			{
1530 				const btVector3	v=m_nodes[i].m_v;
1531 				btScalar		m=getMass(i);
1532 				if(m>0) { m*=0.5f;m_nodes[i].m_im/=0.5f; }
1533 				appendNode(x,m);
1534 				cnodes[i]=m_nodes.size()-1;
1535 				m_nodes[cnodes[i]].m_v=v;
1536 			}
1537 		}
1538 		nbase=&m_nodes[0];
1539 		/* Links		*/
1540 		for(i=0,ni=m_links.size();i<ni;++i)
1541 		{
1542 			const int		id[]={	int(m_links[i].m_n[0]-nbase),
1543 				int(m_links[i].m_n[1]-nbase)};
1544 			int				todetach=0;
1545 			if(cnodes[id[0]]&&cnodes[id[1]])
1546 			{
1547 				appendLink(i);
1548 				todetach=m_links.size()-1;
1549 			}
1550 			else
1551 			{
1552 				if((	(ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
1553 					(ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
1554 					todetach=i;
1555 			}
1556 			if(todetach)
1557 			{
1558 				Link&	l=m_links[todetach];
1559 				for(int j=0;j<2;++j)
1560 				{
1561 					int cn=cnodes[int(l.m_n[j]-nbase)];
1562 					if(cn) l.m_n[j]=&m_nodes[cn];
1563 				}
1564 			}
1565 		}
1566 		/* Faces		*/
1567 		for(i=0,ni=m_faces.size();i<ni;++i)
1568 		{
1569 			Node**			n=	m_faces[i].m_n;
1570 			if(	(ifn->Eval(n[0]->m_x)<accurary)&&
1571 				(ifn->Eval(n[1]->m_x)<accurary)&&
1572 				(ifn->Eval(n[2]->m_x)<accurary))
1573 			{
1574 				for(int j=0;j<3;++j)
1575 				{
1576 					int cn=cnodes[int(n[j]-nbase)];
1577 					if(cn) n[j]=&m_nodes[cn];
1578 				}
1579 			}
1580 		}
1581 		/* Clean orphans	*/
1582 		int							nnodes=m_nodes.size();
1583 		btAlignedObjectArray<int>	ranks;
1584 		btAlignedObjectArray<int>	todelete;
1585 		ranks.resize(nnodes,0);
1586 		for(i=0,ni=m_links.size();i<ni;++i)
1587 		{
1588 			for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
1589 		}
1590 		for(i=0,ni=m_faces.size();i<ni;++i)
1591 		{
1592 			for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
1593 		}
1594 		for(i=0;i<m_links.size();++i)
1595 		{
1596 			const int	id[]={	int(m_links[i].m_n[0]-nbase),
1597 				int(m_links[i].m_n[1]-nbase)};
1598 			const bool	sg[]={	ranks[id[0]]==1,
1599 				ranks[id[1]]==1};
1600 			if(sg[0]||sg[1])
1601 			{
1602 				--ranks[id[0]];
1603 				--ranks[id[1]];
1604 				btSwap(m_links[i],m_links[m_links.size()-1]);
1605 				m_links.pop_back();--i;
1606 			}
1607 		}
1608 #if 0
1609 		for(i=nnodes-1;i>=0;--i)
1610 		{
1611 			if(!ranks[i]) todelete.push_back(i);
1612 		}
1613 		if(todelete.size())
1614 		{
1615 			btAlignedObjectArray<int>&	map=ranks;
1616 			for(int i=0;i<nnodes;++i) map[i]=i;
1617 			PointersToIndices(this);
1618 			for(int i=0,ni=todelete.size();i<ni;++i)
1619 			{
1620 				int		j=todelete[i];
1621 				int&	a=map[j];
1622 				int&	b=map[--nnodes];
1623 				m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1624 				btSwap(m_nodes[a],m_nodes[b]);
1625 				j=a;a=b;b=j;
1626 			}
1627 			IndicesToPointers(this,&map[0]);
1628 			m_nodes.resize(nnodes);
1629 		}
1630 #endif
1631 	}
1632 	m_bUpdateRtCst=true;
1633 }
1634 
1635 //
cutLink(const Node * node0,const Node * node1,btScalar position)1636 bool			btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
1637 {
1638 	return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
1639 }
1640 
1641 //
cutLink(int node0,int node1,btScalar position)1642 bool			btSoftBody::cutLink(int node0,int node1,btScalar position)
1643 {
1644 	bool			done=false;
1645 	int i,ni;
1646 //	const btVector3	d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1647 	const btVector3	x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
1648 	const btVector3	v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
1649 	const btScalar	m=1;
1650 	appendNode(x,m);
1651 	appendNode(x,m);
1652 	Node*			pa=&m_nodes[node0];
1653 	Node*			pb=&m_nodes[node1];
1654 	Node*			pn[2]={	&m_nodes[m_nodes.size()-2],
1655 		&m_nodes[m_nodes.size()-1]};
1656 	pn[0]->m_v=v;
1657 	pn[1]->m_v=v;
1658 	for(i=0,ni=m_links.size();i<ni;++i)
1659 	{
1660 		const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
1661 		if(mtch!=-1)
1662 		{
1663 			appendLink(i);
1664 			Link*	pft[]={&m_links[i],&m_links[m_links.size()-1]};
1665 			pft[0]->m_n[1]=pn[mtch];
1666 			pft[1]->m_n[0]=pn[1-mtch];
1667 			done=true;
1668 		}
1669 	}
1670 	for(i=0,ni=m_faces.size();i<ni;++i)
1671 	{
1672 		for(int k=2,l=0;l<3;k=l++)
1673 		{
1674 			const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
1675 			if(mtch!=-1)
1676 			{
1677 				appendFace(i);
1678 				Face*	pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
1679 				pft[0]->m_n[l]=pn[mtch];
1680 				pft[1]->m_n[k]=pn[1-mtch];
1681 				appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1682 				appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1683 			}
1684 		}
1685 	}
1686 	if(!done)
1687 	{
1688 		m_ndbvt.remove(pn[0]->m_leaf);
1689 		m_ndbvt.remove(pn[1]->m_leaf);
1690 		m_nodes.pop_back();
1691 		m_nodes.pop_back();
1692 	}
1693 	return(done);
1694 }
1695 
1696 //
rayTest(const btVector3 & rayFrom,const btVector3 & rayTo,sRayCast & results)1697 bool			btSoftBody::rayTest(const btVector3& rayFrom,
1698 									const btVector3& rayTo,
1699 									sRayCast& results)
1700 {
1701 	if(m_faces.size()&&m_fdbvt.empty())
1702 		initializeFaceTree();
1703 
1704 	results.body	=	this;
1705 	results.fraction = 1.f;
1706 	results.feature	=	eFeature::None;
1707 	results.index	=	-1;
1708 
1709 	return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0);
1710 }
1711 
1712 //
setSolver(eSolverPresets::_ preset)1713 void			btSoftBody::setSolver(eSolverPresets::_ preset)
1714 {
1715 	m_cfg.m_vsequence.clear();
1716 	m_cfg.m_psequence.clear();
1717 	m_cfg.m_dsequence.clear();
1718 	switch(preset)
1719 	{
1720 	case	eSolverPresets::Positions:
1721 		m_cfg.m_psequence.push_back(ePSolver::Anchors);
1722 		m_cfg.m_psequence.push_back(ePSolver::RContacts);
1723 		m_cfg.m_psequence.push_back(ePSolver::SContacts);
1724 		m_cfg.m_psequence.push_back(ePSolver::Linear);
1725 		break;
1726 	case	eSolverPresets::Velocities:
1727 		m_cfg.m_vsequence.push_back(eVSolver::Linear);
1728 
1729 		m_cfg.m_psequence.push_back(ePSolver::Anchors);
1730 		m_cfg.m_psequence.push_back(ePSolver::RContacts);
1731 		m_cfg.m_psequence.push_back(ePSolver::SContacts);
1732 
1733 		m_cfg.m_dsequence.push_back(ePSolver::Linear);
1734 		break;
1735 	}
1736 }
1737 
1738 //
predictMotion(btScalar dt)1739 void			btSoftBody::predictMotion(btScalar dt)
1740 {
1741 
1742 	int i,ni;
1743 
1744 	/* Update				*/
1745 	if(m_bUpdateRtCst)
1746 	{
1747 		m_bUpdateRtCst=false;
1748 		updateConstants();
1749 		m_fdbvt.clear();
1750 		if(m_cfg.collisions&fCollision::VF_SS)
1751 		{
1752 			initializeFaceTree();
1753 		}
1754 	}
1755 
1756 	/* Prepare				*/
1757 	m_sst.sdt		=	dt*m_cfg.timescale;
1758 	m_sst.isdt		=	1/m_sst.sdt;
1759 	m_sst.velmrg	=	m_sst.sdt*3;
1760 	m_sst.radmrg	=	getCollisionShape()->getMargin();
1761 	m_sst.updmrg	=	m_sst.radmrg*(btScalar)0.25;
1762 	/* Forces				*/
1763 	addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
1764 	applyForces();
1765 	/* Integrate			*/
1766 	for(i=0,ni=m_nodes.size();i<ni;++i)
1767 	{
1768 		Node&	n=m_nodes[i];
1769 		n.m_q	=	n.m_x;
1770 		btVector3 deltaV = n.m_f*n.m_im*m_sst.sdt;
1771 		{
1772 			btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
1773 			btScalar clampDeltaV = maxDisplacement/m_sst.sdt;
1774 			for (int c=0;c<3;c++)
1775 			{
1776 				if (deltaV[c]>clampDeltaV)
1777 				{
1778 					deltaV[c] = clampDeltaV;
1779 				}
1780 				if (deltaV[c]<-clampDeltaV)
1781 				{
1782 					deltaV[c]=-clampDeltaV;
1783 				}
1784 			}
1785 		}
1786 		n.m_v	+=	deltaV;
1787 		n.m_x	+=	n.m_v*m_sst.sdt;
1788 		n.m_f	=	btVector3(0,0,0);
1789 	}
1790 	/* Clusters				*/
1791 	updateClusters();
1792 	/* Bounds				*/
1793 	updateBounds();
1794 	/* Nodes				*/
1795 	ATTRIBUTE_ALIGNED16(btDbvtVolume)	vol;
1796 	for(i=0,ni=m_nodes.size();i<ni;++i)
1797 	{
1798 		Node&	n=m_nodes[i];
1799 		vol = btDbvtVolume::FromCR(n.m_x,m_sst.radmrg);
1800 		m_ndbvt.update(	n.m_leaf,
1801 			vol,
1802 			n.m_v*m_sst.velmrg,
1803 			m_sst.updmrg);
1804 	}
1805 	/* Faces				*/
1806 	if(!m_fdbvt.empty())
1807 	{
1808 		for(int i=0;i<m_faces.size();++i)
1809 		{
1810 			Face&			f=m_faces[i];
1811 			const btVector3	v=(	f.m_n[0]->m_v+
1812 				f.m_n[1]->m_v+
1813 				f.m_n[2]->m_v)/3;
1814 			vol = VolumeOf(f,m_sst.radmrg);
1815 			m_fdbvt.update(	f.m_leaf,
1816 				vol,
1817 				v*m_sst.velmrg,
1818 				m_sst.updmrg);
1819 		}
1820 	}
1821 	/* Pose					*/
1822 	updatePose();
1823 	/* Match				*/
1824 	if(m_pose.m_bframe&&(m_cfg.kMT>0))
1825 	{
1826 		const btMatrix3x3	posetrs=m_pose.m_rot;
1827 		for(int i=0,ni=m_nodes.size();i<ni;++i)
1828 		{
1829 			Node&	n=m_nodes[i];
1830 			if(n.m_im>0)
1831 			{
1832 				const btVector3	x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
1833 				n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
1834 			}
1835 		}
1836 	}
1837 	/* Clear contacts		*/
1838 	m_rcontacts.resize(0);
1839 	m_scontacts.resize(0);
1840 	/* Optimize dbvt's		*/
1841 	m_ndbvt.optimizeIncremental(1);
1842 	m_fdbvt.optimizeIncremental(1);
1843 	m_cdbvt.optimizeIncremental(1);
1844 }
1845 
1846 //
solveConstraints()1847 void			btSoftBody::solveConstraints()
1848 {
1849 
1850 	/* Apply clusters		*/
1851 	applyClusters(false);
1852 	/* Prepare links		*/
1853 
1854 	int i,ni;
1855 
1856 	for(i=0,ni=m_links.size();i<ni;++i)
1857 	{
1858 		Link&	l=m_links[i];
1859 		l.m_c3		=	l.m_n[1]->m_q-l.m_n[0]->m_q;
1860 		l.m_c2		=	1/(l.m_c3.length2()*l.m_c0);
1861 	}
1862 	/* Prepare anchors		*/
1863 	for(i=0,ni=m_anchors.size();i<ni;++i)
1864 	{
1865 		Anchor&			a=m_anchors[i];
1866 		const btVector3	ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
1867 		a.m_c0	=	ImpulseMatrix(	m_sst.sdt,
1868 			a.m_node->m_im,
1869 			a.m_body->getInvMass(),
1870 			a.m_body->getInvInertiaTensorWorld(),
1871 			ra);
1872 		a.m_c1	=	ra;
1873 		a.m_c2	=	m_sst.sdt*a.m_node->m_im;
1874 		a.m_body->activate();
1875 	}
1876 	/* Solve velocities		*/
1877 	if(m_cfg.viterations>0)
1878 	{
1879 		/* Solve			*/
1880 		for(int isolve=0;isolve<m_cfg.viterations;++isolve)
1881 		{
1882 			for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
1883 			{
1884 				getSolver(m_cfg.m_vsequence[iseq])(this,1);
1885 			}
1886 		}
1887 		/* Update			*/
1888 		for(i=0,ni=m_nodes.size();i<ni;++i)
1889 		{
1890 			Node&	n=m_nodes[i];
1891 			n.m_x	=	n.m_q+n.m_v*m_sst.sdt;
1892 		}
1893 	}
1894 	/* Solve positions		*/
1895 	if(m_cfg.piterations>0)
1896 	{
1897 		for(int isolve=0;isolve<m_cfg.piterations;++isolve)
1898 		{
1899 			const btScalar ti=isolve/(btScalar)m_cfg.piterations;
1900 			for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1901 			{
1902 				getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
1903 			}
1904 		}
1905 		const btScalar	vc=m_sst.isdt*(1-m_cfg.kDP);
1906 		for(i=0,ni=m_nodes.size();i<ni;++i)
1907 		{
1908 			Node&	n=m_nodes[i];
1909 			n.m_v	=	(n.m_x-n.m_q)*vc;
1910 			n.m_f	=	btVector3(0,0,0);
1911 		}
1912 	}
1913 	/* Solve drift			*/
1914 	if(m_cfg.diterations>0)
1915 	{
1916 		const btScalar	vcf=m_cfg.kVCF*m_sst.isdt;
1917 		for(i=0,ni=m_nodes.size();i<ni;++i)
1918 		{
1919 			Node&	n=m_nodes[i];
1920 			n.m_q	=	n.m_x;
1921 		}
1922 		for(int idrift=0;idrift<m_cfg.diterations;++idrift)
1923 		{
1924 			for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
1925 			{
1926 				getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
1927 			}
1928 		}
1929 		for(int i=0,ni=m_nodes.size();i<ni;++i)
1930 		{
1931 			Node&	n=m_nodes[i];
1932 			n.m_v	+=	(n.m_x-n.m_q)*vcf;
1933 		}
1934 	}
1935 	/* Apply clusters		*/
1936 	dampClusters();
1937 	applyClusters(true);
1938 }
1939 
1940 //
staticSolve(int iterations)1941 void			btSoftBody::staticSolve(int iterations)
1942 {
1943 	for(int isolve=0;isolve<iterations;++isolve)
1944 	{
1945 		for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1946 		{
1947 			getSolver(m_cfg.m_psequence[iseq])(this,1,0);
1948 		}
1949 	}
1950 }
1951 
1952 //
solveCommonConstraints(btSoftBody **,int,int)1953 void			btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
1954 {
1955 	/// placeholder
1956 }
1957 
1958 //
solveClusters(const btAlignedObjectArray<btSoftBody * > & bodies)1959 void			btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
1960 {
1961 	const int	nb=bodies.size();
1962 	int			iterations=0;
1963 	int i;
1964 
1965 	for(i=0;i<nb;++i)
1966 	{
1967 		iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
1968 	}
1969 	for(i=0;i<nb;++i)
1970 	{
1971 		bodies[i]->prepareClusters(iterations);
1972 	}
1973 	for(i=0;i<iterations;++i)
1974 	{
1975 		const btScalar sor=1;
1976 		for(int j=0;j<nb;++j)
1977 		{
1978 			bodies[j]->solveClusters(sor);
1979 		}
1980 	}
1981 	for(i=0;i<nb;++i)
1982 	{
1983 		bodies[i]->cleanupClusters();
1984 	}
1985 }
1986 
1987 //
integrateMotion()1988 void			btSoftBody::integrateMotion()
1989 {
1990 	/* Update			*/
1991 	updateNormals();
1992 }
1993 
1994 //
RayFromToCaster(const btVector3 & rayFrom,const btVector3 & rayTo,btScalar mxt)1995 btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt)
1996 {
1997 	m_rayFrom = rayFrom;
1998 	m_rayNormalizedDirection = (rayTo-rayFrom);
1999 	m_rayTo = rayTo;
2000 	m_mint	=	mxt;
2001 	m_face	=	0;
2002 	m_tests	=	0;
2003 }
2004 
2005 //
Process(const btDbvtNode * leaf)2006 void				btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
2007 {
2008 	btSoftBody::Face&	f=*(btSoftBody::Face*)leaf->data;
2009 	const btScalar		t=rayFromToTriangle(	m_rayFrom,m_rayTo,m_rayNormalizedDirection,
2010 		f.m_n[0]->m_x,
2011 		f.m_n[1]->m_x,
2012 		f.m_n[2]->m_x,
2013 		m_mint);
2014 	if((t>0)&&(t<m_mint))
2015 	{
2016 		m_mint=t;m_face=&f;
2017 	}
2018 	++m_tests;
2019 }
2020 
2021 //
rayFromToTriangle(const btVector3 & rayFrom,const btVector3 & rayTo,const btVector3 & rayNormalizedDirection,const btVector3 & a,const btVector3 & b,const btVector3 & c,btScalar maxt)2022 btScalar			btSoftBody::RayFromToCaster::rayFromToTriangle(	const btVector3& rayFrom,
2023 																   const btVector3& rayTo,
2024 																   const btVector3& rayNormalizedDirection,
2025 																   const btVector3& a,
2026 																   const btVector3& b,
2027 																   const btVector3& c,
2028 																   btScalar maxt)
2029 {
2030 	static const btScalar	ceps=-SIMD_EPSILON*10;
2031 	static const btScalar	teps=SIMD_EPSILON*10;
2032 
2033 	const btVector3			n=btCross(b-a,c-a);
2034 	const btScalar			d=btDot(a,n);
2035 	const btScalar			den=btDot(rayNormalizedDirection,n);
2036 	if(!btFuzzyZero(den))
2037 	{
2038 		const btScalar		num=btDot(rayFrom,n)-d;
2039 		const btScalar		t=-num/den;
2040 		if((t>teps)&&(t<maxt))
2041 		{
2042 			const btVector3	hit=rayFrom+rayNormalizedDirection*t;
2043 			if(	(btDot(n,btCross(a-hit,b-hit))>ceps)	&&
2044 				(btDot(n,btCross(b-hit,c-hit))>ceps)	&&
2045 				(btDot(n,btCross(c-hit,a-hit))>ceps))
2046 			{
2047 				return(t);
2048 			}
2049 		}
2050 	}
2051 	return(-1);
2052 }
2053 
2054 //
pointersToIndices()2055 void				btSoftBody::pointersToIndices()
2056 {
2057 #define	PTR2IDX(_p_,_b_)	reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
2058 	btSoftBody::Node*	base=m_nodes.size() ? &m_nodes[0] : 0;
2059 	int i,ni;
2060 
2061 	for(i=0,ni=m_nodes.size();i<ni;++i)
2062 	{
2063 		if(m_nodes[i].m_leaf)
2064 		{
2065 			m_nodes[i].m_leaf->data=*(void**)&i;
2066 		}
2067 	}
2068 	for(i=0,ni=m_links.size();i<ni;++i)
2069 	{
2070 		m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
2071 		m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
2072 	}
2073 	for(i=0,ni=m_faces.size();i<ni;++i)
2074 	{
2075 		m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
2076 		m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
2077 		m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
2078 		if(m_faces[i].m_leaf)
2079 		{
2080 			m_faces[i].m_leaf->data=*(void**)&i;
2081 		}
2082 	}
2083 	for(i=0,ni=m_anchors.size();i<ni;++i)
2084 	{
2085 		m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
2086 	}
2087 	for(i=0,ni=m_notes.size();i<ni;++i)
2088 	{
2089 		for(int j=0;j<m_notes[i].m_rank;++j)
2090 		{
2091 			m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
2092 		}
2093 	}
2094 #undef	PTR2IDX
2095 }
2096 
2097 //
indicesToPointers(const int * map)2098 void				btSoftBody::indicesToPointers(const int* map)
2099 {
2100 #define	IDX2PTR(_p_,_b_)	map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]):	\
2101 	(&(_b_)[(((char*)_p_)-(char*)0)])
2102 	btSoftBody::Node*	base=m_nodes.size() ? &m_nodes[0]:0;
2103 	int i,ni;
2104 
2105 	for(i=0,ni=m_nodes.size();i<ni;++i)
2106 	{
2107 		if(m_nodes[i].m_leaf)
2108 		{
2109 			m_nodes[i].m_leaf->data=&m_nodes[i];
2110 		}
2111 	}
2112 	for(i=0,ni=m_links.size();i<ni;++i)
2113 	{
2114 		m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
2115 		m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
2116 	}
2117 	for(i=0,ni=m_faces.size();i<ni;++i)
2118 	{
2119 		m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
2120 		m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
2121 		m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
2122 		if(m_faces[i].m_leaf)
2123 		{
2124 			m_faces[i].m_leaf->data=&m_faces[i];
2125 		}
2126 	}
2127 	for(i=0,ni=m_anchors.size();i<ni;++i)
2128 	{
2129 		m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
2130 	}
2131 	for(i=0,ni=m_notes.size();i<ni;++i)
2132 	{
2133 		for(int j=0;j<m_notes[i].m_rank;++j)
2134 		{
2135 			m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
2136 		}
2137 	}
2138 #undef	IDX2PTR
2139 }
2140 
2141 //
rayTest(const btVector3 & rayFrom,const btVector3 & rayTo,btScalar & mint,eFeature::_ & feature,int & index,bool bcountonly) const2142 int					btSoftBody::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
2143 										btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
2144 {
2145 	int	cnt=0;
2146 	btVector3 dir = rayTo-rayFrom;
2147 
2148 
2149 	if(bcountonly||m_fdbvt.empty())
2150 	{/* Full search	*/
2151 
2152 		for(int i=0,ni=m_faces.size();i<ni;++i)
2153 		{
2154 			const btSoftBody::Face&	f=m_faces[i];
2155 
2156 			const btScalar			t=RayFromToCaster::rayFromToTriangle(	rayFrom,rayTo,dir,
2157 				f.m_n[0]->m_x,
2158 				f.m_n[1]->m_x,
2159 				f.m_n[2]->m_x,
2160 				mint);
2161 			if(t>0)
2162 			{
2163 				++cnt;
2164 				if(!bcountonly)
2165 				{
2166 					feature=btSoftBody::eFeature::Face;
2167 					index=i;
2168 					mint=t;
2169 				}
2170 			}
2171 		}
2172 	}
2173 	else
2174 	{/* Use dbvt	*/
2175 		RayFromToCaster	collider(rayFrom,rayTo,mint);
2176 
2177 		btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider);
2178 		if(collider.m_face)
2179 		{
2180 			mint=collider.m_mint;
2181 			feature=btSoftBody::eFeature::Face;
2182 			index=(int)(collider.m_face-&m_faces[0]);
2183 			cnt=1;
2184 		}
2185 	}
2186 
2187 	for (int i=0;i<m_tetras.size();i++)
2188 	{
2189 		const btSoftBody::Tetra& tet = m_tetras[i];
2190 		int tetfaces[4][3] = {{0,1,2},{0,1,3},{1,2,3},{0,2,3}};
2191 		for (int f=0;f<4;f++)
2192 		{
2193 
2194 			int index0=tetfaces[f][0];
2195 			int index1=tetfaces[f][1];
2196 			int index2=tetfaces[f][2];
2197 			btVector3 v0=tet.m_n[index0]->m_x;
2198 			btVector3 v1=tet.m_n[index1]->m_x;
2199 			btVector3 v2=tet.m_n[index2]->m_x;
2200 
2201 
2202 		const btScalar			t=RayFromToCaster::rayFromToTriangle(	rayFrom,rayTo,dir,
2203 			v0,v1,v2,
2204 				mint);
2205 		if(t>0)
2206 			{
2207 				++cnt;
2208 				if(!bcountonly)
2209 				{
2210 					feature=btSoftBody::eFeature::Tetra;
2211 					index=i;
2212 					mint=t;
2213 				}
2214 			}
2215 		}
2216 	}
2217 	return(cnt);
2218 }
2219 
2220 //
initializeFaceTree()2221 void			btSoftBody::initializeFaceTree()
2222 {
2223 	m_fdbvt.clear();
2224 	for(int i=0;i<m_faces.size();++i)
2225 	{
2226 		Face&	f=m_faces[i];
2227 		f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
2228 	}
2229 }
2230 
2231 //
evaluateCom() const2232 btVector3		btSoftBody::evaluateCom() const
2233 {
2234 	btVector3	com(0,0,0);
2235 	if(m_pose.m_bframe)
2236 	{
2237 		for(int i=0,ni=m_nodes.size();i<ni;++i)
2238 		{
2239 			com+=m_nodes[i].m_x*m_pose.m_wgh[i];
2240 		}
2241 	}
2242 	return(com);
2243 }
2244 
2245 //
checkContact(const btCollisionObjectWrapper * colObjWrap,const btVector3 & x,btScalar margin,btSoftBody::sCti & cti) const2246 bool				btSoftBody::checkContact(	const btCollisionObjectWrapper* colObjWrap,
2247 											 const btVector3& x,
2248 											 btScalar margin,
2249 											 btSoftBody::sCti& cti) const
2250 {
2251 	btVector3 nrm;
2252 	const btCollisionShape *shp = colObjWrap->getCollisionShape();
2253 //	const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
2254 	//const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
2255 	const btTransform &wtr = colObjWrap->getWorldTransform();
2256 	//todo: check which transform is needed here
2257 
2258 	btScalar dst =
2259 		m_worldInfo->m_sparsesdf.Evaluate(
2260 			wtr.invXform(x),
2261 			shp,
2262 			nrm,
2263 			margin);
2264 	if(dst<0)
2265 	{
2266 		cti.m_colObj = colObjWrap->getCollisionObject();
2267 		cti.m_normal = wtr.getBasis()*nrm;
2268 		cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst );
2269 		return(true);
2270 	}
2271 	return(false);
2272 }
2273 
2274 //
updateNormals()2275 void					btSoftBody::updateNormals()
2276 {
2277 
2278 	const btVector3	zv(0,0,0);
2279 	int i,ni;
2280 
2281 	for(i=0,ni=m_nodes.size();i<ni;++i)
2282 	{
2283 		m_nodes[i].m_n=zv;
2284 	}
2285 	for(i=0,ni=m_faces.size();i<ni;++i)
2286 	{
2287 		btSoftBody::Face&	f=m_faces[i];
2288 		const btVector3		n=btCross(f.m_n[1]->m_x-f.m_n[0]->m_x,
2289 			f.m_n[2]->m_x-f.m_n[0]->m_x);
2290 		f.m_normal=n.normalized();
2291 		f.m_n[0]->m_n+=n;
2292 		f.m_n[1]->m_n+=n;
2293 		f.m_n[2]->m_n+=n;
2294 	}
2295 	for(i=0,ni=m_nodes.size();i<ni;++i)
2296 	{
2297 		btScalar len = m_nodes[i].m_n.length();
2298 		if (len>SIMD_EPSILON)
2299 			m_nodes[i].m_n /= len;
2300 	}
2301 }
2302 
2303 //
updateBounds()2304 void					btSoftBody::updateBounds()
2305 {
2306 	/*if( m_acceleratedSoftBody )
2307 	{
2308 		// If we have an accelerated softbody we need to obtain the bounds correctly
2309 		// For now (slightly hackily) just have a very large AABB
2310 		// TODO: Write get bounds kernel
2311 		// If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
2312 		// probably do a test and exchange reasonably efficiently.
2313 
2314 		m_bounds[0] = btVector3(-1000, -1000, -1000);
2315 		m_bounds[1] = btVector3(1000, 1000, 1000);
2316 
2317 	} else {*/
2318 		if(m_ndbvt.m_root)
2319 		{
2320 			const btVector3&	mins=m_ndbvt.m_root->volume.Mins();
2321 			const btVector3&	maxs=m_ndbvt.m_root->volume.Maxs();
2322 			const btScalar		csm=getCollisionShape()->getMargin();
2323 			const btVector3		mrg=btVector3(	csm,
2324 				csm,
2325 				csm)*1; // ??? to investigate...
2326 			m_bounds[0]=mins-mrg;
2327 			m_bounds[1]=maxs+mrg;
2328 			if(0!=getBroadphaseHandle())
2329 			{
2330 				m_worldInfo->m_broadphase->setAabb(	getBroadphaseHandle(),
2331 					m_bounds[0],
2332 					m_bounds[1],
2333 					m_worldInfo->m_dispatcher);
2334 			}
2335 		}
2336 		else
2337 		{
2338 			m_bounds[0]=
2339 				m_bounds[1]=btVector3(0,0,0);
2340 		}
2341 	//}
2342 }
2343 
2344 
2345 //
updatePose()2346 void					btSoftBody::updatePose()
2347 {
2348 	if(m_pose.m_bframe)
2349 	{
2350 		btSoftBody::Pose&	pose=m_pose;
2351 		const btVector3		com=evaluateCom();
2352 		/* Com			*/
2353 		pose.m_com	=	com;
2354 		/* Rotation		*/
2355 		btMatrix3x3		Apq;
2356 		const btScalar	eps=SIMD_EPSILON;
2357 		Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
2358 		Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
2359 		for(int i=0,ni=m_nodes.size();i<ni;++i)
2360 		{
2361 			const btVector3		a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
2362 			const btVector3&	b=pose.m_pos[i];
2363 			Apq[0]+=a.x()*b;
2364 			Apq[1]+=a.y()*b;
2365 			Apq[2]+=a.z()*b;
2366 		}
2367 		btMatrix3x3		r,s;
2368 		PolarDecompose(Apq,r,s);
2369 		pose.m_rot=r;
2370 		pose.m_scl=pose.m_aqq*r.transpose()*Apq;
2371 		if(m_cfg.maxvolume>1)
2372 		{
2373 			const btScalar	idet=Clamp<btScalar>(	1/pose.m_scl.determinant(),
2374 				1,m_cfg.maxvolume);
2375 			pose.m_scl=Mul(pose.m_scl,idet);
2376 		}
2377 
2378 	}
2379 }
2380 
2381 //
updateArea(bool averageArea)2382 void				btSoftBody::updateArea(bool averageArea)
2383 {
2384 	int i,ni;
2385 
2386 	/* Face area		*/
2387 	for(i=0,ni=m_faces.size();i<ni;++i)
2388 	{
2389 		Face&		f=m_faces[i];
2390 		f.m_ra	=	AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
2391 	}
2392 
2393 	/* Node area		*/
2394 
2395 	if (averageArea)
2396 	{
2397 		btAlignedObjectArray<int>	counts;
2398 		counts.resize(m_nodes.size(),0);
2399 		for(i=0,ni=m_nodes.size();i<ni;++i)
2400 		{
2401 			m_nodes[i].m_area	=	0;
2402 		}
2403 		for(i=0,ni=m_faces.size();i<ni;++i)
2404 		{
2405 			btSoftBody::Face&	f=m_faces[i];
2406 			for(int j=0;j<3;++j)
2407 			{
2408 				const int index=(int)(f.m_n[j]-&m_nodes[0]);
2409 				counts[index]++;
2410 				f.m_n[j]->m_area+=btFabs(f.m_ra);
2411 			}
2412 		}
2413 		for(i=0,ni=m_nodes.size();i<ni;++i)
2414 		{
2415 			if(counts[i]>0)
2416 				m_nodes[i].m_area/=(btScalar)counts[i];
2417 			else
2418 				m_nodes[i].m_area=0;
2419 		}
2420 	}
2421 	else
2422 	{
2423 		// initialize node area as zero
2424 		for(i=0,ni=m_nodes.size();i<ni;++i)
2425 		{
2426 			m_nodes[i].m_area=0;
2427 		}
2428 
2429 		for(i=0,ni=m_faces.size();i<ni;++i)
2430 		{
2431 			btSoftBody::Face&	f=m_faces[i];
2432 
2433 			for(int j=0;j<3;++j)
2434 			{
2435 				f.m_n[j]->m_area += f.m_ra;
2436 			}
2437 		}
2438 
2439 		for(i=0,ni=m_nodes.size();i<ni;++i)
2440 		{
2441 			m_nodes[i].m_area *= 0.3333333f;
2442 		}
2443 	}
2444 }
2445 
2446 
updateLinkConstants()2447 void				btSoftBody::updateLinkConstants()
2448 {
2449 	int i,ni;
2450 
2451 	/* Links		*/
2452 	for(i=0,ni=m_links.size();i<ni;++i)
2453 	{
2454 		Link&		l=m_links[i];
2455 		Material&	m=*l.m_material;
2456 		l.m_c0	=	(l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
2457 	}
2458 }
2459 
updateConstants()2460 void				btSoftBody::updateConstants()
2461 {
2462 	resetLinkRestLengths();
2463 	updateLinkConstants();
2464 	updateArea();
2465 }
2466 
2467 
2468 
2469 //
initializeClusters()2470 void					btSoftBody::initializeClusters()
2471 {
2472 	int i;
2473 
2474 	for( i=0;i<m_clusters.size();++i)
2475 	{
2476 		Cluster&	c=*m_clusters[i];
2477 		c.m_imass=0;
2478 		c.m_masses.resize(c.m_nodes.size());
2479 		for(int j=0;j<c.m_nodes.size();++j)
2480 		{
2481 			if (c.m_nodes[j]->m_im==0)
2482 			{
2483 				c.m_containsAnchor = true;
2484 				c.m_masses[j]	=	BT_LARGE_FLOAT;
2485 			} else
2486 			{
2487 				c.m_masses[j]	=	btScalar(1.)/c.m_nodes[j]->m_im;
2488 			}
2489 			c.m_imass		+=	c.m_masses[j];
2490 		}
2491 		c.m_imass		=	btScalar(1.)/c.m_imass;
2492 		c.m_com			=	btSoftBody::clusterCom(&c);
2493 		c.m_lv			=	btVector3(0,0,0);
2494 		c.m_av			=	btVector3(0,0,0);
2495 		c.m_leaf		=	0;
2496 		/* Inertia	*/
2497 		btMatrix3x3&	ii=c.m_locii;
2498 		ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
2499 		{
2500 			int i,ni;
2501 
2502 			for(i=0,ni=c.m_nodes.size();i<ni;++i)
2503 			{
2504 				const btVector3	k=c.m_nodes[i]->m_x-c.m_com;
2505 				const btVector3	q=k*k;
2506 				const btScalar	m=c.m_masses[i];
2507 				ii[0][0]	+=	m*(q[1]+q[2]);
2508 				ii[1][1]	+=	m*(q[0]+q[2]);
2509 				ii[2][2]	+=	m*(q[0]+q[1]);
2510 				ii[0][1]	-=	m*k[0]*k[1];
2511 				ii[0][2]	-=	m*k[0]*k[2];
2512 				ii[1][2]	-=	m*k[1]*k[2];
2513 			}
2514 		}
2515 		ii[1][0]=ii[0][1];
2516 		ii[2][0]=ii[0][2];
2517 		ii[2][1]=ii[1][2];
2518 
2519 		ii = ii.inverse();
2520 
2521 		/* Frame	*/
2522 		c.m_framexform.setIdentity();
2523 		c.m_framexform.setOrigin(c.m_com);
2524 		c.m_framerefs.resize(c.m_nodes.size());
2525 		{
2526 			int i;
2527 			for(i=0;i<c.m_framerefs.size();++i)
2528 			{
2529 				c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
2530 			}
2531 		}
2532 	}
2533 }
2534 
2535 //
updateClusters()2536 void					btSoftBody::updateClusters()
2537 {
2538 	BT_PROFILE("UpdateClusters");
2539 	int i;
2540 
2541 	for(i=0;i<m_clusters.size();++i)
2542 	{
2543 		btSoftBody::Cluster&	c=*m_clusters[i];
2544 		const int				n=c.m_nodes.size();
2545 		//const btScalar			invn=1/(btScalar)n;
2546 		if(n)
2547 		{
2548 			/* Frame				*/
2549 			const btScalar	eps=btScalar(0.0001);
2550 			btMatrix3x3		m,r,s;
2551 			m[0]=m[1]=m[2]=btVector3(0,0,0);
2552 			m[0][0]=eps*1;
2553 			m[1][1]=eps*2;
2554 			m[2][2]=eps*3;
2555 			c.m_com=clusterCom(&c);
2556 			for(int i=0;i<c.m_nodes.size();++i)
2557 			{
2558 				const btVector3		a=c.m_nodes[i]->m_x-c.m_com;
2559 				const btVector3&	b=c.m_framerefs[i];
2560 				m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
2561 			}
2562 			PolarDecompose(m,r,s);
2563 			c.m_framexform.setOrigin(c.m_com);
2564 			c.m_framexform.setBasis(r);
2565 			/* Inertia			*/
2566 #if 1/* Constant	*/
2567 			c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
2568 #else
2569 #if 0/* Sphere	*/
2570 			const btScalar	rk=(2*c.m_extents.length2())/(5*c.m_imass);
2571 			const btVector3	inertia(rk,rk,rk);
2572 			const btVector3	iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
2573 				btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
2574 				btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
2575 
2576 			c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
2577 #else/* Actual	*/
2578 			c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
2579 			for(int i=0;i<n;++i)
2580 			{
2581 				const btVector3	k=c.m_nodes[i]->m_x-c.m_com;
2582 				const btVector3		q=k*k;
2583 				const btScalar		m=1/c.m_nodes[i]->m_im;
2584 				c.m_invwi[0][0]	+=	m*(q[1]+q[2]);
2585 				c.m_invwi[1][1]	+=	m*(q[0]+q[2]);
2586 				c.m_invwi[2][2]	+=	m*(q[0]+q[1]);
2587 				c.m_invwi[0][1]	-=	m*k[0]*k[1];
2588 				c.m_invwi[0][2]	-=	m*k[0]*k[2];
2589 				c.m_invwi[1][2]	-=	m*k[1]*k[2];
2590 			}
2591 			c.m_invwi[1][0]=c.m_invwi[0][1];
2592 			c.m_invwi[2][0]=c.m_invwi[0][2];
2593 			c.m_invwi[2][1]=c.m_invwi[1][2];
2594 			c.m_invwi=c.m_invwi.inverse();
2595 #endif
2596 #endif
2597 			/* Velocities			*/
2598 			c.m_lv=btVector3(0,0,0);
2599 			c.m_av=btVector3(0,0,0);
2600 			{
2601 				int i;
2602 
2603 				for(i=0;i<n;++i)
2604 				{
2605 					const btVector3	v=c.m_nodes[i]->m_v*c.m_masses[i];
2606 					c.m_lv	+=	v;
2607 					c.m_av	+=	btCross(c.m_nodes[i]->m_x-c.m_com,v);
2608 				}
2609 			}
2610 			c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
2611 			c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
2612 			c.m_vimpulses[0]	=
2613 				c.m_vimpulses[1]	= btVector3(0,0,0);
2614 			c.m_dimpulses[0]	=
2615 				c.m_dimpulses[1]	= btVector3(0,0,0);
2616 			c.m_nvimpulses		= 0;
2617 			c.m_ndimpulses		= 0;
2618 			/* Matching				*/
2619 			if(c.m_matching>0)
2620 			{
2621 				for(int j=0;j<c.m_nodes.size();++j)
2622 				{
2623 					Node&			n=*c.m_nodes[j];
2624 					const btVector3	x=c.m_framexform*c.m_framerefs[j];
2625 					n.m_x=Lerp(n.m_x,x,c.m_matching);
2626 				}
2627 			}
2628 			/* Dbvt					*/
2629 			if(c.m_collide)
2630 			{
2631 				btVector3	mi=c.m_nodes[0]->m_x;
2632 				btVector3	mx=mi;
2633 				for(int j=1;j<n;++j)
2634 				{
2635 					mi.setMin(c.m_nodes[j]->m_x);
2636 					mx.setMax(c.m_nodes[j]->m_x);
2637 				}
2638 				ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(mi,mx);
2639 				if(c.m_leaf)
2640 					m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
2641 				else
2642 					c.m_leaf=m_cdbvt.insert(bounds,&c);
2643 			}
2644 		}
2645 	}
2646 
2647 
2648 }
2649 
2650 
2651 
2652 
2653 //
cleanupClusters()2654 void					btSoftBody::cleanupClusters()
2655 {
2656 	for(int i=0;i<m_joints.size();++i)
2657 	{
2658 		m_joints[i]->Terminate(m_sst.sdt);
2659 		if(m_joints[i]->m_delete)
2660 		{
2661 			btAlignedFree(m_joints[i]);
2662 			m_joints.remove(m_joints[i--]);
2663 		}
2664 	}
2665 }
2666 
2667 //
prepareClusters(int iterations)2668 void					btSoftBody::prepareClusters(int iterations)
2669 {
2670 	for(int i=0;i<m_joints.size();++i)
2671 	{
2672 		m_joints[i]->Prepare(m_sst.sdt,iterations);
2673 	}
2674 }
2675 
2676 
2677 //
solveClusters(btScalar sor)2678 void					btSoftBody::solveClusters(btScalar sor)
2679 {
2680 	for(int i=0,ni=m_joints.size();i<ni;++i)
2681 	{
2682 		m_joints[i]->Solve(m_sst.sdt,sor);
2683 	}
2684 }
2685 
2686 //
applyClusters(bool drift)2687 void					btSoftBody::applyClusters(bool drift)
2688 {
2689 	BT_PROFILE("ApplyClusters");
2690 //	const btScalar					f0=m_sst.sdt;
2691 	//const btScalar					f1=f0/2;
2692 	btAlignedObjectArray<btVector3> deltas;
2693 	btAlignedObjectArray<btScalar> weights;
2694 	deltas.resize(m_nodes.size(),btVector3(0,0,0));
2695 	weights.resize(m_nodes.size(),0);
2696 	int i;
2697 
2698 	if(drift)
2699 	{
2700 		for(i=0;i<m_clusters.size();++i)
2701 		{
2702 			Cluster&	c=*m_clusters[i];
2703 			if(c.m_ndimpulses)
2704 			{
2705 				c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
2706 				c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
2707 			}
2708 		}
2709 	}
2710 
2711 	for(i=0;i<m_clusters.size();++i)
2712 	{
2713 		Cluster&	c=*m_clusters[i];
2714 		if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
2715 		{
2716 			const btVector3		v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
2717 			const btVector3		w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
2718 			for(int j=0;j<c.m_nodes.size();++j)
2719 			{
2720 				const int			idx=int(c.m_nodes[j]-&m_nodes[0]);
2721 				const btVector3&	x=c.m_nodes[j]->m_x;
2722 				const btScalar		q=c.m_masses[j];
2723 				deltas[idx]		+=	(v+btCross(w,x-c.m_com))*q;
2724 				weights[idx]	+=	q;
2725 			}
2726 		}
2727 	}
2728 	for(i=0;i<deltas.size();++i)
2729 	{
2730 		if(weights[i]>0)
2731 		{
2732 			m_nodes[i].m_x+=deltas[i]/weights[i];
2733 		}
2734 	}
2735 }
2736 
2737 //
dampClusters()2738 void					btSoftBody::dampClusters()
2739 {
2740 	int i;
2741 
2742 	for(i=0;i<m_clusters.size();++i)
2743 	{
2744 		Cluster&	c=*m_clusters[i];
2745 		if(c.m_ndamping>0)
2746 		{
2747 			for(int j=0;j<c.m_nodes.size();++j)
2748 			{
2749 				Node&			n=*c.m_nodes[j];
2750 				if(n.m_im>0)
2751 				{
2752 					const btVector3	vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
2753 					if(vx.length2()<=n.m_v.length2())
2754 						{
2755 						n.m_v	+=	c.m_ndamping*(vx-n.m_v);
2756 						}
2757 				}
2758 			}
2759 		}
2760 	}
2761 }
2762 
2763 //
Prepare(btScalar dt,int)2764 void				btSoftBody::Joint::Prepare(btScalar dt,int)
2765 {
2766 	m_bodies[0].activate();
2767 	m_bodies[1].activate();
2768 }
2769 
2770 //
Prepare(btScalar dt,int iterations)2771 void				btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
2772 {
2773 	static const btScalar	maxdrift=4;
2774 	Joint::Prepare(dt,iterations);
2775 	m_rpos[0]		=	m_bodies[0].xform()*m_refs[0];
2776 	m_rpos[1]		=	m_bodies[1].xform()*m_refs[1];
2777 	m_drift			=	Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
2778 	m_rpos[0]		-=	m_bodies[0].xform().getOrigin();
2779 	m_rpos[1]		-=	m_bodies[1].xform().getOrigin();
2780 	m_massmatrix	=	ImpulseMatrix(	m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
2781 		m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
2782 	if(m_split>0)
2783 	{
2784 		m_sdrift	=	m_massmatrix*(m_drift*m_split);
2785 		m_drift		*=	1-m_split;
2786 	}
2787 	m_drift	/=(btScalar)iterations;
2788 }
2789 
2790 //
Solve(btScalar dt,btScalar sor)2791 void				btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
2792 {
2793 	const btVector3		va=m_bodies[0].velocity(m_rpos[0]);
2794 	const btVector3		vb=m_bodies[1].velocity(m_rpos[1]);
2795 	const btVector3		vr=va-vb;
2796 	btSoftBody::Impulse	impulse;
2797 	impulse.m_asVelocity	=	1;
2798 	impulse.m_velocity		=	m_massmatrix*(m_drift+vr*m_cfm)*sor;
2799 	m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2800 	m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2801 }
2802 
2803 //
Terminate(btScalar dt)2804 void				btSoftBody::LJoint::Terminate(btScalar dt)
2805 {
2806 	if(m_split>0)
2807 	{
2808 		m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2809 		m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2810 	}
2811 }
2812 
2813 //
Prepare(btScalar dt,int iterations)2814 void				btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
2815 {
2816 	static const btScalar	maxdrift=SIMD_PI/16;
2817 	m_icontrol->Prepare(this);
2818 	Joint::Prepare(dt,iterations);
2819 	m_axis[0]	=	m_bodies[0].xform().getBasis()*m_refs[0];
2820 	m_axis[1]	=	m_bodies[1].xform().getBasis()*m_refs[1];
2821 	m_drift		=	NormalizeAny(btCross(m_axis[1],m_axis[0]));
2822 	m_drift		*=	btMin(maxdrift,btAcos(Clamp<btScalar>(btDot(m_axis[0],m_axis[1]),-1,+1)));
2823 	m_drift		*=	m_erp/dt;
2824 	m_massmatrix=	AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
2825 	if(m_split>0)
2826 	{
2827 		m_sdrift	=	m_massmatrix*(m_drift*m_split);
2828 		m_drift		*=	1-m_split;
2829 	}
2830 	m_drift	/=(btScalar)iterations;
2831 }
2832 
2833 //
Solve(btScalar dt,btScalar sor)2834 void				btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
2835 {
2836 	const btVector3		va=m_bodies[0].angularVelocity();
2837 	const btVector3		vb=m_bodies[1].angularVelocity();
2838 	const btVector3		vr=va-vb;
2839 	const btScalar		sp=btDot(vr,m_axis[0]);
2840 	const btVector3		vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
2841 	btSoftBody::Impulse	impulse;
2842 	impulse.m_asVelocity	=	1;
2843 	impulse.m_velocity		=	m_massmatrix*(m_drift+vc*m_cfm)*sor;
2844 	m_bodies[0].applyAImpulse(-impulse);
2845 	m_bodies[1].applyAImpulse( impulse);
2846 }
2847 
2848 //
Terminate(btScalar dt)2849 void				btSoftBody::AJoint::Terminate(btScalar dt)
2850 {
2851 	if(m_split>0)
2852 	{
2853 		m_bodies[0].applyDAImpulse(-m_sdrift);
2854 		m_bodies[1].applyDAImpulse( m_sdrift);
2855 	}
2856 }
2857 
2858 //
Prepare(btScalar dt,int iterations)2859 void				btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
2860 {
2861 	Joint::Prepare(dt,iterations);
2862 	const bool	dodrift=(m_life==0);
2863 	m_delete=(++m_life)>m_maxlife;
2864 	if(dodrift)
2865 	{
2866 		m_drift=m_drift*m_erp/dt;
2867 		if(m_split>0)
2868 		{
2869 			m_sdrift	=	m_massmatrix*(m_drift*m_split);
2870 			m_drift		*=	1-m_split;
2871 		}
2872 		m_drift/=(btScalar)iterations;
2873 	}
2874 	else
2875 	{
2876 		m_drift=m_sdrift=btVector3(0,0,0);
2877 	}
2878 }
2879 
2880 //
Solve(btScalar dt,btScalar sor)2881 void				btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
2882 {
2883 	const btVector3		va=m_bodies[0].velocity(m_rpos[0]);
2884 	const btVector3		vb=m_bodies[1].velocity(m_rpos[1]);
2885 	const btVector3		vrel=va-vb;
2886 	const btScalar		rvac=btDot(vrel,m_normal);
2887 	btSoftBody::Impulse	impulse;
2888 	impulse.m_asVelocity	=	1;
2889 	impulse.m_velocity		=	m_drift;
2890 	if(rvac<0)
2891 	{
2892 		const btVector3	iv=m_normal*rvac;
2893 		const btVector3	fv=vrel-iv;
2894 		impulse.m_velocity	+=	iv+fv*m_friction;
2895 	}
2896 	impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
2897 
2898 	if (m_bodies[0].m_soft==m_bodies[1].m_soft)
2899 	{
2900 		if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&&
2901 			(impulse.m_velocity.getZ() ==impulse.m_velocity.getZ()))
2902 		{
2903 			if (impulse.m_asVelocity)
2904 			{
2905 				if (impulse.m_velocity.length() <m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
2906 				{
2907 
2908 				} else
2909 				{
2910 					m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]);
2911 					m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]);
2912 				}
2913 			}
2914 		}
2915 	} else
2916 	{
2917 		m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2918 		m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2919 	}
2920 }
2921 
2922 //
Terminate(btScalar dt)2923 void				btSoftBody::CJoint::Terminate(btScalar dt)
2924 {
2925 	if(m_split>0)
2926 	{
2927 		m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2928 		m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2929 	}
2930 }
2931 
2932 //
applyForces()2933 void				btSoftBody::applyForces()
2934 {
2935 
2936 	BT_PROFILE("SoftBody applyForces");
2937 //	const btScalar					dt =			m_sst.sdt;
2938 	const btScalar					kLF =			m_cfg.kLF;
2939 	const btScalar					kDG =			m_cfg.kDG;
2940 	const btScalar					kPR =			m_cfg.kPR;
2941 	const btScalar					kVC =			m_cfg.kVC;
2942 	const bool						as_lift =		kLF>0;
2943 	const bool						as_drag =		kDG>0;
2944 	const bool						as_pressure =	kPR!=0;
2945 	const bool						as_volume =		kVC>0;
2946 	const bool						as_aero =		as_lift	||
2947 													as_drag		;
2948 	//const bool						as_vaero =		as_aero	&&
2949 	//												(m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
2950 	//const bool						as_faero =		as_aero	&&
2951 	//												(m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
2952 	const bool						use_medium =	as_aero;
2953 	const bool						use_volume =	as_pressure	||
2954 		as_volume	;
2955 	btScalar						volume =		0;
2956 	btScalar						ivolumetp =		0;
2957 	btScalar						dvolumetv =		0;
2958 	btSoftBody::sMedium	medium;
2959 	if(use_volume)
2960 	{
2961 		volume		=	getVolume();
2962 		ivolumetp	=	1/btFabs(volume)*kPR;
2963 		dvolumetv	=	(m_pose.m_volume-volume)*kVC;
2964 	}
2965 	/* Per vertex forces			*/
2966 	int i,ni;
2967 
2968 	for(i=0,ni=m_nodes.size();i<ni;++i)
2969 	{
2970 		btSoftBody::Node&	n=m_nodes[i];
2971 		if(n.m_im>0)
2972 		{
2973 			if(use_medium)
2974 			{
2975 				/* Aerodynamics			*/
2976 				addAeroForceToNode(m_windVelocity, i);
2977 			}
2978 			/* Pressure				*/
2979 			if(as_pressure)
2980 			{
2981 				n.m_f	+=	n.m_n*(n.m_area*ivolumetp);
2982 			}
2983 			/* Volume				*/
2984 			if(as_volume)
2985 			{
2986 				n.m_f	+=	n.m_n*(n.m_area*dvolumetv);
2987 			}
2988 		}
2989 	}
2990 
2991 	/* Per face forces				*/
2992 	for(i=0,ni=m_faces.size();i<ni;++i)
2993 	{
2994 	//	btSoftBody::Face&	f=m_faces[i];
2995 
2996 		/* Aerodynamics			*/
2997 		addAeroForceToFace(m_windVelocity, i);
2998 	}
2999 }
3000 
3001 //
PSolve_Anchors(btSoftBody * psb,btScalar kst,btScalar ti)3002 void				btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
3003 {
3004 	const btScalar	kAHR=psb->m_cfg.kAHR*kst;
3005 	const btScalar	dt=psb->m_sst.sdt;
3006 	for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
3007 	{
3008 		const Anchor&		a=psb->m_anchors[i];
3009 		const btTransform&	t=a.m_body->getWorldTransform();
3010 		Node&				n=*a.m_node;
3011 		const btVector3		wa=t*a.m_local;
3012 		const btVector3		va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
3013 		const btVector3		vb=n.m_x-n.m_q;
3014 		const btVector3		vr=(va-vb)+(wa-n.m_x)*kAHR;
3015 		const btVector3		impulse=a.m_c0*vr*a.m_influence;
3016 		n.m_x+=impulse*a.m_c2;
3017 		a.m_body->applyImpulse(-impulse,a.m_c1);
3018 	}
3019 }
3020 
3021 //
PSolve_RContacts(btSoftBody * psb,btScalar kst,btScalar ti)3022 void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
3023 {
3024 	const btScalar	dt = psb->m_sst.sdt;
3025 	const btScalar	mrg = psb->getCollisionShape()->getMargin();
3026 	for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
3027 	{
3028 		const RContact&		c = psb->m_rcontacts[i];
3029 		const sCti&			cti = c.m_cti;
3030 		if (cti.m_colObj->hasContactResponse())
3031 		{
3032 			btRigidBody* tmpRigid = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
3033 			const btVector3		va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0);
3034 			const btVector3		vb = c.m_node->m_x-c.m_node->m_q;
3035 			const btVector3		vr = vb-va;
3036 			const btScalar		dn = btDot(vr, cti.m_normal);
3037 			if(dn<=SIMD_EPSILON)
3038 			{
3039 				const btScalar		dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg );
3040 				const btVector3		fv = vr - (cti.m_normal * dn);
3041 				// c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
3042 				const btVector3		impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst );
3043 				c.m_node->m_x -= impulse * c.m_c2;
3044 				if (tmpRigid)
3045 					tmpRigid->applyImpulse(impulse,c.m_c1);
3046 			}
3047 		}
3048 	}
3049 }
3050 
3051 //
PSolve_SContacts(btSoftBody * psb,btScalar,btScalar ti)3052 void				btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
3053 {
3054 	for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
3055 	{
3056 		const SContact&		c=psb->m_scontacts[i];
3057 		const btVector3&	nr=c.m_normal;
3058 		Node&				n=*c.m_node;
3059 		Face&				f=*c.m_face;
3060 		const btVector3		p=BaryEval(	f.m_n[0]->m_x,
3061 			f.m_n[1]->m_x,
3062 			f.m_n[2]->m_x,
3063 			c.m_weights);
3064 		const btVector3		q=BaryEval(	f.m_n[0]->m_q,
3065 			f.m_n[1]->m_q,
3066 			f.m_n[2]->m_q,
3067 			c.m_weights);
3068 		const btVector3		vr=(n.m_x-n.m_q)-(p-q);
3069 		btVector3			corr(0,0,0);
3070 		btScalar dot = btDot(vr,nr);
3071 		if(dot<0)
3072 		{
3073 			const btScalar	j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p));
3074 			corr+=c.m_normal*j;
3075 		}
3076 		corr			-=	ProjectOnPlane(vr,nr)*c.m_friction;
3077 		n.m_x			+=	corr*c.m_cfm[0];
3078 		f.m_n[0]->m_x	-=	corr*(c.m_cfm[1]*c.m_weights.x());
3079 		f.m_n[1]->m_x	-=	corr*(c.m_cfm[1]*c.m_weights.y());
3080 		f.m_n[2]->m_x	-=	corr*(c.m_cfm[1]*c.m_weights.z());
3081 	}
3082 }
3083 
3084 //
PSolve_Links(btSoftBody * psb,btScalar kst,btScalar ti)3085 void				btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
3086 {
3087 	for(int i=0,ni=psb->m_links.size();i<ni;++i)
3088 	{
3089 		Link&	l=psb->m_links[i];
3090 		if(l.m_c0>0)
3091 		{
3092 			Node&			a=*l.m_n[0];
3093 			Node&			b=*l.m_n[1];
3094 			const btVector3	del=b.m_x-a.m_x;
3095 			const btScalar	len=del.length2();
3096 			if (l.m_c1+len > SIMD_EPSILON)
3097 			{
3098 				const btScalar	k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
3099 				a.m_x-=del*(k*a.m_im);
3100 				b.m_x+=del*(k*b.m_im);
3101 			}
3102 		}
3103 	}
3104 }
3105 
3106 //
VSolve_Links(btSoftBody * psb,btScalar kst)3107 void				btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
3108 {
3109 	for(int i=0,ni=psb->m_links.size();i<ni;++i)
3110 	{
3111 		Link&			l=psb->m_links[i];
3112 		Node**			n=l.m_n;
3113 		const btScalar	j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
3114 		n[0]->m_v+=	l.m_c3*(j*n[0]->m_im);
3115 		n[1]->m_v-=	l.m_c3*(j*n[1]->m_im);
3116 	}
3117 }
3118 
3119 //
getSolver(ePSolver::_ solver)3120 btSoftBody::psolver_t	btSoftBody::getSolver(ePSolver::_ solver)
3121 {
3122 	switch(solver)
3123 	{
3124 	case	ePSolver::Anchors:
3125 		return(&btSoftBody::PSolve_Anchors);
3126 	case	ePSolver::Linear:
3127 		return(&btSoftBody::PSolve_Links);
3128 	case	ePSolver::RContacts:
3129 		return(&btSoftBody::PSolve_RContacts);
3130 	case	ePSolver::SContacts:
3131 		return(&btSoftBody::PSolve_SContacts);
3132 		default:
3133 		{
3134 		}
3135 	}
3136 	return(0);
3137 }
3138 
3139 //
getSolver(eVSolver::_ solver)3140 btSoftBody::vsolver_t	btSoftBody::getSolver(eVSolver::_ solver)
3141 {
3142 	switch(solver)
3143 	{
3144 	case	eVSolver::Linear:		return(&btSoftBody::VSolve_Links);
3145 		default:
3146 		{
3147 		}
3148 	}
3149 	return(0);
3150 }
3151 
3152 //
defaultCollisionHandler(const btCollisionObjectWrapper * pcoWrap)3153 void			btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
3154 {
3155 
3156 	switch(m_cfg.collisions&fCollision::RVSmask)
3157 	{
3158 	case	fCollision::SDF_RS:
3159 		{
3160 			btSoftColliders::CollideSDF_RS	docollide;
3161 			btRigidBody*		prb1=(btRigidBody*) btRigidBody::upcast(pcoWrap->getCollisionObject());
3162 			btTransform	wtr=pcoWrap->getWorldTransform();
3163 
3164 			const btTransform	ctr=pcoWrap->getWorldTransform();
3165 			const btScalar		timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
3166 			const btScalar		basemargin=getCollisionShape()->getMargin();
3167 			btVector3			mins;
3168 			btVector3			maxs;
3169 			ATTRIBUTE_ALIGNED16(btDbvtVolume)		volume;
3170 			pcoWrap->getCollisionShape()->getAabb(	pcoWrap->getWorldTransform(),
3171 				mins,
3172 				maxs);
3173 			volume=btDbvtVolume::FromMM(mins,maxs);
3174 			volume.Expand(btVector3(basemargin,basemargin,basemargin));
3175 			docollide.psb		=	this;
3176 			docollide.m_colObj1Wrap = pcoWrap;
3177 			docollide.m_rigidBody = prb1;
3178 
3179 			docollide.dynmargin	=	basemargin+timemargin;
3180 			docollide.stamargin	=	basemargin;
3181 			m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide);
3182 		}
3183 		break;
3184 	case	fCollision::CL_RS:
3185 		{
3186 			btSoftColliders::CollideCL_RS	collider;
3187 			collider.ProcessColObj(this,pcoWrap);
3188 		}
3189 		break;
3190 	}
3191 }
3192 
3193 //
defaultCollisionHandler(btSoftBody * psb)3194 void			btSoftBody::defaultCollisionHandler(btSoftBody* psb)
3195 {
3196 	const int cf=m_cfg.collisions&psb->m_cfg.collisions;
3197 	switch(cf&fCollision::SVSmask)
3198 	{
3199 	case	fCollision::CL_SS:
3200 		{
3201 
3202 			//support self-collision if CL_SELF flag set
3203 			if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF)
3204 			{
3205 				btSoftColliders::CollideCL_SS	docollide;
3206 				docollide.ProcessSoftSoft(this,psb);
3207 			}
3208 
3209 		}
3210 		break;
3211 	case	fCollision::VF_SS:
3212 		{
3213 			//only self-collision for Cluster, not Vertex-Face yet
3214 			if (this!=psb)
3215 			{
3216 				btSoftColliders::CollideVF_SS	docollide;
3217 				/* common					*/
3218 				docollide.mrg=	getCollisionShape()->getMargin()+
3219 					psb->getCollisionShape()->getMargin();
3220 				/* psb0 nodes vs psb1 faces	*/
3221 				docollide.psb[0]=this;
3222 				docollide.psb[1]=psb;
3223 				docollide.psb[0]->m_ndbvt.collideTT(	docollide.psb[0]->m_ndbvt.m_root,
3224 					docollide.psb[1]->m_fdbvt.m_root,
3225 					docollide);
3226 				/* psb1 nodes vs psb0 faces	*/
3227 				docollide.psb[0]=psb;
3228 				docollide.psb[1]=this;
3229 				docollide.psb[0]->m_ndbvt.collideTT(	docollide.psb[0]->m_ndbvt.m_root,
3230 					docollide.psb[1]->m_fdbvt.m_root,
3231 					docollide);
3232 			}
3233 		}
3234 		break;
3235 	default:
3236 		{
3237 
3238 		}
3239 	}
3240 }
3241 
3242 
3243 
setWindVelocity(const btVector3 & velocity)3244 void btSoftBody::setWindVelocity( const btVector3 &velocity )
3245 {
3246 	m_windVelocity = velocity;
3247 }
3248 
3249 
getWindVelocity()3250 const btVector3& btSoftBody::getWindVelocity()
3251 {
3252 	return m_windVelocity;
3253 }
3254 
3255 
3256 
calculateSerializeBufferSize() const3257 int	btSoftBody::calculateSerializeBufferSize()	const
3258 {
3259 	int sz = sizeof(btSoftBodyData);
3260 	return sz;
3261 }
3262 
3263 	///fills the dataBuffer and returns the struct name (and 0 on failure)
serialize(void * dataBuffer,class btSerializer * serializer) const3264 const char*	btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
3265 {
3266 	btSoftBodyData* sbd = (btSoftBodyData*) dataBuffer;
3267 
3268 	btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
3269 
3270 	btHashMap<btHashPtr,int>	m_nodeIndexMap;
3271 
3272 	sbd->m_numMaterials = m_materials.size();
3273 	sbd->m_materials = sbd->m_numMaterials? (SoftBodyMaterialData**) serializer->getUniquePointer((void*)&m_materials): 0;
3274 
3275 	if (sbd->m_materials)
3276 	{
3277 		int sz = sizeof(SoftBodyMaterialData*);
3278 		int numElem = sbd->m_numMaterials;
3279 		btChunk* chunk = serializer->allocate(sz,numElem);
3280 		//SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
3281 		SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
3282 		for (int i=0;i<numElem;i++,memPtr++)
3283 		{
3284 			btSoftBody::Material* mat = m_materials[i];
3285 			*memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
3286 			if (!serializer->findPointer(mat))
3287 			{
3288 				//serialize it here
3289 				btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData),1);
3290 				SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr;
3291 				memPtr->m_flags = mat->m_flags;
3292 				memPtr->m_angularStiffness = mat->m_kAST;
3293 				memPtr->m_linearStiffness = mat->m_kLST;
3294 				memPtr->m_volumeStiffness = mat->m_kVST;
3295 				serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_SBMATERIAL_CODE,mat);
3296 			}
3297 		}
3298 		serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_ARRAY_CODE,(void*) &m_materials);
3299 	}
3300 
3301 
3302 
3303 
3304 	sbd->m_numNodes = m_nodes.size();
3305 	sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes): 0;
3306 	if (sbd->m_nodes)
3307 	{
3308 		int sz = sizeof(SoftBodyNodeData);
3309 		int numElem = sbd->m_numNodes;
3310 		btChunk* chunk = serializer->allocate(sz,numElem);
3311 		SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
3312 		for (int i=0;i<numElem;i++,memPtr++)
3313 		{
3314 			m_nodes[i].m_f.serializeFloat( memPtr->m_accumulatedForce);
3315 			memPtr->m_area = m_nodes[i].m_area;
3316 			memPtr->m_attach = m_nodes[i].m_battach;
3317 			memPtr->m_inverseMass = m_nodes[i].m_im;
3318 			memPtr->m_material = m_nodes[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_nodes[i].m_material):0;
3319 			m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
3320 			m_nodes[i].m_x.serializeFloat(memPtr->m_position);
3321 			m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
3322 			m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
3323 			m_nodeIndexMap.insert(&m_nodes[i],i);
3324 		}
3325 		serializer->finalizeChunk(chunk,"SoftBodyNodeData",BT_SBNODE_CODE,(void*) &m_nodes);
3326 	}
3327 
3328 	sbd->m_numLinks = m_links.size();
3329 	sbd->m_links = sbd->m_numLinks? (SoftBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0;
3330 	if (sbd->m_links)
3331 	{
3332 		int sz = sizeof(SoftBodyLinkData);
3333 		int numElem = sbd->m_numLinks;
3334 		btChunk* chunk = serializer->allocate(sz,numElem);
3335 		SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
3336 		for (int i=0;i<numElem;i++,memPtr++)
3337 		{
3338 			memPtr->m_bbending = m_links[i].m_bbending;
3339 			memPtr->m_material = m_links[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_links[i].m_material):0;
3340 			memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0]: -1;
3341 			memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0]: -1;
3342 			btAssert(memPtr->m_nodeIndices[0]<m_nodes.size());
3343 			btAssert(memPtr->m_nodeIndices[1]<m_nodes.size());
3344 			memPtr->m_restLength = m_links[i].m_rl;
3345 		}
3346 		serializer->finalizeChunk(chunk,"SoftBodyLinkData",BT_ARRAY_CODE,(void*) &m_links[0]);
3347 
3348 	}
3349 
3350 
3351 	sbd->m_numFaces = m_faces.size();
3352 	sbd->m_faces = sbd->m_numFaces? (SoftBodyFaceData*) serializer->getUniquePointer((void*)&m_faces[0]):0;
3353 	if (sbd->m_faces)
3354 	{
3355 		int sz = sizeof(SoftBodyFaceData);
3356 		int numElem = sbd->m_numFaces;
3357 		btChunk* chunk = serializer->allocate(sz,numElem);
3358 		SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
3359 		for (int i=0;i<numElem;i++,memPtr++)
3360 		{
3361 			memPtr->m_material = m_faces[i].m_material ?  (SoftBodyMaterialData*) serializer->getUniquePointer((void*)m_faces[i].m_material): 0;
3362 			m_faces[i].m_normal.serializeFloat(	memPtr->m_normal);
3363 			for (int j=0;j<3;j++)
3364 			{
3365 				memPtr->m_nodeIndices[j] = m_faces[i].m_n[j]? m_faces[i].m_n[j] - &m_nodes[0]: -1;
3366 			}
3367 			memPtr->m_restArea = m_faces[i].m_ra;
3368 		}
3369 		serializer->finalizeChunk(chunk,"SoftBodyFaceData",BT_ARRAY_CODE,(void*) &m_faces[0]);
3370 	}
3371 
3372 
3373 	sbd->m_numTetrahedra = m_tetras.size();
3374 	sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*) serializer->getUniquePointer((void*)&m_tetras[0]):0;
3375 	if (sbd->m_tetrahedra)
3376 	{
3377 		int sz = sizeof(SoftBodyTetraData);
3378 		int numElem = sbd->m_numTetrahedra;
3379 		btChunk* chunk = serializer->allocate(sz,numElem);
3380 		SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
3381 		for (int i=0;i<numElem;i++,memPtr++)
3382 		{
3383 			for (int j=0;j<4;j++)
3384 			{
3385 				m_tetras[i].m_c0[j].serializeFloat(	memPtr->m_c0[j] );
3386 				memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j]? m_tetras[j].m_n[j]-&m_nodes[0] : -1;
3387 			}
3388 			memPtr->m_c1 = m_tetras[i].m_c1;
3389 			memPtr->m_c2 = m_tetras[i].m_c2;
3390 			memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_tetras[i].m_material): 0;
3391 			memPtr->m_restVolume = m_tetras[i].m_rv;
3392 		}
3393 		serializer->finalizeChunk(chunk,"SoftBodyTetraData",BT_ARRAY_CODE,(void*) &m_tetras[0]);
3394 	}
3395 
3396 	sbd->m_numAnchors = m_anchors.size();
3397 	sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*) serializer->getUniquePointer((void*)&m_anchors[0]):0;
3398 	if (sbd->m_anchors)
3399 	{
3400 		int sz = sizeof(SoftRigidAnchorData);
3401 		int numElem = sbd->m_numAnchors;
3402 		btChunk* chunk = serializer->allocate(sz,numElem);
3403 		SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr;
3404 		for (int i=0;i<numElem;i++,memPtr++)
3405 		{
3406 			m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
3407 			m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
3408 			memPtr->m_c2 = m_anchors[i].m_c2;
3409 			m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
3410 			memPtr->m_nodeIndex = m_anchors[i].m_node? m_anchors[i].m_node-&m_nodes[0]: -1;
3411 
3412 			memPtr->m_rigidBody = m_anchors[i].m_body? (btRigidBodyData*)  serializer->getUniquePointer((void*)m_anchors[i].m_body): 0;
3413 			btAssert(memPtr->m_nodeIndex < m_nodes.size());
3414 		}
3415 		serializer->finalizeChunk(chunk,"SoftRigidAnchorData",BT_ARRAY_CODE,(void*) &m_anchors[0]);
3416 	}
3417 
3418 
3419 	sbd->m_config.m_dynamicFriction = m_cfg.kDF;
3420 	sbd->m_config.m_baumgarte = m_cfg.kVCF;
3421 	sbd->m_config.m_pressure = m_cfg.kPR;
3422 	sbd->m_config.m_aeroModel = this->m_cfg.aeromodel;
3423 	sbd->m_config.m_lift = m_cfg.kLF;
3424 	sbd->m_config.m_drag = m_cfg.kDG;
3425 	sbd->m_config.m_positionIterations = m_cfg.piterations;
3426 	sbd->m_config.m_driftIterations = m_cfg.diterations;
3427 	sbd->m_config.m_clusterIterations = m_cfg.citerations;
3428 	sbd->m_config.m_velocityIterations = m_cfg.viterations;
3429 	sbd->m_config.m_maxVolume = m_cfg.maxvolume;
3430 	sbd->m_config.m_damping = m_cfg.kDP;
3431 	sbd->m_config.m_poseMatch = m_cfg.kMT;
3432 	sbd->m_config.m_collisionFlags = m_cfg.collisions;
3433 	sbd->m_config.m_volume = m_cfg.kVC;
3434 	sbd->m_config.m_rigidContactHardness = m_cfg.kCHR;
3435 	sbd->m_config.m_kineticContactHardness = m_cfg.kKHR;
3436 	sbd->m_config.m_softContactHardness = m_cfg.kSHR;
3437 	sbd->m_config.m_anchorHardness = m_cfg.kAHR;
3438 	sbd->m_config.m_timeScale = m_cfg.timescale;
3439 	sbd->m_config.m_maxVolume = m_cfg.maxvolume;
3440 	sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL;
3441 	sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL;
3442 	sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL;
3443 	sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL;
3444 	sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL;
3445 	sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL;
3446 
3447 	//pose for shape matching
3448 	{
3449 		sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
3450 
3451 		int sz = sizeof(SoftBodyPoseData);
3452 		btChunk* chunk = serializer->allocate(sz,1);
3453 		SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
3454 
3455 		m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
3456 		memPtr->m_bframe = m_pose.m_bframe;
3457 		memPtr->m_bvolume = m_pose.m_bvolume;
3458 		m_pose.m_com.serializeFloat(memPtr->m_com);
3459 
3460 		memPtr->m_numPositions = m_pose.m_pos.size();
3461 		memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]): 0;
3462 		if (memPtr->m_numPositions)
3463 		{
3464 			int numElem = memPtr->m_numPositions;
3465 			int sz = sizeof(btVector3Data);
3466 			btChunk* chunk = serializer->allocate(sz,numElem);
3467 			btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
3468 			for (int i=0;i<numElem;i++,memPtr++)
3469 			{
3470 				m_pose.m_pos[i].serializeFloat(*memPtr);
3471 			}
3472 			serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_pose.m_pos[0]);
3473 		}
3474 		memPtr->m_restVolume = m_pose.m_volume;
3475 		m_pose.m_rot.serializeFloat(memPtr->m_rot);
3476 		m_pose.m_scl.serializeFloat(memPtr->m_scale);
3477 
3478 		memPtr->m_numWeigts = m_pose.m_wgh.size();
3479 		memPtr->m_weights = memPtr->m_numWeigts? (float*) serializer->getUniquePointer((void*) &m_pose.m_wgh[0]) : 0;
3480 		if (memPtr->m_numWeigts)
3481 		{
3482 
3483 			int numElem = memPtr->m_numWeigts;
3484 			int sz = sizeof(float);
3485 			btChunk* chunk = serializer->allocate(sz,numElem);
3486 			float* memPtr = (float*) chunk->m_oldPtr;
3487 			for (int i=0;i<numElem;i++,memPtr++)
3488 			{
3489 				*memPtr = m_pose.m_wgh[i];
3490 			}
3491 			serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_pose.m_wgh[0]);
3492 		}
3493 
3494 		serializer->finalizeChunk(chunk,"SoftBodyPoseData",BT_ARRAY_CODE,(void*)&m_pose);
3495 	}
3496 
3497 	//clusters for convex-cluster collision detection
3498 
3499 	sbd->m_numClusters = m_clusters.size();
3500 	sbd->m_clusters = sbd->m_numClusters? (SoftBodyClusterData*) serializer->getUniquePointer((void*)m_clusters[0]) : 0;
3501 	if (sbd->m_numClusters)
3502 	{
3503 		int numElem = sbd->m_numClusters;
3504 		int sz = sizeof(SoftBodyClusterData);
3505 		btChunk* chunk = serializer->allocate(sz,numElem);
3506 		SoftBodyClusterData* memPtr = (SoftBodyClusterData*) chunk->m_oldPtr;
3507 		for (int i=0;i<numElem;i++,memPtr++)
3508 		{
3509 			memPtr->m_adamping= m_clusters[i]->m_adamping;
3510 			m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
3511 			memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
3512 			memPtr->m_collide = m_clusters[i]->m_collide;
3513 			m_clusters[i]->m_com.serializeFloat(memPtr->m_com);
3514 			memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor;
3515 			m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]);
3516 			m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]);
3517 			m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform);
3518 			memPtr->m_idmass = m_clusters[i]->m_idmass;
3519 			memPtr->m_imass = m_clusters[i]->m_imass;
3520 			m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi);
3521 			memPtr->m_ldamping = m_clusters[i]->m_ldamping;
3522 			m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii);
3523 			m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv);
3524 			memPtr->m_matching = m_clusters[i]->m_matching;
3525 			memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse;
3526 			memPtr->m_ndamping = m_clusters[i]->m_ndamping;
3527 			memPtr->m_ldamping = m_clusters[i]->m_ldamping;
3528 			memPtr->m_adamping = m_clusters[i]->m_adamping;
3529 			memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor;
3530 
3531 			memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size();
3532 			memPtr->m_numMasses = m_clusters[i]->m_masses.size();
3533 			memPtr->m_numNodes = m_clusters[i]->m_nodes.size();
3534 
3535 			memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses;
3536 			m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]);
3537 			m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
3538 			memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
3539 
3540 
3541 
3542 			memPtr->m_framerefs = memPtr->m_numFrameRefs? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
3543 			if (memPtr->m_framerefs)
3544 			{
3545 				int numElem = memPtr->m_numFrameRefs;
3546 				int sz = sizeof(btVector3FloatData);
3547 				btChunk* chunk = serializer->allocate(sz,numElem);
3548 				btVector3FloatData* memPtr = (btVector3FloatData*) chunk->m_oldPtr;
3549 				for (int j=0;j<numElem;j++,memPtr++)
3550 				{
3551 					m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
3552 				}
3553 				serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_framerefs[0]);
3554 			}
3555 
3556 			memPtr->m_masses = memPtr->m_numMasses ? (float*) serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]): 0;
3557 			if (memPtr->m_masses)
3558 			{
3559 				int numElem = memPtr->m_numMasses;
3560 				int sz = sizeof(float);
3561 				btChunk* chunk = serializer->allocate(sz,numElem);
3562 				float* memPtr = (float*) chunk->m_oldPtr;
3563 				for (int j=0;j<numElem;j++,memPtr++)
3564 				{
3565 					*memPtr = m_clusters[i]->m_masses[j];
3566 				}
3567 				serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_masses[0]);
3568 			}
3569 
3570 			memPtr->m_nodeIndices  = memPtr->m_numNodes ? (int*) serializer->getUniquePointer((void*) &m_clusters[i]->m_nodes) : 0;
3571 			if (memPtr->m_nodeIndices )
3572 			{
3573 				int numElem = memPtr->m_numMasses;
3574 				int sz = sizeof(int);
3575 				btChunk* chunk = serializer->allocate(sz,numElem);
3576 				int* memPtr = (int*) chunk->m_oldPtr;
3577 				for (int j=0;j<numElem;j++,memPtr++)
3578 				{
3579 					int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
3580 					btAssert(indexPtr);
3581 					*memPtr = *indexPtr;
3582 				}
3583 				serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_nodes);
3584 			}
3585 		}
3586 		serializer->finalizeChunk(chunk,"SoftBodyClusterData",BT_ARRAY_CODE,(void*)m_clusters[0]);
3587 
3588 	}
3589 
3590 
3591 
3592 	sbd->m_numJoints = m_joints.size();
3593 	sbd->m_joints = m_joints.size()? (btSoftBodyJointData*) serializer->getUniquePointer((void*)&m_joints[0]) : 0;
3594 
3595 	if (sbd->m_joints)
3596 	{
3597 		int sz = sizeof(btSoftBodyJointData);
3598 		int numElem = m_joints.size();
3599 		btChunk* chunk = serializer->allocate(sz,numElem);
3600 		btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr;
3601 
3602 		for (int i=0;i<numElem;i++,memPtr++)
3603 		{
3604 			memPtr->m_jointType = (int)m_joints[i]->Type();
3605 			m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
3606 			m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]);
3607 			memPtr->m_cfm = m_joints[i]->m_cfm;
3608 			memPtr->m_erp = float(m_joints[i]->m_erp);
3609 			memPtr->m_split = float(m_joints[i]->m_split);
3610 			memPtr->m_delete = m_joints[i]->m_delete;
3611 
3612 			for (int j=0;j<4;j++)
3613 			{
3614 				memPtr->m_relPosition[0].m_floats[j] = 0.f;
3615 				memPtr->m_relPosition[1].m_floats[j] = 0.f;
3616 			}
3617 			memPtr->m_bodyA = 0;
3618 			memPtr->m_bodyB = 0;
3619 			if (m_joints[i]->m_bodies[0].m_soft)
3620 			{
3621 				memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER;
3622 				memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft);
3623 			}
3624 			if (m_joints[i]->m_bodies[0].m_collisionObject)
3625 			{
3626 				memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT;
3627 				memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject);
3628 			}
3629 			if (m_joints[i]->m_bodies[0].m_rigid)
3630 			{
3631 				memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY;
3632 				memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid);
3633 			}
3634 
3635 			if (m_joints[i]->m_bodies[1].m_soft)
3636 			{
3637 				memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER;
3638 				memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft);
3639 			}
3640 			if (m_joints[i]->m_bodies[1].m_collisionObject)
3641 			{
3642 				memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT;
3643 				memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject);
3644 			}
3645 			if (m_joints[i]->m_bodies[1].m_rigid)
3646 			{
3647 				memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY;
3648 				memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
3649 			}
3650 		}
3651 		serializer->finalizeChunk(chunk,"btSoftBodyJointData",BT_ARRAY_CODE,(void*) &m_joints[0]);
3652 	}
3653 
3654 
3655 	return btSoftBodyDataName;
3656 }
3657 
3658