Blender  V3.3
btDeformableContactProjection.cpp
Go to the documentation of this file.
1 /*
2  Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
3 
4  Bullet Continuous Collision Detection and Physics Library
5  Copyright (c) 2019 Google Inc. http://bulletphysics.org
6  This software is provided 'as-is', without any express or implied warranty.
7  In no event will the authors be held liable for any damages arising from the use of this software.
8  Permission is granted to anyone to use this software for any purpose,
9  including commercial applications, and to alter it and redistribute it freely,
10  subject to the following restrictions:
11  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13  3. This notice may not be removed or altered from any source distribution.
14  */
15 
18 #include <algorithm>
19 #include <cmath>
21 {
22  btScalar residualSquare = 0;
23  for (int i = 0; i < numDeformableBodies; ++i)
24  {
25  for (int j = 0; j < m_softBodies.size(); ++j)
26  {
28  if (psb != deformableBodies[i])
29  {
30  continue;
31  }
32  for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
33  {
35  btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
36  residualSquare = btMax(residualSquare, localResidualSquare);
37  }
38  for (int k = 0; k < m_nodeAnchorConstraints[j].size(); ++k)
39  {
41  btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
42  residualSquare = btMax(residualSquare, localResidualSquare);
43  }
44  for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
45  {
47  btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
48  residualSquare = btMax(residualSquare, localResidualSquare);
49  }
50  for (int k = 0; k < m_deformableConstraints[j].size(); ++k)
51  {
53  btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
54  residualSquare = btMax(residualSquare, localResidualSquare);
55  }
56  }
57  }
58  return residualSquare;
59 }
60 
62 {
63  btScalar residualSquare = 0;
64  for (int i = 0; i < numDeformableBodies; ++i)
65  {
66  for (int j = 0; j < m_softBodies.size(); ++j)
67  {
69  if (psb != deformableBodies[i])
70  {
71  continue;
72  }
73  for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
74  {
76  btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
77  residualSquare = btMax(residualSquare, localResidualSquare);
78  }
79  for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
80  {
82  btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
83  residualSquare = btMax(residualSquare, localResidualSquare);
84  }
85  }
86  }
87  return residualSquare;
88 }
89 
91 {
92  BT_PROFILE("setConstraints");
93  for (int i = 0; i < m_softBodies.size(); ++i)
94  {
95  btSoftBody* psb = m_softBodies[i];
96  if (!psb->isActive())
97  {
98  continue;
99  }
100 
101  // set Dirichlet constraint
102  for (int j = 0; j < psb->m_nodes.size(); ++j)
103  {
104  if (psb->m_nodes[j].m_im == 0)
105  {
106  btDeformableStaticConstraint static_constraint(&psb->m_nodes[j], infoGlobal);
107  m_staticConstraints[i].push_back(static_constraint);
108  }
109  }
110 
111  // set up deformable anchors
112  for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
113  {
115  // skip fixed points
116  if (anchor.m_node->m_im == 0)
117  {
118  continue;
119  }
120  anchor.m_c1 = anchor.m_cti.m_colObj->getWorldTransform().getBasis() * anchor.m_local;
121  btDeformableNodeAnchorConstraint constraint(anchor, infoGlobal);
122  m_nodeAnchorConstraints[i].push_back(constraint);
123  }
124 
125  // set Deformable Node vs. Rigid constraint
126  for (int j = 0; j < psb->m_nodeRigidContacts.size(); ++j)
127  {
129  // skip fixed points
130  if (contact.m_node->m_im == 0)
131  {
132  continue;
133  }
135  m_nodeRigidConstraints[i].push_back(constraint);
136  }
137 
138  // set Deformable Face vs. Rigid constraint
139  for (int j = 0; j < psb->m_faceRigidContacts.size(); ++j)
140  {
142  // skip fixed faces
143  if (contact.m_c2 == 0)
144  {
145  continue;
146  }
148  m_faceRigidConstraints[i].push_back(constraint);
149  }
150  }
151 }
152 
154 {
155 #ifndef USE_MGS
156  const int dim = 3;
157  for (int index = 0; index < m_projectionsDict.size(); ++index)
158  {
160  size_t i = m_projectionsDict.getKeyAtIndex(index).getUid1();
161  if (projectionDirs.size() >= dim)
162  {
163  // static node
164  x[i].setZero();
165  continue;
166  }
167  else if (projectionDirs.size() == 2)
168  {
169  btVector3 dir0 = projectionDirs[0];
170  btVector3 dir1 = projectionDirs[1];
171  btVector3 free_dir = btCross(dir0, dir1);
172  if (free_dir.safeNorm() < SIMD_EPSILON)
173  {
174  x[i] -= x[i].dot(dir0) * dir0;
175  }
176  else
177  {
178  free_dir.normalize();
179  x[i] = x[i].dot(free_dir) * free_dir;
180  }
181  }
182  else
183  {
184  btAssert(projectionDirs.size() == 1);
185  btVector3 dir0 = projectionDirs[0];
186  x[i] -= x[i].dot(dir0) * dir0;
187  }
188  }
189 #else
190  btReducedVector p(x.size());
191  for (int i = 0; i < m_projections.size(); ++i)
192  {
193  p += (m_projections[i].dot(x) * m_projections[i]);
194  }
195  for (int i = 0; i < p.m_indices.size(); ++i)
196  {
197  x[p.m_indices[i]] -= p.m_vecs[i];
198  }
199 #endif
200 }
201 
203 {
204 #ifndef USE_MGS
205  BT_PROFILE("btDeformableContactProjection::setProjection");
207  units.push_back(btVector3(1, 0, 0));
208  units.push_back(btVector3(0, 1, 0));
209  units.push_back(btVector3(0, 0, 1));
210  for (int i = 0; i < m_softBodies.size(); ++i)
211  {
212  btSoftBody* psb = m_softBodies[i];
213  if (!psb->isActive())
214  {
215  continue;
216  }
217  for (int j = 0; j < m_staticConstraints[i].size(); ++j)
218  {
219  int index = m_staticConstraints[i][j].m_node->index;
220  m_staticConstraints[i][j].m_node->m_constrained = true;
221  if (m_projectionsDict.find(index) == NULL)
222  {
223  m_projectionsDict.insert(index, units);
224  }
225  else
226  {
227  btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
228  for (int k = 0; k < 3; ++k)
229  {
230  projections.push_back(units[k]);
231  }
232  }
233  }
234  for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
235  {
236  int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
237  m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_constrained = true;
238  if (m_projectionsDict.find(index) == NULL)
239  {
240  m_projectionsDict.insert(index, units);
241  }
242  else
243  {
244  btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
245  for (int k = 0; k < 3; ++k)
246  {
247  projections.push_back(units[k]);
248  }
249  }
250  }
251  for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
252  {
253  int index = m_nodeRigidConstraints[i][j].m_node->index;
254  m_nodeRigidConstraints[i][j].m_node->m_constrained = true;
255  if (m_nodeRigidConstraints[i][j].m_binding)
256  {
257  if (m_nodeRigidConstraints[i][j].m_static)
258  {
259  if (m_projectionsDict.find(index) == NULL)
260  {
261  m_projectionsDict.insert(index, units);
262  }
263  else
264  {
265  btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
266  for (int k = 0; k < 3; ++k)
267  {
268  projections.push_back(units[k]);
269  }
270  }
271  }
272  else
273  {
274  if (m_projectionsDict.find(index) == NULL)
275  {
277  projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
278  m_projectionsDict.insert(index, projections);
279  }
280  else
281  {
282  btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
283  projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
284  }
285  }
286  }
287  }
288  for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
289  {
290  const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
291  if (m_faceRigidConstraints[i][j].m_binding)
292  {
293  for (int k = 0; k < 3; ++k)
294  {
295  face->m_n[k]->m_constrained = true;
296  }
297  }
298  for (int k = 0; k < 3; ++k)
299  {
300  btSoftBody::Node* node = face->m_n[k];
301  int index = node->index;
302  if (m_faceRigidConstraints[i][j].m_static)
303  {
304  if (m_projectionsDict.find(index) == NULL)
305  {
306  m_projectionsDict.insert(index, units);
307  }
308  else
309  {
310  btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
311  for (int l = 0; l < 3; ++l)
312  {
313  projections.push_back(units[l]);
314  }
315  }
316  }
317  else
318  {
319  if (m_projectionsDict.find(index) == NULL)
320  {
322  projections.push_back(m_faceRigidConstraints[i][j].m_normal);
323  m_projectionsDict.insert(index, projections);
324  }
325  else
326  {
327  btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
328  projections.push_back(m_faceRigidConstraints[i][j].m_normal);
329  }
330  }
331  }
332  }
333  }
334 #else
335  int dof = 0;
336  for (int i = 0; i < m_softBodies.size(); ++i)
337  {
338  dof += m_softBodies[i]->m_nodes.size();
339  }
340  for (int i = 0; i < m_softBodies.size(); ++i)
341  {
342  btSoftBody* psb = m_softBodies[i];
343  if (!psb->isActive())
344  {
345  continue;
346  }
347  for (int j = 0; j < m_staticConstraints[i].size(); ++j)
348  {
349  int index = m_staticConstraints[i][j].m_node->index;
350  m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
352  btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
353  indices.push_back(index);
354  vecs1.push_back(btVector3(1, 0, 0));
355  vecs2.push_back(btVector3(0, 1, 0));
356  vecs3.push_back(btVector3(0, 0, 1));
357  m_projections.push_back(btReducedVector(dof, indices, vecs1));
358  m_projections.push_back(btReducedVector(dof, indices, vecs2));
359  m_projections.push_back(btReducedVector(dof, indices, vecs3));
360  }
361 
362  for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
363  {
364  int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
365  m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
367  btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
368  indices.push_back(index);
369  vecs1.push_back(btVector3(1, 0, 0));
370  vecs2.push_back(btVector3(0, 1, 0));
371  vecs3.push_back(btVector3(0, 0, 1));
372  m_projections.push_back(btReducedVector(dof, indices, vecs1));
373  m_projections.push_back(btReducedVector(dof, indices, vecs2));
374  m_projections.push_back(btReducedVector(dof, indices, vecs3));
375  }
376  for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
377  {
378  int index = m_nodeRigidConstraints[i][j].m_node->index;
379  m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
381  indices.push_back(index);
382  btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
383  if (m_nodeRigidConstraints[i][j].m_static)
384  {
385  vecs1.push_back(btVector3(1, 0, 0));
386  vecs2.push_back(btVector3(0, 1, 0));
387  vecs3.push_back(btVector3(0, 0, 1));
388  m_projections.push_back(btReducedVector(dof, indices, vecs1));
389  m_projections.push_back(btReducedVector(dof, indices, vecs2));
390  m_projections.push_back(btReducedVector(dof, indices, vecs3));
391  }
392  else
393  {
394  vecs1.push_back(m_nodeRigidConstraints[i][j].m_normal);
395  m_projections.push_back(btReducedVector(dof, indices, vecs1));
396  }
397  }
398  for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
399  {
400  const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
401  btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
402  btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
403  for (int k = 0; k < 3; ++k)
404  {
405  face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
406  }
407  if (m_faceRigidConstraints[i][j].m_static)
408  {
409  for (int l = 0; l < 3; ++l)
410  {
411  btReducedVector rv(dof);
412  for (int k = 0; k < 3; ++k)
413  {
414  rv.m_indices.push_back(face->m_n[k]->index);
415  btVector3 v(0, 0, 0);
416  v[l] = bary[k];
417  rv.m_vecs.push_back(v);
418  rv.sort();
419  }
420  m_projections.push_back(rv);
421  }
422  }
423  else
424  {
425  btReducedVector rv(dof);
426  for (int k = 0; k < 3; ++k)
427  {
428  rv.m_indices.push_back(face->m_n[k]->index);
429  rv.m_vecs.push_back(bary[k] * m_faceRigidConstraints[i][j].m_normal);
430  rv.sort();
431  }
432  m_projections.push_back(rv);
433  }
434  }
435  }
436  btModifiedGramSchmidt<btReducedVector> mgs(m_projections);
437  mgs.solve();
438  m_projections = mgs.m_out;
439 #endif
440 }
441 
443 {
444  for (int i = 0; i < m_lagrangeMultipliers.size(); ++i)
445  {
446  btVector3 d(0, 0, 0);
448  for (int j = 0; j < lm.m_num_constraints; ++j)
449  {
450  for (int k = 0; k < lm.m_num_nodes; ++k)
451  {
452  d[j] += lm.m_weights[k] * x[lm.m_indices[k]].dot(lm.m_dirs[j]);
453  }
454  }
455  // printf("d = %f, %f, %f\n", d[0], d[1], d[2]);
456  // printf("val = %f, %f, %f\n", lm.m_vals[0], lm.m_vals[1], lm.m_vals[2]);
457  }
458 }
459 
461 {
462  for (int i = 0; i < m_softBodies.size(); ++i)
463  {
464  btSoftBody* psb = m_softBodies[i];
465  if (!psb->isActive())
466  {
467  continue;
468  }
469  for (int j = 0; j < m_staticConstraints[i].size(); ++j)
470  {
471  int index = m_staticConstraints[i][j].m_node->index;
472  m_staticConstraints[i][j].m_node->m_constrained = true;
474  lm.m_num_nodes = 1;
475  lm.m_indices[0] = index;
476  lm.m_weights[0] = 1.0;
477  lm.m_num_constraints = 3;
478  lm.m_dirs[0] = btVector3(1, 0, 0);
479  lm.m_dirs[1] = btVector3(0, 1, 0);
480  lm.m_dirs[2] = btVector3(0, 0, 1);
482  }
483  for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
484  {
485  int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
486  m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_constrained = true;
488  lm.m_num_nodes = 1;
489  lm.m_indices[0] = index;
490  lm.m_weights[0] = 1.0;
491  lm.m_num_constraints = 3;
492  lm.m_dirs[0] = btVector3(1, 0, 0);
493  lm.m_dirs[1] = btVector3(0, 1, 0);
494  lm.m_dirs[2] = btVector3(0, 0, 1);
496  }
497 
498  for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
499  {
500  if (!m_nodeRigidConstraints[i][j].m_binding)
501  {
502  continue;
503  }
504  int index = m_nodeRigidConstraints[i][j].m_node->index;
505  m_nodeRigidConstraints[i][j].m_node->m_constrained = true;
507  lm.m_num_nodes = 1;
508  lm.m_indices[0] = index;
509  lm.m_weights[0] = 1.0;
510  if (m_nodeRigidConstraints[i][j].m_static)
511  {
512  lm.m_num_constraints = 3;
513  lm.m_dirs[0] = btVector3(1, 0, 0);
514  lm.m_dirs[1] = btVector3(0, 1, 0);
515  lm.m_dirs[2] = btVector3(0, 0, 1);
516  }
517  else
518  {
519  lm.m_num_constraints = 1;
520  lm.m_dirs[0] = m_nodeRigidConstraints[i][j].m_normal;
521  }
523  }
524 
525  for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
526  {
527  if (!m_faceRigidConstraints[i][j].m_binding)
528  {
529  continue;
530  }
531  btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
532 
533  btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
535  lm.m_num_nodes = 3;
536 
537  for (int k = 0; k < 3; ++k)
538  {
539  face->m_n[k]->m_constrained = true;
540  lm.m_indices[k] = face->m_n[k]->index;
541  lm.m_weights[k] = bary[k];
542  }
543  if (m_faceRigidConstraints[i][j].m_static)
544  {
545  face->m_pcontact[3] = 1;
546  lm.m_num_constraints = 3;
547  lm.m_dirs[0] = btVector3(1, 0, 0);
548  lm.m_dirs[1] = btVector3(0, 1, 0);
549  lm.m_dirs[2] = btVector3(0, 0, 1);
550  }
551  else
552  {
553  face->m_pcontact[3] = 0;
554  lm.m_num_constraints = 1;
555  lm.m_dirs[0] = m_faceRigidConstraints[i][j].m_normal;
556  }
558  }
559  }
560 }
561 
562 //
564 {
565  for (int i = 0; i < m_softBodies.size(); ++i)
566  {
567  for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
568  {
570  const btSoftBody::Node* node = constraint.m_node;
571  if (node->m_im != 0)
572  {
573  int index = node->index;
574  f[index] += constraint.getDv(node) * (1. / node->m_im);
575  }
576  }
577  for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
578  {
580  const btSoftBody::Face* face = constraint.getContact()->m_face;
581  for (int k = 0; k < 3; ++k)
582  {
583  const btSoftBody::Node* node = face->m_n[k];
584  if (node->m_im != 0)
585  {
586  int index = node->index;
587  f[index] += constraint.getDv(node) * (1. / node->m_im);
588  }
589  }
590  }
591  for (int j = 0; j < m_deformableConstraints[i].size(); ++j)
592  {
594  const btSoftBody::Face* face = constraint.getContact()->m_face;
595  const btSoftBody::Node* node = constraint.getContact()->m_node;
596  if (node->m_im != 0)
597  {
598  int index = node->index;
599  f[index] += constraint.getDv(node) * (1. / node->m_im);
600  }
601  for (int k = 0; k < 3; ++k)
602  {
603  const btSoftBody::Node* node = face->m_n[k];
604  if (node->m_im != 0)
605  {
606  int index = node->index;
607  f[index] += constraint.getDv(node) * (1. / node->m_im);
608  }
609  }
610  }
611  }
612 }
613 
615 {
616  int N = m_softBodies.size();
617  if (nodeUpdated)
618  {
624  }
625  for (int i = 0; i < N; ++i)
626  {
632  }
633 #ifndef USE_MGS
635 #else
636  m_projections.clear();
637 #endif
639 }
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
btCollisionObject
SIMD_FORCE_INLINE const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:27
#define BT_PROFILE(name)
Definition: btQuickprof.h:198
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
#define SIMD_INFINITY
Definition: btScalar.h:544
#define SIMD_EPSILON
Definition: btScalar.h:543
#define btAssert(x)
Definition: btScalar.h:295
btSequentialImpulseConstraintSolverMt int btPersistentManifold int btTypedConstraint int const btContactSolverInfo & infoGlobal
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 btCross(const btVector3 &v1, const btVector3 &v2)
Return the cross product of two vectors.
Definition: btVector3.h:918
SIMD_FORCE_INLINE void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0),...
SIMD_FORCE_INLINE int size() const
return the number of elements in the array
SIMD_FORCE_INLINE void resize(int newsize, const T &fillData=T())
SIMD_FORCE_INLINE void push_back(const T &_Val)
virtual btScalar update(btCollisionObject **deformableBodies, int numDeformableBodies, const btContactSolverInfo &infoGlobal)
btAlignedObjectArray< LagrangeMultiplier > m_lagrangeMultipliers
virtual void setConstraints(const btContactSolverInfo &infoGlobal)
virtual void reinitialize(bool nodeUpdated)
btAlignedObjectArray< btSoftBody * > & m_softBodies
btAlignedObjectArray< btAlignedObjectArray< btDeformableFaceNodeContactConstraint > > m_deformableConstraints
btScalar solveSplitImpulse(btCollisionObject **deformableBodies, int numDeformableBodies, const btContactSolverInfo &infoGlobal)
btAlignedObjectArray< btAlignedObjectArray< btDeformableNodeRigidContactConstraint > > m_nodeRigidConstraints
btHashMap< btHashInt, btAlignedObjectArray< btVector3 > > m_projectionsDict
btAlignedObjectArray< btAlignedObjectArray< btDeformableStaticConstraint > > m_staticConstraints
btAlignedObjectArray< btAlignedObjectArray< btDeformableFaceRigidContactConstraint > > m_faceRigidConstraints
btAlignedObjectArray< btAlignedObjectArray< btDeformableNodeAnchorConstraint > > m_nodeAnchorConstraints
const btSoftBody::DeformableFaceNodeContact * getContact() const
virtual btVector3 getDv(const btSoftBody::Node *) const
virtual btScalar solveConstraint(const btContactSolverInfo &infoGlobal)
const btSoftBody::DeformableFaceRigidContact * getContact() const
virtual btVector3 getDv(const btSoftBody::Node *) const
virtual btScalar solveConstraint(const btContactSolverInfo &infoGlobal)
virtual btVector3 getDv(const btSoftBody::Node *) const
virtual btScalar solveConstraint(const btContactSolverInfo &infoGlobal)
btScalar solveSplitImpulse(const btContactSolverInfo &infoGlobal)
int getUid1() const
Definition: btHashMap.h:77
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:264
Key getKeyAtIndex(int index)
Definition: btHashMap.h:400
void clear()
Definition: btHashMap.h:461
int size() const
Definition: btHashMap.h:373
const Value * find(const Key &key) const
Definition: btHashMap.h:424
const Value * getAtIndex(int index) const
Definition: btHashMap.h:378
btAlignedObjectArray< TV > m_out
btAlignedObjectArray< int > m_indices
btAlignedObjectArray< btVector3 > m_vecs
btAlignedObjectArray< DeformableFaceRigidContact > m_faceRigidContacts
Definition: btSoftBody.h:812
btAlignedObjectArray< DeformableNodeRigidAnchor > m_deformableAnchors
Definition: btSoftBody.h:808
btAlignedObjectArray< DeformableNodeRigidContact > m_nodeRigidContacts
Definition: btSoftBody.h:810
tNodeArray m_nodes
Definition: btSoftBody.h:799
OperationNode * node
ccl_gpu_kernel_postfix int ccl_global int * indices
#define N
btVector4 m_pcontact
Definition: btSoftBody.h:300
Node * m_n[3]
Definition: btSoftBody.h:296
const btCollisionObject * m_colObj
Definition: btSoftBody.h:226