Blender  V3.3
btSoftBody.cpp
Go to the documentation of this file.
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 */
16 
17 #include "btSoftBodyInternals.h"
19 #include "btSoftBodyData.h"
27 #include <iostream>
28 //
30 {
31  int N = leafNodes.size();
32  if (N == 0)
33  {
34  return NULL;
35  }
36  while (N > 1)
37  {
42  marked.resize(N);
43  for (int i = 0; i < N; ++i)
44  marked[i] = false;
45 
46  // pair adjacent nodes into new(parent) node
47  for (int i = 0; i < N; ++i)
48  {
49  if (marked[i])
50  continue;
51  bool merged = false;
52  for (int j = 0; j < adj[i].size(); ++j)
53  {
54  int n = adj[i][j];
55  if (!marked[adj[i][j]])
56  {
57  btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
58  node->parent = NULL;
59  node->childs[0] = leafNodes[i];
60  node->childs[1] = leafNodes[n];
61  leafNodes[i]->parent = node;
62  leafNodes[n]->parent = node;
63  newLeafNodes.push_back(node);
64  childIds.push_back(std::make_pair(i, n));
65  merged = true;
66  marked[n] = true;
67  break;
68  }
69  }
70  if (!merged)
71  {
72  newLeafNodes.push_back(leafNodes[i]);
73  childIds.push_back(std::make_pair(i, -1));
74  }
75  marked[i] = true;
76  }
77  // update adjacency matrix
78  newAdj.resize(newLeafNodes.size());
79  for (int i = 0; i < newLeafNodes.size(); ++i)
80  {
81  for (int j = i + 1; j < newLeafNodes.size(); ++j)
82  {
83  bool neighbor = false;
84  const btAlignedObjectArray<int>& leftChildNeighbors = adj[childIds[i].first];
85  for (int k = 0; k < leftChildNeighbors.size(); ++k)
86  {
87  if (leftChildNeighbors[k] == childIds[j].first || leftChildNeighbors[k] == childIds[j].second)
88  {
89  neighbor = true;
90  break;
91  }
92  }
93  if (!neighbor && childIds[i].second != -1)
94  {
95  const btAlignedObjectArray<int>& rightChildNeighbors = adj[childIds[i].second];
96  for (int k = 0; k < rightChildNeighbors.size(); ++k)
97  {
98  if (rightChildNeighbors[k] == childIds[j].first || rightChildNeighbors[k] == childIds[j].second)
99  {
100  neighbor = true;
101  break;
102  }
103  }
104  }
105  if (neighbor)
106  {
107  newAdj[i].push_back(j);
108  newAdj[j].push_back(i);
109  }
110  }
111  }
112  leafNodes = newLeafNodes;
113  //this assignment leaks memory, the assignment doesn't do a deep copy, for now a manual copy
114  //adj = newAdj;
115  adj.clear();
116  adj.resize(newAdj.size());
117  for (int i = 0; i < newAdj.size(); i++)
118  {
119  for (int j = 0; j < newAdj[i].size(); j++)
120  {
121  adj[i].push_back(newAdj[i][j]);
122  }
123  }
124  N = leafNodes.size();
125  }
126  return leafNodes[0];
127 }
128 
129 //
130 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
131  : m_softBodySolver(0), m_worldInfo(worldInfo)
132 {
133  /* Init */
134  initDefaults();
135 
136  /* Default material */
137  Material* pm = appendMaterial();
138  pm->m_kLST = 1;
139  pm->m_kAST = 1;
140  pm->m_kVST = 1;
142 
143  /* Nodes */
144  const btScalar margin = getCollisionShape()->getMargin();
145  m_nodes.resize(node_count);
146  m_X.resize(node_count);
147  for (int i = 0, ni = node_count; i < ni; ++i)
148  {
149  Node& n = m_nodes[i];
150  ZeroInitialize(n);
151  n.m_x = x ? *x++ : btVector3(0, 0, 0);
152  n.m_q = n.m_x;
153  n.m_im = m ? *m++ : 1;
154  n.m_im = n.m_im > 0 ? 1 / n.m_im : 0;
155  n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
156  n.m_material = pm;
157  m_X[i] = n.m_x;
158  }
159  updateBounds();
161  m_fdbvnt = 0;
162 }
163 
165  : m_worldInfo(worldInfo)
166 {
167  initDefaults();
168 }
169 
171 {
174  m_cfg.kVCF = 1;
175  m_cfg.kDG = 0;
176  m_cfg.kLF = 0;
177  m_cfg.kDP = 0;
178  m_cfg.kPR = 0;
179  m_cfg.kVC = 0;
180  m_cfg.kDF = (btScalar)0.2;
181  m_cfg.kMT = 0;
182  m_cfg.kCHR = (btScalar)1.0;
183  m_cfg.kKHR = (btScalar)0.1;
184  m_cfg.kSHR = (btScalar)1.0;
185  m_cfg.kAHR = (btScalar)0.7;
186  m_cfg.kSRHR_CL = (btScalar)0.1;
187  m_cfg.kSKHR_CL = (btScalar)1;
188  m_cfg.kSSHR_CL = (btScalar)0.5;
189  m_cfg.kSR_SPLT_CL = (btScalar)0.5;
190  m_cfg.kSK_SPLT_CL = (btScalar)0.5;
191  m_cfg.kSS_SPLT_CL = (btScalar)0.5;
192  m_cfg.maxvolume = (btScalar)1;
193  m_cfg.timescale = 1;
194  m_cfg.viterations = 0;
195  m_cfg.piterations = 1;
196  m_cfg.diterations = 0;
197  m_cfg.citerations = 4;
198  m_cfg.drag = 0;
199  m_cfg.m_maxStress = 0;
201  m_pose.m_bvolume = false;
202  m_pose.m_bframe = false;
203  m_pose.m_volume = 0;
204  m_pose.m_com = btVector3(0, 0, 0);
205  m_pose.m_rot.setIdentity();
206  m_pose.m_scl.setIdentity();
207  m_tag = 0;
208  m_timeacc = 0;
209  m_bUpdateRtCst = true;
210  m_bounds[0] = btVector3(0, 0, 0);
211  m_bounds[1] = btVector3(0, 0, 0);
212  m_worldTransform.setIdentity();
214 
215  /* Collision shape */
218  m_collisionShape->setMargin(0.25f);
219 
220  m_worldTransform.setIdentity();
221 
222  m_windVelocity = btVector3(0, 0, 0);
224  m_dampingCoefficient = 1.0;
225  m_sleepingThreshold = .04;
226  m_useSelfCollision = false;
227  m_collisionFlags = 0;
228  m_softSoftCollision = false;
229  m_maxSpeedSquared = 0;
230  m_repulsionStiffness = 0.5;
231  m_gravityFactor = 1;
232  m_fdbvnt = 0;
233 }
234 
235 //
237 {
238  //for now, delete the internal shape
239  delete m_collisionShape;
240  int i;
241 
242  releaseClusters();
243  for (i = 0; i < m_materials.size(); ++i)
245  for (i = 0; i < m_joints.size(); ++i)
247  if (m_fdbvnt)
248  delete m_fdbvnt;
249 }
250 
251 //
252 bool btSoftBody::checkLink(int node0, int node1) const
253 {
254  return (checkLink(&m_nodes[node0], &m_nodes[node1]));
255 }
256 
257 //
258 bool btSoftBody::checkLink(const Node* node0, const Node* node1) const
259 {
260  const Node* n[] = {node0, node1};
261  for (int i = 0, ni = m_links.size(); i < ni; ++i)
262  {
263  const Link& l = m_links[i];
264  if ((l.m_n[0] == n[0] && l.m_n[1] == n[1]) ||
265  (l.m_n[0] == n[1] && l.m_n[1] == n[0]))
266  {
267  return (true);
268  }
269  }
270  return (false);
271 }
272 
273 //
274 bool btSoftBody::checkFace(int node0, int node1, int node2) const
275 {
276  const Node* n[] = {&m_nodes[node0],
277  &m_nodes[node1],
278  &m_nodes[node2]};
279  for (int i = 0, ni = m_faces.size(); i < ni; ++i)
280  {
281  const Face& f = m_faces[i];
282  int c = 0;
283  for (int j = 0; j < 3; ++j)
284  {
285  if ((f.m_n[j] == n[0]) ||
286  (f.m_n[j] == n[1]) ||
287  (f.m_n[j] == n[2]))
288  c |= 1 << j;
289  else
290  break;
291  }
292  if (c == 7) return (true);
293  }
294  return (false);
295 }
296 
297 //
299 {
300  Material* pm = new (btAlignedAlloc(sizeof(Material), 16)) Material();
301  if (m_materials.size() > 0)
302  *pm = *m_materials[0];
303  else
304  ZeroInitialize(*pm);
306  return (pm);
307 }
308 
309 //
310 void btSoftBody::appendNote(const char* text,
311  const btVector3& o,
312  const btVector4& c,
313  Node* n0,
314  Node* n1,
315  Node* n2,
316  Node* n3)
317 {
318  Note n;
319  ZeroInitialize(n);
320  n.m_rank = 0;
321  n.m_text = text;
322  n.m_offset = o;
323  n.m_coords[0] = c.x();
324  n.m_coords[1] = c.y();
325  n.m_coords[2] = c.z();
326  n.m_coords[3] = c.w();
327  n.m_nodes[0] = n0;
328  n.m_rank += n0 ? 1 : 0;
329  n.m_nodes[1] = n1;
330  n.m_rank += n1 ? 1 : 0;
331  n.m_nodes[2] = n2;
332  n.m_rank += n2 ? 1 : 0;
333  n.m_nodes[3] = n3;
334  n.m_rank += n3 ? 1 : 0;
335  m_notes.push_back(n);
336 }
337 
338 //
339 void btSoftBody::appendNote(const char* text,
340  const btVector3& o,
341  Node* feature)
342 {
343  appendNote(text, o, btVector4(1, 0, 0, 0), feature);
344 }
345 
346 //
347 void btSoftBody::appendNote(const char* text,
348  const btVector3& o,
349  Link* feature)
350 {
351  static const btScalar w = 1 / (btScalar)2;
352  appendNote(text, o, btVector4(w, w, 0, 0), feature->m_n[0],
353  feature->m_n[1]);
354 }
355 
356 //
357 void btSoftBody::appendNote(const char* text,
358  const btVector3& o,
359  Face* feature)
360 {
361  static const btScalar w = 1 / (btScalar)3;
362  appendNote(text, o, btVector4(w, w, w, 0), feature->m_n[0],
363  feature->m_n[1],
364  feature->m_n[2]);
365 }
366 
367 //
369 {
370  if (m_nodes.capacity() == m_nodes.size())
371  {
373  m_nodes.reserve(m_nodes.size() * 2 + 1);
375  }
376  const btScalar margin = getCollisionShape()->getMargin();
378  Node& n = m_nodes[m_nodes.size() - 1];
379  ZeroInitialize(n);
380  n.m_x = x;
381  n.m_q = n.m_x;
382  n.m_im = m > 0 ? 1 / m : 0;
383  n.m_material = m_materials[0];
384  n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
385 }
386 
387 //
388 void btSoftBody::appendLink(int model, Material* mat)
389 {
390  Link l;
391  if (model >= 0)
392  l = m_links[model];
393  else
394  {
395  ZeroInitialize(l);
396  l.m_material = mat ? mat : m_materials[0];
397  }
399 }
400 
401 //
402 void btSoftBody::appendLink(int node0,
403  int node1,
404  Material* mat,
405  bool bcheckexist)
406 {
407  appendLink(&m_nodes[node0], &m_nodes[node1], mat, bcheckexist);
408 }
409 
410 //
412  Node* node1,
413  Material* mat,
414  bool bcheckexist)
415 {
416  if ((!bcheckexist) || (!checkLink(node0, node1)))
417  {
418  appendLink(-1, mat);
419  Link& l = m_links[m_links.size() - 1];
420  l.m_n[0] = node0;
421  l.m_n[1] = node1;
422  l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
423  m_bUpdateRtCst = true;
424  }
425 }
426 
427 //
428 void btSoftBody::appendFace(int model, Material* mat)
429 {
430  Face f;
431  if (model >= 0)
432  {
433  f = m_faces[model];
434  }
435  else
436  {
437  ZeroInitialize(f);
438  f.m_material = mat ? mat : m_materials[0];
439  }
440  m_faces.push_back(f);
441 }
442 
443 //
444 void btSoftBody::appendFace(int node0, int node1, int node2, Material* mat)
445 {
446  if (node0 == node1)
447  return;
448  if (node1 == node2)
449  return;
450  if (node2 == node0)
451  return;
452 
453  appendFace(-1, mat);
454  Face& f = m_faces[m_faces.size() - 1];
455  btAssert(node0 != node1);
456  btAssert(node1 != node2);
457  btAssert(node2 != node0);
458  f.m_n[0] = &m_nodes[node0];
459  f.m_n[1] = &m_nodes[node1];
460  f.m_n[2] = &m_nodes[node2];
461  f.m_ra = AreaOf(f.m_n[0]->m_x,
462  f.m_n[1]->m_x,
463  f.m_n[2]->m_x);
464  m_bUpdateRtCst = true;
465 }
466 
467 //
468 void btSoftBody::appendTetra(int model, Material* mat)
469 {
470  Tetra t;
471  if (model >= 0)
472  t = m_tetras[model];
473  else
474  {
475  ZeroInitialize(t);
476  t.m_material = mat ? mat : m_materials[0];
477  }
479 }
480 
481 //
482 void btSoftBody::appendTetra(int node0,
483  int node1,
484  int node2,
485  int node3,
486  Material* mat)
487 {
488  appendTetra(-1, mat);
489  Tetra& t = m_tetras[m_tetras.size() - 1];
490  t.m_n[0] = &m_nodes[node0];
491  t.m_n[1] = &m_nodes[node1];
492  t.m_n[2] = &m_nodes[node2];
493  t.m_n[3] = &m_nodes[node3];
494  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);
495  m_bUpdateRtCst = true;
496 }
497 
498 //
499 
500 void btSoftBody::appendAnchor(int node, btRigidBody* body, bool disableCollisionBetweenLinkedBodies, btScalar influence)
501 {
502  btVector3 local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
503  appendAnchor(node, body, local, disableCollisionBetweenLinkedBodies, influence);
504 }
505 
506 //
507 void btSoftBody::appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies, btScalar influence)
508 {
509  if (disableCollisionBetweenLinkedBodies)
510  {
512  {
514  }
515  }
516 
517  Anchor a;
518  a.m_node = &m_nodes[node];
519  a.m_body = body;
520  a.m_local = localPivot;
521  a.m_node->m_battach = 1;
522  a.m_influence = influence;
524 }
525 
526 //
528 {
531  const btScalar ima = n.m_im;
532  const btScalar imb = body->getInvMass();
533  btVector3 nrm;
534  const btCollisionShape* shp = body->getCollisionShape();
535  const btTransform& wtr = body->getWorldTransform();
536  btScalar dst =
538  wtr.invXform(m_nodes[node].m_x),
539  shp,
540  nrm,
541  0);
542 
543  c.m_cti.m_colObj = body;
544  c.m_cti.m_normal = wtr.getBasis() * nrm;
545  c.m_cti.m_offset = dst;
546  c.m_node = &m_nodes[node];
547  const btScalar fc = m_cfg.kDF * body->getFriction();
548  c.m_c2 = ima;
549  c.m_c3 = fc;
550  c.m_c4 = body->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
551  static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
552  const btMatrix3x3& iwi = body->getInvInertiaTensorWorld();
553  const btVector3 ra = n.m_x - wtr.getOrigin();
554 
555  c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
556  c.m_c1 = ra;
557  c.m_local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
558  c.m_node->m_battach = 1;
559  m_deformableAnchors.push_back(c);
560 }
561 
563 {
564  const btSoftBody::Node& n = m_nodes[node];
565  for (int i = 0; i < m_deformableAnchors.size();)
566  {
568  if (c.m_node == &n)
569  {
570  m_deformableAnchors.removeAtIndex(i);
571  }
572  else
573  {
574  i++;
575  }
576  }
577 }
578 
579 //
581 {
584  const btScalar ima = n.m_im;
585  btVector3 nrm;
586  const btCollisionShape* shp = link->getCollisionShape();
587  const btTransform& wtr = link->getWorldTransform();
588  btScalar dst =
590  wtr.invXform(m_nodes[node].m_x),
591  shp,
592  nrm,
593  0);
594  c.m_cti.m_colObj = link;
595  c.m_cti.m_normal = wtr.getBasis() * nrm;
596  c.m_cti.m_offset = dst;
597  c.m_node = &m_nodes[node];
598  const btScalar fc = m_cfg.kDF * link->getFriction();
599  c.m_c2 = ima;
600  c.m_c3 = fc;
601  c.m_c4 = link->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
602  btVector3 normal = c.m_cti.m_normal;
604  btVector3 t2 = btCross(normal, t1);
605  btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
606  findJacobian(link, jacobianData_normal, c.m_node->m_x, normal);
607  findJacobian(link, jacobianData_t1, c.m_node->m_x, t1);
608  findJacobian(link, jacobianData_t2, c.m_node->m_x, t2);
609 
610  btScalar* J_n = &jacobianData_normal.m_jacobians[0];
611  btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
612  btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
613 
614  btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
615  btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
616  btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
617 
618  btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
619  t1.getX(), t1.getY(), t1.getZ(),
620  t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
621  const int ndof = link->m_multiBody->getNumDofs() + 6;
622  btMatrix3x3 local_impulse_matrix = (Diagonal(n.m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
623  c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
624  c.jacobianData_normal = jacobianData_normal;
625  c.jacobianData_t1 = jacobianData_t1;
626  c.jacobianData_t2 = jacobianData_t2;
627  c.t1 = t1;
628  c.t2 = t2;
629  const btVector3 ra = n.m_x - wtr.getOrigin();
630  c.m_c1 = ra;
631  c.m_local = link->getWorldTransform().inverse() * m_nodes[node].m_x;
632  c.m_node->m_battach = 1;
633  m_deformableAnchors.push_back(c);
634 }
635 //
636 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Cluster* body0, Body body1)
637 {
638  LJoint* pj = new (btAlignedAlloc(sizeof(LJoint), 16)) LJoint();
639  pj->m_bodies[0] = body0;
640  pj->m_bodies[1] = body1;
641  pj->m_refs[0] = pj->m_bodies[0].xform().inverse() * specs.position;
642  pj->m_refs[1] = pj->m_bodies[1].xform().inverse() * specs.position;
643  pj->m_cfm = specs.cfm;
644  pj->m_erp = specs.erp;
645  pj->m_split = specs.split;
646  m_joints.push_back(pj);
647 }
648 
649 //
651 {
652  appendLinearJoint(specs, m_clusters[0], body);
653 }
654 
655 //
657 {
658  appendLinearJoint(specs, m_clusters[0], body->m_clusters[0]);
659 }
660 
661 //
662 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, Cluster* body0, Body body1)
663 {
664  AJoint* pj = new (btAlignedAlloc(sizeof(AJoint), 16)) AJoint();
665  pj->m_bodies[0] = body0;
666  pj->m_bodies[1] = body1;
667  pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis() * specs.axis;
668  pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis() * specs.axis;
669  pj->m_cfm = specs.cfm;
670  pj->m_erp = specs.erp;
671  pj->m_split = specs.split;
672  pj->m_icontrol = specs.icontrol;
673  m_joints.push_back(pj);
674 }
675 
676 //
678 {
679  appendAngularJoint(specs, m_clusters[0], body);
680 }
681 
682 //
684 {
685  appendAngularJoint(specs, m_clusters[0], body->m_clusters[0]);
686 }
687 
688 //
689 void btSoftBody::addForce(const btVector3& force)
690 {
691  for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addForce(force, i);
692 }
693 
694 //
695 void btSoftBody::addForce(const btVector3& force, int node)
696 {
697  Node& n = m_nodes[node];
698  if (n.m_im > 0)
699  {
700  n.m_f += force;
701  }
702 }
703 
704 void btSoftBody::addAeroForceToNode(const btVector3& windVelocity, int nodeIndex)
705 {
706  btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size());
707 
708  const btScalar dt = m_sst.sdt;
709  const btScalar kLF = m_cfg.kLF;
710  const btScalar kDG = m_cfg.kDG;
711  //const btScalar kPR = m_cfg.kPR;
712  //const btScalar kVC = m_cfg.kVC;
713  const bool as_lift = kLF > 0;
714  const bool as_drag = kDG > 0;
715  const bool as_aero = as_lift || as_drag;
716  const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
717 
718  Node& n = m_nodes[nodeIndex];
719 
720  if (n.m_im > 0)
721  {
722  btSoftBody::sMedium medium;
723 
724  EvaluateMedium(m_worldInfo, n.m_x, medium);
725  medium.m_velocity = windVelocity;
727 
728  /* Aerodynamics */
729  if (as_vaero)
730  {
731  const btVector3 rel_v = n.m_v - medium.m_velocity;
732  const btScalar rel_v_len = rel_v.length();
733  const btScalar rel_v2 = rel_v.length2();
734 
735  if (rel_v2 > SIMD_EPSILON)
736  {
737  const btVector3 rel_v_nrm = rel_v.normalized();
738  btVector3 nrm = n.m_n;
739 
741  {
742  nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
743  btVector3 fDrag(0, 0, 0);
744  btVector3 fLift(0, 0, 0);
745 
746  btScalar n_dot_v = nrm.dot(rel_v_nrm);
747  btScalar tri_area = 0.5f * n.m_area;
748 
749  fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
750 
751  // Check angle of attack
752  // cos(10º) = 0.98480
753  if (0 < n_dot_v && n_dot_v < 0.98480f)
754  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));
755 
756  // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
757  btVector3 del_v_by_fDrag = fDrag * n.m_im * m_sst.sdt;
758  btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
759  btScalar v_len2 = n.m_v.length2();
760 
761  if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
762  {
763  btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
764  btScalar v_len = n.m_v.length();
765  fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
766  }
767 
768  n.m_f += fDrag;
769  n.m_f += fLift;
770  }
772  {
774  nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
775 
776  const btScalar dvn = btDot(rel_v, nrm);
777  /* Compute forces */
778  if (dvn > 0)
779  {
780  btVector3 force(0, 0, 0);
781  const btScalar c0 = n.m_area * dvn * rel_v2 / 2;
782  const btScalar c1 = c0 * medium.m_density;
783  force += nrm * (-c1 * kLF);
784  force += rel_v.normalized() * (-c1 * kDG);
785  ApplyClampedForce(n, force, dt);
786  }
787  }
788  }
789  }
790  }
791 }
792 
793 void btSoftBody::addAeroForceToFace(const btVector3& windVelocity, int faceIndex)
794 {
795  const btScalar dt = m_sst.sdt;
796  const btScalar kLF = m_cfg.kLF;
797  const btScalar kDG = m_cfg.kDG;
798  // const btScalar kPR = m_cfg.kPR;
799  // const btScalar kVC = m_cfg.kVC;
800  const bool as_lift = kLF > 0;
801  const bool as_drag = kDG > 0;
802  const bool as_aero = as_lift || as_drag;
803  const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
804 
805  if (as_faero)
806  {
807  btSoftBody::Face& f = m_faces[faceIndex];
808 
809  btSoftBody::sMedium medium;
810 
811  const btVector3 v = (f.m_n[0]->m_v + f.m_n[1]->m_v + f.m_n[2]->m_v) / 3;
812  const btVector3 x = (f.m_n[0]->m_x + f.m_n[1]->m_x + f.m_n[2]->m_x) / 3;
813  EvaluateMedium(m_worldInfo, x, medium);
814  medium.m_velocity = windVelocity;
816  const btVector3 rel_v = v - medium.m_velocity;
817  const btScalar rel_v_len = rel_v.length();
818  const btScalar rel_v2 = rel_v.length2();
819 
820  if (rel_v2 > SIMD_EPSILON)
821  {
822  const btVector3 rel_v_nrm = rel_v.normalized();
823  btVector3 nrm = f.m_normal;
824 
826  {
827  nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
828 
829  btVector3 fDrag(0, 0, 0);
830  btVector3 fLift(0, 0, 0);
831 
832  btScalar n_dot_v = nrm.dot(rel_v_nrm);
833  btScalar tri_area = 0.5f * f.m_ra;
834 
835  fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
836 
837  // Check angle of attack
838  // cos(10º) = 0.98480
839  if (0 < n_dot_v && n_dot_v < 0.98480f)
840  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));
841 
842  fDrag /= 3;
843  fLift /= 3;
844 
845  for (int j = 0; j < 3; ++j)
846  {
847  if (f.m_n[j]->m_im > 0)
848  {
849  // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
850  btVector3 del_v_by_fDrag = fDrag * f.m_n[j]->m_im * m_sst.sdt;
851  btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
852  btScalar v_len2 = f.m_n[j]->m_v.length2();
853 
854  if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
855  {
856  btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
857  btScalar v_len = f.m_n[j]->m_v.length();
858  fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
859  }
860 
861  f.m_n[j]->m_f += fDrag;
862  f.m_n[j]->m_f += fLift;
863  }
864  }
865  }
867  {
869  nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
870 
871  const btScalar dvn = btDot(rel_v, nrm);
872  /* Compute forces */
873  if (dvn > 0)
874  {
875  btVector3 force(0, 0, 0);
876  const btScalar c0 = f.m_ra * dvn * rel_v2;
877  const btScalar c1 = c0 * medium.m_density;
878  force += nrm * (-c1 * kLF);
879  force += rel_v.normalized() * (-c1 * kDG);
880  force /= 3;
881  for (int j = 0; j < 3; ++j) ApplyClampedForce(*f.m_n[j], force, dt);
882  }
883  }
884  }
885  }
886 }
887 
888 //
889 void btSoftBody::addVelocity(const btVector3& velocity)
890 {
891  for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addVelocity(velocity, i);
892 }
893 
894 /* Set velocity for the entire body */
895 void btSoftBody::setVelocity(const btVector3& velocity)
896 {
897  for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
898  {
899  Node& n = m_nodes[i];
900  if (n.m_im > 0)
901  {
902  n.m_v = velocity;
903  n.m_vn = velocity;
904  }
905  }
906 }
907 
908 //
909 void btSoftBody::addVelocity(const btVector3& velocity, int node)
910 {
911  Node& n = m_nodes[node];
912  if (n.m_im > 0)
913  {
914  n.m_v += velocity;
915  }
916 }
917 
918 //
920 {
921  m_nodes[node].m_im = mass > 0 ? 1 / mass : 0;
922  m_bUpdateRtCst = true;
923 }
924 
925 //
927 {
928  return (m_nodes[node].m_im > 0 ? 1 / m_nodes[node].m_im : 0);
929 }
930 
931 //
933 {
934  btScalar mass = 0;
935  for (int i = 0; i < m_nodes.size(); ++i)
936  {
937  mass += getMass(i);
938  }
939  return (mass);
940 }
941 
942 //
943 void btSoftBody::setTotalMass(btScalar mass, bool fromfaces)
944 {
945  int i;
946 
947  if (fromfaces)
948  {
949  for (i = 0; i < m_nodes.size(); ++i)
950  {
951  m_nodes[i].m_im = 0;
952  }
953  for (i = 0; i < m_faces.size(); ++i)
954  {
955  const Face& f = m_faces[i];
956  const btScalar twicearea = AreaOf(f.m_n[0]->m_x,
957  f.m_n[1]->m_x,
958  f.m_n[2]->m_x);
959  for (int j = 0; j < 3; ++j)
960  {
961  f.m_n[j]->m_im += twicearea;
962  }
963  }
964  for (i = 0; i < m_nodes.size(); ++i)
965  {
966  m_nodes[i].m_im = 1 / m_nodes[i].m_im;
967  }
968  }
969  const btScalar tm = getTotalMass();
970  const btScalar itm = 1 / tm;
971  for (i = 0; i < m_nodes.size(); ++i)
972  {
973  m_nodes[i].m_im /= itm * mass;
974  }
975  m_bUpdateRtCst = true;
976 }
977 
978 //
980 {
981  setTotalMass(getVolume() * density, true);
982 }
983 
984 //
986 {
988  ranks.resize(m_nodes.size(), 0);
989  int i;
990 
991  for (i = 0; i < m_nodes.size(); ++i)
992  {
993  m_nodes[i].m_im = 0;
994  }
995  for (i = 0; i < m_tetras.size(); ++i)
996  {
997  const Tetra& t = m_tetras[i];
998  for (int j = 0; j < 4; ++j)
999  {
1000  t.m_n[j]->m_im += btFabs(t.m_rv);
1001  ranks[int(t.m_n[j] - &m_nodes[0])] += 1;
1002  }
1003  }
1004  for (i = 0; i < m_nodes.size(); ++i)
1005  {
1006  if (m_nodes[i].m_im > 0)
1007  {
1008  m_nodes[i].m_im = ranks[i] / m_nodes[i].m_im;
1009  }
1010  }
1011  setTotalMass(mass, false);
1012 }
1013 
1014 //
1016 {
1017  btScalar volume = 0;
1018  for (int i = 0; i < m_tetras.size(); ++i)
1019  {
1020  const Tetra& t = m_tetras[i];
1021  for (int j = 0; j < 4; ++j)
1022  {
1023  volume += btFabs(t.m_rv);
1024  }
1025  }
1026  setVolumeMass(volume * density / 6);
1027 }
1028 
1029 //
1031 {
1032  btVector3 total_momentum = btVector3(0, 0, 0);
1033  for (int i = 0; i < m_nodes.size(); ++i)
1034  {
1035  btScalar mass = m_nodes[i].m_im == 0 ? 0 : 1.0 / m_nodes[i].m_im;
1036  total_momentum += mass * m_nodes[i].m_v;
1037  }
1038  btScalar total_mass = getTotalMass();
1039  return total_mass == 0 ? total_momentum : total_momentum / total_mass;
1040 }
1041 
1042 //
1044 {
1045  btVector3 old_vel = getLinearVelocity();
1046  btVector3 diff = linVel - old_vel;
1047  for (int i = 0; i < m_nodes.size(); ++i)
1048  m_nodes[i].m_v += diff;
1049 }
1050 
1051 //
1053 {
1054  btVector3 old_vel = getLinearVelocity();
1055  btVector3 com = getCenterOfMass();
1056  for (int i = 0; i < m_nodes.size(); ++i)
1057  {
1058  m_nodes[i].m_v = angVel.cross(m_nodes[i].m_x - com) + old_vel;
1059  }
1060 }
1061 
1062 //
1064 {
1066  btMatrix3x3 S;
1067  S.setZero();
1068  // Get rotation that minimizes L2 difference: \sum_i || RX_i + t - x_i ||
1069  // It's important to make sure that S has the correct signs.
1070  // SVD is only unique up to the ordering of singular values.
1071  // SVD will manipulate U and V to ensure the ordering of singular values. If all three singular
1072  // vaues are negative, SVD will permute colums of U to make two of them positive.
1073  for (int i = 0; i < m_nodes.size(); ++i)
1074  {
1075  S -= OuterProduct(m_X[i], t - m_nodes[i].m_x);
1076  }
1077  btVector3 sigma;
1078  btMatrix3x3 U, V;
1079  singularValueDecomposition(S, U, sigma, V);
1080  btMatrix3x3 R = V * U.transpose();
1081  btTransform trs;
1082  trs.setIdentity();
1083  trs.setOrigin(t);
1084  trs.setBasis(R);
1085  return trs;
1086 }
1087 
1088 //
1090 {
1091  // get the current best rigid fit
1092  btTransform current_transform = getRigidTransform();
1093  // apply transform in material space
1094  btTransform new_transform = trs * current_transform.inverse();
1095  transform(new_transform);
1096 }
1097 
1098 //
1100 {
1101  const btScalar margin = getCollisionShape()->getMargin();
1103  vol;
1104 
1105  for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
1106  {
1107  Node& n = m_nodes[i];
1108  n.m_x = trs * n.m_x;
1109  n.m_q = trs * n.m_q;
1110  n.m_n = trs.getBasis() * n.m_n;
1111  vol = btDbvtVolume::FromCR(n.m_x, margin);
1112 
1113  m_ndbvt.update(n.m_leaf, vol);
1114  }
1115  updateNormals();
1116  updateBounds();
1117  updateConstants();
1118 }
1119 
1120 //
1122 {
1123  btTransform t;
1124  t.setIdentity();
1125  t.setOrigin(trs);
1126  transform(t);
1127 }
1128 
1129 //
1131 {
1132  btTransform t;
1133  t.setIdentity();
1134  t.setRotation(rot);
1135  transform(t);
1136 }
1137 
1138 //
1140 {
1141  const btScalar margin = getCollisionShape()->getMargin();
1143  vol;
1144 
1145  for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
1146  {
1147  Node& n = m_nodes[i];
1148  n.m_x *= scl;
1149  n.m_q *= scl;
1150  vol = btDbvtVolume::FromCR(n.m_x, margin);
1151  m_ndbvt.update(n.m_leaf, vol);
1152  }
1153  updateNormals();
1154  updateBounds();
1155  updateConstants();
1157 }
1158 
1159 //
1161 {
1162  return m_restLengthScale;
1163 }
1164 
1165 //
1167 {
1168  for (int i = 0, ni = m_links.size(); i < ni; ++i)
1169  {
1170  Link& l = m_links[i];
1171  l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
1172  l.m_c1 = l.m_rl * l.m_rl;
1173  }
1174  m_restLengthScale = restLengthScale;
1175 
1177  activate();
1178 }
1179 
1180 //
1181 void btSoftBody::setPose(bool bvolume, bool bframe)
1182 {
1183  m_pose.m_bvolume = bvolume;
1184  m_pose.m_bframe = bframe;
1185  int i, ni;
1186 
1187  /* Weights */
1188  const btScalar omass = getTotalMass();
1189  const btScalar kmass = omass * m_nodes.size() * 1000;
1190  btScalar tmass = omass;
1192  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
1193  {
1194  if (m_nodes[i].m_im <= 0) tmass += kmass;
1195  }
1196  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
1197  {
1198  Node& n = m_nodes[i];
1199  m_pose.m_wgh[i] = n.m_im > 0 ? 1 / (m_nodes[i].m_im * tmass) : kmass / tmass;
1200  }
1201  /* Pos */
1202  const btVector3 com = evaluateCom();
1204  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
1205  {
1206  m_pose.m_pos[i] = m_nodes[i].m_x - com;
1207  }
1208  m_pose.m_volume = bvolume ? getVolume() : 0;
1209  m_pose.m_com = com;
1210  m_pose.m_rot.setIdentity();
1211  m_pose.m_scl.setIdentity();
1212  /* Aqq */
1213  m_pose.m_aqq[0] =
1214  m_pose.m_aqq[1] =
1215  m_pose.m_aqq[2] = btVector3(0, 0, 0);
1216  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
1217  {
1218  const btVector3& q = m_pose.m_pos[i];
1219  const btVector3 mq = m_pose.m_wgh[i] * q;
1220  m_pose.m_aqq[0] += mq.x() * q;
1221  m_pose.m_aqq[1] += mq.y() * q;
1222  m_pose.m_aqq[2] += mq.z() * q;
1223  }
1224  m_pose.m_aqq = m_pose.m_aqq.inverse();
1225 
1226  updateConstants();
1227 }
1228 
1230 {
1231  for (int i = 0, ni = m_links.size(); i < ni; ++i)
1232  {
1233  Link& l = m_links[i];
1234  l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
1235  l.m_c1 = l.m_rl * l.m_rl;
1236  }
1237 }
1238 
1239 //
1241 {
1242  btScalar vol = 0;
1243  if (m_nodes.size() > 0)
1244  {
1245  int i, ni;
1246 
1247  const btVector3 org = m_nodes[0].m_x;
1248  for (i = 0, ni = m_faces.size(); i < ni; ++i)
1249  {
1250  const Face& f = m_faces[i];
1251  vol += btDot(f.m_n[0]->m_x - org, btCross(f.m_n[1]->m_x - org, f.m_n[2]->m_x - org));
1252  }
1253  vol /= (btScalar)6;
1254  }
1255  return (vol);
1256 }
1257 
1258 //
1260 {
1261  return (m_clusters.size());
1262 }
1263 
1264 //
1266 {
1267  btVector3 com(0, 0, 0);
1268  for (int i = 0, ni = cluster->m_nodes.size(); i < ni; ++i)
1269  {
1270  com += cluster->m_nodes[i]->m_x * cluster->m_masses[i];
1271  }
1272  return (com * cluster->m_imass);
1273 }
1274 
1275 //
1277 {
1278  return (clusterCom(m_clusters[cluster]));
1279 }
1280 
1281 //
1283 {
1284  return (cluster->m_lv + btCross(cluster->m_av, rpos));
1285 }
1286 
1287 //
1288 void btSoftBody::clusterVImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse)
1289 {
1290  const btVector3 li = cluster->m_imass * impulse;
1291  const btVector3 ai = cluster->m_invwi * btCross(rpos, impulse);
1292  cluster->m_vimpulses[0] += li;
1293  cluster->m_lv += li;
1294  cluster->m_vimpulses[1] += ai;
1295  cluster->m_av += ai;
1296  cluster->m_nvimpulses++;
1297 }
1298 
1299 //
1300 void btSoftBody::clusterDImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse)
1301 {
1302  const btVector3 li = cluster->m_imass * impulse;
1303  const btVector3 ai = cluster->m_invwi * btCross(rpos, impulse);
1304  cluster->m_dimpulses[0] += li;
1305  cluster->m_dimpulses[1] += ai;
1306  cluster->m_ndimpulses++;
1307 }
1308 
1309 //
1310 void btSoftBody::clusterImpulse(Cluster* cluster, const btVector3& rpos, const Impulse& impulse)
1311 {
1312  if (impulse.m_asVelocity) clusterVImpulse(cluster, rpos, impulse.m_velocity);
1313  if (impulse.m_asDrift) clusterDImpulse(cluster, rpos, impulse.m_drift);
1314 }
1315 
1316 //
1317 void btSoftBody::clusterVAImpulse(Cluster* cluster, const btVector3& impulse)
1318 {
1319  const btVector3 ai = cluster->m_invwi * impulse;
1320  cluster->m_vimpulses[1] += ai;
1321  cluster->m_av += ai;
1322  cluster->m_nvimpulses++;
1323 }
1324 
1325 //
1326 void btSoftBody::clusterDAImpulse(Cluster* cluster, const btVector3& impulse)
1327 {
1328  const btVector3 ai = cluster->m_invwi * impulse;
1329  cluster->m_dimpulses[1] += ai;
1330  cluster->m_ndimpulses++;
1331 }
1332 
1333 //
1334 void btSoftBody::clusterAImpulse(Cluster* cluster, const Impulse& impulse)
1335 {
1336  if (impulse.m_asVelocity) clusterVAImpulse(cluster, impulse.m_velocity);
1337  if (impulse.m_asDrift) clusterDAImpulse(cluster, impulse.m_drift);
1338 }
1339 
1340 //
1341 void btSoftBody::clusterDCImpulse(Cluster* cluster, const btVector3& impulse)
1342 {
1343  cluster->m_dimpulses[0] += impulse * cluster->m_imass;
1344  cluster->m_ndimpulses++;
1345 }
1346 
1348 {
1350 };
1351 
1352 //
1354 {
1355  int i, j;
1356 
1357  if (distance > 1)
1358  {
1359  /* Build graph */
1360  const int n = m_nodes.size();
1361  const unsigned inf = (~(unsigned)0) >> 1;
1362  unsigned* adj = new unsigned[n * n];
1363 
1364 #define IDX(_x_, _y_) ((_y_)*n + (_x_))
1365  for (j = 0; j < n; ++j)
1366  {
1367  for (i = 0; i < n; ++i)
1368  {
1369  if (i != j)
1370  {
1371  adj[IDX(i, j)] = adj[IDX(j, i)] = inf;
1372  }
1373  else
1374  {
1375  adj[IDX(i, j)] = adj[IDX(j, i)] = 0;
1376  }
1377  }
1378  }
1379  for (i = 0; i < m_links.size(); ++i)
1380  {
1381  const int ia = (int)(m_links[i].m_n[0] - &m_nodes[0]);
1382  const int ib = (int)(m_links[i].m_n[1] - &m_nodes[0]);
1383  adj[IDX(ia, ib)] = 1;
1384  adj[IDX(ib, ia)] = 1;
1385  }
1386 
1387  //special optimized case for distance == 2
1388  if (distance == 2)
1389  {
1391 
1392  /* Build node links */
1393  nodeLinks.resize(m_nodes.size());
1394 
1395  for (i = 0; i < m_links.size(); ++i)
1396  {
1397  const int ia = (int)(m_links[i].m_n[0] - &m_nodes[0]);
1398  const int ib = (int)(m_links[i].m_n[1] - &m_nodes[0]);
1399  if (nodeLinks[ia].m_links.findLinearSearch(ib) == nodeLinks[ia].m_links.size())
1400  nodeLinks[ia].m_links.push_back(ib);
1401 
1402  if (nodeLinks[ib].m_links.findLinearSearch(ia) == nodeLinks[ib].m_links.size())
1403  nodeLinks[ib].m_links.push_back(ia);
1404  }
1405  for (int ii = 0; ii < nodeLinks.size(); ii++)
1406  {
1407  int i = ii;
1408 
1409  for (int jj = 0; jj < nodeLinks[ii].m_links.size(); jj++)
1410  {
1411  int k = nodeLinks[ii].m_links[jj];
1412  for (int kk = 0; kk < nodeLinks[k].m_links.size(); kk++)
1413  {
1414  int j = nodeLinks[k].m_links[kk];
1415  if (i != j)
1416  {
1417  const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
1418  btAssert(sum == 2);
1419  if (adj[IDX(i, j)] > sum)
1420  {
1421  adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
1422  }
1423  }
1424  }
1425  }
1426  }
1427  }
1428  else
1429  {
1431  for (int k = 0; k < n; ++k)
1432  {
1433  for (j = 0; j < n; ++j)
1434  {
1435  for (i = j + 1; i < n; ++i)
1436  {
1437  const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
1438  if (adj[IDX(i, j)] > sum)
1439  {
1440  adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
1441  }
1442  }
1443  }
1444  }
1445  }
1446 
1447  /* Build links */
1448  int nlinks = 0;
1449  for (j = 0; j < n; ++j)
1450  {
1451  for (i = j + 1; i < n; ++i)
1452  {
1453  if (adj[IDX(i, j)] == (unsigned)distance)
1454  {
1455  appendLink(i, j, mat);
1456  m_links[m_links.size() - 1].m_bbending = 1;
1457  ++nlinks;
1458  }
1459  }
1460  }
1461  delete[] adj;
1462  return (nlinks);
1463  }
1464  return (0);
1465 }
1466 
1467 //
1469 {
1470  unsigned long seed = 243703;
1471 #define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
1472  int i, ni;
1473 
1474  for (i = 0, ni = m_links.size(); i < ni; ++i)
1475  {
1476  btSwap(m_links[i], m_links[NEXTRAND % ni]);
1477  }
1478  for (i = 0, ni = m_faces.size(); i < ni; ++i)
1479  {
1480  btSwap(m_faces[i], m_faces[NEXTRAND % ni]);
1481  }
1482 #undef NEXTRAND
1483 }
1484 
1485 //
1487 {
1488  Cluster* c = m_clusters[index];
1489  if (c->m_leaf) m_cdbvt.remove(c->m_leaf);
1490  c->~Cluster();
1491  btAlignedFree(c);
1492  m_clusters.remove(c);
1493 }
1494 
1495 //
1497 {
1498  while (m_clusters.size() > 0) releaseCluster(0);
1499 }
1500 
1501 //
1502 int btSoftBody::generateClusters(int k, int maxiterations)
1503 {
1504  int i;
1505  releaseClusters();
1507  for (i = 0; i < m_clusters.size(); ++i)
1508  {
1509  m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
1510  m_clusters[i]->m_collide = true;
1511  }
1512  k = m_clusters.size();
1513  if (k > 0)
1514  {
1515  /* Initialize */
1517  btVector3 cog(0, 0, 0);
1518  int i;
1519  for (i = 0; i < m_nodes.size(); ++i)
1520  {
1521  cog += m_nodes[i].m_x;
1522  m_clusters[(i * 29873) % m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
1523  }
1524  cog /= (btScalar)m_nodes.size();
1525  centers.resize(k, cog);
1526  /* Iterate */
1527  const btScalar slope = 16;
1528  bool changed;
1529  int iterations = 0;
1530  do
1531  {
1532  const btScalar w = 2 - btMin<btScalar>(1, iterations / slope);
1533  changed = false;
1534  iterations++;
1535  int i;
1536 
1537  for (i = 0; i < k; ++i)
1538  {
1539  btVector3 c(0, 0, 0);
1540  for (int j = 0; j < m_clusters[i]->m_nodes.size(); ++j)
1541  {
1542  c += m_clusters[i]->m_nodes[j]->m_x;
1543  }
1544  if (m_clusters[i]->m_nodes.size())
1545  {
1546  c /= (btScalar)m_clusters[i]->m_nodes.size();
1547  c = centers[i] + (c - centers[i]) * w;
1548  changed |= ((c - centers[i]).length2() > SIMD_EPSILON);
1549  centers[i] = c;
1550  m_clusters[i]->m_nodes.resize(0);
1551  }
1552  }
1553  for (i = 0; i < m_nodes.size(); ++i)
1554  {
1555  const btVector3 nx = m_nodes[i].m_x;
1556  int kbest = 0;
1557  btScalar kdist = ClusterMetric(centers[0], nx);
1558  for (int j = 1; j < k; ++j)
1559  {
1560  const btScalar d = ClusterMetric(centers[j], nx);
1561  if (d < kdist)
1562  {
1563  kbest = j;
1564  kdist = d;
1565  }
1566  }
1567  m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
1568  }
1569  } while (changed && (iterations < maxiterations));
1570  /* Merge */
1572  cids.resize(m_nodes.size(), -1);
1573  for (i = 0; i < m_clusters.size(); ++i)
1574  {
1575  for (int j = 0; j < m_clusters[i]->m_nodes.size(); ++j)
1576  {
1577  cids[int(m_clusters[i]->m_nodes[j] - &m_nodes[0])] = i;
1578  }
1579  }
1580  for (i = 0; i < m_faces.size(); ++i)
1581  {
1582  const int idx[] = {int(m_faces[i].m_n[0] - &m_nodes[0]),
1583  int(m_faces[i].m_n[1] - &m_nodes[0]),
1584  int(m_faces[i].m_n[2] - &m_nodes[0])};
1585  for (int j = 0; j < 3; ++j)
1586  {
1587  const int cid = cids[idx[j]];
1588  for (int q = 1; q < 3; ++q)
1589  {
1590  const int kid = idx[(j + q) % 3];
1591  if (cids[kid] != cid)
1592  {
1593  if (m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid]) == m_clusters[cid]->m_nodes.size())
1594  {
1595  m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
1596  }
1597  }
1598  }
1599  }
1600  }
1601  /* Master */
1602  if (m_clusters.size() > 1)
1603  {
1604  Cluster* pmaster = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
1605  pmaster->m_collide = false;
1606  pmaster->m_nodes.reserve(m_nodes.size());
1607  for (int i = 0; i < m_nodes.size(); ++i) pmaster->m_nodes.push_back(&m_nodes[i]);
1608  m_clusters.push_back(pmaster);
1610  }
1611  /* Terminate */
1612  for (i = 0; i < m_clusters.size(); ++i)
1613  {
1614  if (m_clusters[i]->m_nodes.size() == 0)
1615  {
1616  releaseCluster(i--);
1617  }
1618  }
1619  }
1620  else
1621  {
1622  //create a cluster for each tetrahedron (if tetrahedra exist) or each face
1623  if (m_tetras.size())
1624  {
1626  for (i = 0; i < m_clusters.size(); ++i)
1627  {
1628  m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
1629  m_clusters[i]->m_collide = true;
1630  }
1631  for (i = 0; i < m_tetras.size(); i++)
1632  {
1633  for (int j = 0; j < 4; j++)
1634  {
1635  m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
1636  }
1637  }
1638  }
1639  else
1640  {
1642  for (i = 0; i < m_clusters.size(); ++i)
1643  {
1644  m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
1645  m_clusters[i]->m_collide = true;
1646  }
1647 
1648  for (i = 0; i < m_faces.size(); ++i)
1649  {
1650  for (int j = 0; j < 3; ++j)
1651  {
1652  m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
1653  }
1654  }
1655  }
1656  }
1657 
1658  if (m_clusters.size())
1659  {
1661  updateClusters();
1662 
1663  //for self-collision
1665  {
1666  for (int c0 = 0; c0 < m_clusters.size(); c0++)
1667  {
1668  m_clusters[c0]->m_clusterIndex = c0;
1669  for (int c1 = 0; c1 < m_clusters.size(); c1++)
1670  {
1671  bool connected = false;
1672  Cluster* cla = m_clusters[c0];
1673  Cluster* clb = m_clusters[c1];
1674  for (int i = 0; !connected && i < cla->m_nodes.size(); i++)
1675  {
1676  for (int j = 0; j < clb->m_nodes.size(); j++)
1677  {
1678  if (cla->m_nodes[i] == clb->m_nodes[j])
1679  {
1680  connected = true;
1681  break;
1682  }
1683  }
1684  }
1685  m_clusterConnectivity[c0 + c1 * m_clusters.size()] = connected;
1686  }
1687  }
1688  }
1689  }
1690 
1691  return (m_clusters.size());
1692 }
1693 
1694 //
1695 void btSoftBody::refine(ImplicitFn* ifn, btScalar accurary, bool cut)
1696 {
1697  const Node* nbase = &m_nodes[0];
1698  int ncount = m_nodes.size();
1699  btSymMatrix<int> edges(ncount, -2);
1700  int newnodes = 0;
1701  int i, j, k, ni;
1702 
1703  /* Filter out */
1704  for (i = 0; i < m_links.size(); ++i)
1705  {
1706  Link& l = m_links[i];
1707  if (l.m_bbending)
1708  {
1709  if (!SameSign(ifn->Eval(l.m_n[0]->m_x), ifn->Eval(l.m_n[1]->m_x)))
1710  {
1711  btSwap(m_links[i], m_links[m_links.size() - 1]);
1712  m_links.pop_back();
1713  --i;
1714  }
1715  }
1716  }
1717  /* Fill edges */
1718  for (i = 0; i < m_links.size(); ++i)
1719  {
1720  Link& l = m_links[i];
1721  edges(int(l.m_n[0] - nbase), int(l.m_n[1] - nbase)) = -1;
1722  }
1723  for (i = 0; i < m_faces.size(); ++i)
1724  {
1725  Face& f = m_faces[i];
1726  edges(int(f.m_n[0] - nbase), int(f.m_n[1] - nbase)) = -1;
1727  edges(int(f.m_n[1] - nbase), int(f.m_n[2] - nbase)) = -1;
1728  edges(int(f.m_n[2] - nbase), int(f.m_n[0] - nbase)) = -1;
1729  }
1730  /* Intersect */
1731  for (i = 0; i < ncount; ++i)
1732  {
1733  for (j = i + 1; j < ncount; ++j)
1734  {
1735  if (edges(i, j) == -1)
1736  {
1737  Node& a = m_nodes[i];
1738  Node& b = m_nodes[j];
1739  const btScalar t = ImplicitSolve(ifn, a.m_x, b.m_x, accurary);
1740  if (t > 0)
1741  {
1742  const btVector3 x = Lerp(a.m_x, b.m_x, t);
1743  const btVector3 v = Lerp(a.m_v, b.m_v, t);
1744  btScalar m = 0;
1745  if (a.m_im > 0)
1746  {
1747  if (b.m_im > 0)
1748  {
1749  const btScalar ma = 1 / a.m_im;
1750  const btScalar mb = 1 / b.m_im;
1751  const btScalar mc = Lerp(ma, mb, t);
1752  const btScalar f = (ma + mb) / (ma + mb + mc);
1753  a.m_im = 1 / (ma * f);
1754  b.m_im = 1 / (mb * f);
1755  m = mc * f;
1756  }
1757  else
1758  {
1759  a.m_im /= 0.5f;
1760  m = 1 / a.m_im;
1761  }
1762  }
1763  else
1764  {
1765  if (b.m_im > 0)
1766  {
1767  b.m_im /= 0.5f;
1768  m = 1 / b.m_im;
1769  }
1770  else
1771  m = 0;
1772  }
1773  appendNode(x, m);
1774  edges(i, j) = m_nodes.size() - 1;
1775  m_nodes[edges(i, j)].m_v = v;
1776  ++newnodes;
1777  }
1778  }
1779  }
1780  }
1781  nbase = &m_nodes[0];
1782  /* Refine links */
1783  for (i = 0, ni = m_links.size(); i < ni; ++i)
1784  {
1785  Link& feat = m_links[i];
1786  const int idx[] = {int(feat.m_n[0] - nbase),
1787  int(feat.m_n[1] - nbase)};
1788  if ((idx[0] < ncount) && (idx[1] < ncount))
1789  {
1790  const int ni = edges(idx[0], idx[1]);
1791  if (ni > 0)
1792  {
1793  appendLink(i);
1794  Link* pft[] = {&m_links[i],
1795  &m_links[m_links.size() - 1]};
1796  pft[0]->m_n[0] = &m_nodes[idx[0]];
1797  pft[0]->m_n[1] = &m_nodes[ni];
1798  pft[1]->m_n[0] = &m_nodes[ni];
1799  pft[1]->m_n[1] = &m_nodes[idx[1]];
1800  }
1801  }
1802  }
1803  /* Refine faces */
1804  for (i = 0; i < m_faces.size(); ++i)
1805  {
1806  const Face& feat = m_faces[i];
1807  const int idx[] = {int(feat.m_n[0] - nbase),
1808  int(feat.m_n[1] - nbase),
1809  int(feat.m_n[2] - nbase)};
1810  for (j = 2, k = 0; k < 3; j = k++)
1811  {
1812  if ((idx[j] < ncount) && (idx[k] < ncount))
1813  {
1814  const int ni = edges(idx[j], idx[k]);
1815  if (ni > 0)
1816  {
1817  appendFace(i);
1818  const int l = (k + 1) % 3;
1819  Face* pft[] = {&m_faces[i],
1820  &m_faces[m_faces.size() - 1]};
1821  pft[0]->m_n[0] = &m_nodes[idx[l]];
1822  pft[0]->m_n[1] = &m_nodes[idx[j]];
1823  pft[0]->m_n[2] = &m_nodes[ni];
1824  pft[1]->m_n[0] = &m_nodes[ni];
1825  pft[1]->m_n[1] = &m_nodes[idx[k]];
1826  pft[1]->m_n[2] = &m_nodes[idx[l]];
1827  appendLink(ni, idx[l], pft[0]->m_material);
1828  --i;
1829  break;
1830  }
1831  }
1832  }
1833  }
1834  /* Cut */
1835  if (cut)
1836  {
1838  const int pcount = ncount;
1839  int i;
1840  ncount = m_nodes.size();
1841  cnodes.resize(ncount, 0);
1842  /* Nodes */
1843  for (i = 0; i < ncount; ++i)
1844  {
1845  const btVector3 x = m_nodes[i].m_x;
1846  if ((i >= pcount) || (btFabs(ifn->Eval(x)) < accurary))
1847  {
1848  const btVector3 v = m_nodes[i].m_v;
1849  btScalar m = getMass(i);
1850  if (m > 0)
1851  {
1852  m *= 0.5f;
1853  m_nodes[i].m_im /= 0.5f;
1854  }
1855  appendNode(x, m);
1856  cnodes[i] = m_nodes.size() - 1;
1857  m_nodes[cnodes[i]].m_v = v;
1858  }
1859  }
1860  nbase = &m_nodes[0];
1861  /* Links */
1862  for (i = 0, ni = m_links.size(); i < ni; ++i)
1863  {
1864  const int id[] = {int(m_links[i].m_n[0] - nbase),
1865  int(m_links[i].m_n[1] - nbase)};
1866  int todetach = 0;
1867  if (cnodes[id[0]] && cnodes[id[1]])
1868  {
1869  appendLink(i);
1870  todetach = m_links.size() - 1;
1871  }
1872  else
1873  {
1874  if (((ifn->Eval(m_nodes[id[0]].m_x) < accurary) &&
1875  (ifn->Eval(m_nodes[id[1]].m_x) < accurary)))
1876  todetach = i;
1877  }
1878  if (todetach)
1879  {
1880  Link& l = m_links[todetach];
1881  for (int j = 0; j < 2; ++j)
1882  {
1883  int cn = cnodes[int(l.m_n[j] - nbase)];
1884  if (cn) l.m_n[j] = &m_nodes[cn];
1885  }
1886  }
1887  }
1888  /* Faces */
1889  for (i = 0, ni = m_faces.size(); i < ni; ++i)
1890  {
1891  Node** n = m_faces[i].m_n;
1892  if ((ifn->Eval(n[0]->m_x) < accurary) &&
1893  (ifn->Eval(n[1]->m_x) < accurary) &&
1894  (ifn->Eval(n[2]->m_x) < accurary))
1895  {
1896  for (int j = 0; j < 3; ++j)
1897  {
1898  int cn = cnodes[int(n[j] - nbase)];
1899  if (cn) n[j] = &m_nodes[cn];
1900  }
1901  }
1902  }
1903  /* Clean orphans */
1904  int nnodes = m_nodes.size();
1906  btAlignedObjectArray<int> todelete;
1907  ranks.resize(nnodes, 0);
1908  for (i = 0, ni = m_links.size(); i < ni; ++i)
1909  {
1910  for (int j = 0; j < 2; ++j) ranks[int(m_links[i].m_n[j] - nbase)]++;
1911  }
1912  for (i = 0, ni = m_faces.size(); i < ni; ++i)
1913  {
1914  for (int j = 0; j < 3; ++j) ranks[int(m_faces[i].m_n[j] - nbase)]++;
1915  }
1916  for (i = 0; i < m_links.size(); ++i)
1917  {
1918  const int id[] = {int(m_links[i].m_n[0] - nbase),
1919  int(m_links[i].m_n[1] - nbase)};
1920  const bool sg[] = {ranks[id[0]] == 1,
1921  ranks[id[1]] == 1};
1922  if (sg[0] || sg[1])
1923  {
1924  --ranks[id[0]];
1925  --ranks[id[1]];
1926  btSwap(m_links[i], m_links[m_links.size() - 1]);
1927  m_links.pop_back();
1928  --i;
1929  }
1930  }
1931 #if 0
1932  for(i=nnodes-1;i>=0;--i)
1933  {
1934  if(!ranks[i]) todelete.push_back(i);
1935  }
1936  if(todelete.size())
1937  {
1939  for(int i=0;i<nnodes;++i) map[i]=i;
1940  PointersToIndices(this);
1941  for(int i=0,ni=todelete.size();i<ni;++i)
1942  {
1943  int j=todelete[i];
1944  int& a=map[j];
1945  int& b=map[--nnodes];
1946  m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1947  btSwap(m_nodes[a],m_nodes[b]);
1948  j=a;a=b;b=j;
1949  }
1950  IndicesToPointers(this,&map[0]);
1951  m_nodes.resize(nnodes);
1952  }
1953 #endif
1954  }
1955  m_bUpdateRtCst = true;
1956 }
1957 
1958 //
1959 bool btSoftBody::cutLink(const Node* node0, const Node* node1, btScalar position)
1960 {
1961  return (cutLink(int(node0 - &m_nodes[0]), int(node1 - &m_nodes[0]), position));
1962 }
1963 
1964 //
1965 bool btSoftBody::cutLink(int node0, int node1, btScalar position)
1966 {
1967  bool done = false;
1968  int i, ni;
1969  // const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1970  const btVector3 x = Lerp(m_nodes[node0].m_x, m_nodes[node1].m_x, position);
1971  const btVector3 v = Lerp(m_nodes[node0].m_v, m_nodes[node1].m_v, position);
1972  const btScalar m = 1;
1973  appendNode(x, m);
1974  appendNode(x, m);
1975  Node* pa = &m_nodes[node0];
1976  Node* pb = &m_nodes[node1];
1977  Node* pn[2] = {&m_nodes[m_nodes.size() - 2],
1978  &m_nodes[m_nodes.size() - 1]};
1979  pn[0]->m_v = v;
1980  pn[1]->m_v = v;
1981  for (i = 0, ni = m_links.size(); i < ni; ++i)
1982  {
1983  const int mtch = MatchEdge(m_links[i].m_n[0], m_links[i].m_n[1], pa, pb);
1984  if (mtch != -1)
1985  {
1986  appendLink(i);
1987  Link* pft[] = {&m_links[i], &m_links[m_links.size() - 1]};
1988  pft[0]->m_n[1] = pn[mtch];
1989  pft[1]->m_n[0] = pn[1 - mtch];
1990  done = true;
1991  }
1992  }
1993  for (i = 0, ni = m_faces.size(); i < ni; ++i)
1994  {
1995  for (int k = 2, l = 0; l < 3; k = l++)
1996  {
1997  const int mtch = MatchEdge(m_faces[i].m_n[k], m_faces[i].m_n[l], pa, pb);
1998  if (mtch != -1)
1999  {
2000  appendFace(i);
2001  Face* pft[] = {&m_faces[i], &m_faces[m_faces.size() - 1]};
2002  pft[0]->m_n[l] = pn[mtch];
2003  pft[1]->m_n[k] = pn[1 - mtch];
2004  appendLink(pn[0], pft[0]->m_n[(l + 1) % 3], pft[0]->m_material, true);
2005  appendLink(pn[1], pft[0]->m_n[(l + 1) % 3], pft[0]->m_material, true);
2006  }
2007  }
2008  }
2009  if (!done)
2010  {
2011  m_ndbvt.remove(pn[0]->m_leaf);
2012  m_ndbvt.remove(pn[1]->m_leaf);
2013  m_nodes.pop_back();
2014  m_nodes.pop_back();
2015  }
2016  return (done);
2017 }
2018 
2019 //
2020 bool btSoftBody::rayTest(const btVector3& rayFrom,
2021  const btVector3& rayTo,
2022  sRayCast& results)
2023 {
2024  if (m_faces.size() && m_fdbvt.empty())
2026 
2027  results.body = this;
2028  results.fraction = 1.f;
2029  results.feature = eFeature::None;
2030  results.index = -1;
2031 
2032  return (rayTest(rayFrom, rayTo, results.fraction, results.feature, results.index, false) != 0);
2033 }
2034 
2036  const btVector3& rayTo,
2037  sRayCast& results)
2038 {
2039  if (m_faces.size() == 0)
2040  return false;
2041  else
2042  {
2043  if (m_fdbvt.empty())
2045  }
2046 
2047  results.body = this;
2048  results.fraction = 1.f;
2049  results.index = -1;
2050 
2051  return (rayFaceTest(rayFrom, rayTo, results.fraction, results.index) != 0);
2052 }
2053 
2054 //
2056 {
2060  switch (preset)
2061  {
2067  break;
2070 
2074 
2076  break;
2077  }
2078 }
2079 
2081 {
2082  int i, ni;
2083 
2084  /* Update */
2085  if (m_bUpdateRtCst)
2086  {
2087  m_bUpdateRtCst = false;
2088  updateConstants();
2089  m_fdbvt.clear();
2091  {
2093  }
2094  }
2095 
2096  /* Prepare */
2097  m_sst.sdt = dt * m_cfg.timescale;
2098  m_sst.isdt = 1 / m_sst.sdt;
2099  m_sst.velmrg = m_sst.sdt * 3;
2100  m_sst.radmrg = getCollisionShape()->getMargin();
2101  m_sst.updmrg = m_sst.radmrg * (btScalar)0.25;
2102  /* Forces */
2104  applyForces();
2105  /* Integrate */
2106  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2107  {
2108  Node& n = m_nodes[i];
2109  n.m_q = n.m_x;
2110  btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
2111  {
2112  btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
2113  btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
2114  for (int c = 0; c < 3; c++)
2115  {
2116  if (deltaV[c] > clampDeltaV)
2117  {
2118  deltaV[c] = clampDeltaV;
2119  }
2120  if (deltaV[c] < -clampDeltaV)
2121  {
2122  deltaV[c] = -clampDeltaV;
2123  }
2124  }
2125  }
2126  n.m_v += deltaV;
2127  n.m_x += n.m_v * m_sst.sdt;
2128  n.m_f = btVector3(0, 0, 0);
2129  }
2130  /* Clusters */
2131  updateClusters();
2132  /* Bounds */
2133  updateBounds();
2134  /* Nodes */
2136  vol;
2137  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2138  {
2139  Node& n = m_nodes[i];
2141  m_ndbvt.update(n.m_leaf,
2142  vol,
2143  n.m_v * m_sst.velmrg,
2144  m_sst.updmrg);
2145  }
2146  /* Faces */
2147  if (!m_fdbvt.empty())
2148  {
2149  for (int i = 0; i < m_faces.size(); ++i)
2150  {
2151  Face& f = m_faces[i];
2152  const btVector3 v = (f.m_n[0]->m_v +
2153  f.m_n[1]->m_v +
2154  f.m_n[2]->m_v) /
2155  3;
2156  vol = VolumeOf(f, m_sst.radmrg);
2157  m_fdbvt.update(f.m_leaf,
2158  vol,
2159  v * m_sst.velmrg,
2160  m_sst.updmrg);
2161  }
2162  }
2163  /* Pose */
2164  updatePose();
2165  /* Match */
2166  if (m_pose.m_bframe && (m_cfg.kMT > 0))
2167  {
2168  const btMatrix3x3 posetrs = m_pose.m_rot;
2169  for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
2170  {
2171  Node& n = m_nodes[i];
2172  if (n.m_im > 0)
2173  {
2174  const btVector3 x = posetrs * m_pose.m_pos[i] + m_pose.m_com;
2175  n.m_x = Lerp(n.m_x, x, m_cfg.kMT);
2176  }
2177  }
2178  }
2179  /* Clear contacts */
2180  m_rcontacts.resize(0);
2181  m_scontacts.resize(0);
2182  /* Optimize dbvt's */
2186 }
2187 
2188 //
2190 {
2191  /* Apply clusters */
2192  applyClusters(false);
2193  /* Prepare links */
2194 
2195  int i, ni;
2196 
2197  for (i = 0, ni = m_links.size(); i < ni; ++i)
2198  {
2199  Link& l = m_links[i];
2200  l.m_c3 = l.m_n[1]->m_q - l.m_n[0]->m_q;
2201  l.m_c2 = 1 / (l.m_c3.length2() * l.m_c0);
2202  }
2203  /* Prepare anchors */
2204  for (i = 0, ni = m_anchors.size(); i < ni; ++i)
2205  {
2206  Anchor& a = m_anchors[i];
2207  const btVector3 ra = a.m_body->getWorldTransform().getBasis() * a.m_local;
2208  a.m_c0 = ImpulseMatrix(m_sst.sdt,
2209  a.m_node->m_im,
2210  a.m_body->getInvMass(),
2211  a.m_body->getInvInertiaTensorWorld(),
2212  ra);
2213  a.m_c1 = ra;
2214  a.m_c2 = m_sst.sdt * a.m_node->m_im;
2215  a.m_body->activate();
2216  }
2217  /* Solve velocities */
2218  if (m_cfg.viterations > 0)
2219  {
2220  /* Solve */
2221  for (int isolve = 0; isolve < m_cfg.viterations; ++isolve)
2222  {
2223  for (int iseq = 0; iseq < m_cfg.m_vsequence.size(); ++iseq)
2224  {
2225  getSolver(m_cfg.m_vsequence[iseq])(this, 1);
2226  }
2227  }
2228  /* Update */
2229  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2230  {
2231  Node& n = m_nodes[i];
2232  n.m_x = n.m_q + n.m_v * m_sst.sdt;
2233  }
2234  }
2235  /* Solve positions */
2236  if (m_cfg.piterations > 0)
2237  {
2238  for (int isolve = 0; isolve < m_cfg.piterations; ++isolve)
2239  {
2240  const btScalar ti = isolve / (btScalar)m_cfg.piterations;
2241  for (int iseq = 0; iseq < m_cfg.m_psequence.size(); ++iseq)
2242  {
2243  getSolver(m_cfg.m_psequence[iseq])(this, 1, ti);
2244  }
2245  }
2246  const btScalar vc = m_sst.isdt * (1 - m_cfg.kDP);
2247  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2248  {
2249  Node& n = m_nodes[i];
2250  n.m_v = (n.m_x - n.m_q) * vc;
2251  n.m_f = btVector3(0, 0, 0);
2252  }
2253  }
2254  /* Solve drift */
2255  if (m_cfg.diterations > 0)
2256  {
2257  const btScalar vcf = m_cfg.kVCF * m_sst.isdt;
2258  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2259  {
2260  Node& n = m_nodes[i];
2261  n.m_q = n.m_x;
2262  }
2263  for (int idrift = 0; idrift < m_cfg.diterations; ++idrift)
2264  {
2265  for (int iseq = 0; iseq < m_cfg.m_dsequence.size(); ++iseq)
2266  {
2267  getSolver(m_cfg.m_dsequence[iseq])(this, 1, 0);
2268  }
2269  }
2270  for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
2271  {
2272  Node& n = m_nodes[i];
2273  n.m_v += (n.m_x - n.m_q) * vcf;
2274  }
2275  }
2276  /* Apply clusters */
2277  dampClusters();
2278  applyClusters(true);
2279 }
2280 
2281 //
2282 void btSoftBody::staticSolve(int iterations)
2283 {
2284  for (int isolve = 0; isolve < iterations; ++isolve)
2285  {
2286  for (int iseq = 0; iseq < m_cfg.m_psequence.size(); ++iseq)
2287  {
2288  getSolver(m_cfg.m_psequence[iseq])(this, 1, 0);
2289  }
2290  }
2291 }
2292 
2293 //
2294 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/, int /*count*/, int /*iterations*/)
2295 {
2297 }
2298 
2299 //
2301 {
2302  const int nb = bodies.size();
2303  int iterations = 0;
2304  int i;
2305 
2306  for (i = 0; i < nb; ++i)
2307  {
2308  iterations = btMax(iterations, bodies[i]->m_cfg.citerations);
2309  }
2310  for (i = 0; i < nb; ++i)
2311  {
2312  bodies[i]->prepareClusters(iterations);
2313  }
2314  for (i = 0; i < iterations; ++i)
2315  {
2316  const btScalar sor = 1;
2317  for (int j = 0; j < nb; ++j)
2318  {
2319  bodies[j]->solveClusters(sor);
2320  }
2321  }
2322  for (i = 0; i < nb; ++i)
2323  {
2324  bodies[i]->cleanupClusters();
2325  }
2326 }
2327 
2328 //
2330 {
2331  /* Update */
2332  updateNormals();
2333 }
2334 
2335 //
2337 {
2338  m_rayFrom = rayFrom;
2339  m_rayNormalizedDirection = (rayTo - rayFrom);
2340  m_rayTo = rayTo;
2341  m_mint = mxt;
2342  m_face = 0;
2343  m_tests = 0;
2344 }
2345 
2346 //
2348 {
2349  btSoftBody::Face& f = *(btSoftBody::Face*)leaf->data;
2350  const btScalar t = rayFromToTriangle(m_rayFrom, m_rayTo, m_rayNormalizedDirection,
2351  f.m_n[0]->m_x,
2352  f.m_n[1]->m_x,
2353  f.m_n[2]->m_x,
2354  m_mint);
2355  if ((t > 0) && (t < m_mint))
2356  {
2357  m_mint = t;
2358  m_face = &f;
2359  }
2360  ++m_tests;
2361 }
2362 
2363 //
2365  const btVector3& rayTo,
2366  const btVector3& rayNormalizedDirection,
2367  const btVector3& a,
2368  const btVector3& b,
2369  const btVector3& c,
2370  btScalar maxt)
2371 {
2372  static const btScalar ceps = -SIMD_EPSILON * 10;
2373  static const btScalar teps = SIMD_EPSILON * 10;
2374 
2375  const btVector3 n = btCross(b - a, c - a);
2376  const btScalar d = btDot(a, n);
2377  const btScalar den = btDot(rayNormalizedDirection, n);
2378  if (!btFuzzyZero(den))
2379  {
2380  const btScalar num = btDot(rayFrom, n) - d;
2381  const btScalar t = -num / den;
2382  if ((t > teps) && (t < maxt))
2383  {
2384  const btVector3 hit = rayFrom + rayNormalizedDirection * t;
2385  if ((btDot(n, btCross(a - hit, b - hit)) > ceps) &&
2386  (btDot(n, btCross(b - hit, c - hit)) > ceps) &&
2387  (btDot(n, btCross(c - hit, a - hit)) > ceps))
2388  {
2389  return (t);
2390  }
2391  }
2392  }
2393  return (-1);
2394 }
2395 
2396 //
2398 {
2399 #define PTR2IDX(_p_, _b_) reinterpret_cast<btSoftBody::Node*>((_p_) - (_b_))
2400  btSoftBody::Node* base = m_nodes.size() ? &m_nodes[0] : 0;
2401  int i, ni;
2402 
2403  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2404  {
2405  if (m_nodes[i].m_leaf)
2406  {
2407  m_nodes[i].m_leaf->data = *(void**)&i;
2408  }
2409  }
2410  for (i = 0, ni = m_links.size(); i < ni; ++i)
2411  {
2412  m_links[i].m_n[0] = PTR2IDX(m_links[i].m_n[0], base);
2413  m_links[i].m_n[1] = PTR2IDX(m_links[i].m_n[1], base);
2414  }
2415  for (i = 0, ni = m_faces.size(); i < ni; ++i)
2416  {
2417  m_faces[i].m_n[0] = PTR2IDX(m_faces[i].m_n[0], base);
2418  m_faces[i].m_n[1] = PTR2IDX(m_faces[i].m_n[1], base);
2419  m_faces[i].m_n[2] = PTR2IDX(m_faces[i].m_n[2], base);
2420  if (m_faces[i].m_leaf)
2421  {
2422  m_faces[i].m_leaf->data = *(void**)&i;
2423  }
2424  }
2425  for (i = 0, ni = m_anchors.size(); i < ni; ++i)
2426  {
2427  m_anchors[i].m_node = PTR2IDX(m_anchors[i].m_node, base);
2428  }
2429  for (i = 0, ni = m_notes.size(); i < ni; ++i)
2430  {
2431  for (int j = 0; j < m_notes[i].m_rank; ++j)
2432  {
2433  m_notes[i].m_nodes[j] = PTR2IDX(m_notes[i].m_nodes[j], base);
2434  }
2435  }
2436 #undef PTR2IDX
2437 }
2438 
2439 //
2441 {
2442 #define IDX2PTR(_p_, _b_) map ? (&(_b_)[map[(((char*)_p_) - (char*)0)]]) : (&(_b_)[(((char*)_p_) - (char*)0)])
2443  btSoftBody::Node* base = m_nodes.size() ? &m_nodes[0] : 0;
2444  int i, ni;
2445 
2446  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2447  {
2448  if (m_nodes[i].m_leaf)
2449  {
2450  m_nodes[i].m_leaf->data = &m_nodes[i];
2451  }
2452  }
2453  for (i = 0, ni = m_links.size(); i < ni; ++i)
2454  {
2455  m_links[i].m_n[0] = IDX2PTR(m_links[i].m_n[0], base);
2456  m_links[i].m_n[1] = IDX2PTR(m_links[i].m_n[1], base);
2457  }
2458  for (i = 0, ni = m_faces.size(); i < ni; ++i)
2459  {
2460  m_faces[i].m_n[0] = IDX2PTR(m_faces[i].m_n[0], base);
2461  m_faces[i].m_n[1] = IDX2PTR(m_faces[i].m_n[1], base);
2462  m_faces[i].m_n[2] = IDX2PTR(m_faces[i].m_n[2], base);
2463  if (m_faces[i].m_leaf)
2464  {
2465  m_faces[i].m_leaf->data = &m_faces[i];
2466  }
2467  }
2468  for (i = 0, ni = m_anchors.size(); i < ni; ++i)
2469  {
2470  m_anchors[i].m_node = IDX2PTR(m_anchors[i].m_node, base);
2471  }
2472  for (i = 0, ni = m_notes.size(); i < ni; ++i)
2473  {
2474  for (int j = 0; j < m_notes[i].m_rank; ++j)
2475  {
2476  m_notes[i].m_nodes[j] = IDX2PTR(m_notes[i].m_nodes[j], base);
2477  }
2478  }
2479 #undef IDX2PTR
2480 }
2481 
2482 //
2483 int btSoftBody::rayTest(const btVector3& rayFrom, const btVector3& rayTo,
2484  btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const
2485 {
2486  int cnt = 0;
2487  btVector3 dir = rayTo - rayFrom;
2488 
2489  if (bcountonly || m_fdbvt.empty())
2490  { /* Full search */
2491 
2492  for (int i = 0, ni = m_faces.size(); i < ni; ++i)
2493  {
2494  const btSoftBody::Face& f = m_faces[i];
2495 
2496  const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
2497  f.m_n[0]->m_x,
2498  f.m_n[1]->m_x,
2499  f.m_n[2]->m_x,
2500  mint);
2501  if (t > 0)
2502  {
2503  ++cnt;
2504  if (!bcountonly)
2505  {
2506  feature = btSoftBody::eFeature::Face;
2507  index = i;
2508  mint = t;
2509  }
2510  }
2511  }
2512  }
2513  else
2514  { /* Use dbvt */
2515  RayFromToCaster collider(rayFrom, rayTo, mint);
2516 
2517  btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
2518  if (collider.m_face)
2519  {
2520  mint = collider.m_mint;
2521  feature = btSoftBody::eFeature::Face;
2522  index = (int)(collider.m_face - &m_faces[0]);
2523  cnt = 1;
2524  }
2525  }
2526 
2527  for (int i = 0; i < m_tetras.size(); i++)
2528  {
2529  const btSoftBody::Tetra& tet = m_tetras[i];
2530  int tetfaces[4][3] = {{0, 1, 2}, {0, 1, 3}, {1, 2, 3}, {0, 2, 3}};
2531  for (int f = 0; f < 4; f++)
2532  {
2533  int index0 = tetfaces[f][0];
2534  int index1 = tetfaces[f][1];
2535  int index2 = tetfaces[f][2];
2536  btVector3 v0 = tet.m_n[index0]->m_x;
2537  btVector3 v1 = tet.m_n[index1]->m_x;
2538  btVector3 v2 = tet.m_n[index2]->m_x;
2539 
2540  const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
2541  v0, v1, v2,
2542  mint);
2543  if (t > 0)
2544  {
2545  ++cnt;
2546  if (!bcountonly)
2547  {
2548  feature = btSoftBody::eFeature::Tetra;
2549  index = i;
2550  mint = t;
2551  }
2552  }
2553  }
2554  }
2555  return (cnt);
2556 }
2557 
2558 int btSoftBody::rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
2559  btScalar& mint, int& index) const
2560 {
2561  int cnt = 0;
2562  { /* Use dbvt */
2563  RayFromToCaster collider(rayFrom, rayTo, mint);
2564 
2565  btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
2566  if (collider.m_face)
2567  {
2568  mint = collider.m_mint;
2569  index = (int)(collider.m_face - &m_faces[0]);
2570  cnt = 1;
2571  }
2572  }
2573  return (cnt);
2574 }
2575 
2576 //
2577 static inline btDbvntNode* copyToDbvnt(const btDbvtNode* n)
2578 {
2579  if (n == 0)
2580  return 0;
2581  btDbvntNode* root = new btDbvntNode(n);
2582  if (n->isinternal())
2583  {
2584  btDbvntNode* c0 = copyToDbvnt(n->childs[0]);
2585  root->childs[0] = c0;
2586  btDbvntNode* c1 = copyToDbvnt(n->childs[1]);
2587  root->childs[1] = c1;
2588  }
2589  return root;
2590 }
2591 
2592 static inline void calculateNormalCone(btDbvntNode* root)
2593 {
2594  if (!root)
2595  return;
2596  if (root->isleaf())
2597  {
2598  const btSoftBody::Face* face = (btSoftBody::Face*)root->data;
2599  root->normal = face->m_normal;
2600  root->angle = 0;
2601  }
2602  else
2603  {
2604  btVector3 n0(0, 0, 0), n1(0, 0, 0);
2605  btScalar a0 = 0, a1 = 0;
2606  if (root->childs[0])
2607  {
2608  calculateNormalCone(root->childs[0]);
2609  n0 = root->childs[0]->normal;
2610  a0 = root->childs[0]->angle;
2611  }
2612  if (root->childs[1])
2613  {
2614  calculateNormalCone(root->childs[1]);
2615  n1 = root->childs[1]->normal;
2616  a1 = root->childs[1]->angle;
2617  }
2618  root->normal = (n0 + n1).safeNormalize();
2619  root->angle = btMax(a0, a1) + btAngle(n0, n1) * 0.5;
2620  }
2621 }
2622 
2624 {
2625  BT_PROFILE("btSoftBody::initializeFaceTree");
2626  m_fdbvt.clear();
2627  // create leaf nodes;
2629  leafNodes.resize(m_faces.size());
2630  for (int i = 0; i < m_faces.size(); ++i)
2631  {
2632  Face& f = m_faces[i];
2634  vol = VolumeOf(f, 0);
2635  btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
2636  node->parent = NULL;
2637  node->data = &f;
2638  node->childs[1] = 0;
2639  node->volume = vol;
2640  leafNodes[i] = node;
2641  f.m_leaf = node;
2642  }
2644  adj.resize(m_faces.size());
2645  // construct the adjacency list for triangles
2646  for (int i = 0; i < adj.size(); ++i)
2647  {
2648  for (int j = i + 1; j < adj.size(); ++j)
2649  {
2650  int dup = 0;
2651  for (int k = 0; k < 3; ++k)
2652  {
2653  for (int l = 0; l < 3; ++l)
2654  {
2655  if (m_faces[i].m_n[k] == m_faces[j].m_n[l])
2656  {
2657  ++dup;
2658  break;
2659  }
2660  }
2661  if (dup == 2)
2662  {
2663  adj[i].push_back(j);
2664  adj[j].push_back(i);
2665  }
2666  }
2667  }
2668  }
2669  m_fdbvt.m_root = buildTreeBottomUp(leafNodes, adj);
2670  if (m_fdbvnt)
2671  delete m_fdbvnt;
2673  updateFaceTree(false, false);
2674  rebuildNodeTree();
2675 }
2676 
2677 //
2679 {
2680  m_ndbvt.clear();
2682  leafNodes.resize(m_nodes.size());
2683  for (int i = 0; i < m_nodes.size(); ++i)
2684  {
2685  Node& n = m_nodes[i];
2687  vol = btDbvtVolume::FromCR(n.m_x, 0);
2688  btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
2689  node->parent = NULL;
2690  node->data = &n;
2691  node->childs[1] = 0;
2692  node->volume = vol;
2693  leafNodes[i] = node;
2694  n.m_leaf = node;
2695  }
2697  adj.resize(m_nodes.size());
2699  old_id.resize(m_nodes.size());
2700  for (int i = 0; i < m_nodes.size(); ++i)
2701  old_id[i] = m_nodes[i].index;
2702  for (int i = 0; i < m_nodes.size(); ++i)
2703  m_nodes[i].index = i;
2704  for (int i = 0; i < m_links.size(); ++i)
2705  {
2706  Link& l = m_links[i];
2707  adj[l.m_n[0]->index].push_back(l.m_n[1]->index);
2708  adj[l.m_n[1]->index].push_back(l.m_n[0]->index);
2709  }
2710  m_ndbvt.m_root = buildTreeBottomUp(leafNodes, adj);
2711  for (int i = 0; i < m_nodes.size(); ++i)
2712  m_nodes[i].index = old_id[i];
2713 }
2714 
2715 //
2717 {
2718  btVector3 com(0, 0, 0);
2719  if (m_pose.m_bframe)
2720  {
2721  for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
2722  {
2723  com += m_nodes[i].m_x * m_pose.m_wgh[i];
2724  }
2725  }
2726  return (com);
2727 }
2728 
2730  const btVector3& x,
2731  btScalar margin,
2732  btSoftBody::sCti& cti) const
2733 {
2734  btVector3 nrm;
2735  const btCollisionShape* shp = colObjWrap->getCollisionShape();
2736  // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
2737  //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
2738  const btTransform& wtr = colObjWrap->getWorldTransform();
2739  //todo: check which transform is needed here
2740 
2741  btScalar dst =
2743  wtr.invXform(x),
2744  shp,
2745  nrm,
2746  margin);
2747  if (dst < 0)
2748  {
2749  cti.m_colObj = colObjWrap->getCollisionObject();
2750  cti.m_normal = wtr.getBasis() * nrm;
2751  cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
2752  return (true);
2753  }
2754  return (false);
2755 }
2756 
2757 //
2759  const btVector3& x,
2760  btScalar margin,
2761  btSoftBody::sCti& cti, bool predict) const
2762 {
2763  btVector3 nrm;
2764  const btCollisionShape* shp = colObjWrap->getCollisionShape();
2765  const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
2766  // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
2767  // but resolve contact at x_n
2768  btTransform wtr = (predict) ? (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform() * (*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
2769  : colObjWrap->getWorldTransform();
2770  btScalar dst =
2772  wtr.invXform(x),
2773  shp,
2774  nrm,
2775  margin);
2776 
2777  if (!predict)
2778  {
2779  cti.m_colObj = colObjWrap->getCollisionObject();
2780  cti.m_normal = wtr.getBasis() * nrm;
2781  cti.m_offset = dst;
2782  }
2783  if (dst < 0)
2784  return true;
2785  return (false);
2786 }
2787 
2788 //
2789 // Compute barycentric coordinates (u, v, w) for
2790 // point p with respect to triangle (a, b, c)
2791 static void getBarycentric(const btVector3& p, btVector3& a, btVector3& b, btVector3& c, btVector3& bary)
2792 {
2793  btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
2794  btScalar d00 = v0.dot(v0);
2795  btScalar d01 = v0.dot(v1);
2796  btScalar d11 = v1.dot(v1);
2797  btScalar d20 = v2.dot(v0);
2798  btScalar d21 = v2.dot(v1);
2799  btScalar denom = d00 * d11 - d01 * d01;
2800  bary.setY((d11 * d20 - d01 * d21) / denom);
2801  bary.setZ((d00 * d21 - d01 * d20) / denom);
2802  bary.setX(btScalar(1) - bary.getY() - bary.getZ());
2803 }
2804 
2805 //
2807  Face& f,
2808  btVector3& contact_point,
2809  btVector3& bary,
2810  btScalar margin,
2811  btSoftBody::sCti& cti, bool predict) const
2812 {
2813  btVector3 nrm;
2814  const btCollisionShape* shp = colObjWrap->getCollisionShape();
2815  const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
2816  // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
2817  // but resolve contact at x_n
2818  btTransform wtr = (predict) ? (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform() * (*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
2819  : colObjWrap->getWorldTransform();
2820  btScalar dst;
2821  btGjkEpaSolver2::sResults results;
2822 
2823 // #define USE_QUADRATURE 1
2824 //#define CACHE_PREV_COLLISION
2825 
2826  // use collision quadrature point
2827 #ifdef USE_QUADRATURE
2828  {
2829  dst = SIMD_INFINITY;
2830  btVector3 local_nrm;
2831  for (int q = 0; q < m_quads.size(); ++q)
2832  {
2833  btVector3 p;
2834  if (predict)
2835  p = BaryEval(f.m_n[0]->m_q, f.m_n[1]->m_q, f.m_n[2]->m_q, m_quads[q]);
2836  else
2837  p = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, m_quads[q]);
2839  wtr.invXform(p),
2840  shp,
2841  local_nrm,
2842  margin);
2843  if (local_dst < dst)
2844  {
2845  if (local_dst < 0 && predict)
2846  return true;
2847  dst = local_dst;
2848  contact_point = p;
2849  bary = m_quads[q];
2850  nrm = local_nrm;
2851  }
2852  if (!predict)
2853  {
2854  cti.m_colObj = colObjWrap->getCollisionObject();
2855  cti.m_normal = wtr.getBasis() * nrm;
2856  cti.m_offset = dst;
2857  }
2858  }
2859  return (dst < 0);
2860  }
2861 #endif
2862 
2863  // collision detection using x*
2864  btTransform triangle_transform;
2865  triangle_transform.setIdentity();
2866  triangle_transform.setOrigin(f.m_n[0]->m_q);
2867  btTriangleShape triangle(btVector3(0, 0, 0), f.m_n[1]->m_q - f.m_n[0]->m_q, f.m_n[2]->m_q - f.m_n[0]->m_q);
2868  btVector3 guess(0, 0, 0);
2869  const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
2870  btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
2871  dst = results.distance - 2.0 * csh->getMargin() - margin; // margin padding so that the distance = the actual distance between face and rigid - margin of rigid - margin of deformable
2872  if (dst >= 0)
2873  return false;
2874 
2875 // Use consistent barycenter to recalculate distance.
2876 #ifdef CACHE_PREV_COLLISION
2877  if (f.m_pcontact[3] != 0)
2878  {
2879  for (int i = 0; i < 3; ++i)
2880  bary[i] = f.m_pcontact[i];
2881  contact_point = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
2882  const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
2883  btGjkEpaSolver2::SignedDistance(contact_point, margin, csh, wtr, results);
2884  cti.m_colObj = colObjWrap->getCollisionObject();
2885  dst = results.distance;
2886  cti.m_normal = results.normal;
2887  cti.m_offset = dst;
2888 
2889  //point-convex CD
2890  wtr = colObjWrap->getWorldTransform();
2891  btTriangleShape triangle2(btVector3(0, 0, 0), f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
2892  triangle_transform.setOrigin(f.m_n[0]->m_x);
2893  btGjkEpaSolver2::SignedDistance(&triangle2, triangle_transform, csh, wtr, guess, results);
2894 
2895  dst = results.distance - csh->getMargin() - margin;
2896  return true;
2897  }
2898 #endif
2899 
2900  // Use triangle-convex CD.
2901  wtr = colObjWrap->getWorldTransform();
2902  btTriangleShape triangle2(btVector3(0, 0, 0), f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
2903  triangle_transform.setOrigin(f.m_n[0]->m_x);
2904  btGjkEpaSolver2::SignedDistance(&triangle2, triangle_transform, csh, wtr, guess, results);
2905  contact_point = results.witnesses[0];
2906  getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
2907 
2908  for (int i = 0; i < 3; ++i)
2909  f.m_pcontact[i] = bary[i];
2910 
2911  dst = results.distance - csh->getMargin() - margin;
2912  cti.m_colObj = colObjWrap->getCollisionObject();
2913  cti.m_normal = results.normal;
2914  cti.m_offset = dst;
2915  return true;
2916 }
2917 
2919 {
2920  const btVector3 zv(0, 0, 0);
2921  int i, ni;
2922 
2923  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2924  {
2925  m_nodes[i].m_n = zv;
2926  }
2927  for (i = 0, ni = m_faces.size(); i < ni; ++i)
2928  {
2929  btSoftBody::Face& f = m_faces[i];
2930  const btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x,
2931  f.m_n[2]->m_x - f.m_n[0]->m_x);
2932  f.m_normal = n;
2933  f.m_normal.safeNormalize();
2934  f.m_n[0]->m_n += n;
2935  f.m_n[1]->m_n += n;
2936  f.m_n[2]->m_n += n;
2937  }
2938  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2939  {
2940  btScalar len = m_nodes[i].m_n.length();
2941  if (len > SIMD_EPSILON)
2942  m_nodes[i].m_n /= len;
2943  }
2944 }
2945 
2946 //
2948 {
2949  /*if( m_acceleratedSoftBody )
2950  {
2951  // If we have an accelerated softbody we need to obtain the bounds correctly
2952  // For now (slightly hackily) just have a very large AABB
2953  // TODO: Write get bounds kernel
2954  // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
2955  // probably do a test and exchange reasonably efficiently.
2956 
2957  m_bounds[0] = btVector3(-1000, -1000, -1000);
2958  m_bounds[1] = btVector3(1000, 1000, 1000);
2959 
2960  } else {*/
2961  // if (m_ndbvt.m_root)
2962  // {
2963  // const btVector3& mins = m_ndbvt.m_root->volume.Mins();
2964  // const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
2965  // const btScalar csm = getCollisionShape()->getMargin();
2966  // const btVector3 mrg = btVector3(csm,
2967  // csm,
2968  // csm) *
2969  // 1; // ??? to investigate...
2970  // m_bounds[0] = mins - mrg;
2971  // m_bounds[1] = maxs + mrg;
2972  // if (0 != getBroadphaseHandle())
2973  // {
2974  // m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
2975  // m_bounds[0],
2976  // m_bounds[1],
2977  // m_worldInfo->m_dispatcher);
2978  // }
2979  // }
2980  // else
2981  // {
2982  // m_bounds[0] =
2983  // m_bounds[1] = btVector3(0, 0, 0);
2984  // }
2985  if (m_nodes.size())
2986  {
2987  btVector3 mins = m_nodes[0].m_x;
2988  btVector3 maxs = m_nodes[0].m_x;
2989  for (int i = 1; i < m_nodes.size(); ++i)
2990  {
2991  for (int d = 0; d < 3; ++d)
2992  {
2993  if (m_nodes[i].m_x[d] > maxs[d])
2994  maxs[d] = m_nodes[i].m_x[d];
2995  if (m_nodes[i].m_x[d] < mins[d])
2996  mins[d] = m_nodes[i].m_x[d];
2997  }
2998  }
2999  const btScalar csm = getCollisionShape()->getMargin();
3000  const btVector3 mrg = btVector3(csm,
3001  csm,
3002  csm);
3003  m_bounds[0] = mins - mrg;
3004  m_bounds[1] = maxs + mrg;
3005  if (0 != getBroadphaseHandle())
3006  {
3008  m_bounds[0],
3009  m_bounds[1],
3011  }
3012  }
3013  else
3014  {
3015  m_bounds[0] =
3016  m_bounds[1] = btVector3(0, 0, 0);
3017  }
3018 }
3019 
3020 //
3022 {
3023  if (m_pose.m_bframe)
3024  {
3025  btSoftBody::Pose& pose = m_pose;
3026  const btVector3 com = evaluateCom();
3027  /* Com */
3028  pose.m_com = com;
3029  /* Rotation */
3030  btMatrix3x3 Apq;
3031  const btScalar eps = SIMD_EPSILON;
3032  Apq[0] = Apq[1] = Apq[2] = btVector3(0, 0, 0);
3033  Apq[0].setX(eps);
3034  Apq[1].setY(eps * 2);
3035  Apq[2].setZ(eps * 3);
3036  for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
3037  {
3038  const btVector3 a = pose.m_wgh[i] * (m_nodes[i].m_x - com);
3039  const btVector3& b = pose.m_pos[i];
3040  Apq[0] += a.x() * b;
3041  Apq[1] += a.y() * b;
3042  Apq[2] += a.z() * b;
3043  }
3044  btMatrix3x3 r, s;
3045  PolarDecompose(Apq, r, s);
3046  pose.m_rot = r;
3047  pose.m_scl = pose.m_aqq * r.transpose() * Apq;
3048  if (m_cfg.maxvolume > 1)
3049  {
3050  const btScalar idet = Clamp<btScalar>(1 / pose.m_scl.determinant(),
3051  1, m_cfg.maxvolume);
3052  pose.m_scl = Mul(pose.m_scl, idet);
3053  }
3054  }
3055 }
3056 
3057 //
3058 void btSoftBody::updateArea(bool averageArea)
3059 {
3060  int i, ni;
3061 
3062  /* Face area */
3063  for (i = 0, ni = m_faces.size(); i < ni; ++i)
3064  {
3065  Face& f = m_faces[i];
3066  f.m_ra = AreaOf(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x);
3067  }
3068 
3069  /* Node area */
3070 
3071  if (averageArea)
3072  {
3074  counts.resize(m_nodes.size(), 0);
3075  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3076  {
3077  m_nodes[i].m_area = 0;
3078  }
3079  for (i = 0, ni = m_faces.size(); i < ni; ++i)
3080  {
3081  btSoftBody::Face& f = m_faces[i];
3082  for (int j = 0; j < 3; ++j)
3083  {
3084  const int index = (int)(f.m_n[j] - &m_nodes[0]);
3085  counts[index]++;
3086  f.m_n[j]->m_area += btFabs(f.m_ra);
3087  }
3088  }
3089  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3090  {
3091  if (counts[i] > 0)
3092  m_nodes[i].m_area /= (btScalar)counts[i];
3093  else
3094  m_nodes[i].m_area = 0;
3095  }
3096  }
3097  else
3098  {
3099  // initialize node area as zero
3100  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3101  {
3102  m_nodes[i].m_area = 0;
3103  }
3104 
3105  for (i = 0, ni = m_faces.size(); i < ni; ++i)
3106  {
3107  btSoftBody::Face& f = m_faces[i];
3108 
3109  for (int j = 0; j < 3; ++j)
3110  {
3111  f.m_n[j]->m_area += f.m_ra;
3112  }
3113  }
3114 
3115  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3116  {
3117  m_nodes[i].m_area *= 0.3333333f;
3118  }
3119  }
3120 }
3121 
3123 {
3124  int i, ni;
3125 
3126  /* Links */
3127  for (i = 0, ni = m_links.size(); i < ni; ++i)
3128  {
3129  Link& l = m_links[i];
3130  Material& m = *l.m_material;
3131  l.m_c0 = (l.m_n[0]->m_im + l.m_n[1]->m_im) / m.m_kLST;
3132  }
3133 }
3134 
3136 {
3139  updateArea();
3140 }
3141 
3142 //
3144 {
3145  int i;
3146 
3147  for (i = 0; i < m_clusters.size(); ++i)
3148  {
3149  Cluster& c = *m_clusters[i];
3150  c.m_imass = 0;
3151  c.m_masses.resize(c.m_nodes.size());
3152  for (int j = 0; j < c.m_nodes.size(); ++j)
3153  {
3154  if (c.m_nodes[j]->m_im == 0)
3155  {
3156  c.m_containsAnchor = true;
3157  c.m_masses[j] = BT_LARGE_FLOAT;
3158  }
3159  else
3160  {
3161  c.m_masses[j] = btScalar(1.) / c.m_nodes[j]->m_im;
3162  }
3163  c.m_imass += c.m_masses[j];
3164  }
3165  c.m_imass = btScalar(1.) / c.m_imass;
3166  c.m_com = btSoftBody::clusterCom(&c);
3167  c.m_lv = btVector3(0, 0, 0);
3168  c.m_av = btVector3(0, 0, 0);
3169  c.m_leaf = 0;
3170  /* Inertia */
3171  btMatrix3x3& ii = c.m_locii;
3172  ii[0] = ii[1] = ii[2] = btVector3(0, 0, 0);
3173  {
3174  int i, ni;
3175 
3176  for (i = 0, ni = c.m_nodes.size(); i < ni; ++i)
3177  {
3178  const btVector3 k = c.m_nodes[i]->m_x - c.m_com;
3179  const btVector3 q = k * k;
3180  const btScalar m = c.m_masses[i];
3181  ii[0][0] += m * (q[1] + q[2]);
3182  ii[1][1] += m * (q[0] + q[2]);
3183  ii[2][2] += m * (q[0] + q[1]);
3184  ii[0][1] -= m * k[0] * k[1];
3185  ii[0][2] -= m * k[0] * k[2];
3186  ii[1][2] -= m * k[1] * k[2];
3187  }
3188  }
3189  ii[1][0] = ii[0][1];
3190  ii[2][0] = ii[0][2];
3191  ii[2][1] = ii[1][2];
3192 
3193  ii = ii.inverse();
3194 
3195  /* Frame */
3196  c.m_framexform.setIdentity();
3197  c.m_framexform.setOrigin(c.m_com);
3198  c.m_framerefs.resize(c.m_nodes.size());
3199  {
3200  int i;
3201  for (i = 0; i < c.m_framerefs.size(); ++i)
3202  {
3203  c.m_framerefs[i] = c.m_nodes[i]->m_x - c.m_com;
3204  }
3205  }
3206  }
3207 }
3208 
3209 //
3211 {
3212  BT_PROFILE("UpdateClusters");
3213  int i;
3214 
3215  for (i = 0; i < m_clusters.size(); ++i)
3216  {
3218  const int n = c.m_nodes.size();
3219  //const btScalar invn=1/(btScalar)n;
3220  if (n)
3221  {
3222  /* Frame */
3223  const btScalar eps = btScalar(0.0001);
3224  btMatrix3x3 m, r, s;
3225  m[0] = m[1] = m[2] = btVector3(0, 0, 0);
3226  m[0][0] = eps * 1;
3227  m[1][1] = eps * 2;
3228  m[2][2] = eps * 3;
3229  c.m_com = clusterCom(&c);
3230  for (int i = 0; i < c.m_nodes.size(); ++i)
3231  {
3232  const btVector3 a = c.m_nodes[i]->m_x - c.m_com;
3233  const btVector3& b = c.m_framerefs[i];
3234  m[0] += a[0] * b;
3235  m[1] += a[1] * b;
3236  m[2] += a[2] * b;
3237  }
3238  PolarDecompose(m, r, s);
3239  c.m_framexform.setOrigin(c.m_com);
3240  c.m_framexform.setBasis(r);
3241  /* Inertia */
3242 #if 1 /* Constant */
3243  c.m_invwi = c.m_framexform.getBasis() * c.m_locii * c.m_framexform.getBasis().transpose();
3244 #else
3245 #if 0 /* Sphere */
3246  const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
3247  const btVector3 inertia(rk,rk,rk);
3248  const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
3249  btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
3250  btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
3251 
3252  c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
3253 #else /* Actual */
3254  c.m_invwi[0] = c.m_invwi[1] = c.m_invwi[2] = btVector3(0, 0, 0);
3255  for (int i = 0; i < n; ++i)
3256  {
3257  const btVector3 k = c.m_nodes[i]->m_x - c.m_com;
3258  const btVector3 q = k * k;
3259  const btScalar m = 1 / c.m_nodes[i]->m_im;
3260  c.m_invwi[0][0] += m * (q[1] + q[2]);
3261  c.m_invwi[1][1] += m * (q[0] + q[2]);
3262  c.m_invwi[2][2] += m * (q[0] + q[1]);
3263  c.m_invwi[0][1] -= m * k[0] * k[1];
3264  c.m_invwi[0][2] -= m * k[0] * k[2];
3265  c.m_invwi[1][2] -= m * k[1] * k[2];
3266  }
3267  c.m_invwi[1][0] = c.m_invwi[0][1];
3268  c.m_invwi[2][0] = c.m_invwi[0][2];
3269  c.m_invwi[2][1] = c.m_invwi[1][2];
3270  c.m_invwi = c.m_invwi.inverse();
3271 #endif
3272 #endif
3273  /* Velocities */
3274  c.m_lv = btVector3(0, 0, 0);
3275  c.m_av = btVector3(0, 0, 0);
3276  {
3277  int i;
3278 
3279  for (i = 0; i < n; ++i)
3280  {
3281  const btVector3 v = c.m_nodes[i]->m_v * c.m_masses[i];
3282  c.m_lv += v;
3283  c.m_av += btCross(c.m_nodes[i]->m_x - c.m_com, v);
3284  }
3285  }
3286  c.m_lv = c.m_imass * c.m_lv * (1 - c.m_ldamping);
3287  c.m_av = c.m_invwi * c.m_av * (1 - c.m_adamping);
3288  c.m_vimpulses[0] =
3289  c.m_vimpulses[1] = btVector3(0, 0, 0);
3290  c.m_dimpulses[0] =
3291  c.m_dimpulses[1] = btVector3(0, 0, 0);
3292  c.m_nvimpulses = 0;
3293  c.m_ndimpulses = 0;
3294  /* Matching */
3295  if (c.m_matching > 0)
3296  {
3297  for (int j = 0; j < c.m_nodes.size(); ++j)
3298  {
3299  Node& n = *c.m_nodes[j];
3300  const btVector3 x = c.m_framexform * c.m_framerefs[j];
3301  n.m_x = Lerp(n.m_x, x, c.m_matching);
3302  }
3303  }
3304  /* Dbvt */
3305  if (c.m_collide)
3306  {
3307  btVector3 mi = c.m_nodes[0]->m_x;
3308  btVector3 mx = mi;
3309  for (int j = 1; j < n; ++j)
3310  {
3311  mi.setMin(c.m_nodes[j]->m_x);
3312  mx.setMax(c.m_nodes[j]->m_x);
3313  }
3315  bounds = btDbvtVolume::FromMM(mi, mx);
3316  if (c.m_leaf)
3317  m_cdbvt.update(c.m_leaf, bounds, c.m_lv * m_sst.sdt * 3, m_sst.radmrg);
3318  else
3319  c.m_leaf = m_cdbvt.insert(bounds, &c);
3320  }
3321  }
3322  }
3323 }
3324 
3325 //
3327 {
3328  for (int i = 0; i < m_joints.size(); ++i)
3329  {
3330  m_joints[i]->Terminate(m_sst.sdt);
3331  if (m_joints[i]->m_delete)
3332  {
3333  btAlignedFree(m_joints[i]);
3334  m_joints.remove(m_joints[i--]);
3335  }
3336  }
3337 }
3338 
3339 //
3340 void btSoftBody::prepareClusters(int iterations)
3341 {
3342  for (int i = 0; i < m_joints.size(); ++i)
3343  {
3344  m_joints[i]->Prepare(m_sst.sdt, iterations);
3345  }
3346 }
3347 
3348 //
3350 {
3351  for (int i = 0, ni = m_joints.size(); i < ni; ++i)
3352  {
3353  m_joints[i]->Solve(m_sst.sdt, sor);
3354  }
3355 }
3356 
3357 //
3359 {
3360  BT_PROFILE("ApplyClusters");
3361  // const btScalar f0=m_sst.sdt;
3362  //const btScalar f1=f0/2;
3365  deltas.resize(m_nodes.size(), btVector3(0, 0, 0));
3366  weights.resize(m_nodes.size(), 0);
3367  int i;
3368 
3369  if (drift)
3370  {
3371  for (i = 0; i < m_clusters.size(); ++i)
3372  {
3373  Cluster& c = *m_clusters[i];
3374  if (c.m_ndimpulses)
3375  {
3376  c.m_dimpulses[0] /= (btScalar)c.m_ndimpulses;
3377  c.m_dimpulses[1] /= (btScalar)c.m_ndimpulses;
3378  }
3379  }
3380  }
3381 
3382  for (i = 0; i < m_clusters.size(); ++i)
3383  {
3384  Cluster& c = *m_clusters[i];
3385  if (0 < (drift ? c.m_ndimpulses : c.m_nvimpulses))
3386  {
3387  const btVector3 v = (drift ? c.m_dimpulses[0] : c.m_vimpulses[0]) * m_sst.sdt;
3388  const btVector3 w = (drift ? c.m_dimpulses[1] : c.m_vimpulses[1]) * m_sst.sdt;
3389  for (int j = 0; j < c.m_nodes.size(); ++j)
3390  {
3391  const int idx = int(c.m_nodes[j] - &m_nodes[0]);
3392  const btVector3& x = c.m_nodes[j]->m_x;
3393  const btScalar q = c.m_masses[j];
3394  deltas[idx] += (v + btCross(w, x - c.m_com)) * q;
3395  weights[idx] += q;
3396  }
3397  }
3398  }
3399  for (i = 0; i < deltas.size(); ++i)
3400  {
3401  if (weights[i] > 0)
3402  {
3403  m_nodes[i].m_x += deltas[i] / weights[i];
3404  }
3405  }
3406 }
3407 
3408 //
3410 {
3411  int i;
3412 
3413  for (i = 0; i < m_clusters.size(); ++i)
3414  {
3415  Cluster& c = *m_clusters[i];
3416  if (c.m_ndamping > 0)
3417  {
3418  for (int j = 0; j < c.m_nodes.size(); ++j)
3419  {
3420  Node& n = *c.m_nodes[j];
3421  if (n.m_im > 0)
3422  {
3423  const btVector3 vx = c.m_lv + btCross(c.m_av, c.m_nodes[j]->m_q - c.m_com);
3424  if (vx.length2() <= n.m_v.length2())
3425  {
3426  n.m_v += c.m_ndamping * (vx - n.m_v);
3427  }
3428  }
3429  }
3430  }
3431  }
3432 }
3433 
3435 {
3436  for (int i = 0; i < m_links.size(); ++i)
3437  {
3438  m_links[i].Feature::m_material->m_kLST = k;
3439  }
3441 }
3442 
3444 {
3445  m_gravityFactor = gravFactor;
3446 }
3447 
3449 {
3450  btScalar unit_simplex_measure = 1. / 6.;
3451 
3452  for (int i = 0; i < m_tetras.size(); ++i)
3453  {
3454  Tetra& t = m_tetras[i];
3455  btVector3 c1 = t.m_n[1]->m_x - t.m_n[0]->m_x;
3456  btVector3 c2 = t.m_n[2]->m_x - t.m_n[0]->m_x;
3457  btVector3 c3 = t.m_n[3]->m_x - t.m_n[0]->m_x;
3458  btMatrix3x3 Dm(c1.getX(), c2.getX(), c3.getX(),
3459  c1.getY(), c2.getY(), c3.getY(),
3460  c1.getZ(), c2.getZ(), c3.getZ());
3461  t.m_element_measure = Dm.determinant() * unit_simplex_measure;
3462  t.m_Dm_inverse = Dm.inverse();
3463 
3464  // calculate the first three columns of P^{-1}
3465  btVector3 a = t.m_n[0]->m_x;
3466  btVector3 b = t.m_n[1]->m_x;
3467  btVector3 c = t.m_n[2]->m_x;
3468  btVector3 d = t.m_n[3]->m_x;
3469 
3470  btScalar det = 1 / (a[0] * b[1] * c[2] - a[0] * b[1] * d[2] - a[0] * b[2] * c[1] + a[0] * b[2] * d[1] + a[0] * c[1] * d[2] - a[0] * c[2] * d[1] + a[1] * (-b[0] * c[2] + b[0] * d[2] + b[2] * c[0] - b[2] * d[0] - c[0] * d[2] + c[2] * d[0]) + a[2] * (b[0] * c[1] - b[0] * d[1] + b[1] * (d[0] - c[0]) + c[0] * d[1] - c[1] * d[0]) - b[0] * c[1] * d[2] + b[0] * c[2] * d[1] + b[1] * c[0] * d[2] - b[1] * c[2] * d[0] - b[2] * c[0] * d[1] + b[2] * c[1] * d[0]);
3471 
3472  btScalar P11 = -b[2] * c[1] + d[2] * c[1] + b[1] * c[2] + b[2] * d[1] - c[2] * d[1] - b[1] * d[2];
3473  btScalar P12 = b[2] * c[0] - d[2] * c[0] - b[0] * c[2] - b[2] * d[0] + c[2] * d[0] + b[0] * d[2];
3474  btScalar P13 = -b[1] * c[0] + d[1] * c[0] + b[0] * c[1] + b[1] * d[0] - c[1] * d[0] - b[0] * d[1];
3475  btScalar P21 = a[2] * c[1] - d[2] * c[1] - a[1] * c[2] - a[2] * d[1] + c[2] * d[1] + a[1] * d[2];
3476  btScalar P22 = -a[2] * c[0] + d[2] * c[0] + a[0] * c[2] + a[2] * d[0] - c[2] * d[0] - a[0] * d[2];
3477  btScalar P23 = a[1] * c[0] - d[1] * c[0] - a[0] * c[1] - a[1] * d[0] + c[1] * d[0] + a[0] * d[1];
3478  btScalar P31 = -a[2] * b[1] + d[2] * b[1] + a[1] * b[2] + a[2] * d[1] - b[2] * d[1] - a[1] * d[2];
3479  btScalar P32 = a[2] * b[0] - d[2] * b[0] - a[0] * b[2] - a[2] * d[0] + b[2] * d[0] + a[0] * d[2];
3480  btScalar P33 = -a[1] * b[0] + d[1] * b[0] + a[0] * b[1] + a[1] * d[0] - b[1] * d[0] - a[0] * d[1];
3481  btScalar P41 = a[2] * b[1] - c[2] * b[1] - a[1] * b[2] - a[2] * c[1] + b[2] * c[1] + a[1] * c[2];
3482  btScalar P42 = -a[2] * b[0] + c[2] * b[0] + a[0] * b[2] + a[2] * c[0] - b[2] * c[0] - a[0] * c[2];
3483  btScalar P43 = a[1] * b[0] - c[1] * b[0] - a[0] * b[1] - a[1] * c[0] + b[1] * c[0] + a[0] * c[1];
3484 
3485  btVector4 p1(P11 * det, P21 * det, P31 * det, P41 * det);
3486  btVector4 p2(P12 * det, P22 * det, P32 * det, P42 * det);
3487  btVector4 p3(P13 * det, P23 * det, P33 * det, P43 * det);
3488 
3489  t.m_P_inv[0] = p1;
3490  t.m_P_inv[1] = p2;
3491  t.m_P_inv[2] = p3;
3492  }
3493 }
3494 
3495 static btScalar Dot4(const btVector4& a, const btVector4& b)
3496 {
3497  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
3498 }
3499 
3501 {
3502  btQuaternion q;
3503  for (int i = 0; i < m_tetras.size(); ++i)
3504  {
3506  btVector3 c1 = t.m_n[1]->m_q - t.m_n[0]->m_q;
3507  btVector3 c2 = t.m_n[2]->m_q - t.m_n[0]->m_q;
3508  btVector3 c3 = t.m_n[3]->m_q - t.m_n[0]->m_q;
3509  btMatrix3x3 Ds(c1.getX(), c2.getX(), c3.getX(),
3510  c1.getY(), c2.getY(), c3.getY(),
3511  c1.getZ(), c2.getZ(), c3.getZ());
3512  t.m_F = Ds * t.m_Dm_inverse;
3513 
3515  s.m_F = t.m_F;
3516  s.m_J = t.m_F.determinant();
3517  btMatrix3x3 C = t.m_F.transpose() * t.m_F;
3518  s.m_trace = C[0].getX() + C[1].getY() + C[2].getZ();
3519  s.m_cofF = t.m_F.adjoint().transpose();
3520 
3521  btVector3 a = t.m_n[0]->m_q;
3522  btVector3 b = t.m_n[1]->m_q;
3523  btVector3 c = t.m_n[2]->m_q;
3524  btVector3 d = t.m_n[3]->m_q;
3525  btVector4 q1(a[0], b[0], c[0], d[0]);
3526  btVector4 q2(a[1], b[1], c[1], d[1]);
3527  btVector4 q3(a[2], b[2], c[2], d[2]);
3528  btMatrix3x3 B(Dot4(q1, t.m_P_inv[0]), Dot4(q1, t.m_P_inv[1]), Dot4(q1, t.m_P_inv[2]),
3529  Dot4(q2, t.m_P_inv[0]), Dot4(q2, t.m_P_inv[1]), Dot4(q2, t.m_P_inv[2]),
3530  Dot4(q3, t.m_P_inv[0]), Dot4(q3, t.m_P_inv[1]), Dot4(q3, t.m_P_inv[2]));
3531  q.setRotation(btVector3(0, 0, 1), 0);
3532  B.extractRotation(q, 0.01); // precision of the rotation is not very important for visual correctness.
3533  btMatrix3x3 Q(q);
3534  s.m_corotation = Q;
3535  }
3536 }
3537 
3539 {
3541  for (int i = 0; i < m_tetras.size(); ++i)
3542  {
3544  }
3545 }
3546 //
3548 {
3549  m_bodies[0].activate();
3550  m_bodies[1].activate();
3551 }
3552 
3553 //
3554 void btSoftBody::LJoint::Prepare(btScalar dt, int iterations)
3555 {
3556  static const btScalar maxdrift = 4;
3557  Joint::Prepare(dt, iterations);
3558  m_rpos[0] = m_bodies[0].xform() * m_refs[0];
3559  m_rpos[1] = m_bodies[1].xform() * m_refs[1];
3560  m_drift = Clamp(m_rpos[0] - m_rpos[1], maxdrift) * m_erp / dt;
3561  m_rpos[0] -= m_bodies[0].xform().getOrigin();
3562  m_rpos[1] -= m_bodies[1].xform().getOrigin();
3563  m_massmatrix = ImpulseMatrix(m_bodies[0].invMass(), m_bodies[0].invWorldInertia(), m_rpos[0],
3564  m_bodies[1].invMass(), m_bodies[1].invWorldInertia(), m_rpos[1]);
3565  if (m_split > 0)
3566  {
3567  m_sdrift = m_massmatrix * (m_drift * m_split);
3568  m_drift *= 1 - m_split;
3569  }
3570  m_drift /= (btScalar)iterations;
3571 }
3572 
3573 //
3575 {
3576  const btVector3 va = m_bodies[0].velocity(m_rpos[0]);
3577  const btVector3 vb = m_bodies[1].velocity(m_rpos[1]);
3578  const btVector3 vr = va - vb;
3579  btSoftBody::Impulse impulse;
3580  impulse.m_asVelocity = 1;
3581  impulse.m_velocity = m_massmatrix * (m_drift + vr * m_cfm) * sor;
3582  m_bodies[0].applyImpulse(-impulse, m_rpos[0]);
3583  m_bodies[1].applyImpulse(impulse, m_rpos[1]);
3584 }
3585 
3586 //
3588 {
3589  if (m_split > 0)
3590  {
3591  m_bodies[0].applyDImpulse(-m_sdrift, m_rpos[0]);
3592  m_bodies[1].applyDImpulse(m_sdrift, m_rpos[1]);
3593  }
3594 }
3595 
3596 //
3597 void btSoftBody::AJoint::Prepare(btScalar dt, int iterations)
3598 {
3599  static const btScalar maxdrift = SIMD_PI / 16;
3600  m_icontrol->Prepare(this);
3601  Joint::Prepare(dt, iterations);
3602  m_axis[0] = m_bodies[0].xform().getBasis() * m_refs[0];
3603  m_axis[1] = m_bodies[1].xform().getBasis() * m_refs[1];
3604  m_drift = NormalizeAny(btCross(m_axis[1], m_axis[0]));
3605  m_drift *= btMin(maxdrift, btAcos(Clamp<btScalar>(btDot(m_axis[0], m_axis[1]), -1, +1)));
3606  m_drift *= m_erp / dt;
3607  m_massmatrix = AngularImpulseMatrix(m_bodies[0].invWorldInertia(), m_bodies[1].invWorldInertia());
3608  if (m_split > 0)
3609  {
3610  m_sdrift = m_massmatrix * (m_drift * m_split);
3611  m_drift *= 1 - m_split;
3612  }
3613  m_drift /= (btScalar)iterations;
3614 }
3615 
3616 //
3618 {
3619  const btVector3 va = m_bodies[0].angularVelocity();
3620  const btVector3 vb = m_bodies[1].angularVelocity();
3621  const btVector3 vr = va - vb;
3622  const btScalar sp = btDot(vr, m_axis[0]);
3623  const btVector3 vc = vr - m_axis[0] * m_icontrol->Speed(this, sp);
3624  btSoftBody::Impulse impulse;
3625  impulse.m_asVelocity = 1;
3626  impulse.m_velocity = m_massmatrix * (m_drift + vc * m_cfm) * sor;
3627  m_bodies[0].applyAImpulse(-impulse);
3628  m_bodies[1].applyAImpulse(impulse);
3629 }
3630 
3631 //
3633 {
3634  if (m_split > 0)
3635  {
3636  m_bodies[0].applyDAImpulse(-m_sdrift);
3637  m_bodies[1].applyDAImpulse(m_sdrift);
3638  }
3639 }
3640 
3641 //
3642 void btSoftBody::CJoint::Prepare(btScalar dt, int iterations)
3643 {
3644  Joint::Prepare(dt, iterations);
3645  const bool dodrift = (m_life == 0);
3646  m_delete = (++m_life) > m_maxlife;
3647  if (dodrift)
3648  {
3649  m_drift = m_drift * m_erp / dt;
3650  if (m_split > 0)
3651  {
3652  m_sdrift = m_massmatrix * (m_drift * m_split);
3653  m_drift *= 1 - m_split;
3654  }
3655  m_drift /= (btScalar)iterations;
3656  }
3657  else
3658  {
3659  m_drift = m_sdrift = btVector3(0, 0, 0);
3660  }
3661 }
3662 
3663 //
3665 {
3666  const btVector3 va = m_bodies[0].velocity(m_rpos[0]);
3667  const btVector3 vb = m_bodies[1].velocity(m_rpos[1]);
3668  const btVector3 vrel = va - vb;
3669  const btScalar rvac = btDot(vrel, m_normal);
3670  btSoftBody::Impulse impulse;
3671  impulse.m_asVelocity = 1;
3672  impulse.m_velocity = m_drift;
3673  if (rvac < 0)
3674  {
3675  const btVector3 iv = m_normal * rvac;
3676  const btVector3 fv = vrel - iv;
3677  impulse.m_velocity += iv + fv * m_friction;
3678  }
3679  impulse.m_velocity = m_massmatrix * impulse.m_velocity * sor;
3680 
3681  if (m_bodies[0].m_soft == m_bodies[1].m_soft)
3682  {
3683  if ((impulse.m_velocity.getX() == impulse.m_velocity.getX()) && (impulse.m_velocity.getY() == impulse.m_velocity.getY()) &&
3684  (impulse.m_velocity.getZ() == impulse.m_velocity.getZ()))
3685  {
3686  if (impulse.m_asVelocity)
3687  {
3688  if (impulse.m_velocity.length() < m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
3689  {
3690  }
3691  else
3692  {
3693  m_bodies[0].applyImpulse(-impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[0]);
3694  m_bodies[1].applyImpulse(impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[1]);
3695  }
3696  }
3697  }
3698  }
3699  else
3700  {
3701  m_bodies[0].applyImpulse(-impulse, m_rpos[0]);
3702  m_bodies[1].applyImpulse(impulse, m_rpos[1]);
3703  }
3704 }
3705 
3706 //
3708 {
3709  if (m_split > 0)
3710  {
3711  m_bodies[0].applyDImpulse(-m_sdrift, m_rpos[0]);
3712  m_bodies[1].applyDImpulse(m_sdrift, m_rpos[1]);
3713  }
3714 }
3715 
3716 //
3718 {
3719  BT_PROFILE("SoftBody applyForces");
3720  // const btScalar dt = m_sst.sdt;
3721  const btScalar kLF = m_cfg.kLF;
3722  const btScalar kDG = m_cfg.kDG;
3723  const btScalar kPR = m_cfg.kPR;
3724  const btScalar kVC = m_cfg.kVC;
3725  const bool as_lift = kLF > 0;
3726  const bool as_drag = kDG > 0;
3727  const bool as_pressure = kPR != 0;
3728  const bool as_volume = kVC > 0;
3729  const bool as_aero = as_lift ||
3730  as_drag;
3731  //const bool as_vaero = as_aero &&
3732  // (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
3733  //const bool as_faero = as_aero &&
3734  // (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
3735  const bool use_medium = as_aero;
3736  const bool use_volume = as_pressure ||
3737  as_volume;
3738  btScalar volume = 0;
3739  btScalar ivolumetp = 0;
3740  btScalar dvolumetv = 0;
3741  btSoftBody::sMedium medium;
3742  if (use_volume)
3743  {
3744  volume = getVolume();
3745  ivolumetp = 1 / btFabs(volume) * kPR;
3746  dvolumetv = (m_pose.m_volume - volume) * kVC;
3747  }
3748  /* Per vertex forces */
3749  int i, ni;
3750 
3751  for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3752  {
3753  btSoftBody::Node& n = m_nodes[i];
3754  if (n.m_im > 0)
3755  {
3756  if (use_medium)
3757  {
3758  /* Aerodynamics */
3760  }
3761  /* Pressure */
3762  if (as_pressure)
3763  {
3764  n.m_f += n.m_n * (n.m_area * ivolumetp);
3765  }
3766  /* Volume */
3767  if (as_volume)
3768  {
3769  n.m_f += n.m_n * (n.m_area * dvolumetv);
3770  }
3771  }
3772  }
3773 
3774  /* Per face forces */
3775  for (i = 0, ni = m_faces.size(); i < ni; ++i)
3776  {
3777  // btSoftBody::Face& f=m_faces[i];
3778 
3779  /* Aerodynamics */
3781  }
3782 }
3783 
3784 //
3786 {
3787  m_cfg.m_maxStress = maxStress;
3788 }
3789 
3790 //
3792 {
3793  if (m_z.size() > 0)
3794  {
3795  for (int i = 0; i < m_renderNodes.size(); ++i)
3796  {
3797  const Node* p0 = m_renderNodesParents[i][0];
3798  const Node* p1 = m_renderNodesParents[i][1];
3799  const Node* p2 = m_renderNodesParents[i][2];
3800  btVector3 normal = btCross(p1->m_x - p0->m_x, p2->m_x - p0->m_x);
3801  btVector3 unit_normal = normal.normalized();
3802  Node& n = m_renderNodes[i];
3803  n.m_x.setZero();
3804  for (int j = 0; j < 3; ++j)
3805  {
3807  }
3808  n.m_x += m_z[i] * unit_normal;
3809  }
3810  }
3811  else
3812  {
3813  for (int i = 0; i < m_renderNodes.size(); ++i)
3814  {
3815  Node& n = m_renderNodes[i];
3816  n.m_x.setZero();
3817  for (int j = 0; j < 4; ++j)
3818  {
3819  if (m_renderNodesParents[i].size())
3820  {
3822  }
3823  }
3824  }
3825  }
3826 }
3827 
3829 {
3830  for (int i = 0; i <= N; ++i)
3831  {
3832  for (int j = 0; i + j <= N; ++j)
3833  {
3835  }
3836  }
3837 }
3838 
3839 //
3841 {
3842  BT_PROFILE("PSolve_Anchors");
3843  const btScalar kAHR = psb->m_cfg.kAHR * kst;
3844  const btScalar dt = psb->m_sst.sdt;
3845  for (int i = 0, ni = psb->m_anchors.size(); i < ni; ++i)
3846  {
3847  const Anchor& a = psb->m_anchors[i];
3848  const btTransform& t = a.m_body->getWorldTransform();
3849  Node& n = *a.m_node;
3850  const btVector3 wa = t * a.m_local;
3851  const btVector3 va = a.m_body->getVelocityInLocalPoint(a.m_c1) * dt;
3852  const btVector3 vb = n.m_x - n.m_q;
3853  const btVector3 vr = (va - vb) + (wa - n.m_x) * kAHR;
3854  const btVector3 impulse = a.m_c0 * vr * a.m_influence;
3855  n.m_x += impulse * a.m_c2;
3856  a.m_body->applyImpulse(-impulse, a.m_c1);
3857  }
3858 }
3859 
3860 //
3862 {
3863  BT_PROFILE("PSolve_RContacts");
3864  const btScalar dt = psb->m_sst.sdt;
3865  const btScalar mrg = psb->getCollisionShape()->getMargin();
3866  btMultiBodyJacobianData jacobianData;
3867  for (int i = 0, ni = psb->m_rcontacts.size(); i < ni; ++i)
3868  {
3869  const RContact& c = psb->m_rcontacts[i];
3870  const sCti& cti = c.m_cti;
3871  if (cti.m_colObj->hasContactResponse())
3872  {
3873  btVector3 va(0, 0, 0);
3874  btRigidBody* rigidCol = 0;
3875  btMultiBodyLinkCollider* multibodyLinkCol = 0;
3876  btScalar* deltaV;
3877 
3878  if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
3879  {
3880  rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
3881  va = rigidCol ? rigidCol->getVelocityInLocalPoint(c.m_c1) * dt : btVector3(0, 0, 0);
3882  }
3883  else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
3884  {
3886  if (multibodyLinkCol)
3887  {
3888  const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
3889  jacobianData.m_jacobians.resize(ndof);
3890  jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
3891  btScalar* jac = &jacobianData.m_jacobians[0];
3892 
3893  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);
3894  deltaV = &jacobianData.m_deltaVelocitiesUnitImpulse[0];
3895  multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], deltaV, jacobianData.scratch_r, jacobianData.scratch_v);
3896 
3897  btScalar vel = 0.0;
3898  for (int j = 0; j < ndof; ++j)
3899  {
3900  vel += multibodyLinkCol->m_multiBody->getVelocityVector()[j] * jac[j];
3901  }
3902  va = cti.m_normal * vel * dt;
3903  }
3904  }
3905 
3906  const btVector3 vb = c.m_node->m_x - c.m_node->m_q;
3907  const btVector3 vr = vb - va;
3908  const btScalar dn = btDot(vr, cti.m_normal);
3909  if (dn <= SIMD_EPSILON)
3910  {
3911  const btScalar dp = btMin((btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg);
3912  const btVector3 fv = vr - (cti.m_normal * dn);
3913  // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
3914  const btVector3 impulse = c.m_c0 * ((vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst);
3915  c.m_node->m_x -= impulse * c.m_c2;
3916 
3917  if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
3918  {
3919  if (rigidCol)
3920  rigidCol->applyImpulse(impulse, c.m_c1);
3921  }
3922  else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
3923  {
3924  if (multibodyLinkCol)
3925  {
3926  double multiplier = 0.5;
3927  multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof(deltaV, -impulse.length() * multiplier);
3928  }
3929  }
3930  }
3931  }
3932  }
3933 }
3934 
3935 //
3937 {
3938  BT_PROFILE("PSolve_SContacts");
3939 
3940  for (int i = 0, ni = psb->m_scontacts.size(); i < ni; ++i)
3941  {
3942  const SContact& c = psb->m_scontacts[i];
3943  const btVector3& nr = c.m_normal;
3944  Node& n = *c.m_node;
3945  Face& f = *c.m_face;
3946  const btVector3 p = BaryEval(f.m_n[0]->m_x,
3947  f.m_n[1]->m_x,
3948  f.m_n[2]->m_x,
3949  c.m_weights);
3950  const btVector3 q = BaryEval(f.m_n[0]->m_q,
3951  f.m_n[1]->m_q,
3952  f.m_n[2]->m_q,
3953  c.m_weights);
3954  const btVector3 vr = (n.m_x - n.m_q) - (p - q);
3955  btVector3 corr(0, 0, 0);
3956  btScalar dot = btDot(vr, nr);
3957  if (dot < 0)
3958  {
3959  const btScalar j = c.m_margin - (btDot(nr, n.m_x) - btDot(nr, p));
3960  corr += c.m_normal * j;
3961  }
3962  corr -= ProjectOnPlane(vr, nr) * c.m_friction;
3963  n.m_x += corr * c.m_cfm[0];
3964  f.m_n[0]->m_x -= corr * (c.m_cfm[1] * c.m_weights.x());
3965  f.m_n[1]->m_x -= corr * (c.m_cfm[1] * c.m_weights.y());
3966  f.m_n[2]->m_x -= corr * (c.m_cfm[1] * c.m_weights.z());
3967  }
3968 }
3969 
3970 //
3972 {
3973  BT_PROFILE("PSolve_Links");
3974  for (int i = 0, ni = psb->m_links.size(); i < ni; ++i)
3975  {
3976  Link& l = psb->m_links[i];
3977  if (l.m_c0 > 0)
3978  {
3979  Node& a = *l.m_n[0];
3980  Node& b = *l.m_n[1];
3981  const btVector3 del = b.m_x - a.m_x;
3982  const btScalar len = del.length2();
3983  if (l.m_c1 + len > SIMD_EPSILON)
3984  {
3985  const btScalar k = ((l.m_c1 - len) / (l.m_c0 * (l.m_c1 + len))) * kst;
3986  a.m_x -= del * (k * a.m_im);
3987  b.m_x += del * (k * b.m_im);
3988  }
3989  }
3990  }
3991 }
3992 
3993 //
3995 {
3996  BT_PROFILE("VSolve_Links");
3997  for (int i = 0, ni = psb->m_links.size(); i < ni; ++i)
3998  {
3999  Link& l = psb->m_links[i];
4000  Node** n = l.m_n;
4001  const btScalar j = -btDot(l.m_c3, n[0]->m_v - n[1]->m_v) * l.m_c2 * kst;
4002  n[0]->m_v += l.m_c3 * (j * n[0]->m_im);
4003  n[1]->m_v -= l.m_c3 * (j * n[1]->m_im);
4004  }
4005 }
4006 
4007 //
4009 {
4010  switch (solver)
4011  {
4012  case ePSolver::Anchors:
4013  return (&btSoftBody::PSolve_Anchors);
4014  case ePSolver::Linear:
4015  return (&btSoftBody::PSolve_Links);
4016  case ePSolver::RContacts:
4017  return (&btSoftBody::PSolve_RContacts);
4018  case ePSolver::SContacts:
4019  return (&btSoftBody::PSolve_SContacts);
4020  default:
4021  {
4022  }
4023  }
4024  return (0);
4025 }
4026 
4027 //
4029 {
4030  switch (solver)
4031  {
4032  case eVSolver::Linear:
4033  return (&btSoftBody::VSolve_Links);
4034  default:
4035  {
4036  }
4037  }
4038  return (0);
4039 }
4040 
4042 {
4044 }
4045 
4047 {
4048  return m_useSelfCollision;
4049 }
4050 
4051 //
4053 {
4055  {
4056  case fCollision::SDF_RS:
4057  {
4060  btTransform wtr = pcoWrap->getWorldTransform();
4061 
4062  const btTransform ctr = pcoWrap->getWorldTransform();
4063  const btScalar timemargin = (wtr.getOrigin() - ctr.getOrigin()).length();
4064  const btScalar basemargin = getCollisionShape()->getMargin();
4065  btVector3 mins;
4066  btVector3 maxs;
4068  volume;
4069  pcoWrap->getCollisionShape()->getAabb(pcoWrap->getWorldTransform(),
4070  mins,
4071  maxs);
4072  volume = btDbvtVolume::FromMM(mins, maxs);
4073  volume.Expand(btVector3(basemargin, basemargin, basemargin));
4074  docollide.psb = this;
4075  docollide.m_colObj1Wrap = pcoWrap;
4076  docollide.m_rigidBody = prb1;
4077 
4078  docollide.dynmargin = basemargin + timemargin;
4079  docollide.stamargin = basemargin;
4080  m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollide);
4081  }
4082  break;
4083  case fCollision::CL_RS:
4084  {
4086  collider.ProcessColObj(this, pcoWrap);
4087  }
4088  break;
4089  case fCollision::SDF_RD:
4090  {
4092  if (pcoWrap->getCollisionObject()->isActive() || this->isActive())
4093  {
4094  const btTransform wtr = pcoWrap->getWorldTransform();
4095  const btScalar timemargin = 0;
4096  const btScalar basemargin = getCollisionShape()->getMargin();
4097  btVector3 mins;
4098  btVector3 maxs;
4100  volume;
4101  pcoWrap->getCollisionShape()->getAabb(wtr,
4102  mins,
4103  maxs);
4104  volume = btDbvtVolume::FromMM(mins, maxs);
4105  volume.Expand(btVector3(basemargin, basemargin, basemargin));
4107  {
4108  btSoftColliders::CollideSDF_RD docollideNode;
4109  docollideNode.psb = this;
4110  docollideNode.m_colObj1Wrap = pcoWrap;
4111  docollideNode.m_rigidBody = prb1;
4112  docollideNode.dynmargin = basemargin + timemargin;
4113  docollideNode.stamargin = basemargin;
4114  m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollideNode);
4115  }
4116 
4117  if (((pcoWrap->getCollisionObject()->getInternalType() == CO_RIGID_BODY) && (m_cfg.collisions & fCollision::SDF_RDF)) || ((pcoWrap->getCollisionObject()->getInternalType() == CO_FEATHERSTONE_LINK) && (m_cfg.collisions & fCollision::SDF_MDF)))
4118  {
4119  btSoftColliders::CollideSDF_RDF docollideFace;
4120  docollideFace.psb = this;
4121  docollideFace.m_colObj1Wrap = pcoWrap;
4122  docollideFace.m_rigidBody = prb1;
4123  docollideFace.dynmargin = basemargin + timemargin;
4124  docollideFace.stamargin = basemargin;
4125  m_fdbvt.collideTV(m_fdbvt.m_root, volume, docollideFace);
4126  }
4127  }
4128  }
4129  break;
4130  }
4131 }
4132 
4133 //
4135 {
4136  BT_PROFILE("Deformable Collision");
4137  const int cf = m_cfg.collisions & psb->m_cfg.collisions;
4138  switch (cf & fCollision::SVSmask)
4139  {
4140  case fCollision::CL_SS:
4141  {
4142  //support self-collision if CL_SELF flag set
4143  if (this != psb || psb->m_cfg.collisions & fCollision::CL_SELF)
4144  {
4146  docollide.ProcessSoftSoft(this, psb);
4147  }
4148  }
4149  break;
4150  case fCollision::VF_SS:
4151  {
4152  //only self-collision for Cluster, not Vertex-Face yet
4153  if (this != psb)
4154  {
4156  /* common */
4157  docollide.mrg = getCollisionShape()->getMargin() +
4158  psb->getCollisionShape()->getMargin();
4159  /* psb0 nodes vs psb1 faces */
4160  docollide.psb[0] = this;
4161  docollide.psb[1] = psb;
4162  docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4163  docollide.psb[1]->m_fdbvt.m_root,
4164  docollide);
4165  /* psb1 nodes vs psb0 faces */
4166  docollide.psb[0] = psb;
4167  docollide.psb[1] = this;
4168  docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4169  docollide.psb[1]->m_fdbvt.m_root,
4170  docollide);
4171  }
4172  }
4173  break;
4174  case fCollision::VF_DD:
4175  {
4176  if (!psb->m_softSoftCollision)
4177  return;
4178  if (psb->isActive() || this->isActive())
4179  {
4180  if (this != psb)
4181  {
4183  /* common */
4184  docollide.mrg = getCollisionShape()->getMargin() +
4185  psb->getCollisionShape()->getMargin();
4186  /* psb0 nodes vs psb1 faces */
4187  if (psb->m_tetras.size() > 0)
4188  docollide.useFaceNormal = true;
4189  else
4190  docollide.useFaceNormal = false;
4191  docollide.psb[0] = this;
4192  docollide.psb[1] = psb;
4193  docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4194  docollide.psb[1]->m_fdbvt.m_root,
4195  docollide);
4196 
4197  /* psb1 nodes vs psb0 faces */
4198  if (this->m_tetras.size() > 0)
4199  docollide.useFaceNormal = true;
4200  else
4201  docollide.useFaceNormal = false;
4202  docollide.psb[0] = psb;
4203  docollide.psb[1] = this;
4204  docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4205  docollide.psb[1]->m_fdbvt.m_root,
4206  docollide);
4207  }
4208  else
4209  {
4210  if (psb->useSelfCollision())
4211  {
4213  docollide.mrg = 2 * getCollisionShape()->getMargin();
4214  docollide.psb[0] = this;
4215  docollide.psb[1] = psb;
4216  if (this->m_tetras.size() > 0)
4217  docollide.useFaceNormal = true;
4218  else
4219  docollide.useFaceNormal = false;
4220  /* psb0 faces vs psb0 faces */
4222  this->m_fdbvt.selfCollideT(m_fdbvnt, docollide);
4223  }
4224  }
4225  }
4226  }
4227  break;
4228  default:
4229  {
4230  }
4231  }
4232 }
4233 
4235 {
4236  if (psb->isActive() || this->isActive())
4237  {
4238  if (this != psb)
4239  {
4240  btSoftColliders::CollideCCD docollide;
4241  /* common */
4242  docollide.mrg = SAFE_EPSILON; // for rounding error instead of actual margin
4243  docollide.dt = psb->m_sst.sdt;
4244  /* psb0 nodes vs psb1 faces */
4245  if (psb->m_tetras.size() > 0)
4246  docollide.useFaceNormal = true;
4247  else
4248  docollide.useFaceNormal = false;
4249  docollide.psb[0] = this;
4250  docollide.psb[1] = psb;
4251  docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4252  docollide.psb[1]->m_fdbvt.m_root,
4253  docollide);
4254  /* psb1 nodes vs psb0 faces */
4255  if (this->m_tetras.size() > 0)
4256  docollide.useFaceNormal = true;
4257  else
4258  docollide.useFaceNormal = false;
4259  docollide.psb[0] = psb;
4260  docollide.psb[1] = this;
4261  docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4262  docollide.psb[1]->m_fdbvt.m_root,
4263  docollide);
4264  }
4265  else
4266  {
4267  if (psb->useSelfCollision())
4268  {
4269  btSoftColliders::CollideCCD docollide;
4270  docollide.mrg = SAFE_EPSILON;
4271  docollide.psb[0] = this;
4272  docollide.psb[1] = psb;
4273  docollide.dt = psb->m_sst.sdt;
4274  if (this->m_tetras.size() > 0)
4275  docollide.useFaceNormal = true;
4276  else
4277  docollide.useFaceNormal = false;
4278  /* psb0 faces vs psb0 faces */
4279  calculateNormalCone(this->m_fdbvnt); // should compute this outside of this scope
4280  this->m_fdbvt.selfCollideT(m_fdbvnt, docollide);
4281  }
4282  }
4283  }
4284 }
4285 
4287 {
4288  m_windVelocity = velocity;
4289 }
4290 
4292 {
4293  return m_windVelocity;
4294 }
4295 
4297 {
4298  int sz = sizeof(btSoftBodyData);
4299  return sz;
4300 }
4301 
4303 const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
4304 {
4305  btSoftBodyData* sbd = (btSoftBodyData*)dataBuffer;
4306 
4307  btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
4308 
4309  btHashMap<btHashPtr, int> m_nodeIndexMap;
4310 
4311  sbd->m_numMaterials = m_materials.size();
4312  sbd->m_materials = sbd->m_numMaterials ? (SoftBodyMaterialData**)serializer->getUniquePointer((void*)&m_materials) : 0;
4313 
4314  if (sbd->m_materials)
4315  {
4316  int sz = sizeof(SoftBodyMaterialData*);
4317  int numElem = sbd->m_numMaterials;
4318  btChunk* chunk = serializer->allocate(sz, numElem);
4319  //SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
4320  SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
4321  for (int i = 0; i < numElem; i++, memPtr++)
4322  {
4324  *memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
4325  if (!serializer->findPointer(mat))
4326  {
4327  //serialize it here
4328  btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData), 1);
4330  memPtr->m_flags = mat->m_flags;
4331  memPtr->m_angularStiffness = mat->m_kAST;
4332  memPtr->m_linearStiffness = mat->m_kLST;
4333  memPtr->m_volumeStiffness = mat->m_kVST;
4334  serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_SBMATERIAL_CODE, mat);
4335  }
4336  }
4337  serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_ARRAY_CODE, (void*)&m_materials);
4338  }
4339 
4340  sbd->m_numNodes = m_nodes.size();
4341  sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes) : 0;
4342  if (sbd->m_nodes)
4343  {
4344  int sz = sizeof(SoftBodyNodeData);
4345  int numElem = sbd->m_numNodes;
4346  btChunk* chunk = serializer->allocate(sz, numElem);
4347  SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
4348  for (int i = 0; i < numElem; i++, memPtr++)
4349  {
4350  m_nodes[i].m_f.serializeFloat(memPtr->m_accumulatedForce);
4351  memPtr->m_area = m_nodes[i].m_area;
4352  memPtr->m_attach = m_nodes[i].m_battach;
4353  memPtr->m_inverseMass = m_nodes[i].m_im;
4354  memPtr->m_material = m_nodes[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_nodes[i].m_material) : 0;
4355  m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
4356  m_nodes[i].m_x.serializeFloat(memPtr->m_position);
4357  m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
4358  m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
4359  m_nodeIndexMap.insert(&m_nodes[i], i);
4360  }
4361  serializer->finalizeChunk(chunk, "SoftBodyNodeData", BT_SBNODE_CODE, (void*)&m_nodes);
4362  }
4363 
4364  sbd->m_numLinks = m_links.size();
4365  sbd->m_links = sbd->m_numLinks ? (SoftBodyLinkData*)serializer->getUniquePointer((void*)&m_links[0]) : 0;
4366  if (sbd->m_links)
4367  {
4368  int sz = sizeof(SoftBodyLinkData);
4369  int numElem = sbd->m_numLinks;
4370  btChunk* chunk = serializer->allocate(sz, numElem);
4371  SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
4372  for (int i = 0; i < numElem; i++, memPtr++)
4373  {
4374  memPtr->m_bbending = m_links[i].m_bbending;
4375  memPtr->m_material = m_links[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_links[i].m_material) : 0;
4376  memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0] : -1;
4377  memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0] : -1;
4378  btAssert(memPtr->m_nodeIndices[0] < m_nodes.size());
4379  btAssert(memPtr->m_nodeIndices[1] < m_nodes.size());
4380  memPtr->m_restLength = m_links[i].m_rl;
4381  }
4382  serializer->finalizeChunk(chunk, "SoftBodyLinkData", BT_ARRAY_CODE, (void*)&m_links[0]);
4383  }
4384 
4385  sbd->m_numFaces = m_faces.size();
4386  sbd->m_faces = sbd->m_numFaces ? (SoftBodyFaceData*)serializer->getUniquePointer((void*)&m_faces[0]) : 0;
4387  if (sbd->m_faces)
4388  {
4389  int sz = sizeof(SoftBodyFaceData);
4390  int numElem = sbd->m_numFaces;
4391  btChunk* chunk = serializer->allocate(sz, numElem);
4392  SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
4393  for (int i = 0; i < numElem; i++, memPtr++)
4394  {
4395  memPtr->m_material = m_faces[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_faces[i].m_material) : 0;
4396  m_faces[i].m_normal.serializeFloat(memPtr->m_normal);
4397  for (int j = 0; j < 3; j++)
4398  {
4399  memPtr->m_nodeIndices[j] = m_faces[i].m_n[j] ? m_faces[i].m_n[j] - &m_nodes[0] : -1;
4400  }
4401  memPtr->m_restArea = m_faces[i].m_ra;
4402  }
4403  serializer->finalizeChunk(chunk, "SoftBodyFaceData", BT_ARRAY_CODE, (void*)&m_faces[0]);
4404  }
4405 
4406  sbd->m_numTetrahedra = m_tetras.size();
4407  sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*)serializer->getUniquePointer((void*)&m_tetras[0]) : 0;
4408  if (sbd->m_tetrahedra)
4409  {
4410  int sz = sizeof(SoftBodyTetraData);
4411  int numElem = sbd->m_numTetrahedra;
4412  btChunk* chunk = serializer->allocate(sz, numElem);
4413  SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
4414  for (int i = 0; i < numElem; i++, memPtr++)
4415  {
4416  for (int j = 0; j < 4; j++)
4417  {
4418  m_tetras[i].m_c0[j].serializeFloat(memPtr->m_c0[j]);
4419  memPtr->m_nodeIndices[j] = m_tetras[i].m_n[j] ? m_tetras[i].m_n[j] - &m_nodes[0] : -1;
4420  }
4421  memPtr->m_c1 = m_tetras[i].m_c1;
4422  memPtr->m_c2 = m_tetras[i].m_c2;
4423  memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_tetras[i].m_material) : 0;
4424  memPtr->m_restVolume = m_tetras[i].m_rv;
4425  }
4426  serializer->finalizeChunk(chunk, "SoftBodyTetraData", BT_ARRAY_CODE, (void*)&m_tetras[0]);
4427  }
4428 
4429  sbd->m_numAnchors = m_anchors.size();
4430  sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*)serializer->getUniquePointer((void*)&m_anchors[0]) : 0;
4431  if (sbd->m_anchors)
4432  {
4433  int sz = sizeof(SoftRigidAnchorData);
4434  int numElem = sbd->m_numAnchors;
4435  btChunk* chunk = serializer->allocate(sz, numElem);
4437  for (int i = 0; i < numElem; i++, memPtr++)
4438  {
4439  m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
4440  m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
4441  memPtr->m_c2 = m_anchors[i].m_c2;
4442  m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
4443  memPtr->m_nodeIndex = m_anchors[i].m_node ? m_anchors[i].m_node - &m_nodes[0] : -1;
4444 
4445  memPtr->m_rigidBody = m_anchors[i].m_body ? (btRigidBodyData*)serializer->getUniquePointer((void*)m_anchors[i].m_body) : 0;
4446  btAssert(memPtr->m_nodeIndex < m_nodes.size());
4447  }
4448  serializer->finalizeChunk(chunk, "SoftRigidAnchorData", BT_ARRAY_CODE, (void*)&m_anchors[0]);
4449  }
4450 
4451  sbd->m_config.m_dynamicFriction = m_cfg.kDF;
4452  sbd->m_config.m_baumgarte = m_cfg.kVCF;
4453  sbd->m_config.m_pressure = m_cfg.kPR;
4454  sbd->m_config.m_aeroModel = this->m_cfg.aeromodel;
4455  sbd->m_config.m_lift = m_cfg.kLF;
4456  sbd->m_config.m_drag = m_cfg.kDG;
4457  sbd->m_config.m_positionIterations = m_cfg.piterations;
4458  sbd->m_config.m_driftIterations = m_cfg.diterations;
4459  sbd->m_config.m_clusterIterations = m_cfg.citerations;
4460  sbd->m_config.m_velocityIterations = m_cfg.viterations;
4461  sbd->m_config.m_maxVolume = m_cfg.maxvolume;
4462  sbd->m_config.m_damping = m_cfg.kDP;
4463  sbd->m_config.m_poseMatch = m_cfg.kMT;
4464  sbd->m_config.m_collisionFlags = m_cfg.collisions;
4465  sbd->m_config.m_volume = m_cfg.kVC;
4466  sbd->m_config.m_rigidContactHardness = m_cfg.kCHR;
4467  sbd->m_config.m_kineticContactHardness = m_cfg.kKHR;
4468  sbd->m_config.m_softContactHardness = m_cfg.kSHR;
4469  sbd->m_config.m_anchorHardness = m_cfg.kAHR;
4470  sbd->m_config.m_timeScale = m_cfg.timescale;
4471  sbd->m_config.m_maxVolume = m_cfg.maxvolume;
4472  sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL;
4473  sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL;
4474  sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL;
4475  sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL;
4476  sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL;
4477  sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL;
4478 
4479  //pose for shape matching
4480  {
4481  sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
4482 
4483  int sz = sizeof(SoftBodyPoseData);
4484  btChunk* chunk = serializer->allocate(sz, 1);
4485  SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
4486 
4487  m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
4488  memPtr->m_bframe = m_pose.m_bframe;
4489  memPtr->m_bvolume = m_pose.m_bvolume;
4490  m_pose.m_com.serializeFloat(memPtr->m_com);
4491 
4492  memPtr->m_numPositions = m_pose.m_pos.size();
4493  memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]) : 0;
4494  if (memPtr->m_numPositions)
4495  {
4496  int numElem = memPtr->m_numPositions;
4497  int sz = sizeof(btVector3Data);
4498  btChunk* chunk = serializer->allocate(sz, numElem);
4499  btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
4500  for (int i = 0; i < numElem; i++, memPtr++)
4501  {
4502  m_pose.m_pos[i].serializeFloat(*memPtr);
4503  }
4504  serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_pose.m_pos[0]);
4505  }
4506  memPtr->m_restVolume = m_pose.m_volume;
4507  m_pose.m_rot.serializeFloat(memPtr->m_rot);
4508  m_pose.m_scl.serializeFloat(memPtr->m_scale);
4509 
4510  memPtr->m_numWeigts = m_pose.m_wgh.size();
4511  memPtr->m_weights = memPtr->m_numWeigts ? (float*)serializer->getUniquePointer((void*)&m_pose.m_wgh[0]) : 0;
4512  if (memPtr->m_numWeigts)
4513  {
4514  int numElem = memPtr->m_numWeigts;
4515  int sz = sizeof(float);
4516  btChunk* chunk = serializer->allocate(sz, numElem);
4517  float* memPtr = (float*)chunk->m_oldPtr;
4518  for (int i = 0; i < numElem; i++, memPtr++)
4519  {
4520  *memPtr = m_pose.m_wgh[i];
4521  }
4522  serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_pose.m_wgh[0]);
4523  }
4524 
4525  serializer->finalizeChunk(chunk, "SoftBodyPoseData", BT_ARRAY_CODE, (void*)&m_pose);
4526  }
4527 
4528  //clusters for convex-cluster collision detection
4529 
4530  sbd->m_numClusters = m_clusters.size();
4531  sbd->m_clusters = sbd->m_numClusters ? (SoftBodyClusterData*)serializer->getUniquePointer((void*)m_clusters[0]) : 0;
4532  if (sbd->m_numClusters)
4533  {
4534  int numElem = sbd->m_numClusters;
4535  int sz = sizeof(SoftBodyClusterData);
4536  btChunk* chunk = serializer->allocate(sz, numElem);
4538  for (int i = 0; i < numElem; i++, memPtr++)
4539  {
4540  memPtr->m_adamping = m_clusters[i]->m_adamping;
4541  m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
4542  memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
4543  memPtr->m_collide = m_clusters[i]->m_collide;
4544  m_clusters[i]->m_com.serializeFloat(memPtr->m_com);
4545  memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor;
4546  m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]);
4547  m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]);
4548  m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform);
4549  memPtr->m_idmass = m_clusters[i]->m_idmass;
4550  memPtr->m_imass = m_clusters[i]->m_imass;
4551  m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi);
4552  memPtr->m_ldamping = m_clusters[i]->m_ldamping;
4553  m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii);
4554  m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv);
4555  memPtr->m_matching = m_clusters[i]->m_matching;
4556  memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse;
4557  memPtr->m_ndamping = m_clusters[i]->m_ndamping;
4558  memPtr->m_ldamping = m_clusters[i]->m_ldamping;
4559  memPtr->m_adamping = m_clusters[i]->m_adamping;
4560  memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor;
4561 
4562  memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size();
4563  memPtr->m_numMasses = m_clusters[i]->m_masses.size();
4564  memPtr->m_numNodes = m_clusters[i]->m_nodes.size();
4565 
4566  memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses;
4567  m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]);
4568  m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
4569  memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
4570 
4571  memPtr->m_framerefs = memPtr->m_numFrameRefs ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
4572  if (memPtr->m_framerefs)
4573  {
4574  int numElem = memPtr->m_numFrameRefs;
4575  int sz = sizeof(btVector3FloatData);
4576  btChunk* chunk = serializer->allocate(sz, numElem);
4577  btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
4578  for (int j = 0; j < numElem; j++, memPtr++)
4579  {
4580  m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
4581  }
4582  serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_framerefs[0]);
4583  }
4584 
4585  memPtr->m_masses = memPtr->m_numMasses ? (float*)serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]) : 0;
4586  if (memPtr->m_masses)
4587  {
4588  int numElem = memPtr->m_numMasses;
4589  int sz = sizeof(float);
4590  btChunk* chunk = serializer->allocate(sz, numElem);
4591  float* memPtr = (float*)chunk->m_oldPtr;
4592  for (int j = 0; j < numElem; j++, memPtr++)
4593  {
4594  *memPtr = m_clusters[i]->m_masses[j];
4595  }
4596  serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_masses[0]);
4597  }
4598 
4599  memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*)serializer->getUniquePointer((void*)&m_clusters[i]->m_nodes) : 0;
4600  if (memPtr->m_nodeIndices)
4601  {
4602  int numElem = memPtr->m_numMasses;
4603  int sz = sizeof(int);
4604  btChunk* chunk = serializer->allocate(sz, numElem);
4605  int* memPtr = (int*)chunk->m_oldPtr;
4606  for (int j = 0; j < numElem; j++, memPtr++)
4607  {
4608  int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
4609  btAssert(indexPtr);
4610  *memPtr = *indexPtr;
4611  }
4612  serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_nodes);
4613  }
4614  }
4615  serializer->finalizeChunk(chunk, "SoftBodyClusterData", BT_ARRAY_CODE, (void*)m_clusters[0]);
4616  }
4617 
4618  sbd->m_numJoints = m_joints.size();
4619  sbd->m_joints = m_joints.size() ? (btSoftBodyJointData*)serializer->getUniquePointer((void*)&m_joints[0]) : 0;
4620 
4621  if (sbd->m_joints)
4622  {
4623  int sz = sizeof(btSoftBodyJointData);
4624  int numElem = m_joints.size();
4625  btChunk* chunk = serializer->allocate(sz, numElem);
4627 
4628  for (int i = 0; i < numElem; i++, memPtr++)
4629  {
4630  memPtr->m_jointType = (int)m_joints[i]->Type();
4631  m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
4632  m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]);
4633  memPtr->m_cfm = m_joints[i]->m_cfm;
4634  memPtr->m_erp = float(m_joints[i]->m_erp);
4635  memPtr->m_split = float(m_joints[i]->m_split);
4636  memPtr->m_delete = m_joints[i]->m_delete;
4637 
4638  for (int j = 0; j < 4; j++)
4639  {
4640  memPtr->m_relPosition[0].m_floats[j] = 0.f;
4641  memPtr->m_relPosition[1].m_floats[j] = 0.f;
4642  }
4643  memPtr->m_bodyA = 0;
4644  memPtr->m_bodyB = 0;
4645  if (m_joints[i]->m_bodies[0].m_soft)
4646  {
4648  memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft);
4649  }
4650  if (m_joints[i]->m_bodies[0].m_collisionObject)
4651  {
4653  memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject);
4654  }
4655  if (m_joints[i]->m_bodies[0].m_rigid)
4656  {
4657  memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY;
4658  memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid);
4659  }
4660 
4661  if (m_joints[i]->m_bodies[1].m_soft)
4662  {
4664  memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft);
4665  }
4666  if (m_joints[i]->m_bodies[1].m_collisionObject)
4667  {
4669  memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject);
4670  }
4671  if (m_joints[i]->m_bodies[1].m_rigid)
4672  {
4673  memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY;
4674  memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
4675  }
4676  }
4677  serializer->finalizeChunk(chunk, "btSoftBodyJointData", BT_ARRAY_CODE, (void*)&m_joints[0]);
4678  }
4679 
4680  return btSoftBodyDataName;
4681 }
4682 
4684 {
4686  return;
4687 
4689  {
4690  m_deactivationTime += timeStep;
4691  }
4692  else
4693  {
4695  setActivationState(0);
4696  }
4697 }
4698 
4700 {
4701  for (int i = 0; i < m_nodes.size(); ++i)
4702  {
4703  m_nodes[i].m_v.setZero();
4704  }
4705 }
4706 
4708 {
4710  return false;
4711 
4712  //disable deactivation
4714  return false;
4715 
4717  return true;
4718 
4720  {
4721  return true;
4722  }
4723  return false;
4724 }
typedef float(TangentPoint)[2]
struct Material Material
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp
#define C
Definition: RandGen.cpp:25
#define U
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define btAlignedFree(ptr)
#define btAlignedAlloc(size, alignment)
btCollisionObject
SIMD_FORCE_INLINE btBroadphaseProxy * getBroadphaseHandle()
void activate(bool forceActivation=false) const
#define DISABLE_DEACTIVATION
btScalar m_deactivationTime
void setActivationState(int newState) const
@ CO_FEATHERSTONE_LINK
@ CO_RIGID_BODY
@ CO_SOFT_BODY
btScalar m_friction
SIMD_FORCE_INLINE int getActivationState() const
#define WANTS_DEACTIVATION
int m_collisionFlags
SIMD_FORCE_INLINE bool isActive() const
#define ISLAND_SLEEPING
SIMD_FORCE_INLINE const btCollisionShape * getCollisionShape() const
int m_internalType
btCollisionShape * m_collisionShape
btCollisionShape
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
struct btDbvtNode * m_node
btConvexShape()
not supported on IBM SDK, until we fix the alignment of btVector3
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
unsigned int U
Definition: btGjkEpa3.h:78
void singularValueDecomposition(const btMatrix2x2 &A, GivensRotation &U, const btMatrix2x2 &Sigma, GivensRotation &V, const btScalar tol=64 *std::numeric_limits< btScalar >::epsilon())
2x2 SVD (singular value decomposition) A=USV'
btMatrix3x3 inverse() const
Return the inverse of the matrix.
Definition: btTransform.h:182
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:50
SIMD_FORCE_INLINE const T & btMin(const T &a, const T &b)
Definition: btMinMax.h:21
SIMD_FORCE_INLINE const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:27
btScalar m_erp
btScalar m_cfm
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
Data buffer MUST be 16 byte aligned.
SIMD_FORCE_INLINE btScalar btAngle(const btQuaternion &q1, const btQuaternion &q2)
Return the angle between two quaternions.
Definition: btQuaternion.h:902
#define BT_PROFILE(name)
Definition: btQuickprof.h:198
bool gDisableDeactivation
Definition: btRigidBody.cpp:26
btScalar gDeactivationTime
Definition: btRigidBody.cpp:25
#define btRigidBodyData
Definition: btRigidBody.h:35
SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
Definition: btScalar.h:501
#define SIMD_PI
Definition: btScalar.h:526
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
#define ATTRIBUTE_ALIGNED16(a)
Definition: btScalar.h:285
#define BT_LARGE_FLOAT
Definition: btScalar.h:316
SIMD_FORCE_INLINE btScalar btFabs(btScalar x)
Definition: btScalar.h:497
SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x)
Definition: btScalar.h:572
SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
Definition: btScalar.h:466
#define SIMD_INFINITY
Definition: btScalar.h:544
SIMD_FORCE_INLINE void btSwap(T &a, T &b)
Definition: btScalar.h:643
#define SIMD_EPSILON
Definition: btScalar.h:543
#define btAssert(x)
Definition: btScalar.h:295
#define BT_SBMATERIAL_CODE
Definition: btSerializer.h:119
#define BT_ARRAY_CODE
Definition: btSerializer.h:118
#define BT_SBNODE_CODE
Definition: btSerializer.h:120
@ BT_JOINT_RIGID_BODY
@ BT_JOINT_SOFT_BODY_CLUSTER
@ BT_JOINT_COLLISION_OBJECT
static T sum(const btAlignedObjectArray< T > &items)
static btMatrix3x3 OuterProduct(const btScalar *v1, const btScalar *v2, const btScalar *v3, const btScalar *u1, const btScalar *u2, const btScalar *u3, int ndof)
static btMatrix3x3 Mul(const btMatrix3x3 &a, btScalar b)
static btScalar ImplicitSolve(btSoftBody::ImplicitFn *fn, const btVector3 &a, const btVector3 &b, const btScalar accuracy, const int maxiterations=256)
static btDbvtVolume VolumeOf(const btSoftBody::Face &f, btScalar margin)
static T Lerp(const T &a, const T &b, btScalar t)
static btMatrix3x3 AngularImpulseMatrix(const btMatrix3x3 &iia, const btMatrix3x3 &iib)
static btScalar AreaOf(const btVector3 &x0, const btVector3 &x1, const btVector3 &x2)
static btVector3 NormalizeAny(const btVector3 &v)
static int PolarDecompose(const btMatrix3x3 &m, btMatrix3x3 &q, btMatrix3x3 &s)
static int MatchEdge(const btSoftBody::Node *a, const btSoftBody::Node *b, const btSoftBody::Node *ma, const btSoftBody::Node *mb)
static SIMD_FORCE_INLINE btVector3 generateUnitOrthogonalVector(const btVector3 &u)
static bool SameSign(const T &x, const T &y)
static void EvaluateMedium(const btSoftBodyWorldInfo *wfi, const btVector3 &x, btSoftBody::sMedium &medium)
static void ZeroInitialize(T &value)
static btVector3 ProjectOnPlane(const btVector3 &v, const btVector3 &a)
static btScalar ClusterMetric(const btVector3 &x, const btVector3 &y)
static btMatrix3x3 ImpulseMatrix(btScalar dt, btScalar ima, btScalar imb, const btMatrix3x3 &iwi, const btVector3 &r)
static void ApplyClampedForce(btSoftBody::Node &n, const btVector3 &f, btScalar dt)
static SIMD_FORCE_INLINE void findJacobian(const btMultiBodyLinkCollider *multibodyLinkCol, btMultiBodyJacobianData &jacobianData, const btVector3 &contact_point, const btVector3 &dir)
btSoftBody implementation by Nathanael Presson
static btMatrix3x3 Diagonal(btScalar x)
static void calculateNormalCone(btDbvntNode *root)
#define IDX(_x_, _y_)
#define IDX2PTR(_p_, _b_)
#define PTR2IDX(_p_, _b_)
static void getBarycentric(const btVector3 &p, btVector3 &a, btVector3 &b, btVector3 &c, btVector3 &bary)
static btDbvtNode * buildTreeBottomUp(btAlignedObjectArray< btDbvtNode * > &leafNodes, btAlignedObjectArray< btAlignedObjectArray< int > > &adj)
btSoftBody implementation by Nathanael Presson
Definition: btSoftBody.cpp:29
static btDbvntNode * copyToDbvnt(const btDbvtNode *n)
static btScalar Dot4(const btVector4 &a, const btVector4 &b)
#define NEXTRAND
static unsigned long seed
Definition: btSoftBody.h:39
#define btSoftBodyDataName
Definition: btSoftBody.h:37
#define btSoftBodyData
btSoftBody implementation by Nathanael Presson
Definition: btSoftBody.h:36
#define SAFE_EPSILON
Definition: btSoftBody.h:1194
btTransform m_worldTransform
Definition: btSolverBody.h:107
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:30
btTriangleShape()
SIMD_FORCE_INLINE btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:251
SIMD_FORCE_INLINE btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:890
btVector3
btVector3 can be used to represent 3D points and vectors. It has an un-used w component to suit 16-by...
Definition: btVector3.h:82
SIMD_FORCE_INLINE btVector3 & safeNormalize()
Definition: btVector3.h:286
#define btVector3Data
Definition: btVector3.h:27
SIMD_FORCE_INLINE btVector3 btCross(const btVector3 &v1, const btVector3 &v2)
Return the cross product of two vectors.
Definition: btVector3.h:918
SIMD_FORCE_INLINE void reserve(int _Count)
SIMD_FORCE_INLINE void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0),...
SIMD_FORCE_INLINE int capacity() const
return the pre-allocated (reserved) elements, this is at least as large as the total number of elemen...
int findLinearSearch(const T &key) const
SIMD_FORCE_INLINE int size() const
return the number of elements in the array
SIMD_FORCE_INLINE void pop_back()
void remove(const T &key)
SIMD_FORCE_INLINE void resize(int newsize, const T &fillData=T())
SIMD_FORCE_INLINE void push_back(const T &_Val)
virtual void setAabb(btBroadphaseProxy *proxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *dispatcher)=0
void * m_oldPtr
Definition: btSerializer.h:52
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:264
const Value * find(const Key &key) const
Definition: btHashMap.h:424
static btMultiBodyLinkCollider * upcast(btCollisionObject *colObj)
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
Definition: btQuaternion.h:50
void setRotation(const btVector3 &axis, const btScalar &_angle)
Set the rotation using axis angle notation.
Definition: btQuaternion.h:108
SIMD_FORCE_INLINE const btCollisionShape * getCollisionShape() const
Definition: btRigidBody.h:242
btVector3 getVelocityInLocalPoint(const btVector3 &rel_pos) const
Definition: btRigidBody.h:460
btScalar getInvMass() const
Definition: btRigidBody.h:263
static const btRigidBody * upcast(const btCollisionObject *colObj)
Definition: btRigidBody.h:189
void applyImpulse(const btVector3 &impulse, const btVector3 &rel_pos)
Definition: btRigidBody.h:335
const btMatrix3x3 & getInvInertiaTensorWorld() const
Definition: btRigidBody.h:265
virtual btChunk * allocate(size_t size, int numElements)=0
virtual void * findPointer(void *oldPtr)=0
virtual void * getUniquePointer(void *oldPtr)=0
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
static void PSolve_Links(btSoftBody *psb, btScalar kst, btScalar ti)
static void PSolve_SContacts(btSoftBody *psb, btScalar, btScalar ti)
bool checkLink(int node0, int node1) const
Definition: btSoftBody.cpp:252
bool m_bUpdateRtCst
Definition: btSoftBody.h:818
btScalar m_sleepingThreshold
Definition: btSoftBody.h:825
void transformTo(const btTransform &trs)
btVector3 getLinearVelocity()
bool checkFace(int node0, int node1, int node2) const
Definition: btSoftBody.cpp:274
void advanceDeformation()
void setGravityFactor(btScalar gravFactor)
void updateClusters()
btDbvt m_cdbvt
Definition: btSoftBody.h:822
void setPose(bool bvolume, bool bframe)
bool cutLink(int node0, int node1, btScalar position)
void appendFace(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:428
void setMass(int node, btScalar mass)
Definition: btSoftBody.cpp:919
void interpolateRenderMesh()
tJointArray m_joints
Definition: btSoftBody.h:814
btScalar m_dampingCoefficient
Definition: btSoftBody.h:824
btAlignedObjectArray< TetraScratch > m_tetraScratchesTn
Definition: btSoftBody.h:806
void integrateMotion()
void rebuildNodeTree()
bool rayFaceTest(const btVector3 &rayFrom, const btVector3 &rayTo, sRayCast &results)
void appendLinearJoint(const LJoint::Specs &specs, Cluster *body0, Body body1)
Definition: btSoftBody.cpp:636
void scale(const btVector3 &scl)
btAlignedObjectArray< bool > m_clusterConnectivity
Definition: btSoftBody.h:838
void updateFaceTree(bool use_velocity, bool margin)
Definition: btSoftBody.h:1270
void defaultCollisionHandler(const btCollisionObjectWrapper *pcoWrap)
btScalar getVolume() const
bool rayTest(const btVector3 &rayFrom, const btVector3 &rayTo, sRayCast &results)
Ray casting using rayFrom and rayTo in worldspace, (not direction!)
SolverState m_sst
Definition: btSoftBody.h:794
void addVelocity(const btVector3 &velocity)
Definition: btSoftBody.cpp:889
void predictMotion(btScalar dt)
void setSelfCollision(bool useSelfCollision)
void setLinearVelocity(const btVector3 &linVel)
btScalar m_timeacc
Definition: btSoftBody.h:816
Pose m_pose
Definition: btSoftBody.h:795
void appendTetra(int model, Material *mat)
Definition: btSoftBody.cpp:468
void setRestLengthScale(btScalar restLength)
btDbvntNode * m_fdbvnt
Definition: btSoftBody.h:821
void rotate(const btQuaternion &rot)
void applyClusters(bool drift)
void setZeroVelocity()
static void PSolve_Anchors(btSoftBody *psb, btScalar kst, btScalar ti)
btSoftBodyWorldInfo * m_worldInfo
Definition: btSoftBody.h:797
void updateArea(bool averageArea=true)
void addForce(const btVector3 &force)
Definition: btSoftBody.cpp:689
bool wantsSleeping()
void prepareClusters(int iterations)
void setCollisionQuadrature(int N)
static void clusterVImpulse(Cluster *cluster, const btVector3 &rpos, const btVector3 &impulse)
virtual const char * serialize(void *dataBuffer, class btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
static void VSolve_Links(btSoftBody *psb, btScalar kst)
tTetraArray m_tetras
Definition: btSoftBody.h:804
bool useSelfCollision()
btVector3 evaluateCom() const
void setTotalDensity(btScalar density)
Definition: btSoftBody.cpp:979
btAlignedObjectArray< const class btCollisionObject * > m_collisionDisabledObjects
Definition: btSoftBody.h:77
static void clusterDAImpulse(Cluster *cluster, const btVector3 &impulse)
void appendNode(const btVector3 &x, btScalar m)
Definition: btSoftBody.cpp:368
void staticSolve(int iterations)
void setVolumeMass(btScalar mass)
Definition: btSoftBody.cpp:985
btScalar m_restLengthScale
Definition: btSoftBody.h:842
bool checkDeformableContact(const btCollisionObjectWrapper *colObjWrap, const btVector3 &x, btScalar margin, btSoftBody::sCti &cti, bool predict=false) const
void cleanupClusters()
Config m_cfg
Definition: btSoftBody.h:793
Node * m_n[2]
Definition: btSoftBody.h:284
void updateDeactivation(btScalar timeStep)
btAlignedObjectArray< TetraScratch > m_tetraScratches
Definition: btSoftBody.h:805
const btVector3 & getWindVelocity()
void addAeroForceToFace(const btVector3 &windVelocity, int faceIndex)
Definition: btSoftBody.cpp:793
btAlignedObjectArray< btVector4 > m_renderNodesInterpolationWeights
Definition: btSoftBody.h:832
void appendAngularJoint(const AJoint::Specs &specs, Cluster *body0, Body body1)
Definition: btSoftBody.cpp:662
tFaceArray m_faces
Definition: btSoftBody.h:802
void setAngularVelocity(const btVector3 &angVel)
void setVolumeDensity(btScalar density)
static void clusterDCImpulse(Cluster *cluster, const btVector3 &impulse)
void transform(const btTransform &trs)
bool m_softSoftCollision
Definition: btSoftBody.h:836
static void clusterVAImpulse(Cluster *cluster, const btVector3 &impulse)
btScalar getMass(int node) const
Definition: btSoftBody.cpp:926
tMaterialArray m_materials
Definition: btSoftBody.h:815
void setMaxStress(btScalar maxStress)
void dampClusters()
btSoftBody(btSoftBodyWorldInfo *worldInfo, int node_count, const btVector3 *x, const btScalar *m)
Definition: btSoftBody.cpp:130
void updateDeformation()
btAlignedObjectArray< btScalar > m_z
Definition: btSoftBody.h:834
void addAeroForceToNode(const btVector3 &windVelocity, int nodeIndex)
Definition: btSoftBody.cpp:704
static btVector3 clusterCom(const Cluster *cluster)
tRContactArray m_rcontacts
Definition: btSoftBody.h:809
void appendAnchor(int node, btRigidBody *body, bool disableCollisionBetweenLinkedBodies=false, btScalar influence=1)
Definition: btSoftBody.cpp:500
btVector3 m_bounds[2]
Definition: btSoftBody.h:817
btScalar m_maxSpeedSquared
Definition: btSoftBody.h:826
void releaseCluster(int index)
btScalar m_repulsionStiffness
Definition: btSoftBody.h:828
void setVelocity(const btVector3 &velocity)
Definition: btSoftBody.cpp:895
tClusterArray m_clusters
Definition: btSoftBody.h:823
void solveConstraints()
int generateClusters(int k, int maxiterations=8192)
void geometricCollisionHandler(btSoftBody *psb)
void releaseClusters()
void refine(ImplicitFn *ifn, btScalar accurary, bool cut)
void setSolver(eSolverPresets::_ preset)
static T BaryEval(const T &a, const T &b, const T &c, const btVector3 &coord)
Definition: btSoftBody.h:1279
Material * appendMaterial()
Definition: btSoftBody.cpp:298
void removeAnchor(int node)
Definition: btSoftBody.cpp:562
btAlignedObjectArray< DeformableNodeRigidAnchor > m_deformableAnchors
Definition: btSoftBody.h:808
btScalar m_gravityFactor
Definition: btSoftBody.h:829
static void solveClusters(const btAlignedObjectArray< btSoftBody * > &bodies)
void appendNote(const char *text, const btVector3 &o, const btVector4 &c=btVector4(1, 0, 0, 0), Node *n0=0, Node *n1=0, Node *n2=0, Node *n3=0)
Definition: btSoftBody.cpp:310
bool checkDeformableFaceContact(const btCollisionObjectWrapper *colObjWrap, Face &f, btVector3 &contact_point, btVector3 &bary, btScalar margin, btSoftBody::sCti &cti, bool predict=false) const
virtual int calculateSerializeBufferSize() const
static void PSolve_RContacts(btSoftBody *psb, btScalar kst, btScalar ti)
static void clusterImpulse(Cluster *cluster, const btVector3 &rpos, const Impulse &impulse)
btAlignedObjectArray< btAlignedObjectArray< const btSoftBody::Node * > > m_renderNodesParents
Definition: btSoftBody.h:833
void pointersToIndices()
tNoteArray m_notes
Definition: btSoftBody.h:798
void updateNormals()
static void clusterDImpulse(Cluster *cluster, const btVector3 &rpos, const btVector3 &impulse)
btDbvt m_fdbvt
Definition: btSoftBody.h:820
tLinkArray m_links
Definition: btSoftBody.h:801
void applyForces()
static btVector3 clusterVelocity(const Cluster *cluster, const btVector3 &rpos)
btTransform getRigidTransform()
tSContactArray m_scontacts
Definition: btSoftBody.h:813
bool m_useSelfCollision
Definition: btSoftBody.h:835
void * m_tag
Definition: btSoftBody.h:796
void updatePose()
void(* psolver_t)(btSoftBody *, btScalar, btScalar)
Definition: btSoftBody.h:773
void initializeClusters()
tAnchorArray m_anchors
Definition: btSoftBody.h:807
btScalar getRestLengthScale()
void randomizeConstraints()
btVector3 m_windVelocity
Definition: btSoftBody.h:840
btScalar getTotalMass() const
Definition: btSoftBody.cpp:932
tNodeArray m_nodes
Definition: btSoftBody.h:799
void appendLink(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:388
void setSpringStiffness(btScalar k)
void initializeDmInverse()
void updateConstants()
void setTotalMass(btScalar mass, bool fromfaces=false)
Definition: btSoftBody.cpp:943
virtual ~btSoftBody()
Definition: btSoftBody.cpp:236
void appendDeformableAnchor(int node, btRigidBody *body)
Definition: btSoftBody.cpp:527
void updateLinkConstants()
void(* vsolver_t)(btSoftBody *, btScalar)
Definition: btSoftBody.h:774
tNodeArray m_renderNodes
Definition: btSoftBody.h:800
void initDefaults()
Definition: btSoftBody.cpp:170
btAlignedObjectArray< btVector3 > m_quads
Definition: btSoftBody.h:827
static psolver_t getSolver(ePSolver::_ solver)
bool checkContact(const btCollisionObjectWrapper *colObjWrap, const btVector3 &x, btScalar margin, btSoftBody::sCti &cti) const
void indicesToPointers(const int *map=0)
static void solveCommonConstraints(btSoftBody **bodies, int count, int iterations)
void updateBounds()
void setWindVelocity(const btVector3 &velocity)
int generateBendingConstraints(int distance, Material *mat=0)
btAlignedObjectArray< btVector3 > m_X
Definition: btSoftBody.h:830
void translate(const btVector3 &trs)
btVector3 getCenterOfMass() const
Definition: btSoftBody.h:1011
void initializeFaceTree()
void resetLinkRestLengths()
int clusterCount() const
btDbvt m_ndbvt
Definition: btSoftBody.h:819
static void clusterAImpulse(Cluster *cluster, const Impulse &impulse)
OperationNode * node
int len
Definition: draw_manager.c:108
#define rot(x, k)
IconTextureDrawCall normal
#define N
#define B
#define R
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
T length(const vec_base< T, Size > &a)
T distance(const T &a, const T &b)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken density("density", pxr::TfToken::Immortal)
SocketIndexByIdentifierMap * map
const btScalar eps
Definition: poly34.cpp:11
btVector3FloatData m_av
btMatrix3x3FloatData m_invwi
btVector3FloatData m_vimpulses[2]
btVector3FloatData * m_framerefs
btVector3FloatData m_dimpulses[2]
btMatrix3x3FloatData m_locii
btVector3FloatData m_lv
btTransformFloatData m_framexform
float m_selfCollisionImpulseFactor
btVector3FloatData m_com
btVector3FloatData m_normal
SoftBodyMaterialData * m_material
SoftBodyMaterialData * m_material
btVector3FloatData m_accumulatedForce
btVector3FloatData m_normal
btVector3FloatData m_previousPosition
btVector3FloatData m_velocity
btVector3FloatData m_position
SoftBodyMaterialData * m_material
btMatrix3x3FloatData m_rot
btVector3FloatData m_com
btVector3FloatData * m_positions
btMatrix3x3FloatData m_aqq
btMatrix3x3FloatData m_scale
btVector3FloatData m_c0[4]
SoftBodyMaterialData * m_material
btMatrix3x3FloatData m_c0
btVector3FloatData m_localFrame
btVector3FloatData m_c1
btRigidBodyData * m_rigidBody
SIMD_FORCE_INLINE const btCollisionShape * getCollisionShape() const
SIMD_FORCE_INLINE const btTransform & getWorldTransform() const
const btTransform * m_preTransform
SIMD_FORCE_INLINE const btCollisionObject * getCollisionObject() const
void * data
Definition: btDbvt.h:202
btVector3 normal
Definition: btDbvt.h:197
btDbvntNode * childs[2]
Definition: btDbvt.h:201
btScalar angle
Definition: btDbvt.h:198
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:199
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
Definition: btDbvt.h:479
static btDbvtAabbMm FromCR(const btVector3 &c, btScalar r)
Definition: btDbvt.h:473
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:185
btDbvtNode * childs[2]
Definition: btDbvt.h:187
void * data
Definition: btDbvt.h:188
btDbvtNode * insert(const btDbvtVolume &box, void *data)
Definition: btDbvt.cpp:535
void optimizeIncremental(int passes)
Definition: btDbvt.cpp:514
void update(btDbvtNode *leaf, int lookahead=-1)
Definition: btDbvt.cpp:544
DBVT_PREFIX void collideTV(const btDbvtNode *root, const btDbvtVolume &volume, DBVT_IPOLICY) const
Definition: btDbvt.h:1148
bool empty() const
Definition: btDbvt.h:314
static DBVT_PREFIX void rayTest(const btDbvtNode *root, const btVector3 &rayFrom, const btVector3 &rayTo, DBVT_IPOLICY)
Definition: btDbvt.h:1276
void clear()
Definition: btDbvt.cpp:477
btDbvtNode * m_root
Definition: btDbvt.h:302
void remove(btDbvtNode *leaf)
Definition: btDbvt.cpp:611
DBVT_PREFIX void collideTT(const btDbvtNode *root0, const btDbvtNode *root1, DBVT_IPOLICY)
Definition: btDbvt.h:822
DBVT_PREFIX void selfCollideT(const btDbvntNode *root, DBVT_IPOLICY)
Definition: btDbvt.h:887
btVector3 witnesses[2]
Definition: btGjkEpa2.h:42
static btScalar SignedDistance(const btVector3 &position, btScalar margin, const btConvexShape *shape, const btTransform &wtrs, sResults &results)
Definition: btGjkEpa2.cpp:1021
btAlignedObjectArray< btScalar > m_deltaVelocitiesUnitImpulse
btAlignedObjectArray< btScalar > m_jacobians
btAlignedObjectArray< btScalar > scratch_r
btAlignedObjectArray< btMatrix3x3 > scratch_m
btAlignedObjectArray< btVector3 > scratch_v
btVector3FloatData m_refs[2]
btVector3FloatData m_relPosition[2]
btScalar air_density
Definition: btSoftBody.h:49
btDispatcher * m_dispatcher
Definition: btSoftBody.h:55
btSparseSdf< 3 > m_sparsesdf
Definition: btSoftBody.h:57
btVector3 m_gravity
Definition: btSoftBody.h:56
btScalar m_maxDisplacement
Definition: btSoftBody.h:52
btBroadphaseInterface * m_broadphase
Definition: btSoftBody.h:54
void Prepare(btScalar dt, int iterations)
void Solve(btScalar dt, btScalar sor)
IControl * m_icontrol
Definition: btSoftBody.h:676
void Terminate(btScalar dt)
const btTransform & xform() const
Definition: btSoftBody.h:534
void Terminate(btScalar dt)
void Prepare(btScalar dt, int iterations)
void Solve(btScalar dt, btScalar sor)
btVector3 m_dimpulses[2]
Definition: btSoftBody.h:458
btMatrix3x3 m_invwi
Definition: btSoftBody.h:455
btAlignedObjectArray< Node * > m_nodes
Definition: btSoftBody.h:449
btVector3 m_vimpulses[2]
Definition: btSoftBody.h:457
tScalarArray m_masses
Definition: btSoftBody.h:448
btScalar maxvolume
Definition: btSoftBody.h:717
tPSolverArray m_psequence
Definition: btSoftBody.h:725
tPSolverArray m_dsequence
Definition: btSoftBody.h:726
btScalar kSK_SPLT_CL
Definition: btSoftBody.h:715
btScalar kSS_SPLT_CL
Definition: btSoftBody.h:716
btScalar m_maxStress
Definition: btSoftBody.h:728
eAeroModel::_ aeromodel
Definition: btSoftBody.h:698
btScalar kSR_SPLT_CL
Definition: btSoftBody.h:714
tVSolverArray m_vsequence
Definition: btSoftBody.h:724
btScalar timescale
Definition: btSoftBody.h:718
btVector4 m_pcontact
Definition: btSoftBody.h:300
btVector3 m_normal
Definition: btSoftBody.h:297
Node * m_n[3]
Definition: btSoftBody.h:296
btDbvtNode * m_leaf
Definition: btSoftBody.h:299
Material * m_material
Definition: btSoftBody.h:258
virtual btScalar Eval(const btVector3 &x)=0
btVector3 m_velocity
Definition: btSoftBody.h:480
btScalar m_split
Definition: btSoftBody.h:630
btVector3 m_refs[2]
Definition: btSoftBody.h:627
virtual void Prepare(btScalar dt, int iterations)
void Solve(btScalar dt, btScalar sor)
void Prepare(btScalar dt, int iterations)
void Terminate(btScalar dt)
btScalar m_area
Definition: btSoftBody.h:270
btVector3 m_x
Definition: btSoftBody.h:263
btVector3 m_vn
Definition: btSoftBody.h:266
btVector3 m_v
Definition: btSoftBody.h:265
btVector3 m_q
Definition: btSoftBody.h:264
btDbvtNode * m_leaf
Definition: btSoftBody.h:271
btVector3 m_n
Definition: btSoftBody.h:268
btVector3 m_f
Definition: btSoftBody.h:267
btScalar m_coords[4]
Definition: btSoftBody.h:430
btVector3 m_offset
Definition: btSoftBody.h:427
Node * m_nodes[4]
Definition: btSoftBody.h:429
const char * m_text
Definition: btSoftBody.h:426
btMatrix3x3 m_scl
Definition: btSoftBody.h:442
btScalar m_volume
Definition: btSoftBody.h:437
btVector3 m_com
Definition: btSoftBody.h:440
tVector3Array m_pos
Definition: btSoftBody.h:438
btMatrix3x3 m_aqq
Definition: btSoftBody.h:443
btMatrix3x3 m_rot
Definition: btSoftBody.h:441
tScalarArray m_wgh
Definition: btSoftBody.h:439
RayFromToCaster takes a ray from, ray to (instead of direction!)
Definition: btSoftBody.h:750
RayFromToCaster(const btVector3 &rayFrom, const btVector3 &rayTo, btScalar mxt)
void Process(const btDbvtNode *leaf)
static btScalar rayFromToTriangle(const btVector3 &rayFrom, const btVector3 &rayTo, const btVector3 &rayNormalizedDirection, const btVector3 &a, const btVector3 &b, const btVector3 &c, btScalar maxt=SIMD_INFINITY)
btVector3 m_rayNormalizedDirection
Definition: btSoftBody.h:753
btMatrix3x3 m_corotation
Definition: btSoftBody.h:326
@ V_TwoSided
Vertex normals are oriented toward velocity.
Definition: btSoftBody.h:92
@ V_OneSided
Vertex normals are flipped to match velocity and lift and drag forces are applied.
Definition: btSoftBody.h:94
@ V_TwoSidedLiftDrag
Vertex normals are flipped to match velocity.
Definition: btSoftBody.h:93
@ F_OneSided
Face normals are flipped to match velocity and lift and drag forces are applied.
Definition: btSoftBody.h:97
@ F_TwoSided
Vertex normals are taken as it is.
Definition: btSoftBody.h:95
@ F_TwoSidedLiftDrag
Face normals are flipped to match velocity.
Definition: btSoftBody.h:96
@ RContacts
Anchor solver.
Definition: btSoftBody.h:119
@ SContacts
Rigid contacts solver.
Definition: btSoftBody.h:120
@ Anchors
Linear solver.
Definition: btSoftBody.h:118
@ SDF_RDN
GJK based Multibody vs. deformable face.
Definition: btSoftBody.h:177
@ VF_SS
Rigid versus soft mask.
Definition: btSoftBody.h:169
@ Default
SDF based Rigid vs. deformable node.
Definition: btSoftBody.h:179
@ VF_DD
Cluster soft body self collision.
Definition: btSoftBody.h:172
@ CL_SS
Vertex vs face soft vs soft handling.
Definition: btSoftBody.h:170
@ CL_SELF
Cluster vs cluster soft vs soft handling.
Definition: btSoftBody.h:171
@ SVSmask
rigid vs deformable
Definition: btSoftBody.h:168
@ SDF_RS
Rigid versus soft mask.
Definition: btSoftBody.h:164
@ SDF_RD
Cluster vs convex rigid vs soft.
Definition: btSoftBody.h:166
@ SDF_RDF
Rigid versus deformable face mask.
Definition: btSoftBody.h:175
@ SDF_MDF
GJK based Rigid vs. deformable face.
Definition: btSoftBody.h:176
@ CL_RS
SDF based rigid vs soft.
Definition: btSoftBody.h:165
@ Default
Enable debug draw.
Definition: btSoftBody.h:191
const btCollisionObject * m_colObj
Definition: btSoftBody.h:226
btScalar m_offset
Definition: btSoftBody.h:228
btVector3 m_normal
Definition: btSoftBody.h:227
btVector3 m_velocity
Definition: btSoftBody.h:235
eFeature::_ feature
soft body
Definition: btSoftBody.h:204
btScalar fraction
feature index
Definition: btSoftBody.h:206
int index
feature type
Definition: btSoftBody.h:205
btSoftBody * body
Definition: btSoftBody.h:203
void ProcessColObj(btSoftBody *ps, const btCollisionObjectWrapper *colObWrap)
void ProcessSoftSoft(btSoftBody *psa, btSoftBody *psb)
const btCollisionObjectWrapper * m_colObj1Wrap
const btCollisionObjectWrapper * m_colObj1Wrap
const btCollisionObjectWrapper * m_colObj1Wrap
btScalar Evaluate(const btVector3 &x, const btCollisionShape *shape, btVector3 &normal, btScalar margin)
Definition: btSparseSDF.h:196
CCL_NAMESPACE_BEGIN struct Window V