Blender V4.3
btSoftBody.cpp
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. 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//
130btSoftBody::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];
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;
188 m_cfg.kSSHR_CL = (btScalar)0.5;
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);
226 m_useSelfCollision = false;
228 m_softSoftCollision = false;
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
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//
252bool btSoftBody::checkLink(int node0, int node1) const
253{
254 return (checkLink(&m_nodes[node0], &m_nodes[node1]));
255}
256
257//
258bool 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//
274bool 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//
310void 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;
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;
336}
337
338//
339void 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//
347void 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//
357void 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//
368void btSoftBody::appendNode(const btVector3& x, btScalar m)
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];
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//
388void btSoftBody::appendLink(int model, Material* mat)
389{
390 Link l;
391 if (model >= 0)
392 l = m_links[model];
393 else
394 {
396 l.m_material = mat ? mat : m_materials[0];
397 }
399}
400
401//
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//
428void btSoftBody::appendFace(int model, Material* mat)
429{
430 Face f;
431 if (model >= 0)
432 {
433 f = m_faces[model];
434 }
435 else
436 {
438 f.m_material = mat ? mat : m_materials[0];
439 }
441}
442
443//
444void 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//
469{
470 Tetra t;
471 if (model >= 0)
472 t = m_tetras[model];
473 else
474 {
476 t.m_material = mat ? mat : m_materials[0];
477 }
479}
480
481//
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
500void 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//
507void 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;
603 btVector3 t1 = generateUnitOrthogonalVector(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//
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;
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//
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;
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//
689void btSoftBody::addForce(const btVector3& force)
690{
691 for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addForce(force, i);
692}
693
694//
695void 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
704void 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
793void 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//
889void 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 */
895void 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//
909void 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//
919void btSoftBody::setMass(int node, btScalar mass)
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//
943void 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//
1043void btSoftBody::setLinearVelocity(const btVector3& linVel)
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//
1052void btSoftBody::setAngularVelocity(const btVector3& angVel)
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{
1065 btVector3 t = getCenterOfMass();
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();
1118}
1119
1120//
1121void btSoftBody::translate(const btVector3& trs)
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//
1139void btSoftBody::scale(const btVector3& scl)
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();
1157}
1158
1159//
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//
1181void 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
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//
1265btVector3 btSoftBody::clusterCom(const Cluster* cluster)
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//
1276btVector3 btSoftBody::clusterCom(int cluster) const
1277{
1278 return (clusterCom(m_clusters[cluster]));
1279}
1280
1281//
1282btVector3 btSoftBody::clusterVelocity(const Cluster* cluster, const btVector3& rpos)
1283{
1284 return (cluster->m_lv + btCross(cluster->m_av, rpos));
1285}
1286
1287//
1288void 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//
1300void 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//
1310void 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//
1317void 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//
1326void 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//
1334void 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//
1341void btSoftBody::clusterDCImpulse(Cluster* cluster, const btVector3& impulse)
1342{
1343 cluster->m_dimpulses[0] += impulse * cluster->m_imass;
1344 cluster->m_ndimpulses++;
1345}
1346
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//
1502int btSoftBody::generateClusters(int k, int maxiterations)
1503{
1504 int i;
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 {
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//
1695void 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();
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 {
1938 btAlignedObjectArray<int>& map=ranks;
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//
1959bool 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//
1965bool 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//
2020bool 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
2035bool btSoftBody::rayFaceTest(const btVector3& rayFrom,
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//
2079
2081{
2082 int i, ni;
2083
2084 /* Update */
2085 if (m_bUpdateRtCst)
2086 {
2087 m_bUpdateRtCst = false;
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 */
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];
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);
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 */
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//
2282void 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//
2294void 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//
2336btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt)
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{
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//
2483int 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 {
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;
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 {
2549 index = i;
2550 mint = t;
2551 }
2552 }
2553 }
2554 }
2555 return (cnt);
2556}
2557
2558int 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//
2577static 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
2592static 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);
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)
2791static 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;
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//
3058void 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
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;
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)
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 {
3334 m_joints.remove(m_joints[i--]);
3335 }
3336 }
3337}
3338
3339//
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 {
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
3495static 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//
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//
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//
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:
4014 case ePSolver::Linear:
4015 return (&btSoftBody::PSolve_Links);
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
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 {
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 {
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
4286void btSoftBody::setWindVelocity(const btVector3& velocity)
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
4303const 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;
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);
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);
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 {
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 {
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 {
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}
struct Material Material
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 Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp
#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)
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.
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
SIMD_FORCE_INLINE btScalar btAngle(const btQuaternion &q1, const btQuaternion &q2)
Return the angle between two quaternions.
#define BT_PROFILE(name)
bool gDisableDeactivation
btScalar gDeactivationTime
#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
#define BT_ARRAY_CODE
#define BT_SBNODE_CODE
@ 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 btScalar Dot4(const btVector4 &a, const btVector4 &b)
static btDbvtNode * buildTreeBottomUp(btAlignedObjectArray< btDbvtNode * > &leafNodes, btAlignedObjectArray< btAlignedObjectArray< int > > &adj)
btSoftBody implementation by Nathanael Presson
static btDbvntNode * copyToDbvnt(const btDbvtNode *n)
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 NEXTRAND
#define SAFE_EPSILON
btTransform m_worldTransform
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition btTransform.h:30
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 btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
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
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...
void setRotation(const btVector3 &axis, const btScalar &_angle)
Set the rotation using axis angle notation.
btVector3 getVelocityInLocalPoint(const btVector3 &rel_pos) const
btScalar getInvMass() const
void applyImpulse(const btVector3 &impulse, const btVector3 &rel_pos)
SIMD_FORCE_INLINE const btCollisionShape * getCollisionShape() const
static const btRigidBody * upcast(const btCollisionObject *colObj)
const btMatrix3x3 & getInvInertiaTensorWorld() const
virtual btChunk * allocate(size_t size, int numElements)=0
virtual void * getUniquePointer(void *oldPtr)=0
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
virtual void * findPointer(void *oldPtr)=0
btMultiBodyJacobianData jacobianData_t1
Definition btSoftBody.h:361
btMultiBodyJacobianData jacobianData_normal
Definition btSoftBody.h:360
btMultiBodyJacobianData jacobianData_t2
Definition btSoftBody.h:362
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
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
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)
void setMass(int node, btScalar mass)
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)
void scale(const btVector3 &scl)
btAlignedObjectArray< bool > m_clusterConnectivity
Definition btSoftBody.h:838
void updateFaceTree(bool use_velocity, bool margin)
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)
void predictMotion(btScalar dt)
void setSelfCollision(bool useSelfCollision)
void setLinearVelocity(const btVector3 &linVel)
btScalar m_timeacc
Definition btSoftBody.h:816
void appendTetra(int model, Material *mat)
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)
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)
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)
void staticSolve(int iterations)
void setVolumeMass(btScalar mass)
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)
btAlignedObjectArray< btVector4 > m_renderNodesInterpolationWeights
Definition btSoftBody.h:832
void appendAngularJoint(const AJoint::Specs &specs, Cluster *body0, Body body1)
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
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)
void updateDeformation()
btAlignedObjectArray< btScalar > m_z
Definition btSoftBody.h:834
void addAeroForceToNode(const btVector3 &windVelocity, int nodeIndex)
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)
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)
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)
Material * appendMaterial()
void removeAnchor(int node)
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)
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
tNodeArray m_nodes
Definition btSoftBody.h:799
void appendLink(int model=-1, Material *mat=0)
void setSpringStiffness(btScalar k)
void initializeDmInverse()
void updateConstants()
void setTotalMass(btScalar mass, bool fromfaces=false)
virtual ~btSoftBody()
void appendDeformableAnchor(int node, btRigidBody *body)
void updateLinkConstants()
void(* vsolver_t)(btSoftBody *, btScalar)
Definition btSoftBody.h:774
tNodeArray m_renderNodes
Definition btSoftBody.h:800
void initDefaults()
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
void initializeFaceTree()
void resetLinkRestLengths()
int clusterCount() const
btDbvt m_ndbvt
Definition btSoftBody.h:819
static void clusterAImpulse(Cluster *cluster, const Impulse &impulse)
local_group_size(16, 16) .push_constant(Type b
OperationNode * node
#define NULL
int len
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define rot(x, k)
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
#define N
#define B
#define R
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
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
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
btDbvtNode * parent
Definition btDbvt.h:183
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
static btScalar SignedDistance(const btVector3 &position, btScalar margin, const btConvexShape *shape, const btTransform &wtrs, sResults &results)
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]
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
tVector3Array m_framerefs
Definition btSoftBody.h:450
btMatrix3x3 m_invwi
Definition btSoftBody.h:455
btMatrix3x3 m_locii
Definition btSoftBody.h:454
btAlignedObjectArray< Node * > m_nodes
Definition btSoftBody.h:449
btDbvtNode * m_leaf
Definition btSoftBody.h:463
btVector3 m_vimpulses[2]
Definition btSoftBody.h:457
tScalarArray m_masses
Definition btSoftBody.h:448
btTransform m_framexform
Definition btSoftBody.h:451
tPSolverArray m_psequence
Definition btSoftBody.h:725
tPSolverArray m_dsequence
Definition btSoftBody.h:726
eAeroModel::_ aeromodel
Definition btSoftBody.h:698
tVSolverArray m_vsequence
Definition btSoftBody.h:724
btVector4 m_pcontact
Definition btSoftBody.h:300
btVector3 m_normal
Definition btSoftBody.h:297
btDbvtNode * m_leaf
Definition btSoftBody.h:299
Material * m_material
Definition btSoftBody.h:258
virtual btScalar Eval(const btVector3 &x)=0
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)
btDbvtNode * m_leaf
Definition btSoftBody.h:271
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)
btScalar m_element_measure
Definition btSoftBody.h:315
btMatrix3x3 m_Dm_inverse
Definition btSoftBody.h:313
btMatrix3x3 m_F
Definition btSoftBody.h:314
btVector4 m_P_inv[3]
Definition btSoftBody.h:316
@ 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
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)
CCL_NAMESPACE_BEGIN struct Window V