Browse Source

Update to bullet master (2.90)

PouleyKetchoupp 5 years ago
parent
commit
3e7db60d56
56 changed files with 4401 additions and 856 deletions
  1. 1 0
      modules/bullet/SCsub
  2. 5 3
      platform/linuxbsd/detect.py
  3. 4 1
      thirdparty/README.md
  4. 1 1
      thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
  5. 10 1
      thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
  6. 2 2
      thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
  7. 4 2
      thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
  8. 14 8
      thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
  9. 1 0
      thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
  10. 6 1
      thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
  11. 4 2
      thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
  12. 4 1
      thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
  13. 1 0
      thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
  14. 8 4
      thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
  15. 8 0
      thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
  16. 13 6
      thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
  17. 42 1
      thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
  18. 2 0
      thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
  19. 0 46
      thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
  20. 0 7
      thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
  21. 18 13
      thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
  22. 188 0
      thirdparty/bullet/BulletSoftBody/btConjugateResidual.h
  23. 36 6
      thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp
  24. 41 2
      thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h
  25. 39 39
      thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp
  26. 7 9
      thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h
  27. 84 100
      thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp
  28. 48 84
      thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h
  29. 383 258
      thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp
  30. 28 18
      thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h
  31. 2 0
      thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h
  32. 2 0
      thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h
  33. 10 1
      thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h
  34. 46 0
      thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h
  35. 145 0
      thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h
  36. 4 4
      thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp
  37. 171 16
      thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp
  38. 151 5
      thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h
  39. 48 2
      thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h
  40. 211 2
      thirdparty/bullet/BulletSoftBody/btPreconditioner.h
  41. 524 112
      thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
  42. 223 21
      thirdparty/bullet/BulletSoftBody/btSoftBody.h
  43. 79 1
      thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
  44. 4 0
      thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
  45. 726 72
      thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
  46. 2 1
      thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
  47. 419 0
      thirdparty/bullet/BulletSoftBody/poly34.cpp
  48. 38 0
      thirdparty/bullet/BulletSoftBody/poly34.h
  49. 2 2
      thirdparty/bullet/LinearMath/btImplicitQRSVD.h
  50. 16 0
      thirdparty/bullet/LinearMath/btMatrix3x3.h
  51. 1 2
      thirdparty/bullet/LinearMath/btMatrixX.h
  52. 83 0
      thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h
  53. 170 0
      thirdparty/bullet/LinearMath/btReducedVector.cpp
  54. 320 0
      thirdparty/bullet/LinearMath/btReducedVector.h
  55. 1 0
      thirdparty/bullet/btBulletCollisionAll.cpp
  56. 1 0
      thirdparty/bullet/btLinearMathAll.cpp

+ 1 - 0
modules/bullet/SCsub

@@ -175,6 +175,7 @@ if env["builtin_bullet"]:
         "BulletSoftBody/btDeformableContactProjection.cpp",
         "BulletSoftBody/btDeformableContactProjection.cpp",
         "BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp",
         "BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp",
         "BulletSoftBody/btDeformableContactConstraint.cpp",
         "BulletSoftBody/btDeformableContactConstraint.cpp",
+        "BulletSoftBody/poly34.cpp",
         # clew
         # clew
         "clew/clew.c",
         "clew/clew.c",
         # LinearMath
         # LinearMath

+ 5 - 3
platform/linuxbsd/detect.py

@@ -217,15 +217,17 @@ def configure(env):
         env.ParseConfig("pkg-config libpng16 --cflags --libs")
         env.ParseConfig("pkg-config libpng16 --cflags --libs")
 
 
     if not env["builtin_bullet"]:
     if not env["builtin_bullet"]:
-        # We need at least version 2.89
+        # We need at least version 2.90
+        min_bullet_version = "2.90"
+
         import subprocess
         import subprocess
 
 
         bullet_version = subprocess.check_output(["pkg-config", "bullet", "--modversion"]).strip()
         bullet_version = subprocess.check_output(["pkg-config", "bullet", "--modversion"]).strip()
-        if str(bullet_version) < "2.89":
+        if str(bullet_version) < min_bullet_version:
             # Abort as system bullet was requested but too old
             # Abort as system bullet was requested but too old
             print(
             print(
                 "Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format(
                 "Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format(
-                    bullet_version, "2.89"
+                    bullet_version, min_bullet_version
                 )
                 )
             )
             )
             sys.exit(255)
             sys.exit(255)

+ 4 - 1
thirdparty/README.md

@@ -40,9 +40,12 @@ Files extracted from upstream source:
 ## bullet
 ## bullet
 
 
 - Upstream: https://github.com/bulletphysics/bullet3
 - Upstream: https://github.com/bulletphysics/bullet3
-- Version: 2.89
+- Version: 2.90 (master cd8cf7521cbb8b7808126a6adebd47bb83ea166a)
 - License: zlib
 - License: zlib
 
 
+Important: Synced with a pre-release version of bullet 2.90 from the master branch.
+Commit hash: cd8cf7521cbb8b7808126a6adebd47bb83ea166a
+
 Files extracted from upstream source:
 Files extracted from upstream source:
 
 
 - src/* apart from CMakeLists.txt and premake4.lua files
 - src/* apart from CMakeLists.txt and premake4.lua files

+ 1 - 1
thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h

@@ -203,8 +203,8 @@ struct btDbvntNode
 
 
     btDbvntNode(const btDbvtNode* n)
     btDbvntNode(const btDbvtNode* n)
     : volume(n->volume)
     : volume(n->volume)
-    , angle(0)
     , normal(0,0,0)
     , normal(0,0,0)
+    , angle(0)
     , data(n->data)
     , data(n->data)
     {
     {
         childs[0] = 0;
         childs[0] = 0;

+ 10 - 1
thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h

@@ -61,7 +61,8 @@ public:
 	virtual void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher) = 0;
 	virtual void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher) = 0;
 
 
 	virtual int getNumOverlappingPairs() const = 0;
 	virtual int getNumOverlappingPairs() const = 0;
-
+	virtual bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const = 0;
+	virtual btOverlapFilterCallback* getOverlapFilterCallback() = 0;
 	virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
 	virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
 
 
 	virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
 	virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
@@ -380,6 +381,14 @@ public:
 	{
 	{
 	}
 	}
 
 
+	bool needsBroadphaseCollision(btBroadphaseProxy*, btBroadphaseProxy*) const
+	{
+		return true;
+	}
+	btOverlapFilterCallback* getOverlapFilterCallback()
+	{
+		return 0;
+	}
 	virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
 	virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
 	{
 	{
 	}
 	}

+ 2 - 2
thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp

@@ -468,7 +468,7 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
 
 
 #ifdef RAYAABB2
 #ifdef RAYAABB2
 	btVector3 rayDir = (rayTarget - raySource);
 	btVector3 rayDir = (rayTarget - raySource);
-	rayDir.normalize();
+	rayDir.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
 	lambda_max = rayDir.dot(rayTarget - raySource);
 	lambda_max = rayDir.dot(rayTarget - raySource);
 	///what about division by zero? --> just set rayDirection[i] to 1.0
 	///what about division by zero? --> just set rayDirection[i] to 1.0
 	btVector3 rayDirectionInverse;
 	btVector3 rayDirectionInverse;
@@ -554,7 +554,7 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback*
 
 
 #ifdef RAYAABB2
 #ifdef RAYAABB2
 	btVector3 rayDirection = (rayTarget - raySource);
 	btVector3 rayDirection = (rayTarget - raySource);
-	rayDirection.normalize();
+	rayDirection.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
 	lambda_max = rayDirection.dot(rayTarget - raySource);
 	lambda_max = rayDirection.dot(rayTarget - raySource);
 	///what about division by zero? --> just set rayDirection[i] to 1.0
 	///what about division by zero? --> just set rayDirection[i] to 1.0
 	rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
 	rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];

+ 4 - 2
thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h

@@ -46,8 +46,6 @@ protected:
 
 
 	btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
 	btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
 
 
-	btManifoldResult m_defaultManifoldResult;
-
 	btNearCallback m_nearCallback;
 	btNearCallback m_nearCallback;
 
 
 	btPoolAllocator* m_collisionAlgorithmPoolAllocator;
 	btPoolAllocator* m_collisionAlgorithmPoolAllocator;
@@ -95,11 +93,15 @@ public:
 
 
 	btPersistentManifold* getManifoldByIndexInternal(int index)
 	btPersistentManifold* getManifoldByIndexInternal(int index)
 	{
 	{
+		btAssert(index>=0);
+		btAssert(index<m_manifoldsPtr.size());
 		return m_manifoldsPtr[index];
 		return m_manifoldsPtr[index];
 	}
 	}
 
 
 	const btPersistentManifold* getManifoldByIndexInternal(int index) const
 	const btPersistentManifold* getManifoldByIndexInternal(int index) const
 	{
 	{
+		btAssert(index>=0);
+		btAssert(index<m_manifoldsPtr.size());
 		return m_manifoldsPtr[index];
 		return m_manifoldsPtr[index];
 	}
 	}
 
 

+ 14 - 8
thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp

@@ -28,6 +28,7 @@ subject to the following restrictions:
 btCollisionDispatcherMt::btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize)
 btCollisionDispatcherMt::btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize)
 	: btCollisionDispatcher(config)
 	: btCollisionDispatcher(config)
 {
 {
+	m_batchManifoldsPtr.resize(btGetTaskScheduler()->getNumThreads());
 	m_batchUpdating = false;
 	m_batchUpdating = false;
 	m_grainSize = grainSize;  // iterations per task
 	m_grainSize = grainSize;  // iterations per task
 }
 }
@@ -65,6 +66,10 @@ btPersistentManifold* btCollisionDispatcherMt::getNewManifold(const btCollisionO
 		manifold->m_index1a = m_manifoldsPtr.size();
 		manifold->m_index1a = m_manifoldsPtr.size();
 		m_manifoldsPtr.push_back(manifold);
 		m_manifoldsPtr.push_back(manifold);
 	}
 	}
+	else
+	{
+		m_batchManifoldsPtr[btGetCurrentThreadIndex()].push_back(manifold);
+	}
 
 
 	return manifold;
 	return manifold;
 }
 }
@@ -121,7 +126,7 @@ struct CollisionDispatcherUpdater : public btIParallelForBody
 
 
 void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher)
 void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher)
 {
 {
-	int pairCount = pairCache->getNumOverlappingPairs();
+	const int pairCount = pairCache->getNumOverlappingPairs();
 	if (pairCount == 0)
 	if (pairCount == 0)
 	{
 	{
 		return;
 		return;
@@ -136,16 +141,17 @@ void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache*
 	btParallelFor(0, pairCount, m_grainSize, updater);
 	btParallelFor(0, pairCount, m_grainSize, updater);
 	m_batchUpdating = false;
 	m_batchUpdating = false;
 
 
-	// reconstruct the manifolds array to ensure determinism
-	m_manifoldsPtr.resizeNoInitialize(0);
-
-	btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
-	for (int i = 0; i < pairCount; ++i)
+	// merge new manifolds, if any
+	for (int i = 0; i < m_batchManifoldsPtr.size(); ++i)
 	{
 	{
-		if (btCollisionAlgorithm* algo = pairs[i].m_algorithm)
+		btAlignedObjectArray<btPersistentManifold*>& batchManifoldsPtr = m_batchManifoldsPtr[i];
+
+		for (int j = 0; j < batchManifoldsPtr.size(); ++j)
 		{
 		{
-			algo->getAllContactManifolds(m_manifoldsPtr);
+			m_manifoldsPtr.push_back(batchManifoldsPtr[j]);
 		}
 		}
+
+		batchManifoldsPtr.resizeNoInitialize(0);
 	}
 	}
 
 
 	// update the indices (used when releasing manifolds)
 	// update the indices (used when releasing manifolds)

+ 1 - 0
thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h

@@ -30,6 +30,7 @@ public:
 	virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher) BT_OVERRIDE;
 	virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher) BT_OVERRIDE;
 
 
 protected:
 protected:
+	btAlignedObjectArray<btAlignedObjectArray<btPersistentManifold*> > m_batchManifoldsPtr;
 	bool m_batchUpdating;
 	bool m_batchUpdating;
 	int m_grainSize;
 	int m_grainSize;
 };
 };

+ 6 - 1
thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp

@@ -139,7 +139,12 @@ public:
 
 
 		if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
 		if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
 		{
 		{
-			btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, childTrans, -1, index);
+			btTransform preTransform = childTrans;
+			if (this->m_compoundColObjWrap->m_preTransform)
+			{
+				preTransform = preTransform *(*(this->m_compoundColObjWrap->m_preTransform));
+			}
+			btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, preTransform, -1, index);
 
 
 			btCollisionAlgorithm* algo = 0;
 			btCollisionAlgorithm* algo = 0;
 			bool allocatedAlgorithm = false;
 			bool allocatedAlgorithm = false;

+ 4 - 2
thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h

@@ -46,7 +46,7 @@ struct btContactSolverInfoData
 	btScalar m_sor;          //successive over-relaxation term
 	btScalar m_sor;          //successive over-relaxation term
 	btScalar m_erp;          //error reduction for non-contact constraints
 	btScalar m_erp;          //error reduction for non-contact constraints
 	btScalar m_erp2;         //error reduction for contact constraints
 	btScalar m_erp2;         //error reduction for contact constraints
-    btScalar m_deformable_erp;          //error reduction for deformable constraints
+	btScalar m_deformable_erp;          //error reduction for deformable constraints
 	btScalar m_globalCfm;    //constraint force mixing for contacts and non-contacts
 	btScalar m_globalCfm;    //constraint force mixing for contacts and non-contacts
 	btScalar m_frictionERP;  //error reduction for friction constraints
 	btScalar m_frictionERP;  //error reduction for friction constraints
 	btScalar m_frictionCFM;  //constraint force mixing for friction constraints
 	btScalar m_frictionCFM;  //constraint force mixing for friction constraints
@@ -67,6 +67,7 @@ struct btContactSolverInfoData
 	bool m_jointFeedbackInWorldSpace;
 	bool m_jointFeedbackInWorldSpace;
 	bool m_jointFeedbackInJointFrame;
 	bool m_jointFeedbackInJointFrame;
 	int m_reportSolverAnalytics;
 	int m_reportSolverAnalytics;
+	int m_numNonContactInnerIterations;
 };
 };
 
 
 struct btContactSolverInfo : public btContactSolverInfoData
 struct btContactSolverInfo : public btContactSolverInfoData
@@ -82,7 +83,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
 		m_numIterations = 10;
 		m_numIterations = 10;
 		m_erp = btScalar(0.2);
 		m_erp = btScalar(0.2);
 		m_erp2 = btScalar(0.2);
 		m_erp2 = btScalar(0.2);
-        m_deformable_erp = btScalar(0.);
+		m_deformable_erp = btScalar(0.1);
 		m_globalCfm = btScalar(0.);
 		m_globalCfm = btScalar(0.);
 		m_frictionERP = btScalar(0.2);  //positional friction 'anchors' are disabled by default
 		m_frictionERP = btScalar(0.2);  //positional friction 'anchors' are disabled by default
 		m_frictionCFM = btScalar(0.);
 		m_frictionCFM = btScalar(0.);
@@ -104,6 +105,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
 		m_jointFeedbackInWorldSpace = false;
 		m_jointFeedbackInWorldSpace = false;
 		m_jointFeedbackInJointFrame = false;
 		m_jointFeedbackInJointFrame = false;
 		m_reportSolverAnalytics = 0;
 		m_reportSolverAnalytics = 0;
+		m_numNonContactInnerIterations = 1;   // the number of inner iterations for solving motor constraint in a single iteration of the constraint solve
 	}
 	}
 };
 };
 
 

+ 4 - 1
thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp

@@ -876,7 +876,10 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
 		// will we not request a velocity with the wrong direction ?
 		// will we not request a velocity with the wrong direction ?
 		// and the answer is not, because in practice during the solving the current velocity is subtracted from the m_constraintError
 		// and the answer is not, because in practice during the solving the current velocity is subtracted from the m_constraintError
 		// so the sign of the force that is really matters
 		// so the sign of the force that is really matters
-		info->m_constraintError[srow] = (rotational ? -1 : 1) * (f < 0 ? -SIMD_INFINITY : SIMD_INFINITY);
+		if (m_flags & BT_6DOF_FLAGS_USE_INFINITE_ERROR)
+			info->m_constraintError[srow] = (rotational ? -1 : 1) * (f < 0 ? -SIMD_INFINITY : SIMD_INFINITY);
+		else
+			info->m_constraintError[srow] = vel + f / m * (rotational ? -1 : 1);
 
 
 		btScalar minf = f < fd ? f : fd;
 		btScalar minf = f < fd ? f : fd;
 		btScalar maxf = f < fd ? fd : f;
 		btScalar maxf = f < fd ? fd : f;

+ 1 - 0
thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h

@@ -265,6 +265,7 @@ enum bt6DofFlags2
 	BT_6DOF_FLAGS_ERP_STOP2 = 2,
 	BT_6DOF_FLAGS_ERP_STOP2 = 2,
 	BT_6DOF_FLAGS_CFM_MOTO2 = 4,
 	BT_6DOF_FLAGS_CFM_MOTO2 = 4,
 	BT_6DOF_FLAGS_ERP_MOTO2 = 8,
 	BT_6DOF_FLAGS_ERP_MOTO2 = 8,
+	BT_6DOF_FLAGS_USE_INFINITE_ERROR = (1<<16)
 };
 };
 #define BT_6DOF_FLAGS_AXIS_SHIFT2 4  // bits per axis
 #define BT_6DOF_FLAGS_AXIS_SHIFT2 4  // bits per axis
 
 

+ 8 - 4
thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp

@@ -14,7 +14,9 @@ subject to the following restrictions:
 */
 */
 
 
 //#define COMPUTE_IMPULSE_DENOM 1
 //#define COMPUTE_IMPULSE_DENOM 1
-//#define BT_ADDITIONAL_DEBUG
+#ifdef BT_DEBUG
+#	define BT_ADDITIONAL_DEBUG
+#endif
 
 
 //It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
 //It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
 
 
@@ -690,8 +692,10 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
 {
 {
 #if BT_THREADSAFE
 #if BT_THREADSAFE
 	int solverBodyId = -1;
 	int solverBodyId = -1;
-	bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
-	if (isRigidBodyType && !body.isStaticOrKinematicObject())
+	const bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
+	const bool isStaticOrKinematic = body.isStaticOrKinematicObject();
+	const bool isKinematic = body.isKinematicObject();
+	if (isRigidBodyType && !isStaticOrKinematic)
 	{
 	{
 		// dynamic body
 		// dynamic body
 		// Dynamic bodies can only be in one island, so it's safe to write to the companionId
 		// Dynamic bodies can only be in one island, so it's safe to write to the companionId
@@ -704,7 +708,7 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
 			body.setCompanionId(solverBodyId);
 			body.setCompanionId(solverBodyId);
 		}
 		}
 	}
 	}
-	else if (isRigidBodyType && body.isKinematicObject())
+	else if (isRigidBodyType && isKinematic)
 	{
 	{
 		//
 		//
 		// NOTE: must test for kinematic before static because some kinematic objects also
 		// NOTE: must test for kinematic before static because some kinematic objects also

+ 8 - 0
thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp

@@ -800,6 +800,14 @@ public:
 		///don't do CCD when the collision filters are not matching
 		///don't do CCD when the collision filters are not matching
 		if (!ClosestConvexResultCallback::needsCollision(proxy0))
 		if (!ClosestConvexResultCallback::needsCollision(proxy0))
 			return false;
 			return false;
+		if (m_pairCache->getOverlapFilterCallback()) {
+			btBroadphaseProxy* proxy1 = m_me->getBroadphaseHandle();
+			bool collides = m_pairCache->needsBroadphaseCollision(proxy0, proxy1);
+			if (!collides)
+			{
+				return false;
+			}
+		}
 
 
 		btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
 		btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
 
 

+ 13 - 6
thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp

@@ -136,8 +136,13 @@ void btRigidBody::setGravity(const btVector3& acceleration)
 
 
 void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
 void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
 {
 {
-	m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
-	m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#ifdef BT_USE_OLD_DAMPING_METHOD
+	m_linearDamping = btMax(lin_damping, btScalar(0.0));
+	m_angularDamping = btMax(ang_damping, btScalar(0.0));
+#else
+	m_linearDamping = btClamped(lin_damping, btScalar(0.0), btScalar(1.0));
+	m_angularDamping = btClamped(ang_damping, btScalar(0.0), btScalar(1.0));
+#endif
 }
 }
 
 
 ///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
 ///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
@@ -146,10 +151,9 @@ void btRigidBody::applyDamping(btScalar timeStep)
 	//On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
 	//On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
 	//todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
 	//todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
 
 
-//#define USE_OLD_DAMPING_METHOD 1
-#ifdef USE_OLD_DAMPING_METHOD
-	m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
-	m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#ifdef BT_USE_OLD_DAMPING_METHOD
+	m_linearVelocity *= btMax((btScalar(1.0) - timeStep * m_linearDamping), btScalar(0.0));
+	m_angularVelocity *= btMax((btScalar(1.0) - timeStep * m_angularDamping), btScalar(0.0));
 #else
 #else
 	m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
 	m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
 	m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);
 	m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);
@@ -380,6 +384,9 @@ void btRigidBody::integrateVelocities(btScalar step)
 	{
 	{
 		m_angularVelocity *= (MAX_ANGVEL / step) / angvel;
 		m_angularVelocity *= (MAX_ANGVEL / step) / angvel;
 	}
 	}
+	#if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+	clampVelocity(m_angularVelocity);
+	#endif
 }
 }
 
 
 btQuaternion btRigidBody::getOrientation() const
 btQuaternion btRigidBody::getOrientation() const

+ 42 - 1
thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h

@@ -305,6 +305,9 @@ public:
 	void applyTorque(const btVector3& torque)
 	void applyTorque(const btVector3& torque)
 	{
 	{
 		m_totalTorque += torque * m_angularFactor;
 		m_totalTorque += torque * m_angularFactor;
+		#if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+		clampVelocity(m_totalTorque);
+		#endif
 	}
 	}
 
 
 	void applyForce(const btVector3& force, const btVector3& rel_pos)
 	void applyForce(const btVector3& force, const btVector3& rel_pos)
@@ -316,11 +319,17 @@ public:
 	void applyCentralImpulse(const btVector3& impulse)
 	void applyCentralImpulse(const btVector3& impulse)
 	{
 	{
 		m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
 		m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
+		#if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+		clampVelocity(m_linearVelocity);
+		#endif
 	}
 	}
 
 
 	void applyTorqueImpulse(const btVector3& torque)
 	void applyTorqueImpulse(const btVector3& torque)
 	{
 	{
 		m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
 		m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+		#if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+		clampVelocity(m_angularVelocity);
+		#endif
 	}
 	}
 
 
 	void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
 	void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
@@ -361,20 +370,46 @@ public:
     {
     {
         m_pushVelocity = v;
         m_pushVelocity = v;
     }
     }
-    
+
+    #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+    void clampVelocity(btVector3& v) const {
+        v.setX(
+            fmax(-BT_CLAMP_VELOCITY_TO,
+                 fmin(BT_CLAMP_VELOCITY_TO, v.getX()))
+        );
+        v.setY(
+            fmax(-BT_CLAMP_VELOCITY_TO,
+                 fmin(BT_CLAMP_VELOCITY_TO, v.getY()))
+        );
+        v.setZ(
+            fmax(-BT_CLAMP_VELOCITY_TO,
+                 fmin(BT_CLAMP_VELOCITY_TO, v.getZ()))
+        );
+    }
+    #endif
+
     void setTurnVelocity(const btVector3& v)
     void setTurnVelocity(const btVector3& v)
     {
     {
         m_turnVelocity = v;
         m_turnVelocity = v;
+        #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+        clampVelocity(m_turnVelocity);
+        #endif
     }
     }
     
     
     void applyCentralPushImpulse(const btVector3& impulse)
     void applyCentralPushImpulse(const btVector3& impulse)
     {
     {
         m_pushVelocity += impulse * m_linearFactor * m_inverseMass;
         m_pushVelocity += impulse * m_linearFactor * m_inverseMass;
+        #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+        clampVelocity(m_pushVelocity);
+        #endif
     }
     }
     
     
     void applyTorqueTurnImpulse(const btVector3& torque)
     void applyTorqueTurnImpulse(const btVector3& torque)
     {
     {
         m_turnVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
         m_turnVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+        #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+        clampVelocity(m_turnVelocity);
+        #endif
     }
     }
 
 
 	void clearForces()
 	void clearForces()
@@ -408,12 +443,18 @@ public:
 	{
 	{
 		m_updateRevision++;
 		m_updateRevision++;
 		m_linearVelocity = lin_vel;
 		m_linearVelocity = lin_vel;
+		#if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+		clampVelocity(m_linearVelocity);
+		#endif
 	}
 	}
 
 
 	inline void setAngularVelocity(const btVector3& ang_vel)
 	inline void setAngularVelocity(const btVector3& ang_vel)
 	{
 	{
 		m_updateRevision++;
 		m_updateRevision++;
 		m_angularVelocity = ang_vel;
 		m_angularVelocity = ang_vel;
+		#if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+		clampVelocity(m_angularVelocity);
+		#endif
 	}
 	}
 
 
 	btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
 	btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const

+ 2 - 0
thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp

@@ -171,6 +171,8 @@ void btSimulationIslandManagerMt::initIslandPools()
 
 
 btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland(int id)
 btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland(int id)
 {
 {
+	btAssert(id >= 0);
+	btAssert(id < m_lookupIslandFromId.size());
 	Island* island = m_lookupIslandFromId[id];
 	Island* island = m_lookupIslandFromId[id];
 	if (island == NULL)
 	if (island == NULL)
 	{
 	{

+ 0 - 46
thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp

@@ -583,52 +583,6 @@ void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
 	}
 	}
 }
 }
 
 
-btScalar btMultiBody::getKineticEnergy() const
-{
-	int num_links = getNumLinks();
-	// TODO: would be better not to allocate memory here
-	btAlignedObjectArray<btVector3> omega;
-	omega.resize(num_links + 1);
-	btAlignedObjectArray<btVector3> vel;
-	vel.resize(num_links + 1);
-	compTreeLinkVelocities(&omega[0], &vel[0]);
-
-	// we will do the factor of 0.5 at the end
-	btScalar result = m_baseMass * vel[0].dot(vel[0]);
-	result += omega[0].dot(m_baseInertia * omega[0]);
-
-	for (int i = 0; i < num_links; ++i)
-	{
-		result += m_links[i].m_mass * vel[i + 1].dot(vel[i + 1]);
-		result += omega[i + 1].dot(m_links[i].m_inertiaLocal * omega[i + 1]);
-	}
-
-	return 0.5f * result;
-}
-
-btVector3 btMultiBody::getAngularMomentum() const
-{
-	int num_links = getNumLinks();
-	// TODO: would be better not to allocate memory here
-	btAlignedObjectArray<btVector3> omega;
-	omega.resize(num_links + 1);
-	btAlignedObjectArray<btVector3> vel;
-	vel.resize(num_links + 1);
-	btAlignedObjectArray<btQuaternion> rot_from_world;
-	rot_from_world.resize(num_links + 1);
-	compTreeLinkVelocities(&omega[0], &vel[0]);
-
-	rot_from_world[0] = m_baseQuat;
-	btVector3 result = quatRotate(rot_from_world[0].inverse(), (m_baseInertia * omega[0]));
-
-	for (int i = 0; i < num_links; ++i)
-	{
-		rot_from_world[i + 1] = m_links[i].m_cachedRotParentToThis * rot_from_world[m_links[i].m_parent + 1];
-		result += (quatRotate(rot_from_world[i + 1].inverse(), (m_links[i].m_inertiaLocal * omega[i + 1])));
-	}
-
-	return result;
-}
 
 
 void btMultiBody::clearConstraintForces()
 void btMultiBody::clearConstraintForces()
 {
 {

+ 0 - 7
thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h

@@ -307,13 +307,6 @@ public:
 	//
 	//
 	btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &local_frame) const;
 	btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &local_frame) const;
 
 
-	//
-	// calculate kinetic energy and angular momentum
-	// useful for debugging.
-	//
-
-	btScalar getKineticEnergy() const;
-	btVector3 getAngularMomentum() const;
 
 
 	//
 	//
 	// set external forces and torques. Note all external forces/torques are given in the WORLD frame.
 	// set external forces and torques. Note all external forces/torques are given in the WORLD frame.

+ 18 - 13
thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp

@@ -30,23 +30,28 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl
 	btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
 	btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
 
 
 	//solve featherstone non-contact constraints
 	//solve featherstone non-contact constraints
-
+	btScalar nonContactResidual = 0;
 	//printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
 	//printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
-
-	for (int j = 0; j < m_multiBodyNonContactConstraints.size(); j++)
+	for (int i = 0; i < infoGlobal.m_numNonContactInnerIterations; ++i)
 	{
 	{
-		int index = iteration & 1 ? j : m_multiBodyNonContactConstraints.size() - 1 - j;
+		// reset the nonContactResdual to 0 at start of each inner iteration
+		nonContactResidual = 0;
+		for (int j = 0; j < m_multiBodyNonContactConstraints.size(); j++)
+		{
+			int index = iteration & 1 ? j : m_multiBodyNonContactConstraints.size() - 1 - j;
 
 
-		btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
+			btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
 
 
-		btScalar residual = resolveSingleConstraintRowGeneric(constraint);
-		leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+			btScalar residual = resolveSingleConstraintRowGeneric(constraint);
+			nonContactResidual = btMax(nonContactResidual, residual * residual);
 
 
-		if (constraint.m_multiBodyA)
-			constraint.m_multiBodyA->setPosUpdated(false);
-		if (constraint.m_multiBodyB)
-			constraint.m_multiBodyB->setPosUpdated(false);
+			if (constraint.m_multiBodyA)
+				constraint.m_multiBodyA->setPosUpdated(false);
+			if (constraint.m_multiBodyB)
+				constraint.m_multiBodyB->setPosUpdated(false);
+		}
 	}
 	}
+	leastSquaredResidual = btMax(leastSquaredResidual, nonContactResidual);
 
 
 	//solve featherstone normal contact
 	//solve featherstone normal contact
 	for (int j0 = 0; j0 < m_multiBodyNormalContactConstraints.size(); j0++)
 	for (int j0 = 0; j0 < m_multiBodyNormalContactConstraints.size(); j0++)
@@ -1250,7 +1255,7 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
 {
 {
 	const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
 	const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
 	const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
 	const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
+	
 	btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
 	btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
 	btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
 	btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
 
 
@@ -1270,7 +1275,7 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
 	//	return;
 	//	return;
 
 
 	//only a single rollingFriction per manifold
 	//only a single rollingFriction per manifold
-	int rollingFriction = 1;
+	int rollingFriction = 4;
 
 
 	for (int j = 0; j < manifold->getNumContacts(); j++)
 	for (int j = 0; j < manifold->getNumContacts(); j++)
 	{
 	{

+ 188 - 0
thirdparty/bullet/BulletSoftBody/btConjugateResidual.h

@@ -0,0 +1,188 @@
+/*
+ Written by Xuchen Han <[email protected]>
+ 
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 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.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_CONJUGATE_RESIDUAL_H
+#define BT_CONJUGATE_RESIDUAL_H
+#include <iostream>
+#include <cmath>
+#include <limits>
+#include <LinearMath/btAlignedObjectArray.h>
+#include <LinearMath/btVector3.h>
+#include <LinearMath/btScalar.h>
+#include "LinearMath/btQuickprof.h"
+template <class MatrixX>
+class btConjugateResidual
+{
+    typedef btAlignedObjectArray<btVector3> TVStack;
+    TVStack r,p,z,temp_p, temp_r, best_x;
+    // temp_r = A*r
+    // temp_p = A*p
+    // z = M^(-1) * temp_p = M^(-1) * A * p
+    int max_iterations;
+    btScalar tolerance_squared, best_r;
+public:
+    btConjugateResidual(const int max_it_in)
+    : max_iterations(max_it_in)
+    {
+        tolerance_squared = 1e-2;
+    }
+    
+    virtual ~btConjugateResidual(){}
+    
+    // return the number of iterations taken
+    int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false)
+    {
+        BT_PROFILE("CRSolve");
+        btAssert(x.size() == b.size());
+        reinitialize(b);
+        // r = b - A * x --with assigned dof zeroed out
+        A.multiply(x, temp_r); // borrow temp_r here to store A*x
+        r = sub(b, temp_r);
+        // z = M^(-1) * r
+        A.precondition(r, z);  // borrow z to store preconditioned r
+        r = z;
+        btScalar residual_norm = norm(r);
+        if (residual_norm <= tolerance_squared) {
+            if (verbose)
+            {
+                std::cout << "Iteration = 0" << std::endl;
+                std::cout << "Two norm of the residual = " << residual_norm << std::endl;
+            }
+            return 0;
+        }
+        p = r;
+        btScalar r_dot_Ar, r_dot_Ar_new;
+        // temp_p = A*p
+        A.multiply(p, temp_p);
+        // temp_r = A*r
+        temp_r = temp_p;
+        r_dot_Ar = dot(r, temp_r);
+        for (int k = 1; k <= max_iterations; k++) {
+            // z = M^(-1) * Ap
+            A.precondition(temp_p, z);
+            // alpha = r^T * A * r / (Ap)^T * M^-1 * Ap)
+            btScalar alpha = r_dot_Ar / dot(temp_p, z);
+            //  x += alpha * p;
+            multAndAddTo(alpha, p, x);
+            //  r -= alpha * z;
+            multAndAddTo(-alpha, z, r);
+            btScalar norm_r = norm(r);
+            if (norm_r < best_r)
+            {
+                best_x = x;
+                best_r = norm_r;
+                if (norm_r < tolerance_squared) {
+                    if (verbose)
+                    {
+                        std::cout << "ConjugateResidual iterations " << k << std::endl;
+                    }
+                    return k;
+                }
+                else
+                {
+                    if (verbose)
+                    {
+                        std::cout << "ConjugateResidual iterations " << k << " has residual "<< norm_r << std::endl;
+                    }
+                }
+            }
+            // temp_r = A * r;
+            A.multiply(r, temp_r);
+            r_dot_Ar_new = dot(r, temp_r);
+            btScalar beta = r_dot_Ar_new/r_dot_Ar;
+            r_dot_Ar = r_dot_Ar_new;
+            // p = beta*p + r;
+            p = multAndAdd(beta, p, r);
+            // temp_p = beta*temp_p + temp_r;
+            temp_p = multAndAdd(beta, temp_p, temp_r);
+        }
+        if (verbose)
+        {
+            std::cout << "ConjugateResidual max iterations reached " << max_iterations << std::endl;
+        }
+        x = best_x;
+        return max_iterations;
+    }
+    
+    void reinitialize(const TVStack& b)
+    {
+        r.resize(b.size());
+        p.resize(b.size());
+        z.resize(b.size());
+        temp_p.resize(b.size());
+        temp_r.resize(b.size());
+        best_x.resize(b.size());
+        best_r = SIMD_INFINITY;
+    }
+    
+    TVStack sub(const TVStack& a, const TVStack& b)
+    {
+        // c = a-b
+        btAssert(a.size() == b.size());
+        TVStack c;
+        c.resize(a.size());
+        for (int i = 0; i < a.size(); ++i)
+        {
+            c[i] = a[i] - b[i];
+        }
+        return c;
+    }
+    
+    btScalar squaredNorm(const TVStack& a)
+    {
+        return dot(a,a);
+    }
+    
+    btScalar norm(const TVStack& a)
+    {
+        btScalar ret = 0;
+        for (int i = 0; i < a.size(); ++i)
+        {
+            for (int d = 0; d < 3; ++d)
+            {
+                ret = btMax(ret, btFabs(a[i][d]));
+            }
+        }
+        return ret;
+    }
+    
+    btScalar dot(const TVStack& a, const TVStack& b)
+    {
+        btScalar ans(0);
+        for (int i = 0; i < a.size(); ++i)
+            ans += a[i].dot(b[i]);
+        return ans;
+    }
+    
+    void multAndAddTo(btScalar s, const TVStack& a, TVStack& result)
+    {
+        //        result += s*a
+        btAssert(a.size() == result.size());
+        for (int i = 0; i < a.size(); ++i)
+            result[i] += s * a[i];
+    }
+    
+    TVStack multAndAdd(btScalar s, const TVStack& a, const TVStack& b)
+    {
+        // result = a*s + b
+        TVStack result;
+        result.resize(a.size());
+        for (int i = 0; i < a.size(); ++i)
+            result[i] = s * a[i] + b[i];
+        return result;
+    }
+};
+#endif /* btConjugateResidual_h */
+

+ 36 - 6
thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp

@@ -23,12 +23,15 @@ btDeformableBackwardEulerObjective::btDeformableBackwardEulerObjective(btAligned
 , m_backupVelocity(backup_v)
 , m_backupVelocity(backup_v)
 , m_implicit(false)
 , m_implicit(false)
 {
 {
-    m_preconditioner = new MassPreconditioner(m_softBodies);
+    m_massPreconditioner = new MassPreconditioner(m_softBodies);
+    m_KKTPreconditioner = new KKTPreconditioner(m_softBodies, m_projection, m_lf, m_dt, m_implicit);
+    m_preconditioner = m_KKTPreconditioner;
 }
 }
 
 
 btDeformableBackwardEulerObjective::~btDeformableBackwardEulerObjective()
 btDeformableBackwardEulerObjective::~btDeformableBackwardEulerObjective()
 {
 {
-    delete m_preconditioner;
+    delete m_KKTPreconditioner;
+    delete m_massPreconditioner;
 }
 }
 
 
 void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar dt)
 void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar dt)
@@ -47,7 +50,7 @@ void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar
         m_lf[i]->reinitialize(nodeUpdated);
         m_lf[i]->reinitialize(nodeUpdated);
     }
     }
     m_projection.reinitialize(nodeUpdated);
     m_projection.reinitialize(nodeUpdated);
-    m_preconditioner->reinitialize(nodeUpdated);
+//    m_preconditioner->reinitialize(nodeUpdated);
 }
 }
 
 
 void btDeformableBackwardEulerObjective::setDt(btScalar dt)
 void btDeformableBackwardEulerObjective::setDt(btScalar dt)
@@ -80,6 +83,33 @@ void btDeformableBackwardEulerObjective::multiply(const TVStack& x, TVStack& b)
              m_lf[i]->addScaledElasticForceDifferential(-m_dt*m_dt, x, b);
              m_lf[i]->addScaledElasticForceDifferential(-m_dt*m_dt, x, b);
         }
         }
     }
     }
+    int offset = m_nodes.size();
+    for (int i = offset; i < b.size(); ++i)
+    {
+        b[i].setZero();
+    }
+    // add in the lagrange multiplier terms
+    
+    for (int c = 0; c < m_projection.m_lagrangeMultipliers.size(); ++c)
+    {
+        // C^T * lambda
+        const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[c];
+        for (int i = 0; i < lm.m_num_nodes; ++i)
+        {
+            for (int j = 0; j < lm.m_num_constraints; ++j)
+            {
+                b[lm.m_indices[i]] += x[offset+c][j] * lm.m_weights[i] * lm.m_dirs[j];
+            }
+        }
+        // C * x
+        for (int d = 0; d < lm.m_num_constraints; ++d)
+        {
+            for (int i = 0; i < lm.m_num_nodes; ++i)
+            {
+                b[offset+c][d] += lm.m_weights[i] * x[lm.m_indices[i]].dot(lm.m_dirs[d]);
+            }
+        }
+    }
 }
 }
 
 
 void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv)
 void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv)
@@ -134,7 +164,7 @@ void btDeformableBackwardEulerObjective::computeResidual(btScalar dt, TVStack &r
             m_lf[i]->addScaledDampingForce(dt, residual);
             m_lf[i]->addScaledDampingForce(dt, residual);
         }
         }
     }
     }
-    m_projection.project(residual);
+//    m_projection.project(residual);
 }
 }
 
 
 btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const
 btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const
@@ -186,9 +216,9 @@ void btDeformableBackwardEulerObjective::initialGuess(TVStack& dv, const TVStack
 }
 }
 
 
 //set constraints as projections
 //set constraints as projections
-void btDeformableBackwardEulerObjective::setConstraints()
+void btDeformableBackwardEulerObjective::setConstraints(const btContactSolverInfo& infoGlobal)
 {
 {
-    m_projection.setConstraints();
+    m_projection.setConstraints(infoGlobal);
 }
 }
 
 
 void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r)
 void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r)

+ 41 - 2
thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h

@@ -15,11 +15,12 @@
 
 
 #ifndef BT_BACKWARD_EULER_OBJECTIVE_H
 #ifndef BT_BACKWARD_EULER_OBJECTIVE_H
 #define BT_BACKWARD_EULER_OBJECTIVE_H
 #define BT_BACKWARD_EULER_OBJECTIVE_H
-#include "btConjugateGradient.h"
+//#include "btConjugateGradient.h"
 #include "btDeformableLagrangianForce.h"
 #include "btDeformableLagrangianForce.h"
 #include "btDeformableMassSpringForce.h"
 #include "btDeformableMassSpringForce.h"
 #include "btDeformableGravityForce.h"
 #include "btDeformableGravityForce.h"
 #include "btDeformableCorotatedForce.h"
 #include "btDeformableCorotatedForce.h"
+#include "btDeformableMousePickingForce.h"
 #include "btDeformableLinearElasticityForce.h"
 #include "btDeformableLinearElasticityForce.h"
 #include "btDeformableNeoHookeanForce.h"
 #include "btDeformableNeoHookeanForce.h"
 #include "btDeformableContactProjection.h"
 #include "btDeformableContactProjection.h"
@@ -39,6 +40,8 @@ public:
     const TVStack& m_backupVelocity;
     const TVStack& m_backupVelocity;
     btAlignedObjectArray<btSoftBody::Node* > m_nodes;
     btAlignedObjectArray<btSoftBody::Node* > m_nodes;
     bool m_implicit;
     bool m_implicit;
+    MassPreconditioner* m_massPreconditioner;
+    KKTPreconditioner* m_KKTPreconditioner;
 
 
     btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v);
     btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v);
     
     
@@ -79,7 +82,7 @@ public:
     void updateVelocity(const TVStack& dv);
     void updateVelocity(const TVStack& dv);
     
     
     //set constraints as projections
     //set constraints as projections
-    void setConstraints();
+    void setConstraints(const btContactSolverInfo& infoGlobal);
     
     
     // update the projections and project the residual
     // update the projections and project the residual
     void project(TVStack& r)
     void project(TVStack& r)
@@ -129,6 +132,42 @@ public:
 
 
     // Calculate the total potential energy in the system
     // Calculate the total potential energy in the system
     btScalar totalEnergy(btScalar dt);
     btScalar totalEnergy(btScalar dt);
+    
+    void addLagrangeMultiplier(const TVStack& vec, TVStack& extended_vec)
+    {
+        extended_vec.resize(vec.size() + m_projection.m_lagrangeMultipliers.size());
+        for (int i = 0; i < vec.size(); ++i)
+        {
+            extended_vec[i] = vec[i];
+        }
+        int offset = vec.size();
+        for (int i = 0; i < m_projection.m_lagrangeMultipliers.size(); ++i)
+        {
+            extended_vec[offset + i].setZero();
+        }
+    }
+    
+    void addLagrangeMultiplierRHS(const TVStack& residual, const TVStack& m_dv, TVStack& extended_residual)
+    {
+        extended_residual.resize(residual.size() + m_projection.m_lagrangeMultipliers.size());
+        for (int i = 0; i < residual.size(); ++i)
+        {
+            extended_residual[i] = residual[i];
+        }
+        int offset = residual.size();
+        for (int i = 0; i < m_projection.m_lagrangeMultipliers.size(); ++i)
+        {
+            const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[i];
+            extended_residual[offset + i].setZero();
+            for (int d = 0; d < lm.m_num_constraints; ++d)
+            {
+                for (int n = 0; n < lm.m_num_nodes; ++n)
+                {
+                    extended_residual[offset + i][d] += lm.m_weights[n] * m_dv[lm.m_indices[n]].dot(lm.m_dirs[d]);
+                }
+            }
+        }
+    }
 };
 };
 
 
 #endif /* btBackwardEulerObjective_h */
 #endif /* btBackwardEulerObjective_h */

+ 39 - 39
thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp

@@ -18,13 +18,15 @@
 #include "btDeformableBodySolver.h"
 #include "btDeformableBodySolver.h"
 #include "btSoftBodyInternals.h"
 #include "btSoftBodyInternals.h"
 #include "LinearMath/btQuickprof.h"
 #include "LinearMath/btQuickprof.h"
-static const int kMaxConjugateGradientIterations  = 50;
+static const int kMaxConjugateGradientIterations = 50;
 btDeformableBodySolver::btDeformableBodySolver()
 btDeformableBodySolver::btDeformableBodySolver()
 : m_numNodes(0)
 : m_numNodes(0)
 , m_cg(kMaxConjugateGradientIterations)
 , m_cg(kMaxConjugateGradientIterations)
+, m_cr(kMaxConjugateGradientIterations)
 , m_maxNewtonIterations(5)
 , m_maxNewtonIterations(5)
 , m_newtonTolerance(1e-4)
 , m_newtonTolerance(1e-4)
 , m_lineSearch(false)
 , m_lineSearch(false)
+, m_useProjection(false)
 {
 {
     m_objective = new btDeformableBackwardEulerObjective(m_softBodies, m_backupVelocity);
     m_objective = new btDeformableBackwardEulerObjective(m_softBodies, m_backupVelocity);
 }
 }
@@ -41,7 +43,22 @@ void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
     {
     {
         m_objective->computeResidual(solverdt, m_residual);
         m_objective->computeResidual(solverdt, m_residual);
         m_objective->applyDynamicFriction(m_residual);
         m_objective->applyDynamicFriction(m_residual);
-        computeStep(m_dv, m_residual);
+        if (m_useProjection)
+        {
+            computeStep(m_dv, m_residual);
+        }
+        else
+        {
+            TVStack rhs, x;
+            m_objective->addLagrangeMultiplierRHS(m_residual, m_dv, rhs);
+            m_objective->addLagrangeMultiplier(m_dv, x);
+            m_objective->m_preconditioner->reinitialize(true);
+            computeStep(x, rhs);
+            for (int i = 0; i<m_dv.size(); ++i)
+            {
+                    m_dv[i] = x[i];
+            }
+        }
         updateVelocity();
         updateVelocity();
     }
     }
     else
     else
@@ -63,7 +80,7 @@ void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
                     ++counter;
                     ++counter;
                 }
                 }
             }
             }
-            
+
             m_objective->computeResidual(solverdt, m_residual);
             m_objective->computeResidual(solverdt, m_residual);
             if (m_objective->computeNorm(m_residual) < m_newtonTolerance && i > 0)
             if (m_objective->computeNorm(m_residual) < m_newtonTolerance && i > 0)
             {
             {
@@ -200,7 +217,10 @@ void btDeformableBodySolver::updateDv(btScalar scale)
 
 
 void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual)
 void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual)
 {
 {
-    m_cg.solve(*m_objective, ddv, residual);
+    if (m_useProjection)
+        m_cg.solve(*m_objective, ddv, residual, false);
+    else
+        m_cr.solve(*m_objective, ddv, residual, false);
 }
 }
 
 
 void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt)
 void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt)
@@ -226,27 +246,22 @@ void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody
     
     
     m_dt = dt;
     m_dt = dt;
     m_objective->reinitialize(nodeUpdated, dt);
     m_objective->reinitialize(nodeUpdated, dt);
+    updateSoftBodies();
 }
 }
 
 
-void btDeformableBodySolver::setConstraints()
+void btDeformableBodySolver::setConstraints(const btContactSolverInfo& infoGlobal)
 {
 {
     BT_PROFILE("setConstraint");
     BT_PROFILE("setConstraint");
-    m_objective->setConstraints();
+    m_objective->setConstraints(infoGlobal);
 }
 }
 
 
-btScalar btDeformableBodySolver::solveContactConstraints(btCollisionObject** deformableBodies,int numDeformableBodies)
+btScalar btDeformableBodySolver::solveContactConstraints(btCollisionObject** deformableBodies,int numDeformableBodies, const btContactSolverInfo& infoGlobal)
 {
 {
     BT_PROFILE("solveContactConstraints");
     BT_PROFILE("solveContactConstraints");
-    btScalar maxSquaredResidual = m_objective->m_projection.update(deformableBodies,numDeformableBodies);
+    btScalar maxSquaredResidual = m_objective->m_projection.update(deformableBodies,numDeformableBodies, infoGlobal);
     return maxSquaredResidual;
     return maxSquaredResidual;
 }
 }
 
 
-btScalar btDeformableBodySolver::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
-{
-    BT_PROFILE("solveSplitImpulse");
-    return m_objective->m_projection.solveSplitImpulse(infoGlobal);
-}
-
 void btDeformableBodySolver::splitImpulseSetup(const btContactSolverInfo& infoGlobal)
 void btDeformableBodySolver::splitImpulseSetup(const btContactSolverInfo& infoGlobal)
 {
 {
      m_objective->m_projection.splitImpulseSetup(infoGlobal);
      m_objective->m_projection.splitImpulseSetup(infoGlobal);
@@ -333,8 +348,10 @@ void btDeformableBodySolver::setupDeformableSolve(bool implicit)
                 m_backupVelocity[counter] = psb->m_nodes[j].m_vn;
                 m_backupVelocity[counter] = psb->m_nodes[j].m_vn;
             }
             }
             else
             else
+            {
                 m_dv[counter] =  psb->m_nodes[j].m_v - m_backupVelocity[counter];
                 m_dv[counter] =  psb->m_nodes[j].m_v - m_backupVelocity[counter];
-            psb->m_nodes[j].m_v = m_backupVelocity[counter] + psb->m_nodes[j].m_vsplit;
+            }
+            psb->m_nodes[j].m_v = m_backupVelocity[counter];
             ++counter;
             ++counter;
         }
         }
     }
     }
@@ -385,6 +402,7 @@ void btDeformableBodySolver::predictMotion(btScalar solverdt)
 
 
 void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar dt)
 void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar dt)
 {
 {
+    BT_PROFILE("btDeformableBodySolver::predictDeformableMotion");
     int i, ni;
     int i, ni;
     
     
     /* Update                */
     /* Update                */
@@ -423,40 +441,22 @@ void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar d
             n.m_v *= max_v;
             n.m_v *= max_v;
         }
         }
         n.m_q = n.m_x + n.m_v * dt;
         n.m_q = n.m_x + n.m_v * dt;
+        n.m_penetration = 0;
     }
     }
 
 
     /* Nodes                */
     /* Nodes                */
-    ATTRIBUTE_ALIGNED16(btDbvtVolume)
-    vol;
-    for (i = 0, ni = psb->m_nodes.size(); i < ni; ++i)
-    {
-        btSoftBody::Node& n = psb->m_nodes[i];
-        btVector3 points[2] = {n.m_x, n.m_q};
-        vol = btDbvtVolume::FromPoints(points, 2);
-        vol.Expand(btVector3(psb->m_sst.radmrg, psb->m_sst.radmrg, psb->m_sst.radmrg));
-        psb->m_ndbvt.update(n.m_leaf, vol);
-    }
-
+    psb->updateNodeTree(true, true);
     if (!psb->m_fdbvt.empty())
     if (!psb->m_fdbvt.empty())
     {
     {
-        for (int i = 0; i < psb->m_faces.size(); ++i)
-        {
-            btSoftBody::Face& f = psb->m_faces[i];
-            btVector3 points[6] = {f.m_n[0]->m_x, f.m_n[0]->m_q,
-                                   f.m_n[1]->m_x, f.m_n[1]->m_q,
-                                   f.m_n[2]->m_x, f.m_n[2]->m_q};
-            vol = btDbvtVolume::FromPoints(points, 6);
-            vol.Expand(btVector3(psb->m_sst.radmrg, psb->m_sst.radmrg, psb->m_sst.radmrg));
-            psb->m_fdbvt.update(f.m_leaf, vol);
-        }
+        psb->updateFaceTree(true, true);
     }
     }
-    /* Clear contacts        */
+    /* Clear contacts */
     psb->m_nodeRigidContacts.resize(0);
     psb->m_nodeRigidContacts.resize(0);
     psb->m_faceRigidContacts.resize(0);
     psb->m_faceRigidContacts.resize(0);
     psb->m_faceNodeContacts.resize(0);
     psb->m_faceNodeContacts.resize(0);
     /* Optimize dbvt's        */
     /* Optimize dbvt's        */
-    psb->m_ndbvt.optimizeIncremental(1);
-    psb->m_fdbvt.optimizeIncremental(1);
+//    psb->m_ndbvt.optimizeIncremental(1);
+//    psb->m_fdbvt.optimizeIncremental(1);
 }
 }
 
 
 
 

+ 7 - 9
thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h

@@ -22,7 +22,8 @@
 #include "btDeformableMultiBodyDynamicsWorld.h"
 #include "btDeformableMultiBodyDynamicsWorld.h"
 #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
 #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-
+#include "btConjugateResidual.h"
+#include "btConjugateGradient.h"
 struct btCollisionObjectWrapper;
 struct btCollisionObjectWrapper;
 class btDeformableBackwardEulerObjective;
 class btDeformableBackwardEulerObjective;
 class btDeformableMultiBodyDynamicsWorld;
 class btDeformableMultiBodyDynamicsWorld;
@@ -40,14 +41,15 @@ protected:
     TVStack m_backupVelocity;       // backed up v, equals v_n for implicit, equals v_{n+1}^* for explicit
     TVStack m_backupVelocity;       // backed up v, equals v_n for implicit, equals v_{n+1}^* for explicit
     btScalar m_dt;                  // dt
     btScalar m_dt;                  // dt
     btConjugateGradient<btDeformableBackwardEulerObjective> m_cg;  // CG solver
     btConjugateGradient<btDeformableBackwardEulerObjective> m_cg;  // CG solver
+    btConjugateResidual<btDeformableBackwardEulerObjective> m_cr;  // CR solver
     bool m_implicit;                // use implicit scheme if true, explicit scheme if false
     bool m_implicit;                // use implicit scheme if true, explicit scheme if false
     int m_maxNewtonIterations;      // max number of newton iterations
     int m_maxNewtonIterations;      // max number of newton iterations
     btScalar m_newtonTolerance;     // stop newton iterations if f(x) < m_newtonTolerance
     btScalar m_newtonTolerance;     // stop newton iterations if f(x) < m_newtonTolerance
     bool m_lineSearch;              // If true, use newton's method with line search under implicit scheme
     bool m_lineSearch;              // If true, use newton's method with line search under implicit scheme
-    
 public:
 public:
     // handles data related to objective function
     // handles data related to objective function
     btDeformableBackwardEulerObjective* m_objective;
     btDeformableBackwardEulerObjective* m_objective;
+    bool m_useProjection;
     
     
     btDeformableBodySolver();
     btDeformableBodySolver();
     
     
@@ -61,15 +63,11 @@ public:
     // update soft body normals
     // update soft body normals
     virtual void updateSoftBodies();
     virtual void updateSoftBodies();
     
     
+    virtual btScalar solveContactConstraints(btCollisionObject** deformableBodies,int numDeformableBodies, const btContactSolverInfo& infoGlobal);
+    
     // solve the momentum equation
     // solve the momentum equation
     virtual void solveDeformableConstraints(btScalar solverdt);
     virtual void solveDeformableConstraints(btScalar solverdt);
     
     
-    // solve the contact between deformable and rigid as well as among deformables
-    btScalar solveContactConstraints(btCollisionObject** deformableBodies,int numDeformableBodies);
-    
-    // solve the position error  between deformable and rigid as well as among deformables;
-    btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
-    
     // set up the position error in split impulse
     // set up the position error in split impulse
     void splitImpulseSetup(const btContactSolverInfo& infoGlobal);
     void splitImpulseSetup(const btContactSolverInfo& infoGlobal);
 
 
@@ -77,7 +75,7 @@ public:
     void reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt);
     void reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt);
     
     
     // set up contact constraints
     // set up contact constraints
-    void setConstraints();
+    void setConstraints(const btContactSolverInfo& infoGlobal);
     
     
     // add in elastic forces and gravity to obtain v_{n+1}^* and calls predictDeformableMotion
     // add in elastic forces and gravity to obtain v_{n+1}^* and calls predictDeformableMotion
     virtual void predictMotion(btScalar solverdt);
     virtual void predictMotion(btScalar solverdt);

+ 84 - 100
thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp

@@ -15,9 +15,9 @@
 
 
 #include "btDeformableContactConstraint.h"
 #include "btDeformableContactConstraint.h"
 /* ================   Deformable Node Anchor   =================== */
 /* ================   Deformable Node Anchor   =================== */
-btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& a)
+btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& a, const btContactSolverInfo& infoGlobal)
 : m_anchor(&a)
 : m_anchor(&a)
-, btDeformableContactConstraint(a.m_cti.m_normal)
+, btDeformableContactConstraint(a.m_cti.m_normal, infoGlobal)
 {
 {
 }
 }
 
 
@@ -79,14 +79,14 @@ btVector3 btDeformableNodeAnchorConstraint::getVa() const
     return va;
     return va;
 }
 }
 
 
-btScalar btDeformableNodeAnchorConstraint::solveConstraint()
+btScalar btDeformableNodeAnchorConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
 {
 {
     const btSoftBody::sCti& cti = m_anchor->m_cti;
     const btSoftBody::sCti& cti = m_anchor->m_cti;
     btVector3 va = getVa();
     btVector3 va = getVa();
     btVector3 vb = getVb();
     btVector3 vb = getVb();
     btVector3 vr = (vb - va);
     btVector3 vr = (vb - va);
     // + (m_anchor->m_node->m_x - cti.m_colObj->getWorldTransform() * m_anchor->m_local) * 10.0
     // + (m_anchor->m_node->m_x - cti.m_colObj->getWorldTransform() * m_anchor->m_local) * 10.0
-    const btScalar dn = btDot(vr, cti.m_normal);
+    const btScalar dn = btDot(vr, vr);
     // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
     // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
     btScalar residualSquare = dn*dn;
     btScalar residualSquare = dn*dn;
     btVector3 impulse = m_anchor->m_c0 * vr;
     btVector3 impulse = m_anchor->m_c0 * vr;
@@ -134,14 +134,15 @@ void btDeformableNodeAnchorConstraint::applyImpulse(const btVector3& impulse)
 }
 }
 
 
 /* ================   Deformable vs. Rigid   =================== */
 /* ================   Deformable vs. Rigid   =================== */
-btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c)
+btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal)
 : m_contact(&c)
 : m_contact(&c)
-, btDeformableContactConstraint(c.m_cti.m_normal)
+, btDeformableContactConstraint(c.m_cti.m_normal, infoGlobal)
 {
 {
     m_total_normal_dv.setZero();
     m_total_normal_dv.setZero();
     m_total_tangent_dv.setZero();
     m_total_tangent_dv.setZero();
-    // penetration is non-positive. The magnitude of penetration is the depth of penetration.
-    m_penetration = btMin(btScalar(0), c.m_cti.m_offset);
+    // The magnitude of penetration is the depth of penetration.
+    m_penetration = c.m_cti.m_offset;
+//	m_penetration = btMin(btScalar(0),c.m_cti.m_offset);
 }
 }
 
 
 btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other)
 btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other)
@@ -206,16 +207,16 @@ btVector3 btDeformableRigidContactConstraint::getVa() const
     return va;
     return va;
 }
 }
 
 
-btScalar btDeformableRigidContactConstraint::solveConstraint()
+btScalar btDeformableRigidContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
 {
 {
     const btSoftBody::sCti& cti = m_contact->m_cti;
     const btSoftBody::sCti& cti = m_contact->m_cti;
     btVector3 va = getVa();
     btVector3 va = getVa();
     btVector3 vb = getVb();
     btVector3 vb = getVb();
     btVector3 vr = vb - va;
     btVector3 vr = vb - va;
-    const btScalar dn = btDot(vr, cti.m_normal);
+    btScalar dn = btDot(vr, cti.m_normal) + m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep;
     // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
     // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
     btScalar residualSquare = dn*dn;
     btScalar residualSquare = dn*dn;
-    btVector3 impulse = m_contact->m_c0 * vr;
+    btVector3 impulse = m_contact->m_c0 * (vr + m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep * cti.m_normal) ;
     const btVector3 impulse_normal = m_contact->m_c0 * (cti.m_normal * dn);
     const btVector3 impulse_normal = m_contact->m_c0 * (cti.m_normal * dn);
     btVector3 impulse_tangent = impulse - impulse_normal;
     btVector3 impulse_tangent = impulse - impulse_normal;
     btVector3 old_total_tangent_dv = m_total_tangent_dv;
     btVector3 old_total_tangent_dv = m_total_tangent_dv;
@@ -256,6 +257,8 @@ btScalar btDeformableRigidContactConstraint::solveConstraint()
     impulse = impulse_normal + impulse_tangent;
     impulse = impulse_normal + impulse_tangent;
     // apply impulse to deformable nodes involved and change their velocities
     // apply impulse to deformable nodes involved and change their velocities
     applyImpulse(impulse);
     applyImpulse(impulse);
+	if (residualSquare < 1e-7)
+		return residualSquare;
     // apply impulse to the rigid/multibodies involved and change their velocities
     // apply impulse to the rigid/multibodies involved and change their velocities
     if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
     if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
     {
     {
@@ -285,43 +288,17 @@ btScalar btDeformableRigidContactConstraint::solveConstraint()
             }
             }
         }
         }
     }
     }
+//    va = getVa();
+//    vb = getVb();
+//    vr = vb - va;
+//    btScalar dn1 = btDot(vr, cti.m_normal) / 150;
+//    m_penetration += dn1;
     return residualSquare;
     return residualSquare;
 }
 }
-
-btScalar btDeformableRigidContactConstraint::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
-{
-    const btSoftBody::sCti& cti = m_contact->m_cti;
-    const btScalar dn = m_penetration;
-    if (dn != 0)
-    {
-        const btVector3 impulse = (m_contact->m_c0 * (cti.m_normal * dn / infoGlobal.m_timeStep));
-        // one iteration of the position impulse corrects all the position error at this timestep
-        m_penetration -= dn;
-        // apply impulse to deformable nodes involved and change their position
-        applySplitImpulse(impulse);
-        // apply impulse to the rigid/multibodies involved and change their position
-        if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
-        {
-            btRigidBody* rigidCol = 0;
-            rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
-            if (rigidCol)
-            {
-                rigidCol->applyPushImpulse(impulse, m_contact->m_c1);
-            }
-        }
-        else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
-        {
-            // todo xuchenhan@
-        }
-        return (m_penetration/infoGlobal.m_timeStep) * (m_penetration/infoGlobal.m_timeStep);
-    }
-    return 0;
-}
-
 /* ================   Node vs. Rigid   =================== */
 /* ================   Node vs. Rigid   =================== */
-btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact)
+btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal)
     : m_node(contact.m_node)
     : m_node(contact.m_node)
-    , btDeformableRigidContactConstraint(contact)
+    , btDeformableRigidContactConstraint(contact, infoGlobal)
     {
     {
     }
     }
 
 
@@ -349,22 +326,17 @@ void btDeformableNodeRigidContactConstraint::applyImpulse(const btVector3& impul
     contact->m_node->m_v -= dv;
     contact->m_node->m_v -= dv;
 }
 }
 
 
-void btDeformableNodeRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
-{
-    const btSoftBody::DeformableNodeRigidContact* contact = getContact();
-    btVector3 dv = impulse * contact->m_c2;
-    contact->m_node->m_vsplit -= dv;
-};
-
 /* ================   Face vs. Rigid   =================== */
 /* ================   Face vs. Rigid   =================== */
-btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact)
+btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting)
 : m_face(contact.m_face)
 : m_face(contact.m_face)
-, btDeformableRigidContactConstraint(contact)
+, m_useStrainLimiting(useStrainLimiting)
+, btDeformableRigidContactConstraint(contact, infoGlobal)
 {
 {
 }
 }
 
 
 btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other)
 btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other)
 : m_face(other.m_face)
 : m_face(other.m_face)
+, m_useStrainLimiting(other.m_useStrainLimiting)
 , btDeformableRigidContactConstraint(other)
 , btDeformableRigidContactConstraint(other)
 {
 {
 }
 }
@@ -411,47 +383,70 @@ void btDeformableFaceRigidContactConstraint::applyImpulse(const btVector3& impul
         v1 -= dv * contact->m_weights[1];
         v1 -= dv * contact->m_weights[1];
     if (im2 > 0)
     if (im2 > 0)
         v2 -= dv * contact->m_weights[2];
         v2 -= dv * contact->m_weights[2];
-    
-    // apply strain limiting to prevent undamped modes
-    btScalar m01 = (btScalar(1)/(im0 + im1));
-    btScalar m02 = (btScalar(1)/(im0 + im2));
-    btScalar m12 = (btScalar(1)/(im1 + im2));
-    
-    btVector3 dv0 = im0 * (m01 * (v1-v0) + m02 * (v2-v0));
-    btVector3 dv1 = im1 * (m01 * (v0-v1) + m12 * (v2-v1));
-    btVector3 dv2 = im2 * (m12 * (v1-v2) + m02 * (v0-v2));
-    
-    v0 += dv0;
-    v1 += dv1;
-    v2 += dv2;
-}
-
-void btDeformableFaceRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
-{
-    const btSoftBody::DeformableFaceRigidContact* contact = getContact();
-    btVector3 dv = impulse * contact->m_c2;
-    btSoftBody::Face* face = contact->m_face;
-
-    btVector3& v0 = face->m_n[0]->m_vsplit;
-    btVector3& v1 = face->m_n[1]->m_vsplit;
-    btVector3& v2 = face->m_n[2]->m_vsplit;
-    const btScalar& im0 = face->m_n[0]->m_im;
-    const btScalar& im1 = face->m_n[1]->m_im;
-    const btScalar& im2 = face->m_n[2]->m_im;
-    if (im0 > 0)
-        v0 -= dv * contact->m_weights[0];
-    if (im1 > 0)
-        v1 -= dv * contact->m_weights[1];
-    if (im2 > 0)
-        v2 -= dv * contact->m_weights[2];
+	if (m_useStrainLimiting)
+	{
+		btScalar relaxation = 1./btScalar(m_infoGlobal->m_numIterations);
+		btScalar m01 = (relaxation/(im0 + im1));
+		btScalar m02 = (relaxation/(im0 + im2));
+		btScalar m12 = (relaxation/(im1 + im2));
+		#ifdef USE_STRAIN_RATE_LIMITING
+		// apply strain limiting to prevent the new velocity to change the current length of the edge by more than 1%.
+		btScalar p = 0.01;
+		btVector3& x0 = face->m_n[0]->m_x;
+		btVector3& x1 = face->m_n[1]->m_x;
+		btVector3& x2 = face->m_n[2]->m_x;
+		const btVector3 x_diff[3] = {x1-x0, x2-x0, x2-x1};
+		const btVector3 v_diff[3] = {v1-v0, v2-v0, v2-v1};
+		btVector3 u[3];
+		btScalar x_diff_dot_u, dn[3];
+		btScalar dt = m_infoGlobal->m_timeStep;
+		for (int i = 0; i < 3; ++i)
+		{
+			btScalar x_diff_norm = x_diff[i].safeNorm();
+			btScalar x_diff_norm_new = (x_diff[i] + v_diff[i] * dt).safeNorm();
+			btScalar strainRate = x_diff_norm_new/x_diff_norm;
+			u[i] = v_diff[i];
+			u[i].safeNormalize();
+			if (x_diff_norm == 0 || (1-p <= strainRate && strainRate <= 1+p))
+			{
+				dn[i] = 0;
+				continue;
+			}
+			x_diff_dot_u = btDot(x_diff[i], u[i]);
+			btScalar s;
+			if (1-p > strainRate)
+			{
+				s = 1/dt * (-x_diff_dot_u - btSqrt(x_diff_dot_u*x_diff_dot_u + (p*p-2*p) * x_diff_norm * x_diff_norm));
+			}
+			else
+			{
+				s = 1/dt * (-x_diff_dot_u + btSqrt(x_diff_dot_u*x_diff_dot_u + (p*p+2*p) * x_diff_norm * x_diff_norm));
+			}
+			//		x_diff_norm_new = (x_diff[i] + s * u[i] * dt).safeNorm();
+			//		strainRate = x_diff_norm_new/x_diff_norm;
+			dn[i] = s - v_diff[i].safeNorm();
+		}
+		btVector3 dv0 = im0 * (m01 * u[0]*(-dn[0]) + m02 * u[1]*-(dn[1]));
+		btVector3 dv1 = im1 * (m01 * u[0]*(dn[0]) + m12 * u[2]*(-dn[2]));
+		btVector3 dv2 = im2 * (m12 * u[2]*(dn[2]) + m02 * u[1]*(dn[1]));
+	#else
+		// apply strain limiting to prevent undamped modes
+		btVector3 dv0 = im0 * (m01 * (v1-v0) + m02 * (v2-v0));
+		btVector3 dv1 = im1 * (m01 * (v0-v1) + m12 * (v2-v1));
+		btVector3 dv2 = im2 * (m12 * (v1-v2) + m02 * (v0-v2));
+	#endif
+		v0 += dv0;
+		v1 += dv1;
+		v2 += dv2;
+	}
 }
 }
 
 
 /* ================   Face vs. Node   =================== */
 /* ================   Face vs. Node   =================== */
-btDeformableFaceNodeContactConstraint::btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact)
+btDeformableFaceNodeContactConstraint::btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal)
 : m_node(contact.m_node)
 : m_node(contact.m_node)
 , m_face(contact.m_face)
 , m_face(contact.m_face)
 , m_contact(&contact)
 , m_contact(&contact)
-, btDeformableContactConstraint(contact.m_normal)
+, btDeformableContactConstraint(contact.m_normal, infoGlobal)
 {
 {
     m_total_normal_dv.setZero();
     m_total_normal_dv.setZero();
     m_total_tangent_dv.setZero();
     m_total_tangent_dv.setZero();
@@ -487,7 +482,7 @@ btVector3 btDeformableFaceNodeContactConstraint::getDv(const btSoftBody::Node* n
     return dv * contact->m_weights[2];
     return dv * contact->m_weights[2];
 }
 }
 
 
-btScalar btDeformableFaceNodeContactConstraint::solveConstraint()
+btScalar btDeformableFaceNodeContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
 {
 {
     btVector3 va = getVa();
     btVector3 va = getVa();
     btVector3 vb = getVb();
     btVector3 vb = getVb();
@@ -577,15 +572,4 @@ void btDeformableFaceNodeContactConstraint::applyImpulse(const btVector3& impuls
     {
     {
         v2 -= dvb * contact->m_weights[2];
         v2 -= dvb * contact->m_weights[2];
     }
     }
-    // todo: Face node constraints needs more work
-//    btScalar m01 = (btScalar(1)/(im0 + im1));
-//    btScalar m02 = (btScalar(1)/(im0 + im2));
-//    btScalar m12 = (btScalar(1)/(im1 + im2));
-//
-//    btVector3 dv0 = im0 * (m01 * (v1-v0) + m02 * (v2-v0));
-//    btVector3 dv1 = im1 * (m01 * (v0-v1) + m12 * (v2-v1));
-//    btVector3 dv2 = im2 * (m12 * (v1-v2) + m02 * (v0-v2));
-//    v0 += dv0;
-//    v1 += dv1;
-//    v2 += dv2;
 }
 }

+ 48 - 84
thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h

@@ -24,34 +24,33 @@ public:
     // True if the friction is static
     // True if the friction is static
     // False if the friction is dynamic
     // False if the friction is dynamic
     bool m_static;
     bool m_static;
-    
-    // normal of the contact
-    btVector3 m_normal;
-    
-    btDeformableContactConstraint(const btVector3& normal): m_static(false), m_normal(normal)
-    {
-    }
-    
-    btDeformableContactConstraint(bool isStatic, const btVector3& normal): m_static(isStatic), m_normal(normal)
-    {
-    }
-    
-    btDeformableContactConstraint(const btDeformableContactConstraint& other)
-    : m_static(other.m_static)
-    , m_normal(other.m_normal)
-    {
-        
-    }
-    btDeformableContactConstraint(){}
-    
+	const btContactSolverInfo* m_infoGlobal;
+
+	// normal of the contact
+	btVector3 m_normal;
+
+	btDeformableContactConstraint(const btVector3& normal, const btContactSolverInfo& infoGlobal): m_static(false), m_normal(normal), m_infoGlobal(&infoGlobal)
+	{
+	}
+
+	btDeformableContactConstraint(bool isStatic, const btVector3& normal, const btContactSolverInfo& infoGlobal): m_static(isStatic), m_normal(normal), m_infoGlobal(&infoGlobal)
+	{
+	}
+	
+	btDeformableContactConstraint(){}
+
+	btDeformableContactConstraint(const btDeformableContactConstraint& other)
+	: m_static(other.m_static)
+	, m_normal(other.m_normal)
+	, m_infoGlobal(other.m_infoGlobal)
+	{
+	}
+
     virtual ~btDeformableContactConstraint(){}
     virtual ~btDeformableContactConstraint(){}
     
     
     // solve the constraint with inelastic impulse and return the error, which is the square of normal component of velocity diffrerence
     // solve the constraint with inelastic impulse and return the error, which is the square of normal component of velocity diffrerence
     // the constraint is solved by calculating the impulse between object A and B in the contact and apply the impulse to both objects involved in the contact
     // the constraint is solved by calculating the impulse between object A and B in the contact and apply the impulse to both objects involved in the contact
-    virtual btScalar solveConstraint() = 0;
-    
-    // solve the position error by applying an inelastic impulse that changes only the position (not velocity)
-    virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal) = 0;
+    virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal) = 0;
     
     
     // get the velocity of the object A in the contact
     // get the velocity of the object A in the contact
     virtual btVector3 getVa() const = 0;
     virtual btVector3 getVa() const = 0;
@@ -65,9 +64,6 @@ public:
     // apply impulse to the soft body node and/or face involved
     // apply impulse to the soft body node and/or face involved
     virtual void applyImpulse(const btVector3& impulse) = 0;
     virtual void applyImpulse(const btVector3& impulse) = 0;
     
     
-    // apply position based impulse to the soft body node and/or face involved
-    virtual void applySplitImpulse(const btVector3& impulse) = 0;
-    
     // scale the penetration depth by erp
     // scale the penetration depth by erp
     virtual void setPenetrationScale(btScalar scale) = 0;
     virtual void setPenetrationScale(btScalar scale) = 0;
 };
 };
@@ -77,29 +73,21 @@ public:
 class btDeformableStaticConstraint : public btDeformableContactConstraint
 class btDeformableStaticConstraint : public btDeformableContactConstraint
 {
 {
 public:
 public:
-    const btSoftBody::Node* m_node;
-    
-    btDeformableStaticConstraint(){}
+    btSoftBody::Node* m_node;
     
     
-    btDeformableStaticConstraint(const btSoftBody::Node* node): m_node(node), btDeformableContactConstraint(false, btVector3(0,0,0))
+    btDeformableStaticConstraint(btSoftBody::Node* node, const btContactSolverInfo& infoGlobal): m_node(node), btDeformableContactConstraint(false, btVector3(0,0,0), infoGlobal)
     {
     {
     }
     }
-    
+	btDeformableStaticConstraint(){}
     btDeformableStaticConstraint(const btDeformableStaticConstraint& other)
     btDeformableStaticConstraint(const btDeformableStaticConstraint& other)
     : m_node(other.m_node)
     : m_node(other.m_node)
     , btDeformableContactConstraint(other)
     , btDeformableContactConstraint(other)
     {
     {
-        
     }
     }
     
     
     virtual ~btDeformableStaticConstraint(){}
     virtual ~btDeformableStaticConstraint(){}
     
     
-    virtual btScalar solveConstraint()
-    {
-        return 0;
-    }
-    
-    virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal)
+    virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal)
     {
     {
         return 0;
         return 0;
     }
     }
@@ -120,7 +108,6 @@ public:
     }
     }
     
     
     virtual void applyImpulse(const btVector3& impulse){}
     virtual void applyImpulse(const btVector3& impulse){}
-    virtual void applySplitImpulse(const btVector3& impulse){}
     virtual void setPenetrationScale(btScalar scale){}
     virtual void setPenetrationScale(btScalar scale){}
 };
 };
 
 
@@ -130,19 +117,15 @@ class btDeformableNodeAnchorConstraint : public btDeformableContactConstraint
 {
 {
 public:
 public:
     const btSoftBody::DeformableNodeRigidAnchor* m_anchor;
     const btSoftBody::DeformableNodeRigidAnchor* m_anchor;
-    
-    btDeformableNodeAnchorConstraint(){}
-    btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& c);
+	
+    btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& c, const btContactSolverInfo& infoGlobal);
     btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other);
     btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other);
+	btDeformableNodeAnchorConstraint(){}
     virtual ~btDeformableNodeAnchorConstraint()
     virtual ~btDeformableNodeAnchorConstraint()
     {
     {
     }
     }
-    virtual btScalar solveConstraint();
-    virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal)
-    {
-        // todo xuchenhan@
-        return 0;
-    }
+    virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+
     // object A is the rigid/multi body, and object B is the deformable node/face
     // object A is the rigid/multi body, and object B is the deformable node/face
     virtual btVector3 getVa() const;
     virtual btVector3 getVa() const;
     // get the velocity of the deformable node in contact
     // get the velocity of the deformable node in contact
@@ -152,10 +135,7 @@ public:
         return btVector3(0,0,0);
         return btVector3(0,0,0);
     }
     }
     virtual void applyImpulse(const btVector3& impulse);
     virtual void applyImpulse(const btVector3& impulse);
-    virtual void applySplitImpulse(const btVector3& impulse)
-    {
-        // todo xuchenhan@
-    };
+
     virtual void setPenetrationScale(btScalar scale){}
     virtual void setPenetrationScale(btScalar scale){}
 };
 };
 
 
@@ -169,10 +149,10 @@ public:
     btVector3 m_total_tangent_dv;
     btVector3 m_total_tangent_dv;
     btScalar m_penetration;
     btScalar m_penetration;
     const btSoftBody::DeformableRigidContact* m_contact;
     const btSoftBody::DeformableRigidContact* m_contact;
-    
-    btDeformableRigidContactConstraint(){}
-    btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c);
+	
+    btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal);
     btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other);
     btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other);
+	btDeformableRigidContactConstraint(){}
     virtual ~btDeformableRigidContactConstraint()
     virtual ~btDeformableRigidContactConstraint()
     {
     {
     }
     }
@@ -180,9 +160,7 @@ public:
     // object A is the rigid/multi body, and object B is the deformable node/face
     // object A is the rigid/multi body, and object B is the deformable node/face
     virtual btVector3 getVa() const;
     virtual btVector3 getVa() const;
     
     
-    virtual btScalar solveConstraint();
-    
-    virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
+    virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
     
     
     virtual void setPenetrationScale(btScalar scale)
     virtual void setPenetrationScale(btScalar scale)
     {
     {
@@ -196,12 +174,11 @@ class btDeformableNodeRigidContactConstraint : public btDeformableRigidContactCo
 {
 {
 public:
 public:
     // the deformable node in contact
     // the deformable node in contact
-    const btSoftBody::Node* m_node;
-    
-    btDeformableNodeRigidContactConstraint(){}
-    btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact);
+    btSoftBody::Node* m_node;
+	
+    btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal);
     btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other);
     btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other);
-    
+	btDeformableNodeRigidContactConstraint(){}
     virtual ~btDeformableNodeRigidContactConstraint()
     virtual ~btDeformableNodeRigidContactConstraint()
     {
     {
     }
     }
@@ -219,7 +196,6 @@ public:
     }
     }
     
     
     virtual void applyImpulse(const btVector3& impulse);
     virtual void applyImpulse(const btVector3& impulse);
-    virtual void applySplitImpulse(const btVector3& impulse);
 };
 };
 
 
 //
 //
@@ -228,10 +204,10 @@ class btDeformableFaceRigidContactConstraint : public btDeformableRigidContactCo
 {
 {
 public:
 public:
     const btSoftBody::Face* m_face;
     const btSoftBody::Face* m_face;
-    btDeformableFaceRigidContactConstraint(){}
-    btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact);
+    bool m_useStrainLimiting;
+    btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting);
     btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other);
     btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other);
-    
+    btDeformableFaceRigidContactConstraint(): m_useStrainLimiting(false) {}
     virtual ~btDeformableFaceRigidContactConstraint()
     virtual ~btDeformableFaceRigidContactConstraint()
     {
     {
     }
     }
@@ -249,7 +225,6 @@ public:
     }
     }
     
     
     virtual void applyImpulse(const btVector3& impulse);
     virtual void applyImpulse(const btVector3& impulse);
-    virtual void applySplitImpulse(const btVector3& impulse);
 };
 };
 
 
 //
 //
@@ -263,19 +238,11 @@ public:
     btVector3 m_total_normal_dv;
     btVector3 m_total_normal_dv;
     btVector3 m_total_tangent_dv;
     btVector3 m_total_tangent_dv;
     
     
-    btDeformableFaceNodeContactConstraint(){}
-    
-    btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact);
-    
+    btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal);
+	btDeformableFaceNodeContactConstraint(){}
     virtual ~btDeformableFaceNodeContactConstraint(){}
     virtual ~btDeformableFaceNodeContactConstraint(){}
     
     
-    virtual btScalar solveConstraint();
-    
-    virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal)
-    {
-        // todo: xuchenhan@
-        return 0;
-    }
+    virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
     
     
     // get the velocity of the object A in the contact
     // get the velocity of the object A in the contact
     virtual btVector3 getVa() const;
     virtual btVector3 getVa() const;
@@ -293,10 +260,7 @@ public:
     }
     }
     
     
     virtual void applyImpulse(const btVector3& impulse);
     virtual void applyImpulse(const btVector3& impulse);
-    virtual void applySplitImpulse(const btVector3& impulse)
-    {
-        // todo xuchenhan@
-    }
+
     virtual void setPenetrationScale(btScalar scale){}
     virtual void setPenetrationScale(btScalar scale){}
 };
 };
 #endif /* BT_DEFORMABLE_CONTACT_CONSTRAINT_H */
 #endif /* BT_DEFORMABLE_CONTACT_CONSTRAINT_H */

+ 383 - 258
thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp

@@ -17,7 +17,7 @@
 #include "btDeformableMultiBodyDynamicsWorld.h"
 #include "btDeformableMultiBodyDynamicsWorld.h"
 #include <algorithm>
 #include <algorithm>
 #include <cmath>
 #include <cmath>
-btScalar btDeformableContactProjection::update(btCollisionObject** deformableBodies,int numDeformableBodies)
+btScalar btDeformableContactProjection::update(btCollisionObject** deformableBodies,int numDeformableBodies, const btContactSolverInfo& infoGlobal)
 {
 {
 	btScalar residualSquare = 0;
 	btScalar residualSquare = 0;
 	for (int i = 0; i < numDeformableBodies; ++i)
 	for (int i = 0; i < numDeformableBodies; ++i)
@@ -32,25 +32,25 @@ btScalar btDeformableContactProjection::update(btCollisionObject** deformableBod
 			for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
 			for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
 			{
 			{
 				btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
 				btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
-				btScalar localResidualSquare = constraint.solveConstraint();
+				btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
 				residualSquare = btMax(residualSquare, localResidualSquare);
 				residualSquare = btMax(residualSquare, localResidualSquare);
 			}
 			}
 			for (int k = 0; k < m_nodeAnchorConstraints[j].size(); ++k)
 			for (int k = 0; k < m_nodeAnchorConstraints[j].size(); ++k)
 			{
 			{
 				btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[j][k];
 				btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[j][k];
-				btScalar localResidualSquare = constraint.solveConstraint();
+				btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
 				residualSquare = btMax(residualSquare, localResidualSquare);
 				residualSquare = btMax(residualSquare, localResidualSquare);
 			}
 			}
 			for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
 			for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
 			{
 			{
 				btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
 				btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
-				btScalar localResidualSquare = constraint.solveConstraint();
+				btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
 				residualSquare = btMax(residualSquare, localResidualSquare);
 				residualSquare = btMax(residualSquare, localResidualSquare);
 			}
 			}
 			for (int k = 0; k < m_deformableConstraints[j].size(); ++k)
 			for (int k = 0; k < m_deformableConstraints[j].size(); ++k)
 			{
 			{
 				btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[j][k];
 				btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[j][k];
-				btScalar localResidualSquare = constraint.solveConstraint();
+				btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
 				residualSquare = btMax(residualSquare, localResidualSquare);
 				residualSquare = btMax(residualSquare, localResidualSquare);
 			}
 			}
 		}
 		}
@@ -77,39 +77,8 @@ void btDeformableContactProjection::splitImpulseSetup(const btContactSolverInfo&
 	}
 	}
 }
 }
 
 
-btScalar btDeformableContactProjection::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
-{
-	btScalar residualSquare = 0;
-	for (int i = 0; i < m_softBodies.size(); ++i)
-	{
-		// node constraints
-		for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
-		{
-			btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
-			btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
-			residualSquare = btMax(residualSquare, localResidualSquare);
-		}
-		// anchor constraints
-		for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
-		{
-			btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[i][j];
-			btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
-			residualSquare = btMax(residualSquare, localResidualSquare);
-		}
-		// face constraints
-		for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
-		{
-			btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
-			btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
-			residualSquare = btMax(residualSquare, localResidualSquare);
-		}
-
-	}
-	return residualSquare;
-}
-
-void btDeformableContactProjection::setConstraints()
-{
+void btDeformableContactProjection::setConstraints(const btContactSolverInfo& infoGlobal)
+{  
 	BT_PROFILE("setConstraints");
 	BT_PROFILE("setConstraints");
 	for (int i = 0; i < m_softBodies.size(); ++i)
 	for (int i = 0; i < m_softBodies.size(); ++i)
 	{
 	{
@@ -124,7 +93,7 @@ void btDeformableContactProjection::setConstraints()
 		{
 		{
 			if (psb->m_nodes[j].m_im == 0)
 			if (psb->m_nodes[j].m_im == 0)
 			{
 			{
-				btDeformableStaticConstraint static_constraint(&psb->m_nodes[j]);
+				btDeformableStaticConstraint static_constraint(&psb->m_nodes[j], infoGlobal);
 				m_staticConstraints[i].push_back(static_constraint);
 				m_staticConstraints[i].push_back(static_constraint);
 			}
 			}
 		}
 		}
@@ -139,7 +108,7 @@ void btDeformableContactProjection::setConstraints()
 				continue;
 				continue;
 			}
 			}
 			anchor.m_c1 = anchor.m_cti.m_colObj->getWorldTransform().getBasis() * anchor.m_local;
 			anchor.m_c1 = anchor.m_cti.m_colObj->getWorldTransform().getBasis() * anchor.m_local;
-			btDeformableNodeAnchorConstraint constraint(anchor);
+			btDeformableNodeAnchorConstraint constraint(anchor, infoGlobal);
 			m_nodeAnchorConstraints[i].push_back(constraint);
 			m_nodeAnchorConstraints[i].push_back(constraint);
 		}
 		}
 		
 		
@@ -152,7 +121,7 @@ void btDeformableContactProjection::setConstraints()
 			{
 			{
 				continue;
 				continue;
 			}
 			}
-			btDeformableNodeRigidContactConstraint constraint(contact);
+			btDeformableNodeRigidContactConstraint constraint(contact, infoGlobal);
 			btVector3 va = constraint.getVa();
 			btVector3 va = constraint.getVa();
 			btVector3 vb = constraint.getVb();
 			btVector3 vb = constraint.getVb();
 			const btVector3 vr = vb - va;
 			const btVector3 vr = vb - va;
@@ -173,7 +142,7 @@ void btDeformableContactProjection::setConstraints()
 			{
 			{
 				continue;
 				continue;
 			}
 			}
-			btDeformableFaceRigidContactConstraint constraint(contact);
+			btDeformableFaceRigidContactConstraint constraint(contact, infoGlobal, m_useStrainLimiting);
 			btVector3 va = constraint.getVa();
 			btVector3 va = constraint.getVa();
 			btVector3 vb = constraint.getVb();
 			btVector3 vb = constraint.getVb();
 			const btVector3 vr = vb - va;
 			const btVector3 vr = vb - va;
@@ -184,253 +153,404 @@ void btDeformableContactProjection::setConstraints()
 				m_faceRigidConstraints[i].push_back(constraint);
 				m_faceRigidConstraints[i].push_back(constraint);
 			}
 			}
 		}
 		}
-		
-		// set Deformable Face vs. Deformable Node constraint
-		for (int j = 0; j < psb->m_faceNodeContacts.size(); ++j)
-		{
-			const btSoftBody::DeformableFaceNodeContact& contact = psb->m_faceNodeContacts[j];
-
-			btDeformableFaceNodeContactConstraint constraint(contact);
-			btVector3 va = constraint.getVa();
-			btVector3 vb = constraint.getVb();
-			const btVector3 vr = vb - va;
-			const btScalar dn = btDot(vr, contact.m_normal);
-			if (dn > -SIMD_EPSILON)
-			{
-				m_deformableConstraints[i].push_back(constraint);
-			}
-		}
 	}
 	}
 }
 }
 
 
 void btDeformableContactProjection::project(TVStack& x)
 void btDeformableContactProjection::project(TVStack& x)
 {
 {
-	const int dim = 3;
-	for (int index = 0; index < m_projectionsDict.size(); ++index)
-	{
-		btAlignedObjectArray<btVector3>& projectionDirs = *m_projectionsDict.getAtIndex(index);
-		size_t i = m_projectionsDict.getKeyAtIndex(index).getUid1();
-		if (projectionDirs.size() >= dim)
-		{
-			// static node
-			x[i].setZero();
-			continue;
-		}
-		else if (projectionDirs.size() == 2)
-		{
-			btVector3 dir0 = projectionDirs[0];
-			btVector3 dir1 = projectionDirs[1];
-			btVector3 free_dir = btCross(dir0, dir1);
-			if (free_dir.safeNorm() < SIMD_EPSILON)
-			{
-				x[i] -= x[i].dot(dir0) * dir0;
-				x[i] -= x[i].dot(dir1) * dir1;
-			}
-			else
-			{
-				free_dir.normalize();
-				x[i] = x[i].dot(free_dir) * free_dir;
-			}
-		}
-		else
-		{
-			btAssert(projectionDirs.size() == 1);
-			btVector3 dir0 = projectionDirs[0];
-			x[i] -= x[i].dot(dir0) * dir0;
-		}
-	}
+#ifndef USE_MGS
+    const int dim = 3;
+    for (int index = 0; index < m_projectionsDict.size(); ++index)
+    {
+        btAlignedObjectArray<btVector3>& projectionDirs = *m_projectionsDict.getAtIndex(index);
+        size_t i = m_projectionsDict.getKeyAtIndex(index).getUid1();
+        if (projectionDirs.size() >= dim)
+        {
+            // static node
+            x[i].setZero();
+            continue;
+        }
+        else if (projectionDirs.size() == 2)
+        {
+            btVector3 dir0 = projectionDirs[0];
+            btVector3 dir1 = projectionDirs[1];
+            btVector3 free_dir = btCross(dir0, dir1);
+            if (free_dir.safeNorm() < SIMD_EPSILON)
+            {
+                x[i] -= x[i].dot(dir0) * dir0;
+                x[i] -= x[i].dot(dir1) * dir1;
+            }
+            else
+            {
+                free_dir.normalize();
+                x[i] = x[i].dot(free_dir) * free_dir;
+            }
+        }
+        else
+        {
+            btAssert(projectionDirs.size() == 1);
+            btVector3 dir0 = projectionDirs[0];
+            x[i] -= x[i].dot(dir0) * dir0;
+        }
+    }
+#else
+    btReducedVector p(x.size());
+    for (int i = 0; i < m_projections.size(); ++i)
+    {
+        p += (m_projections[i].dot(x) * m_projections[i]);
+    }
+    for (int i = 0; i < p.m_indices.size(); ++i)
+    {
+        x[p.m_indices[i]] -= p.m_vecs[i];
+    }
+#endif
 }
 }
 
 
 void btDeformableContactProjection::setProjection()
 void btDeformableContactProjection::setProjection()
 {
 {
-	btAlignedObjectArray<btVector3> units;
-	units.push_back(btVector3(1,0,0));
-	units.push_back(btVector3(0,1,0));
-	units.push_back(btVector3(0,0,1));
-	for (int i = 0; i < m_softBodies.size(); ++i)
-	{
-		btSoftBody* psb = m_softBodies[i];
-		if (!psb->isActive())
-		{
-			continue;
-		}
-		for (int j = 0; j < m_staticConstraints[i].size(); ++j)
-		{
-			int index = m_staticConstraints[i][j].m_node->index;
-			if (m_projectionsDict.find(index) == NULL)
+#ifndef USE_MGS
+    BT_PROFILE("btDeformableContactProjection::setProjection");
+    btAlignedObjectArray<btVector3> units;
+    units.push_back(btVector3(1,0,0));
+    units.push_back(btVector3(0,1,0));
+    units.push_back(btVector3(0,0,1));
+    for (int i = 0; i < m_softBodies.size(); ++i)
+    {
+        btSoftBody* psb = m_softBodies[i];
+        if (!psb->isActive())
+        {
+            continue;
+        }
+        for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+        {
+            int index = m_staticConstraints[i][j].m_node->index;
+            m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
+            if (m_projectionsDict.find(index) == NULL)
+            {
+                m_projectionsDict.insert(index, units);
+            }
+            else
+            {
+                btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                for (int k = 0; k < 3; ++k)
+                {
+                    projections.push_back(units[k]);
+                }
+            }
+        }
+        for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+        {
+            int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+            m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
+            if (m_projectionsDict.find(index) == NULL)
+            {
+                m_projectionsDict.insert(index, units);
+            }
+            else
+            {
+                btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                for (int k = 0; k < 3; ++k)
+                {
+                    projections.push_back(units[k]);
+                }
+            }
+        }
+        for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+        {
+            int index = m_nodeRigidConstraints[i][j].m_node->index;
+            m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
+            if (m_nodeRigidConstraints[i][j].m_static)
+            {
+                if (m_projectionsDict.find(index) == NULL)
+                {
+                    m_projectionsDict.insert(index, units);
+                }
+                else
+                {
+                    btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                    for (int k = 0; k < 3; ++k)
+                    {
+                        projections.push_back(units[k]);
+                    }
+                }
+            }
+            else
+            {
+                if (m_projectionsDict.find(index) == NULL)
+                {
+                    btAlignedObjectArray<btVector3> projections;
+                    projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
+                    m_projectionsDict.insert(index, projections);
+                }
+                else
+                {
+                    btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                    projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
+                }
+            }
+        }
+        for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+        {
+            const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+            btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
+            for (int k = 0; k < 3; ++k)
+            {
+                face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
+            }
+            for (int k = 0; k < 3; ++k)
+            {
+                btSoftBody::Node* node = face->m_n[k];
+                node->m_penetration = true;
+                int index = node->index;
+                if (m_faceRigidConstraints[i][j].m_static)
+                {
+                    if (m_projectionsDict.find(index) == NULL)
+                    {
+                        m_projectionsDict.insert(index, units);
+                    }
+                    else
+                    {
+                        btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                        for (int k = 0; k < 3; ++k)
+                        {
+                            projections.push_back(units[k]);
+                        }
+                    }
+                }
+                else
+                {
+                    if (m_projectionsDict.find(index) == NULL)
+                    {
+                        btAlignedObjectArray<btVector3> projections;
+                        projections.push_back(m_faceRigidConstraints[i][j].m_normal);
+                        m_projectionsDict.insert(index, projections);
+                    }
+                    else
+                    {
+                        btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                        projections.push_back(m_faceRigidConstraints[i][j].m_normal);
+                    }
+                }
+            }
+        }
+    }
+#else
+    int dof = 0;
+    for (int i = 0; i < m_softBodies.size(); ++i)
+    {
+        dof += m_softBodies[i]->m_nodes.size();
+    }
+    for (int i = 0; i < m_softBodies.size(); ++i)
+    {
+        btSoftBody* psb = m_softBodies[i];
+        if (!psb->isActive())
+        {
+            continue;
+        }
+        for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+        {
+            int index = m_staticConstraints[i][j].m_node->index;
+            m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
+            btAlignedObjectArray<int> indices;
+            btAlignedObjectArray<btVector3> vecs1,vecs2,vecs3;
+            indices.push_back(index);
+            vecs1.push_back(btVector3(1,0,0));
+            vecs2.push_back(btVector3(0,1,0));
+            vecs3.push_back(btVector3(0,0,1));
+            m_projections.push_back(btReducedVector(dof, indices, vecs1));
+            m_projections.push_back(btReducedVector(dof, indices, vecs2));
+            m_projections.push_back(btReducedVector(dof, indices, vecs3));
+        }
+        
+        for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+        {
+            int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+            m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
+            btAlignedObjectArray<int> indices;
+            btAlignedObjectArray<btVector3> vecs1,vecs2,vecs3;
+            indices.push_back(index);
+            vecs1.push_back(btVector3(1,0,0));
+            vecs2.push_back(btVector3(0,1,0));
+            vecs3.push_back(btVector3(0,0,1));
+            m_projections.push_back(btReducedVector(dof, indices, vecs1));
+            m_projections.push_back(btReducedVector(dof, indices, vecs2));
+            m_projections.push_back(btReducedVector(dof, indices, vecs3));
+        }
+        for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+        {
+            int index = m_nodeRigidConstraints[i][j].m_node->index;
+            m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
+            btAlignedObjectArray<int> indices;
+            indices.push_back(index);
+            btAlignedObjectArray<btVector3> vecs1,vecs2,vecs3;
+            if (m_nodeRigidConstraints[i][j].m_static)
+            {
+                vecs1.push_back(btVector3(1,0,0));
+                vecs2.push_back(btVector3(0,1,0));
+                vecs3.push_back(btVector3(0,0,1));
+                m_projections.push_back(btReducedVector(dof, indices, vecs1));
+                m_projections.push_back(btReducedVector(dof, indices, vecs2));
+                m_projections.push_back(btReducedVector(dof, indices, vecs3));
+            }
+            else
+            {
+                vecs1.push_back(m_nodeRigidConstraints[i][j].m_normal);
+                m_projections.push_back(btReducedVector(dof, indices, vecs1));
+            }
+        }
+        for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+        {
+            const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+			btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
+            btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
+            for (int k = 0; k < 3; ++k)
+            {
+                face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
+            }
+			if (m_faceRigidConstraints[i][j].m_static)
 			{
 			{
-				m_projectionsDict.insert(index, units);
-			}
-			else
-			{
-				btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-				for (int k = 0; k < 3; ++k)
+				for (int l = 0; l < 3; ++l)
 				{
 				{
-					projections.push_back(units[k]);
-				}
-			}
-		}
-		for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
-		{
-			int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
-			if (m_projectionsDict.find(index) == NULL)
-			{
-				m_projectionsDict.insert(index, units);
-			}
-			else
-			{
-				btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-				for (int k = 0; k < 3; ++k)
-				{
-					projections.push_back(units[k]);
-				}
-			}
-		}
-		for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
-		{
-			int index = m_nodeRigidConstraints[i][j].m_node->index;
-			if (m_nodeRigidConstraints[i][j].m_static)
-			{
-				if (m_projectionsDict.find(index) == NULL)
-				{
-					m_projectionsDict.insert(index, units);
-				}
-				else
-				{
-					btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+					
+					btReducedVector rv(dof);
 					for (int k = 0; k < 3; ++k)
 					for (int k = 0; k < 3; ++k)
 					{
 					{
-						projections.push_back(units[k]);
+						rv.m_indices.push_back(face->m_n[k]->index);
+						btVector3 v(0,0,0);
+						v[l] = bary[k];
+						rv.m_vecs.push_back(v);
+                        rv.sort();
 					}
 					}
+					m_projections.push_back(rv);
 				}
 				}
 			}
 			}
 			else
 			else
 			{
 			{
-				if (m_projectionsDict.find(index) == NULL)
-				{
-					btAlignedObjectArray<btVector3> projections;
-					projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
-					m_projectionsDict.insert(index, projections);
-				}
-				else
-				{
-					btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-					projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
-				}
-			}
-		}
-		for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
-		{
-			const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
-			for (int k = 0; k < 3; ++k)
-			{
-				const btSoftBody::Node* node = face->m_n[k];
-				int index = node->index;
-				if (m_faceRigidConstraints[i][j].m_static)
+				btReducedVector rv(dof);
+				for (int k = 0; k < 3; ++k)
 				{
 				{
-					if (m_projectionsDict.find(index) == NULL)
-					{
-						m_projectionsDict.insert(index, units);
-					}
-					else
-					{
-						btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-						for (int k = 0; k < 3; ++k)
-						{
-							projections.push_back(units[k]);
-						}
-					}
-				}
-				else
-				{
-					if (m_projectionsDict.find(index) == NULL)
-					{
-						btAlignedObjectArray<btVector3> projections;
-						projections.push_back(m_faceRigidConstraints[i][j].m_normal);
-						m_projectionsDict.insert(index, projections);
-					}
-					else
-					{
-						btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-						projections.push_back(m_faceRigidConstraints[i][j].m_normal);
-					}
+					rv.m_indices.push_back(face->m_n[k]->index);
+					rv.m_vecs.push_back(bary[k] * m_faceRigidConstraints[i][j].m_normal);
+                    rv.sort();
 				}
 				}
+				m_projections.push_back(rv);
 			}
 			}
 		}
 		}
-		for (int j = 0; j < m_deformableConstraints[i].size(); ++j)
-		{
-			const btSoftBody::Face* face = m_deformableConstraints[i][j].m_face;
-			for (int k = 0; k < 3; ++k)
-			{
-				const btSoftBody::Node* node = face->m_n[k];
-				int index = node->index;
-				if (m_deformableConstraints[i][j].m_static)
-				{
-					if (m_projectionsDict.find(index) == NULL)
-					{
-						m_projectionsDict.insert(index, units);
-					}
-					else
-					{
-						btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-						for (int k = 0; k < 3; ++k)
-						{
-							projections.push_back(units[k]);
-						}
-					}
-				}
-				else
-				{
-					if (m_projectionsDict.find(index) == NULL)
-					{
-						btAlignedObjectArray<btVector3> projections;
-						projections.push_back(m_deformableConstraints[i][j].m_normal);
-						m_projectionsDict.insert(index, projections);
-					}
-					else
-					{
-						btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-						projections.push_back(m_deformableConstraints[i][j].m_normal);
-					}
-				}
-			}
+    }
+    btModifiedGramSchmidt<btReducedVector> mgs(m_projections);
+    mgs.solve();
+    m_projections = mgs.m_out;
+#endif
+}
+
+void btDeformableContactProjection::checkConstraints(const TVStack& x)
+{
+    for (int i = 0; i < m_lagrangeMultipliers.size(); ++i)
+    {
+        btVector3 d(0,0,0);
+        const LagrangeMultiplier& lm = m_lagrangeMultipliers[i];
+        for (int j = 0; j < lm.m_num_constraints; ++j)
+        {
+            for (int k = 0; k < lm.m_num_nodes; ++k)
+            {
+                d[j] += lm.m_weights[k] * x[lm.m_indices[k]].dot(lm.m_dirs[j]);
+            }
+        }
+        printf("d = %f, %f, %f\n",d[0],d[1],d[2]);
+    }
+}
+
+void btDeformableContactProjection::setLagrangeMultiplier()
+{
+    for (int i = 0; i < m_softBodies.size(); ++i)
+    {
+        btSoftBody* psb = m_softBodies[i];
+        if (!psb->isActive())
+        {
+            continue;
+        }
+        for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+        {
+            int index = m_staticConstraints[i][j].m_node->index;
+            m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
+            LagrangeMultiplier lm;
+            lm.m_num_nodes = 1;
+            lm.m_indices[0] = index;
+            lm.m_weights[0] = 1.0;
+            lm.m_num_constraints = 3;
+            lm.m_dirs[0] = btVector3(1,0,0);
+            lm.m_dirs[1] = btVector3(0,1,0);
+            lm.m_dirs[2] = btVector3(0,0,1);
+            m_lagrangeMultipliers.push_back(lm);
+        }
+        for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+        {
+            int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+            m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
+            LagrangeMultiplier lm;
+            lm.m_num_nodes = 1;
+            lm.m_indices[0] = index;
+            lm.m_weights[0] = 1.0;
+            lm.m_num_constraints = 3;
+            lm.m_dirs[0] = btVector3(1,0,0);
+            lm.m_dirs[1] = btVector3(0,1,0);
+            lm.m_dirs[2] = btVector3(0,0,1);
+            m_lagrangeMultipliers.push_back(lm);
+        }
+        for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+        {
+            int index = m_nodeRigidConstraints[i][j].m_node->index;
+            m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
+            LagrangeMultiplier lm;
+            lm.m_num_nodes = 1;
+            lm.m_indices[0] = index;
+            lm.m_weights[0] = 1.0;
+            if (m_nodeRigidConstraints[i][j].m_static)
+            {
+                lm.m_num_constraints = 3;
+                lm.m_dirs[0] = btVector3(1,0,0);
+                lm.m_dirs[1] = btVector3(0,1,0);
+                lm.m_dirs[2] = btVector3(0,0,1);
+            }
+            else
+            {
+                lm.m_num_constraints = 1;
+                lm.m_dirs[0] = m_nodeRigidConstraints[i][j].m_normal;
+            }
+            m_lagrangeMultipliers.push_back(lm);
+        }
+        for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+        {
+            const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
 			
 			
-			const btSoftBody::Node* node = m_deformableConstraints[i][j].m_node;
-			int index = node->index;
-			if (m_deformableConstraints[i][j].m_static)
+            btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
+            btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
+			LagrangeMultiplier lm;
+			lm.m_num_nodes = 3;
+			for (int k = 0; k<3; ++k)
 			{
 			{
-				if (m_projectionsDict.find(index) == NULL)
-				{
-					m_projectionsDict.insert(index, units);
-				}
-				else
-				{
-					btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-					for (int k = 0; k < 3; ++k)
-					{
-						projections.push_back(units[k]);
-					}
-				}
+				face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
+				lm.m_indices[k] = face->m_n[k]->index;
+				lm.m_weights[k] = bary[k];
+			}
+            if (m_faceRigidConstraints[i][j].m_static)
+            {
+				lm.m_num_constraints = 3;
+				lm.m_dirs[0] = btVector3(1,0,0);
+				lm.m_dirs[1] = btVector3(0,1,0);
+				lm.m_dirs[2] = btVector3(0,0,1);
 			}
 			}
 			else
 			else
 			{
 			{
-				if (m_projectionsDict.find(index) == NULL)
-				{
-					btAlignedObjectArray<btVector3> projections;
-					projections.push_back(m_deformableConstraints[i][j].m_normal);
-					m_projectionsDict.insert(index, projections);
-				}
-				else
-				{
-					btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
-					projections.push_back(m_deformableConstraints[i][j].m_normal);
-				}
+				lm.m_num_constraints = 1;
+				lm.m_dirs[0] = m_faceRigidConstraints[i][j].m_normal;
 			}
 			}
+            m_lagrangeMultipliers.push_back(lm);
 		}
 		}
 	}
 	}
 }
 }
 
 
-
+//
 void btDeformableContactProjection::applyDynamicFriction(TVStack& f)
 void btDeformableContactProjection::applyDynamicFriction(TVStack& f)
 {
 {
 	for (int i = 0; i < m_softBodies.size(); ++i)
 	for (int i = 0; i < m_softBodies.size(); ++i)
@@ -502,7 +622,12 @@ void btDeformableContactProjection::reinitialize(bool nodeUpdated)
 		m_faceRigidConstraints[i].clear();
 		m_faceRigidConstraints[i].clear();
 		m_deformableConstraints[i].clear();
 		m_deformableConstraints[i].clear();
 	}
 	}
-	m_projectionsDict.clear();
+#ifndef USE_MGS
+    m_projectionsDict.clear();
+#else
+    m_projections.clear();
+#endif
+    m_lagrangeMultipliers.clear();
 }
 }
 
 
 
 

+ 28 - 18
thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h

@@ -21,30 +21,37 @@
 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
 #include "btDeformableContactConstraint.h"
 #include "btDeformableContactConstraint.h"
 #include "LinearMath/btHashMap.h"
 #include "LinearMath/btHashMap.h"
+#include "LinearMath/btReducedVector.h"
+#include "LinearMath/btModifiedGramSchmidt.h"
 #include <vector>
 #include <vector>
+
+struct LagrangeMultiplier
+{
+    int m_num_constraints;        // Number of constraints
+    int m_num_nodes;              // Number of nodes in these constraints
+    btScalar m_weights[3];        // weights of the nodes involved, same size as m_num_nodes
+    btVector3 m_dirs[3];          // Constraint directions, same size of m_num_constraints;
+    int m_indices[3];             // indices of the nodes involved, same size as m_num_nodes;
+};
+
+
 class btDeformableContactProjection
 class btDeformableContactProjection
 {
 {
 public:
 public:
     typedef btAlignedObjectArray<btVector3> TVStack;
     typedef btAlignedObjectArray<btVector3> TVStack;
     btAlignedObjectArray<btSoftBody *>& m_softBodies;
     btAlignedObjectArray<btSoftBody *>& m_softBodies;
-    
-//    // map from node index to static constraint
-//    btHashMap<btHashInt, btDeformableStaticConstraint> m_staticConstraints;
-//    // map from node index to node rigid constraint
-//    btHashMap<btHashInt, btAlignedObjectArray<btDeformableNodeRigidContactConstraint> > m_nodeRigidConstraints;
-//    // map from node index to face rigid constraint
-//    btHashMap<btHashInt, btAlignedObjectArray<btDeformableFaceRigidContactConstraint*> > m_faceRigidConstraints;
-//    // map from node index to deformable constraint
-//    btHashMap<btHashInt, btAlignedObjectArray<btDeformableFaceNodeContactConstraint*> > m_deformableConstraints;
-//    // map from node index to node anchor constraint
-//    btHashMap<btHashInt, btDeformableNodeAnchorConstraint> m_nodeAnchorConstraints;
 	
 	
     // all constraints involving face
     // all constraints involving face
     btAlignedObjectArray<btDeformableContactConstraint*> m_allFaceConstraints;
     btAlignedObjectArray<btDeformableContactConstraint*> m_allFaceConstraints;
-    
+#ifndef USE_MGS
     // map from node index to projection directions
     // map from node index to projection directions
     btHashMap<btHashInt, btAlignedObjectArray<btVector3> > m_projectionsDict;
     btHashMap<btHashInt, btAlignedObjectArray<btVector3> > m_projectionsDict;
-	
+#else
+    btAlignedObjectArray<btReducedVector> m_projections;
+#endif
+    
+    btAlignedObjectArray<LagrangeMultiplier> m_lagrangeMultipliers;
+    
 	// map from node index to static constraint
 	// map from node index to static constraint
 	btAlignedObjectArray<btAlignedObjectArray<btDeformableStaticConstraint> > m_staticConstraints;
 	btAlignedObjectArray<btAlignedObjectArray<btDeformableStaticConstraint> > m_staticConstraints;
 	// map from node index to node rigid constraint
 	// map from node index to node rigid constraint
@@ -56,6 +63,8 @@ public:
 	// map from node index to node anchor constraint
 	// map from node index to node anchor constraint
 	btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeAnchorConstraint> > m_nodeAnchorConstraints;
 	btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeAnchorConstraint> > m_nodeAnchorConstraints;
     
     
+    bool m_useStrainLimiting;
+    
     btDeformableContactProjection(btAlignedObjectArray<btSoftBody *>& softBodies)
     btDeformableContactProjection(btAlignedObjectArray<btSoftBody *>& softBodies)
     : m_softBodies(softBodies)
     : m_softBodies(softBodies)
     {
     {
@@ -72,13 +81,10 @@ public:
     virtual void applyDynamicFriction(TVStack& f);
     virtual void applyDynamicFriction(TVStack& f);
     
     
     // update and solve the constraints
     // update and solve the constraints
-    virtual btScalar update(btCollisionObject** deformableBodies,int numDeformableBodies);
-    
-    // solve the position error using split impulse
-    virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
+    virtual btScalar update(btCollisionObject** deformableBodies,int numDeformableBodies, const btContactSolverInfo& infoGlobal);
     
     
     // Add constraints to m_constraints. In addition, the constraints that each vertex own are recorded in m_constraintsDict.
     // Add constraints to m_constraints. In addition, the constraints that each vertex own are recorded in m_constraintsDict.
-    virtual void setConstraints();
+    virtual void setConstraints(const btContactSolverInfo& infoGlobal);
     
     
     // Set up projections for each vertex by adding the projection direction to
     // Set up projections for each vertex by adding the projection direction to
     virtual void setProjection();
     virtual void setProjection();
@@ -86,5 +92,9 @@ public:
     virtual void reinitialize(bool nodeUpdated);
     virtual void reinitialize(bool nodeUpdated);
     
     
     virtual void splitImpulseSetup(const btContactSolverInfo& infoGlobal);
     virtual void splitImpulseSetup(const btContactSolverInfo& infoGlobal);
+    
+    virtual void setLagrangeMultiplier();
+    
+    void checkConstraints(const TVStack& x);
 };
 };
 #endif /* btDeformableContactProjection_h */
 #endif /* btDeformableContactProjection_h */

+ 2 - 0
thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h

@@ -114,6 +114,8 @@ public:
     {
     {
     }
     }
     
     
+    virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA){}
+    
     virtual btDeformableLagrangianForceType getForceType()
     virtual btDeformableLagrangianForceType getForceType()
     {
     {
         return BT_COROTATED_FORCE;
         return BT_COROTATED_FORCE;

+ 2 - 0
thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h

@@ -50,6 +50,8 @@ public:
     {
     {
     }
     }
     
     
+    virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA){}
+    
     virtual void addScaledGravityForce(btScalar scale, TVStack& force)
     virtual void addScaledGravityForce(btScalar scale, TVStack& force)
     {
     {
         int numNodes = getNumNodes();
         int numNodes = getNumNodes();

+ 10 - 1
thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h

@@ -26,7 +26,8 @@ enum btDeformableLagrangianForceType
     BT_MASSSPRING_FORCE = 2,
     BT_MASSSPRING_FORCE = 2,
     BT_COROTATED_FORCE = 3,
     BT_COROTATED_FORCE = 3,
     BT_NEOHOOKEAN_FORCE = 4,
     BT_NEOHOOKEAN_FORCE = 4,
-    BT_LINEAR_ELASTICITY_FORCE = 5
+    BT_LINEAR_ELASTICITY_FORCE = 5,
+    BT_MOUSE_PICKING_FORCE = 6
 };
 };
 
 
 static inline double randomDouble(double low, double high)
 static inline double randomDouble(double low, double high)
@@ -53,6 +54,9 @@ public:
     // add damping df
     // add damping df
     virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df) = 0;
     virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df) = 0;
     
     
+    // build diagonal of A matrix
+    virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) = 0;
+    
     // add elastic df
     // add elastic df
     virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df) = 0;
     virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df) = 0;
     
     
@@ -85,6 +89,11 @@ public:
         m_softBodies.push_back(psb);
         m_softBodies.push_back(psb);
     }
     }
     
     
+    virtual void removeSoftBody(btSoftBody* psb)
+    {
+        m_softBodies.remove(psb);
+    }
+    
     virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
     virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
     {
     {
         m_nodes = nodes;
         m_nodes = nodes;

+ 46 - 0
thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h

@@ -149,6 +149,52 @@ public:
         }
         }
     }
     }
     
     
+    virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA)
+    {
+        // implicit damping force differential
+        for (int i = 0; i < m_softBodies.size(); ++i)
+        {
+            btSoftBody* psb = m_softBodies[i];
+            if (!psb->isActive())
+            {
+                continue;
+            }
+            btScalar scaled_k_damp = m_dampingStiffness * scale;
+            for (int j = 0; j < psb->m_links.size(); ++j)
+            {
+                const btSoftBody::Link& link = psb->m_links[j];
+                btSoftBody::Node* node1 = link.m_n[0];
+                btSoftBody::Node* node2 = link.m_n[1];
+                size_t id1 = node1->index;
+                size_t id2 = node2->index;
+                if (m_momentum_conserving)
+                {
+                    if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+                    {
+                        btVector3 dir = (node2->m_x - node1->m_x).normalized();
+                        for (int d = 0; d < 3; ++d)
+                        {
+                            if (node1->m_im > 0)
+                                diagA[id1][d] -= scaled_k_damp * dir[d] * dir[d];
+                            if (node2->m_im > 0)
+                                diagA[id2][d] -= scaled_k_damp * dir[d] * dir[d];
+                        }
+                    }
+                }
+                else
+                {
+                    for (int d = 0; d < 3; ++d)
+                    {
+                        if (node1->m_im > 0)
+                            diagA[id1][d] -= scaled_k_damp;
+                        if (node2->m_im > 0)
+                            diagA[id2][d] -= scaled_k_damp;
+                    }
+                }
+            }
+        }
+    }
+    
     virtual double totalElasticEnergy(btScalar dt)
     virtual double totalElasticEnergy(btScalar dt)
     {
     {
         double energy = 0;
         double energy = 0;

+ 145 - 0
thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h

@@ -0,0 +1,145 @@
+/*
+ Written by Xuchen Han <[email protected]>
+ 
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 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.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_MOUSE_PICKING_FORCE_H
+#define BT_MOUSE_PICKING_FORCE_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableMousePickingForce : public btDeformableLagrangianForce
+{
+    // If true, the damping force will be in the direction of the spring
+    // If false, the damping force will be in the direction of the velocity
+    btScalar m_elasticStiffness, m_dampingStiffness;
+    const btSoftBody::Face& m_face;
+    btVector3 m_mouse_pos;
+    btScalar m_maxForce;
+public:
+    typedef btAlignedObjectArray<btVector3> TVStack;
+    btDeformableMousePickingForce(btScalar k, btScalar d, const btSoftBody::Face& face, btVector3 mouse_pos, btScalar maxForce = 0.3) : m_elasticStiffness(k), m_dampingStiffness(d), m_face(face), m_mouse_pos(mouse_pos),  m_maxForce(maxForce)
+    {
+    }
+    
+    virtual void addScaledForces(btScalar scale, TVStack& force)
+    {
+        addScaledDampingForce(scale, force);
+        addScaledElasticForce(scale, force);
+    }
+    
+    virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+    {
+        addScaledElasticForce(scale, force);
+    }
+    
+    virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+    {
+        for (int i = 0; i < 3; ++i)
+        {
+            btVector3 v_diff = m_face.m_n[i]->m_v;
+            btVector3 scaled_force = scale * m_dampingStiffness * v_diff;
+            if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+            {
+                btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+                scaled_force = scale * m_dampingStiffness * v_diff.dot(dir) * dir;
+            }
+            force[m_face.m_n[i]->index] -= scaled_force;
+        }
+    }
+    
+    virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+    {
+        btScalar scaled_stiffness = scale * m_elasticStiffness;
+        for (int i = 0; i < 3; ++i)
+        {
+            btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
+            btVector3 scaled_force = scaled_stiffness * dir;
+            if (scaled_force.safeNorm() > m_maxForce)
+            {
+                scaled_force.safeNormalize();
+                scaled_force *= m_maxForce;
+            }
+            force[m_face.m_n[i]->index] -= scaled_force;
+        }
+    }
+    
+    virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+    {
+        btScalar scaled_k_damp = m_dampingStiffness * scale;
+        for (int i = 0; i < 3; ++i)
+        {
+            btVector3 local_scaled_df = scaled_k_damp * dv[m_face.m_n[i]->index];
+            if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+            {
+                btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+                local_scaled_df= scaled_k_damp * dv[m_face.m_n[i]->index].dot(dir) * dir;
+            }
+            df[m_face.m_n[i]->index] -= local_scaled_df;
+        }
+    }
+    
+    virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA){}
+    
+    virtual double totalElasticEnergy(btScalar dt)
+    {
+        double energy = 0;
+        for (int i = 0; i < 3; ++i)
+        {
+            btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
+            btVector3 scaled_force = m_elasticStiffness * dir;
+            if (scaled_force.safeNorm() > m_maxForce)
+            {
+                scaled_force.safeNormalize();
+                scaled_force *= m_maxForce;
+            }
+            energy += 0.5 * scaled_force.dot(dir);
+        }
+        return energy;
+    }
+    
+    virtual double totalDampingEnergy(btScalar dt)
+    {
+        double energy = 0;
+        for (int i = 0; i < 3; ++i)
+        {
+            btVector3 v_diff = m_face.m_n[i]->m_v;
+            btVector3 scaled_force = m_dampingStiffness * v_diff;
+            if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+            {
+                btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+                scaled_force = m_dampingStiffness * v_diff.dot(dir) * dir;
+            }
+            energy -= scaled_force.dot(m_face.m_n[i]->m_v) / dt;
+        }
+        return energy;
+    }
+    
+    virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+    {
+        //TODO
+    }
+    
+    void setMousePos(const btVector3& p)
+    {
+        m_mouse_pos = p;
+    }
+    
+    virtual btDeformableLagrangianForceType getForceType()
+    {
+        return BT_MOUSE_PICKING_FORCE;
+    }
+    
+};
+
+#endif /* btMassSpring_h */

+ 4 - 4
thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp

@@ -32,7 +32,7 @@ btScalar btDeformableMultiBodyConstraintSolver::solveDeformableGroupIterations(b
             m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
             m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
             // solver body velocity -> rigid body velocity
             // solver body velocity -> rigid body velocity
             solverBodyWriteBack(infoGlobal);
             solverBodyWriteBack(infoGlobal);
-            btScalar deformableResidual = m_deformableSolver->solveContactConstraints(deformableBodies,numDeformableBodies);
+            btScalar deformableResidual = m_deformableSolver->solveContactConstraints(deformableBodies,numDeformableBodies, infoGlobal);
             // update rigid body velocity in rigid/deformable contact
             // update rigid body velocity in rigid/deformable contact
             m_leastSquaresResidual = btMax(m_leastSquaresResidual, deformableResidual);
             m_leastSquaresResidual = btMax(m_leastSquaresResidual, deformableResidual);
             // solver body velocity <- rigid body velocity
             // solver body velocity <- rigid body velocity
@@ -112,7 +112,7 @@ void btDeformableMultiBodyConstraintSolver::solveGroupCacheFriendlySplitImpulseI
     if (infoGlobal.m_splitImpulse)
     if (infoGlobal.m_splitImpulse)
     {
     {
         {
         {
-            m_deformableSolver->splitImpulseSetup(infoGlobal);
+//            m_deformableSolver->splitImpulseSetup(infoGlobal);
             for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
             for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
             {
             {
                 btScalar leastSquaresResidual = 0.f;
                 btScalar leastSquaresResidual = 0.f;
@@ -127,8 +127,8 @@ void btDeformableMultiBodyConstraintSolver::solveGroupCacheFriendlySplitImpulseI
                         leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
                         leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
                     }
                     }
                     // solve the position correction between deformable and rigid/multibody
                     // solve the position correction between deformable and rigid/multibody
-                    btScalar residual = m_deformableSolver->solveSplitImpulse(infoGlobal);
-                    leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+//                    btScalar residual = m_deformableSolver->solveSplitImpulse(infoGlobal);
+//                    leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
                 }
                 }
                 if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
                 if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
                 {
                 {

+ 171 - 16
thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp

@@ -22,7 +22,6 @@ Call internalStepSimulation multiple times, to achieve 240Hz (4 steps of 60Hz).
 2. Detect discrete collisions between rigid and deformable bodies at position x_{n+1}^* = x_n + dt * v_{n+1}^*.
 2. Detect discrete collisions between rigid and deformable bodies at position x_{n+1}^* = x_n + dt * v_{n+1}^*.
 
 
 3a. Solve all constraints, including LCP. Contact, position correction due to numerical drift, friction, and anchors for deformable.
 3a. Solve all constraints, including LCP. Contact, position correction due to numerical drift, friction, and anchors for deformable.
-    TODO: add option for positional drift correction (using vel_target += erp * pos_error/dt
 
 
 3b. 5 Newton steps (multiple step). Conjugent Gradient solves linear system. Deformable Damping: Then velocities of deformable bodies v_{n+1} are solved in
 3b. 5 Newton steps (multiple step). Conjugent Gradient solves linear system. Deformable Damping: Then velocities of deformable bodies v_{n+1} are solved in
         M(v_{n+1} - v_{n+1}^*) = damping_force * dt / mass,
         M(v_{n+1} - v_{n+1}^*) = damping_force * dt / mass,
@@ -58,14 +57,20 @@ m_deformableBodySolver(deformableBodySolver), m_solverCallback(0)
 	m_sbi.water_density = 0;
 	m_sbi.water_density = 0;
 	m_sbi.water_offset = 0;
 	m_sbi.water_offset = 0;
 	m_sbi.water_normal = btVector3(0, 0, 0);
 	m_sbi.water_normal = btVector3(0, 0, 0);
-	m_sbi.m_gravity.setValue(0, -10, 0);
+	m_sbi.m_gravity.setValue(0, -9.8, 0);
 	m_internalTime = 0.0;
 	m_internalTime = 0.0;
 	m_implicit = false;
 	m_implicit = false;
 	m_lineSearch = false;
 	m_lineSearch = false;
-	m_selfCollision = true;
+    m_useProjection = true;
+	m_ccdIterations = 5;
 	m_solverDeformableBodyIslandCallback = new DeformableBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
 	m_solverDeformableBodyIslandCallback = new DeformableBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
 }
 }
 
 
+btDeformableMultiBodyDynamicsWorld::~btDeformableMultiBodyDynamicsWorld()
+{
+    delete m_solverDeformableBodyIslandCallback;
+}
+
 void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
 void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
 {
 {
     BT_PROFILE("internalSingleStepSimulation");
     BT_PROFILE("internalSingleStepSimulation");
@@ -74,20 +79,16 @@ void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar t
         (*m_internalPreTickCallback)(this, timeStep);
         (*m_internalPreTickCallback)(this, timeStep);
     }
     }
     reinitialize(timeStep);
     reinitialize(timeStep);
+    
     // add gravity to velocity of rigid and multi bodys
     // add gravity to velocity of rigid and multi bodys
     applyRigidBodyGravity(timeStep);
     applyRigidBodyGravity(timeStep);
     
     
     ///apply gravity and explicit force to velocity, predict motion
     ///apply gravity and explicit force to velocity, predict motion
     predictUnconstraintMotion(timeStep);
     predictUnconstraintMotion(timeStep);
     
     
-    ///perform collision detection
+    ///perform collision detection that involves rigid/multi bodies
     btMultiBodyDynamicsWorld::performDiscreteCollisionDetection();
     btMultiBodyDynamicsWorld::performDiscreteCollisionDetection();
     
     
-    if (m_selfCollision)
-    {
-        softBodySelfCollision();
-    }
-    
     btMultiBodyDynamicsWorld::calculateSimulationIslands();
     btMultiBodyDynamicsWorld::calculateSimulationIslands();
     
     
     beforeSolverCallbacks(timeStep);
     beforeSolverCallbacks(timeStep);
@@ -96,7 +97,13 @@ void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar t
     solveConstraints(timeStep);
     solveConstraints(timeStep);
     
     
     afterSolverCallbacks(timeStep);
     afterSolverCallbacks(timeStep);
-    
+
+	performDeformableCollisionDetection();
+
+    applyRepulsionForce(timeStep);
+
+    performGeometricCollisions(timeStep);
+
     integrateTransforms(timeStep);
     integrateTransforms(timeStep);
     
     
     ///update vehicle simulation
     ///update vehicle simulation
@@ -107,6 +114,27 @@ void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar t
     // ///////////////////////////////
     // ///////////////////////////////
 }
 }
 
 
+void btDeformableMultiBodyDynamicsWorld::performDeformableCollisionDetection()
+{
+	for (int i = 0; i < m_softBodies.size(); ++i)
+	{
+		m_softBodies[i]->m_softSoftCollision = true;
+	}
+	
+	for (int i = 0; i < m_softBodies.size(); ++i)
+	{
+		for (int j = i; j < m_softBodies.size(); ++j)
+		{
+			m_softBodies[i]->defaultCollisionHandler(m_softBodies[j]);
+		}
+	}
+	
+	for (int i = 0; i < m_softBodies.size(); ++i)
+	{
+		m_softBodies[i]->m_softSoftCollision = false;
+	}
+}
+
 void btDeformableMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
 void btDeformableMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
 {
 {
     for (int i = 0; i < m_softBodies.size(); i++)
     for (int i = 0; i < m_softBodies.size(); i++)
@@ -131,10 +159,106 @@ void btDeformableMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep
     btMultiBodyDynamicsWorld::updateActivationState(timeStep);
     btMultiBodyDynamicsWorld::updateActivationState(timeStep);
 }
 }
 
 
+void btDeformableMultiBodyDynamicsWorld::applyRepulsionForce(btScalar timeStep)
+{
+    BT_PROFILE("btDeformableMultiBodyDynamicsWorld::applyRepulsionForce");
+    for (int i = 0; i < m_softBodies.size(); i++)
+    {
+        btSoftBody* psb = m_softBodies[i];
+        if (psb->isActive())
+        {
+			psb->applyRepulsionForce(timeStep, true);
+        }
+    }
+}
+
+void btDeformableMultiBodyDynamicsWorld::performGeometricCollisions(btScalar timeStep)
+{
+	BT_PROFILE("btDeformableMultiBodyDynamicsWorld::performGeometricCollisions");
+    // refit the BVH tree for CCD
+	for (int i = 0; i < m_softBodies.size(); ++i)
+	{
+		btSoftBody* psb = m_softBodies[i];
+		if (psb->isActive())
+		{
+			m_softBodies[i]->updateFaceTree(true, false);
+			m_softBodies[i]->updateNodeTree(true, false);
+			for (int j = 0; j < m_softBodies[i]->m_faces.size(); ++j)
+			{
+				btSoftBody::Face& f = m_softBodies[i]->m_faces[j];
+				f.m_n0 = (f.m_n[1]->m_x - f.m_n[0]->m_x).cross(f.m_n[2]->m_x - f.m_n[0]->m_x);
+			}
+		}
+	}
+
+	// clear contact points & update DBVT
+	for (int r = 0; r < m_ccdIterations; ++r)
+	{
+		for (int i = 0; i < m_softBodies.size(); ++i)
+		{
+			btSoftBody* psb = m_softBodies[i];
+			if (psb->isActive())
+			{
+				// clear contact points in the previous iteration
+				psb->m_faceNodeContacts.clear();
+
+				// update m_q and normals for CCD calculation
+				for (int j = 0; j < psb->m_nodes.size(); ++j)
+				{
+					psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + timeStep * psb->m_nodes[j].m_v;
+				}
+				for (int j = 0; j < psb->m_faces.size(); ++j)
+				{
+					btSoftBody::Face& f = psb->m_faces[j];
+					f.m_n1 = (f.m_n[1]->m_q - f.m_n[0]->m_q).cross(f.m_n[2]->m_q - f.m_n[0]->m_q);
+					f.m_vn = (f.m_n[1]->m_v - f.m_n[0]->m_v).cross(f.m_n[2]->m_v - f.m_n[0]->m_v) * timeStep * timeStep;
+				}
+			}
+        }
+
+		// apply CCD to register new contact points
+		for (int i = 0; i < m_softBodies.size(); ++i)
+		{
+			for (int j = i; j < m_softBodies.size(); ++j)
+			{
+				btSoftBody* psb1 = m_softBodies[i];
+				btSoftBody* psb2 = m_softBodies[j];
+				if (psb1->isActive() && psb2->isActive())
+				{
+					m_softBodies[i]->geometricCollisionHandler(m_softBodies[j]);
+				}
+			}
+        }
+
+		int penetration_count = 0;
+		for (int i = 0; i < m_softBodies.size(); ++i)
+		{
+			btSoftBody* psb = m_softBodies[i];
+			if (psb->isActive())
+			{
+				penetration_count += psb->m_faceNodeContacts.size();
+			}
+		}
+		if (penetration_count == 0)
+		{
+			break;
+		}
+
+		// apply inelastic impulse
+		for (int i = 0; i < m_softBodies.size(); ++i)
+		{
+			btSoftBody* psb = m_softBodies[i];
+			if (psb->isActive())
+			{
+				psb->applyRepulsionForce(timeStep, false);
+			}
+		}
+	}
+}
 
 
 void btDeformableMultiBodyDynamicsWorld::softBodySelfCollision()
 void btDeformableMultiBodyDynamicsWorld::softBodySelfCollision()
 {
 {
-    m_deformableBodySolver->updateSoftBodies();
+    BT_PROFILE("btDeformableMultiBodyDynamicsWorld::softBodySelfCollision");
     for (int i = 0; i < m_softBodies.size(); i++)
     for (int i = 0; i < m_softBodies.size(); i++)
     {
     {
         btSoftBody* psb = m_softBodies[i];
         btSoftBody* psb = m_softBodies[i];
@@ -192,8 +316,6 @@ void btDeformableMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
                 }
                 }
             }
             }
             node.m_x  =  node.m_x + timeStep * node.m_v;
             node.m_x  =  node.m_x + timeStep * node.m_v;
-            node.m_v -= node.m_vsplit;
-            node.m_vsplit.setZero();
             node.m_q = node.m_x;
             node.m_q = node.m_x;
             node.m_vn = node.m_v;
             node.m_vn = node.m_v;
         }
         }
@@ -255,6 +377,7 @@ void btDeformableMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
 
 
 void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
 void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
 {
 {
+    BT_PROFILE("btDeformableMultiBodyDynamicsWorld::solveConstraints");
     // save v_{n+1}^* velocity after explicit forces
     // save v_{n+1}^* velocity after explicit forces
     m_deformableBodySolver->backupVelocity();
     m_deformableBodySolver->backupVelocity();
     
     
@@ -265,8 +388,11 @@ void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
     solveContactConstraints();
     solveContactConstraints();
     
     
     // set up the directions in which the velocity does not change in the momentum solve
     // set up the directions in which the velocity does not change in the momentum solve
-    m_deformableBodySolver->m_objective->m_projection.setProjection();
-    
+    if (m_useProjection)
+        m_deformableBodySolver->m_objective->m_projection.setProjection();
+    else
+        m_deformableBodySolver->m_objective->m_projection.setLagrangeMultiplier();
+
     // for explicit scheme, m_backupVelocity = v_{n+1}^*
     // for explicit scheme, m_backupVelocity = v_{n+1}^*
     // for implicit scheme, m_backupVelocity = v_n
     // for implicit scheme, m_backupVelocity = v_n
     // Here, set dv = v_{n+1} - v_n for nodes in contact
     // Here, set dv = v_{n+1} - v_n for nodes in contact
@@ -280,7 +406,7 @@ void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
 void btDeformableMultiBodyDynamicsWorld::setupConstraints()
 void btDeformableMultiBodyDynamicsWorld::setupConstraints()
 {
 {
     // set up constraints between multibody and deformable bodies
     // set up constraints between multibody and deformable bodies
-    m_deformableBodySolver->setConstraints();
+    m_deformableBodySolver->setConstraints(m_solverInfo);
     
     
     // set up constraints among multibodies
     // set up constraints among multibodies
     {
     {
@@ -403,6 +529,17 @@ void btDeformableMultiBodyDynamicsWorld::reinitialize(btScalar timeStep)
     dispatchInfo.m_stepCount = 0;
     dispatchInfo.m_stepCount = 0;
     dispatchInfo.m_debugDraw = btMultiBodyDynamicsWorld::getDebugDrawer();
     dispatchInfo.m_debugDraw = btMultiBodyDynamicsWorld::getDebugDrawer();
     btMultiBodyDynamicsWorld::getSolverInfo().m_timeStep = timeStep;
     btMultiBodyDynamicsWorld::getSolverInfo().m_timeStep = timeStep;
+    if (m_useProjection)
+    {
+        m_deformableBodySolver->m_useProjection = true;
+//        m_deformableBodySolver->m_objective->m_projection.m_useStrainLimiting = true;
+        m_deformableBodySolver->m_objective->m_preconditioner =  m_deformableBodySolver->m_objective->m_massPreconditioner;
+    }
+    else
+    {
+        m_deformableBodySolver->m_objective->m_preconditioner =  m_deformableBodySolver->m_objective->m_KKTPreconditioner;
+    }
+        
 }
 }
 
 
 
 
@@ -566,6 +703,24 @@ void btDeformableMultiBodyDynamicsWorld::addForce(btSoftBody* psb, btDeformableL
     }
     }
 }
 }
 
 
+void btDeformableMultiBodyDynamicsWorld::removeForce(btSoftBody* psb, btDeformableLagrangianForce* force)
+{
+    btAlignedObjectArray<btDeformableLagrangianForce*>& forces = m_deformableBodySolver->m_objective->m_lf;
+    int removed_index = -1;
+    for (int i = 0; i < forces.size(); ++i)
+    {
+        if (forces[i]->getForceType() == force->getForceType())
+        {
+            forces[i]->removeSoftBody(psb);
+            if (forces[i]->m_softBodies.size() == 0)
+                removed_index = i;
+            break;
+        }
+    }
+    if (removed_index >= 0)
+        forces.removeAtIndex(removed_index);
+}
+
 void btDeformableMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
 void btDeformableMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
 {
 {
     m_softBodies.remove(body);
     m_softBodies.remove(body);

+ 151 - 5
thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h

@@ -46,10 +46,10 @@ class btDeformableMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
     bool m_drawClusterTree;
     bool m_drawClusterTree;
     btSoftBodyWorldInfo m_sbi;
     btSoftBodyWorldInfo m_sbi;
     btScalar m_internalTime;
     btScalar m_internalTime;
-    int m_contact_iterations;
+    int m_ccdIterations;
     bool m_implicit;
     bool m_implicit;
     bool m_lineSearch;
     bool m_lineSearch;
-    bool m_selfCollision;
+    bool m_useProjection;
     DeformableBodyInplaceSolverIslandCallback* m_solverDeformableBodyIslandCallback;
     DeformableBodyInplaceSolverIslandCallback* m_solverDeformableBodyIslandCallback;
     
     
     typedef void (*btSolverCallback)(btScalar time, btDeformableMultiBodyDynamicsWorld* world);
     typedef void (*btSolverCallback)(btScalar time, btDeformableMultiBodyDynamicsWorld* world);
@@ -80,9 +80,7 @@ public:
         m_solverCallback = cb;
         m_solverCallback = cb;
     }
     }
     
     
-    virtual ~btDeformableMultiBodyDynamicsWorld()
-    {
-    }
+    virtual ~btDeformableMultiBodyDynamicsWorld();
     
     
     virtual btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld()
     virtual btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld()
     {
     {
@@ -133,6 +131,8 @@ public:
     
     
     void addForce(btSoftBody* psb, btDeformableLagrangianForce* force);
     void addForce(btSoftBody* psb, btDeformableLagrangianForce* force);
     
     
+    void removeForce(btSoftBody* psb, btDeformableLagrangianForce* force);
+    
     void removeSoftBody(btSoftBody* body);
     void removeSoftBody(btSoftBody* body);
     
     
     void removeCollisionObject(btCollisionObject* collisionObject);
     void removeCollisionObject(btCollisionObject* collisionObject);
@@ -142,6 +142,8 @@ public:
     
     
     void setupConstraints();
     void setupConstraints();
     
     
+    void performDeformableCollisionDetection();
+    
     void solveMultiBodyConstraints();
     void solveMultiBodyConstraints();
     
     
     void solveContactConstraints();
     void solveContactConstraints();
@@ -159,7 +161,151 @@ public:
     {
     {
         m_lineSearch = lineSearch;
         m_lineSearch = lineSearch;
     }
     }
+    
+    void applyRepulsionForce(btScalar timeStep);
+    
+    void performGeometricCollisions(btScalar timeStep);
+    
+    struct btDeformableSingleRayCallback : public btBroadphaseRayCallback
+    {
+        btVector3 m_rayFromWorld;
+        btVector3 m_rayToWorld;
+        btTransform m_rayFromTrans;
+        btTransform m_rayToTrans;
+        btVector3 m_hitNormal;
+        
+        const btDeformableMultiBodyDynamicsWorld* m_world;
+        btCollisionWorld::RayResultCallback& m_resultCallback;
+        
+        btDeformableSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btDeformableMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+        : m_rayFromWorld(rayFromWorld),
+        m_rayToWorld(rayToWorld),
+        m_world(world),
+        m_resultCallback(resultCallback)
+        {
+            m_rayFromTrans.setIdentity();
+            m_rayFromTrans.setOrigin(m_rayFromWorld);
+            m_rayToTrans.setIdentity();
+            m_rayToTrans.setOrigin(m_rayToWorld);
+            
+            btVector3 rayDir = (rayToWorld - rayFromWorld);
+            
+            rayDir.normalize();
+            ///what about division by zero? --> just set rayDirection[i] to INF/1e30
+            m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
+            m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
+            m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
+            m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+            m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+            m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+            
+            m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
+        }
+        
+        virtual bool process(const btBroadphaseProxy* proxy)
+        {
+            ///terminate further ray tests, once the closestHitFraction reached zero
+            if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+                return false;
+            
+            btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+            
+            //only perform raycast if filterMask matches
+            if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+            {
+                //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+                //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+                btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+                collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+                //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+                const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+                const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+                //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+                //culling already done by broadphase
+                //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+                {
+                    m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+                                           collisionObject,
+                                           collisionObject->getCollisionShape(),
+                                           collisionObject->getWorldTransform(),
+                                           m_resultCallback);
+                }
+            }
+            return true;
+        }
+    };
 
 
+    
+    
+    void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+    {
+        BT_PROFILE("rayTest");
+        /// use the broadphase to accelerate the search for objects, based on their aabb
+        /// and for each object with ray-aabb overlap, perform an exact ray test
+        btDeformableSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
+        
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+        m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
+#else
+        for (int i = 0; i < this->getNumCollisionObjects(); i++)
+        {
+            rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+        }
+#endif  //USE_BRUTEFORCE_RAYBROADPHASE
+    }
+    
+    void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                     btCollisionObject* collisionObject,
+                                                     const btCollisionShape* collisionShape,
+                                                     const btTransform& colObjWorldTransform,
+                                                     RayResultCallback& resultCallback) const
+    {
+        if (collisionShape->isSoftBody())
+        {
+            btSoftBody* softBody = btSoftBody::upcast(collisionObject);
+            if (softBody)
+            {
+                btSoftBody::sRayCast softResult;
+                if (softBody->rayFaceTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+                {
+                    if (softResult.fraction <= resultCallback.m_closestHitFraction)
+                    {
+                        btCollisionWorld::LocalShapeInfo shapeInfo;
+                        shapeInfo.m_shapePart = 0;
+                        shapeInfo.m_triangleIndex = softResult.index;
+                        // get the normal
+                        btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
+                        btVector3 normal = -rayDir;
+                        normal.normalize();
+                        {
+                            normal = softBody->m_faces[softResult.index].m_normal;
+                            if (normal.dot(rayDir) > 0)
+                            {
+                                // normal always point toward origin of the ray
+                                normal = -normal;
+                            }
+                        }
+                        
+                        btCollisionWorld::LocalRayResult rayResult(collisionObject,
+                                                                   &shapeInfo,
+                                                                   normal,
+                                                                   softResult.fraction);
+                        bool normalInWorldSpace = true;
+                        resultCallback.addSingleResult(rayResult, normalInWorldSpace);
+                    }
+                }
+            }
+        }
+        else
+        {
+            btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
+        }
+    }
 };
 };
 
 
 #endif  //BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
 #endif  //BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H

+ 48 - 2
thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h

@@ -24,21 +24,65 @@ class btDeformableNeoHookeanForce : public btDeformableLagrangianForce
 {
 {
 public:
 public:
     typedef btAlignedObjectArray<btVector3> TVStack;
     typedef btAlignedObjectArray<btVector3> TVStack;
-    btScalar m_mu, m_lambda;
+	btScalar m_mu, m_lambda; // Lame Parameters
+	btScalar m_E, m_nu;  // Young's modulus and Poisson ratio
     btScalar m_mu_damp, m_lambda_damp;
     btScalar m_mu_damp, m_lambda_damp;
     btDeformableNeoHookeanForce(): m_mu(1), m_lambda(1)
     btDeformableNeoHookeanForce(): m_mu(1), m_lambda(1)
     {
     {
         btScalar damping = 0.05;
         btScalar damping = 0.05;
         m_mu_damp = damping * m_mu;
         m_mu_damp = damping * m_mu;
         m_lambda_damp = damping * m_lambda;
         m_lambda_damp = damping * m_lambda;
+		updateYoungsModulusAndPoissonRatio();
     }
     }
     
     
     btDeformableNeoHookeanForce(btScalar mu, btScalar lambda, btScalar damping = 0.05): m_mu(mu), m_lambda(lambda)
     btDeformableNeoHookeanForce(btScalar mu, btScalar lambda, btScalar damping = 0.05): m_mu(mu), m_lambda(lambda)
     {
     {
         m_mu_damp = damping * m_mu;
         m_mu_damp = damping * m_mu;
         m_lambda_damp = damping * m_lambda;
         m_lambda_damp = damping * m_lambda;
+		updateYoungsModulusAndPoissonRatio();
     }
     }
-    
+
+	void updateYoungsModulusAndPoissonRatio()
+	{
+		// conversion from Lame Parameters to Young's modulus and Poisson ratio
+		// https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
+		m_E  = m_mu * (3*m_lambda + 2*m_mu)/(m_lambda + m_mu);
+		m_nu = m_lambda * 0.5 / (m_mu + m_lambda);
+	}
+
+	void updateLameParameters()
+	{
+		// conversion from Young's modulus and Poisson ratio to Lame Parameters
+		// https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
+		m_mu = m_E * 0.5 / (1 + m_nu);
+		m_lambda = m_E * m_nu / ((1 + m_nu) * (1- 2*m_nu));
+	}
+
+    void setYoungsModulus(btScalar E)
+    {
+		m_E = E;
+		updateLameParameters();
+    }
+
+	void setPoissonRatio(btScalar nu)
+	{
+		m_nu = nu;
+		updateLameParameters();
+	}
+	
+	void setDamping(btScalar damping)
+	{
+		m_mu_damp = damping * m_mu;
+		m_lambda_damp = damping * m_lambda;
+	}
+
+	void setLameParameters(btScalar mu, btScalar lambda)
+	{
+		m_mu = mu;
+		m_lambda = lambda;
+		updateYoungsModulusAndPoissonRatio();
+	}
+
     virtual void addScaledForces(btScalar scale, TVStack& force)
     virtual void addScaledForces(btScalar scale, TVStack& force)
     {
     {
         addScaledDampingForce(scale, force);
         addScaledDampingForce(scale, force);
@@ -269,6 +313,8 @@ public:
         }
         }
     }
     }
     
     
+    virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA){}
+    
     virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
     virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
     {
     {
         int numNodes = getNumNodes();
         int numNodes = getNumNodes();

+ 211 - 2
thirdparty/bullet/BulletSoftBody/btPreconditioner.h

@@ -68,12 +68,221 @@ public:
     virtual void operator()(const TVStack& x, TVStack& b)
     virtual void operator()(const TVStack& x, TVStack& b)
     {
     {
         btAssert(b.size() == x.size());
         btAssert(b.size() == x.size());
-        btAssert(m_inv_mass.size() == x.size());
-        for (int i = 0; i < b.size(); ++i)
+        btAssert(m_inv_mass.size() <= x.size());
+        for (int i = 0; i < m_inv_mass.size(); ++i)
         {
         {
             b[i] = x[i] * m_inv_mass[i];
             b[i] = x[i] * m_inv_mass[i];
         }
         }
+        for (int i = m_inv_mass.size(); i < b.size(); ++i)
+        {
+            b[i] = x[i];
+        }
+    }
+};
+
+
+class KKTPreconditioner : public Preconditioner
+{
+    const btAlignedObjectArray<btSoftBody *>& m_softBodies;
+    const btDeformableContactProjection& m_projections;
+    const btAlignedObjectArray<btDeformableLagrangianForce*>& m_lf;
+    TVStack m_inv_A, m_inv_S;
+    const btScalar& m_dt;
+    const bool& m_implicit;
+public:
+    KKTPreconditioner(const btAlignedObjectArray<btSoftBody *>& softBodies, const btDeformableContactProjection& projections, const btAlignedObjectArray<btDeformableLagrangianForce*>& lf, const btScalar& dt, const bool& implicit)
+    : m_softBodies(softBodies)
+    , m_projections(projections)
+    , m_lf(lf)
+    , m_dt(dt)
+    , m_implicit(implicit)
+    {
+    }
+    
+    virtual void reinitialize(bool nodeUpdated)
+    {
+        if (nodeUpdated)
+        {
+            int num_nodes = 0;
+            for (int i = 0; i < m_softBodies.size(); ++i)
+            {
+                btSoftBody* psb = m_softBodies[i];
+                num_nodes += psb->m_nodes.size();
+            }
+            m_inv_A.resize(num_nodes);
+        }
+        buildDiagonalA(m_inv_A);
+        for (int i = 0; i < m_inv_A.size(); ++i)
+        {
+//            printf("A[%d] = %f, %f, %f \n", i, m_inv_A[i][0], m_inv_A[i][1], m_inv_A[i][2]);
+            for (int d = 0; d < 3; ++d)
+            {
+                m_inv_A[i][d] = (m_inv_A[i][d] == 0) ? 0.0 : 1.0/ m_inv_A[i][d];
+            }
+        }
+        m_inv_S.resize(m_projections.m_lagrangeMultipliers.size());
+//        printf("S.size() = %d \n", m_inv_S.size());
+        buildDiagonalS(m_inv_A, m_inv_S);
+        for (int i = 0; i < m_inv_S.size(); ++i)
+        {
+//            printf("S[%d] = %f, %f, %f \n", i, m_inv_S[i][0], m_inv_S[i][1], m_inv_S[i][2]);
+            for (int d = 0; d < 3; ++d)
+            {
+                m_inv_S[i][d] = (m_inv_S[i][d] == 0) ? 0.0 : 1.0/ m_inv_S[i][d];
+            }
+        }
+    }
+    
+    void buildDiagonalA(TVStack& diagA) const
+    {
+        size_t counter = 0;
+        for (int i = 0; i < m_softBodies.size(); ++i)
+        {
+            btSoftBody* psb = m_softBodies[i];
+            for (int j = 0; j < psb->m_nodes.size(); ++j)
+            {
+                const btSoftBody::Node& node = psb->m_nodes[j];
+                diagA[counter] = (node.m_im == 0) ? btVector3(0,0,0) : btVector3(1.0/node.m_im, 1.0 / node.m_im, 1.0 / node.m_im);
+                ++counter;
+            }
+        }
+        if (m_implicit)
+        {
+            printf("implicit not implemented\n");
+            btAssert(false);
+        }
+        for (int i = 0; i < m_lf.size(); ++i)
+        {
+            // add damping matrix
+            m_lf[i]->buildDampingForceDifferentialDiagonal(-m_dt, diagA);
+        }
+    }
+    
+    void buildDiagonalS(const TVStack& inv_A, TVStack& diagS)
+    {
+        for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+        {
+            // S[k,k] = e_k^T * C A_d^-1 C^T * e_k
+            const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+            btVector3& t = diagS[c];
+            t.setZero();
+            for (int j = 0; j < lm.m_num_constraints; ++j)
+            {
+                for (int i = 0; i < lm.m_num_nodes; ++i)
+                {
+                    for (int d = 0; d < 3; ++d)
+                    {
+                        t[j] += inv_A[lm.m_indices[i]][d] * lm.m_dirs[j][d] * lm.m_dirs[j][d] * lm.m_weights[i] * lm.m_weights[i];
+                    }
+                }
+            }
+        }
+    }
+#define USE_FULL_PRECONDITIONER
+#ifndef USE_FULL_PRECONDITIONER
+    virtual void operator()(const TVStack& x, TVStack& b)
+    {
+        btAssert(b.size() == x.size());
+        for (int i = 0; i < m_inv_A.size(); ++i)
+        {
+            b[i] = x[i] * m_inv_A[i];
+        }
+        int offset = m_inv_A.size();
+        for (int i = 0; i < m_inv_S.size(); ++i)
+        {
+            b[i+offset] = x[i+offset] * m_inv_S[i];
+        }
+    }
+#else
+    virtual void operator()(const TVStack& x, TVStack& b)
+    {
+        btAssert(b.size() == x.size());
+        int offset = m_inv_A.size();
+
+        for (int i = 0; i < m_inv_A.size(); ++i)
+        {
+            b[i] = x[i] * m_inv_A[i];
+        }
+
+        for (int i = 0; i < m_inv_S.size(); ++i)
+        {
+            b[i+offset].setZero();
+        }
+
+        for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+        {
+            const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+            // C * x
+            for (int d = 0; d < lm.m_num_constraints; ++d)
+            {
+                for (int i = 0; i < lm.m_num_nodes; ++i)
+                {
+                    b[offset+c][d] += lm.m_weights[i] * b[lm.m_indices[i]].dot(lm.m_dirs[d]);
+                }
+            }
+        }
+
+        for (int i = 0; i < m_inv_S.size(); ++i)
+        {
+            b[i+offset] = b[i+offset] * m_inv_S[i];
+        }
+
+        for (int i = 0; i < m_inv_A.size(); ++i)
+        {
+            b[i].setZero();
+        }
+
+        for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+        {
+            // C^T * lambda
+            const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+            for (int i = 0; i < lm.m_num_nodes; ++i)
+            {
+                for (int j = 0; j < lm.m_num_constraints; ++j)
+                {
+                    b[lm.m_indices[i]] += b[offset+c][j] * lm.m_weights[i] * lm.m_dirs[j];
+                }
+            }
+        }
+
+        for (int i = 0; i < m_inv_A.size(); ++i)
+        {
+            b[i] = (x[i] - b[i]) * m_inv_A[i];
+        }
+
+        TVStack t;
+        t.resize(b.size());
+        for (int i = 0; i < m_inv_S.size(); ++i)
+        {
+            t[i+offset] = x[i+offset] * m_inv_S[i];
+        }
+        for (int i = 0; i < m_inv_A.size(); ++i)
+        {
+            t[i].setZero();
+        }
+        for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+        {
+            // C^T * lambda
+            const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+            for (int i = 0; i < lm.m_num_nodes; ++i)
+            {
+                for (int j = 0; j < lm.m_num_constraints; ++j)
+                {
+                    t[lm.m_indices[i]] += t[offset+c][j] * lm.m_weights[i] * lm.m_dirs[j];
+                }
+            }
+        }
+        for (int i = 0; i < m_inv_A.size(); ++i)
+        {
+            b[i] += t[i] * m_inv_A[i];
+        }
+
+        for (int i = 0; i < m_inv_S.size(); ++i)
+        {
+            b[i+offset] -= x[i+offset] * m_inv_S[i];
+        }
     }
     }
+#endif
 };
 };
 
 
 #endif /* BT_PRECONDITIONER_H */
 #endif /* BT_PRECONDITIONER_H */

+ 524 - 112
thirdparty/bullet/BulletSoftBody/btSoftBody.cpp

@@ -18,12 +18,114 @@ subject to the following restrictions:
 #include "BulletSoftBody/btSoftBodySolvers.h"
 #include "BulletSoftBody/btSoftBodySolvers.h"
 #include "btSoftBodyData.h"
 #include "btSoftBodyData.h"
 #include "LinearMath/btSerializer.h"
 #include "LinearMath/btSerializer.h"
+#include "LinearMath/btImplicitQRSVD.h"
 #include "LinearMath/btAlignedAllocator.h"
 #include "LinearMath/btAlignedAllocator.h"
 #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
 #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
 #include <iostream>
 #include <iostream>
+//
+static inline btDbvtNode* buildTreeBottomUp(btAlignedObjectArray<btDbvtNode*>& leafNodes, btAlignedObjectArray<btAlignedObjectArray<int> >& adj)
+{
+	int N = leafNodes.size();
+	if (N == 0)
+	{
+		return NULL;
+	}
+	while (N > 1)
+	{
+		btAlignedObjectArray<bool> marked;
+		btAlignedObjectArray<btDbvtNode*> newLeafNodes;
+		btAlignedObjectArray<std::pair<int,int> > childIds;
+		btAlignedObjectArray<btAlignedObjectArray<int> > newAdj;
+		marked.resize(N);
+		for (int i = 0; i < N; ++i)
+			marked[i] = false;
+		
+		// pair adjacent nodes into new(parent) node
+		for (int i = 0; i < N; ++i)
+		{
+			if (marked[i])
+				continue;
+			bool merged = false;
+			for (int j = 0; j < adj[i].size(); ++j)
+			{
+				int n = adj[i][j];
+				if (!marked[adj[i][j]])
+				{
+					btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+					node->parent = NULL;
+					node->childs[0] = leafNodes[i];
+					node->childs[1] = leafNodes[n];
+					leafNodes[i]->parent = node;
+					leafNodes[n]->parent = node;
+					newLeafNodes.push_back(node);
+					childIds.push_back(std::make_pair(i,n));
+					merged = true;
+					marked[n] = true;
+					break;
+				}
+			}
+			if (!merged)
+			{
+				newLeafNodes.push_back(leafNodes[i]);
+				childIds.push_back(std::make_pair(i,-1));
+			}
+			marked[i] = true;
+		}
+		// update adjacency matrix
+		newAdj.resize(newLeafNodes.size());
+		for (int i = 0; i < newLeafNodes.size(); ++i)
+		{
+			for (int j = i+1; j < newLeafNodes.size(); ++j)
+			{
+				bool neighbor = false;
+				const btAlignedObjectArray<int>& leftChildNeighbors = adj[childIds[i].first];
+				for (int k = 0; k < leftChildNeighbors.size(); ++k)
+				{
+					if (leftChildNeighbors[k] == childIds[j].first || leftChildNeighbors[k] == childIds[j].second)
+					{
+						neighbor = true;
+						break;
+					}
+				}
+				if (!neighbor && childIds[i].second != -1)
+				{
+					const btAlignedObjectArray<int>& rightChildNeighbors = adj[childIds[i].second];
+					for (int k = 0; k < rightChildNeighbors.size(); ++k)
+					{
+						if (rightChildNeighbors[k] == childIds[j].first || rightChildNeighbors[k] == childIds[j].second)
+						{
+							neighbor = true;
+							break;
+						}
+					}
+				}
+				if (neighbor)
+				{
+					newAdj[i].push_back(j);
+					newAdj[j].push_back(i);
+				}
+			}
+		}
+		leafNodes = newLeafNodes;
+		//this assignment leaks memory, the assignment doesn't do a deep copy, for now a manual copy
+		//adj = newAdj;
+		adj.clear();
+		adj.resize(newAdj.size());
+		for (int i = 0; i < newAdj.size(); i++)
+		{
+			for (int j = 0; j < newAdj[i].size(); j++)
+			{
+				adj[i].push_back(newAdj[i][j]);
+			}
+		}
+		N = leafNodes.size();
+	}
+	return leafNodes[0];
+}
+
 //
 //
 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
 	: m_softBodySolver(0), m_worldInfo(worldInfo)
 	: m_softBodySolver(0), m_worldInfo(worldInfo)
@@ -41,6 +143,7 @@ btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btV
 	/* Nodes			*/
 	/* Nodes			*/
 	const btScalar margin = getCollisionShape()->getMargin();
 	const btScalar margin = getCollisionShape()->getMargin();
 	m_nodes.resize(node_count);
 	m_nodes.resize(node_count);
+    m_X.resize(node_count);
 	for (int i = 0, ni = node_count; i < ni; ++i)
 	for (int i = 0, ni = node_count; i < ni; ++i)
 	{
 	{
 		Node& n = m_nodes[i];
 		Node& n = m_nodes[i];
@@ -51,8 +154,11 @@ btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btV
 		n.m_im = n.m_im > 0 ? 1 / n.m_im : 0;
 		n.m_im = n.m_im > 0 ? 1 / n.m_im : 0;
 		n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
 		n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
 		n.m_material = pm;
 		n.m_material = pm;
+        m_X[i] = n.m_x;
 	}
 	}
 	updateBounds();
 	updateBounds();
+	setCollisionQuadrature(3);
+	m_fdbvnt = 0;
 }
 }
 
 
 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
@@ -111,15 +217,18 @@ void btSoftBody::initDefaults()
 	m_collisionShape = new btSoftBodyCollisionShape(this);
 	m_collisionShape = new btSoftBodyCollisionShape(this);
 	m_collisionShape->setMargin(0.25f);
 	m_collisionShape->setMargin(0.25f);
 
 
-	m_initialWorldTransform.setIdentity();
+	m_worldTransform.setIdentity();
 
 
 	m_windVelocity = btVector3(0, 0, 0);
 	m_windVelocity = btVector3(0, 0, 0);
 	m_restLengthScale = btScalar(1.0);
 	m_restLengthScale = btScalar(1.0);
-    m_dampingCoefficient = 1;
-    m_sleepingThreshold = 0.1;
-    m_useFaceContact = true;
+	m_dampingCoefficient = 1.0;
+	m_sleepingThreshold = .4;
 	m_useSelfCollision = false;
 	m_useSelfCollision = false;
-    m_collisionFlags = 0;
+	m_collisionFlags = 0;
+	m_softSoftCollision = false;
+	m_maxSpeedSquared = 0;
+	m_repulsionStiffness = 0.5;
+	m_fdbvnt = 0;
 }
 }
 
 
 //
 //
@@ -134,6 +243,8 @@ btSoftBody::~btSoftBody()
 		btAlignedFree(m_materials[i]);
 		btAlignedFree(m_materials[i]);
 	for (i = 0; i < m_joints.size(); ++i)
 	for (i = 0; i < m_joints.size(); ++i)
 		btAlignedFree(m_joints[i]);
 		btAlignedFree(m_joints[i]);
+	if (m_fdbvnt)
+		delete m_fdbvnt;
 }
 }
 
 
 //
 //
@@ -896,6 +1007,71 @@ void btSoftBody::setVolumeDensity(btScalar density)
 	setVolumeMass(volume * density / 6);
 	setVolumeMass(volume * density / 6);
 }
 }
 
 
+//
+btVector3 btSoftBody::getLinearVelocity()
+{
+    btVector3 total_momentum = btVector3(0,0,0);
+    for (int i = 0; i < m_nodes.size(); ++i)
+    {
+        btScalar mass = m_nodes[i].m_im == 0 ? 0 : 1.0/m_nodes[i].m_im;
+        total_momentum += mass * m_nodes[i].m_v;
+    }
+    btScalar total_mass = getTotalMass();
+    return total_mass == 0 ? total_momentum : total_momentum / total_mass;
+}
+
+//
+void btSoftBody::setLinearVelocity(const btVector3& linVel)
+{
+    btVector3 old_vel = getLinearVelocity();
+    btVector3 diff = linVel - old_vel;
+    for (int i = 0; i < m_nodes.size(); ++i)
+        m_nodes[i].m_v += diff;
+}
+
+//
+void btSoftBody::setAngularVelocity(const btVector3& angVel)
+{
+    btVector3 old_vel = getLinearVelocity();
+    btVector3 com = getCenterOfMass();
+    for (int i = 0; i < m_nodes.size(); ++i)
+    {
+        m_nodes[i].m_v = angVel.cross(m_nodes[i].m_x - com) + old_vel;
+    }
+}
+
+//
+btTransform btSoftBody::getRigidTransform()
+{
+    btVector3 t = getCenterOfMass();
+    btMatrix3x3 S;
+    S.setZero();
+    // get rotation that minimizes L2 difference: \sum_i || RX_i + t - x_i ||
+    for (int i = 0; i < m_nodes.size(); ++i)
+    {
+        S += OuterProduct(m_X[i], t-m_nodes[i].m_x);
+    }
+    btVector3 sigma;
+    btMatrix3x3 U,V;
+    singularValueDecomposition(S,U,sigma,V);
+    btMatrix3x3 R = V * U.transpose();
+    btTransform trs;
+    trs.setIdentity();
+    trs.setOrigin(t);
+    trs.setBasis(R);
+    return trs;
+}
+
+//
+void btSoftBody::transformTo(const btTransform& trs)
+{
+    // get the current best rigid fit
+    btTransform current_transform = getRigidTransform();
+    // apply transform in material space
+    btTransform new_transform = trs * current_transform.inverse();
+    transform(new_transform);
+}
+
 //
 //
 void btSoftBody::transform(const btTransform& trs)
 void btSoftBody::transform(const btTransform& trs)
 {
 {
@@ -916,7 +1092,6 @@ void btSoftBody::transform(const btTransform& trs)
 	updateNormals();
 	updateNormals();
 	updateBounds();
 	updateBounds();
 	updateConstants();
 	updateConstants();
-	m_initialWorldTransform = trs;
 }
 }
 
 
 //
 //
@@ -1834,6 +2009,25 @@ bool btSoftBody::rayTest(const btVector3& rayFrom,
 	return (rayTest(rayFrom, rayTo, results.fraction, results.feature, results.index, false) != 0);
 	return (rayTest(rayFrom, rayTo, results.fraction, results.feature, results.index, false) != 0);
 }
 }
 
 
+bool btSoftBody::rayFaceTest(const btVector3& rayFrom,
+                         const btVector3& rayTo,
+                         sRayCast& results)
+{
+	if (m_faces.size() == 0)
+		return false;
+	else
+	{
+    	if (m_fdbvt.empty())
+        	initializeFaceTree();
+	}
+    
+    results.body = this;
+    results.fraction = 1.f;
+    results.index = -1;
+    
+    return (rayFaceTest(rayFrom, rayTo, results.fraction,  results.index) != 0);
+}
+
 //
 //
 void btSoftBody::setSolver(eSolverPresets::_ preset)
 void btSoftBody::setSolver(eSolverPresets::_ preset)
 {
 {
@@ -2339,15 +2533,160 @@ int btSoftBody::rayTest(const btVector3& rayFrom, const btVector3& rayTo,
 	return (cnt);
 	return (cnt);
 }
 }
 
 
+int btSoftBody::rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
+						btScalar& mint, int& index) const
+{
+	int cnt = 0;
+	{ /* Use dbvt	*/
+		RayFromToCaster collider(rayFrom, rayTo, mint);
+		
+		btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
+		if (collider.m_face)
+		{
+			mint = collider.m_mint;
+			index = (int)(collider.m_face - &m_faces[0]);
+			cnt = 1;
+		}
+	}
+	return (cnt);
+}
+
+
 //
 //
+static inline btDbvntNode* copyToDbvnt(const btDbvtNode* n)
+{
+	if (n == 0)
+		return 0;
+	btDbvntNode* root = new btDbvntNode(n);
+	if (n->isinternal())
+	{
+		btDbvntNode* c0 = copyToDbvnt(n->childs[0]);
+		root->childs[0] = c0;
+		btDbvntNode* c1 = copyToDbvnt(n->childs[1]);
+		root->childs[1] = c1;
+	}
+	return root;
+}
+
+static inline void calculateNormalCone(btDbvntNode* root)
+{
+	if (!root)
+		return;
+	if (root->isleaf())
+	{
+		const btSoftBody::Face* face = (btSoftBody::Face*)root->data;
+		root->normal = face->m_normal;
+		root->angle = 0;
+	}
+	else
+	{
+		btVector3 n0(0,0,0), n1(0,0,0);
+		btScalar a0 = 0, a1 = 0;
+		if (root->childs[0])
+		{
+			calculateNormalCone(root->childs[0]);
+			n0 = root->childs[0]->normal;
+			a0 = root->childs[0]->angle;
+		}
+		if (root->childs[1])
+		{
+			calculateNormalCone(root->childs[1]);
+			n1 = root->childs[1]->normal;
+			a1 = root->childs[1]->angle;
+		}
+		root->normal = (n0+n1).safeNormalize();
+		root->angle = btMax(a0,a1) + btAngle(n0, n1)*0.5;
+	}
+}
+
 void btSoftBody::initializeFaceTree()
 void btSoftBody::initializeFaceTree()
 {
 {
+	BT_PROFILE("btSoftBody::initializeFaceTree");
 	m_fdbvt.clear();
 	m_fdbvt.clear();
+	// create leaf nodes;
+	btAlignedObjectArray<btDbvtNode*> leafNodes;
+	leafNodes.resize(m_faces.size());
 	for (int i = 0; i < m_faces.size(); ++i)
 	for (int i = 0; i < m_faces.size(); ++i)
 	{
 	{
 		Face& f = m_faces[i];
 		Face& f = m_faces[i];
-		f.m_leaf = m_fdbvt.insert(VolumeOf(f, 0), &f);
+		ATTRIBUTE_ALIGNED16(btDbvtVolume) vol = VolumeOf(f, 0);
+		btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+		node->parent = NULL;
+		node->data = &f;
+		node->childs[1] = 0;
+		node->volume = vol;
+		leafNodes[i] = node;
+		f.m_leaf = node;
 	}
 	}
+	btAlignedObjectArray<btAlignedObjectArray<int> > adj;
+	adj.resize(m_faces.size());
+	// construct the adjacency list for triangles
+	for (int i = 0; i < adj.size(); ++i)
+	{
+		for (int j = i+1; j < adj.size(); ++j)
+		{
+			int dup = 0;
+			for (int k = 0; k < 3; ++k)
+			{
+				for (int l = 0; l < 3; ++l)
+				{
+					if (m_faces[i].m_n[k] == m_faces[j].m_n[l])
+					{
+						++dup;
+						break;
+					}
+				}
+				if (dup == 2)
+				{
+					adj[i].push_back(j);
+					adj[j].push_back(i);
+				}
+			}
+		}
+	}
+	m_fdbvt.m_root = buildTreeBottomUp(leafNodes, adj);
+	if (m_fdbvnt)
+		delete m_fdbvnt;
+	m_fdbvnt = copyToDbvnt(m_fdbvt.m_root);
+	updateFaceTree(false, false);
+	rebuildNodeTree();
+}
+
+//
+void btSoftBody::rebuildNodeTree()
+{
+	m_ndbvt.clear();
+	btAlignedObjectArray<btDbvtNode*> leafNodes;
+	leafNodes.resize(m_nodes.size());
+	for (int i = 0; i < m_nodes.size(); ++i)
+	{
+		Node& n = m_nodes[i];
+		ATTRIBUTE_ALIGNED16(btDbvtVolume) vol = btDbvtVolume::FromCR(n.m_x, 0);
+		btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+		node->parent = NULL;
+		node->data = &n;
+		node->childs[1] = 0;
+		node->volume = vol;
+		leafNodes[i] = node;
+		n.m_leaf = node;
+	}
+	btAlignedObjectArray<btAlignedObjectArray<int> > adj;
+	adj.resize(m_nodes.size());
+	btAlignedObjectArray<int> old_id;
+	old_id.resize(m_nodes.size());
+	for (int i = 0; i < m_nodes.size(); ++i)
+		old_id[i] = m_nodes[i].index;
+	for (int i = 0; i < m_nodes.size(); ++i)
+		m_nodes[i].index = i;
+	for (int i = 0; i < m_links.size(); ++i)
+	{
+		Link& l = m_links[i];
+		adj[l.m_n[0]->index].push_back(l.m_n[1]->index);
+		adj[l.m_n[1]->index].push_back(l.m_n[0]->index);
+	}
+	m_ndbvt.m_root = buildTreeBottomUp(leafNodes, adj);
+	for (int i = 0; i < m_nodes.size(); ++i)
+		m_nodes[i].index = old_id[i];
 }
 }
 
 
 //
 //
@@ -2403,10 +2742,9 @@ bool btSoftBody::checkDeformableContact(const btCollisionObjectWrapper* colObjWr
     const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
     const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
     // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
     // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
     // but resolve contact at x_n
     // but resolve contact at x_n
-//    btTransform wtr = (predict) ?
-//    (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform()*(*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
-//                 : colObjWrap->getWorldTransform();
-    const btTransform& wtr = colObjWrap->getWorldTransform();
+    btTransform wtr = (predict) ?
+    (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform()*(*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
+                 : colObjWrap->getWorldTransform();
 	btScalar dst =
 	btScalar dst =
 		m_worldInfo->m_sparsesdf.Evaluate(
 		m_worldInfo->m_sparsesdf.Evaluate(
 			wtr.invXform(x),
 			wtr.invXform(x),
@@ -2457,7 +2795,6 @@ bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colO
     btTransform wtr = (predict) ?
     btTransform wtr = (predict) ?
     (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform()*(*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
     (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform()*(*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
     : colObjWrap->getWorldTransform();
     : colObjWrap->getWorldTransform();
-//    const btTransform& wtr = colObjWrap->getWorldTransform();
     btScalar dst;
     btScalar dst;
     
     
 //#define USE_QUADRATURE 1
 //#define USE_QUADRATURE 1
@@ -2476,6 +2813,7 @@ bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colO
                                           nrm,
                                           nrm,
                                           margin);
                                           margin);
         nrm = wtr.getBasis() * nrm;
         nrm = wtr.getBasis() * nrm;
+        cti.m_colObj = colObjWrap->getCollisionObject();
         // use cached contact point
         // use cached contact point
     }
     }
     else
     else
@@ -2492,10 +2830,11 @@ bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colO
         contact_point = results.witnesses[0];
         contact_point = results.witnesses[0];
         getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
         getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
         nrm = results.normal;
         nrm = results.normal;
+        cti.m_colObj = colObjWrap->getCollisionObject();
         for (int i = 0; i < 3; ++i)
         for (int i = 0; i < 3; ++i)
             f.m_pcontact[i] = bary[i];
             f.m_pcontact[i] = bary[i];
     }
     }
-
+    return (dst < 0);
 #endif
 #endif
 
 
     // use collision quadrature point
     // use collision quadrature point
@@ -2505,7 +2844,11 @@ bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colO
         btVector3 local_nrm;
         btVector3 local_nrm;
         for (int q = 0; q < m_quads.size(); ++q)
         for (int q = 0; q < m_quads.size(); ++q)
         {
         {
-            btVector3 p = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, m_quads[q]);
+            btVector3 p;
+            if (predict)
+                p = BaryEval(f.m_n[0]->m_q, f.m_n[1]->m_q, f.m_n[2]->m_q, m_quads[q]);
+            else
+                p = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, m_quads[q]);
             btScalar local_dst = m_worldInfo->m_sparsesdf.Evaluate(
             btScalar local_dst = m_worldInfo->m_sparsesdf.Evaluate(
                                                     wtr.invXform(p),
                                                     wtr.invXform(p),
                                                     shp,
                                                     shp,
@@ -2513,43 +2856,83 @@ bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colO
                                                     margin);
                                                     margin);
             if (local_dst < dst)
             if (local_dst < dst)
             {
             {
+                if (local_dst < 0 && predict)
+                    return true;
                 dst = local_dst;
                 dst = local_dst;
                 contact_point = p;
                 contact_point = p;
                 bary = m_quads[q];
                 bary = m_quads[q];
-                nrm = wtr.getBasis() * local_nrm;
+                nrm = local_nrm;
+            }
+            if (!predict)
+            {
+                cti.m_colObj = colObjWrap->getCollisionObject();
+                cti.m_normal = wtr.getBasis() * nrm;
+                cti.m_offset = dst;
             }
             }
         }
         }
+        return (dst < 0);
     }
     }
 #endif
 #endif
     
     
+//    // regular face contact
+//    {
+//        btGjkEpaSolver2::sResults results;
+//        btTransform triangle_transform;
+//        triangle_transform.setIdentity();
+//        triangle_transform.setOrigin(f.m_n[0]->m_x);
+//        btTriangleShape triangle(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);
+//        btVector3 guess(0,0,0);
+//        if (predict)
+//        {
+//            triangle_transform.setOrigin(f.m_n[0]->m_q);
+//            triangle = btTriangleShape(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);
+//        }
+//        const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
+////        btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
+////        dst = results.distance - margin;
+////        contact_point = results.witnesses[0];
+//        btGjkEpaSolver2::Penetration(&triangle, triangle_transform, csh, wtr, guess, results);
+//        if (results.status == btGjkEpaSolver2::sResults::Separated)
+//            return false;
+//        dst = results.distance - margin;
+//        contact_point = results.witnesses[1];
+//        getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+//        nrm = results.normal;
+//        for (int i = 0; i < 3; ++i)
+//            f.m_pcontact[i] = bary[i];
+//    }
+//
+//    if (!predict)
+//    {
+//        cti.m_colObj = colObjWrap->getCollisionObject();
+//        cti.m_normal = nrm;
+//        cti.m_offset = dst;
+//    }
+//
+    
     // regular face contact
     // regular face contact
     {
     {
         btGjkEpaSolver2::sResults results;
         btGjkEpaSolver2::sResults results;
         btTransform triangle_transform;
         btTransform triangle_transform;
         triangle_transform.setIdentity();
         triangle_transform.setIdentity();
-        triangle_transform.setOrigin(f.m_n[0]->m_x);
-        btTriangleShape triangle(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);
+        triangle_transform.setOrigin(f.m_n[0]->m_q);
+        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);
         btVector3 guess(0,0,0);
         btVector3 guess(0,0,0);
         const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
         const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
         btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
         btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
-        dst = results.distance - margin;
+        dst = results.distance-csh->getMargin();
+        dst -= margin;
+        if (dst >= 0)
+            return false;
         contact_point = results.witnesses[0];
         contact_point = results.witnesses[0];
-        getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+        getBarycentric(contact_point, f.m_n[0]->m_q, f.m_n[1]->m_q, f.m_n[2]->m_q, bary);
+        btVector3 curr = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
         nrm = results.normal;
         nrm = results.normal;
-        for (int i = 0; i < 3; ++i)
-            f.m_pcontact[i] = bary[i];
-    }
-    
-    if (!predict)
-    {
         cti.m_colObj = colObjWrap->getCollisionObject();
         cti.m_colObj = colObjWrap->getCollisionObject();
         cti.m_normal = nrm;
         cti.m_normal = nrm;
-        cti.m_offset = dst;
+        cti.m_offset = dst + (curr - contact_point).dot(nrm);
     }
     }
-    
-    if (dst < 0)
-        return true;
-    return (false);
+    return (dst < 0);
 }
 }
 
 
 //
 //
@@ -3075,6 +3458,7 @@ void btSoftBody::setSpringStiffness(btScalar k)
     {
     {
         m_links[i].Feature::m_material->m_kLST = k;
         m_links[i].Feature::m_material->m_kLST = k;
     }
     }
+    m_repulsionStiffness = k;
 }
 }
 
 
 void btSoftBody::initializeDmInverse()
 void btSoftBody::initializeDmInverse()
@@ -3372,18 +3756,39 @@ void btSoftBody::setMaxStress(btScalar maxStress)
 //
 //
 void btSoftBody::interpolateRenderMesh()
 void btSoftBody::interpolateRenderMesh()
 {
 {
-    for (int i = 0; i < m_renderNodes.size(); ++i)
-    {
-        Node& n = m_renderNodes[i];
-        n.m_x.setZero();
-        for (int j = 0; j < 4; ++j)
-        {
-			if (m_renderNodesParents[i].size())
+	if (m_z.size() > 0)
+	{
+		for (int i = 0; i < m_renderNodes.size(); ++i)
+		{
+			const Node* p0 = m_renderNodesParents[i][0];
+			const Node* p1 = m_renderNodesParents[i][1];
+			const Node* p2 = m_renderNodesParents[i][2];
+			btVector3 normal = btCross(p1->m_x - p0->m_x, p2->m_x - p0->m_x);
+			btVector3 unit_normal = normal.normalized();
+			Node& n = m_renderNodes[i];
+			n.m_x.setZero();
+			for (int j = 0; j < 3; ++j)
 			{
 			{
 				n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
 				n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
 			}
 			}
-        }
-    }
+			n.m_x += m_z[i] * unit_normal;
+		}
+	}
+	else
+	{
+		for (int i = 0; i < m_renderNodes.size(); ++i)
+		{
+			Node& n = m_renderNodes[i];
+			n.m_x.setZero();
+			for (int j = 0; j < 4; ++j)
+			{
+				if (m_renderNodesParents[i].size())
+				{
+					n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
+				}
+			}
+		}
+	}
 }
 }
 
 
 void btSoftBody::setCollisionQuadrature(int N)
 void btSoftBody::setCollisionQuadrature(int N)
@@ -3649,13 +4054,10 @@ void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap
 		break;
 		break;
         case fCollision::SDF_RD:
         case fCollision::SDF_RD:
         {
         {
-            
             btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
             btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
             if (pcoWrap->getCollisionObject()->isActive() || this->isActive())
             if (pcoWrap->getCollisionObject()->isActive() || this->isActive())
             {
             {
                 const btTransform wtr = pcoWrap->getWorldTransform();
                 const btTransform wtr = pcoWrap->getWorldTransform();
-//                const btTransform ctr = pcoWrap->getWorldTransform();
-//                const btScalar timemargin = (wtr.getOrigin() - ctr.getOrigin()).length();
                 const btScalar timemargin = 0;
                 const btScalar timemargin = 0;
                 const btScalar basemargin = getCollisionShape()->getMargin();
                 const btScalar basemargin = getCollisionShape()->getMargin();
                 btVector3 mins;
                 btVector3 mins;
@@ -3667,22 +4069,25 @@ void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap
                                                       maxs);
                                                       maxs);
                 volume = btDbvtVolume::FromMM(mins, maxs);
                 volume = btDbvtVolume::FromMM(mins, maxs);
                 volume.Expand(btVector3(basemargin, basemargin, basemargin));
                 volume.Expand(btVector3(basemargin, basemargin, basemargin));
-                btSoftColliders::CollideSDF_RD docollideNode;
-                docollideNode.psb = this;
-                docollideNode.m_colObj1Wrap = pcoWrap;
-                docollideNode.m_rigidBody = prb1;
-                docollideNode.dynmargin = basemargin + timemargin;
-                docollideNode.stamargin = basemargin;
-                m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollideNode);
-                
-                if (this->m_useFaceContact)
+				if (m_cfg.collisions & fCollision::SDF_RDN)
+				{
+					btSoftColliders::CollideSDF_RD docollideNode;
+					docollideNode.psb = this;
+					docollideNode.m_colObj1Wrap = pcoWrap;
+					docollideNode.m_rigidBody = prb1;
+					docollideNode.dynmargin = basemargin + timemargin;
+					docollideNode.stamargin = basemargin;
+					m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollideNode);
+				}
+
+                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)))
                 {
                 {
                     btSoftColliders::CollideSDF_RDF docollideFace;
                     btSoftColliders::CollideSDF_RDF docollideFace;
                     docollideFace.psb = this;
                     docollideFace.psb = this;
                     docollideFace.m_colObj1Wrap = pcoWrap;
                     docollideFace.m_colObj1Wrap = pcoWrap;
                     docollideFace.m_rigidBody = prb1;
                     docollideFace.m_rigidBody = prb1;
-                    docollideFace.dynmargin = basemargin + timemargin;
-                    docollideFace.stamargin = basemargin;
+					docollideFace.dynmargin = basemargin + timemargin;
+					docollideFace.stamargin = basemargin;
                     m_fdbvt.collideTV(m_fdbvt.m_root, volume, docollideFace);
                     m_fdbvt.collideTV(m_fdbvt.m_root, volume, docollideFace);
                 }
                 }
             }
             }
@@ -3691,51 +4096,6 @@ void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap
 	}
 	}
 }
 }
 
 
-static inline btDbvntNode* copyToDbvnt(const btDbvtNode* n)
-{
-    if (n == 0)
-        return 0;
-    btDbvntNode* root = new btDbvntNode(n);
-    if (n->isinternal())
-    {
-        btDbvntNode* c0 = copyToDbvnt(n->childs[0]);
-        root->childs[0] = c0;
-        btDbvntNode* c1 = copyToDbvnt(n->childs[1]);
-        root->childs[1] = c1;
-    }
-    return root;
-}
-
-static inline void calculateNormalCone(btDbvntNode* root)
-{
-    if (!root)
-        return;
-    if (root->isleaf())
-    {
-        const btSoftBody::Face* face = (btSoftBody::Face*)root->data;
-        root->normal = face->m_normal;
-        root->angle = 0;
-    }
-    else
-    {
-        btVector3 n0(0,0,0), n1(0,0,0);
-        btScalar a0 = 0, a1 = 0;
-        if (root->childs[0])
-        {
-            calculateNormalCone(root->childs[0]);
-            n0 = root->childs[0]->normal;
-            a0 = root->childs[0]->angle;
-        }
-        if (root->childs[1])
-        {
-            calculateNormalCone(root->childs[1]);
-            n1 = root->childs[1]->normal;
-            a1 = root->childs[1]->angle;
-        }
-        root->normal = (n0+n1).safeNormalize();
-        root->angle = btMax(a0,a1) + btAngle(n0, n1)*0.5;
-    }
-}
 //
 //
 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
 {
 {
@@ -3779,6 +4139,8 @@ void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
 		break;
 		break;
         case fCollision::VF_DD:
         case fCollision::VF_DD:
         {
         {
+            if (!psb->m_softSoftCollision)
+                return;
             if (psb->isActive() || this->isActive())
             if (psb->isActive() || this->isActive())
             {
             {
                 if (this != psb)
                 if (this != psb)
@@ -3797,6 +4159,7 @@ void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
                     docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
                     docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
                                                         docollide.psb[1]->m_fdbvt.m_root,
                                                         docollide.psb[1]->m_fdbvt.m_root,
                                                         docollide);
                                                         docollide);
+
                     /* psb1 nodes vs psb0 faces    */
                     /* psb1 nodes vs psb0 faces    */
                     if (this->m_tetras.size() > 0)
                     if (this->m_tetras.size() > 0)
                         docollide.useFaceNormal = true;
                         docollide.useFaceNormal = true;
@@ -3812,20 +4175,17 @@ void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
                 {
                 {
                     if (psb->useSelfCollision())
                     if (psb->useSelfCollision())
                     {
                     {
-                      btSoftColliders::CollideFF_DD docollide;
-                      docollide.mrg = getCollisionShape()->getMargin() +
-                      psb->getCollisionShape()->getMargin();
-                      docollide.psb[0] = this;
-                      docollide.psb[1] = psb;
-                      if (this->m_tetras.size() > 0)
-                          docollide.useFaceNormal = true;
-                      else
-                          docollide.useFaceNormal = false;
-                      /* psb0 faces vs psb0 faces    */
-                      btDbvntNode* root = copyToDbvnt(this->m_fdbvt.m_root);
-                      calculateNormalCone(root);
-                      this->m_fdbvt.selfCollideT(root,docollide);
-                      delete root;
+                        btSoftColliders::CollideFF_DD docollide;
+                        docollide.mrg = 2*getCollisionShape()->getMargin();
+                        docollide.psb[0] = this;
+                        docollide.psb[1] = psb;
+                        if (this->m_tetras.size() > 0)
+                            docollide.useFaceNormal = true;
+                        else
+                            docollide.useFaceNormal = false;
+                        /* psb0 faces vs psb0 faces    */
+                        calculateNormalCone(this->m_fdbvnt);
+                        this->m_fdbvt.selfCollideT(m_fdbvnt,docollide);
                     }
                     }
                 }
                 }
             }
             }
@@ -3837,6 +4197,58 @@ void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
 	}
 	}
 }
 }
 
 
+void btSoftBody::geometricCollisionHandler(btSoftBody* psb)
+{
+	if (psb->isActive() || this->isActive())
+	{
+		if (this != psb)
+		{
+			btSoftColliders::CollideCCD docollide;
+			/* common                    */
+			docollide.mrg = SAFE_EPSILON; // for rounding error instead of actual margin
+			docollide.dt = psb->m_sst.sdt;
+			/* psb0 nodes vs psb1 faces    */
+			if (psb->m_tetras.size() > 0)
+				docollide.useFaceNormal = true;
+			else
+				docollide.useFaceNormal = false;
+			docollide.psb[0] = this;
+			docollide.psb[1] = psb;
+			docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+												 docollide.psb[1]->m_fdbvt.m_root,
+												 docollide);
+			/* psb1 nodes vs psb0 faces    */
+			if (this->m_tetras.size() > 0)
+				docollide.useFaceNormal = true;
+			else
+				docollide.useFaceNormal = false;
+			docollide.psb[0] = psb;
+			docollide.psb[1] = this;
+			docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+												 docollide.psb[1]->m_fdbvt.m_root,
+												 docollide);
+		}
+		else
+		{
+			if (psb->useSelfCollision())
+			{
+				btSoftColliders::CollideCCD docollide;
+				docollide.mrg = SAFE_EPSILON;
+				docollide.psb[0] = this;
+				docollide.psb[1] = psb;
+                docollide.dt = psb->m_sst.sdt;
+				if (this->m_tetras.size() > 0)
+					docollide.useFaceNormal = true;
+				else
+					docollide.useFaceNormal = false;
+				/* psb0 faces vs psb0 faces    */
+				calculateNormalCone(this->m_fdbvnt);  // should compute this outside of this scope
+				this->m_fdbvt.selfCollideT(m_fdbvnt,docollide);
+			}
+		}
+	}
+}
+
 void btSoftBody::setWindVelocity(const btVector3& velocity)
 void btSoftBody::setWindVelocity(const btVector3& velocity)
 {
 {
 	m_windVelocity = velocity;
 	m_windVelocity = velocity;

+ 223 - 21
thirdparty/bullet/BulletSoftBody/btSoftBody.h

@@ -35,6 +35,8 @@ subject to the following restrictions:
 //#else
 //#else
 #define btSoftBodyData btSoftBodyFloatData
 #define btSoftBodyData btSoftBodyFloatData
 #define btSoftBodyDataName "btSoftBodyFloatData"
 #define btSoftBodyDataName "btSoftBodyFloatData"
+static const btScalar  OVERLAP_REDUCTION_FACTOR = 0.1;
+static unsigned long seed = 243703;
 //#endif //BT_USE_DOUBLE_PRECISION
 //#endif //BT_USE_DOUBLE_PRECISION
 
 
 class btBroadphaseInterface;
 class btBroadphaseInterface;
@@ -161,14 +163,18 @@ public:
 			RVSmask = 0x000f,  ///Rigid versus soft mask
 			RVSmask = 0x000f,  ///Rigid versus soft mask
 			SDF_RS = 0x0001,   ///SDF based rigid vs soft
 			SDF_RS = 0x0001,   ///SDF based rigid vs soft
 			CL_RS = 0x0002,    ///Cluster vs convex rigid vs soft
 			CL_RS = 0x0002,    ///Cluster vs convex rigid vs soft
-            SDF_RD = 0x0003,   ///DF based rigid vs deformable
-            SDF_RDF = 0x0004,   ///DF based rigid vs deformable faces
+			SDF_RD = 0x0004,   ///rigid vs deformable
 
 
-			SVSmask = 0x00F0,  ///Rigid versus soft mask
+			SVSmask = 0x00f0,  ///Rigid versus soft mask
 			VF_SS = 0x0010,    ///Vertex vs face soft vs soft handling
 			VF_SS = 0x0010,    ///Vertex vs face soft vs soft handling
 			CL_SS = 0x0020,    ///Cluster vs cluster soft vs soft handling
 			CL_SS = 0x0020,    ///Cluster vs cluster soft vs soft handling
 			CL_SELF = 0x0040,  ///Cluster soft body self collision
 			CL_SELF = 0x0040,  ///Cluster soft body self collision
-            VF_DD = 0x0050,    ///Vertex vs face soft vs soft handling
+			VF_DD = 0x0080,    ///Vertex vs face soft vs soft handling
+
+			RVDFmask = 0x0f00, /// Rigid versus deformable face mask
+			SDF_RDF = 0x0100,  /// GJK based Rigid vs. deformable face
+			SDF_MDF = 0x0200,  /// GJK based Multibody vs. deformable face
+            SDF_RDN = 0x0400,  /// SDF based Rigid vs. deformable node
 			/* presets	*/
 			/* presets	*/
 			Default = SDF_RS,
 			Default = SDF_RS,
 			END
 			END
@@ -257,13 +263,13 @@ public:
 		btVector3 m_x;       // Position
 		btVector3 m_x;       // Position
 		btVector3 m_q;       // Previous step position/Test position
 		btVector3 m_q;       // Previous step position/Test position
 		btVector3 m_v;       // Velocity
 		btVector3 m_v;       // Velocity
-        btVector3 m_vsplit;  // Temporary Velocity in addintion to velocity used in split impulse
         btVector3 m_vn;      // Previous step velocity
         btVector3 m_vn;      // Previous step velocity
 		btVector3 m_f;       // Force accumulator
 		btVector3 m_f;       // Force accumulator
 		btVector3 m_n;       // Normal
 		btVector3 m_n;       // Normal
 		btScalar m_im;       // 1/mass
 		btScalar m_im;       // 1/mass
 		btScalar m_area;     // Area
 		btScalar m_area;     // Area
 		btDbvtNode* m_leaf;  // Leaf data
 		btDbvtNode* m_leaf;  // Leaf data
+		btScalar m_penetration;   // depth of penetration
 		int m_battach : 1;   // Attached
 		int m_battach : 1;   // Attached
         int index;
         int index;
 	};
 	};
@@ -289,6 +295,7 @@ public:
 		btScalar m_ra;       // Rest area
 		btScalar m_ra;       // Rest area
 		btDbvtNode* m_leaf;  // Leaf data
 		btDbvtNode* m_leaf;  // Leaf data
         btVector4 m_pcontact; // barycentric weights of the persistent contact
         btVector4 m_pcontact; // barycentric weights of the persistent contact
+        btVector3 m_n0, m_n1, m_vn;
         int m_index;
         int m_index;
 	};
 	};
 	/* Tetra		*/
 	/* Tetra		*/
@@ -717,6 +724,15 @@ public:
 	/* SolverState	*/
 	/* SolverState	*/
 	struct SolverState
 	struct SolverState
 	{
 	{
+		//if you add new variables, always initialize them!
+		SolverState()
+			:sdt(0),
+			isdt(0),
+			velmrg(0),
+			radmrg(0),
+			updmrg(0)
+		{
+		}
 		btScalar sdt;     // dt*timescale
 		btScalar sdt;     // dt*timescale
 		btScalar isdt;    // 1/sdt
 		btScalar isdt;    // 1/sdt
 		btScalar velmrg;  // velocity margin
 		btScalar velmrg;  // velocity margin
@@ -796,22 +812,24 @@ public:
 	bool m_bUpdateRtCst;               // Update runtime constants
 	bool m_bUpdateRtCst;               // Update runtime constants
 	btDbvt m_ndbvt;                    // Nodes tree
 	btDbvt m_ndbvt;                    // Nodes tree
 	btDbvt m_fdbvt;                    // Faces tree
 	btDbvt m_fdbvt;                    // Faces tree
+	btDbvntNode* m_fdbvnt;              // Faces tree with normals
 	btDbvt m_cdbvt;                    // Clusters tree
 	btDbvt m_cdbvt;                    // Clusters tree
 	tClusterArray m_clusters;          // Clusters
 	tClusterArray m_clusters;          // Clusters
-    btScalar m_dampingCoefficient;     // Damping Coefficient
-    btScalar m_sleepingThreshold;
-    btScalar m_maxSpeedSquared;
-    bool m_useFaceContact;
-    btAlignedObjectArray<btVector3> m_quads; // quadrature points for collision detection
-    
-    btAlignedObjectArray<btVector4> m_renderNodesInterpolationWeights;
-    btAlignedObjectArray<btAlignedObjectArray<const btSoftBody::Node*> > m_renderNodesParents;
-    bool m_useSelfCollision;
+	btScalar m_dampingCoefficient;     // Damping Coefficient
+	btScalar m_sleepingThreshold;
+	btScalar m_maxSpeedSquared;
+	btAlignedObjectArray<btVector3> m_quads; // quadrature points for collision detection
+	btScalar m_repulsionStiffness;
+    btAlignedObjectArray<btVector3> m_X;   // initial positions
+
+	btAlignedObjectArray<btVector4> m_renderNodesInterpolationWeights;
+	btAlignedObjectArray<btAlignedObjectArray<const btSoftBody::Node*> > m_renderNodesParents;
+	btAlignedObjectArray<btScalar> m_z; // vertical distance used in extrapolation
+	bool m_useSelfCollision;
+	bool m_softSoftCollision;
 
 
 	btAlignedObjectArray<bool> m_clusterConnectivity;  //cluster connectivity, for self-collision
 	btAlignedObjectArray<bool> m_clusterConnectivity;  //cluster connectivity, for self-collision
 
 
-	btTransform m_initialWorldTransform;
-
 	btVector3 m_windVelocity;
 	btVector3 m_windVelocity;
 
 
 	btScalar m_restLengthScale;
 	btScalar m_restLengthScale;
@@ -843,11 +861,6 @@ public:
     {
     {
         m_dampingCoefficient = damping_coeff;
         m_dampingCoefficient = damping_coeff;
     }
     }
-    
-    void setUseFaceContact(bool useFaceContact)
-    {
-        m_useFaceContact = false;
-    }
 
 
 	///@todo: avoid internal softbody shape hack and move collision code to collision library
 	///@todo: avoid internal softbody shape hack and move collision code to collision library
 	virtual void setCollisionShape(btCollisionShape* collisionShape)
 	virtual void setCollisionShape(btCollisionShape* collisionShape)
@@ -957,6 +970,16 @@ public:
 	void setVolumeMass(btScalar mass);
 	void setVolumeMass(btScalar mass);
 	/* Set volume density (using tetrahedrons)								*/
 	/* Set volume density (using tetrahedrons)								*/
 	void setVolumeDensity(btScalar density);
 	void setVolumeDensity(btScalar density);
+	/* Get the linear velocity of the center of mass                        */
+	btVector3 getLinearVelocity();
+	/* Set the linear velocity of the center of mass                        */
+	void setLinearVelocity(const btVector3& linVel);
+	/* Set the angular velocity of the center of mass                       */
+	void setAngularVelocity(const btVector3& angVel);
+    /* Get best fit rigid transform                                         */
+    btTransform getRigidTransform();
+    /* Transform to given pose                                              */
+    void transformTo(const btTransform& trs);
 	/* Transform															*/
 	/* Transform															*/
 	void transform(const btTransform& trs);
 	void transform(const btTransform& trs);
 	/* Translate															*/
 	/* Translate															*/
@@ -1023,6 +1046,11 @@ public:
 	bool rayTest(const btVector3& rayFrom,
 	bool rayTest(const btVector3& rayFrom,
 				 const btVector3& rayTo,
 				 const btVector3& rayTo,
 				 sRayCast& results);
 				 sRayCast& results);
+	bool rayFaceTest(const btVector3& rayFrom,
+					 const btVector3& rayTo,
+					 sRayCast& results);
+	int rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
+					btScalar& mint, int& index) const;
 	/* Solver presets														*/
 	/* Solver presets														*/
 	void setSolver(eSolverPresets::_ preset);
 	void setSolver(eSolverPresets::_ preset);
 	/* predictMotion														*/
 	/* predictMotion														*/
@@ -1120,6 +1148,7 @@ public:
 	int rayTest(const btVector3& rayFrom, const btVector3& rayTo,
 	int rayTest(const btVector3& rayFrom, const btVector3& rayTo,
 				btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const;
 				btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const;
 	void initializeFaceTree();
 	void initializeFaceTree();
+	void rebuildNodeTree();
 	btVector3 evaluateCom() const;
 	btVector3 evaluateCom() const;
 	bool checkDeformableContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
 	bool checkDeformableContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
     bool checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap, Face& f, btVector3& contact_point, btVector3& bary, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
     bool checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap, Face& f, btVector3& contact_point, btVector3& bary, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
@@ -1152,7 +1181,180 @@ public:
 	static void VSolve_Links(btSoftBody* psb, btScalar kst);
 	static void VSolve_Links(btSoftBody* psb, btScalar kst);
 	static psolver_t getSolver(ePSolver::_ solver);
 	static psolver_t getSolver(ePSolver::_ solver);
 	static vsolver_t getSolver(eVSolver::_ solver);
 	static vsolver_t getSolver(eVSolver::_ solver);
+	void geometricCollisionHandler(btSoftBody* psb);
+#define SAFE_EPSILON SIMD_EPSILON*100.0
+	void updateNode(btDbvtNode* node, bool use_velocity, bool margin)
+	{
+		if (node->isleaf())
+		{
+			btSoftBody::Node* n = (btSoftBody::Node*)(node->data);
+			ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+			btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON; // use user defined margin or margin for floating point precision
+			if (use_velocity)
+			{
+				btVector3 points[2] = {n->m_x, n->m_x + m_sst.sdt * n->m_v};
+				vol = btDbvtVolume::FromPoints(points, 2);
+				vol.Expand(btVector3(pad, pad, pad));
+			}
+			else
+			{
+				vol = btDbvtVolume::FromCR(n->m_x, pad);
+			}
+			node->volume = vol;
+			return;
+		}
+		else
+		{
+			updateNode(node->childs[0], use_velocity, margin);
+			updateNode(node->childs[1], use_velocity, margin);
+			ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+			Merge(node->childs[0]->volume, node->childs[1]->volume, vol);
+			node->volume = vol;
+		}
+	}
+	
+    void updateNodeTree(bool use_velocity, bool margin)
+	{
+		if (m_ndbvt.m_root)
+			updateNode(m_ndbvt.m_root, use_velocity, margin);
+	}
+
+	template <class DBVTNODE> // btDbvtNode or btDbvntNode
+	void updateFace(DBVTNODE* node, bool use_velocity, bool margin)
+	{
+		if (node->isleaf())
+		{
+			btSoftBody::Face* f = (btSoftBody::Face*)(node->data);
+			btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON; // use user defined margin or margin for floating point precision
+			ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+			if (use_velocity)
+			{
+				btVector3 points[6] = {f->m_n[0]->m_x, f->m_n[0]->m_x + m_sst.sdt * f->m_n[0]->m_v,
+					f->m_n[1]->m_x, f->m_n[1]->m_x + m_sst.sdt * f->m_n[1]->m_v,
+					f->m_n[2]->m_x, f->m_n[2]->m_x + m_sst.sdt * f->m_n[2]->m_v};
+				vol = btDbvtVolume::FromPoints(points, 6);
+			}
+			else
+			{
+				btVector3 points[3] = {f->m_n[0]->m_x,
+					f->m_n[1]->m_x,
+					f->m_n[2]->m_x};
+				vol = btDbvtVolume::FromPoints(points, 3);
+			}
+			vol.Expand(btVector3(pad, pad, pad));
+			node->volume = vol;
+			return;
+		}
+		else
+		{
+			updateFace(node->childs[0], use_velocity, margin);
+			updateFace(node->childs[1], use_velocity, margin);
+			ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+			Merge(node->childs[0]->volume, node->childs[1]->volume, vol);
+			node->volume = vol;
+		}
+	}
+	void updateFaceTree(bool use_velocity, bool margin)
+	{
+		if (m_fdbvt.m_root)
+			updateFace(m_fdbvt.m_root, use_velocity, margin);
+		if (m_fdbvnt)
+			updateFace(m_fdbvnt, use_velocity, margin);
+	}
+
+	template <typename T>
+	static inline T BaryEval(const T& a,
+							 const T& b,
+							 const T& c,
+							 const btVector3& coord)
+	{
+		return (a * coord.x() + b * coord.y() + c * coord.z());
+	}
 
 
+    void applyRepulsionForce(btScalar timeStep, bool applySpringForce)
+	{
+		btAlignedObjectArray<int> indices;
+		{
+			// randomize the order of repulsive force
+			indices.resize(m_faceNodeContacts.size());
+			for (int i = 0; i < m_faceNodeContacts.size(); ++i)
+				indices[i] = i;
+#define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
+			int i, ni;
+
+			for (i = 0, ni = indices.size(); i < ni; ++i)
+			{
+				btSwap(indices[i], indices[NEXTRAND % ni]);
+			}
+		}
+		for (int k = 0; k < m_faceNodeContacts.size(); ++k)
+		{
+			int i = indices[k];
+			btSoftBody::DeformableFaceNodeContact& c = m_faceNodeContacts[i];
+			btSoftBody::Node* node = c.m_node;
+			btSoftBody::Face* face = c.m_face;
+			const btVector3& w = c.m_bary;
+			const btVector3& n = c.m_normal;
+			btVector3 l = node->m_x - BaryEval(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, w);
+			btScalar d = c.m_margin - n.dot(l);
+			d = btMax(btScalar(0),d);
+			
+			const btVector3& va = node->m_v;
+			btVector3 vb = BaryEval(face->m_n[0]->m_v, face->m_n[1]->m_v, face->m_n[2]->m_v, w);
+			btVector3 vr = va - vb;
+			const btScalar vn = btDot(vr, n); // dn < 0 <==> opposing
+			if (vn > OVERLAP_REDUCTION_FACTOR * d / timeStep)
+				continue;
+			btVector3 vt = vr - vn*n;
+			btScalar I = 0;
+			btScalar mass = node->m_im == 0 ? 0 : btScalar(1)/node->m_im;
+			if (applySpringForce)
+				I = -btMin(m_repulsionStiffness * timeStep * d, mass * (OVERLAP_REDUCTION_FACTOR * d / timeStep - vn));
+			if (vn < 0)
+				I += 0.5 * mass * vn;
+			btScalar face_penetration = 0, node_penetration = node->m_penetration;
+			for (int i = 0; i < 3; ++i)
+				face_penetration =  btMax(face_penetration, face->m_n[i]->m_penetration);
+			btScalar I_tilde = .5 *I /(1.0+w.length2());
+			
+//             double the impulse if node or face is constrained.
+            if (face_penetration > 0 || node_penetration > 0)
+                I_tilde *= 2.0;
+            if (face_penetration <= node_penetration)
+			{
+				for (int j = 0; j < 3; ++j)
+					face->m_n[j]->m_v += w[j]*n*I_tilde*node->m_im;
+			}
+            if (face_penetration >= node_penetration)
+			{
+				node->m_v -= I_tilde*node->m_im*n;
+			}
+			
+			// apply frictional impulse
+			btScalar vt_norm = vt.safeNorm();
+			if (vt_norm > SIMD_EPSILON)
+			{
+				btScalar delta_vn = -2 * I * node->m_im;
+				btScalar mu = c.m_friction;
+				btScalar vt_new = btMax(btScalar(1) - mu * delta_vn / (vt_norm + SIMD_EPSILON), btScalar(0))*vt_norm;
+				I = 0.5 * mass * (vt_norm-vt_new);
+				vt.safeNormalize();
+				I_tilde = .5 *I /(1.0+w.length2());
+//                 double the impulse if node or face is constrained.
+//                if (face_penetration > 0 || node_penetration > 0)
+//                    I_tilde *= 2.0;
+                if (face_penetration <= node_penetration)
+				{
+					for (int j = 0; j < 3; ++j)
+						face->m_n[j]->m_v += w[j] * vt * I_tilde * (face->m_n[j])->m_im;
+				}
+                if (face_penetration >= node_penetration)
+				{
+					node->m_v -= I_tilde * node->m_im * vt;
+				}
+			}
+		}
+	}
 	virtual int calculateSerializeBufferSize() const;
 	virtual int calculateSerializeBufferSize() const;
   
   
 	///fills the dataBuffer and returns the struct name (and 0 on failure)
 	///fills the dataBuffer and returns the struct name (and 0 on failure)

+ 79 - 1
thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp

@@ -1300,13 +1300,23 @@ btSoftBody* btSoftBodyHelpers::CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo,
         }
         }
         else if (reading_tets)
         else if (reading_tets)
         {
         {
+			int d;
+			ss >> d;
+			if (d != 4)
+			{
+				printf("Load deformable failed: Only Tetrahedra are supported in VTK file.\n");
+				fs.close();
+				return 0;
+			}
             ss.ignore(128, ' '); // ignore "4"
             ss.ignore(128, ' '); // ignore "4"
             Index tet;
             Index tet;
             tet.resize(4);
             tet.resize(4);
             for (size_t i = 0; i < 4; i++)
             for (size_t i = 0; i < 4; i++)
             {
             {
                 ss >> tet[i];
                 ss >> tet[i];
+                printf("%d ", tet[i]);
             }
             }
+            printf("\n");
             indices[indices_count++] = tet;
             indices[indices_count++] = tet;
         }
         }
     }
     }
@@ -1500,10 +1510,27 @@ void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector
     bary = btVector4(va6*v6, vb6*v6, vc6*v6, vd6*v6);
     bary = btVector4(va6*v6, vb6*v6, vc6*v6, vd6*v6);
 }
 }
 
 
+// Given a simplex with vertices a,b,c, find the barycentric weights of p in this simplex. bary[3] = 0.
+void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary)
+{
+    btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
+    btScalar d00 = btDot(v0, v0);
+    btScalar d01 = btDot(v0, v1);
+    btScalar d11 = btDot(v1, v1);
+    btScalar d20 = btDot(v2, v0);
+    btScalar d21 = btDot(v2, v1);
+    btScalar invDenom = 1.0 / (d00 * d11 - d01 * d01);
+    bary[1] = (d11 * d20 - d01 * d21) * invDenom;
+    bary[2] = (d00 * d21 - d01 * d20) * invDenom;
+    bary[0] = 1.0 - bary[1] - bary[2];
+    bary[3] = 0;
+}
+
 // Iterate through all render nodes to find the simulation tetrahedron that contains the render node and record the barycentric weights
 // Iterate through all render nodes to find the simulation tetrahedron that contains the render node and record the barycentric weights
 // If the node is not inside any tetrahedron, assign it to the tetrahedron in which the node has the least negative barycentric weight
 // If the node is not inside any tetrahedron, assign it to the tetrahedron in which the node has the least negative barycentric weight
 void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
 void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
 {
 {
+    psb->m_z.resize(0);
     psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
     psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
     psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
     psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
     for (int i = 0; i < psb->m_renderNodes.size(); ++i)
     for (int i = 0; i < psb->m_renderNodes.size(); ++i)
@@ -1513,7 +1540,6 @@ void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
         btVector4 optimal_bary;
         btVector4 optimal_bary;
         btScalar min_bary_weight = -1e3;
         btScalar min_bary_weight = -1e3;
         btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
         btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
-        bool found = false;
         for (int j = 0; j < psb->m_tetras.size(); ++j)
         for (int j = 0; j < psb->m_tetras.size(); ++j)
         {
         {
             const btSoftBody::Tetra& t = psb->m_tetras[j];
             const btSoftBody::Tetra& t = psb->m_tetras[j];
@@ -1544,3 +1570,55 @@ void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
         psb->m_renderNodesParents[i] = optimal_parents;
         psb->m_renderNodesParents[i] = optimal_parents;
     }
     }
 }
 }
+
+
+// Iterate through all render nodes to find the simulation triangle that's closest to the node in the barycentric sense.
+void btSoftBodyHelpers::extrapolateBarycentricWeights(btSoftBody* psb)
+{
+    psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
+    psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
+    psb->m_z.resize(psb->m_renderNodes.size());
+    for (int i = 0; i < psb->m_renderNodes.size(); ++i)
+    {
+        const btVector3& p = psb->m_renderNodes[i].m_x;
+        btVector4 bary;
+        btVector4 optimal_bary;
+        btScalar min_bary_weight = -SIMD_INFINITY;
+        btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
+        btScalar dist = 0, optimal_dist = 0;
+        for (int j = 0; j < psb->m_faces.size(); ++j)
+        {
+            const btSoftBody::Face& f = psb->m_faces[j];
+            btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x,  f.m_n[2]->m_x - f.m_n[0]->m_x);
+            btVector3 unit_n = n.normalized();
+            dist = (p-f.m_n[0]->m_x).dot(unit_n);
+            btVector3 proj_p = p - dist*unit_n;
+            getBarycentricWeights(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, proj_p, bary);
+            btScalar new_min_bary_weight = bary[0];
+            for (int k = 1; k < 3; ++k)
+            {
+                new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
+            }
+
+            // p is out of the current best triangle, we found a traingle that's better
+            bool better_than_closest_outisde = (new_min_bary_weight > min_bary_weight && min_bary_weight<0.);
+            // p is inside of the current best triangle, we found a triangle that's better
+            bool better_than_best_inside = (new_min_bary_weight>=0 &&  min_bary_weight>=0 && btFabs(dist)<btFabs(optimal_dist));
+
+            if (better_than_closest_outisde || better_than_best_inside)
+            {
+                btAlignedObjectArray<const btSoftBody::Node*> parents;
+                parents.push_back(f.m_n[0]);
+                parents.push_back(f.m_n[1]);
+                parents.push_back(f.m_n[2]);
+                optimal_parents = parents;
+                optimal_bary = bary;
+                optimal_dist = dist;
+                min_bary_weight = new_min_bary_weight;
+            }
+        }
+        psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
+        psb->m_renderNodesParents[i] = optimal_parents;
+        psb->m_z[i] = optimal_dist;
+    }
+}

+ 4 - 0
thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h

@@ -148,8 +148,12 @@ struct btSoftBodyHelpers
     
     
     static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary);
     static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary);
     
     
+    static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary);
+    
     static void interpolateBarycentricWeights(btSoftBody* psb);
     static void interpolateBarycentricWeights(btSoftBody* psb);
     
     
+    static void extrapolateBarycentricWeights(btSoftBody* psb);
+    
     static void generateBoundaryFaces(btSoftBody* psb);
     static void generateBoundaryFaces(btSoftBody* psb);
     
     
     static void duplicateFaces(const char* filename, const btSoftBody* psb);
     static void duplicateFaces(const char* filename, const btSoftBody* psb);

+ 726 - 72
thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h

@@ -18,7 +18,6 @@ subject to the following restrictions:
 #define _BT_SOFT_BODY_INTERNALS_H
 #define _BT_SOFT_BODY_INTERNALS_H
 
 
 #include "btSoftBody.h"
 #include "btSoftBody.h"
-
 #include "LinearMath/btQuickprof.h"
 #include "LinearMath/btQuickprof.h"
 #include "LinearMath/btPolarDecomposition.h"
 #include "LinearMath/btPolarDecomposition.h"
 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
@@ -29,9 +28,10 @@ subject to the following restrictions:
 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
 #include <string.h>  //for memset
 #include <string.h>  //for memset
 #include <cmath>
 #include <cmath>
+#include "poly34.h"
 
 
 // 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
 // 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
-static void findJacobian(const btMultiBodyLinkCollider* multibodyLinkCol,
+static SIMD_FORCE_INLINE void findJacobian(const btMultiBodyLinkCollider* multibodyLinkCol,
                          btMultiBodyJacobianData& jacobianData,
                          btMultiBodyJacobianData& jacobianData,
                          const btVector3& contact_point,
                          const btVector3& contact_point,
                          const btVector3& dir)
                          const btVector3& dir)
@@ -44,7 +44,7 @@ static void findJacobian(const btMultiBodyLinkCollider* multibodyLinkCol,
     multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, contact_point, dir, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
     multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, contact_point, dir, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
     multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], &jacobianData.m_deltaVelocitiesUnitImpulse[0], jacobianData.scratch_r, jacobianData.scratch_v);
     multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], &jacobianData.m_deltaVelocitiesUnitImpulse[0], jacobianData.scratch_r, jacobianData.scratch_v);
 }
 }
-static btVector3 generateUnitOrthogonalVector(const btVector3& u)
+static SIMD_FORCE_INLINE btVector3 generateUnitOrthogonalVector(const btVector3& u)
 {
 {
     btScalar ux = u.getX();
     btScalar ux = u.getX();
     btScalar uy = u.getY();
     btScalar uy = u.getY();
@@ -62,6 +62,571 @@ static btVector3 generateUnitOrthogonalVector(const btVector3& u)
     v.normalize();
     v.normalize();
     return v;
     return v;
 }
 }
+
+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)
+{
+    btVector3 x43 = x4-x3;
+    if (std::abs(x43.dot(normal)) > mrg)
+        return false;
+    btVector3 x13 = x1-x3;
+    btVector3 x23 = x2-x3;
+    btScalar a11 = x13.length2();
+    btScalar a22 = x23.length2();
+    btScalar a12 = x13.dot(x23);
+    btScalar b1 = x13.dot(x43);
+    btScalar b2 = x23.dot(x43);
+    btScalar det = a11*a22 - a12*a12;
+    if (det < SIMD_EPSILON)
+        return false;
+    btScalar w1 = (b1*a22-b2*a12)/det;
+    btScalar w2 = (b2*a11-b1*a12)/det;
+    btScalar w3 = 1-w1-w2;
+    btScalar delta = mrg / std::sqrt(0.5*std::abs(x13.cross(x23).safeNorm()));
+    bary = btVector3(w1,w2,w3);
+    for (int i = 0; i < 3; ++i)
+    {
+        if (bary[i] < -delta || bary[i] > 1+delta)
+            return false;
+    }
+    return true;
+}
+static const int KDOP_COUNT = 13;
+static btVector3 dop[KDOP_COUNT]={btVector3(1,0,0),
+	btVector3(0,1,0),
+	btVector3(0,0,1),
+	btVector3(1,1,0),
+	btVector3(1,0,1),
+	btVector3(0,1,1),
+	btVector3(1,-1,0),
+	btVector3(1,0,-1),
+	btVector3(0,1,-1),
+	btVector3(1,1,1),
+	btVector3(1,-1,1),
+	btVector3(1,1,-1),
+	btVector3(1,-1,-1)
+};
+
+static inline int getSign(const btVector3& n, const btVector3& x)
+{
+	btScalar d = n.dot(x);
+	if (d>SIMD_EPSILON)
+		return 1;
+	if (d<-SIMD_EPSILON)
+		return -1;
+	return 0;
+}
+
+static SIMD_FORCE_INLINE bool hasSeparatingPlane(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+	btVector3 hex[6] = {face->m_n[0]->m_x - node->m_x,
+		face->m_n[1]->m_x - node->m_x,
+		face->m_n[2]->m_x - node->m_x,
+		face->m_n[0]->m_x + dt*face->m_n[0]->m_v - node->m_x,
+		face->m_n[1]->m_x + dt*face->m_n[1]->m_v - node->m_x,
+		face->m_n[2]->m_x + dt*face->m_n[2]->m_v - node->m_x
+	};
+	btVector3 segment = dt*node->m_v;
+	for (int i = 0; i < KDOP_COUNT; ++i)
+	{
+		int s = getSign(dop[i], segment);
+		int j = 0;
+		for (; j < 6; ++j)
+		{
+			if (getSign(dop[i], hex[j]) == s)
+				break;
+		}
+		if (j == 6)
+			return true;
+	}
+	return false;
+}
+
+static SIMD_FORCE_INLINE bool nearZero(const btScalar& a)
+{
+    return (a>-SAFE_EPSILON && a<SAFE_EPSILON);
+}
+static SIMD_FORCE_INLINE bool sameSign(const btScalar& a, const btScalar& b)
+{
+    return (nearZero(a) || nearZero(b) || (a>SAFE_EPSILON && b>SAFE_EPSILON) || (a<-SAFE_EPSILON && b<-SAFE_EPSILON));
+}
+static SIMD_FORCE_INLINE bool diffSign(const btScalar& a, const btScalar& b)
+{
+    return !sameSign(a, b);
+}
+inline btScalar evaluateBezier2(const btScalar &p0, const btScalar &p1, const btScalar &p2, const btScalar &t, const btScalar &s)
+{
+    btScalar s2 = s*s;
+    btScalar t2 = t*t;
+    
+    return p0*s2+p1*btScalar(2.0)*s*t+p2*t2;
+}
+inline btScalar evaluateBezier(const btScalar &p0, const btScalar &p1, const btScalar &p2, const btScalar &p3, const btScalar &t, const btScalar &s)
+{
+    btScalar s2 = s*s;
+    btScalar s3 = s2*s;
+    btScalar t2 = t*t;
+    btScalar t3 = t2*t;
+    
+    return p0*s3+p1*btScalar(3.0)*s2*t+p2*btScalar(3.0)*s*t2+p3*t3;
+}
+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)
+{
+    if (sameSign(t0, t1)) {
+        lt0 = t0;
+        lt1 = t0;
+        return true;
+    }
+    
+    if (type_c || diffSign(k0, k3)) {
+        btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
+        if (t0<-0)
+            ft = -ft;
+        
+        if (sameSign(ft, k0)) {
+            lt0 = t1;
+            lt1 = t1;
+        }
+        else {
+            lt0 = t0;
+            lt1 = t0;
+        }
+        return true;
+    }
+    
+    if (!type_c) {
+        btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
+        if (t0<-0)
+            ft = -ft;
+        
+        if (diffSign(ft, k0)) {
+            lt0 = t0;
+            lt1 = t1;
+            return true;
+        }
+        
+        btScalar fk = evaluateBezier2(k1-k0, k2-k1, k3-k2, t0, -t1);
+        
+        if (sameSign(fk, k1-k0))
+            lt0 = lt1 = t1;
+        else
+            lt0 = lt1 = t0;
+        
+        return true;
+    }
+    return false;
+}
+
+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)
+{
+    const btVector3& n0 = face->m_n0;
+    const btVector3& n1 = face->m_n1;
+    btVector3 n_hat = n0 + n1 - face->m_vn;
+    btVector3 p0ma0 = node->m_x - face->m_n[0]->m_x;
+    btVector3 p1ma1 = node->m_q - face->m_n[0]->m_q;
+    k0 = (p0ma0).dot(n0) * 3.0;
+    k1 = (p0ma0).dot(n_hat) + (p1ma1).dot(n0);
+    k2 = (p1ma1).dot(n_hat) + (p0ma0).dot(n1);
+    k3 = (p1ma1).dot(n1) * 3.0;
+}
+
+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)
+{
+    btScalar denom = 4.0 * (j1-j2) * (j1-j0) + (j2-j0) * (j2-j0);
+    u0 = (2.0*(j1-j2)*(3.0*k1-2.0*k0-k3) - (j0-j2)*(3.0*k2-2.0*k3-k0)) / denom;
+    u1 = (2.0*(j1-j0)*(3.0*k2-2.0*k3-k0) - (j2-j0)*(3.0*k1-2.0*k0-k3)) / denom;
+    v0 = k0-u0*j0;
+    v1 = k3-u1*j2;
+}
+
+static SIMD_FORCE_INLINE bool rootFindingLemma(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3)
+{
+    btScalar u0, u1, v0, v1;
+    btScalar j0 = 3.0*(k1-k0);
+    btScalar j1 = 3.0*(k2-k1);
+    btScalar j2 = 3.0*(k3-k2);
+    polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+    if (sameSign(v0, v1))
+    {
+        btScalar Ypa = j0*(1.0-v0)*(1.0-v0) + 2.0*j1*v0*(1.0-v0) + j2*v0*v0; // Y'(v0)
+        if (sameSign(Ypa, j0))
+        {
+            return (diffSign(k0,v1));
+        }
+    }
+    return diffSign(k0,v0);
+}
+
+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)
+{
+    const btVector3& a0 = a->m_x;
+    const btVector3& b0 = b->m_x;
+    const btVector3& c0 = c->m_x;
+    const btVector3& va = a->m_v;
+    const btVector3& vb = b->m_v;
+    const btVector3& vc = c->m_v;
+    const btVector3 a1 = a0 + dt*va;
+    const btVector3 b1 = b0 + dt*vb;
+    const btVector3 c1 = c0 + dt*vc;
+    btVector3 n0 = (b0-a0).cross(c0-a0);
+    btVector3 n1 = (b1-a1).cross(c1-a1);
+    btVector3 n_hat = n0+n1 - dt*dt*(vb-va).cross(vc-va);
+    const btVector3& p0 = p->m_x;
+    const btVector3& vp = p->m_v;
+    btVector3 p1 = p0 + dt*vp;
+    btVector3 m0 = (b0-p0).cross(c0-p0);
+    btVector3 m1 = (b1-p1).cross(c1-p1);
+    btVector3 m_hat = m0+m1 - dt*dt*(vb-vp).cross(vc-vp);
+    btScalar l0 = m0.dot(n0);
+    btScalar l1 = 0.25 * (m0.dot(n_hat) + m_hat.dot(n0));
+    btScalar l2 = btScalar(1)/btScalar(6)*(m0.dot(n1) + m_hat.dot(n_hat) + m1.dot(n0));
+    btScalar l3 = 0.25 * (m_hat.dot(n1) + m1.dot(n_hat));
+    btScalar l4 = m1.dot(n1);
+    
+    btScalar k1p = 0.25 * k0 + 0.75 * k1;
+    btScalar k2p = 0.5 * k1 + 0.5 * k2;
+    btScalar k3p = 0.75 * k2 + 0.25 * k3;
+    
+    btScalar s0 = (l1 * k0 - l0 * k1p)*4.0;
+    btScalar s1 = (l2 * k0 - l0 * k2p)*2.0;
+    btScalar s2 = (l3 * k0 - l0 * k3p)*btScalar(4)/btScalar(3);
+    btScalar s3 = l4 * k0 - l0 * k3;
+    
+    j0 = (s1*k0 - s0*k1) * 3.0;
+    j1 = (s2*k0 - s0*k2) * 1.5;
+    j2 = (s3*k0 - s0*k3);
+}
+
+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)
+{
+    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)
+    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)
+
+    btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0;
+    btScalar L = sameSign(sign_Ytp, k0) ? u1 : u0;
+    sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
+    btScalar K = (sameSign(sign_Ytp,k0)) ? v1 : v0;
+    return diffSign(L,K);
+}
+
+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)
+{
+    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)
+    btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0, L1, L2;
+    if (diffSign(sign_Ytp,k0))
+    {
+        L1 = u0;
+        L2 = u1;
+    }
+    else
+    {
+        btScalar Yp_u0 = j0*(1.0-u0)*(1.0-u0) + 2.0*j1*(1.0-u0)*u0 + j2*u0*u0;
+        if (sameSign(Yp_u0,j0))
+        {
+            L1 = u1;
+            L2 = u1;
+        }
+        else
+        {
+            L1 = u0;
+            L2 = u0;
+        }
+    }
+    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)
+    sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
+    btScalar K1, K2;
+    if (diffSign(sign_Ytp,k0))
+    {
+        K1 = v0;
+        K2 = v1;
+    }
+    else
+    {
+        btScalar Yp_v0 = j0*(1.0-v0)*(1.0-v0) + 2.0*j1*(1.0-v0)*v0 + j2*v0*v0;
+        if (sameSign(Yp_v0,j0))
+        {
+            K1 = v1;
+            K2 = v1;
+        }
+        else
+        {
+            K1 = v0;
+            K2 = v0;
+        }
+    }
+    return (diffSign(K1, L1) || diffSign(L2, K2));
+}
+
+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)
+{
+    btScalar j0, j1, j2, u0, u1, v0, v1;
+    // p1
+    getJs(k0,k1,k2,k3,face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
+    if (nearZero(j0+j2-j1*2.0))
+    {
+        btScalar lt0, lt1;
+        getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+        if (lt0 < -SAFE_EPSILON)
+            return false;
+    }
+    else
+    {
+        polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+        if (!signDetermination1Internal(k0,k1,k2,k3,u0,u1,v0,v1))
+            return false;
+    }
+    // p2
+    getJs(k0,k1,k2,k3,face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
+    if (nearZero(j0+j2-j1*2.0))
+    {
+        btScalar lt0, lt1;
+        getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+        if (lt0 < -SAFE_EPSILON)
+            return false;
+    }
+    else
+    {
+        polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+        if (!signDetermination1Internal(k0,k1,k2,k3,u0,u1,v0,v1))
+            return false;
+    }
+    // p3
+    getJs(k0,k1,k2,k3,face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
+    if (nearZero(j0+j2-j1*2.0))
+    {
+        btScalar lt0, lt1;
+        getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+        if (lt0 < -SAFE_EPSILON)
+            return false;
+    }
+    else
+    {
+        polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+        if (!signDetermination1Internal(k0,k1,k2,k3,u0,u1,v0,v1))
+            return false;
+    }
+    return true;
+}
+
+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)
+{
+    btScalar j0, j1, j2, u0, u1, v0, v1;
+    // p1
+    getJs(k0,k1,k2,k3,face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
+    if (nearZero(j0+j2-j1*2.0))
+    {
+        btScalar lt0, lt1;
+        bool bt0 = true, bt1=true;
+        getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+        if (lt0 < -SAFE_EPSILON)
+            bt0 = false;
+        if (lt1 < -SAFE_EPSILON)
+            bt1 = false;
+        if (!bt0 && !bt1)
+            return false;
+    }
+    else
+    {
+        polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+        if (!signDetermination2Internal(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1))
+            return false;
+    }
+    // p2
+    getJs(k0,k1,k2,k3,face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
+    if (nearZero(j0+j2-j1*2.0))
+    {
+        btScalar lt0, lt1;
+        bool bt0=true, bt1=true;
+        getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+        if (lt0 < -SAFE_EPSILON)
+            bt0 = false;
+        if (lt1 < -SAFE_EPSILON)
+            bt1 = false;
+        if (!bt0 && !bt1)
+            return false;
+    }
+    else
+    {
+        polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+        if (!signDetermination2Internal(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1))
+            return false;
+    }
+    // p3
+    getJs(k0,k1,k2,k3,face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
+    if (nearZero(j0+j2-j1*2.0))
+    {
+        btScalar lt0, lt1;
+        bool bt0=true, bt1=true;
+        getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+        if (lt0 < -SAFE_EPSILON)
+            bt0 = false;
+        if (lt1 < -SAFE_EPSILON)
+            bt1 = false;
+        if (!bt0 && !bt1)
+            return false;
+    }
+    else
+    {
+        polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+        if (!signDetermination2Internal(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1))
+            return false;
+    }
+    return true;
+}
+
+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)
+{
+    // Coplanar test
+    if (diffSign(k1-k0, k3-k2))
+    {
+        // Case b:
+        if (sameSign(k0, k3) && !rootFindingLemma(k0,k1,k2,k3))
+            return false;
+        // inside test
+        return signDetermination2(k0, k1, k2, k3, face, node, dt);
+    }
+    else
+    {
+        // Case c:
+        if (sameSign(k0, k3))
+            return false;
+        // inside test
+        return signDetermination1(k0, k1, k2, k3, face, node, dt);
+    }
+    return false;
+}
+static SIMD_FORCE_INLINE bool conservativeCulling(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg)
+{
+    if (k0 > mrg && k1 > mrg && k2 > mrg && k3 > mrg)
+        return true;
+    if (k0 < -mrg && k1 < -mrg && k2 < -mrg && k3 < -mrg)
+        return true;
+    return false;
+}
+
+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)
+{
+    if (conservativeCulling(k0, k1, k2, k3, mrg))
+        return false;
+    return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
+}
+
+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)
+{
+    k10 = k0*(1.0-t0) + k1*t0;
+    btScalar k11 = k1*(1.0-t0) + k2*t0;
+    k12 = k2*(1.0-t0) + k3*t0;
+    k20 = k10*(1.0-t0) + k11*t0;
+    k21 = k11*(1.0-t0) + k12*t0;
+    k30 = k20*(1.0-t0) + k21*t0;
+}
+static SIMD_FORCE_INLINE bool bernsteinVFTest(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg)
+{
+    btScalar k0, k1, k2, k3;
+    getBernsteinCoeff(face, node, dt, k0, k1, k2, k3);
+    if (conservativeCulling(k0, k1, k2, k3, mrg))
+        return false;
+    return true;
+    if (diffSign(k2-2.0*k1+k0, k3-2.0*k2+k1))
+    {
+        btScalar k10, k20, k30, k21, k12;
+        btScalar t0 = (k2-2.0*k1+k0)/(k0-3.0*k1+3.0*k2-k3);
+        deCasteljau(k0, k1, k2, k3, t0, k10, k20, k30, k21, k12);
+        return bernsteinVFTest(k0, k10, k20, k30, mrg, face, node, dt) || bernsteinVFTest(k30, k21, k12, k3, mrg, face, node, dt);
+    }
+    return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
+}
+
+static SIMD_FORCE_INLINE bool continuousCollisionDetection(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
+{
+    if (hasSeparatingPlane(face, node, dt))
+        return false;
+    btVector3 x21 = face->m_n[1]->m_x - face->m_n[0]->m_x;
+    btVector3 x31 = face->m_n[2]->m_x - face->m_n[0]->m_x;
+    btVector3 x41 = node->m_x - face->m_n[0]->m_x;
+    btVector3 v21 = face->m_n[1]->m_v - face->m_n[0]->m_v;
+    btVector3 v31 = face->m_n[2]->m_v - face->m_n[0]->m_v;
+    btVector3 v41 = node->m_v - face->m_n[0]->m_v;
+    btVector3 a = x21.cross(x31);
+    btVector3 b = x21.cross(v31) + v21.cross(x31);
+    btVector3 c = v21.cross(v31);
+    btVector3 d = x41;
+    btVector3 e = v41;
+    btScalar a0 = a.dot(d);
+    btScalar a1 = a.dot(e) + b.dot(d);
+    btScalar a2 = c.dot(d) + b.dot(e);
+    btScalar a3 = c.dot(e);
+    btScalar eps = SAFE_EPSILON;
+    int num_roots = 0;
+    btScalar roots[3];
+    if (std::abs(a3) < eps)
+    {
+        // cubic term is zero
+        if (std::abs(a2) < eps)
+        {
+            if (std::abs(a1) < eps)
+            {
+                if (std::abs(a0) < eps)
+                {
+                    num_roots = 2;
+                    roots[0] = 0;
+                    roots[1] = dt;
+                }
+            }
+            else
+            {
+                num_roots = 1;
+                roots[0] = -a0/a1;
+            }
+        }
+        else
+        {
+            num_roots = SolveP2(roots, a1/a2, a0/a2);
+        }
+    }
+    else
+    {
+        num_roots = SolveP3(roots, a2/a3, a1/a3, a0/a3);
+    }
+//    std::sort(roots, roots+num_roots);
+    if (num_roots > 1)
+    {
+        if (roots[0] > roots[1])
+            btSwap(roots[0], roots[1]);
+    }
+    if (num_roots > 2)
+    {
+        if (roots[0] > roots[2])
+            btSwap(roots[0], roots[2]);
+        if (roots[1] > roots[2])
+            btSwap(roots[1], roots[2]);
+    }
+    for (int r = 0; r < num_roots; ++r)
+    {
+        double root = roots[r];
+        if (root <= 0)
+            continue;
+        if (root > dt + SIMD_EPSILON)
+            return false;
+        btVector3 x1 = face->m_n[0]->m_x + root * face->m_n[0]->m_v;
+        btVector3 x2 = face->m_n[1]->m_x + root * face->m_n[1]->m_v;
+        btVector3 x3 = face->m_n[2]->m_x + root * face->m_n[2]->m_v;
+        btVector3 x4 = node->m_x + root * node->m_v;
+        btVector3 normal = (x2-x1).cross(x3-x1);
+        normal.safeNormalize();
+        if (proximityTest(x1, x2, x3, x4, normal, mrg, bary))
+            return true;
+    }
+    return false;
+}
+static SIMD_FORCE_INLINE bool bernsteinCCD(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
+{
+    if (!bernsteinVFTest(face, node, dt, mrg))
+        return false;
+    if (!continuousCollisionDetection(face, node, dt, 1e-6, bary))
+        return false;
+    return true;
+}
+
 //
 //
 // btSymMatrix
 // btSymMatrix
 //
 //
@@ -373,6 +938,26 @@ static inline btMatrix3x3 OuterProduct(const btScalar* v1,const btScalar* v2,con
     return (m);
     return (m);
 }
 }
 
 
+static inline btMatrix3x3 OuterProduct(const btVector3& v1,const btVector3& v2)
+{
+    btMatrix3x3 m;
+    btScalar a11 = v1[0] * v2[0];
+    btScalar a12 = v1[0] * v2[1];
+    btScalar a13 = v1[0] * v2[2];
+    
+    btScalar a21 = v1[1] * v2[0];
+    btScalar a22 = v1[1] * v2[1];
+    btScalar a23 = v1[1] * v2[2];
+    
+    btScalar a31 = v1[2] * v2[0];
+    btScalar a32 = v1[2] * v2[1];
+    btScalar a33 = v1[2] * v2[2];
+    m[0] = btVector3(a11, a12, a13);
+    m[1] = btVector3(a21, a22, a23);
+    m[2] = btVector3(a31, a32, a33);
+    return (m);
+}
+
 
 
 //
 //
 static inline btMatrix3x3 Add(const btMatrix3x3& a,
 static inline btMatrix3x3 Add(const btMatrix3x3& a,
@@ -1070,8 +1655,8 @@ struct btSoftColliders
 
 
 			if (!n.m_battach)
 			if (!n.m_battach)
             {
             {
-                // check for collision at x_{n+1}^* as well at x_n
-                if (psb->checkDeformableContact(m_colObj1Wrap, n.m_x, m, c.m_cti, /*predict = */ true) || psb->checkDeformableContact(m_colObj1Wrap, n.m_q, m, c.m_cti, /*predict = */ true))
+				// check for collision at x_{n+1}^*
+				if (psb->checkDeformableContact(m_colObj1Wrap, n.m_q, m, c.m_cti, /*predict = */ true))
                 {
                 {
                     const btScalar ima = n.m_im;
                     const btScalar ima = n.m_im;
                     // todo: collision between multibody and fixed deformable node will be missed.
                     // todo: collision between multibody and fixed deformable node will be missed.
@@ -1159,7 +1744,6 @@ struct btSoftColliders
             btSoftBody::Node* n0 = f.m_n[0];
             btSoftBody::Node* n0 = f.m_n[0];
             btSoftBody::Node* n1 = f.m_n[1];
             btSoftBody::Node* n1 = f.m_n[1];
             btSoftBody::Node* n2 = f.m_n[2];
             btSoftBody::Node* n2 = f.m_n[2];
-            
             const btScalar m = (n0->m_im > 0 && n1->m_im > 0 && n2->m_im > 0 )? dynmargin : stamargin;
             const btScalar m = (n0->m_im > 0 && n1->m_im > 0 && n2->m_im > 0 )? dynmargin : stamargin;
             btSoftBody::DeformableFaceRigidContact c;
             btSoftBody::DeformableFaceRigidContact c;
             btVector3 contact_point;
             btVector3 contact_point;
@@ -1174,18 +1758,19 @@ struct btSoftColliders
                 if (ms > 0)
                 if (ms > 0)
                 {
                 {
                     // resolve contact at x_n
                     // resolve contact at x_n
-                    psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, /*predict = */ false);
+//                    psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, /*predict = */ false);
                     btSoftBody::sCti& cti = c.m_cti;
                     btSoftBody::sCti& cti = c.m_cti;
                     c.m_contactPoint = contact_point;
                     c.m_contactPoint = contact_point;
                     c.m_bary = bary;
                     c.m_bary = bary;
                     // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
                     // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
                     c.m_weights = btScalar(2)/(btScalar(1) + bary.length2()) * bary;
                     c.m_weights = btScalar(2)/(btScalar(1) + bary.length2()) * bary;
                     c.m_face = &f;
                     c.m_face = &f;
+					// friction is handled by the nodes to prevent sticking
+//                    const btScalar fc = 0;
                     const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
                     const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
                     
                     
                     // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
                     // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
                     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;
                     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;
-                    
                     c.m_c2 = ima;
                     c.m_c2 = ima;
                     c.m_c3 = fc;
                     c.m_c3 = fc;
                     c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
                     c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
@@ -1316,19 +1901,11 @@ struct btSoftColliders
         {
         {
             btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
             btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
             btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
             btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
-            
-            btVector3 o = node->m_x;
-            btVector3 p;
-            btScalar d = SIMD_INFINITY;
-            ProjectOrigin(face->m_n[0]->m_x - o,
-                          face->m_n[1]->m_x - o,
-                          face->m_n[2]->m_x - o,
-                          p, d);
-            const btScalar m = mrg + (o - node->m_q).safeNorm() * 2;
-            if (d < (m * m))
+            btVector3 bary;
+            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))
             {
             {
                 const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
                 const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
-                const btVector3 w = BaryCoord(n[0]->m_x, n[1]->m_x, n[2]->m_x, p + o);
+                const btVector3 w = bary;
                 const btScalar ma = node->m_im;
                 const btScalar ma = node->m_im;
                 btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
                 btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
                 if ((n[0]->m_im <= 0) ||
                 if ((n[0]->m_im <= 0) ||
@@ -1341,20 +1918,14 @@ struct btSoftColliders
                 if (ms > 0)
                 if (ms > 0)
                 {
                 {
                     btSoftBody::DeformableFaceNodeContact c;
                     btSoftBody::DeformableFaceNodeContact c;
-                    if (useFaceNormal)
-                        c.m_normal = face->m_normal;
-                    else
-                        c.m_normal = p / -btSqrt(d);
+                    c.m_normal = face->m_normal;
+                    if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+                        c.m_normal  = -face->m_normal;
                     c.m_margin = mrg;
                     c.m_margin = mrg;
                     c.m_node = node;
                     c.m_node = node;
                     c.m_face = face;
                     c.m_face = face;
                     c.m_bary = w;
                     c.m_bary = w;
-                    // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
-                    c.m_weights = btScalar(2)/(btScalar(1) + w.length2()) * w;
                     c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
                     c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
-                    // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
-                    c.m_imf = c.m_bary[0]*c.m_weights[0] * n[0]->m_im + c.m_bary[1]*c.m_weights[1] * n[1]->m_im + c.m_bary[2]*c.m_weights[2] * n[2]->m_im;
-                    c.m_c0 = btScalar(1)/(ma + c.m_imf);
                     psb[0]->m_faceNodeContacts.push_back(c);
                     psb[0]->m_faceNodeContacts.push_back(c);
                 }
                 }
             }
             }
@@ -1372,69 +1943,152 @@ struct btSoftColliders
         void Process(const btDbvntNode* lface1,
         void Process(const btDbvntNode* lface1,
                      const btDbvntNode* lface2)
                      const btDbvntNode* lface2)
         {
         {
-            btSoftBody::Face* f = (btSoftBody::Face*)lface1->data;
-            btSoftBody::Face* face = (btSoftBody::Face*)lface2->data;
+            btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
+            btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
+            if (f1 != f2)
+            {
+                Repel(f1, f2);
+                Repel(f2, f1);
+            }
+        }
+        void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
+        {
+            //#define REPEL_NEIGHBOR 1
+#ifndef REPEL_NEIGHBOR
             for (int node_id = 0; node_id < 3; ++node_id)
             for (int node_id = 0; node_id < 3; ++node_id)
             {
             {
-                btSoftBody::Node* node = f->m_n[node_id];
-                bool skip = false;
+                btSoftBody::Node* node = f1->m_n[node_id];
                 for (int i = 0; i < 3; ++i)
                 for (int i = 0; i < 3; ++i)
                 {
                 {
-                    if (face->m_n[i] == node)
+                    if (f2->m_n[i] == node)
+                        return;
+                }
+            }
+#endif
+            bool skip = false;
+            for (int node_id = 0; node_id < 3; ++node_id)
+            {
+                btSoftBody::Node* node = f1->m_n[node_id];
+#ifdef REPEL_NEIGHBOR
+                for (int i = 0; i < 3; ++i)
+                {
+                    if (f2->m_n[i] == node)
                     {
                     {
                         skip = true;
                         skip = true;
                         break;
                         break;
                     }
                     }
                 }
                 }
                 if (skip)
                 if (skip)
+                {
+                    skip = false;
+                    continue;
+                }
+#endif
+                btSoftBody::Face* face = f2;
+                btVector3 bary;
+                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))
                     continue;
                     continue;
-                btVector3 o = node->m_x;
-                btVector3 p;
-                btScalar d = SIMD_INFINITY;
-                ProjectOrigin(face->m_n[0]->m_x - o,
-                              face->m_n[1]->m_x - o,
-                              face->m_n[2]->m_x - o,
-                              p, d);
-                const btScalar m = mrg + (o - node->m_q).safeNorm() * 2;
-                if (d < (m * m))
+                btSoftBody::DeformableFaceNodeContact c;
+                c.m_normal = face->m_normal;
+                if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+                    c.m_normal  = -face->m_normal;
+                c.m_margin = mrg;
+                c.m_node = node;
+                c.m_face = face;
+                c.m_bary = bary;
+                c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+                psb[0]->m_faceNodeContacts.push_back(c);
+            }
+        }
+        btSoftBody* psb[2];
+        btScalar mrg;
+        bool useFaceNormal;
+    };
+
+    struct CollideCCD : btDbvt::ICollide
+    {
+        void Process(const btDbvtNode* lnode,
+                     const btDbvtNode* lface)
+        {
+            btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
+            btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
+            btVector3 bary;
+            if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
+            {
+                btSoftBody::DeformableFaceNodeContact c;
+                c.m_normal = face->m_normal;
+                if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+                    c.m_normal  = -face->m_normal;
+                c.m_node = node;
+                c.m_face = face;
+                c.m_bary = bary;
+                c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+                psb[0]->m_faceNodeContacts.push_back(c);
+            }
+        }
+        void Process(const btDbvntNode* lface1,
+                     const btDbvntNode* lface2)
+        {
+            btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
+            btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
+            if (f1 != f2)
+            {
+                Repel(f1, f2);
+                Repel(f2, f1);
+            }
+        }
+        void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
+        {
+            //#define REPEL_NEIGHBOR 1
+#ifndef REPEL_NEIGHBOR
+            for (int node_id = 0; node_id < 3; ++node_id)
+            {
+                btSoftBody::Node* node = f1->m_n[node_id];
+                for (int i = 0; i < 3; ++i)
                 {
                 {
-                    const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
-                    const btVector3 w = BaryCoord(n[0]->m_x, n[1]->m_x, n[2]->m_x, p + o);
-                    const btScalar ma = node->m_im;
-                    btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
-                    if ((n[0]->m_im <= 0) ||
-                        (n[1]->m_im <= 0) ||
-                        (n[2]->m_im <= 0))
-                    {
-                        mb = 0;
-                    }
-                    const btScalar ms = ma + mb;
-                    if (ms > 0)
+                    if (f2->m_n[i] == node)
+                        return;
+                }
+            }
+#endif
+            bool skip = false;
+            for (int node_id = 0; node_id < 3; ++node_id)
+            {
+                btSoftBody::Node* node = f1->m_n[node_id];
+#ifdef REPEL_NEIGHBOR
+                for (int i = 0; i < 3; ++i)
+                {
+                    if (f2->m_n[i] == node)
                     {
                     {
-                        btSoftBody::DeformableFaceNodeContact c;
-                        if (useFaceNormal)
-                            c.m_normal = face->m_normal;
-                        else
-                            c.m_normal = p / -btSqrt(d);
-                        c.m_margin = mrg;
-                        c.m_node = node;
-                        c.m_face = face;
-                        c.m_bary = w;
-                        // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
-                        c.m_weights = btScalar(2)/(btScalar(1) + w.length2()) * w;
-                        c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
-                        // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
-                        c.m_imf = c.m_bary[0]*c.m_weights[0] * n[0]->m_im + c.m_bary[1]*c.m_weights[1] * n[1]->m_im + c.m_bary[2]*c.m_weights[2] * n[2]->m_im;
-                        c.m_c0 = btScalar(1)/(ma + c.m_imf);
-                        psb[0]->m_faceNodeContacts.push_back(c);
+                        skip = true;
+                        break;
                     }
                     }
                 }
                 }
+                if (skip)
+                {
+                    skip = false;
+                    continue;
+                }
+#endif
+                btSoftBody::Face* face = f2;
+                btVector3 bary;
+				if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
+                {
+                    btSoftBody::DeformableFaceNodeContact c;
+                    c.m_normal = face->m_normal;
+                    if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+                        c.m_normal  = -face->m_normal;
+                    c.m_node = node;
+                    c.m_face = face;
+                    c.m_bary = bary;
+                    c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+                    psb[0]->m_faceNodeContacts.push_back(c);
+                }
             }
             }
         }
         }
         btSoftBody* psb[2];
         btSoftBody* psb[2];
-        btScalar mrg;
+        btScalar dt, mrg;
         bool useFaceNormal;
         bool useFaceNormal;
     };
     };
 };
 };
-
 #endif  //_BT_SOFT_BODY_INTERNALS_H
 #endif  //_BT_SOFT_BODY_INTERNALS_H

+ 2 - 1
thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp

@@ -48,9 +48,10 @@ btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
 }
 }
 
 
 #include <stdio.h>
 #include <stdio.h>
-
+#include "LinearMath/btQuickprof.h"
 void btSoftRigidCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
 void btSoftRigidCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
 {
 {
+	BT_PROFILE("btSoftRigidCollisionAlgorithm::processCollision");
 	(void)dispatchInfo;
 	(void)dispatchInfo;
 	(void)resultOut;
 	(void)resultOut;
 	//printf("btSoftRigidCollisionAlgorithm\n");
 	//printf("btSoftRigidCollisionAlgorithm\n");

+ 419 - 0
thirdparty/bullet/BulletSoftBody/poly34.cpp

@@ -0,0 +1,419 @@
+// poly34.cpp : solution of cubic and quartic equation
+// (c) Khashin S.I. http://math.ivanovo.ac.ru/dalgebra/Khashin/index.html
+// khash2 (at) gmail.com
+// Thanks to Alexandr Rakhmanin <rakhmanin (at) gmail.com>
+// public domain
+//
+#include <math.h>
+
+#include "poly34.h" // solution of cubic and quartic equation
+#define TwoPi 6.28318530717958648
+const btScalar eps = SIMD_EPSILON;
+
+//=============================================================================
+// _root3, root3 from http://prografix.narod.ru
+//=============================================================================
+static SIMD_FORCE_INLINE btScalar _root3(btScalar x)
+{
+    btScalar s = 1.;
+    while (x < 1.) {
+        x *= 8.;
+        s *= 0.5;
+    }
+    while (x > 8.) {
+        x *= 0.125;
+        s *= 2.;
+    }
+    btScalar r = 1.5;
+    r -= 1. / 3. * (r - x / (r * r));
+    r -= 1. / 3. * (r - x / (r * r));
+    r -= 1. / 3. * (r - x / (r * r));
+    r -= 1. / 3. * (r - x / (r * r));
+    r -= 1. / 3. * (r - x / (r * r));
+    r -= 1. / 3. * (r - x / (r * r));
+    return r * s;
+}
+
+btScalar SIMD_FORCE_INLINE root3(btScalar x)
+{
+    if (x > 0)
+        return _root3(x);
+    else if (x < 0)
+        return -_root3(-x);
+    else
+        return 0.;
+}
+
+// x - array of size 2
+// return 2: 2 real roots x[0], x[1]
+// return 0: pair of complex roots: x[0]i*x[1]
+int SolveP2(btScalar* x, btScalar a, btScalar b)
+{ // solve equation x^2 + a*x + b = 0
+    btScalar D = 0.25 * a * a - b;
+    if (D >= 0) {
+        D = sqrt(D);
+        x[0] = -0.5 * a + D;
+        x[1] = -0.5 * a - D;
+        return 2;
+    }
+    x[0] = -0.5 * a;
+    x[1] = sqrt(-D);
+    return 0;
+}
+//---------------------------------------------------------------------------
+// x - array of size 3
+// In case 3 real roots: => x[0], x[1], x[2], return 3
+//         2 real roots: x[0], x[1],          return 2
+//         1 real root : x[0], x[1]  i*x[2], return 1
+int SolveP3(btScalar* x, btScalar a, btScalar b, btScalar c)
+{ // solve cubic equation x^3 + a*x^2 + b*x + c = 0
+    btScalar a2 = a * a;
+    btScalar q = (a2 - 3 * b) / 9;
+    if (q < 0)
+        q = eps;
+    btScalar r = (a * (2 * a2 - 9 * b) + 27 * c) / 54;
+    // equation x^3 + q*x + r = 0
+    btScalar r2 = r * r;
+    btScalar q3 = q * q * q;
+    btScalar A, B;
+    if (r2 <= (q3 + eps)) { //<<-- FIXED!
+        btScalar t = r / sqrt(q3);
+        if (t < -1)
+            t = -1;
+        if (t > 1)
+            t = 1;
+        t = acos(t);
+        a /= 3;
+        q = -2 * sqrt(q);
+        x[0] = q * cos(t / 3) - a;
+        x[1] = q * cos((t + TwoPi) / 3) - a;
+        x[2] = q * cos((t - TwoPi) / 3) - a;
+        return (3);
+    }
+    else {
+        //A =-pow(fabs(r)+sqrt(r2-q3),1./3);
+        A = -root3(fabs(r) + sqrt(r2 - q3));
+        if (r < 0)
+            A = -A;
+        B = (A == 0 ? 0 : q / A);
+        
+        a /= 3;
+        x[0] = (A + B) - a;
+        x[1] = -0.5 * (A + B) - a;
+        x[2] = 0.5 * sqrt(3.) * (A - B);
+        if (fabs(x[2]) < eps) {
+            x[2] = x[1];
+            return (2);
+        }
+        return (1);
+    }
+} // SolveP3(btScalar *x,btScalar a,btScalar b,btScalar c) {
+//---------------------------------------------------------------------------
+// a>=0!
+void CSqrt(btScalar x, btScalar y, btScalar& a, btScalar& b) // returns:  a+i*s = sqrt(x+i*y)
+{
+    btScalar r = sqrt(x * x + y * y);
+    if (y == 0) {
+        r = sqrt(r);
+        if (x >= 0) {
+            a = r;
+            b = 0;
+        }
+        else {
+            a = 0;
+            b = r;
+        }
+    }
+    else { // y != 0
+        a = sqrt(0.5 * (x + r));
+        b = 0.5 * y / a;
+    }
+}
+//---------------------------------------------------------------------------
+int SolveP4Bi(btScalar* x, btScalar b, btScalar d) // solve equation x^4 + b*x^2 + d = 0
+{
+    btScalar D = b * b - 4 * d;
+    if (D >= 0) {
+        btScalar sD = sqrt(D);
+        btScalar x1 = (-b + sD) / 2;
+        btScalar x2 = (-b - sD) / 2; // x2 <= x1
+        if (x2 >= 0) // 0 <= x2 <= x1, 4 real roots
+        {
+            btScalar sx1 = sqrt(x1);
+            btScalar sx2 = sqrt(x2);
+            x[0] = -sx1;
+            x[1] = sx1;
+            x[2] = -sx2;
+            x[3] = sx2;
+            return 4;
+        }
+        if (x1 < 0) // x2 <= x1 < 0, two pair of imaginary roots
+        {
+            btScalar sx1 = sqrt(-x1);
+            btScalar sx2 = sqrt(-x2);
+            x[0] = 0;
+            x[1] = sx1;
+            x[2] = 0;
+            x[3] = sx2;
+            return 0;
+        }
+        // now x2 < 0 <= x1 , two real roots and one pair of imginary root
+        btScalar sx1 = sqrt(x1);
+        btScalar sx2 = sqrt(-x2);
+        x[0] = -sx1;
+        x[1] = sx1;
+        x[2] = 0;
+        x[3] = sx2;
+        return 2;
+    }
+    else { // if( D < 0 ), two pair of compex roots
+        btScalar sD2 = 0.5 * sqrt(-D);
+        CSqrt(-0.5 * b, sD2, x[0], x[1]);
+        CSqrt(-0.5 * b, -sD2, x[2], x[3]);
+        return 0;
+    } // if( D>=0 )
+} // SolveP4Bi(btScalar *x, btScalar b, btScalar d)    // solve equation x^4 + b*x^2 d
+//---------------------------------------------------------------------------
+#define SWAP(a, b) \
+{              \
+t = b;     \
+b = a;     \
+a = t;     \
+}
+static void dblSort3(btScalar& a, btScalar& b, btScalar& c) // make: a <= b <= c
+{
+    btScalar t;
+    if (a > b)
+        SWAP(a, b); // now a<=b
+    if (c < b) {
+        SWAP(b, c); // now a<=b, b<=c
+        if (a > b)
+            SWAP(a, b); // now a<=b
+    }
+}
+//---------------------------------------------------------------------------
+int SolveP4De(btScalar* x, btScalar b, btScalar c, btScalar d) // solve equation x^4 + b*x^2 + c*x + d
+{
+    //if( c==0 ) return SolveP4Bi(x,b,d); // After that, c!=0
+    if (fabs(c) < 1e-14 * (fabs(b) + fabs(d)))
+        return SolveP4Bi(x, b, d); // After that, c!=0
+    
+    int res3 = SolveP3(x, 2 * b, b * b - 4 * d, -c * c); // solve resolvent
+    // by Viet theorem:  x1*x2*x3=-c*c not equals to 0, so x1!=0, x2!=0, x3!=0
+    if (res3 > 1) // 3 real roots,
+    {
+        dblSort3(x[0], x[1], x[2]); // sort roots to x[0] <= x[1] <= x[2]
+        // Note: x[0]*x[1]*x[2]= c*c > 0
+        if (x[0] > 0) // all roots are positive
+        {
+            btScalar sz1 = sqrt(x[0]);
+            btScalar sz2 = sqrt(x[1]);
+            btScalar sz3 = sqrt(x[2]);
+            // Note: sz1*sz2*sz3= -c (and not equal to 0)
+            if (c > 0) {
+                x[0] = (-sz1 - sz2 - sz3) / 2;
+                x[1] = (-sz1 + sz2 + sz3) / 2;
+                x[2] = (+sz1 - sz2 + sz3) / 2;
+                x[3] = (+sz1 + sz2 - sz3) / 2;
+                return 4;
+            }
+            // now: c<0
+            x[0] = (-sz1 - sz2 + sz3) / 2;
+            x[1] = (-sz1 + sz2 - sz3) / 2;
+            x[2] = (+sz1 - sz2 - sz3) / 2;
+            x[3] = (+sz1 + sz2 + sz3) / 2;
+            return 4;
+        } // if( x[0] > 0) // all roots are positive
+        // now x[0] <= x[1] < 0, x[2] > 0
+        // two pair of comlex roots
+        btScalar sz1 = sqrt(-x[0]);
+        btScalar sz2 = sqrt(-x[1]);
+        btScalar sz3 = sqrt(x[2]);
+        
+        if (c > 0) // sign = -1
+        {
+            x[0] = -sz3 / 2;
+            x[1] = (sz1 - sz2) / 2; // x[0]i*x[1]
+            x[2] = sz3 / 2;
+            x[3] = (-sz1 - sz2) / 2; // x[2]i*x[3]
+            return 0;
+        }
+        // now: c<0 , sign = +1
+        x[0] = sz3 / 2;
+        x[1] = (-sz1 + sz2) / 2;
+        x[2] = -sz3 / 2;
+        x[3] = (sz1 + sz2) / 2;
+        return 0;
+    } // if( res3>1 )    // 3 real roots,
+    // now resoventa have 1 real and pair of compex roots
+    // x[0] - real root, and x[0]>0,
+    // x[1]i*x[2] - complex roots,
+    // x[0] must be >=0. But one times x[0]=~ 1e-17, so:
+    if (x[0] < 0)
+        x[0] = 0;
+    btScalar sz1 = sqrt(x[0]);
+    btScalar szr, szi;
+    CSqrt(x[1], x[2], szr, szi); // (szr+i*szi)^2 = x[1]+i*x[2]
+    if (c > 0) // sign = -1
+    {
+        x[0] = -sz1 / 2 - szr; // 1st real root
+        x[1] = -sz1 / 2 + szr; // 2nd real root
+        x[2] = sz1 / 2;
+        x[3] = szi;
+        return 2;
+    }
+    // now: c<0 , sign = +1
+    x[0] = sz1 / 2 - szr; // 1st real root
+    x[1] = sz1 / 2 + szr; // 2nd real root
+    x[2] = -sz1 / 2;
+    x[3] = szi;
+    return 2;
+} // SolveP4De(btScalar *x, btScalar b, btScalar c, btScalar d)    // solve equation x^4 + b*x^2 + c*x + d
+//-----------------------------------------------------------------------------
+btScalar N4Step(btScalar x, btScalar a, btScalar b, btScalar c, btScalar d) // one Newton step for x^4 + a*x^3 + b*x^2 + c*x + d
+{
+    btScalar fxs = ((4 * x + 3 * a) * x + 2 * b) * x + c; // f'(x)
+    if (fxs == 0)
+        return x; //return 1e99; <<-- FIXED!
+    btScalar fx = (((x + a) * x + b) * x + c) * x + d; // f(x)
+    return x - fx / fxs;
+}
+//-----------------------------------------------------------------------------
+// x - array of size 4
+// return 4: 4 real roots x[0], x[1], x[2], x[3], possible multiple roots
+// return 2: 2 real roots x[0], x[1] and complex x[2]i*x[3],
+// return 0: two pair of complex roots: x[0]i*x[1],  x[2]i*x[3],
+int SolveP4(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d)
+{ // solve equation x^4 + a*x^3 + b*x^2 + c*x + d by Dekart-Euler method
+    // move to a=0:
+    btScalar d1 = d + 0.25 * a * (0.25 * b * a - 3. / 64 * a * a * a - c);
+    btScalar c1 = c + 0.5 * a * (0.25 * a * a - b);
+    btScalar b1 = b - 0.375 * a * a;
+    int res = SolveP4De(x, b1, c1, d1);
+    if (res == 4) {
+        x[0] -= a / 4;
+        x[1] -= a / 4;
+        x[2] -= a / 4;
+        x[3] -= a / 4;
+    }
+    else if (res == 2) {
+        x[0] -= a / 4;
+        x[1] -= a / 4;
+        x[2] -= a / 4;
+    }
+    else {
+        x[0] -= a / 4;
+        x[2] -= a / 4;
+    }
+    // one Newton step for each real root:
+    if (res > 0) {
+        x[0] = N4Step(x[0], a, b, c, d);
+        x[1] = N4Step(x[1], a, b, c, d);
+    }
+    if (res > 2) {
+        x[2] = N4Step(x[2], a, b, c, d);
+        x[3] = N4Step(x[3], a, b, c, d);
+    }
+    return res;
+}
+//-----------------------------------------------------------------------------
+#define F5(t) (((((t + a) * t + b) * t + c) * t + d) * t + e)
+//-----------------------------------------------------------------------------
+btScalar SolveP5_1(btScalar a, btScalar b, btScalar c, btScalar d, btScalar e) // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+{
+    int cnt;
+    if (fabs(e) < eps)
+        return 0;
+    
+    btScalar brd = fabs(a); // brd - border of real roots
+    if (fabs(b) > brd)
+        brd = fabs(b);
+    if (fabs(c) > brd)
+        brd = fabs(c);
+    if (fabs(d) > brd)
+        brd = fabs(d);
+    if (fabs(e) > brd)
+        brd = fabs(e);
+    brd++; // brd - border of real roots
+    
+    btScalar x0, f0; // less than root
+    btScalar x1, f1; // greater than root
+    btScalar x2, f2, f2s; // next values, f(x2), f'(x2)
+    btScalar dx = 0;
+    
+    if (e < 0) {
+        x0 = 0;
+        x1 = brd;
+        f0 = e;
+        f1 = F5(x1);
+        x2 = 0.01 * brd;
+    } // positive root
+    else {
+        x0 = -brd;
+        x1 = 0;
+        f0 = F5(x0);
+        f1 = e;
+        x2 = -0.01 * brd;
+    } // negative root
+    
+    if (fabs(f0) < eps)
+        return x0;
+    if (fabs(f1) < eps)
+        return x1;
+    
+    // now x0<x1, f(x0)<0, f(x1)>0
+    // Firstly 10 bisections
+    for (cnt = 0; cnt < 10; cnt++) {
+        x2 = (x0 + x1) / 2; // next point
+        //x2 = x0 - f0*(x1 - x0) / (f1 - f0);        // next point
+        f2 = F5(x2); // f(x2)
+        if (fabs(f2) < eps)
+            return x2;
+        if (f2 > 0) {
+            x1 = x2;
+            f1 = f2;
+        }
+        else {
+            x0 = x2;
+            f0 = f2;
+        }
+    }
+    
+    // At each step:
+    // x0<x1, f(x0)<0, f(x1)>0.
+    // x2 - next value
+    // we hope that x0 < x2 < x1, but not necessarily
+    do {
+        if (cnt++ > 50)
+            break;
+        if (x2 <= x0 || x2 >= x1)
+            x2 = (x0 + x1) / 2; // now  x0 < x2 < x1
+        f2 = F5(x2); // f(x2)
+        if (fabs(f2) < eps)
+            return x2;
+        if (f2 > 0) {
+            x1 = x2;
+            f1 = f2;
+        }
+        else {
+            x0 = x2;
+            f0 = f2;
+        }
+        f2s = (((5 * x2 + 4 * a) * x2 + 3 * b) * x2 + 2 * c) * x2 + d; // f'(x2)
+        if (fabs(f2s) < eps) {
+            x2 = 1e99;
+            continue;
+        }
+        dx = f2 / f2s;
+        x2 -= dx;
+    } while (fabs(dx) > eps);
+    return x2;
+} // SolveP5_1(btScalar a,btScalar b,btScalar c,btScalar d,btScalar e)    // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+//-----------------------------------------------------------------------------
+int SolveP5(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d, btScalar e) // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+{
+    btScalar r = x[0] = SolveP5_1(a, b, c, d, e);
+    btScalar a1 = a + r, b1 = b + r * a1, c1 = c + r * b1, d1 = d + r * c1;
+    return 1 + SolveP4(x + 1, a1, b1, c1, d1);
+} // SolveP5(btScalar *x,btScalar a,btScalar b,btScalar c,btScalar d,btScalar e)    // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+//-----------------------------------------------------------------------------

+ 38 - 0
thirdparty/bullet/BulletSoftBody/poly34.h

@@ -0,0 +1,38 @@
+// poly34.h : solution of cubic and quartic equation
+// (c) Khashin S.I. http://math.ivanovo.ac.ru/dalgebra/Khashin/index.html
+// khash2 (at) gmail.com
+
+#ifndef POLY_34
+#define POLY_34
+#include "LinearMath/btScalar.h"
+// x - array of size 2
+// return 2: 2 real roots x[0], x[1]
+// return 0: pair of complex roots: x[0]i*x[1]
+int SolveP2(btScalar* x, btScalar a, btScalar b); // solve equation x^2 + a*x + b = 0
+
+// x - array of size 3
+// return 3: 3 real roots x[0], x[1], x[2]
+// return 1: 1 real root x[0] and pair of complex roots: x[1]i*x[2]
+int SolveP3(btScalar* x, btScalar a, btScalar b, btScalar c); // solve cubic equation x^3 + a*x^2 + b*x + c = 0
+
+// x - array of size 4
+// return 4: 4 real roots x[0], x[1], x[2], x[3], possible multiple roots
+// return 2: 2 real roots x[0], x[1] and complex x[2]i*x[3],
+// return 0: two pair of complex roots: x[0]i*x[1],  x[2]i*x[3],
+int SolveP4(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d); // solve equation x^4 + a*x^3 + b*x^2 + c*x + d = 0 by Dekart-Euler method
+
+// x - array of size 5
+// return 5: 5 real roots x[0], x[1], x[2], x[3], x[4], possible multiple roots
+// return 3: 3 real roots x[0], x[1], x[2] and complex x[3]i*x[4],
+// return 1: 1 real root x[0] and two pair of complex roots: x[1]i*x[2],  x[3]i*x[4],
+int SolveP5(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d, btScalar e); // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+
+//-----------------------------------------------------------------------------
+// And some additional functions for internal use.
+// Your may remove this definitions from here
+int SolveP4Bi(btScalar* x, btScalar b, btScalar d); // solve equation x^4 + b*x^2 + d = 0
+int SolveP4De(btScalar* x, btScalar b, btScalar c, btScalar d); // solve equation x^4 + b*x^2 + c*x + d = 0
+void CSqrt(btScalar x, btScalar y, btScalar& a, btScalar& b); // returns as a+i*s,  sqrt(x+i*y)
+btScalar N4Step(btScalar x, btScalar a, btScalar b, btScalar c, btScalar d); // one Newton step for x^4 + a*x^3 + b*x^2 + c*x + d
+btScalar SolveP5_1(btScalar a, btScalar b, btScalar c, btScalar d, btScalar e); // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+#endif

+ 2 - 2
thirdparty/bullet/LinearMath/btImplicitQRSVD.h

@@ -41,7 +41,7 @@
 
 
 #ifndef btImplicitQRSVD_h
 #ifndef btImplicitQRSVD_h
 #define btImplicitQRSVD_h
 #define btImplicitQRSVD_h
-
+#include <limits>
 #include "btMatrix3x3.h"
 #include "btMatrix3x3.h"
 class btMatrix2x2
 class btMatrix2x2
 {
 {
@@ -753,7 +753,7 @@ inline int singularValueDecomposition(const btMatrix3x3& A,
                                      btMatrix3x3& V,
                                      btMatrix3x3& V,
                                      btScalar tol = 128*std::numeric_limits<btScalar>::epsilon())
                                      btScalar tol = 128*std::numeric_limits<btScalar>::epsilon())
 {
 {
-    using std::fabs;
+//    using std::fabs;
     btMatrix3x3 B = A;
     btMatrix3x3 B = A;
     U.setIdentity();
     U.setIdentity();
     V.setIdentity();
     V.setIdentity();

+ 16 - 0
thirdparty/bullet/LinearMath/btMatrix3x3.h

@@ -26,10 +26,12 @@ subject to the following restrictions:
 #endif
 #endif
 
 
 #if defined(BT_USE_SSE)
 #if defined(BT_USE_SSE)
+#define v0000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f))
 #define v1000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f))
 #define v1000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f))
 #define v0100 (_mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f))
 #define v0100 (_mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f))
 #define v0010 (_mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f))
 #define v0010 (_mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f))
 #elif defined(BT_USE_NEON)
 #elif defined(BT_USE_NEON)
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0000) = {0.0f, 0.0f, 0.0f, 0.0f};
 const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
 const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
 const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
 const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
 const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
 const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
@@ -330,6 +332,20 @@ public:
 				 btScalar(0.0), btScalar(0.0), btScalar(1.0));
 				 btScalar(0.0), btScalar(0.0), btScalar(1.0));
 #endif
 #endif
 	}
 	}
+    
+    /**@brief Set the matrix to the identity */
+    void setZero()
+    {
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+        m_el[0] = v0000;
+        m_el[1] = v0000;
+        m_el[2] = v0000;
+#else
+        setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0),
+                 btScalar(0.0), btScalar(0.0), btScalar(0.0),
+                 btScalar(0.0), btScalar(0.0), btScalar(0.0));
+#endif
+    }
 
 
 	static const btMatrix3x3& getIdentity()
 	static const btMatrix3x3& getIdentity()
 	{
 	{

+ 1 - 2
thirdparty/bullet/LinearMath/btMatrixX.h

@@ -346,10 +346,9 @@ struct btMatrixX
 					T dotProd = 0;
 					T dotProd = 0;
 					{
 					{
 						{
 						{
-							int r = rows();
 							int c = cols();
 							int c = cols();
 
 
-							for (int k = 0; k < cols(); k++)
+							for (int k = 0; k < c; k++)
 							{
 							{
 								T w = (*this)(i, k);
 								T w = (*this)(i, k);
 								if (other(k, j) != 0.f)
 								if (other(k, j) != 0.f)

+ 83 - 0
thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h

@@ -0,0 +1,83 @@
+//
+//  btModifiedGramSchmidt.h
+//  LinearMath
+//
+//  Created by Xuchen Han on 4/4/20.
+//
+
+#ifndef btModifiedGramSchmidt_h
+#define btModifiedGramSchmidt_h
+
+#include "btReducedVector.h"
+#include "btAlignedObjectArray.h"
+#include <iostream>
+#include <cmath>
+template<class TV>
+class btModifiedGramSchmidt
+{
+public:
+    btAlignedObjectArray<TV> m_in;
+    btAlignedObjectArray<TV> m_out;
+    
+    btModifiedGramSchmidt(const btAlignedObjectArray<TV>& vecs): m_in(vecs)
+    {
+        m_out.resize(0);
+    }
+    
+    void solve()
+    {
+        m_out.resize(m_in.size());
+        for (int i = 0; i < m_in.size(); ++i)
+        {
+//            printf("========= starting %d ==========\n", i);
+            TV v(m_in[i]);
+//            v.print();
+            for (int j = 0; j < i; ++j)
+            {
+                v = v - v.proj(m_out[j]);
+//                v.print();
+            }
+            v.normalize();
+            m_out[i] = v;
+//            v.print();
+        }
+    }
+    
+    void test()
+    {
+        std::cout << SIMD_EPSILON << std::endl;
+        printf("=======inputs=========\n");
+        for (int i = 0; i < m_out.size(); ++i)
+        {
+            m_in[i].print();
+        }
+        printf("=======output=========\n");
+        for (int i = 0; i < m_out.size(); ++i)
+        {
+            m_out[i].print();
+        }
+        btScalar eps = SIMD_EPSILON;
+        for (int i = 0; i < m_out.size(); ++i)
+        {
+            for (int j = 0; j < m_out.size(); ++j)
+            {
+                if (i == j)
+                {
+                    if (std::abs(1.0-m_out[i].dot(m_out[j])) > eps)// && std::abs(m_out[i].dot(m_out[j])) > eps)
+                    {
+                        printf("vec[%d] is not unit, norm squared = %f\n", i,m_out[i].dot(m_out[j]));
+                    }
+                }
+                else
+                {
+                    if (std::abs(m_out[i].dot(m_out[j])) > eps)
+                    {
+                        printf("vec[%d] and vec[%d] is not orthogonal, dot product = %f\n", i, j, m_out[i].dot(m_out[j]));
+                    }
+                }
+            }
+        }
+    }
+};
+template class btModifiedGramSchmidt<btReducedVector>;
+#endif /* btModifiedGramSchmidt_h */

+ 170 - 0
thirdparty/bullet/LinearMath/btReducedVector.cpp

@@ -0,0 +1,170 @@
+//
+//  btReducedVector.cpp
+//  LinearMath
+//
+//  Created by Xuchen Han on 4/4/20.
+//
+#include <stdio.h>
+#include "btReducedVector.h"
+#include <cmath>
+
+// returns the projection of this onto other
+btReducedVector btReducedVector::proj(const btReducedVector& other) const
+{
+    btReducedVector ret(m_sz);
+    btScalar other_length2 = other.length2();
+    if (other_length2 < SIMD_EPSILON)
+    {
+        return ret;
+    }
+    return other*(this->dot(other))/other_length2;
+}
+
+void btReducedVector::normalize()
+{
+    if (this->length2() < SIMD_EPSILON)
+    {
+        m_indices.clear();
+        m_vecs.clear();
+        return;
+    }
+    *this /= std::sqrt(this->length2());
+}
+
+bool btReducedVector::testAdd() const
+{
+    int sz = 5;
+    btAlignedObjectArray<int> id1;
+    id1.push_back(1);
+    id1.push_back(3);
+    btAlignedObjectArray<btVector3> v1;
+    v1.push_back(btVector3(1,0,1));
+    v1.push_back(btVector3(3,1,5));
+    btAlignedObjectArray<int> id2;
+    id2.push_back(2);
+    id2.push_back(3);
+    id2.push_back(5);
+    btAlignedObjectArray<btVector3> v2;
+    v2.push_back(btVector3(2,3,1));
+    v2.push_back(btVector3(3,4,9));
+    v2.push_back(btVector3(0,4,0));
+    btAlignedObjectArray<int> id3;
+    id3.push_back(1);
+    id3.push_back(2);
+    id3.push_back(3);
+    id3.push_back(5);
+    btAlignedObjectArray<btVector3> v3;
+    v3.push_back(btVector3(1,0,1));
+    v3.push_back(btVector3(2,3,1));
+    v3.push_back(btVector3(6,5,14));
+    v3.push_back(btVector3(0,4,0));
+    btReducedVector rv1(sz, id1, v1);
+    btReducedVector rv2(sz, id2, v2);
+    btReducedVector ans(sz, id3, v3);
+    bool ret = ((ans == rv1+rv2) && (ans == rv2+rv1));
+    if (!ret)
+        printf("btReducedVector testAdd failed\n");
+    return ret;
+}
+
+bool btReducedVector::testMinus() const
+{
+    int sz = 5;
+    btAlignedObjectArray<int> id1;
+    id1.push_back(1);
+    id1.push_back(3);
+    btAlignedObjectArray<btVector3> v1;
+    v1.push_back(btVector3(1,0,1));
+    v1.push_back(btVector3(3,1,5));
+    btAlignedObjectArray<int> id2;
+    id2.push_back(2);
+    id2.push_back(3);
+    id2.push_back(5);
+    btAlignedObjectArray<btVector3> v2;
+    v2.push_back(btVector3(2,3,1));
+    v2.push_back(btVector3(3,4,9));
+    v2.push_back(btVector3(0,4,0));
+    btAlignedObjectArray<int> id3;
+    id3.push_back(1);
+    id3.push_back(2);
+    id3.push_back(3);
+    id3.push_back(5);
+    btAlignedObjectArray<btVector3> v3;
+    v3.push_back(btVector3(-1,-0,-1));
+    v3.push_back(btVector3(2,3,1));
+    v3.push_back(btVector3(0,3,4));
+    v3.push_back(btVector3(0,4,0));
+    btReducedVector rv1(sz, id1, v1);
+    btReducedVector rv2(sz, id2, v2);
+    btReducedVector ans(sz, id3, v3);
+    bool ret = (ans == rv2-rv1);
+    if (!ret)
+        printf("btReducedVector testMinus failed\n");
+    return ret;
+}
+
+bool btReducedVector::testDot() const
+{
+    int sz = 5;
+    btAlignedObjectArray<int> id1;
+    id1.push_back(1);
+    id1.push_back(3);
+    btAlignedObjectArray<btVector3> v1;
+    v1.push_back(btVector3(1,0,1));
+    v1.push_back(btVector3(3,1,5));
+    btAlignedObjectArray<int> id2;
+    id2.push_back(2);
+    id2.push_back(3);
+    id2.push_back(5);
+    btAlignedObjectArray<btVector3> v2;
+    v2.push_back(btVector3(2,3,1));
+    v2.push_back(btVector3(3,4,9));
+    v2.push_back(btVector3(0,4,0));
+    btReducedVector rv1(sz, id1, v1);
+    btReducedVector rv2(sz, id2, v2);
+    btScalar ans = 58;
+    bool ret = (ans == rv2.dot(rv1) && ans == rv1.dot(rv2));
+    ans = 14+16+9+16+81;
+    ret &= (ans==rv2.dot(rv2));
+    
+    if (!ret)
+        printf("btReducedVector testDot failed\n");
+    return ret;
+}
+
+bool btReducedVector::testMultiply() const
+{
+    int sz = 5;
+    btAlignedObjectArray<int> id1;
+    id1.push_back(1);
+    id1.push_back(3);
+    btAlignedObjectArray<btVector3> v1;
+    v1.push_back(btVector3(1,0,1));
+    v1.push_back(btVector3(3,1,5));
+    btScalar s = 2;
+    btReducedVector rv1(sz, id1, v1);
+    btAlignedObjectArray<int> id2;
+    id2.push_back(1);
+    id2.push_back(3);
+    btAlignedObjectArray<btVector3> v2;
+    v2.push_back(btVector3(2,0,2));
+    v2.push_back(btVector3(6,2,10));
+    btReducedVector ans(sz, id2, v2);
+    bool ret = (ans == rv1*s);
+    if (!ret)
+        printf("btReducedVector testMultiply failed\n");
+    return ret;
+}
+
+void btReducedVector::test() const
+{
+    bool ans = testAdd() && testMinus() && testDot() && testMultiply();
+    if (ans)
+    {
+        printf("All tests passed\n");
+    }
+    else
+    {
+        printf("Tests failed\n");
+    }
+}

+ 320 - 0
thirdparty/bullet/LinearMath/btReducedVector.h

@@ -0,0 +1,320 @@
+//
+//  btReducedVectors.h
+//  BulletLinearMath
+//
+//  Created by Xuchen Han on 4/4/20.
+//
+#ifndef btReducedVectors_h
+#define btReducedVectors_h
+#include "btVector3.h"
+#include "btMatrix3x3.h"
+#include "btAlignedObjectArray.h"
+#include <stdio.h>
+#include <vector>
+#include <algorithm>
+struct TwoInts
+{
+    int a,b;
+};
+inline bool operator<(const TwoInts& A, const TwoInts& B)
+{
+    return A.b < B.b;
+}
+
+
+// A helper vector type used for CG projections
+class btReducedVector
+{
+public:
+    btAlignedObjectArray<int> m_indices;
+    btAlignedObjectArray<btVector3> m_vecs;
+    int m_sz; // all m_indices value < m_sz
+public:
+	btReducedVector():m_sz(0)
+	{
+		m_indices.resize(0);
+		m_vecs.resize(0);
+        m_indices.clear();
+        m_vecs.clear();
+	}
+	
+    btReducedVector(int sz): m_sz(sz)
+    {
+        m_indices.resize(0);
+        m_vecs.resize(0);
+        m_indices.clear();
+        m_vecs.clear();
+    }
+    
+    btReducedVector(int sz, const btAlignedObjectArray<int>& indices, const btAlignedObjectArray<btVector3>& vecs): m_sz(sz), m_indices(indices), m_vecs(vecs)
+    {
+    }
+    
+    void simplify()
+    {
+        btAlignedObjectArray<int> old_indices(m_indices);
+        btAlignedObjectArray<btVector3> old_vecs(m_vecs);
+        m_indices.resize(0);
+        m_vecs.resize(0);
+        m_indices.clear();
+        m_vecs.clear();
+        for (int i = 0; i < old_indices.size(); ++i)
+        {
+            if (old_vecs[i].length2() > SIMD_EPSILON)
+            {
+                m_indices.push_back(old_indices[i]);
+                m_vecs.push_back(old_vecs[i]);
+            }
+        }
+    }
+    
+    btReducedVector operator+(const btReducedVector& other)
+    {
+		btReducedVector ret(m_sz);
+		int i=0, j=0;
+		while (i < m_indices.size() && j < other.m_indices.size())
+		{
+			if (m_indices[i] < other.m_indices[j])
+			{
+				ret.m_indices.push_back(m_indices[i]);
+				ret.m_vecs.push_back(m_vecs[i]);
+				++i;
+			}
+			else if (m_indices[i] > other.m_indices[j])
+			{
+				ret.m_indices.push_back(other.m_indices[j]);
+				ret.m_vecs.push_back(other.m_vecs[j]);
+				++j;
+			}
+			else
+			{
+				ret.m_indices.push_back(other.m_indices[j]);
+				ret.m_vecs.push_back(m_vecs[i] + other.m_vecs[j]);
+				++i; ++j;
+			}
+		}
+		while (i < m_indices.size())
+		{
+			ret.m_indices.push_back(m_indices[i]);
+			ret.m_vecs.push_back(m_vecs[i]);
+			++i;
+		}
+		while (j < other.m_indices.size())
+		{
+			ret.m_indices.push_back(other.m_indices[j]);
+			ret.m_vecs.push_back(other.m_vecs[j]);
+			++j;
+		}
+        ret.simplify();
+        return ret;
+    }
+
+    btReducedVector operator-()
+    {
+        btReducedVector ret(m_sz);
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            ret.m_indices.push_back(m_indices[i]);
+            ret.m_vecs.push_back(-m_vecs[i]);
+        }
+        ret.simplify();
+        return ret;
+    }
+    
+    btReducedVector operator-(const btReducedVector& other)
+    {
+		btReducedVector ret(m_sz);
+		int i=0, j=0;
+		while (i < m_indices.size() && j < other.m_indices.size())
+		{
+			if (m_indices[i] < other.m_indices[j])
+			{
+				ret.m_indices.push_back(m_indices[i]);
+				ret.m_vecs.push_back(m_vecs[i]);
+				++i;
+			}
+			else if (m_indices[i] > other.m_indices[j])
+			{
+				ret.m_indices.push_back(other.m_indices[j]);
+				ret.m_vecs.push_back(-other.m_vecs[j]);
+				++j;
+			}
+			else
+			{
+				ret.m_indices.push_back(other.m_indices[j]);
+				ret.m_vecs.push_back(m_vecs[i] - other.m_vecs[j]);
+				++i; ++j;
+			}
+		}
+		while (i < m_indices.size())
+		{
+			ret.m_indices.push_back(m_indices[i]);
+			ret.m_vecs.push_back(m_vecs[i]);
+			++i;
+		}
+		while (j < other.m_indices.size())
+		{
+			ret.m_indices.push_back(other.m_indices[j]);
+			ret.m_vecs.push_back(-other.m_vecs[j]);
+			++j;
+		}
+        ret.simplify();
+		return ret;
+    }
+    
+    bool operator==(const btReducedVector& other) const
+    {
+        if (m_sz != other.m_sz)
+            return false;
+        if (m_indices.size() != other.m_indices.size())
+            return false;
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            if (m_indices[i] != other.m_indices[i] || m_vecs[i] != other.m_vecs[i])
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    bool operator!=(const btReducedVector& other) const
+    {
+        return !(*this == other);
+    }
+	
+	btReducedVector& operator=(const btReducedVector& other)
+	{
+		if (this == &other)
+		{
+			return *this;
+		}
+        m_sz = other.m_sz;
+		m_indices.copyFromArray(other.m_indices);
+		m_vecs.copyFromArray(other.m_vecs);
+		return *this;
+	}
+    
+    btScalar dot(const btReducedVector& other) const
+    {
+        btScalar ret = 0;
+        int j = 0;
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            while (j < other.m_indices.size() && other.m_indices[j] < m_indices[i])
+            {
+                ++j;
+            }
+            if (j < other.m_indices.size() && other.m_indices[j] == m_indices[i])
+            {
+                ret += m_vecs[i].dot(other.m_vecs[j]);
+//                ++j;
+            }
+        }
+        return ret;
+    }
+    
+    btScalar dot(const btAlignedObjectArray<btVector3>& other) const
+    {
+        btScalar ret = 0;
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            ret += m_vecs[i].dot(other[m_indices[i]]);
+        }
+        return ret;
+    }
+    
+    btScalar length2() const
+    {
+        return this->dot(*this);
+    }
+	
+	void normalize();
+    
+    // returns the projection of this onto other
+    btReducedVector proj(const btReducedVector& other) const;
+    
+    bool testAdd() const;
+    
+    bool testMinus() const;
+    
+    bool testDot() const;
+    
+    bool testMultiply() const;
+    
+    void test() const;
+    
+    void print() const
+    {
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            printf("%d: (%f, %f, %f)/", m_indices[i], m_vecs[i][0],m_vecs[i][1],m_vecs[i][2]);
+        }
+        printf("\n");
+    }
+    
+    
+    void sort()
+    {
+        std::vector<TwoInts> tuples;
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            TwoInts ti;
+            ti.a = i;
+            ti.b = m_indices[i];
+            tuples.push_back(ti);
+        }
+        std::sort(tuples.begin(), tuples.end());
+        btAlignedObjectArray<int> new_indices;
+        btAlignedObjectArray<btVector3> new_vecs;
+        for (int i = 0; i < tuples.size(); ++i)
+        {
+            new_indices.push_back(tuples[i].b);
+            new_vecs.push_back(m_vecs[tuples[i].a]);
+        }
+        m_indices = new_indices;
+        m_vecs = new_vecs;
+    }
+};
+
+SIMD_FORCE_INLINE btReducedVector operator*(const btReducedVector& v, btScalar s)
+{
+    btReducedVector ret(v.m_sz);
+    for (int i = 0; i < v.m_indices.size(); ++i)
+    {
+        ret.m_indices.push_back(v.m_indices[i]);
+        ret.m_vecs.push_back(s*v.m_vecs[i]);
+    }
+    ret.simplify();
+    return ret;
+}
+
+SIMD_FORCE_INLINE btReducedVector operator*(btScalar s, const btReducedVector& v)
+{
+    return v*s;
+}
+
+SIMD_FORCE_INLINE btReducedVector operator/(const btReducedVector& v, btScalar s)
+{
+	return v * (1.0/s);
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator/=(btReducedVector& v, btScalar s)
+{
+	v = v/s;
+	return v;
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator+=(btReducedVector& v1, const btReducedVector& v2)
+{
+	v1 = v1+v2;
+	return v1;
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator-=(btReducedVector& v1, const btReducedVector& v2)
+{
+	v1 = v1-v2;
+	return v1;
+}
+
+#endif /* btReducedVectors_h */

+ 1 - 0
thirdparty/bullet/btBulletCollisionAll.cpp

@@ -23,6 +23,7 @@
 #include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp"
 #include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp"
 #include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp"
 #include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp"
 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp"
 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp"
 #include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp"
 #include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp"
 #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp"
 #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp"
 #include "BulletCollision/CollisionDispatch/btCollisionObject.cpp"
 #include "BulletCollision/CollisionDispatch/btCollisionObject.cpp"

+ 1 - 0
thirdparty/bullet/btLinearMathAll.cpp

@@ -8,6 +8,7 @@
 #include "LinearMath/btConvexHullComputer.cpp"
 #include "LinearMath/btConvexHullComputer.cpp"
 #include "LinearMath/btQuickprof.cpp"
 #include "LinearMath/btQuickprof.cpp"
 #include "LinearMath/btThreads.cpp"
 #include "LinearMath/btThreads.cpp"
+#include "LinearMath/btReducedVector.cpp"
 #include "LinearMath/TaskScheduler/btTaskScheduler.cpp"
 #include "LinearMath/TaskScheduler/btTaskScheduler.cpp"
 #include "LinearMath/TaskScheduler/btThreadSupportPosix.cpp"
 #include "LinearMath/TaskScheduler/btThreadSupportPosix.cpp"
 #include "LinearMath/TaskScheduler/btThreadSupportWin32.cpp"
 #include "LinearMath/TaskScheduler/btThreadSupportWin32.cpp"