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