39 #include "btBulletDynamicsCommon.h"
40 #include "BulletCollision/CollisionDispatch/btGhostObject.h"
41 #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
42 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
43 #include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
44 #include "BulletCollision/BroadphaseCollision/btDispatcher.h"
45 #include "BulletDynamics/Dynamics/btDynamicsWorld.h"
46 #include "LinearMath/btDefaultMotionState.h"
47 #include "LinearMath/btQuaternion.h"
48 #include "LinearMath/btQuickprof.h"
59 const std::vector<tgBulletSpringCableAnchor*>& anchors,
61 double dampingCoefficient,
66 m_ghostObject(ghostObject),
68 m_thickness(thickness),
69 m_resolution(resolution)
80 deleteCollisionShape(shape);
89 for (std::size_t i = 0; i < n; i++)
91 length += (
m_anchors[i]->getWorldPosition() -
m_anchors[i+1]->getWorldPosition()).length();
100 #if (0) // Typically causes contacts to be lost
102 while (numPruned > 0)
104 numPruned = updateAnchorPositions();
120 calculateAndApplyForce(dt);
123 updateCollisionObject();
128 void tgBulletContactSpringCable::calculateAndApplyForce(
double dt)
130 #ifndef BT_NO_PROFILE
131 BT_PROFILE(
"calculateAndApplyForce");
132 #endif //BT_NO_PROFILE
142 if (btFabs(tension) * 1.0 < btFabs(
m_damping))
145 (
m_damping > 0.0 ? tension * 1.0 : -tension * 1.0);
148 const double magnitude = tension +
m_damping;
153 for (std::size_t i = 0; i < n; i++)
155 btVector3 force = btVector3 (0.0, 0.0, 0.0);
158 btVector3 direction =
m_anchors[i + 1]->getWorldPosition() -
m_anchors[i]->getWorldPosition();
159 force = direction.normalize() * magnitude;
164 btVector3 direction =
m_anchors[i]->getWorldPosition() -
m_anchors[i - 1]->getWorldPosition();
165 force = -direction.normalize() * magnitude;
170 btVector3 direction =
m_anchors[i]->getContactNormal();
173 btVector3 back =
m_anchors[i - 1]->getWorldPosition();
174 btVector3 current =
m_anchors[i]->getWorldPosition();
175 btVector3 forward =
m_anchors[i + 1]->getWorldPosition();
178 btVector3 first = (forward - current);
179 btVector3 second = (back - current);
181 btVector3 forceDir = first.normalize() + second.normalize();
184 force = magnitude * forceDir;
189 throw std::runtime_error(
"tgBulletContactSpringCable: First or last anchor is a sliding constraint!!");
196 btVector3 totalForce(0.0, 0.0, 0.0);
198 for (std::size_t i = 0; i < n; i++)
200 btRigidBody* body =
m_anchors[i]->attachedBody;
202 btVector3 contactPoint =
m_anchors[i]->getRelativePosition();
207 btVector3 impulse =
m_anchors[i]->force* dt;
209 body->applyImpulse(impulse, contactPoint);
212 if (!totalForce.fuzzyZero())
214 std::cout <<
"Total Force Error! " << totalForce << std::endl;
215 throw std::runtime_error(
"Total force did not sum to zero!");
219 m_prevLength = currLength;
223 void tgBulletContactSpringCable::updateManifolds()
225 #ifndef BT_NO_PROFILE
226 BT_PROFILE(
"updateManifolds");
227 #endif //BT_NO_PROFILE
231 btManifoldArray m_manifoldArray;
232 btVector3 m_touchingNormal;
237 btBroadphasePairArray& pairArray =
m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray();
238 int numPairs = pairArray.size();
240 std::vector<tgBulletSpringCableAnchor*> rejectedAnchors;
242 for (
int i = 0; i < numPairs; i++)
244 m_manifoldArray.clear();
246 const btBroadphasePair& pair = pairArray[i];
249 btBroadphasePair* collisionPair = m_overlappingPairCache->getOverlappingPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
251 btCollisionObject* obj0 =
static_cast<btCollisionObject*
>(collisionPair->m_pProxy0->m_clientObject);
252 btCollisionObject* obj1 =
static_cast<btCollisionObject*
>(collisionPair->m_pProxy1->m_clientObject);
254 if (collisionPair->m_algorithm)
255 collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
257 for (
int j = 0; j < m_manifoldArray.size(); j++)
259 btPersistentManifold* manifold = m_manifoldArray[j];
260 btScalar directionSign = manifold->getBody0() ==
m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
262 for (
int p=0; p < manifold->getNumContacts(); p++)
264 const btManifoldPoint& pt = manifold->getContactPoint(p);
266 btScalar dist = pt.getDistance();
271 m_touchingNormal = pt.m_normalWorldOnB * directionSign;
273 btVector3 pos = directionSign < 0 ? pt.m_positionWorldOnB : pt.m_positionWorldOnA;
275 btRigidBody* rb = NULL;
281 if (manifold->getBody1() == obj1)
282 rb = btRigidBody::upcast(obj1);
283 else if (manifold->getBody1() == obj0)
284 rb = btRigidBody::upcast(obj0);
287 throw std::runtime_error(
"Can't find the right object!!");
292 if (manifold->getBody0() == obj0)
293 rb = btRigidBody::upcast(obj0);
294 else if (manifold->getBody0() == obj1)
295 rb = btRigidBody::upcast(obj1);
298 throw std::runtime_error(
"Can't find the right object!!");
305 int anchorPos = findNearestPastAnchor(pos);
306 assert(anchorPos < (
int)(
m_anchors.size() - 1));
321 btVector3 lineA = (pos2 - pos);
322 btVector3 lineB = (pos0 - pos);
324 btScalar lengthA = lineA.length();
325 btScalar lengthB = lineB.length();
334 if (lengthB <= m_resolution && rb == backAnchor->attachedBody && mDistB < mDistA)
340 if (lengthA <= m_resolution && rb == forwardAnchor->attachedBody && (!del || mDistA < mDistB))
355 m_newAnchors.push_back(newAnchor);
367 void tgBulletContactSpringCable::updateAnchorList()
369 #ifndef BT_NO_PROFILE
370 BT_PROFILE(
"updateAnchorList");
371 #endif //BT_NO_PROFILE
376 while (m_newAnchors.size() > 0)
380 m_newAnchors.erase(m_newAnchors.begin());
384 int anchorPos = findNearestPastAnchor(pos1);
386 assert(anchorPos < (
int) (
m_anchors.size() - 1));
398 btVector3 lineA = (pos2 - pos1);
399 btVector3 lineB = (pos0 - pos1);
401 btScalar lengthA = lineA.length();
402 btScalar lengthB = lineB.length();
406 btScalar normalValue1 = (lineA).dot(contactNormal);
407 btScalar normalValue2 = (lineB).dot(contactNormal);
417 if (lengthB <= m_resolution && newAnchor->attachedBody == backAnchor->
attachedBody && mDistB < mDistA)
425 if (lengthA <= m_resolution && newAnchor->attachedBody == forwardAnchor->
attachedBody && (!del || mDistA < mDistB))
439 else if(normalValue1 < 0.0 || normalValue2 < 0.0)
447 std::cout <<
"Deleting based on contact normals! " << backNormal.dot(contactNormal);
448 std::cout <<
" " << forwardNormal.dot(contactNormal) << std::endl;
455 m_anchorIt =
m_anchors.begin() + anchorPos + 1;
457 m_anchorIt =
m_anchors.insert(m_anchorIt, newAnchor);
459 #if (1) // Keeps the energy down very well
463 std::cout <<
"Deleting anchor on basis of length " << std::endl;
465 deleteAnchor(anchorPos + 1);
476 std::cout <<
"Prev: " << m_prevLength <<
" LengthDiff " << startLength <<
" " <<
getActualLength();
477 std::cout <<
" Anchors " <<
m_anchors.size() << std::endl;
493 int tgBulletContactSpringCable::updateAnchorPositions()
502 btVector3 back =
m_anchors[i - 1]->getWorldPosition();
503 btVector3 current =
m_anchors[i]->getWorldPosition();
504 btVector3 forward =
m_anchors[i + 1]->getWorldPosition();
506 btVector3 lineA = (forward - current);
507 btVector3 lineB = (back - current);
509 btVector3 contactNormal =
m_anchors[i]->getContactNormal();
514 btVector3 tangentMove = ((contactNormal)(lineA + lineB));
518 btVector3 tangentDir = ( (lineB - lineA).normalize().cross(contactNormal)).normalize();
520 btVector3 tangentMove = (lineB + lineA).dot(tangentDir) * tangentDir;
522 btVector3 newPos = current + tangentMove;
525 if (!keep || !
m_anchors[i]->setWorldPosition(newPos))
548 void tgBulletContactSpringCable::pruneAnchors()
558 btVector3 oldPos =
m_anchors[i]->getWorldPosition();
559 if (!
m_anchors[i]->setWorldPosition(oldPos))
572 btPersistentManifold* m =
m_anchors[i]->getManifold();
573 if (
m_anchors[i]->getManifoldDistance(m).first == INFINITY)
586 std::cout <<
"Pruned off the bat " << numPruned << std::endl;
589 while (numPruned > 0 || passes <= 3)
591 #ifndef BT_NO_PROFILE
592 BT_PROFILE(
"pruneAnchors");
593 #endif //BT_NO_PROFILE
596 numPruned = updateAnchorPositions();
607 btScalar normalValue1;
608 btScalar normalValue2;
612 btVector3 back =
m_anchors[i - 1]->getWorldPosition();
613 btVector3 current =
m_anchors[i]->getWorldPosition();
614 btVector3 forward =
m_anchors[i + 1]->getWorldPosition();
616 btVector3 lineA = (forward - current);
617 btVector3 lineB = (back - current);
619 btVector3 contactNormal =
m_anchors[i]->getContactNormal();
634 normalValue1 = (lineA).dot(contactNormal);
635 normalValue2 = (lineB).dot(contactNormal);
637 if ((normalValue1 < 0.0) || (normalValue2 < 0.0))
640 std::cout <<
"Erased normal: " << normalValue1 <<
" " << normalValue2 <<
" ";
674 for (i = 0; i < n; i++)
676 std::cout <<
m_anchors[i]->getWorldPosition() << std::endl;
683 void tgBulletContactSpringCable::updateCollisionObject()
685 #ifndef BT_NO_PROFILE
686 BT_PROFILE(
"updateCollisionObject");
687 #endif //BT_NO_PROFILE
693 btCompoundShape* m_compoundShape = tgCast::cast<btCollisionShape, btCompoundShape> (
m_ghostObject->getCollisionShape());
694 clearCompoundShape(m_compoundShape);
701 for (std::size_t i = 0; i < n; i++)
703 btVector3 worldPos =
m_anchors[i]->getWorldPosition();
704 for (std::size_t j = 0; j < 3; j++)
706 if (worldPos[j] > maxes[j])
708 maxes[j] = worldPos[j];
710 if (worldPos[j] < mins[j])
712 mins[j] = worldPos[j];
716 btVector3 center = (maxes + mins)/2.0;
721 for (std::size_t i = 0; i < n-1; i++)
723 btVector3 pos1 =
m_anchors[i]->getWorldPosition();
724 btVector3 pos2 =
m_anchors[i+1]->getWorldPosition();
728 t.setOrigin(t.getOrigin() - center);
730 btScalar length = (pos2 - pos1).length() / 2.0;
735 m_compoundShape->addChildShape(t, box);
740 btTransform transform;
741 transform.setOrigin(center);
742 transform.setRotation(btQuaternion::getIdentity());
748 m_overlappingPairCache->getOverlappingPairCache()->cleanProxyFromPairs(
m_ghostObject->getBroadphaseHandle(),m_dispatcher);
751 void tgBulletContactSpringCable::deleteCollisionShape(btCollisionShape* pShape)
753 #ifndef BT_NO_PROFILE
754 BT_PROFILE(
"deleteCollisionShape");
755 #endif //BT_NO_PROFILE
759 btCompoundShape* cShape = tgCast::cast<btCollisionShape, btCompoundShape>(pShape);
762 std::size_t n = cShape->getNumChildShapes();
763 for( std::size_t i = 0; i < n; i++)
765 deleteCollisionShape(cShape->getChildShape(i));
773 void tgBulletContactSpringCable::clearCompoundShape(btCompoundShape* pShape)
775 #ifndef BT_NO_PROFILE
776 BT_PROFILE(
"clearCompoundShape");
777 #endif //BT_NO_PROFILE
781 while (pShape->getNumChildShapes() > 0)
783 btCollisionShape* pCShape = pShape->getChildShape(0);
784 deleteCollisionShape(pCShape);
785 pShape->removeChildShapeByIndex(0);
791 bool tgBulletContactSpringCable::deleteAnchor(
int i)
793 #ifndef BT_NO_PROFILE
794 BT_PROFILE(
"deleteAnchor");
795 #endif //BT_NO_PROFILE
810 int tgBulletContactSpringCable::findNearestPastAnchor(btVector3& pos)
820 btScalar startDist = (pos -
m_anchors[i]->getWorldPosition()).length();
821 btScalar dist = startDist;
823 while (dist <= startDist && i < n)
826 btVector3 anchorPos =
m_anchors[i]->getWorldPosition();
827 dist = (pos - anchorPos).length();
828 if (dist < startDist)
835 if (dist > startDist)
855 tgBulletContactSpringCable::anchorCompare m_acTemp(a0, an);
857 btVector3 current =
m_anchors[i]->getWorldPosition();
859 m_acTemp.comparePoints(pos, current) ? i-- : i+=0;
869 tgBulletContactSpringCable::anchorCompare m_acTemp(a0, an);
870 if( m_acTemp.comparePoints(current, pos))
878 btScalar endDist = (pos -
m_anchors[n]->getWorldPosition()).length();
879 btScalar dist2 = endDist;
883 while (dist2 <= endDist && j > 0)
886 btVector3 anchorPos =
m_anchors[j]->getWorldPosition();
887 dist2 = (pos - anchorPos).length();
909 tgBulletContactSpringCable::anchorCompare m_acTemp(a0, an);
911 btVector3 current =
m_anchors[j]->getWorldPosition();
913 m_acTemp.comparePoints(pos, current) ? j-- : j+=0;
924 tgBulletContactSpringCable::anchorCompare m_acTemp(a0, an);
925 if( m_acTemp.comparePoints(current, pos))
934 std::cout <<
"Error in iteration order First try: " << i <<
" Second Try: " << j << std::endl;
962 return comparePoints(pt2, pt3);
965 bool tgBulletContactSpringCable::anchorCompare::comparePoints(btVector3& pt2, btVector3& pt3)
const
968 btVector3 pt1 = ma1->getWorldPosition();
969 btVector3 ptN = ma2->getWorldPosition();
971 btScalar lhDot = (ptN - pt1).dot(pt2);
972 btScalar rhDot = (ptN - pt1).dot(pt3);
974 return lhDot < rhDot;
978 bool tgBulletContactSpringCable::invariant(
void)
const
982 m_prevLength >= 0.0 &&
990 m_newAnchors.size() == 0);
Contains the definition of class tgWorldBulletPhysicsImpl.
static btDynamicsWorld & worldToDynamicsWorld(const tgWorld &world)
Utility class for class casting and filtering collections by type.
const double m_dampingCoefficient
btPersistentManifold * getManifold() const
virtual btVector3 getWorldPosition() const
tgBulletSpringCableAnchor *const anchor2
btRigidBody *const attachedBody
virtual const double getTension() const
std::vector< tgBulletSpringCableAnchor * > m_anchors
static btTransform getTransform(const btVector3 &startOrientation, const btVector3 &start, const btVector3 &end)
Contains the definition of class tgWorld $Id$.
Contains the definition of class tgBulletUtil.
bool updateManifold(btPersistentManifold *m)
Definitions of class tgBulletSpringCableAnchor, formerly muscleAnchor.
std::pair< btScalar, btVector3 > getManifoldDistance(btPersistentManifold *m) const
Contains the definition of class tgUtil and overloaded operator<<() free functions.
virtual btVector3 getContactNormal() const
tgBulletSpringCableAnchor *const anchor1