2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
15 ///btSoftBody implementation by Nathanael Presson
17 #ifndef _BT_SOFT_BODY_INTERNALS_H
18 #define _BT_SOFT_BODY_INTERNALS_H
20 #include "btSoftBody.h"
21 #include "LinearMath/btQuickprof.h"
22 #include "LinearMath/btPolarDecomposition.h"
23 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
24 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
25 #include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
26 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
27 #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
28 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
29 #include <string.h> //for memset
33 // Given a multibody link, a contact point and a contact direction, fill in the jacobian data needed to calculate the velocity change given an impulse in the contact direction
34 static SIMD_FORCE_INLINE void findJacobian(const btMultiBodyLinkCollider* multibodyLinkCol,
35 btMultiBodyJacobianData& jacobianData,
36 const btVector3& contact_point,
39 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
40 jacobianData.m_jacobians.resize(ndof);
41 jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
42 btScalar* jac = &jacobianData.m_jacobians[0];
44 multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, contact_point, dir, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
45 multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], &jacobianData.m_deltaVelocitiesUnitImpulse[0], jacobianData.scratch_r, jacobianData.scratch_v);
47 static SIMD_FORCE_INLINE btVector3 generateUnitOrthogonalVector(const btVector3& u)
49 btScalar ux = u.getX();
50 btScalar uy = u.getY();
51 btScalar uz = u.getZ();
52 btScalar ax = std::abs(ux);
53 btScalar ay = std::abs(uy);
54 btScalar az = std::abs(uz);
56 if (ax <= ay && ax <= az)
57 v = btVector3(0, -uz, uy);
58 else if (ay <= ax && ay <= az)
59 v = btVector3(-uz, 0, ux);
61 v = btVector3(-uy, ux, 0);
66 static SIMD_FORCE_INLINE bool proximityTest(const btVector3& x1, const btVector3& x2, const btVector3& x3, const btVector3& x4, const btVector3& normal, const btScalar& mrg, btVector3& bary)
68 btVector3 x43 = x4 - x3;
69 if (std::abs(x43.dot(normal)) > mrg)
71 btVector3 x13 = x1 - x3;
72 btVector3 x23 = x2 - x3;
73 btScalar a11 = x13.length2();
74 btScalar a22 = x23.length2();
75 btScalar a12 = x13.dot(x23);
76 btScalar b1 = x13.dot(x43);
77 btScalar b2 = x23.dot(x43);
78 btScalar det = a11 * a22 - a12 * a12;
79 if (det < SIMD_EPSILON)
81 btScalar w1 = (b1 * a22 - b2 * a12) / det;
82 btScalar w2 = (b2 * a11 - b1 * a12) / det;
83 btScalar w3 = 1 - w1 - w2;
84 btScalar delta = mrg / std::sqrt(0.5 * std::abs(x13.cross(x23).safeNorm()));
85 bary = btVector3(w1, w2, w3);
86 for (int i = 0; i < 3; ++i)
88 if (bary[i] < -delta || bary[i] > 1 + delta)
93 static const int KDOP_COUNT = 13;
94 static btVector3 dop[KDOP_COUNT] = {btVector3(1, 0, 0),
106 btVector3(1, -1, -1)};
108 static inline int getSign(const btVector3& n, const btVector3& x)
110 btScalar d = n.dot(x);
111 if (d > SIMD_EPSILON)
113 if (d < -SIMD_EPSILON)
118 static SIMD_FORCE_INLINE bool hasSeparatingPlane(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
120 btVector3 hex[6] = {face->m_n[0]->m_x - node->m_x,
121 face->m_n[1]->m_x - node->m_x,
122 face->m_n[2]->m_x - node->m_x,
123 face->m_n[0]->m_x + dt * face->m_n[0]->m_v - node->m_x,
124 face->m_n[1]->m_x + dt * face->m_n[1]->m_v - node->m_x,
125 face->m_n[2]->m_x + dt * face->m_n[2]->m_v - node->m_x};
126 btVector3 segment = dt * node->m_v;
127 for (int i = 0; i < KDOP_COUNT; ++i)
129 int s = getSign(dop[i], segment);
133 if (getSign(dop[i], hex[j]) == s)
142 static SIMD_FORCE_INLINE bool nearZero(const btScalar& a)
144 return (a > -SAFE_EPSILON && a < SAFE_EPSILON);
146 static SIMD_FORCE_INLINE bool sameSign(const btScalar& a, const btScalar& b)
148 return (nearZero(a) || nearZero(b) || (a > SAFE_EPSILON && b > SAFE_EPSILON) || (a < -SAFE_EPSILON && b < -SAFE_EPSILON));
150 static SIMD_FORCE_INLINE bool diffSign(const btScalar& a, const btScalar& b)
152 return !sameSign(a, b);
154 inline btScalar evaluateBezier2(const btScalar& p0, const btScalar& p1, const btScalar& p2, const btScalar& t, const btScalar& s)
159 return p0 * s2 + p1 * btScalar(2.0) * s * t + p2 * t2;
161 inline btScalar evaluateBezier(const btScalar& p0, const btScalar& p1, const btScalar& p2, const btScalar& p3, const btScalar& t, const btScalar& s)
164 btScalar s3 = s2 * s;
166 btScalar t3 = t2 * t;
168 return p0 * s3 + p1 * btScalar(3.0) * s2 * t + p2 * btScalar(3.0) * s * t2 + p3 * t3;
170 static SIMD_FORCE_INLINE bool getSigns(bool type_c, const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& t0, const btScalar& t1, btScalar& lt0, btScalar& lt1)
172 if (sameSign(t0, t1))
179 if (type_c || diffSign(k0, k3))
181 btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
185 if (sameSign(ft, k0))
200 btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
204 if (diffSign(ft, k0))
211 btScalar fk = evaluateBezier2(k1 - k0, k2 - k1, k3 - k2, t0, -t1);
213 if (sameSign(fk, k1 - k0))
223 static SIMD_FORCE_INLINE void getBernsteinCoeff(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, btScalar& k0, btScalar& k1, btScalar& k2, btScalar& k3)
225 const btVector3& n0 = face->m_n0;
226 const btVector3& n1 = face->m_n1;
227 btVector3 n_hat = n0 + n1 - face->m_vn;
228 btVector3 p0ma0 = node->m_x - face->m_n[0]->m_x;
229 btVector3 p1ma1 = node->m_q - face->m_n[0]->m_q;
230 k0 = (p0ma0).dot(n0) * 3.0;
231 k1 = (p0ma0).dot(n_hat) + (p1ma1).dot(n0);
232 k2 = (p1ma1).dot(n_hat) + (p0ma0).dot(n1);
233 k3 = (p1ma1).dot(n1) * 3.0;
236 static SIMD_FORCE_INLINE void polyDecomposition(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& j0, const btScalar& j1, const btScalar& j2, btScalar& u0, btScalar& u1, btScalar& v0, btScalar& v1)
238 btScalar denom = 4.0 * (j1 - j2) * (j1 - j0) + (j2 - j0) * (j2 - j0);
239 u0 = (2.0 * (j1 - j2) * (3.0 * k1 - 2.0 * k0 - k3) - (j0 - j2) * (3.0 * k2 - 2.0 * k3 - k0)) / denom;
240 u1 = (2.0 * (j1 - j0) * (3.0 * k2 - 2.0 * k3 - k0) - (j2 - j0) * (3.0 * k1 - 2.0 * k0 - k3)) / denom;
245 static SIMD_FORCE_INLINE bool rootFindingLemma(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3)
247 btScalar u0, u1, v0, v1;
248 btScalar j0 = 3.0 * (k1 - k0);
249 btScalar j1 = 3.0 * (k2 - k1);
250 btScalar j2 = 3.0 * (k3 - k2);
251 polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
252 if (sameSign(v0, v1))
254 btScalar Ypa = j0 * (1.0 - v0) * (1.0 - v0) + 2.0 * j1 * v0 * (1.0 - v0) + j2 * v0 * v0; // Y'(v0)
255 if (sameSign(Ypa, j0))
257 return (diffSign(k0, v1));
260 return diffSign(k0, v0);
263 static SIMD_FORCE_INLINE void getJs(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Node* a, const btSoftBody::Node* b, const btSoftBody::Node* c, const btSoftBody::Node* p, const btScalar& dt, btScalar& j0, btScalar& j1, btScalar& j2)
265 const btVector3& a0 = a->m_x;
266 const btVector3& b0 = b->m_x;
267 const btVector3& c0 = c->m_x;
268 const btVector3& va = a->m_v;
269 const btVector3& vb = b->m_v;
270 const btVector3& vc = c->m_v;
271 const btVector3 a1 = a0 + dt * va;
272 const btVector3 b1 = b0 + dt * vb;
273 const btVector3 c1 = c0 + dt * vc;
274 btVector3 n0 = (b0 - a0).cross(c0 - a0);
275 btVector3 n1 = (b1 - a1).cross(c1 - a1);
276 btVector3 n_hat = n0 + n1 - dt * dt * (vb - va).cross(vc - va);
277 const btVector3& p0 = p->m_x;
278 const btVector3& vp = p->m_v;
279 btVector3 p1 = p0 + dt * vp;
280 btVector3 m0 = (b0 - p0).cross(c0 - p0);
281 btVector3 m1 = (b1 - p1).cross(c1 - p1);
282 btVector3 m_hat = m0 + m1 - dt * dt * (vb - vp).cross(vc - vp);
283 btScalar l0 = m0.dot(n0);
284 btScalar l1 = 0.25 * (m0.dot(n_hat) + m_hat.dot(n0));
285 btScalar l2 = btScalar(1) / btScalar(6) * (m0.dot(n1) + m_hat.dot(n_hat) + m1.dot(n0));
286 btScalar l3 = 0.25 * (m_hat.dot(n1) + m1.dot(n_hat));
287 btScalar l4 = m1.dot(n1);
289 btScalar k1p = 0.25 * k0 + 0.75 * k1;
290 btScalar k2p = 0.5 * k1 + 0.5 * k2;
291 btScalar k3p = 0.75 * k2 + 0.25 * k3;
293 btScalar s0 = (l1 * k0 - l0 * k1p) * 4.0;
294 btScalar s1 = (l2 * k0 - l0 * k2p) * 2.0;
295 btScalar s2 = (l3 * k0 - l0 * k3p) * btScalar(4) / btScalar(3);
296 btScalar s3 = l4 * k0 - l0 * k3;
298 j0 = (s1 * k0 - s0 * k1) * 3.0;
299 j1 = (s2 * k0 - s0 * k2) * 1.5;
300 j2 = (s3 * k0 - s0 * k3);
303 static SIMD_FORCE_INLINE bool signDetermination1Internal(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& u0, const btScalar& u1, const btScalar& v0, const btScalar& v1)
305 btScalar Yu0 = k0 * (1.0 - u0) * (1.0 - u0) * (1.0 - u0) + 3.0 * k1 * u0 * (1.0 - u0) * (1.0 - u0) + 3.0 * k2 * u0 * u0 * (1.0 - u0) + k3 * u0 * u0 * u0; // Y(u0)
306 btScalar Yv0 = k0 * (1.0 - v0) * (1.0 - v0) * (1.0 - v0) + 3.0 * k1 * v0 * (1.0 - v0) * (1.0 - v0) + 3.0 * k2 * v0 * v0 * (1.0 - v0) + k3 * v0 * v0 * v0; // Y(v0)
308 btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0;
309 btScalar L = sameSign(sign_Ytp, k0) ? u1 : u0;
310 sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
311 btScalar K = (sameSign(sign_Ytp, k0)) ? v1 : v0;
312 return diffSign(L, K);
315 static SIMD_FORCE_INLINE bool signDetermination2Internal(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& j0, const btScalar& j1, const btScalar& j2, const btScalar& u0, const btScalar& u1, const btScalar& v0, const btScalar& v1)
317 btScalar Yu0 = k0 * (1.0 - u0) * (1.0 - u0) * (1.0 - u0) + 3.0 * k1 * u0 * (1.0 - u0) * (1.0 - u0) + 3.0 * k2 * u0 * u0 * (1.0 - u0) + k3 * u0 * u0 * u0; // Y(u0)
318 btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0, L1, L2;
319 if (diffSign(sign_Ytp, k0))
326 btScalar Yp_u0 = j0 * (1.0 - u0) * (1.0 - u0) + 2.0 * j1 * (1.0 - u0) * u0 + j2 * u0 * u0;
327 if (sameSign(Yp_u0, j0))
338 btScalar Yv0 = k0 * (1.0 - v0) * (1.0 - v0) * (1.0 - v0) + 3.0 * k1 * v0 * (1.0 - v0) * (1.0 - v0) + 3.0 * k2 * v0 * v0 * (1.0 - v0) + k3 * v0 * v0 * v0; // Y(uv0)
339 sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
341 if (diffSign(sign_Ytp, k0))
348 btScalar Yp_v0 = j0 * (1.0 - v0) * (1.0 - v0) + 2.0 * j1 * (1.0 - v0) * v0 + j2 * v0 * v0;
349 if (sameSign(Yp_v0, j0))
360 return (diffSign(K1, L1) || diffSign(L2, K2));
363 static SIMD_FORCE_INLINE bool signDetermination1(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
365 btScalar j0, j1, j2, u0, u1, v0, v1;
367 getJs(k0, k1, k2, k3, face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
368 if (nearZero(j0 + j2 - j1 * 2.0))
371 getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
372 if (lt0 < -SAFE_EPSILON)
377 polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
378 if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
382 getJs(k0, k1, k2, k3, face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
383 if (nearZero(j0 + j2 - j1 * 2.0))
386 getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
387 if (lt0 < -SAFE_EPSILON)
392 polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
393 if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
397 getJs(k0, k1, k2, k3, face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
398 if (nearZero(j0 + j2 - j1 * 2.0))
401 getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
402 if (lt0 < -SAFE_EPSILON)
407 polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
408 if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
414 static SIMD_FORCE_INLINE bool signDetermination2(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
416 btScalar j0, j1, j2, u0, u1, v0, v1;
418 getJs(k0, k1, k2, k3, face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
419 if (nearZero(j0 + j2 - j1 * 2.0))
422 bool bt0 = true, bt1 = true;
423 getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
424 if (lt0 < -SAFE_EPSILON)
426 if (lt1 < -SAFE_EPSILON)
433 polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
434 if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
438 getJs(k0, k1, k2, k3, face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
439 if (nearZero(j0 + j2 - j1 * 2.0))
442 bool bt0 = true, bt1 = true;
443 getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
444 if (lt0 < -SAFE_EPSILON)
446 if (lt1 < -SAFE_EPSILON)
453 polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
454 if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
458 getJs(k0, k1, k2, k3, face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
459 if (nearZero(j0 + j2 - j1 * 2.0))
462 bool bt0 = true, bt1 = true;
463 getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
464 if (lt0 < -SAFE_EPSILON)
466 if (lt1 < -SAFE_EPSILON)
473 polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
474 if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
480 static SIMD_FORCE_INLINE bool coplanarAndInsideTest(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
483 if (diffSign(k1 - k0, k3 - k2))
486 if (sameSign(k0, k3) && !rootFindingLemma(k0, k1, k2, k3))
489 return signDetermination2(k0, k1, k2, k3, face, node, dt);
494 if (sameSign(k0, k3))
497 return signDetermination1(k0, k1, k2, k3, face, node, dt);
501 static SIMD_FORCE_INLINE bool conservativeCulling(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg)
503 if (k0 > mrg && k1 > mrg && k2 > mrg && k3 > mrg)
505 if (k0 < -mrg && k1 < -mrg && k2 < -mrg && k3 < -mrg)
510 static SIMD_FORCE_INLINE bool bernsteinVFTest(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
512 if (conservativeCulling(k0, k1, k2, k3, mrg))
514 return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
517 static SIMD_FORCE_INLINE void deCasteljau(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& t0, btScalar& k10, btScalar& k20, btScalar& k30, btScalar& k21, btScalar& k12)
519 k10 = k0 * (1.0 - t0) + k1 * t0;
520 btScalar k11 = k1 * (1.0 - t0) + k2 * t0;
521 k12 = k2 * (1.0 - t0) + k3 * t0;
522 k20 = k10 * (1.0 - t0) + k11 * t0;
523 k21 = k11 * (1.0 - t0) + k12 * t0;
524 k30 = k20 * (1.0 - t0) + k21 * t0;
526 static SIMD_FORCE_INLINE bool bernsteinVFTest(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg)
528 btScalar k0, k1, k2, k3;
529 getBernsteinCoeff(face, node, dt, k0, k1, k2, k3);
530 if (conservativeCulling(k0, k1, k2, k3, mrg))
533 if (diffSign(k2 - 2.0 * k1 + k0, k3 - 2.0 * k2 + k1))
535 btScalar k10, k20, k30, k21, k12;
536 btScalar t0 = (k2 - 2.0 * k1 + k0) / (k0 - 3.0 * k1 + 3.0 * k2 - k3);
537 deCasteljau(k0, k1, k2, k3, t0, k10, k20, k30, k21, k12);
538 return bernsteinVFTest(k0, k10, k20, k30, mrg, face, node, dt) || bernsteinVFTest(k30, k21, k12, k3, mrg, face, node, dt);
540 return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
543 static SIMD_FORCE_INLINE bool continuousCollisionDetection(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
545 if (hasSeparatingPlane(face, node, dt))
547 btVector3 x21 = face->m_n[1]->m_x - face->m_n[0]->m_x;
548 btVector3 x31 = face->m_n[2]->m_x - face->m_n[0]->m_x;
549 btVector3 x41 = node->m_x - face->m_n[0]->m_x;
550 btVector3 v21 = face->m_n[1]->m_v - face->m_n[0]->m_v;
551 btVector3 v31 = face->m_n[2]->m_v - face->m_n[0]->m_v;
552 btVector3 v41 = node->m_v - face->m_n[0]->m_v;
553 btVector3 a = x21.cross(x31);
554 btVector3 b = x21.cross(v31) + v21.cross(x31);
555 btVector3 c = v21.cross(v31);
558 btScalar a0 = a.dot(d);
559 btScalar a1 = a.dot(e) + b.dot(d);
560 btScalar a2 = c.dot(d) + b.dot(e);
561 btScalar a3 = c.dot(e);
562 btScalar eps = SAFE_EPSILON;
565 if (std::abs(a3) < eps)
567 // cubic term is zero
568 if (std::abs(a2) < eps)
570 if (std::abs(a1) < eps)
572 if (std::abs(a0) < eps)
587 num_roots = SolveP2(roots, a1 / a2, a0 / a2);
592 num_roots = SolveP3(roots, a2 / a3, a1 / a3, a0 / a3);
594 // std::sort(roots, roots+num_roots);
597 if (roots[0] > roots[1])
598 btSwap(roots[0], roots[1]);
602 if (roots[0] > roots[2])
603 btSwap(roots[0], roots[2]);
604 if (roots[1] > roots[2])
605 btSwap(roots[1], roots[2]);
607 for (int r = 0; r < num_roots; ++r)
609 double root = roots[r];
612 if (root > dt + SIMD_EPSILON)
614 btVector3 x1 = face->m_n[0]->m_x + root * face->m_n[0]->m_v;
615 btVector3 x2 = face->m_n[1]->m_x + root * face->m_n[1]->m_v;
616 btVector3 x3 = face->m_n[2]->m_x + root * face->m_n[2]->m_v;
617 btVector3 x4 = node->m_x + root * node->m_v;
618 btVector3 normal = (x2 - x1).cross(x3 - x1);
619 normal.safeNormalize();
620 if (proximityTest(x1, x2, x3, x4, normal, mrg, bary))
625 static SIMD_FORCE_INLINE bool bernsteinCCD(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
627 if (!bernsteinVFTest(face, node, dt, mrg))
629 if (!continuousCollisionDetection(face, node, dt, 1e-6, bary))
637 template <typename T>
640 btSymMatrix() : dim(0) {}
641 btSymMatrix(int n, const T& init = T()) { resize(n, init); }
642 void resize(int n, const T& init = T())
645 store.resize((n * (n + 1)) / 2, init);
647 int index(int c, int r) const
649 if (c > r) btSwap(c, r);
651 return ((r * (r + 1)) / 2 + c);
653 T& operator()(int c, int r) { return (store[index(c, r)]); }
654 const T& operator()(int c, int r) const { return (store[index(c, r)]); }
655 btAlignedObjectArray<T> store;
660 // btSoftBodyCollisionShape
662 class btSoftBodyCollisionShape : public btConcaveShape
667 btSoftBodyCollisionShape(btSoftBody* backptr)
669 m_shapeType = SOFTBODY_SHAPE_PROXYTYPE;
673 virtual ~btSoftBodyCollisionShape()
677 void processAllTriangles(btTriangleCallback* /*callback*/, const btVector3& /*aabbMin*/, const btVector3& /*aabbMax*/) const
683 ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
684 virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
686 /* t is usually identity, except when colliding against btCompoundShape. See Issue 512 */
687 const btVector3 mins = m_body->m_bounds[0];
688 const btVector3 maxs = m_body->m_bounds[1];
689 const btVector3 crns[] = {t * btVector3(mins.x(), mins.y(), mins.z()),
690 t * btVector3(maxs.x(), mins.y(), mins.z()),
691 t * btVector3(maxs.x(), maxs.y(), mins.z()),
692 t * btVector3(mins.x(), maxs.y(), mins.z()),
693 t * btVector3(mins.x(), mins.y(), maxs.z()),
694 t * btVector3(maxs.x(), mins.y(), maxs.z()),
695 t * btVector3(maxs.x(), maxs.y(), maxs.z()),
696 t * btVector3(mins.x(), maxs.y(), maxs.z())};
697 aabbMin = aabbMax = crns[0];
698 for (int i = 1; i < 8; ++i)
700 aabbMin.setMin(crns[i]);
701 aabbMax.setMax(crns[i]);
705 virtual void setLocalScaling(const btVector3& /*scaling*/)
709 virtual const btVector3& getLocalScaling() const
711 static const btVector3 dummy(1, 1, 1);
714 virtual void calculateLocalInertia(btScalar /*mass*/, btVector3& /*inertia*/) const
719 virtual const char* getName() const
726 // btSoftClusterCollisionShape
728 class btSoftClusterCollisionShape : public btConvexInternalShape
731 const btSoftBody::Cluster* m_cluster;
733 btSoftClusterCollisionShape(const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); }
735 virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
737 btSoftBody::Node* const* n = &m_cluster->m_nodes[0];
738 btScalar d = btDot(vec, n[0]->m_x);
740 for (int i = 1, ni = m_cluster->m_nodes.size(); i < ni; ++i)
742 const btScalar k = btDot(vec, n[i]->m_x);
751 virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
753 return (localGetSupportingVertex(vec));
755 //notice that the vectors should be unit length
756 virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
760 virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const
764 virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
768 virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; }
771 virtual const char* getName() const { return "SOFTCLUSTER"; }
773 virtual void setMargin(btScalar margin)
775 btConvexInternalShape::setMargin(margin);
777 virtual btScalar getMargin() const
779 return btConvexInternalShape::getMargin();
788 template <typename T>
789 static inline void ZeroInitialize(T& value)
791 memset(&value, 0, sizeof(T));
794 template <typename T>
795 static inline bool CompLess(const T& a, const T& b)
800 template <typename T>
801 static inline bool CompGreater(const T& a, const T& b)
806 template <typename T>
807 static inline T Lerp(const T& a, const T& b, btScalar t)
809 return (a + (b - a) * t);
812 template <typename T>
813 static inline T InvLerp(const T& a, const T& b, btScalar t)
815 return ((b + a * t - b * t) / (a * b));
818 static inline btMatrix3x3 Lerp(const btMatrix3x3& a,
819 const btMatrix3x3& b,
823 r[0] = Lerp(a[0], b[0], t);
824 r[1] = Lerp(a[1], b[1], t);
825 r[2] = Lerp(a[2], b[2], t);
829 static inline btVector3 Clamp(const btVector3& v, btScalar maxlength)
831 const btScalar sql = v.length2();
832 if (sql > (maxlength * maxlength))
833 return ((v * maxlength) / btSqrt(sql));
838 template <typename T>
839 static inline T Clamp(const T& x, const T& l, const T& h)
841 return (x < l ? l : x > h ? h : x);
844 template <typename T>
845 static inline T Sq(const T& x)
850 template <typename T>
851 static inline T Cube(const T& x)
856 template <typename T>
857 static inline T Sign(const T& x)
859 return ((T)(x < 0 ? -1 : +1));
862 template <typename T>
863 static inline bool SameSign(const T& x, const T& y)
865 return ((x * y) > 0);
868 static inline btScalar ClusterMetric(const btVector3& x, const btVector3& y)
870 const btVector3 d = x - y;
871 return (btFabs(d[0]) + btFabs(d[1]) + btFabs(d[2]));
874 static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a, btScalar s)
876 const btScalar xx = a.x() * a.x();
877 const btScalar yy = a.y() * a.y();
878 const btScalar zz = a.z() * a.z();
879 const btScalar xy = a.x() * a.y();
880 const btScalar yz = a.y() * a.z();
881 const btScalar zx = a.z() * a.x();
883 m[0] = btVector3(1 - xx + xx * s, xy * s - xy, zx * s - zx);
884 m[1] = btVector3(xy * s - xy, 1 - yy + yy * s, yz * s - yz);
885 m[2] = btVector3(zx * s - zx, yz * s - yz, 1 - zz + zz * s);
889 static inline btMatrix3x3 Cross(const btVector3& v)
892 m[0] = btVector3(0, -v.z(), +v.y());
893 m[1] = btVector3(+v.z(), 0, -v.x());
894 m[2] = btVector3(-v.y(), +v.x(), 0);
898 static inline btMatrix3x3 Diagonal(btScalar x)
901 m[0] = btVector3(x, 0, 0);
902 m[1] = btVector3(0, x, 0);
903 m[2] = btVector3(0, 0, x);
907 static inline btMatrix3x3 Diagonal(const btVector3& v)
910 m[0] = btVector3(v.getX(), 0, 0);
911 m[1] = btVector3(0, v.getY(), 0);
912 m[2] = btVector3(0, 0, v.getZ());
916 static inline btScalar Dot(const btScalar* a, const btScalar* b, int ndof)
919 for (int i = 0; i < ndof; ++i)
920 result += a[i] * b[i];
924 static inline btMatrix3x3 OuterProduct(const btScalar* v1, const btScalar* v2, const btScalar* v3,
925 const btScalar* u1, const btScalar* u2, const btScalar* u3, int ndof)
928 btScalar a11 = Dot(v1, u1, ndof);
929 btScalar a12 = Dot(v1, u2, ndof);
930 btScalar a13 = Dot(v1, u3, ndof);
932 btScalar a21 = Dot(v2, u1, ndof);
933 btScalar a22 = Dot(v2, u2, ndof);
934 btScalar a23 = Dot(v2, u3, ndof);
936 btScalar a31 = Dot(v3, u1, ndof);
937 btScalar a32 = Dot(v3, u2, ndof);
938 btScalar a33 = Dot(v3, u3, ndof);
939 m[0] = btVector3(a11, a12, a13);
940 m[1] = btVector3(a21, a22, a23);
941 m[2] = btVector3(a31, a32, a33);
945 static inline btMatrix3x3 OuterProduct(const btVector3& v1, const btVector3& v2)
948 btScalar a11 = v1[0] * v2[0];
949 btScalar a12 = v1[0] * v2[1];
950 btScalar a13 = v1[0] * v2[2];
952 btScalar a21 = v1[1] * v2[0];
953 btScalar a22 = v1[1] * v2[1];
954 btScalar a23 = v1[1] * v2[2];
956 btScalar a31 = v1[2] * v2[0];
957 btScalar a32 = v1[2] * v2[1];
958 btScalar a33 = v1[2] * v2[2];
959 m[0] = btVector3(a11, a12, a13);
960 m[1] = btVector3(a21, a22, a23);
961 m[2] = btVector3(a31, a32, a33);
966 static inline btMatrix3x3 Add(const btMatrix3x3& a,
967 const btMatrix3x3& b)
970 for (int i = 0; i < 3; ++i) r[i] = a[i] + b[i];
974 static inline btMatrix3x3 Sub(const btMatrix3x3& a,
975 const btMatrix3x3& b)
978 for (int i = 0; i < 3; ++i) r[i] = a[i] - b[i];
982 static inline btMatrix3x3 Mul(const btMatrix3x3& a,
986 for (int i = 0; i < 3; ++i) r[i] = a[i] * b;
990 static inline void Orthogonalize(btMatrix3x3& m)
992 m[2] = btCross(m[0], m[1]).normalized();
993 m[1] = btCross(m[2], m[0]).normalized();
994 m[0] = btCross(m[1], m[2]).normalized();
997 static inline btMatrix3x3 MassMatrix(btScalar im, const btMatrix3x3& iwi, const btVector3& r)
999 const btMatrix3x3 cr = Cross(r);
1000 return (Sub(Diagonal(im), cr * iwi * cr));
1004 static inline btMatrix3x3 ImpulseMatrix(btScalar dt,
1007 const btMatrix3x3& iwi,
1010 return (Diagonal(1 / dt) * Add(Diagonal(ima), MassMatrix(imb, iwi, r)).inverse());
1014 static inline btMatrix3x3 ImpulseMatrix(btScalar dt,
1015 const btMatrix3x3& effective_mass_inv,
1017 const btMatrix3x3& iwi,
1020 return (Diagonal(1 / dt) * Add(effective_mass_inv, MassMatrix(imb, iwi, r)).inverse());
1021 // btMatrix3x3 iimb = MassMatrix(imb, iwi, r);
1022 // if (iimb.determinant() == 0)
1023 // return effective_mass_inv.inverse();
1024 // return effective_mass_inv.inverse() * Add(effective_mass_inv.inverse(), iimb.inverse()).inverse() * iimb.inverse();
1028 static inline btMatrix3x3 ImpulseMatrix(btScalar ima, const btMatrix3x3& iia, const btVector3& ra,
1029 btScalar imb, const btMatrix3x3& iib, const btVector3& rb)
1031 return (Add(MassMatrix(ima, iia, ra), MassMatrix(imb, iib, rb)).inverse());
1035 static inline btMatrix3x3 AngularImpulseMatrix(const btMatrix3x3& iia,
1036 const btMatrix3x3& iib)
1038 return (Add(iia, iib).inverse());
1042 static inline btVector3 ProjectOnAxis(const btVector3& v,
1045 return (a * btDot(v, a));
1048 static inline btVector3 ProjectOnPlane(const btVector3& v,
1051 return (v - ProjectOnAxis(v, a));
1055 static inline void ProjectOrigin(const btVector3& a,
1060 const btVector3 d = b - a;
1061 const btScalar m2 = d.length2();
1062 if (m2 > SIMD_EPSILON)
1064 const btScalar t = Clamp<btScalar>(-btDot(a, d) / m2, 0, 1);
1065 const btVector3 p = a + d * t;
1066 const btScalar l2 = p.length2();
1075 static inline void ProjectOrigin(const btVector3& a,
1081 const btVector3& q = btCross(b - a, c - a);
1082 const btScalar m2 = q.length2();
1083 if (m2 > SIMD_EPSILON)
1085 const btVector3 n = q / btSqrt(m2);
1086 const btScalar k = btDot(a, n);
1087 const btScalar k2 = k * k;
1090 const btVector3 p = n * k;
1091 if ((btDot(btCross(a - p, b - p), q) > 0) &&
1092 (btDot(btCross(b - p, c - p), q) > 0) &&
1093 (btDot(btCross(c - p, a - p), q) > 0))
1100 ProjectOrigin(a, b, prj, sqd);
1101 ProjectOrigin(b, c, prj, sqd);
1102 ProjectOrigin(c, a, prj, sqd);
1109 static inline bool rayIntersectsTriangle(const btVector3& origin, const btVector3& dir, const btVector3& v0, const btVector3& v1, const btVector3& v2, btScalar& t)
1111 btScalar a, f, u, v;
1113 btVector3 e1 = v1 - v0;
1114 btVector3 e2 = v2 - v0;
1115 btVector3 h = dir.cross(e2);
1118 if (a > -0.00001 && a < 0.00001)
1121 f = btScalar(1) / a;
1122 btVector3 s = origin - v0;
1125 if (u < 0.0 || u > 1.0)
1128 btVector3 q = s.cross(e1);
1130 if (v < 0.0 || u + v > 1.0)
1132 // at this stage we can compute t to find out where
1133 // the intersection point is on the line
1135 if (t > 0) // ray intersection
1137 else // this means that there is a line intersection
1138 // but not a ray intersection
1142 static inline bool lineIntersectsTriangle(const btVector3& rayStart, const btVector3& rayEnd, const btVector3& p1, const btVector3& p2, const btVector3& p3, btVector3& sect, btVector3& normal)
1144 btVector3 dir = rayEnd - rayStart;
1145 btScalar dir_norm = dir.norm();
1146 if (dir_norm < SIMD_EPSILON)
1150 bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t);
1156 sect = rayStart + dir * t;
1166 btVector3 n = (p3 - p1).cross(p2 - p1);
1177 template <typename T>
1178 static inline T BaryEval(const T& a,
1181 const btVector3& coord)
1183 return (a * coord.x() + b * coord.y() + c * coord.z());
1186 static inline btVector3 BaryCoord(const btVector3& a,
1191 const btScalar w[] = {btCross(a - p, b - p).length(),
1192 btCross(b - p, c - p).length(),
1193 btCross(c - p, a - p).length()};
1194 const btScalar isum = 1 / (w[0] + w[1] + w[2]);
1195 return (btVector3(w[1] * isum, w[2] * isum, w[0] * isum));
1199 inline static btScalar ImplicitSolve(btSoftBody::ImplicitFn* fn,
1202 const btScalar accuracy,
1203 const int maxiterations = 256)
1205 btScalar span[2] = {0, 1};
1206 btScalar values[2] = {fn->Eval(a), fn->Eval(b)};
1207 if (values[0] > values[1])
1209 btSwap(span[0], span[1]);
1210 btSwap(values[0], values[1]);
1212 if (values[0] > -accuracy) return (-1);
1213 if (values[1] < +accuracy) return (-1);
1214 for (int i = 0; i < maxiterations; ++i)
1216 const btScalar t = Lerp(span[0], span[1], values[0] / (values[0] - values[1]));
1217 const btScalar v = fn->Eval(Lerp(a, b, t));
1218 if ((t <= 0) || (t >= 1)) break;
1219 if (btFabs(v) < accuracy) return (t);
1234 inline static void EvaluateMedium(const btSoftBodyWorldInfo* wfi,
1236 btSoftBody::sMedium& medium)
1238 medium.m_velocity = btVector3(0, 0, 0);
1239 medium.m_pressure = 0;
1240 medium.m_density = wfi->air_density;
1241 if (wfi->water_density > 0)
1243 const btScalar depth = -(btDot(x, wfi->water_normal) + wfi->water_offset);
1246 medium.m_density = wfi->water_density;
1247 medium.m_pressure = depth * wfi->water_density * wfi->m_gravity.length();
1253 static inline btVector3 NormalizeAny(const btVector3& v)
1255 const btScalar l = v.length();
1256 if (l > SIMD_EPSILON)
1259 return (btVector3(0, 0, 0));
1263 static inline btDbvtVolume VolumeOf(const btSoftBody::Face& f,
1266 const btVector3* pts[] = {&f.m_n[0]->m_x,
1269 btDbvtVolume vol = btDbvtVolume::FromPoints(pts, 3);
1270 vol.Expand(btVector3(margin, margin, margin));
1275 static inline btVector3 CenterOf(const btSoftBody::Face& f)
1277 return ((f.m_n[0]->m_x + f.m_n[1]->m_x + f.m_n[2]->m_x) / 3);
1281 static inline btScalar AreaOf(const btVector3& x0,
1282 const btVector3& x1,
1283 const btVector3& x2)
1285 const btVector3 a = x1 - x0;
1286 const btVector3 b = x2 - x0;
1287 const btVector3 cr = btCross(a, b);
1288 const btScalar area = cr.length();
1293 static inline btScalar VolumeOf(const btVector3& x0,
1294 const btVector3& x1,
1295 const btVector3& x2,
1296 const btVector3& x3)
1298 const btVector3 a = x1 - x0;
1299 const btVector3 b = x2 - x0;
1300 const btVector3 c = x3 - x0;
1301 return (btDot(a, btCross(b, c)));
1307 static inline void ApplyClampedForce(btSoftBody::Node& n,
1311 const btScalar dtim = dt * n.m_im;
1312 if ((f * dtim).length2() > n.m_v.length2())
1314 n.m_f -= ProjectOnAxis(n.m_v, f.normalized()) / dtim;
1323 static inline int MatchEdge(const btSoftBody::Node* a,
1324 const btSoftBody::Node* b,
1325 const btSoftBody::Node* ma,
1326 const btSoftBody::Node* mb)
1328 if ((a == ma) && (b == mb)) return (0);
1329 if ((a == mb) && (b == ma)) return (1);
1334 // btEigen : Extract eigen system,
1335 // straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html
1336 // outputs are NOT sorted.
1340 static int system(btMatrix3x3& a, btMatrix3x3* vectors, btVector3* values = 0)
1342 static const int maxiterations = 16;
1343 static const btScalar accuracy = (btScalar)0.0001;
1344 btMatrix3x3& v = *vectors;
1346 vectors->setIdentity();
1350 if (btFabs(a[p][q]) < btFabs(a[0][2]))
1355 if (btFabs(a[p][q]) < btFabs(a[1][2]))
1360 if (btFabs(a[p][q]) > accuracy)
1362 const btScalar w = (a[q][q] - a[p][p]) / (2 * a[p][q]);
1363 const btScalar z = btFabs(w);
1364 const btScalar t = w / (z * (btSqrt(1 + w * w) + z));
1365 if (t == t) /* [WARNING] let hope that one does not get thrown aways by some compilers... */
1367 const btScalar c = 1 / btSqrt(t * t + 1);
1368 const btScalar s = c * t;
1369 mulPQ(a, c, s, p, q);
1370 mulTPQ(a, c, s, p, q);
1371 mulPQ(v, c, s, p, q);
1378 } while ((++iterations) < maxiterations);
1381 *values = btVector3(a[0][0], a[1][1], a[2][2]);
1383 return (iterations);
1387 static inline void mulTPQ(btMatrix3x3& a, btScalar c, btScalar s, int p, int q)
1389 const btScalar m[2][3] = {{a[p][0], a[p][1], a[p][2]},
1390 {a[q][0], a[q][1], a[q][2]}};
1393 for (i = 0; i < 3; ++i) a[p][i] = c * m[0][i] - s * m[1][i];
1394 for (i = 0; i < 3; ++i) a[q][i] = c * m[1][i] + s * m[0][i];
1396 static inline void mulPQ(btMatrix3x3& a, btScalar c, btScalar s, int p, int q)
1398 const btScalar m[2][3] = {{a[0][p], a[1][p], a[2][p]},
1399 {a[0][q], a[1][q], a[2][q]}};
1402 for (i = 0; i < 3; ++i) a[i][p] = c * m[0][i] - s * m[1][i];
1403 for (i = 0; i < 3; ++i) a[i][q] = c * m[1][i] + s * m[0][i];
1408 // Polar decomposition,
1409 // "Computing the Polar Decomposition with Applications", Nicholas J. Higham, 1986.
1411 static inline int PolarDecompose(const btMatrix3x3& m, btMatrix3x3& q, btMatrix3x3& s)
1413 static const btPolarDecomposition polar;
1414 return polar.decompose(m, q, s);
1420 struct btSoftColliders
1425 struct ClusterBase : btDbvt::ICollide
1438 threshold = (btScalar)0;
1440 bool SolveContact(const btGjkEpaSolver2::sResults& res,
1441 btSoftBody::Body ba, const btSoftBody::Body bb,
1442 btSoftBody::CJoint& joint)
1444 if (res.distance < m_margin)
1446 btVector3 norm = res.normal;
1447 norm.normalize(); //is it necessary?
1449 const btVector3 ra = res.witnesses[0] - ba.xform().getOrigin();
1450 const btVector3 rb = res.witnesses[1] - bb.xform().getOrigin();
1451 const btVector3 va = ba.velocity(ra);
1452 const btVector3 vb = bb.velocity(rb);
1453 const btVector3 vrel = va - vb;
1454 const btScalar rvac = btDot(vrel, norm);
1455 btScalar depth = res.distance - m_margin;
1457 // printf("depth=%f\n",depth);
1458 const btVector3 iv = norm * rvac;
1459 const btVector3 fv = vrel - iv;
1460 joint.m_bodies[0] = ba;
1461 joint.m_bodies[1] = bb;
1462 joint.m_refs[0] = ra * ba.xform().getBasis();
1463 joint.m_refs[1] = rb * bb.xform().getBasis();
1464 joint.m_rpos[0] = ra;
1465 joint.m_rpos[1] = rb;
1469 joint.m_maxlife = 0;
1472 joint.m_drift = depth * norm;
1474 joint.m_normal = norm;
1475 // printf("normal=%f,%f,%f\n",res.normal.getX(),res.normal.getY(),res.normal.getZ());
1476 joint.m_delete = false;
1477 joint.m_friction = fv.length2() < (rvac * friction * rvac * friction) ? 1 : friction;
1478 joint.m_massmatrix = ImpulseMatrix(ba.invMass(), ba.invWorldInertia(), joint.m_rpos[0],
1479 bb.invMass(), bb.invWorldInertia(), joint.m_rpos[1]);
1489 struct CollideCL_RS : ClusterBase
1492 const btCollisionObjectWrapper* m_colObjWrap;
1494 void Process(const btDbvtNode* leaf)
1496 btSoftBody::Cluster* cluster = (btSoftBody::Cluster*)leaf->data;
1497 btSoftClusterCollisionShape cshape(cluster);
1499 const btConvexShape* rshape = (const btConvexShape*)m_colObjWrap->getCollisionShape();
1501 ///don't collide an anchored cluster with a static/kinematic object
1502 if (m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor)
1505 btGjkEpaSolver2::sResults res;
1506 if (btGjkEpaSolver2::SignedDistance(&cshape, btTransform::getIdentity(),
1507 rshape, m_colObjWrap->getWorldTransform(),
1508 btVector3(1, 0, 0), res))
1510 btSoftBody::CJoint joint;
1511 if (SolveContact(res, cluster, m_colObjWrap->getCollisionObject(), joint)) //prb,joint))
1513 btSoftBody::CJoint* pj = new (btAlignedAlloc(sizeof(btSoftBody::CJoint), 16)) btSoftBody::CJoint();
1515 psb->m_joints.push_back(pj);
1516 if (m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject())
1518 pj->m_erp *= psb->m_cfg.kSKHR_CL;
1519 pj->m_split *= psb->m_cfg.kSK_SPLT_CL;
1523 pj->m_erp *= psb->m_cfg.kSRHR_CL;
1524 pj->m_split *= psb->m_cfg.kSR_SPLT_CL;
1529 void ProcessColObj(btSoftBody* ps, const btCollisionObjectWrapper* colObWrap)
1532 m_colObjWrap = colObWrap;
1533 idt = ps->m_sst.isdt;
1534 m_margin = m_colObjWrap->getCollisionShape()->getMargin() + psb->getCollisionShape()->getMargin();
1535 ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful.
1536 friction = btMin(psb->m_cfg.kDF, m_colObjWrap->getCollisionObject()->getFriction());
1540 ATTRIBUTE_ALIGNED16(btDbvtVolume)
1542 colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(), mins, maxs);
1543 volume = btDbvtVolume::FromMM(mins, maxs);
1544 volume.Expand(btVector3(1, 1, 1) * m_margin);
1545 ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root, volume, *this);
1551 struct CollideCL_SS : ClusterBase
1553 btSoftBody* bodies[2];
1554 void Process(const btDbvtNode* la, const btDbvtNode* lb)
1556 btSoftBody::Cluster* cla = (btSoftBody::Cluster*)la->data;
1557 btSoftBody::Cluster* clb = (btSoftBody::Cluster*)lb->data;
1559 bool connected = false;
1560 if ((bodies[0] == bodies[1]) && (bodies[0]->m_clusterConnectivity.size()))
1562 connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex + bodies[0]->m_clusters.size() * clb->m_clusterIndex];
1567 btSoftClusterCollisionShape csa(cla);
1568 btSoftClusterCollisionShape csb(clb);
1569 btGjkEpaSolver2::sResults res;
1570 if (btGjkEpaSolver2::SignedDistance(&csa, btTransform::getIdentity(),
1571 &csb, btTransform::getIdentity(),
1572 cla->m_com - clb->m_com, res))
1574 btSoftBody::CJoint joint;
1575 if (SolveContact(res, cla, clb, joint))
1577 btSoftBody::CJoint* pj = new (btAlignedAlloc(sizeof(btSoftBody::CJoint), 16)) btSoftBody::CJoint();
1579 bodies[0]->m_joints.push_back(pj);
1580 pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL, bodies[1]->m_cfg.kSSHR_CL);
1581 pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL + bodies[1]->m_cfg.kSS_SPLT_CL) / 2;
1587 static int count = 0;
1589 //printf("count=%d\n",count);
1592 void ProcessSoftSoft(btSoftBody* psa, btSoftBody* psb)
1594 idt = psa->m_sst.isdt;
1595 //m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
1596 m_margin = (psa->getCollisionShape()->getMargin() + psb->getCollisionShape()->getMargin());
1597 friction = btMin(psa->m_cfg.kDF, psb->m_cfg.kDF);
1600 psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root, psb->m_cdbvt.m_root, *this);
1606 struct CollideSDF_RS : btDbvt::ICollide
1608 void Process(const btDbvtNode* leaf)
1610 btSoftBody::Node* node = (btSoftBody::Node*)leaf->data;
1613 void DoNode(btSoftBody::Node& n) const
1615 const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
1616 btSoftBody::RContact c;
1618 if ((!n.m_battach) &&
1619 psb->checkContact(m_colObj1Wrap, n.m_x, m, c.m_cti))
1621 const btScalar ima = n.m_im;
1622 const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
1623 const btScalar ms = ima + imb;
1626 const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
1627 static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
1628 const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
1629 const btVector3 ra = n.m_x - wtr.getOrigin();
1630 const btVector3 va = m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra) * psb->m_sst.sdt : btVector3(0, 0, 0);
1631 const btVector3 vb = n.m_x - n.m_q;
1632 const btVector3 vr = vb - va;
1633 const btScalar dn = btDot(vr, c.m_cti.m_normal);
1634 const btVector3 fv = vr - c.m_cti.m_normal * dn;
1635 const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
1637 c.m_c0 = ImpulseMatrix(psb->m_sst.sdt, ima, imb, iwi, ra);
1639 c.m_c2 = ima * psb->m_sst.sdt;
1640 c.m_c3 = fv.length2() < (dn * fc * dn * fc) ? 0 : 1 - fc;
1641 c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
1642 psb->m_rcontacts.push_back(c);
1644 m_rigidBody->activate();
1649 const btCollisionObjectWrapper* m_colObj1Wrap;
1650 btRigidBody* m_rigidBody;
1658 struct CollideSDF_RD : btDbvt::ICollide
1660 void Process(const btDbvtNode* leaf)
1662 btSoftBody::Node* node = (btSoftBody::Node*)leaf->data;
1665 void DoNode(btSoftBody::Node& n) const
1667 const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
1668 btSoftBody::DeformableNodeRigidContact c;
1672 // check for collision at x_{n+1}^*
1673 if (psb->checkDeformableContact(m_colObj1Wrap, n.m_q, m, c.m_cti, /*predict = */ true))
1675 const btScalar ima = n.m_im;
1676 // todo: collision between multibody and fixed deformable node will be missed.
1677 const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
1678 const btScalar ms = ima + imb;
1681 // resolve contact at x_n
1682 psb->checkDeformableContact(m_colObj1Wrap, n.m_x, m, c.m_cti, /*predict = */ false);
1683 btSoftBody::sCti& cti = c.m_cti;
1685 const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
1688 c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
1689 c.m_c5 = n.m_effectiveMass_inv;
1691 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
1693 const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
1694 const btVector3 ra = n.m_x - wtr.getOrigin();
1696 static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
1697 const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
1698 if (psb->m_reducedModel)
1700 c.m_c0 = MassMatrix(imb, iwi, ra); //impulse factor K of the rigid body only (not the inverse)
1704 c.m_c0 = ImpulseMatrix(1, n.m_effectiveMass_inv, imb, iwi, ra);
1705 // c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
1709 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
1711 btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
1712 if (multibodyLinkCol)
1714 btVector3 normal = cti.m_normal;
1715 btVector3 t1 = generateUnitOrthogonalVector(normal);
1716 btVector3 t2 = btCross(normal, t1);
1717 btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
1718 findJacobian(multibodyLinkCol, jacobianData_normal, c.m_node->m_x, normal);
1719 findJacobian(multibodyLinkCol, jacobianData_t1, c.m_node->m_x, t1);
1720 findJacobian(multibodyLinkCol, jacobianData_t2, c.m_node->m_x, t2);
1722 btScalar* J_n = &jacobianData_normal.m_jacobians[0];
1723 btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
1724 btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
1726 btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
1727 btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
1728 btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
1730 btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
1731 t1.getX(), t1.getY(), t1.getZ(),
1732 t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
1733 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
1735 btMatrix3x3 local_impulse_matrix;
1736 if (psb->m_reducedModel)
1738 local_impulse_matrix = OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof);
1742 local_impulse_matrix = (n.m_effectiveMass_inv + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
1744 c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
1745 c.jacobianData_normal = jacobianData_normal;
1746 c.jacobianData_t1 = jacobianData_t1;
1747 c.jacobianData_t2 = jacobianData_t2;
1752 psb->m_nodeRigidContacts.push_back(c);
1758 const btCollisionObjectWrapper* m_colObj1Wrap;
1759 btRigidBody* m_rigidBody;
1767 struct CollideSDF_RDF : btDbvt::ICollide
1769 void Process(const btDbvtNode* leaf)
1771 btSoftBody::Face* face = (btSoftBody::Face*)leaf->data;
1774 void DoNode(btSoftBody::Face& f) const
1776 btSoftBody::Node* n0 = f.m_n[0];
1777 btSoftBody::Node* n1 = f.m_n[1];
1778 btSoftBody::Node* n2 = f.m_n[2];
1779 const btScalar m = (n0->m_im > 0 && n1->m_im > 0 && n2->m_im > 0) ? dynmargin : stamargin;
1780 btSoftBody::DeformableFaceRigidContact c;
1781 btVector3 contact_point;
1783 if (psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, true))
1785 btScalar ima = n0->m_im + n1->m_im + n2->m_im;
1786 const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
1787 // todo: collision between multibody and fixed deformable face will be missed.
1788 const btScalar ms = ima + imb;
1791 // resolve contact at x_n
1792 // psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, /*predict = */ false);
1793 btSoftBody::sCti& cti = c.m_cti;
1794 c.m_contactPoint = contact_point;
1796 // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
1797 c.m_weights = btScalar(2) / (btScalar(1) + bary.length2()) * bary;
1799 // friction is handled by the nodes to prevent sticking
1800 // const btScalar fc = 0;
1801 const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
1803 // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
1804 ima = bary.getX() * c.m_weights.getX() * n0->m_im + bary.getY() * c.m_weights.getY() * n1->m_im + bary.getZ() * c.m_weights.getZ() * n2->m_im;
1807 c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
1808 c.m_c5 = Diagonal(ima);
1809 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
1811 const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
1812 static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
1813 const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
1814 const btVector3 ra = contact_point - wtr.getOrigin();
1816 // we do not scale the impulse matrix by dt
1817 c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
1820 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
1822 btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
1823 if (multibodyLinkCol)
1825 btVector3 normal = cti.m_normal;
1826 btVector3 t1 = generateUnitOrthogonalVector(normal);
1827 btVector3 t2 = btCross(normal, t1);
1828 btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
1829 findJacobian(multibodyLinkCol, jacobianData_normal, contact_point, normal);
1830 findJacobian(multibodyLinkCol, jacobianData_t1, contact_point, t1);
1831 findJacobian(multibodyLinkCol, jacobianData_t2, contact_point, t2);
1833 btScalar* J_n = &jacobianData_normal.m_jacobians[0];
1834 btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
1835 btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
1837 btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
1838 btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
1839 btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
1841 btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
1842 t1.getX(), t1.getY(), t1.getZ(),
1843 t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
1844 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
1845 btMatrix3x3 local_impulse_matrix = (Diagonal(ima) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
1846 c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
1847 c.jacobianData_normal = jacobianData_normal;
1848 c.jacobianData_t1 = jacobianData_t1;
1849 c.jacobianData_t2 = jacobianData_t2;
1854 psb->m_faceRigidContacts.push_back(c);
1857 // Set caching barycenters to be false after collision detection.
1858 // Only turn on when contact is static.
1859 f.m_pcontact[3] = 0;
1862 const btCollisionObjectWrapper* m_colObj1Wrap;
1863 btRigidBody* m_rigidBody;
1871 struct CollideVF_SS : btDbvt::ICollide
1873 void Process(const btDbvtNode* lnode,
1874 const btDbvtNode* lface)
1876 btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
1877 btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
1878 for (int i = 0; i < 3; ++i)
1880 if (face->m_n[i] == node)
1884 btVector3 o = node->m_x;
1886 btScalar d = SIMD_INFINITY;
1887 ProjectOrigin(face->m_n[0]->m_x - o,
1888 face->m_n[1]->m_x - o,
1889 face->m_n[2]->m_x - o,
1891 const btScalar m = mrg + (o - node->m_q).length() * 2;
1894 const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
1895 const btVector3 w = BaryCoord(n[0]->m_x, n[1]->m_x, n[2]->m_x, p + o);
1896 const btScalar ma = node->m_im;
1897 btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
1898 if ((n[0]->m_im <= 0) ||
1899 (n[1]->m_im <= 0) ||
1904 const btScalar ms = ma + mb;
1907 btSoftBody::SContact c;
1908 c.m_normal = p / -btSqrt(d);
1913 c.m_friction = btMax(psb[0]->m_cfg.kDF, psb[1]->m_cfg.kDF);
1914 c.m_cfm[0] = ma / ms * psb[0]->m_cfg.kSHR;
1915 c.m_cfm[1] = mb / ms * psb[1]->m_cfg.kSHR;
1916 psb[0]->m_scontacts.push_back(c);
1927 struct CollideVF_DD : btDbvt::ICollide
1929 void Process(const btDbvtNode* lnode,
1930 const btDbvtNode* lface)
1932 btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
1933 btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
1935 if (proximityTest(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, node->m_x, face->m_normal, mrg, bary))
1937 const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
1938 const btVector3 w = bary;
1939 const btScalar ma = node->m_im;
1940 btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
1941 if ((n[0]->m_im <= 0) ||
1942 (n[1]->m_im <= 0) ||
1947 const btScalar ms = ma + mb;
1950 btSoftBody::DeformableFaceNodeContact c;
1951 c.m_normal = face->m_normal;
1952 if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
1953 c.m_normal = -face->m_normal;
1958 c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
1959 // Initialize unused fields.
1960 c.m_weights = btVector3(0, 0, 0);
1963 c.m_colObj = psb[1];
1964 psb[0]->m_faceNodeContacts.push_back(c);
1976 struct CollideFF_DD : btDbvt::ICollide
1978 void Process(const btDbvntNode* lface1,
1979 const btDbvntNode* lface2)
1981 btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
1982 btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
1989 void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
1991 //#define REPEL_NEIGHBOR 1
1992 #ifndef REPEL_NEIGHBOR
1993 for (int node_id = 0; node_id < 3; ++node_id)
1995 btSoftBody::Node* node = f1->m_n[node_id];
1996 for (int i = 0; i < 3; ++i)
1998 if (f2->m_n[i] == node)
2004 for (int node_id = 0; node_id < 3; ++node_id)
2006 btSoftBody::Node* node = f1->m_n[node_id];
2007 #ifdef REPEL_NEIGHBOR
2008 for (int i = 0; i < 3; ++i)
2010 if (f2->m_n[i] == node)
2022 btSoftBody::Face* face = f2;
2024 if (!proximityTest(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, node->m_x, face->m_normal, mrg, bary))
2026 btSoftBody::DeformableFaceNodeContact c;
2027 c.m_normal = face->m_normal;
2028 if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
2029 c.m_normal = -face->m_normal;
2034 c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
2035 // Initialize unused fields.
2036 c.m_weights = btVector3(0, 0, 0);
2039 c.m_colObj = psb[1];
2040 psb[0]->m_faceNodeContacts.push_back(c);
2048 struct CollideCCD : btDbvt::ICollide
2050 void Process(const btDbvtNode* lnode,
2051 const btDbvtNode* lface)
2053 btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
2054 btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
2056 if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
2058 btSoftBody::DeformableFaceNodeContact c;
2059 c.m_normal = face->m_normal;
2060 if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
2061 c.m_normal = -face->m_normal;
2065 c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
2066 // Initialize unused fields.
2067 c.m_weights = btVector3(0, 0, 0);
2071 c.m_colObj = psb[1];
2072 psb[0]->m_faceNodeContactsCCD.push_back(c);
2075 void Process(const btDbvntNode* lface1,
2076 const btDbvntNode* lface2)
2078 btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
2079 btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
2086 void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
2088 //#define REPEL_NEIGHBOR 1
2089 #ifndef REPEL_NEIGHBOR
2090 for (int node_id = 0; node_id < 3; ++node_id)
2092 btSoftBody::Node* node = f1->m_n[node_id];
2093 for (int i = 0; i < 3; ++i)
2095 if (f2->m_n[i] == node)
2101 for (int node_id = 0; node_id < 3; ++node_id)
2103 btSoftBody::Node* node = f1->m_n[node_id];
2104 #ifdef REPEL_NEIGHBOR
2105 for (int i = 0; i < 3; ++i)
2107 if (f2->m_n[i] == node)
2119 btSoftBody::Face* face = f2;
2121 if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
2123 btSoftBody::DeformableFaceNodeContact c;
2124 c.m_normal = face->m_normal;
2125 if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
2126 c.m_normal = -face->m_normal;
2130 c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
2131 // Initialize unused fields.
2132 c.m_weights = btVector3(0, 0, 0);
2136 c.m_colObj = psb[1];
2137 psb[0]->m_faceNodeContactsCCD.push_back(c);
2146 #endif //_BT_SOFT_BODY_INTERNALS_H