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