Changeset 2882 for code/trunk/src/bullet
- Timestamp:
- Mar 31, 2009, 8:05:51 PM (16 years ago)
- Location:
- code/trunk/src/bullet
- Files:
-
- 1 added
- 110 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
r2662 r2882 20 20 #include "btAxisSweep3.h" 21 21 22 #include <assert.h>23 22 24 23 btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator) -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
r2662 r2882 43 43 public: 44 44 45 BT_DECLARE_ALIGNED_ALLOCATOR(); 45 46 46 47 class Edge … … 139 140 SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} 140 141 141 v oid resetPool();142 virtual void resetPool(btDispatcher* dispatcher); 142 143 143 144 void processAllOverlappingPairs(btOverlapCallback* callback); … … 221 222 222 223 if (checkCardinality) 223 assert(numEdges == m_numHandles*2+1);224 btAssert(numEdges == m_numHandles*2+1); 224 225 } 225 226 #endif //DEBUG_BROADPHASE … … 347 348 } 348 349 349 // assert(bounds.HasVolume());350 //btAssert(bounds.HasVolume()); 350 351 351 352 // init bounds … … 453 454 BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle() 454 455 { 455 assert(m_firstFreeHandle);456 btAssert(m_firstFreeHandle); 456 457 457 458 BP_FP_INT_TYPE handle = m_firstFreeHandle; … … 465 466 void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle) 466 467 { 467 assert(handle > 0 && handle < m_maxHandles);468 btAssert(handle > 0 && handle < m_maxHandles); 468 469 469 470 getHandle(handle)->SetNextFree(m_firstFreeHandle); … … 588 589 589 590 template <typename BP_FP_INT_TYPE> 590 void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool( )591 void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* dispatcher) 591 592 { 592 593 if (m_numHandles == 0) … … 642 643 if (!isDuplicate) 643 644 { 645 ///important to use an AABB test that is consistent with the broadphase 644 646 bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); 645 647 … … 687 689 } 688 690 689 690 691 692 693 691 } 694 692 … … 731 729 void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) 732 730 { 733 // assert(bounds.IsFinite());734 // assert(bounds.HasVolume());731 // btAssert(bounds.IsFinite()); 732 //btAssert(bounds.HasVolume()); 735 733 736 734 Handle* pHandle = getHandle(handle); -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
r2662 r2882 65 65 virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0; 66 66 67 ///reset broadphase internal structures, to ensure determinism/reproducability 68 virtual void resetPool(btDispatcher* dispatcher) {}; 69 67 70 virtual void printStats() = 0; 68 71 -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
r2662 r2882 70 70 71 71 SOFTBODY_SHAPE_PROXYTYPE, 72 72 HFFLUID_SHAPE_PROXYTYPE, 73 HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE, 73 74 INVALID_SHAPE_PROXYTYPE, 74 75 … … 188 189 189 190 //keep them sorted, so the std::set operations work 190 if ( &proxy0 < &proxy1)191 if (proxy0.m_uniqueId < proxy1.m_uniqueId) 191 192 { 192 193 m_pProxy0 = &proxy0; … … 229 230 bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) 230 231 { 231 return a.m_pProxy0 > b.m_pProxy0 || 232 (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 > b.m_pProxy1) || 232 const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1; 233 const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1; 234 const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1; 235 const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1; 236 237 return uidA0 > uidB0 || 238 (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) || 233 239 (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); 234 240 } -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
r2662 r2882 394 394 } 395 395 396 // 396 #if 0 397 397 static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count) 398 398 { … … 400 400 return(n); 401 401 } 402 #endif 402 403 403 404 // … … 424 425 void btDbvt::clear() 425 426 { 426 if(m_root) recursedeletenode(this,m_root); 427 if(m_root) 428 recursedeletenode(this,m_root); 427 429 btAlignedFree(m_free); 428 430 m_free=0; 431 m_lkhd = -1; 432 m_stkStack.clear(); 433 m_opath = 0; 434 429 435 } 430 436 -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
r2662 r2882 58 58 59 59 //SSE gives errors on a MSVC 7.1 60 #if (defined (WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))60 #ifdef BT_USE_SSE 61 61 #define DBVT_SELECT_IMPL DBVT_IMPL_SSE 62 62 #define DBVT_MERGE_IMPL DBVT_IMPL_SSE … … 83 83 #define DBVT_PREFIX template <typename T> 84 84 #define DBVT_IPOLICY T& policy 85 #define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*) 0;85 #define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker; 86 86 #else 87 87 #define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} … … 147 147 DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, 148 148 const btDbvtAabbMm& b); 149 DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, 150 const btDbvtAabbMm& b, 151 const btTransform& xform); 149 152 150 DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, 153 151 const btVector3& b); … … 305 303 const btDbvtNode* root1, 306 304 DBVT_IPOLICY); 307 305 #if 0 308 306 DBVT_PREFIX 309 307 void collideTT( const btDbvtNode* root0, … … 317 315 const btTransform& xform1, 318 316 DBVT_IPOLICY); 317 #endif 318 319 319 DBVT_PREFIX 320 320 void collideTV( const btDbvtNode* root, … … 531 531 } 532 532 533 // 534 DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, 535 const btDbvtAabbMm& b, 536 const btTransform& xform) 537 { 538 const btVector3 d0=xform*b.Center()-a.Center(); 539 const btVector3 d1=d0*xform.getBasis(); 540 btScalar s0[2]={0,0}; 541 btScalar s1[2]={dot(xform.getOrigin(),d0),s1[0]}; 542 a.AddSpan(d0,s0[0],s0[1]); 543 b.AddSpan(d1,s1[0],s1[1]); 544 if(s0[0]>(s1[1])) return(false); 545 if(s0[1]<(s1[0])) return(false); 546 return(true); 547 } 533 548 534 549 535 // … … 849 835 } 850 836 851 837 #if 0 852 838 // 853 839 DBVT_PREFIX … … 905 891 } 906 892 } 907 908 893 // 909 894 DBVT_PREFIX … … 917 902 collideTT(root0,root1,xform,policy); 918 903 } 904 #endif 919 905 920 906 // -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
r2662 r2882 101 101 btDbvtProxy* pb=(btDbvtProxy*)nb->data; 102 102 #if DBVT_BP_SORTPAIRS 103 if(pa>pb) btSwap(pa,pb); 103 if(pa->m_uniqueId>pb->m_uniqueId) 104 btSwap(pa,pb); 104 105 #endif 105 106 pbp->m_paircache->addOverlappingPair(pa,pb); … … 133 134 m_updates_done = 0; 134 135 m_updates_ratio = 0; 135 m_paircache = paircache? 136 paircache : 137 new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); 136 m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); 138 137 m_gid = 0; 139 138 m_pid = 0; … … 211 210 } 212 211 212 struct BroadphaseRayTester : btDbvt::ICollide 213 { 214 btBroadphaseRayCallback& m_rayCallback; 215 BroadphaseRayTester(btBroadphaseRayCallback& orgCallback) 216 :m_rayCallback(orgCallback) 217 { 218 } 219 void Process(const btDbvtNode* leaf) 220 { 221 btDbvtProxy* proxy=(btDbvtProxy*)leaf->data; 222 m_rayCallback.process(proxy); 223 } 224 }; 225 213 226 void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) 214 227 { 215 216 struct BroadphaseRayTester : btDbvt::ICollide217 {218 btBroadphaseRayCallback& m_rayCallback;219 BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)220 :m_rayCallback(orgCallback)221 {222 }223 void Process(const btDbvtNode* leaf)224 {225 btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;226 m_rayCallback.process(proxy);227 }228 };229 230 228 BroadphaseRayTester callback(rayCallback); 231 229 … … 342 340 } 343 341 #endif 342 343 performDeferredRemoval(dispatcher); 344 345 } 346 347 void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher) 348 { 349 350 if (m_paircache->hasDeferredRemoval()) 351 { 352 353 btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray(); 354 355 //perform a sort, to find duplicates and to sort 'invalid' pairs to the end 356 overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); 357 358 int invalidPair = 0; 359 360 361 int i; 362 363 btBroadphasePair previousPair; 364 previousPair.m_pProxy0 = 0; 365 previousPair.m_pProxy1 = 0; 366 previousPair.m_algorithm = 0; 367 368 369 for (i=0;i<overlappingPairArray.size();i++) 370 { 371 372 btBroadphasePair& pair = overlappingPairArray[i]; 373 374 bool isDuplicate = (pair == previousPair); 375 376 previousPair = pair; 377 378 bool needsRemoval = false; 379 380 if (!isDuplicate) 381 { 382 //important to perform AABB check that is consistent with the broadphase 383 btDbvtProxy* pa=(btDbvtProxy*)pair.m_pProxy0; 384 btDbvtProxy* pb=(btDbvtProxy*)pair.m_pProxy1; 385 bool hasOverlap = Intersect(pa->leaf->volume,pb->leaf->volume); 386 387 if (hasOverlap) 388 { 389 needsRemoval = false; 390 } else 391 { 392 needsRemoval = true; 393 } 394 } else 395 { 396 //remove duplicate 397 needsRemoval = true; 398 //should have no algorithm 399 btAssert(!pair.m_algorithm); 400 } 401 402 if (needsRemoval) 403 { 404 m_paircache->cleanOverlappingPair(pair,dispatcher); 405 406 pair.m_pProxy0 = 0; 407 pair.m_pProxy1 = 0; 408 invalidPair++; 409 } 410 411 } 412 413 //perform a sort, to sort 'invalid' pairs to the end 414 overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); 415 overlappingPairArray.resize(overlappingPairArray.size() - invalidPair); 416 } 344 417 } 345 418 … … 347 420 void btDbvtBroadphase::collide(btDispatcher* dispatcher) 348 421 { 422 /*printf("---------------------------------------------------------\n"); 423 printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves); 424 printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves); 425 printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs()); 426 { 427 int i; 428 for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++) 429 { 430 printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(), 431 getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid()); 432 } 433 printf("\n"); 434 } 435 */ 436 437 438 349 439 SPC(m_profiling.m_total); 350 440 /* optimize */ … … 402 492 if(pairs.size()>0) 403 493 { 404 const int ci=pairs.size(); 405 int ni=btMin( ci,btMax<int>(m_newpairs,(ci*m_cupdates)/100));494 495 int ni=btMin(pairs.size(),btMax<int>(m_newpairs,(pairs.size()*m_cupdates)/100)); 406 496 for(int i=0;i<ni;++i) 407 497 { 408 btBroadphasePair& p=pairs[(m_cid+i)% ci];498 btBroadphasePair& p=pairs[(m_cid+i)%pairs.size()]; 409 499 btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0; 410 500 btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1; … … 412 502 { 413 503 #if DBVT_BP_SORTPAIRS 414 if(pa>pb) btSwap(pa,pb); 504 if(pa->m_uniqueId>pb->m_uniqueId) 505 btSwap(pa,pb); 415 506 #endif 416 507 m_paircache->removeOverlappingPair(pa,pb,dispatcher); … … 467 558 aabbMin=bounds.Mins(); 468 559 aabbMax=bounds.Maxs(); 560 } 561 562 void btDbvtBroadphase::resetPool(btDispatcher* dispatcher) 563 { 564 565 int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves; 566 if (!totalObjects) 567 { 568 //reset internal dynamic tree data structures 569 m_sets[0].clear(); 570 m_sets[1].clear(); 571 572 m_deferedcollide = false; 573 m_needcleanup = true; 574 m_prediction = 1/(btScalar)2; 575 m_stageCurrent = 0; 576 m_fixedleft = 0; 577 m_fupdates = 1; 578 m_dupdates = 0; 579 m_cupdates = 10; 580 m_newpairs = 1; 581 m_updates_call = 0; 582 m_updates_done = 0; 583 m_updates_ratio = 0; 584 585 m_gid = 0; 586 m_pid = 0; 587 m_cid = 0; 588 for(int i=0;i<=STAGECOUNT;++i) 589 { 590 m_stageRoots[i]=0; 591 } 592 } 469 593 } 470 594 … … 601 725 #undef SPC 602 726 #endif 727 -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
r2662 r2882 25 25 26 26 #define DBVT_BP_PROFILE 0 27 #define DBVT_BP_SORTPAIRS 127 //#define DBVT_BP_SORTPAIRS 1 28 28 #define DBVT_BP_PREVENTFALSEUPDATE 0 29 29 #define DBVT_BP_ACCURATESLEEPING 0 … … 115 115 void printStats(); 116 116 static void benchmark(btBroadphaseInterface*); 117 118 119 void performDeferredRemoval(btDispatcher* dispatcher); 120 121 ///reset broadphase internal structures, to ensure determinism/reproducability 122 virtual void resetPool(btDispatcher* dispatcher); 123 117 124 }; 118 125 -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
r2662 r2882 483 483 484 484 } 485 486 void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher) 487 { 488 // not yet 489 } -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
r2662 r2882 144 144 void quicksort (btBroadphasePairArray& a, int lo, int hi); 145 145 146 ///reset broadphase internal structures, to ensure determinism/reproducability 147 virtual void resetPool(btDispatcher* dispatcher); 148 146 149 }; 147 150 -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
r2662 r2882 20 20 #include "btDispatcher.h" 21 21 #include "btCollisionAlgorithm.h" 22 #include "LinearMath/btAabbUtil2.h" 22 23 23 24 #include <stdio.h> … … 136 137 { 137 138 gFindPairs++; 138 if(proxy0>proxy1) btSwap(proxy0,proxy1); 139 if(proxy0->m_uniqueId>proxy1->m_uniqueId) 140 btSwap(proxy0,proxy1); 139 141 int proxyId1 = proxy0->getUid(); 140 142 int proxyId2 = proxy1->getUid(); … … 212 214 btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) 213 215 { 214 if(proxy0>proxy1) btSwap(proxy0,proxy1); 216 if(proxy0->m_uniqueId>proxy1->m_uniqueId) 217 btSwap(proxy0,proxy1); 215 218 int proxyId1 = proxy0->getUid(); 216 219 int proxyId2 = proxy1->getUid(); … … 271 274 { 272 275 gRemovePairs++; 273 if(proxy0>proxy1) btSwap(proxy0,proxy1); 276 if(proxy0->m_uniqueId>proxy1->m_uniqueId) 277 btSwap(proxy0,proxy1); 274 278 int proxyId1 = proxy0->getUid(); 275 279 int proxyId2 = proxy1->getUid(); … … 393 397 } 394 398 399 void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) 400 { 401 ///need to keep hashmap in sync with pair address, so rebuild all 402 btBroadphasePairArray tmpPairs; 403 int i; 404 for (i=0;i<m_overlappingPairArray.size();i++) 405 { 406 tmpPairs.push_back(m_overlappingPairArray[i]); 407 } 408 409 for (i=0;i<tmpPairs.size();i++) 410 { 411 removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher); 412 } 413 414 for (i = 0; i < m_next.size(); i++) 415 { 416 m_next[i] = BT_NULL_PAIR; 417 } 418 419 tmpPairs.quickSort(btBroadphasePairSortPredicate()); 420 421 for (i=0;i<tmpPairs.size();i++) 422 { 423 addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1); 424 } 425 426 427 } 395 428 396 429 … … 430 463 { 431 464 //don't add overlap with own 432 assert(proxy0 != proxy1);465 btAssert(proxy0 != proxy1); 433 466 434 467 if (!needsBroadphaseCollision(proxy0,proxy1)) … … 461 494 if (findIndex < m_overlappingPairArray.size()) 462 495 { 463 // assert(it != m_overlappingPairSet.end());496 //btAssert(it != m_overlappingPairSet.end()); 464 497 btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; 465 498 return pair; … … 491 524 { 492 525 cleanOverlappingPair(*pair,dispatcher); 493 494 m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1); 526 pair->m_pProxy0 = 0; 527 pair->m_pProxy1 = 0; 528 m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); 495 529 m_overlappingPairArray.pop_back(); 496 530 gOverlappingPairs--; … … 592 626 processAllOverlappingPairs(&removeCallback,dispatcher); 593 627 } 628 629 void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) 630 { 631 //should already be sorted 632 } 633 -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
r2662 r2882 84 84 85 85 virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0; 86 87 virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0; 88 86 89 87 90 }; … … 260 263 } 261 264 262 public: 265 virtual void sortOverlappingPairs(btDispatcher* dispatcher); 266 267 268 protected: 263 269 264 270 btAlignedObjectArray<int> m_hashTable; … … 370 376 } 371 377 378 virtual void sortOverlappingPairs(btDispatcher* dispatcher); 379 372 380 373 381 }; … … 448 456 } 449 457 458 virtual void sortOverlappingPairs(btDispatcher* dispatcher) 459 { 460 } 450 461 451 462 -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
r2662 r2882 470 470 471 471 #ifdef RAYAABB2 472 btVector3 rayFrom = raySource;473 472 btVector3 rayDir = (rayTarget-raySource); 474 473 rayDir.normalize (); … … 559 558 560 559 #ifdef RAYAABB2 561 btVector3 rayFrom = raySource;562 560 btVector3 rayDirection = (rayTarget-raySource); 563 561 rayDirection.normalize (); … … 818 816 #include <new> 819 817 818 #if 0 820 819 //PCK: consts 821 820 static const unsigned BVH_ALIGNMENT = 16; … … 823 822 824 823 static const unsigned BVH_ALIGNMENT_BLOCKS = 2; 825 824 #endif 826 825 827 826 … … 1147 1146 1148 1147 1148 -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
r2662 r2882 325 325 } 326 326 327 328 327 void btSimpleBroadphase::resetPool(btDispatcher* dispatcher) 328 { 329 //not yet 330 } -
code/trunk/src/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
r2662 r2882 109 109 } 110 110 111 ///reset broadphase internal structures, to ensure determinism/reproducability 112 virtual void resetPool(btDispatcher* dispatcher); 113 111 114 112 115 void validate(); -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
r2662 r2882 53 53 { 54 54 m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j); 55 assert(m_doubleDispatch[i][j]);55 btAssert(m_doubleDispatch[i][j]); 56 56 } 57 57 } … … 80 80 btCollisionObject* body1 = (btCollisionObject*)b1; 81 81 82 btScalar contactBreakingThreshold = btMin(gContactBreakingThreshold,btMin(body0->getCollisionShape()->getContactBreakingThreshold(),body1->getCollisionShape()->getContactBreakingThreshold())); 83 82 //test for Bullet 2.74: use a relative contact breaking threshold without clamping against 'gContactBreakingThreshold' 83 //btScalar contactBreakingThreshold = btMin(gContactBreakingThreshold,btMin(body0->getCollisionShape()->getContactBreakingThreshold(),body1->getCollisionShape()->getContactBreakingThreshold())); 84 btScalar contactBreakingThreshold = btMin(body0->getCollisionShape()->getContactBreakingThreshold(),body1->getCollisionShape()->getContactBreakingThreshold()); 85 86 btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold()); 87 84 88 void* mem = 0; 85 89 … … 92 96 93 97 } 94 btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold );98 btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold); 95 99 manifold->m_index1a = m_manifoldsPtr.size(); 96 100 m_manifoldsPtr.push_back(manifold); … … 143 147 return algo; 144 148 } 145 146 149 147 150 … … 161 164 bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1) 162 165 { 163 assert(body0);164 assert(body1);166 btAssert(body0); 167 btAssert(body1); 165 168 166 169 bool needsCollision = true; -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
r2662 r2882 18 18 19 19 btCollisionObject::btCollisionObject() 20 : m_broadphaseHandle(0), 20 : m_anisotropicFriction(1.f,1.f,1.f), 21 m_hasAnisotropicFriction(false), 22 m_contactProcessingThreshold(1e30f), 23 m_broadphaseHandle(0), 21 24 m_collisionShape(0), 22 25 m_rootCollisionShape(0), -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
r2662 r2882 53 53 btVector3 m_interpolationLinearVelocity; 54 54 btVector3 m_interpolationAngularVelocity; 55 56 btVector3 m_anisotropicFriction; 57 bool m_hasAnisotropicFriction; 58 btScalar m_contactProcessingThreshold; 59 55 60 btBroadphaseProxy* m_broadphaseHandle; 56 61 btCollisionShape* m_collisionShape; … … 115 120 CO_COLLISION_OBJECT =1, 116 121 CO_RIGID_BODY, 117 CO_SOFT_BODY,118 122 ///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter 119 123 ///It is useful for collision sensors, explosion objects, character controller etc. 120 CO_GHOST_OBJECT 124 CO_GHOST_OBJECT, 125 CO_SOFT_BODY, 126 CO_HF_FLUID 121 127 }; 122 128 … … 127 133 } 128 134 135 const btVector3& getAnisotropicFriction() const 136 { 137 return m_anisotropicFriction; 138 } 139 void setAnisotropicFriction(const btVector3& anisotropicFriction) 140 { 141 m_anisotropicFriction = anisotropicFriction; 142 m_hasAnisotropicFriction = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f); 143 } 144 bool hasAnisotropicFriction() const 145 { 146 return m_hasAnisotropicFriction; 147 } 148 149 ///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default. 150 ///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges 151 void setContactProcessingThreshold( btScalar contactProcessingThreshold) 152 { 153 m_contactProcessingThreshold = contactProcessingThreshold; 154 } 155 btScalar getContactProcessingThreshold() const 156 { 157 return m_contactProcessingThreshold; 158 } 129 159 130 160 SIMD_FORCE_INLINE bool isStaticObject() const { -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
r2662 r2882 70 70 getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); 71 71 getBroadphase()->destroyProxy(bp,m_dispatcher1); 72 collisionObject->setBroadphaseHandle(0); 72 73 } 73 74 } … … 119 120 120 121 122 void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj) 123 { 124 btVector3 minAabb,maxAabb; 125 colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); 126 //need to increase the aabb for contact thresholds 127 btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); 128 minAabb -= contactThreshold; 129 maxAabb += contactThreshold; 130 131 btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; 132 133 //moving objects should be moderately sized, probably something wrong if not 134 if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) 135 { 136 bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); 137 } else 138 { 139 //something went wrong, investigate 140 //this assert is unwanted in 3D modelers (danger of loosing work) 141 colObj->setActivationState(DISABLE_SIMULATION); 142 143 static bool reportMe = true; 144 if (reportMe && m_debugDrawer) 145 { 146 reportMe = false; 147 m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); 148 m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); 149 m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); 150 m_debugDrawer->reportErrorWarning("Thanks.\n"); 151 } 152 } 153 } 154 121 155 void btCollisionWorld::updateAabbs() 122 156 { … … 131 165 if (colObj->isActive()) 132 166 { 133 btVector3 minAabb,maxAabb; 134 colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); 135 //need to increase the aabb for contact thresholds 136 btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); 137 minAabb -= contactThreshold; 138 maxAabb += contactThreshold; 139 140 btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; 141 142 //moving objects should be moderately sized, probably something wrong if not 143 if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) 144 { 145 bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); 146 } else 147 { 148 //something went wrong, investigate 149 //this assert is unwanted in 3D modelers (danger of loosing work) 150 colObj->setActivationState(DISABLE_SIMULATION); 151 152 static bool reportMe = true; 153 if (reportMe && m_debugDrawer) 154 { 155 reportMe = false; 156 m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); 157 m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); 158 m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); 159 m_debugDrawer->reportErrorWarning("Thanks.\n"); 160 } 161 } 162 } 163 } 164 167 updateSingleAabb(colObj); 168 } 169 } 165 170 } 166 171 … … 294 299 BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, 295 300 btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): 296 btTriangleRaycastCallback(from,to), 301 //@BP Mod 302 btTriangleRaycastCallback(from,to, resultCallback->m_flags), 297 303 m_resultCallback(resultCallback), 298 304 m_collisionObject(collisionObject), … … 343 349 BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, 344 350 btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh): 345 btTriangleRaycastCallback(from,to), 351 //@BP Mod 352 btTriangleRaycastCallback(from,to, resultCallback->m_flags), 346 353 m_resultCallback(resultCallback), 347 354 m_collisionObject(collisionObject), … … 664 671 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); 665 672 //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; 666 673 #if 0 667 674 #ifdef RECALCULATE_AABB 668 675 btVector3 collisionObjectAabbMin,collisionObjectAabbMax; … … 672 679 const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; 673 680 const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; 681 #endif 674 682 #endif 675 683 //btScalar hitLambda = m_resultCallback.m_closestHitFraction; -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
r2877 r2882 139 139 } 140 140 141 void updateSingleAabb(btCollisionObject* colObj); 142 141 143 virtual void updateAabbs(); 142 143 144 144 145 … … 193 194 short int m_collisionFilterGroup; 194 195 short int m_collisionFilterMask; 196 //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback 197 unsigned int m_flags; 195 198 196 199 virtual ~RayResultCallback() … … 206 209 m_collisionObject(0), 207 210 m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), 208 m_collisionFilterMask(btBroadphaseProxy::AllFilter) 211 m_collisionFilterMask(btBroadphaseProxy::AllFilter), 212 //@BP Mod 213 m_flags(0) 209 214 { 210 215 } -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
r2662 r2882 20 20 #include "LinearMath/btIDebugDraw.h" 21 21 #include "LinearMath/btAabbUtil2.h" 22 #include "btManifoldResult.h" 22 23 23 24 btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) … … 29 30 30 31 btCollisionObject* colObj = m_isSwapped? body1 : body0; 32 btAssert (colObj->getCollisionShape()->isCompound()); 33 34 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); 35 m_compoundShapeRevision = compoundShape->getUpdateRevision(); 36 37 preallocateChildAlgorithms(body0,body1); 38 } 39 40 void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1) 41 { 42 btCollisionObject* colObj = m_isSwapped? body1 : body0; 31 43 btCollisionObject* otherObj = m_isSwapped? body0 : body1; 32 assert (colObj->getCollisionShape()->isCompound());44 btAssert (colObj->getCollisionShape()->isCompound()); 33 45 34 46 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); 47 35 48 int numChildren = compoundShape->getNumChildShapes(); 36 49 int i; … … 47 60 btCollisionShape* childShape = compoundShape->getChildShape(i); 48 61 colObj->internalSetTemporaryCollisionShape( childShape ); 49 m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold);62 m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold); 50 63 colObj->internalSetTemporaryCollisionShape( tmpShape ); 51 64 } … … 53 66 } 54 67 55 56 btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() 68 void btCompoundCollisionAlgorithm::removeChildAlgorithms() 57 69 { 58 70 int numChildren = m_childCollisionAlgorithms.size(); … … 66 78 } 67 79 } 80 } 81 82 btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() 83 { 84 removeChildAlgorithms(); 68 85 } 69 86 … … 168 185 btCollisionObject* otherObj = m_isSwapped? body0 : body1; 169 186 170 assert (colObj->getCollisionShape()->isCompound()); 187 188 189 btAssert (colObj->getCollisionShape()->isCompound()); 171 190 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); 191 192 ///btCompoundShape might have changed: 193 ////make sure the internal child collision algorithm caches are still valid 194 if (compoundShape->getUpdateRevision() != m_compoundShapeRevision) 195 { 196 ///clear and update all 197 removeChildAlgorithms(); 198 199 preallocateChildAlgorithms(body0,body1); 200 } 201 172 202 173 203 btDbvt* tree = compoundShape->getDynamicAabbTree(); … … 175 205 btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold); 176 206 207 ///we need to refresh all contact manifolds 208 ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep 209 ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm 210 { 211 int i; 212 btManifoldArray manifoldArray; 213 for (i=0;i<m_childCollisionAlgorithms.size();i++) 214 { 215 if (m_childCollisionAlgorithms[i]) 216 { 217 m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray); 218 for (int m=0;m<manifoldArray.size();m++) 219 { 220 if (manifoldArray[m]->getNumContacts()) 221 { 222 resultOut->setPersistentManifold(manifoldArray[m]); 223 resultOut->refreshContactPoints(); 224 resultOut->setPersistentManifold(0);//??necessary? 225 } 226 } 227 manifoldArray.clear(); 228 } 229 } 230 } 177 231 178 232 if (tree) … … 243 297 btCollisionObject* otherObj = m_isSwapped? body0 : body1; 244 298 245 assert (colObj->getCollisionShape()->isCompound());299 btAssert (colObj->getCollisionShape()->isCompound()); 246 300 247 301 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); … … 286 340 287 341 342 -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
r2662 r2882 27 27 #include "LinearMath/btAlignedObjectArray.h" 28 28 class btDispatcher; 29 class btCollisionObject; 29 30 30 31 /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes … … 36 37 class btPersistentManifold* m_sharedManifold; 37 38 bool m_ownsManifold; 39 40 int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated 38 41 42 void removeChildAlgorithms(); 43 44 void preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1); 45 39 46 public: 40 47 -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
r2662 r2882 52 52 btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) 53 53 { 54 m_numPerturbationIterations = 0; 55 m_minimumPointsPerturbationThreshold = 3; 54 56 m_simplexSolver = simplexSolver; 55 57 m_pdSolver = pdSolver; … … 60 62 } 61 63 62 btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver )64 btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) 63 65 : btActivatingCollisionAlgorithm(ci,body0,body1), 64 66 m_simplexSolver(simplexSolver), … … 66 68 m_ownManifold (false), 67 69 m_manifoldPtr(mf), 68 m_lowLevelOfDetail(false) 70 m_lowLevelOfDetail(false), 69 71 #ifdef USE_SEPDISTANCE_UTIL2 70 72 ,m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(), 71 (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()) 73 (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()), 72 74 #endif 75 m_numPerturbationIterations(numPerturbationIterations), 76 m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) 73 77 { 74 78 (void)body0; … … 94 98 95 99 96 97 100 struct btPerturbedContactResult : public btManifoldResult 101 { 102 btManifoldResult* m_originalManifoldResult; 103 btTransform m_transformA; 104 btTransform m_transformB; 105 btTransform m_unPerturbedTransform; 106 bool m_perturbA; 107 btIDebugDraw* m_debugDrawer; 108 109 110 btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer) 111 :m_originalManifoldResult(originalResult), 112 m_transformA(transformA), 113 m_transformB(transformB), 114 m_perturbA(perturbA), 115 m_unPerturbedTransform(unPerturbedTransform), 116 m_debugDrawer(debugDrawer) 117 { 118 } 119 virtual ~ btPerturbedContactResult() 120 { 121 } 122 123 virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth) 124 { 125 btVector3 endPt,startPt; 126 btScalar newDepth; 127 btVector3 newNormal; 128 129 if (m_perturbA) 130 { 131 btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth; 132 endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg); 133 newDepth = (endPt - pointInWorld).dot(normalOnBInWorld); 134 startPt = endPt+normalOnBInWorld*newDepth; 135 } else 136 { 137 endPt = pointInWorld + normalOnBInWorld*orgDepth; 138 startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld); 139 newDepth = (endPt - startPt).dot(normalOnBInWorld); 140 141 } 142 143 //#define DEBUG_CONTACTS 1 144 #ifdef DEBUG_CONTACTS 145 m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0)); 146 m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0)); 147 m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1)); 148 #endif //DEBUG_CONTACTS 149 150 151 m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth); 152 } 153 154 }; 155 156 extern btScalar gContactBreakingThreshold; 98 157 99 158 // … … 111 170 resultOut->setPersistentManifold(m_manifoldPtr); 112 171 172 //comment-out next line to test multi-contact generation 173 //resultOut->getPersistentManifold()->clearManifold(); 113 174 114 175 … … 147 208 148 209 gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); 149 150 210 btScalar sepDist = gjkPairDetector.getCachedSeparatingDistance()+dispatchInfo.m_convexConservativeDistanceThreshold; 211 212 //now perturbe directions to get multiple contact points 213 btVector3 v0,v1; 214 btVector3 sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized(); 215 btPlaneSpace1(sepNormalWorldSpace,v0,v1); 216 //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects 217 218 //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points 219 if (resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold) 220 { 221 222 int i; 223 224 bool perturbeA = true; 225 const btScalar angleLimit = 0.125f * SIMD_PI; 226 btScalar perturbeAngle; 227 btScalar radiusA = min0->getAngularMotionDisc(); 228 btScalar radiusB = min1->getAngularMotionDisc(); 229 if (radiusA < radiusB) 230 { 231 perturbeAngle = gContactBreakingThreshold /radiusA; 232 perturbeA = true; 233 } else 234 { 235 perturbeAngle = gContactBreakingThreshold / radiusB; 236 perturbeA = false; 237 } 238 if ( perturbeAngle > angleLimit ) 239 perturbeAngle = angleLimit; 240 241 btTransform unPerturbedTransform; 242 if (perturbeA) 243 { 244 unPerturbedTransform = input.m_transformA; 245 } else 246 { 247 unPerturbedTransform = input.m_transformB; 248 } 249 250 for ( i=0;i<m_numPerturbationIterations;i++) 251 { 252 btQuaternion perturbeRot(v0,perturbeAngle); 253 btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); 254 btQuaternion rotq(sepNormalWorldSpace,iterationAngle); 255 256 257 if (perturbeA) 258 { 259 input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis()); 260 input.m_transformB = body1->getWorldTransform(); 261 #ifdef DEBUG_CONTACTS 262 dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0); 263 #endif //DEBUG_CONTACTS 264 } else 265 { 266 input.m_transformA = body0->getWorldTransform(); 267 input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis()); 268 #ifdef DEBUG_CONTACTS 269 dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0); 270 #endif 271 } 272 273 btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw); 274 gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw); 275 276 277 } 278 } 279 280 151 281 152 282 #ifdef USE_SEPDISTANCE_UTIL2 -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
r2662 r2882 34 34 ///#define USE_SEPDISTANCE_UTIL2 1 35 35 36 ///ConvexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations. 36 ///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects. 37 ///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal. 38 ///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888 37 39 class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm 38 40 { … … 48 50 bool m_lowLevelOfDetail; 49 51 52 int m_numPerturbationIterations; 53 int m_minimumPointsPerturbationThreshold; 54 55 50 56 ///cache separating vector to speedup collision detection 51 57 … … 53 59 public: 54 60 55 btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); 61 btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); 62 56 63 57 64 virtual ~btConvexConvexAlgorithm(); … … 79 86 struct CreateFunc :public btCollisionAlgorithmCreateFunc 80 87 { 88 81 89 btConvexPenetrationDepthSolver* m_pdSolver; 82 90 btSimplexSolverInterface* m_simplexSolver; 83 91 int m_numPerturbationIterations; 92 int m_minimumPointsPerturbationThreshold; 93 84 94 CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); 85 95 … … 89 99 { 90 100 void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); 91 return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver );101 return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); 92 102 } 93 103 }; -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
r2662 r2882 5 5 This software is provided 'as-is', without any express or implied warranty. 6 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 9 subject to the following restrictions: 10 10 … … 23 23 //#include <stdio.h> 24 24 25 btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped )25 btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold) 26 26 : btCollisionAlgorithm(ci), 27 27 m_ownManifold(false), 28 28 m_manifoldPtr(mf), 29 m_isSwapped(isSwapped) 29 m_isSwapped(isSwapped), 30 m_numPerturbationIterations(numPerturbationIterations), 31 m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) 30 32 { 31 33 btCollisionObject* convexObj = m_isSwapped? col1 : col0; 32 34 btCollisionObject* planeObj = m_isSwapped? col0 : col1; 33 35 34 36 if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj)) 35 37 { … … 49 51 } 50 52 51 52 53 void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 53 void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 54 54 { 55 (void)dispatchInfo; 56 (void)resultOut; 57 if (!m_manifoldPtr) 58 return; 59 60 btCollisionObject* convexObj = m_isSwapped? body1 : body0; 55 btCollisionObject* convexObj = m_isSwapped? body1 : body0; 61 56 btCollisionObject* planeObj = m_isSwapped? body0: body1; 62 57 … … 64 59 btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); 65 60 66 61 bool hasCollision = false; 67 62 const btVector3& planeNormal = planeShape->getPlaneNormal(); 68 63 const btScalar& planeConstant = planeShape->getPlaneConstant(); 64 65 btTransform convexWorldTransform = convexObj->getWorldTransform(); 66 btTransform convexInPlaneTrans; 67 convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform; 68 //now perturbe the convex-world transform 69 convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot); 69 70 btTransform planeInConvex; 70 planeInConvex= convex Obj->getWorldTransform().inverse() * planeObj->getWorldTransform();71 btTransform convexInPlaneTrans;72 convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform();71 planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform(); 72 73 btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); 73 74 74 btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);75 75 btVector3 vtxInPlane = convexInPlaneTrans(vtx); 76 76 btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); … … 88 88 resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); 89 89 } 90 } 91 92 93 void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 94 { 95 (void)dispatchInfo; 96 if (!m_manifoldPtr) 97 return; 98 99 btCollisionObject* convexObj = m_isSwapped? body1 : body0; 100 btCollisionObject* planeObj = m_isSwapped? body0: body1; 101 102 btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); 103 btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); 104 105 bool hasCollision = false; 106 const btVector3& planeNormal = planeShape->getPlaneNormal(); 107 const btScalar& planeConstant = planeShape->getPlaneConstant(); 108 109 //first perform a collision query with the non-perturbated collision objects 110 { 111 btQuaternion rotq(0,0,0,1); 112 collideSingleContact(rotq,body0,body1,dispatchInfo,resultOut); 113 } 114 115 if (resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold) 116 { 117 btVector3 v0,v1; 118 btPlaneSpace1(planeNormal,v0,v1); 119 //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects 120 121 const btScalar angleLimit = 0.125f * SIMD_PI; 122 btScalar perturbeAngle; 123 btScalar radius = convexShape->getAngularMotionDisc(); 124 perturbeAngle = gContactBreakingThreshold / radius; 125 if ( perturbeAngle > angleLimit ) 126 perturbeAngle = angleLimit; 127 128 btQuaternion perturbeRot(v0,perturbeAngle); 129 for (int i=0;i<m_numPerturbationIterations;i++) 130 { 131 btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); 132 btQuaternion rotq(planeNormal,iterationAngle); 133 collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0,body1,dispatchInfo,resultOut); 134 } 135 } 136 90 137 if (m_ownManifold) 91 138 { -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
r2662 r2882 5 5 This software is provided 'as-is', without any express or implied warranty. 6 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 9 subject to the following restrictions: 10 10 … … 29 29 class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm 30 30 { 31 bool m_ownManifold;31 bool m_ownManifold; 32 32 btPersistentManifold* m_manifoldPtr; 33 bool m_isSwapped; 34 33 bool m_isSwapped; 34 int m_numPerturbationIterations; 35 int m_minimumPointsPerturbationThreshold; 36 35 37 public: 36 38 37 btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped );39 btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold); 38 40 39 41 virtual ~btConvexPlaneCollisionAlgorithm(); 40 42 41 43 virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); 44 45 void collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); 42 46 43 47 virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); … … 53 57 struct CreateFunc :public btCollisionAlgorithmCreateFunc 54 58 { 59 int m_numPerturbationIterations; 60 int m_minimumPointsPerturbationThreshold; 61 62 CreateFunc() 63 : m_numPerturbationIterations(3), 64 m_minimumPointsPerturbationThreshold(3) 65 { 66 } 67 55 68 virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) 56 69 { … … 58 71 if (!m_swapped) 59 72 { 60 return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false );73 return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); 61 74 } else 62 75 { 63 return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true );76 return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); 64 77 } 65 78 } -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
r2662 r2882 289 289 return m_emptyCreateFunc; 290 290 } 291 292 void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold) 293 { 294 btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc; 295 convexConvex->m_numPerturbationIterations = numPerturbationIterations; 296 convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; 297 } -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
r2662 r2882 112 112 virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); 113 113 114 ///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm. 115 ///By default, this feature is disabled for best performance. 116 ///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature. 117 ///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled 118 ///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first. 119 ///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points. 120 ///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection. 121 void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); 114 122 115 123 }; -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
r2662 r2882 64 64 btPairCachingGhostObject::~btPairCachingGhostObject() 65 65 { 66 m_hashPairCache->~btHashedOverlappingPairCache(); 66 67 btAlignedFree( m_hashPairCache ); 67 68 } -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
r2662 r2882 56 56 void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) 57 57 { 58 assert(m_manifoldPtr);58 btAssert(m_manifoldPtr); 59 59 //order in manifold needs to match 60 60 … … 93 93 newPt.m_index0 = m_index0; 94 94 newPt.m_index1 = m_index1; 95 95 //printf("depth=%f\n",depth); 96 96 ///@todo, check this for any side effects 97 97 if (insertIndex >= 0) -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
r2662 r2882 46 46 int m_index0; 47 47 int m_index1; 48 49 48 50 public: 49 51 … … 78 80 } 79 81 82 80 83 virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); 81 84 -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
r2662 r2882 25 25 #include "LinearMath/btQuickprof.h" 26 26 27 btSimulationIslandManager::btSimulationIslandManager() 27 btSimulationIslandManager::btSimulationIslandManager(): 28 m_splitIslands(true) 28 29 { 29 30 } … … 44 45 45 46 { 46 btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); 47 47 48 48 for (int i=0;i<colWorld->getPairCache()->getNumOverlappingPairs();i++) 49 49 { 50 btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); 50 51 const btBroadphasePair& collisionPair = pairPtr[i]; 51 52 btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; … … 186 187 } 187 188 188 assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));189 btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); 189 190 if (colObj0->getIslandTag() == islandId) 190 191 { … … 213 214 } 214 215 215 assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));216 btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); 216 217 217 218 if (colObj0->getIslandTag() == islandId) … … 234 235 } 235 236 236 assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));237 btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); 237 238 238 239 if (colObj0->getIslandTag() == islandId) … … 252 253 int maxNumManifolds = dispatcher->getNumManifolds(); 253 254 254 #define SPLIT_ISLANDS 1255 #ifdef SPLIT_ISLANDS256 257 258 #endif //SPLIT_ISLANDS255 //#define SPLIT_ISLANDS 1 256 //#ifdef SPLIT_ISLANDS 257 258 259 //#endif //SPLIT_ISLANDS 259 260 260 261 … … 280 281 colObj0->activate(); 281 282 } 282 #ifdef SPLIT_ISLANDS 283 // //filtering for response 284 if (dispatcher->needsResponse(colObj0,colObj1)) 285 m_islandmanifold.push_back(manifold); 286 #endif //SPLIT_ISLANDS 283 if(m_splitIslands) 284 { 285 //filtering for response 286 if (dispatcher->needsResponse(colObj0,colObj1)) 287 m_islandmanifold.push_back(manifold); 288 } 287 289 } 288 290 } … … 304 306 BT_PROFILE("processIslands"); 305 307 306 #ifndef SPLIT_ISLANDS 307 btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); 308 309 callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); 310 #else 311 // Sort manifolds, based on islands 312 // Sort the vector using predicate and std::sort 313 //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); 314 315 int numManifolds = int (m_islandmanifold.size()); 316 317 //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) 318 m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); 319 320 //now process all active islands (sets of manifolds for now) 321 322 int startManifoldIndex = 0; 323 int endManifoldIndex = 1; 324 325 //int islandId; 326 327 328 329 // printf("Start Islands\n"); 330 331 //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated 332 for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) 333 { 334 int islandId = getUnionFind().getElement(startIslandIndex).m_id; 335 336 337 bool islandSleeping = false; 338 339 for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) 340 { 341 int i = getUnionFind().getElement(endIslandIndex).m_sz; 342 btCollisionObject* colObj0 = collisionObjects[i]; 343 m_islandBodies.push_back(colObj0); 344 if (!colObj0->isActive()) 345 islandSleeping = true; 346 } 347 348 349 //find the accompanying contact manifold for this islandId 350 int numIslandManifolds = 0; 351 btPersistentManifold** startManifold = 0; 352 353 if (startManifoldIndex<numManifolds) 354 { 355 int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]); 356 if (curIslandId == islandId) 357 { 358 startManifold = &m_islandmanifold[startManifoldIndex]; 308 if(!m_splitIslands) 309 { 310 btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); 311 int maxNumManifolds = dispatcher->getNumManifolds(); 312 callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); 313 } 314 else 315 { 316 // Sort manifolds, based on islands 317 // Sort the vector using predicate and std::sort 318 //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); 319 320 int numManifolds = int (m_islandmanifold.size()); 321 322 //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) 323 m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); 324 325 //now process all active islands (sets of manifolds for now) 326 327 int startManifoldIndex = 0; 328 int endManifoldIndex = 1; 329 330 //int islandId; 331 332 333 334 // printf("Start Islands\n"); 335 336 //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated 337 for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) 338 { 339 int islandId = getUnionFind().getElement(startIslandIndex).m_id; 340 341 342 bool islandSleeping = false; 343 344 for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) 345 { 346 int i = getUnionFind().getElement(endIslandIndex).m_sz; 347 btCollisionObject* colObj0 = collisionObjects[i]; 348 m_islandBodies.push_back(colObj0); 349 if (!colObj0->isActive()) 350 islandSleeping = true; 351 } 352 353 354 //find the accompanying contact manifold for this islandId 355 int numIslandManifolds = 0; 356 btPersistentManifold** startManifold = 0; 357 358 if (startManifoldIndex<numManifolds) 359 { 360 int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]); 361 if (curIslandId == islandId) 362 { 363 startManifold = &m_islandmanifold[startManifoldIndex]; 364 365 for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++) 366 { 367 368 } 369 /// Process the actual simulation, only if not sleeping/deactivated 370 numIslandManifolds = endManifoldIndex-startManifoldIndex; 371 } 372 373 } 374 375 if (!islandSleeping) 376 { 377 callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); 378 // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); 379 } 359 380 360 for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++) 361 { 362 363 } 364 /// Process the actual simulation, only if not sleeping/deactivated 365 numIslandManifolds = endManifoldIndex-startManifoldIndex; 366 } 367 368 } 369 370 if (!islandSleeping) 371 { 372 callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); 373 // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); 374 } 375 376 if (numIslandManifolds) 377 { 378 startManifoldIndex = endManifoldIndex; 379 } 380 381 m_islandBodies.resize(0); 382 } 383 #endif //SPLIT_ISLANDS 384 385 386 } 381 if (numIslandManifolds) 382 { 383 startManifoldIndex = endManifoldIndex; 384 } 385 386 m_islandBodies.resize(0); 387 } 388 } // else if(!splitIslands) 389 390 } -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
r2662 r2882 36 36 btAlignedObjectArray<btCollisionObject* > m_islandBodies; 37 37 38 bool m_splitIslands; 38 39 39 40 public: … … 66 67 void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld); 67 68 69 bool getSplitIslands() 70 { 71 return m_splitIslands; 72 } 73 void setSplitIslands(bool doSplitIslands) 74 { 75 m_splitIslands = doSplitIslands; 76 } 77 68 78 }; 69 79 -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
r2662 r2882 79 79 80 80 ///point on A (worldspace) 81 btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;81 ///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; 82 82 ///point on B (worldspace) 83 83 btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
r2662 r2882 15 15 16 16 #include "btUnionFind.h" 17 #include <assert.h>18 19 17 20 18 -
code/trunk/src/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
r2662 r2882 99 99 int find(int x) 100 100 { 101 // assert(x < m_N);102 // assert(x >= 0);101 //btAssert(x < m_N); 102 //btAssert(x >= 0); 103 103 104 104 while (x != m_elements[x].m_id) … … 111 111 #endif // 112 112 x = m_elements[x].m_id; 113 // assert(x < m_N);114 // assert(x >= 0);113 //btAssert(x < m_N); 114 //btAssert(x >= 0); 115 115 116 116 } -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btBoxShape.h
r2662 r2882 162 162 { 163 163 case 0: 164 plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); 165 plane[3] = -halfExtents.x(); 164 plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x()); 166 165 break; 167 166 case 1: 168 plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); 169 plane[3] = -halfExtents.x(); 167 plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x()); 170 168 break; 171 169 case 2: 172 plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); 173 plane[3] = -halfExtents.y(); 170 plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y()); 174 171 break; 175 172 case 3: 176 plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); 177 plane[3] = -halfExtents.y(); 173 plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y()); 178 174 break; 179 175 case 4: 180 plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); 181 plane[3] = -halfExtents.z(); 176 plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z()); 182 177 break; 183 178 case 5: 184 plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); 185 plane[3] = -halfExtents.z(); 179 plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z()); 186 180 break; 187 181 default: 188 assert(0);182 btAssert(0); 189 183 } 190 184 } … … 313 307 break; 314 308 default: 315 assert(0);309 btAssert(0); 316 310 } 317 311 } -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
r2662 r2882 15 15 16 16 #include "BulletCollision/CollisionShapes/btCollisionShape.h" 17 18 19 btScalar gContactThresholdFactor=btScalar(0.02); 17 20 18 21 … … 45 48 btScalar btCollisionShape::getContactBreakingThreshold() const 46 49 { 47 ///@todo make this 0.1 configurable 48 return getAngularMotionDisc() * btScalar(0.1); 50 return getAngularMotionDisc() * gContactThresholdFactor; 49 51 } 50 52 btScalar btCollisionShape::getAngularMotionDisc() const -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
r2662 r2882 23 23 m_collisionMargin(btScalar(0.)), 24 24 m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), 25 m_dynamicAabbTree(0) 25 m_dynamicAabbTree(0), 26 m_updateRevision(1) 26 27 { 27 28 m_shapeType = COMPOUND_SHAPE_PROXYTYPE; … … 47 48 void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) 48 49 { 50 m_updateRevision++; 49 51 //m_childTransforms.push_back(localTransform); 50 52 //m_childShapes.push_back(shape); … … 55 57 child.m_childMargin = shape->getMargin(); 56 58 57 m_children.push_back(child); 58 59 59 60 //extend the local aabbMin/aabbMax 60 61 btVector3 localAabbMin,localAabbMax; … … 75 76 { 76 77 const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); 77 int index = m_children.size() -1;78 int index = m_children.size(); 78 79 child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); 79 80 } 81 82 m_children.push_back(child); 80 83 81 84 } … … 100 103 void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) 101 104 { 105 m_updateRevision++; 102 106 btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); 103 107 if (m_dynamicAabbTree) … … 114 118 void btCompoundShape::removeChildShape(btCollisionShape* shape) 115 119 { 120 m_updateRevision++; 116 121 // Find the children containing the shape specified, and remove those children. 117 122 //note: there might be multiple children using the same shape! … … 140 145 // Recalculate the local aabb 141 146 // Brute force, it iterates over all the shapes left. 147 142 148 m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)); 143 149 m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); … … 162 168 { 163 169 btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); 170 btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); 171 172 //avoid an illegal AABB when there are no children 173 if (!m_children.size()) 174 { 175 localHalfExtents.setValue(0,0,0); 176 localCenter.setValue(0,0,0); 177 } 164 178 localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); 165 btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);179 166 180 167 181 btMatrix3x3 abs_b = trans.getBasis().absolute(); … … 174 188 aabbMin = center-extent; 175 189 aabbMax = center+extent; 176 190 177 191 } 178 192 -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
r2662 r2882 59 59 60 60 btDbvt* m_dynamicAabbTree; 61 62 ///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated 63 int m_updateRevision; 61 64 62 65 public: … … 153 156 void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; 154 157 158 int getUpdateRevision() const 159 { 160 return m_updateRevision; 161 } 155 162 156 163 private: -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
r2662 r2882 61 61 break; 62 62 default: 63 assert(0);63 btAssert(0); 64 64 }; 65 65 } -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
r2662 r2882 182 182 bool btConvexHullShape::isInside(const btVector3& ,btScalar ) const 183 183 { 184 assert(0);184 btAssert(0); 185 185 return false; 186 186 } -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
r2662 r2882 151 151 bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const 152 152 { 153 assert(0);153 btAssert(0); 154 154 return false; 155 155 } -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
r2662 r2882 155 155 156 156 btCapsuleShape* capsuleShape = (btCapsuleShape*)this; 157 btVector3 halfExtents = capsuleShape->getImplicitShapeDimensions();158 157 btScalar halfHeight = capsuleShape->getHalfHeight(); 159 158 int capsuleUpAxis = capsuleShape->getUpAxis(); … … 302 301 { 303 302 btSphereShape* sphereShape = (btSphereShape*)this; 304 floatradius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();305 floatmargin = radius + sphereShape->getMarginNonVirtual();303 btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX(); 304 btScalar margin = radius + sphereShape->getMarginNonVirtual(); 306 305 const btVector3& center = t.getOrigin(); 307 306 btVector3 extent(margin,margin,margin); … … 315 314 { 316 315 btBoxShape* convexShape = (btBoxShape*)this; 317 floatmargin=convexShape->getMarginNonVirtual();316 btScalar margin=convexShape->getMarginNonVirtual(); 318 317 btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); 319 318 halfExtents += btVector3(margin,margin,margin); -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
r2662 r2882 145 145 } 146 146 147 btScalar btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const 147 148 /// This returns the "raw" (user's initial) height, not the actual height. 149 /// The actual height needs to be adjusted to be relative to the center 150 /// of the heightfield's AABB. 151 btScalar 152 btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const 148 153 { 149 154 btScalar val = 0.f; … … 182 187 183 188 184 189 /// this returns the vertex in bullet-local coordinates 185 190 void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const 186 191 { 187 188 192 btAssert(x>=0); 189 193 btAssert(y>=0); … … 191 195 btAssert(y<m_heightStickLength); 192 196 193 194 btScalar height = getHeightFieldValue(x,y); 197 btScalar height = getRawHeightFieldValue(x,y); 195 198 196 199 switch (m_upAxis) … … 199 202 { 200 203 vertex.setValue( 201 height ,204 height - m_localOrigin.getX(), 202 205 (-m_width/btScalar(2.0)) + x, 203 206 (-m_length/btScalar(2.0) ) + y … … 209 212 vertex.setValue( 210 213 (-m_width/btScalar(2.0)) + x, 211 height ,214 height - m_localOrigin.getY(), 212 215 (-m_length/btScalar(2.0)) + y 213 216 ); … … 219 222 (-m_width/btScalar(2.0)) + x, 220 223 (-m_length/btScalar(2.0)) + y, 221 height 224 height - m_localOrigin.getZ() 222 225 ); 223 226 break; … … 231 234 232 235 vertex*=m_localScaling; 233 234 236 } 235 237 … … 239 241 getQuantized 240 242 ( 241 floatx243 btScalar x 242 244 ) 243 245 { -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
r2662 r2882 30 30 center (as determined by width and length and height, with each 31 31 axis multiplied by the localScaling). 32 33 \b NOTE: be careful with coordinates. If you have a heightfield with a local 34 min height of -100m, and a max height of +500m, you may be tempted to place it 35 at the origin (0,0) and expect the heights in world coordinates to be 36 -100 to +500 meters. 37 Actually, the heights will be -300 to +300m, because bullet will re-center 38 the heightfield based on its AABB (which is determined by the min/max 39 heights). So keep in mind that once you create a btHeightfieldTerrainShape 40 object, the heights will be adjusted relative to the center of the AABB. This 41 is different to the behavior of many rendering engines, but is useful for 42 physics engines. 32 43 33 44 Most (but not all) rendering and heightfield libraries assume upAxis = 1 … … 89 100 btVector3 m_localScaling; 90 101 91 virtual btScalar get HeightFieldValue(int x,int y) const;102 virtual btScalar getRawHeightFieldValue(int x,int y) const; 92 103 void quantizeWithClamp(int* out, const btVector3& point,int isMax) const; 93 104 void getVertex(int x,int y,btVector3& vertex) const; -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
r2662 r2882 29 29 btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const 30 30 { 31 btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin( -vec*m_transA.getBasis()));32 btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin( vec*m_transB.getBasis()));31 btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); 32 btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec*m_transB.getBasis())); 33 33 return supVertexA - supVertexB; 34 34 } -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
r2662 r2882 32 32 BT_DECLARE_ALIGNED_ALLOCATOR(); 33 33 34 btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() { }34 btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;} 35 35 btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true): 36 36 btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh) 37 37 { 38 m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; 39 38 40 btVector3 m_triangle[3]; 39 41 const unsigned char *vertexbase; … … 68 70 btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh) 69 71 { 72 m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; 73 70 74 btVector3 m_triangle[3]; 71 75 const unsigned char *vertexbase; … … 108 112 */ 109 113 } 110 virtual int getShapeType() const111 {112 return MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;113 }114 115 114 //debugging 116 115 virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";} -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btSphereShape.h
r2662 r2882 48 48 btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();} 49 49 50 void setUnscaledRadius(btScalar radius) 51 { 52 m_implicitShapeDimensions.setX(radius); 53 btConvexInternalShape::setMargin(radius); 54 } 55 50 56 //debugging 51 57 virtual const char* getName()const {return "SPHERE";} -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
r2662 r2882 83 83 } 84 84 85 void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) 85 86 void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const 86 87 { 87 88 m_aabbMin = aabbMin; … … 96 97 } 97 98 99 -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
r2662 r2882 53 53 IndexedMeshArray m_indexedMeshes; 54 54 int m_pad[2]; 55 int m_hasAabb; // using int instead of bool to maintain alignment56 btVector3 m_aabbMin;57 btVector3 m_aabbMax;55 mutable int m_hasAabb; // using int instead of bool to maintain alignment 56 mutable btVector3 m_aabbMin; 57 mutable btVector3 m_aabbMax; 58 58 59 59 public: … … 107 107 108 108 virtual bool hasPremadeAabb() const; 109 virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) ;109 virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const; 110 110 virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const; 111 111 -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
r2662 r2882 1 1 2 /* 2 3 Bullet Continuous Collision Detection and Physics Library -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
r2662 r2882 36 36 { 37 37 m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3; 38 m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];38 m_indexedMeshes[0].m_triangleIndexBase = 0; 39 39 m_indexedMeshes[0].m_indexType = PHY_INTEGER; 40 40 m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int); … … 42 42 { 43 43 m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3; 44 m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];44 m_indexedMeshes[0].m_triangleIndexBase = 0; 45 45 m_indexedMeshes[0].m_indexType = PHY_SHORT; 46 46 m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int); … … 50 50 { 51 51 m_indexedMeshes[0].m_numVertices = m_4componentVertices.size(); 52 m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];52 m_indexedMeshes[0].m_vertexBase = 0; 53 53 m_indexedMeshes[0].m_vertexStride = sizeof(btVector3); 54 54 } else 55 55 { 56 56 m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3; 57 m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];57 m_indexedMeshes[0].m_vertexBase = 0; 58 58 m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar); 59 59 } … … 112 112 } 113 113 } 114 m_3componentVertices.push_back( vertex.getX());115 m_3componentVertices.push_back( vertex.getY());116 m_3componentVertices.push_back( vertex.getZ());114 m_3componentVertices.push_back((float)vertex.getX()); 115 m_3componentVertices.push_back((float)vertex.getY()); 116 m_3componentVertices.push_back((float)vertex.getZ()); 117 117 m_indexedMeshes[0].m_numVertices++; 118 118 m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; -
code/trunk/src/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
r2662 r2882 41 41 virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const 42 42 { 43 assert(0);43 btAssert(0); 44 44 return localGetSupportingVertex(vec); 45 45 } -
code/trunk/src/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp
r2662 r2882 151 151 } 152 152 153 bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); 154 btAssert(!unbal); 153 btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); 155 154 156 155 return splitIndex; -
code/trunk/src/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
r2662 r2882 172 172 } 173 173 174 bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); 175 btAssert(!unbal); 174 btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); 176 175 177 176 return splitIndex; -
code/trunk/src/bullet/BulletCollision/Gimpact/btGImpactShape.h
r2662 r2882 882 882 class btGImpactMeshShape : public btGImpactShapeInterface 883 883 { 884 btStridingMeshInterface* m_meshInterface; 885 884 886 protected: 885 887 btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts; … … 908 910 btGImpactMeshShape(btStridingMeshInterface * meshInterface) 909 911 { 912 m_meshInterface = meshInterface; 910 913 buildMeshParts(meshInterface); 911 914 } … … 923 926 924 927 928 btStridingMeshInterface* getMeshInterface() 929 { 930 return m_meshInterface; 931 } 932 933 const btStridingMeshInterface* getMeshInterface() const 934 { 935 return m_meshInterface; 936 } 925 937 926 938 int getMeshPartCount() const … … 1034 1046 1035 1047 //! call when reading child shapes 1036 virtual void lockChildShapes() 1037 { 1038 btAssert(0); 1039 } 1040 1041 virtual void unlockChildShapes() 1048 virtual void lockChildShapes() const 1049 { 1050 btAssert(0); 1051 } 1052 1053 virtual void unlockChildShapes() const 1042 1054 { 1043 1055 btAssert(0); -
code/trunk/src/bullet/BulletCollision/Gimpact/gim_box_set.cpp
r2662 r2882 111 111 } 112 112 113 bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); 114 btAssert(!unbal); 113 btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); 115 114 116 115 return splitIndex; … … 181 180 } 182 181 182 -
code/trunk/src/bullet/BulletCollision/Gimpact/gim_math.h
r2662 r2882 108 108 #define GIM_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number)) 109 109 110 #define GIM_GREATER(x, y) fabsf(x) > (y)110 #define GIM_GREATER(x, y) btFabs(x) > (y) 111 111 112 112 ///Swap numbers -
code/trunk/src/bullet/BulletCollision/Gimpact/gim_tri_collision.h
r2662 r2882 276 276 else 277 277 { 278 floatsumuv;278 btScalar sumuv; 279 279 sumuv = u+v; 280 280 if(sumuv<-G_EPSILON) -
code/trunk/src/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
r2662 r2882 136 136 //btScalar clippedDist = dist; 137 137 138 //don't report time of impact for motion away from the contact normal (or causes minor penetration) 139 if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON) 140 return false; 138 141 139 142 dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); … … 197 200 198 201 } 199 200 //don't report time of impact for motion away from the contact normal (or causes minor penetration) 202 201 203 if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON) 202 204 return false; 203 205 204 206 result.m_fraction = lambda; 205 207 result.m_normal = n; -
code/trunk/src/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
r2662 r2882 151 151 if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared)) 152 152 { 153 checkPenetration = false; 153 checkSimplex=true; 154 //checkPenetration = false; 154 155 break; 155 156 } -
code/trunk/src/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
r2662 r2882 113 113 } 114 114 115 ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver 116 btScalar getAppliedImpulse() const 117 { 118 return m_appliedImpulse; 119 } 120 115 121 116 122 -
code/trunk/src/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
r2662 r2882 184 184 185 185 } 186 if (insertIndex<0) 187 insertIndex=0; 188 186 189 btAssert(m_pointCache[insertIndex].m_userPersistentData==0); 187 190 m_pointCache[insertIndex] = newPoint; -
code/trunk/src/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
r2662 r2882 56 56 57 57 btScalar m_contactBreakingThreshold; 58 btScalar m_contactProcessingThreshold; 58 59 59 60 … … 71 72 btPersistentManifold(); 72 73 73 btPersistentManifold(void* body0,void* body1,int , btScalar contactBreakingThreshold )74 btPersistentManifold(void* body0,void* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold) 74 75 : m_body0(body0),m_body1(body1),m_cachedPoints(0), 75 m_contactBreakingThreshold(contactBreakingThreshold) 76 m_contactBreakingThreshold(contactBreakingThreshold), 77 m_contactProcessingThreshold(contactProcessingThreshold) 76 78 { 77 79 … … 112 114 ///@todo: get this margin from the current physics / collision environment 113 115 btScalar getContactBreakingThreshold() const; 116 117 btScalar getContactProcessingThreshold() const 118 { 119 return m_contactProcessingThreshold; 120 } 114 121 115 122 int getCacheEntry(const btManifoldPoint& newPoint) const; -
code/trunk/src/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
r2662 r2882 24 24 #include "btRaycastCallback.h" 25 25 26 btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to )26 btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags) 27 27 : 28 28 m_from(from), 29 29 m_to(to), 30 //@BP Mod 31 m_flags(flags), 30 32 m_hitFraction(btScalar(1.)) 31 33 { … … 56 58 return ; // same sign 57 59 } 60 //@BP Mod - Backface filtering 61 if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a > btScalar(0.0))) 62 { 63 // Backface, skip check 64 return; 65 } 58 66 59 67 const btScalar proj_length=dist_a-dist_b; … … 90 98 if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) 91 99 { 100 //@BP Mod 101 // Triangle normal isn't normalized 102 triangleNormal.normalize(); 92 103 93 if ( dist_a > 0 ) 104 //@BP Mod - Allow for unflipped normal when raycasting against backfaces 105 if (((m_flags & kF_KeepUnflippedNormal) != 0) || (dist_a <= btScalar(0.0))) 94 106 { 95 m_hitFraction = reportHit( triangleNormal,distance,partId,triangleIndex);107 m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex); 96 108 } 97 109 else 98 110 { 99 m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);111 m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); 100 112 } 101 113 } -
code/trunk/src/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
r2662 r2882 30 30 btVector3 m_to; 31 31 32 //@BP Mod - allow backface filtering and unflipped normals 33 enum EFlags 34 { 35 kF_None = 0, 36 kF_FilterBackfaces = 1 << 0, 37 kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle 38 39 kF_Terminator = 0xFFFFFFFF 40 }; 41 unsigned int m_flags; 42 32 43 btScalar m_hitFraction; 33 44 34 btTriangleRaycastCallback(const btVector3& from,const btVector3& to );45 btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0); 35 46 36 47 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); -
code/trunk/src/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
r2662 r2882 26 26 27 27 #include "btVoronoiSimplexSolver.h" 28 #include <assert.h>29 //#include <stdio.h>30 28 31 29 #define VERTA 0 … … 38 36 { 39 37 40 assert(m_numVertices>0);38 btAssert(m_numVertices>0); 41 39 m_numVertices--; 42 40 m_simplexVectorW[index] = m_simplexVectorW[m_numVertices]; -
code/trunk/src/bullet/BulletDynamics/CMakeLists.txt
r2710 r2882 36 36 ConstraintSolver/btTypedConstraint.h 37 37 38 Dynamics/btActionInterface.h 38 39 Dynamics/btContinuousDynamicsWorld.h 39 40 Dynamics/btDiscreteDynamicsWorld.h -
code/trunk/src/bullet/BulletDynamics/Character/btCharacterControllerInterface.h
r2662 r2882 18 18 19 19 #include "LinearMath/btVector3.h" 20 #include "BulletDynamics/Dynamics/btActionInterface.h" 20 21 21 22 class btCollisionShape; … … 23 24 class btCollisionWorld; 24 25 25 class btCharacterControllerInterface 26 class btCharacterControllerInterface : public btActionInterface 26 27 { 27 28 public: -
code/trunk/src/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp
r2662 r2882 23 23 #include "btKinematicCharacterController.h" 24 24 25 static btVector3 upAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) }; 26 25 27 ///@todo Interact with dynamic objects, 26 28 ///Ride kinematicly animated platforms properly … … 94 96 } 95 97 96 btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight) 97 { 98 btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis) 99 { 100 m_upAxis = upAxis; 98 101 m_addedMargin = 0.02f; 99 102 m_walkDirection.setValue(0,0,0); … … 102 105 m_stepHeight = stepHeight; 103 106 m_turnAngle = btScalar(0.0); 104 m_convexShape=convexShape; 105 107 m_convexShape=convexShape; 106 108 } 107 109 … … 110 112 } 111 113 112 113 114 btPairCachingGhostObject* btKinematicCharacterController::getGhostObject() 114 115 { … … 116 117 } 117 118 118 bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld)119 bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld) 119 120 { 120 121 … … 173 174 // phase 1: up 174 175 btTransform start, end; 175 m_targetPosition = m_currentPosition + btVector3 (btScalar(0.0), m_stepHeight, btScalar(0.0));176 m_targetPosition = m_currentPosition + upAxisDirection[m_upAxis] * m_stepHeight; 176 177 177 178 start.setIdentity (); … … 179 180 180 181 /* FIXME: Handle penetration properly */ 181 start.setOrigin (m_currentPosition + btVector3(btScalar(0.0), btScalar(0.1), btScalar(0.0)));182 start.setOrigin (m_currentPosition + upAxisDirection[m_upAxis] * btScalar(0.1f)); 182 183 end.setOrigin (m_targetPosition); 183 184 … … 344 345 345 346 // phase 3: down 346 btVector3 step_drop = btVector3(btScalar(0.0), m_currentStepOffset, btScalar(0.0));347 btVector3 gravity_drop = btVector3(btScalar(0.0), m_stepHeight, btScalar(0.0));347 btVector3 step_drop = upAxisDirection[m_upAxis] * m_currentStepOffset; 348 btVector3 gravity_drop = upAxisDirection[m_upAxis] * m_stepHeight; 348 349 m_targetPosition -= (step_drop + gravity_drop); 349 350 … … 390 391 391 392 392 void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld)393 void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld) 393 394 { 394 395 … … 413 414 } 414 415 415 void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt)416 void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt) 416 417 { 417 418 btTransform xform; … … 469 470 return true; 470 471 } 472 473 474 void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer) 475 { 476 } -
code/trunk/src/bullet/BulletDynamics/Character/btKinematicCharacterController.h
r2662 r2882 63 63 64 64 bool m_useGhostObjectSweepTest; 65 66 int m_upAxis; 65 67 66 68 btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal); … … 68 70 btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal); 69 71 70 bool recoverFromPenetration ( btCollisionWorld* collisionWorld);72 bool recoverFromPenetration ( btCollisionWorld* collisionWorld); 71 73 void stepUp (btCollisionWorld* collisionWorld); 72 74 void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0)); … … 74 76 void stepDown (btCollisionWorld* collisionWorld, btScalar dt); 75 77 public: 76 btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight );78 btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1); 77 79 ~btKinematicCharacterController (); 78 80 81 82 ///btActionInterface interface 83 virtual void updateAction( btCollisionWorld* collisionWorld,btScalar deltaTime) 84 { 85 preStep ( collisionWorld); 86 playerStep (collisionWorld, deltaTime); 87 } 88 89 ///btActionInterface interface 90 void debugDraw(btIDebugDraw* debugDrawer); 91 92 void setUpAxis (int axis) 93 { 94 if (axis < 0) 95 axis = 0; 96 if (axis > 2) 97 axis = 2; 98 m_upAxis = axis; 99 } 100 79 101 virtual void setWalkDirection(const btVector3& walkDirection) 80 102 { … … 85 107 void warp (const btVector3& origin); 86 108 87 void preStep ( btCollisionWorld* collisionWorld);88 void playerStep ( btCollisionWorld* collisionWorld, btScalar dt);109 void preStep ( btCollisionWorld* collisionWorld); 110 void playerStep ( btCollisionWorld* collisionWorld, btScalar dt); 89 111 90 112 void setFallSpeed (btScalar fallSpeed); -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
r2662 r2882 23 23 #include <new> 24 24 25 //----------------------------------------------------------------------------- 26 27 #define CONETWIST_USE_OBSOLETE_SOLVER false 28 #define CONETWIST_DEF_FIX_THRESH btScalar(.05f) 29 30 //----------------------------------------------------------------------------- 31 25 32 btConeTwistConstraint::btConeTwistConstraint() 26 :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE) 33 :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE), 34 m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) 27 35 { 28 36 } … … 32 40 const btTransform& rbAFrame,const btTransform& rbBFrame) 33 41 :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), 34 m_angularOnly(false) 35 { 36 m_swingSpan1 = btScalar(1e30); 37 m_swingSpan2 = btScalar(1e30); 38 m_twistSpan = btScalar(1e30); 39 m_biasFactor = 0.3f; 40 m_relaxationFactor = 1.0f; 41 42 m_angularOnly(false), 43 m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) 44 { 45 init(); 46 } 47 48 btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) 49 :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), 50 m_angularOnly(false), 51 m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) 52 { 53 m_rbBFrame = m_rbAFrame; 54 init(); 55 } 56 57 58 void btConeTwistConstraint::init() 59 { 60 m_angularOnly = false; 42 61 m_solveTwistLimit = false; 43 62 m_solveSwingLimit = false; 44 45 } 46 47 btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) 48 :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), 49 m_angularOnly(false) 50 { 51 m_rbBFrame = m_rbAFrame; 63 m_bMotorEnabled = false; 64 m_maxMotorImpulse = btScalar(-1); 65 66 setLimit(btScalar(1e30), btScalar(1e30), btScalar(1e30)); 67 m_damping = btScalar(0.01); 68 m_fixThresh = CONETWIST_DEF_FIX_THRESH; 69 } 70 71 72 //----------------------------------------------------------------------------- 73 74 void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) 75 { 76 if (m_useSolveConstraintObsolete) 77 { 78 info->m_numConstraintRows = 0; 79 info->nub = 0; 80 } 81 else 82 { 83 info->m_numConstraintRows = 3; 84 info->nub = 3; 85 calcAngleInfo2(); 86 if(m_solveSwingLimit) 87 { 88 info->m_numConstraintRows++; 89 info->nub--; 90 if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) 91 { 92 info->m_numConstraintRows++; 93 info->nub--; 94 } 95 } 96 if(m_solveTwistLimit) 97 { 98 info->m_numConstraintRows++; 99 info->nub--; 100 } 101 } 102 } // btConeTwistConstraint::getInfo1() 52 103 53 m_swingSpan1 = btScalar(1e30); 54 m_swingSpan2 = btScalar(1e30); 55 m_twistSpan = btScalar(1e30); 56 m_biasFactor = 0.3f; 57 m_relaxationFactor = 1.0f; 58 59 m_solveTwistLimit = false; 60 m_solveSwingLimit = false; 104 //----------------------------------------------------------------------------- 105 106 void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info) 107 { 108 btAssert(!m_useSolveConstraintObsolete); 109 //retrieve matrices 110 btTransform body0_trans; 111 body0_trans = m_rbA.getCenterOfMassTransform(); 112 btTransform body1_trans; 113 body1_trans = m_rbB.getCenterOfMassTransform(); 114 // set jacobian 115 info->m_J1linearAxis[0] = 1; 116 info->m_J1linearAxis[info->rowskip+1] = 1; 117 info->m_J1linearAxis[2*info->rowskip+2] = 1; 118 btVector3 a1 = body0_trans.getBasis() * m_rbAFrame.getOrigin(); 119 { 120 btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); 121 btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); 122 btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); 123 btVector3 a1neg = -a1; 124 a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); 125 } 126 btVector3 a2 = body1_trans.getBasis() * m_rbBFrame.getOrigin(); 127 { 128 btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); 129 btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); 130 btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); 131 a2.getSkewSymmetricMatrix(angular0,angular1,angular2); 132 } 133 // set right hand side 134 btScalar k = info->fps * info->erp; 135 int j; 136 for (j=0; j<3; j++) 137 { 138 info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); 139 info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY; 140 info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY; 141 } 142 int row = 3; 143 int srow = row * info->rowskip; 144 btVector3 ax1; 145 // angular limits 146 if(m_solveSwingLimit) 147 { 148 btScalar *J1 = info->m_J1angularAxis; 149 btScalar *J2 = info->m_J2angularAxis; 150 if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) 151 { 152 btTransform trA = m_rbA.getCenterOfMassTransform()*m_rbAFrame; 153 btVector3 p = trA.getBasis().getColumn(1); 154 btVector3 q = trA.getBasis().getColumn(2); 155 int srow1 = srow + info->rowskip; 156 J1[srow+0] = p[0]; 157 J1[srow+1] = p[1]; 158 J1[srow+2] = p[2]; 159 J1[srow1+0] = q[0]; 160 J1[srow1+1] = q[1]; 161 J1[srow1+2] = q[2]; 162 J2[srow+0] = -p[0]; 163 J2[srow+1] = -p[1]; 164 J2[srow+2] = -p[2]; 165 J2[srow1+0] = -q[0]; 166 J2[srow1+1] = -q[1]; 167 J2[srow1+2] = -q[2]; 168 btScalar fact = info->fps * m_relaxationFactor; 169 info->m_constraintError[srow] = fact * m_swingAxis.dot(p); 170 info->m_constraintError[srow1] = fact * m_swingAxis.dot(q); 171 info->m_lowerLimit[srow] = -SIMD_INFINITY; 172 info->m_upperLimit[srow] = SIMD_INFINITY; 173 info->m_lowerLimit[srow1] = -SIMD_INFINITY; 174 info->m_upperLimit[srow1] = SIMD_INFINITY; 175 srow = srow1 + info->rowskip; 176 } 177 else 178 { 179 ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor; 180 J1[srow+0] = ax1[0]; 181 J1[srow+1] = ax1[1]; 182 J1[srow+2] = ax1[2]; 183 J2[srow+0] = -ax1[0]; 184 J2[srow+1] = -ax1[1]; 185 J2[srow+2] = -ax1[2]; 186 btScalar k = info->fps * m_biasFactor; 187 188 info->m_constraintError[srow] = k * m_swingCorrection; 189 info->cfm[srow] = 0.0f; 190 // m_swingCorrection is always positive or 0 191 info->m_lowerLimit[srow] = 0; 192 info->m_upperLimit[srow] = SIMD_INFINITY; 193 srow += info->rowskip; 194 } 195 } 196 if(m_solveTwistLimit) 197 { 198 ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor; 199 btScalar *J1 = info->m_J1angularAxis; 200 btScalar *J2 = info->m_J2angularAxis; 201 J1[srow+0] = ax1[0]; 202 J1[srow+1] = ax1[1]; 203 J1[srow+2] = ax1[2]; 204 J2[srow+0] = -ax1[0]; 205 J2[srow+1] = -ax1[1]; 206 J2[srow+2] = -ax1[2]; 207 btScalar k = info->fps * m_biasFactor; 208 info->m_constraintError[srow] = k * m_twistCorrection; 209 info->cfm[srow] = 0.0f; 210 if(m_twistSpan > 0.0f) 211 { 212 213 if(m_twistCorrection > 0.0f) 214 { 215 info->m_lowerLimit[srow] = 0; 216 info->m_upperLimit[srow] = SIMD_INFINITY; 217 } 218 else 219 { 220 info->m_lowerLimit[srow] = -SIMD_INFINITY; 221 info->m_upperLimit[srow] = 0; 222 } 223 } 224 else 225 { 226 info->m_lowerLimit[srow] = -SIMD_INFINITY; 227 info->m_upperLimit[srow] = SIMD_INFINITY; 228 } 229 srow += info->rowskip; 230 } 231 } 61 232 62 } 233 //----------------------------------------------------------------------------- 63 234 64 235 void btConeTwistConstraint::buildJacobian() 65 236 { 66 m_appliedImpulse = btScalar(0.); 67 68 //set bias, sign, clear accumulator 69 m_swingCorrection = btScalar(0.); 70 m_twistLimitSign = btScalar(0.); 71 m_solveTwistLimit = false; 72 m_solveSwingLimit = false; 73 m_accTwistLimitImpulse = btScalar(0.); 74 m_accSwingLimitImpulse = btScalar(0.); 75 76 if (!m_angularOnly) 77 { 78 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); 79 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); 80 btVector3 relPos = pivotBInW - pivotAInW; 81 82 btVector3 normal[3]; 83 if (relPos.length2() > SIMD_EPSILON) 84 { 85 normal[0] = relPos.normalized(); 86 } 87 else 88 { 89 normal[0].setValue(btScalar(1.0),0,0); 90 } 91 92 btPlaneSpace1(normal[0], normal[1], normal[2]); 93 94 for (int i=0;i<3;i++) 95 { 96 new (&m_jac[i]) btJacobianEntry( 237 if (m_useSolveConstraintObsolete) 238 { 239 m_appliedImpulse = btScalar(0.); 240 m_accTwistLimitImpulse = btScalar(0.); 241 m_accSwingLimitImpulse = btScalar(0.); 242 243 if (!m_angularOnly) 244 { 245 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); 246 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); 247 btVector3 relPos = pivotBInW - pivotAInW; 248 249 btVector3 normal[3]; 250 if (relPos.length2() > SIMD_EPSILON) 251 { 252 normal[0] = relPos.normalized(); 253 } 254 else 255 { 256 normal[0].setValue(btScalar(1.0),0,0); 257 } 258 259 btPlaneSpace1(normal[0], normal[1], normal[2]); 260 261 for (int i=0;i<3;i++) 262 { 263 new (&m_jac[i]) btJacobianEntry( 97 264 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 98 265 m_rbB.getCenterOfMassTransform().getBasis().transpose(), … … 104 271 m_rbB.getInvInertiaDiagLocal(), 105 272 m_rbB.getInvMass()); 106 } 107 } 273 } 274 } 275 276 calcAngleInfo2(); 277 } 278 } 279 280 //----------------------------------------------------------------------------- 281 282 void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) 283 { 284 if (m_useSolveConstraintObsolete) 285 { 286 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); 287 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); 288 289 btScalar tau = btScalar(0.3); 290 291 //linear part 292 if (!m_angularOnly) 293 { 294 btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 295 btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 296 297 btVector3 vel1; 298 bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); 299 btVector3 vel2; 300 bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); 301 btVector3 vel = vel1 - vel2; 302 303 for (int i=0;i<3;i++) 304 { 305 const btVector3& normal = m_jac[i].m_linearJointAxis; 306 btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); 307 308 btScalar rel_vel; 309 rel_vel = normal.dot(vel); 310 //positional error (zeroth order error) 311 btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal 312 btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; 313 m_appliedImpulse += impulse; 314 315 btVector3 ftorqueAxis1 = rel_pos1.cross(normal); 316 btVector3 ftorqueAxis2 = rel_pos2.cross(normal); 317 bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); 318 bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); 319 320 } 321 } 322 323 // apply motor 324 if (m_bMotorEnabled) 325 { 326 // compute current and predicted transforms 327 btTransform trACur = m_rbA.getCenterOfMassTransform(); 328 btTransform trBCur = m_rbB.getCenterOfMassTransform(); 329 btVector3 omegaA; bodyA.getAngularVelocity(omegaA); 330 btVector3 omegaB; bodyB.getAngularVelocity(omegaB); 331 btTransform trAPred; trAPred.setIdentity(); 332 btVector3 zerovec(0,0,0); 333 btTransformUtil::integrateTransform( 334 trACur, zerovec, omegaA, timeStep, trAPred); 335 btTransform trBPred; trBPred.setIdentity(); 336 btTransformUtil::integrateTransform( 337 trBCur, zerovec, omegaB, timeStep, trBPred); 338 339 // compute desired transforms in world 340 btTransform trPose(m_qTarget); 341 btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse(); 342 btTransform trADes = trBPred * trABDes; 343 btTransform trBDes = trAPred * trABDes.inverse(); 344 345 // compute desired omegas in world 346 btVector3 omegaADes, omegaBDes; 347 348 btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes); 349 btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes); 350 351 // compute delta omegas 352 btVector3 dOmegaA = omegaADes - omegaA; 353 btVector3 dOmegaB = omegaBDes - omegaB; 354 355 // compute weighted avg axis of dOmega (weighting based on inertias) 356 btVector3 axisA, axisB; 357 btScalar kAxisAInv = 0, kAxisBInv = 0; 358 359 if (dOmegaA.length2() > SIMD_EPSILON) 360 { 361 axisA = dOmegaA.normalized(); 362 kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA); 363 } 364 365 if (dOmegaB.length2() > SIMD_EPSILON) 366 { 367 axisB = dOmegaB.normalized(); 368 kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB); 369 } 370 371 btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB; 372 373 static bool bDoTorque = true; 374 if (bDoTorque && avgAxis.length2() > SIMD_EPSILON) 375 { 376 avgAxis.normalize(); 377 kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis); 378 kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis); 379 btScalar kInvCombined = kAxisAInv + kAxisBInv; 380 381 btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) / 382 (kInvCombined * kInvCombined); 383 384 if (m_maxMotorImpulse >= 0) 385 { 386 btScalar fMaxImpulse = m_maxMotorImpulse; 387 if (m_bNormalizedMotorStrength) 388 fMaxImpulse = fMaxImpulse/kAxisAInv; 389 390 btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse; 391 btScalar newUnclampedMag = newUnclampedAccImpulse.length(); 392 if (newUnclampedMag > fMaxImpulse) 393 { 394 newUnclampedAccImpulse.normalize(); 395 newUnclampedAccImpulse *= fMaxImpulse; 396 impulse = newUnclampedAccImpulse - m_accMotorImpulse; 397 } 398 m_accMotorImpulse += impulse; 399 } 400 401 btScalar impulseMag = impulse.length(); 402 btVector3 impulseAxis = impulse / impulseMag; 403 404 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); 405 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); 406 407 } 408 } 409 else // no motor: do a little damping 410 { 411 const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); 412 const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); 413 btVector3 relVel = angVelB - angVelA; 414 if (relVel.length2() > SIMD_EPSILON) 415 { 416 btVector3 relVelAxis = relVel.normalized(); 417 btScalar m_kDamping = btScalar(1.) / 418 (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) + 419 getRigidBodyB().computeAngularImpulseDenominator(relVelAxis)); 420 btVector3 impulse = m_damping * m_kDamping * relVel; 421 422 btScalar impulseMag = impulse.length(); 423 btVector3 impulseAxis = impulse / impulseMag; 424 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); 425 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); 426 } 427 } 428 429 // joint limits 430 { 431 ///solve angular part 432 btVector3 angVelA; 433 bodyA.getAngularVelocity(angVelA); 434 btVector3 angVelB; 435 bodyB.getAngularVelocity(angVelB); 436 437 // solve swing limit 438 if (m_solveSwingLimit) 439 { 440 btScalar amplitude = m_swingLimitRatio * m_swingCorrection*m_biasFactor/timeStep; 441 btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis); 442 if (relSwingVel > 0) 443 amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor; 444 btScalar impulseMag = amplitude * m_kSwing; 445 446 // Clamp the accumulated impulse 447 btScalar temp = m_accSwingLimitImpulse; 448 m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); 449 impulseMag = m_accSwingLimitImpulse - temp; 450 451 btVector3 impulse = m_swingAxis * impulseMag; 452 453 // don't let cone response affect twist 454 // (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit) 455 { 456 btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA; 457 btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple; 458 impulse = impulseNoTwistCouple; 459 } 460 461 impulseMag = impulse.length(); 462 btVector3 noTwistSwingAxis = impulse / impulseMag; 463 464 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*noTwistSwingAxis, impulseMag); 465 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*noTwistSwingAxis, -impulseMag); 466 } 467 468 469 // solve twist limit 470 if (m_solveTwistLimit) 471 { 472 btScalar amplitude = m_twistLimitRatio * m_twistCorrection*m_biasFactor/timeStep; 473 btScalar relTwistVel = (angVelB - angVelA).dot( m_twistAxis ); 474 if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important) 475 amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor; 476 btScalar impulseMag = amplitude * m_kTwist; 477 478 // Clamp the accumulated impulse 479 btScalar temp = m_accTwistLimitImpulse; 480 m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); 481 impulseMag = m_accTwistLimitImpulse - temp; 482 483 btVector3 impulse = m_twistAxis * impulseMag; 484 485 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag); 486 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag); 487 } 488 } 489 } 490 491 } 492 493 //----------------------------------------------------------------------------- 494 495 void btConeTwistConstraint::updateRHS(btScalar timeStep) 496 { 497 (void)timeStep; 498 499 } 500 501 //----------------------------------------------------------------------------- 502 503 void btConeTwistConstraint::calcAngleInfo() 504 { 505 m_swingCorrection = btScalar(0.); 506 m_twistLimitSign = btScalar(0.); 507 m_solveTwistLimit = false; 508 m_solveSwingLimit = false; 108 509 109 510 btVector3 b1Axis1,b1Axis2,b1Axis3; … … 123 524 { 124 525 b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); 125 // swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) );126 526 swx = b2Axis1.dot(b1Axis1); 127 527 swy = b2Axis1.dot(b1Axis2); … … 130 530 fact = fact / (fact + btScalar(1.0)); 131 531 swing1 *= fact; 132 133 532 } 134 533 … … 136 535 { 137 536 b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); 138 // swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) );139 537 swx = b2Axis1.dot(b1Axis1); 140 538 swy = b2Axis1.dot(b1Axis3); … … 153 551 m_swingCorrection = EllipseAngle-1.0f; 154 552 m_solveSwingLimit = true; 155 156 553 // Calculate necessary axis & factors 157 554 m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3)); 158 555 m_swingAxis.normalize(); 159 160 556 btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; 161 557 m_swingAxis *= swingAxisSign; 162 163 m_kSwing = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_swingAxis) +164 getRigidBodyB().computeAngularImpulseDenominator(m_swingAxis));165 166 558 } 167 559 … … 173 565 btVector3 TwistRef = quatRotate(rotationArc,b2Axis2); 174 566 btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) ); 175 176 btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); 567 m_twistAngle = twist; 568 569 // btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); 570 btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.); 177 571 if (twist <= -m_twistSpan*lockedFreeFactor) 178 572 { 179 573 m_twistCorrection = -(twist + m_twistSpan); 180 574 m_solveTwistLimit = true; 181 182 575 m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; 183 576 m_twistAxis.normalize(); 184 577 m_twistAxis *= -1.0f; 185 186 m_kTwist = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + 187 getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); 188 189 } else 190 if (twist > m_twistSpan*lockedFreeFactor) 191 { 192 m_twistCorrection = (twist - m_twistSpan); 578 } 579 else if (twist > m_twistSpan*lockedFreeFactor) 580 { 581 m_twistCorrection = (twist - m_twistSpan); 582 m_solveTwistLimit = true; 583 m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; 584 m_twistAxis.normalize(); 585 } 586 } 587 } // btConeTwistConstraint::calcAngleInfo() 588 589 590 static btVector3 vTwist(1,0,0); // twist axis in constraint's space 591 592 //----------------------------------------------------------------------------- 593 594 void btConeTwistConstraint::calcAngleInfo2() 595 { 596 m_swingCorrection = btScalar(0.); 597 m_twistLimitSign = btScalar(0.); 598 m_solveTwistLimit = false; 599 m_solveSwingLimit = false; 600 601 { 602 // compute rotation of A wrt B (in constraint space) 603 btQuaternion qA = getRigidBodyA().getCenterOfMassTransform().getRotation() * m_rbAFrame.getRotation(); 604 btQuaternion qB = getRigidBodyB().getCenterOfMassTransform().getRotation() * m_rbBFrame.getRotation(); 605 btQuaternion qAB = qB.inverse() * qA; 606 607 // split rotation into cone and twist 608 // (all this is done from B's perspective. Maybe I should be averaging axes...) 609 btVector3 vConeNoTwist = quatRotate(qAB, vTwist); vConeNoTwist.normalize(); 610 btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist); qABCone.normalize(); 611 btQuaternion qABTwist = qABCone.inverse() * qAB; qABTwist.normalize(); 612 613 if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh) 614 { 615 btScalar swingAngle, swingLimit = 0; btVector3 swingAxis; 616 computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit); 617 618 if (swingAngle > swingLimit * m_limitSoftness) 619 { 620 m_solveSwingLimit = true; 621 622 // compute limit ratio: 0->1, where 623 // 0 == beginning of soft limit 624 // 1 == hard/real limit 625 m_swingLimitRatio = 1.f; 626 if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON) 627 { 628 m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness)/ 629 (swingLimit - swingLimit * m_limitSoftness); 630 } 631 632 // swing correction tries to get back to soft limit 633 m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness); 634 635 // adjustment of swing axis (based on ellipse normal) 636 adjustSwingAxisToUseEllipseNormal(swingAxis); 637 638 // Calculate necessary axis & factors 639 m_swingAxis = quatRotate(qB, -swingAxis); 640 641 m_twistAxisA.setValue(0,0,0); 642 643 m_kSwing = btScalar(1.) / 644 (getRigidBodyA().computeAngularImpulseDenominator(m_swingAxis) + 645 getRigidBodyB().computeAngularImpulseDenominator(m_swingAxis)); 646 } 647 } 648 else 649 { 650 // you haven't set any limits; 651 // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?) 652 // anyway, we have either hinge or fixed joint 653 btVector3 ivA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); 654 btVector3 jvA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); 655 btVector3 kvA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 656 btVector3 ivB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(0); 657 btVector3 target; 658 btScalar x = ivB.dot(ivA); 659 btScalar y = ivB.dot(jvA); 660 btScalar z = ivB.dot(kvA); 661 if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) 662 { // fixed. We'll need to add one more row to constraint 663 if((!btFuzzyZero(y)) || (!(btFuzzyZero(z)))) 664 { 665 m_solveSwingLimit = true; 666 m_swingAxis = -ivB.cross(ivA); 667 } 668 } 669 else 670 { 671 if(m_swingSpan1 < m_fixThresh) 672 { // hinge around Y axis 673 if(!(btFuzzyZero(y))) 674 { 675 m_solveSwingLimit = true; 676 if(m_swingSpan2 >= m_fixThresh) 677 { 678 y = btScalar(0.f); 679 btScalar span2 = btAtan2(z, x); 680 if(span2 > m_swingSpan2) 681 { 682 x = btCos(m_swingSpan2); 683 z = btSin(m_swingSpan2); 684 } 685 else if(span2 < -m_swingSpan2) 686 { 687 x = btCos(m_swingSpan2); 688 z = -btSin(m_swingSpan2); 689 } 690 } 691 } 692 } 693 else 694 { // hinge around Z axis 695 if(!btFuzzyZero(z)) 696 { 697 m_solveSwingLimit = true; 698 if(m_swingSpan1 >= m_fixThresh) 699 { 700 z = btScalar(0.f); 701 btScalar span1 = btAtan2(y, x); 702 if(span1 > m_swingSpan1) 703 { 704 x = btCos(m_swingSpan1); 705 y = btSin(m_swingSpan1); 706 } 707 else if(span1 < -m_swingSpan1) 708 { 709 x = btCos(m_swingSpan1); 710 y = -btSin(m_swingSpan1); 711 } 712 } 713 } 714 } 715 target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0]; 716 target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1]; 717 target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2]; 718 target.normalize(); 719 m_swingAxis = -ivB.cross(target); 720 m_swingCorrection = m_swingAxis.length(); 721 m_swingAxis.normalize(); 722 } 723 } 724 725 if (m_twistSpan >= btScalar(0.f)) 726 { 727 btVector3 twistAxis; 728 computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis); 729 730 if (m_twistAngle > m_twistSpan*m_limitSoftness) 731 { 193 732 m_solveTwistLimit = true; 194 733 195 m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; 196 m_twistAxis.normalize(); 197 198 m_kTwist = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + 199 getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); 200 201 } 202 } 203 } 204 205 void btConeTwistConstraint::solveConstraint(btScalar timeStep) 206 { 207 208 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); 209 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); 210 211 btScalar tau = btScalar(0.3); 212 213 //linear part 214 if (!m_angularOnly) 215 { 216 btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 217 btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 218 219 btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); 220 btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); 221 btVector3 vel = vel1 - vel2; 222 223 for (int i=0;i<3;i++) 224 { 225 const btVector3& normal = m_jac[i].m_linearJointAxis; 226 btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); 227 228 btScalar rel_vel; 229 rel_vel = normal.dot(vel); 230 //positional error (zeroth order error) 231 btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal 232 btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; 233 m_appliedImpulse += impulse; 234 btVector3 impulse_vector = normal * impulse; 235 m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); 236 m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); 237 } 238 } 239 240 { 241 ///solve angular part 242 const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); 243 const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); 244 245 // solve swing limit 246 if (m_solveSwingLimit) 247 { 248 btScalar amplitude = ((angVelB - angVelA).dot( m_swingAxis )*m_relaxationFactor*m_relaxationFactor + m_swingCorrection*(btScalar(1.)/timeStep)*m_biasFactor); 249 btScalar impulseMag = amplitude * m_kSwing; 250 251 // Clamp the accumulated impulse 252 btScalar temp = m_accSwingLimitImpulse; 253 m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); 254 impulseMag = m_accSwingLimitImpulse - temp; 255 256 btVector3 impulse = m_swingAxis * impulseMag; 257 258 m_rbA.applyTorqueImpulse(impulse); 259 m_rbB.applyTorqueImpulse(-impulse); 260 261 } 262 263 // solve twist limit 264 if (m_solveTwistLimit) 265 { 266 btScalar amplitude = ((angVelB - angVelA).dot( m_twistAxis )*m_relaxationFactor*m_relaxationFactor + m_twistCorrection*(btScalar(1.)/timeStep)*m_biasFactor ); 267 btScalar impulseMag = amplitude * m_kTwist; 268 269 // Clamp the accumulated impulse 270 btScalar temp = m_accTwistLimitImpulse; 271 m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); 272 impulseMag = m_accTwistLimitImpulse - temp; 273 274 btVector3 impulse = m_twistAxis * impulseMag; 275 276 m_rbA.applyTorqueImpulse(impulse); 277 m_rbB.applyTorqueImpulse(-impulse); 278 279 } 280 281 } 282 283 } 284 285 void btConeTwistConstraint::updateRHS(btScalar timeStep) 286 { 287 (void)timeStep; 288 289 } 734 m_twistLimitRatio = 1.f; 735 if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON) 736 { 737 m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness)/ 738 (m_twistSpan - m_twistSpan * m_limitSoftness); 739 } 740 741 // twist correction tries to get back to soft limit 742 m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness); 743 744 m_twistAxis = quatRotate(qB, -twistAxis); 745 746 m_kTwist = btScalar(1.) / 747 (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + 748 getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); 749 } 750 751 if (m_solveSwingLimit) 752 m_twistAxisA = quatRotate(qA, -twistAxis); 753 } 754 else 755 { 756 m_twistAngle = btScalar(0.f); 757 } 758 } 759 } // btConeTwistConstraint::calcAngleInfo2() 760 761 762 763 // given a cone rotation in constraint space, (pre: twist must already be removed) 764 // this method computes its corresponding swing angle and axis. 765 // more interestingly, it computes the cone/swing limit (angle) for this cone "pose". 766 void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, 767 btScalar& swingAngle, // out 768 btVector3& vSwingAxis, // out 769 btScalar& swingLimit) // out 770 { 771 swingAngle = qCone.getAngle(); 772 if (swingAngle > SIMD_EPSILON) 773 { 774 vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z()); 775 vSwingAxis.normalize(); 776 if (fabs(vSwingAxis.x()) > SIMD_EPSILON) 777 { 778 // non-zero twist?! this should never happen. 779 int wtf = 0; wtf = wtf; 780 } 781 782 // Compute limit for given swing. tricky: 783 // Given a swing axis, we're looking for the intersection with the bounding cone ellipse. 784 // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.) 785 786 // For starters, compute the direction from center to surface of ellipse. 787 // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis. 788 // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.) 789 btScalar xEllipse = vSwingAxis.y(); 790 btScalar yEllipse = -vSwingAxis.z(); 791 792 // Now, we use the slope of the vector (using x/yEllipse) and find the length 793 // of the line that intersects the ellipse: 794 // x^2 y^2 795 // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits) 796 // a^2 b^2 797 // Do the math and it should be clear. 798 799 swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1 800 if (fabs(xEllipse) > SIMD_EPSILON) 801 { 802 btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); 803 btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); 804 norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); 805 btScalar swingLimit2 = (1 + surfaceSlope2) / norm; 806 swingLimit = sqrt(swingLimit2); 807 } 808 809 // test! 810 /*swingLimit = m_swingSpan2; 811 if (fabs(vSwingAxis.z()) > SIMD_EPSILON) 812 { 813 btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2; 814 btScalar sinphi = m_swingSpan2 / sqrt(mag_2); 815 btScalar phi = asin(sinphi); 816 btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z())); 817 btScalar alpha = 3.14159f - theta - phi; 818 btScalar sinalpha = sin(alpha); 819 swingLimit = m_swingSpan1 * sinphi/sinalpha; 820 }*/ 821 } 822 else if (swingAngle < 0) 823 { 824 // this should never happen! 825 int wtf = 0; wtf = wtf; 826 } 827 } 828 829 btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const 830 { 831 // compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone) 832 btScalar xEllipse = btCos(fAngleInRadians); 833 btScalar yEllipse = btSin(fAngleInRadians); 834 835 // Use the slope of the vector (using x/yEllipse) and find the length 836 // of the line that intersects the ellipse: 837 // x^2 y^2 838 // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits) 839 // a^2 b^2 840 // Do the math and it should be clear. 841 842 float swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1) 843 if (fabs(xEllipse) > SIMD_EPSILON) 844 { 845 btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); 846 btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); 847 norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); 848 btScalar swingLimit2 = (1 + surfaceSlope2) / norm; 849 swingLimit = sqrt(swingLimit2); 850 } 851 852 // convert into point in constraint space: 853 // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively 854 btVector3 vSwingAxis(0, xEllipse, -yEllipse); 855 btQuaternion qSwing(vSwingAxis, swingLimit); 856 btVector3 vPointInConstraintSpace(fLength,0,0); 857 return quatRotate(qSwing, vPointInConstraintSpace); 858 } 859 860 // given a twist rotation in constraint space, (pre: cone must already be removed) 861 // this method computes its corresponding angle and axis. 862 void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist, 863 btScalar& twistAngle, // out 864 btVector3& vTwistAxis) // out 865 { 866 btQuaternion qMinTwist = qTwist; 867 twistAngle = qTwist.getAngle(); 868 869 if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate. 870 { 871 qMinTwist = operator-(qTwist); 872 twistAngle = qMinTwist.getAngle(); 873 } 874 if (twistAngle < 0) 875 { 876 // this should never happen 877 int wtf = 0; wtf = wtf; 878 } 879 880 vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z()); 881 if (twistAngle > SIMD_EPSILON) 882 vTwistAxis.normalize(); 883 } 884 885 886 void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const 887 { 888 // the swing axis is computed as the "twist-free" cone rotation, 889 // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2). 890 // so, if we're outside the limits, the closest way back inside the cone isn't 891 // along the vector back to the center. better (and more stable) to use the ellipse normal. 892 893 // convert swing axis to direction from center to surface of ellipse 894 // (ie. rotate 2D vector by PI/2) 895 btScalar y = -vSwingAxis.z(); 896 btScalar z = vSwingAxis.y(); 897 898 // do the math... 899 if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0. 900 { 901 // compute gradient/normal of ellipse surface at current "point" 902 btScalar grad = y/z; 903 grad *= m_swingSpan2 / m_swingSpan1; 904 905 // adjust y/z to represent normal at point (instead of vector to point) 906 if (y > 0) 907 y = fabs(grad * z); 908 else 909 y = -fabs(grad * z); 910 911 // convert ellipse direction back to swing axis 912 vSwingAxis.setZ(-y); 913 vSwingAxis.setY( z); 914 vSwingAxis.normalize(); 915 } 916 } 917 918 919 920 void btConeTwistConstraint::setMotorTarget(const btQuaternion &q) 921 { 922 btTransform trACur = m_rbA.getCenterOfMassTransform(); 923 btTransform trBCur = m_rbB.getCenterOfMassTransform(); 924 btTransform trABCur = trBCur.inverse() * trACur; 925 btQuaternion qABCur = trABCur.getRotation(); 926 btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame); 927 btQuaternion qConstraintCur = trConstraintCur.getRotation(); 928 929 btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation(); 930 setMotorTargetInConstraintSpace(qConstraint); 931 } 932 933 934 void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &q) 935 { 936 m_qTarget = q; 937 938 // clamp motor target to within limits 939 { 940 btScalar softness = 1.f;//m_limitSoftness; 941 942 // split into twist and cone 943 btVector3 vTwisted = quatRotate(m_qTarget, vTwist); 944 btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted); qTargetCone.normalize(); 945 btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; qTargetTwist.normalize(); 946 947 // clamp cone 948 if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f)) 949 { 950 btScalar swingAngle, swingLimit; btVector3 swingAxis; 951 computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit); 952 953 if (fabs(swingAngle) > SIMD_EPSILON) 954 { 955 if (swingAngle > swingLimit*softness) 956 swingAngle = swingLimit*softness; 957 else if (swingAngle < -swingLimit*softness) 958 swingAngle = -swingLimit*softness; 959 qTargetCone = btQuaternion(swingAxis, swingAngle); 960 } 961 } 962 963 // clamp twist 964 if (m_twistSpan >= btScalar(0.05f)) 965 { 966 btScalar twistAngle; btVector3 twistAxis; 967 computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis); 968 969 if (fabs(twistAngle) > SIMD_EPSILON) 970 { 971 // eddy todo: limitSoftness used here??? 972 if (twistAngle > m_twistSpan*softness) 973 twistAngle = m_twistSpan*softness; 974 else if (twistAngle < -m_twistSpan*softness) 975 twistAngle = -m_twistSpan*softness; 976 qTargetTwist = btQuaternion(twistAxis, twistAngle); 977 } 978 } 979 980 m_qTarget = qTargetCone * qTargetTwist; 981 } 982 } 983 984 985 //----------------------------------------------------------------------------- 986 //----------------------------------------------------------------------------- 987 //----------------------------------------------------------------------------- 988 989 -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
r2662 r2882 43 43 btScalar m_relaxationFactor; 44 44 45 btScalar m_damping; 46 45 47 btScalar m_swingSpan1; 46 48 btScalar m_swingSpan2; 47 49 btScalar m_twistSpan; 48 50 51 btScalar m_fixThresh; 52 49 53 btVector3 m_swingAxis; 50 54 btVector3 m_twistAxis; … … 57 61 btScalar m_twistCorrection; 58 62 63 btScalar m_twistAngle; 64 59 65 btScalar m_accSwingLimitImpulse; 60 66 btScalar m_accTwistLimitImpulse; … … 64 70 bool m_solveSwingLimit; 65 71 72 bool m_useSolveConstraintObsolete; 73 74 // not yet used... 75 btScalar m_swingLimitRatio; 76 btScalar m_twistLimitRatio; 77 btVector3 m_twistAxisA; 78 79 // motor 80 bool m_bMotorEnabled; 81 bool m_bNormalizedMotorStrength; 82 btQuaternion m_qTarget; 83 btScalar m_maxMotorImpulse; 84 btVector3 m_accMotorImpulse; 66 85 67 86 public: … … 75 94 virtual void buildJacobian(); 76 95 77 virtual void solveConstraint(btScalar timeStep); 96 virtual void getInfo1 (btConstraintInfo1* info); 97 98 virtual void getInfo2 (btConstraintInfo2* info); 99 100 101 virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); 78 102 79 103 void updateRHS(btScalar timeStep); … … 93 117 } 94 118 95 void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 0.8f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) 119 void setLimit(int limitIndex,btScalar limitValue) 120 { 121 switch (limitIndex) 122 { 123 case 3: 124 { 125 m_twistSpan = limitValue; 126 break; 127 } 128 case 4: 129 { 130 m_swingSpan2 = limitValue; 131 break; 132 } 133 case 5: 134 { 135 m_swingSpan1 = limitValue; 136 break; 137 } 138 default: 139 { 140 } 141 }; 142 } 143 144 void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) 96 145 { 97 146 m_swingSpan1 = _swingSpan1; … … 122 171 } 123 172 173 void calcAngleInfo(); 174 void calcAngleInfo2(); 175 176 inline btScalar getSwingSpan1() 177 { 178 return m_swingSpan1; 179 } 180 inline btScalar getSwingSpan2() 181 { 182 return m_swingSpan2; 183 } 184 inline btScalar getTwistSpan() 185 { 186 return m_twistSpan; 187 } 188 inline btScalar getTwistAngle() 189 { 190 return m_twistAngle; 191 } 192 bool isPastSwingLimit() { return m_solveSwingLimit; } 193 194 195 void setDamping(btScalar damping) { m_damping = damping; } 196 197 void enableMotor(bool b) { m_bMotorEnabled = b; } 198 void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; } 199 void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; } 200 201 btScalar getFixThresh() { return m_fixThresh; } 202 void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; } 203 204 // setMotorTarget: 205 // q: the desired rotation of bodyA wrt bodyB. 206 // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability) 207 // note: don't forget to enableMotor() 208 void setMotorTarget(const btQuaternion &q); 209 210 // same as above, but q is the desired rotation of frameA wrt frameB in constraint space 211 void setMotorTargetInConstraintSpace(const btQuaternion &q); 212 213 btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const; 214 215 216 217 protected: 218 void init(); 219 220 void computeConeLimitInfo(const btQuaternion& qCone, // in 221 btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs 222 223 void computeTwistLimitInfo(const btQuaternion& qTwist, // in 224 btScalar& twistAngle, btVector3& vTwistAxis); // all outs 225 226 void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const; 124 227 }; 125 228 -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
r2662 r2882 23 23 #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" 24 24 25 #define ASSERT2 assert25 #define ASSERT2 btAssert 26 26 27 27 #define USE_INTERNAL_APPLY_IMPULSE 1 … … 53 53 54 54 55 btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),55 btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), 56 56 body2.getCenterOfMassTransform().getBasis().transpose(), 57 57 rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(), … … 115 115 116 116 btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; 117 assert(cpd);117 btAssert(cpd); 118 118 btScalar distance = cpd->m_penetration; 119 119 btScalar positionalError = Kcor *-distance; … … 167 167 168 168 btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; 169 assert(cpd);169 btAssert(cpd); 170 170 171 171 btScalar combinedFriction = cpd->m_friction; … … 256 256 257 257 btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; 258 assert(cpd);258 btAssert(cpd); 259 259 260 260 btScalar combinedFriction = cpd->m_friction; … … 338 338 339 339 btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; 340 assert(cpd);340 btAssert(cpd); 341 341 btScalar distance = cpd->m_penetration; 342 342 btScalar positionalError = Kcor *-distance; -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
r2662 r2882 23 23 SOLVER_USE_WARMSTARTING = 4, 24 24 SOLVER_USE_FRICTION_WARMSTARTING = 8, 25 SOLVER_CACHE_FRIENDLY = 16 25 SOLVER_USE_2_FRICTION_DIRECTIONS = 16, 26 SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32, 27 SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64, 28 SOLVER_CACHE_FRIENDLY = 128, 29 SOLVER_SIMD = 256, //enabled for Windows, the solver innerloop is branchless SIMD, 40% faster than FPU/scalar version 30 SOLVER_CUDA = 512 //will be open sourced during Game Developers Conference 2009. Much faster. 26 31 }; 27 32 … … 40 45 btScalar m_erp;//used as Baumgarte factor 41 46 btScalar m_erp2;//used in Split Impulse 47 btScalar m_globalCfm;//constraint force mixing 42 48 int m_splitImpulse; 43 49 btScalar m_splitImpulsePenetrationThreshold; … … 66 72 m_erp = btScalar(0.2); 67 73 m_erp2 = btScalar(0.1); 68 m_sor = btScalar(1.3); 74 m_globalCfm = btScalar(0.); 75 m_sor = btScalar(1.); 69 76 m_splitImpulse = false; 70 77 m_splitImpulsePenetrationThreshold = -0.02f; 71 78 m_linearSlop = btScalar(0.0); 72 79 m_warmstartingFactor=btScalar(0.85); 73 m_solverMode = SOLVER_ CACHE_FRIENDLY | SOLVER_RANDMIZE_ORDER | SOLVER_USE_WARMSTARTING;80 m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD ;//SOLVER_RANDMIZE_ORDER 74 81 m_restingContactRestitutionThreshold = 2;//resting contact lifetime threshold to disable restitution 75 82 } -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
r2662 r2882 20 20 */ 21 21 22 23 22 #include "btGeneric6DofConstraint.h" 24 23 #include "BulletDynamics/Dynamics/btRigidBody.h" … … 27 26 28 27 28 #define D6_USE_OBSOLETE_METHOD false 29 //----------------------------------------------------------------------------- 30 31 btGeneric6DofConstraint::btGeneric6DofConstraint() 32 :btTypedConstraint(D6_CONSTRAINT_TYPE), 33 m_useLinearReferenceFrameA(true), 34 m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) 35 { 36 } 37 38 //----------------------------------------------------------------------------- 39 40 btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) 41 : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) 42 , m_frameInA(frameInA) 43 , m_frameInB(frameInB), 44 m_useLinearReferenceFrameA(useLinearReferenceFrameA), 45 m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) 46 { 47 48 } 49 //----------------------------------------------------------------------------- 50 51 29 52 #define GENERIC_D6_DISABLE_WARMSTARTING 1 53 54 //----------------------------------------------------------------------------- 30 55 31 56 btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); … … 37 62 } 38 63 64 //----------------------------------------------------------------------------- 65 39 66 ///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html 40 67 bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); 41 68 bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) 42 69 { 43 // // rot = cy*cz -cy*sz sy 44 // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx 45 // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy 46 // 47 48 if (btGetMatrixElem(mat,2) < btScalar(1.0)) 49 { 50 if (btGetMatrixElem(mat,2) > btScalar(-1.0)) 51 { 52 xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); 53 xyz[1] = btAsin(btGetMatrixElem(mat,2)); 54 xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); 55 return true; 56 } 57 else 58 { 59 // WARNING. Not unique. XA - ZA = -atan2(r10,r11) 60 xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); 61 xyz[1] = -SIMD_HALF_PI; 62 xyz[2] = btScalar(0.0); 63 return false; 64 } 70 // // rot = cy*cz -cy*sz sy 71 // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx 72 // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy 73 // 74 75 btScalar fi = btGetMatrixElem(mat,2); 76 if (fi < btScalar(1.0f)) 77 { 78 if (fi > btScalar(-1.0f)) 79 { 80 xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); 81 xyz[1] = btAsin(btGetMatrixElem(mat,2)); 82 xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); 83 return true; 65 84 } 66 85 else 67 86 { 68 // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) 69 xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); 70 xyz[1] = SIMD_HALF_PI; 71 xyz[2] = 0.0; 72 73 } 74 75 87 // WARNING. Not unique. XA - ZA = -atan2(r10,r11) 88 xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); 89 xyz[1] = -SIMD_HALF_PI; 90 xyz[2] = btScalar(0.0); 91 return false; 92 } 93 } 94 else 95 { 96 // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) 97 xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); 98 xyz[1] = SIMD_HALF_PI; 99 xyz[2] = 0.0; 100 } 76 101 return false; 77 102 } 78 103 79 80 81 104 //////////////////////////// btRotationalLimitMotor //////////////////////////////////// 82 83 105 84 106 int btRotationalLimitMotor::testLimitValue(btScalar test_value) … … 105 127 m_currentLimit = 0;//Free from violation 106 128 return 0; 107 108 } 109 129 130 } 131 132 //----------------------------------------------------------------------------- 110 133 111 134 btScalar btRotationalLimitMotor::solveAngularLimits( 112 113 btRigidBody * body0, btRigidBody * body1)114 { 115 116 117 118 135 btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, 136 btRigidBody * body0, btSolverBody& bodyA, btRigidBody * body1, btSolverBody& bodyB) 137 { 138 if (needApplyTorques()==false) return 0.0f; 139 140 btScalar target_velocity = m_targetVelocity; 141 btScalar maxMotorForce = m_maxMotorForce; 119 142 120 143 //current error correction 121 if (m_currentLimit!=0) 122 { 123 target_velocity = -m_ERP*m_currentLimitError/(timeStep); 124 maxMotorForce = m_maxLimitForce; 125 } 126 127 maxMotorForce *= timeStep; 128 129 // current velocity difference 130 btVector3 vel_diff = body0->getAngularVelocity(); 131 if (body1) 132 { 133 vel_diff -= body1->getAngularVelocity(); 134 } 135 136 137 138 btScalar rel_vel = axis.dot(vel_diff); 144 if (m_currentLimit!=0) 145 { 146 target_velocity = -m_ERP*m_currentLimitError/(timeStep); 147 maxMotorForce = m_maxLimitForce; 148 } 149 150 maxMotorForce *= timeStep; 151 152 // current velocity difference 153 154 btVector3 angVelA; 155 bodyA.getAngularVelocity(angVelA); 156 btVector3 angVelB; 157 bodyB.getAngularVelocity(angVelB); 158 159 btVector3 vel_diff; 160 vel_diff = angVelA-angVelB; 161 162 163 164 btScalar rel_vel = axis.dot(vel_diff); 139 165 140 166 // correction velocity 141 142 143 144 145 146 147 167 btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); 168 169 170 if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) 171 { 172 return 0.0f;//no need for applying force 173 } 148 174 149 175 150 176 // correction impulse 151 177 btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; 152 178 153 179 // clip correction impulse 154 155 156 157 158 159 160 161 162 163 164 180 btScalar clippedMotorImpulse; 181 182 ///@todo: should clip against accumulated impulse 183 if (unclippedMotorImpulse>0.0f) 184 { 185 clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; 186 } 187 else 188 { 189 clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; 190 } 165 191 166 192 167 193 // sort with accumulated impulses 168 btScalar lo = btScalar(-1e30); 169 btScalar hi = btScalar(1e30); 170 171 btScalar oldaccumImpulse = m_accumulatedImpulse; 172 btScalar sum = oldaccumImpulse + clippedMotorImpulse; 173 m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; 174 175 clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; 176 177 178 179 btVector3 motorImp = clippedMotorImpulse * axis; 180 181 182 body0->applyTorqueImpulse(motorImp); 183 if (body1) body1->applyTorqueImpulse(-motorImp); 184 185 return clippedMotorImpulse; 194 btScalar lo = btScalar(-1e30); 195 btScalar hi = btScalar(1e30); 196 197 btScalar oldaccumImpulse = m_accumulatedImpulse; 198 btScalar sum = oldaccumImpulse + clippedMotorImpulse; 199 m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; 200 201 clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; 202 203 btVector3 motorImp = clippedMotorImpulse * axis; 204 205 //body0->applyTorqueImpulse(motorImp); 206 //body1->applyTorqueImpulse(-motorImp); 207 208 bodyA.applyImpulse(btVector3(0,0,0), body0->getInvInertiaTensorWorld()*axis,clippedMotorImpulse); 209 bodyB.applyImpulse(btVector3(0,0,0), body1->getInvInertiaTensorWorld()*axis,-clippedMotorImpulse); 210 211 212 return clippedMotorImpulse; 186 213 187 214 … … 190 217 //////////////////////////// End btRotationalLimitMotor //////////////////////////////////// 191 218 219 220 221 192 222 //////////////////////////// btTranslationalLimitMotor //////////////////////////////////// 223 224 225 int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value) 226 { 227 btScalar loLimit = m_lowerLimit[limitIndex]; 228 btScalar hiLimit = m_upperLimit[limitIndex]; 229 if(loLimit > hiLimit) 230 { 231 m_currentLimit[limitIndex] = 0;//Free from violation 232 m_currentLimitError[limitIndex] = btScalar(0.f); 233 return 0; 234 } 235 236 if (test_value < loLimit) 237 { 238 m_currentLimit[limitIndex] = 2;//low limit violation 239 m_currentLimitError[limitIndex] = test_value - loLimit; 240 return 2; 241 } 242 else if (test_value> hiLimit) 243 { 244 m_currentLimit[limitIndex] = 1;//High limit violation 245 m_currentLimitError[limitIndex] = test_value - hiLimit; 246 return 1; 247 }; 248 249 m_currentLimit[limitIndex] = 0;//Free from violation 250 m_currentLimitError[limitIndex] = btScalar(0.f); 251 return 0; 252 } // btTranslationalLimitMotor::testLimitValue() 253 254 //----------------------------------------------------------------------------- 255 193 256 btScalar btTranslationalLimitMotor::solveLinearAxis( 194 btScalar timeStep, 195 btScalar jacDiagABInv, 196 btRigidBody& body1,const btVector3 &pointInA, 197 btRigidBody& body2,const btVector3 &pointInB, 198 int limit_index, 199 const btVector3 & axis_normal_on_a, 200 const btVector3 & anchorPos) 201 { 202 203 ///find relative velocity 204 // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); 205 // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); 206 btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); 207 btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); 208 209 btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); 210 btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); 211 btVector3 vel = vel1 - vel2; 212 213 btScalar rel_vel = axis_normal_on_a.dot(vel); 214 215 216 217 /// apply displacement correction 218 219 //positional error (zeroth order error) 220 btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); 221 btScalar lo = btScalar(-1e30); 222 btScalar hi = btScalar(1e30); 223 224 btScalar minLimit = m_lowerLimit[limit_index]; 225 btScalar maxLimit = m_upperLimit[limit_index]; 226 227 //handle the limits 228 if (minLimit < maxLimit) 229 { 230 { 231 if (depth > maxLimit) 232 { 233 depth -= maxLimit; 234 lo = btScalar(0.); 235 236 } 237 else 238 { 239 if (depth < minLimit) 240 { 241 depth -= minLimit; 242 hi = btScalar(0.); 243 } 244 else 245 { 246 return 0.0f; 247 } 248 } 249 } 250 } 251 252 btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; 253 254 255 256 257 btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; 258 btScalar sum = oldNormalImpulse + normalImpulse; 259 m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; 260 normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; 261 262 btVector3 impulse_vector = axis_normal_on_a * normalImpulse; 263 body1.applyImpulse( impulse_vector, rel_pos1); 264 body2.applyImpulse(-impulse_vector, rel_pos2); 265 return normalImpulse; 257 btScalar timeStep, 258 btScalar jacDiagABInv, 259 btRigidBody& body1,btSolverBody& bodyA,const btVector3 &pointInA, 260 btRigidBody& body2,btSolverBody& bodyB,const btVector3 &pointInB, 261 int limit_index, 262 const btVector3 & axis_normal_on_a, 263 const btVector3 & anchorPos) 264 { 265 266 ///find relative velocity 267 // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); 268 // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); 269 btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); 270 btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); 271 272 btVector3 vel1; 273 bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); 274 btVector3 vel2; 275 bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); 276 btVector3 vel = vel1 - vel2; 277 278 btScalar rel_vel = axis_normal_on_a.dot(vel); 279 280 281 282 /// apply displacement correction 283 284 //positional error (zeroth order error) 285 btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); 286 btScalar lo = btScalar(-1e30); 287 btScalar hi = btScalar(1e30); 288 289 btScalar minLimit = m_lowerLimit[limit_index]; 290 btScalar maxLimit = m_upperLimit[limit_index]; 291 292 //handle the limits 293 if (minLimit < maxLimit) 294 { 295 { 296 if (depth > maxLimit) 297 { 298 depth -= maxLimit; 299 lo = btScalar(0.); 300 301 } 302 else 303 { 304 if (depth < minLimit) 305 { 306 depth -= minLimit; 307 hi = btScalar(0.); 308 } 309 else 310 { 311 return 0.0f; 312 } 313 } 314 } 315 } 316 317 btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; 318 319 320 321 322 btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; 323 btScalar sum = oldNormalImpulse + normalImpulse; 324 m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; 325 normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; 326 327 btVector3 impulse_vector = axis_normal_on_a * normalImpulse; 328 //body1.applyImpulse( impulse_vector, rel_pos1); 329 //body2.applyImpulse(-impulse_vector, rel_pos2); 330 331 btVector3 ftorqueAxis1 = rel_pos1.cross(axis_normal_on_a); 332 btVector3 ftorqueAxis2 = rel_pos2.cross(axis_normal_on_a); 333 bodyA.applyImpulse(axis_normal_on_a*body1.getInvMass(), body1.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse); 334 bodyB.applyImpulse(axis_normal_on_a*body2.getInvMass(), body2.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse); 335 336 337 338 339 return normalImpulse; 266 340 } 267 341 268 342 //////////////////////////// btTranslationalLimitMotor //////////////////////////////////// 269 343 270 271 btGeneric6DofConstraint::btGeneric6DofConstraint()272 :btTypedConstraint(D6_CONSTRAINT_TYPE),273 m_useLinearReferenceFrameA(true)274 {275 }276 277 btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)278 : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB)279 , m_frameInA(frameInA)280 , m_frameInB(frameInB),281 m_useLinearReferenceFrameA(useLinearReferenceFrameA)282 {283 284 }285 286 287 288 289 290 344 void btGeneric6DofConstraint::calculateAngleInfo() 291 345 { 292 346 btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); 293 294 347 matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); 295 296 297 298 348 // in euler angle mode we do not actually constrain the angular velocity 299 // along the axes axis[0] and axis[2] (although we do use axis[1]) : 300 // 301 // to get constrain w2-w1 along ...not 302 // ------ --------------------- ------ 303 // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] 304 // d(angle[1])/dt = 0 ax[1] 305 // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] 306 // 307 // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. 308 // to prove the result for angle[0], write the expression for angle[0] from 309 // GetInfo1 then take the derivative. to prove this for angle[2] it is 310 // easier to take the euler rate expression for d(angle[2])/dt with respect 311 // to the components of w and set that to 0. 312 349 // along the axes axis[0] and axis[2] (although we do use axis[1]) : 350 // 351 // to get constrain w2-w1 along ...not 352 // ------ --------------------- ------ 353 // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] 354 // d(angle[1])/dt = 0 ax[1] 355 // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] 356 // 357 // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. 358 // to prove the result for angle[0], write the expression for angle[0] from 359 // GetInfo1 then take the derivative. to prove this for angle[2] it is 360 // easier to take the euler rate expression for d(angle[2])/dt with respect 361 // to the components of w and set that to 0. 313 362 btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); 314 363 btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); … … 318 367 m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); 319 368 320 321 // if(m_debugDrawer) 322 // { 323 // 324 // char buff[300]; 325 // sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", 326 // m_calculatedAxisAngleDiff[0], 327 // m_calculatedAxisAngleDiff[1], 328 // m_calculatedAxisAngleDiff[2]); 329 // m_debugDrawer->reportErrorWarning(buff); 330 // } 331 332 } 369 m_calculatedAxis[0].normalize(); 370 m_calculatedAxis[1].normalize(); 371 m_calculatedAxis[2].normalize(); 372 373 } 374 375 //----------------------------------------------------------------------------- 333 376 334 377 void btGeneric6DofConstraint::calculateTransforms() 335 378 { 336 m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; 337 m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; 338 339 calculateAngleInfo(); 340 } 341 379 m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; 380 m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; 381 calculateLinearInfo(); 382 calculateAngleInfo(); 383 } 384 385 //----------------------------------------------------------------------------- 342 386 343 387 void btGeneric6DofConstraint::buildLinearJacobian( 344 345 346 { 347 388 btJacobianEntry & jacLinear,const btVector3 & normalWorld, 389 const btVector3 & pivotAInW,const btVector3 & pivotBInW) 390 { 391 new (&jacLinear) btJacobianEntry( 348 392 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 349 393 m_rbB.getCenterOfMassTransform().getBasis().transpose(), … … 355 399 m_rbB.getInvInertiaDiagLocal(), 356 400 m_rbB.getInvMass()); 357 358 } 401 } 402 403 //----------------------------------------------------------------------------- 359 404 360 405 void btGeneric6DofConstraint::buildAngularJacobian( 361 362 { 363 406 btJacobianEntry & jacAngular,const btVector3 & jointAxisW) 407 { 408 new (&jacAngular) btJacobianEntry(jointAxisW, 364 409 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 365 410 m_rbB.getCenterOfMassTransform().getBasis().transpose(), … … 369 414 } 370 415 416 //----------------------------------------------------------------------------- 417 371 418 bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) 372 419 { 373 btScalar angle = m_calculatedAxisAngleDiff[axis_index]; 374 375 //test limits 376 m_angularLimits[axis_index].testLimitValue(angle); 377 return m_angularLimits[axis_index].needApplyTorques(); 378 } 420 btScalar angle = m_calculatedAxisAngleDiff[axis_index]; 421 //test limits 422 m_angularLimits[axis_index].testLimitValue(angle); 423 return m_angularLimits[axis_index].needApplyTorques(); 424 } 425 426 //----------------------------------------------------------------------------- 379 427 380 428 void btGeneric6DofConstraint::buildJacobian() 381 429 { 382 383 // Clear accumulated impulses for the next simulation step 384 m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); 385 int i; 386 for(i = 0; i < 3; i++) 387 { 388 m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); 389 } 390 //calculates transform 391 calculateTransforms(); 392 393 // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); 394 // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); 395 calcAnchorPos(); 396 btVector3 pivotAInW = m_AnchorPos; 397 btVector3 pivotBInW = m_AnchorPos; 398 399 // not used here 400 // btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 401 // btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 402 403 btVector3 normalWorld; 404 //linear part 405 for (i=0;i<3;i++) 406 { 407 if (m_linearLimits.isLimited(i)) 408 { 409 if (m_useLinearReferenceFrameA) 410 normalWorld = m_calculatedTransformA.getBasis().getColumn(i); 411 else 412 normalWorld = m_calculatedTransformB.getBasis().getColumn(i); 413 414 buildLinearJacobian( 415 m_jacLinear[i],normalWorld , 416 pivotAInW,pivotBInW); 417 418 } 419 } 420 421 // angular part 422 for (i=0;i<3;i++) 423 { 424 //calculates error angle 425 if (testAngularLimitMotor(i)) 426 { 427 normalWorld = this->getAxis(i); 428 // Create angular atom 429 buildAngularJacobian(m_jacAng[i],normalWorld); 430 } 431 } 432 433 434 } 435 436 437 void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) 438 { 439 m_timeStep = timeStep; 440 441 //calculateTransforms(); 442 443 int i; 444 445 // linear 446 447 btVector3 pointInA = m_calculatedTransformA.getOrigin(); 448 btVector3 pointInB = m_calculatedTransformB.getOrigin(); 449 450 btScalar jacDiagABInv; 451 btVector3 linear_axis; 452 for (i=0;i<3;i++) 453 { 454 if (m_linearLimits.isLimited(i)) 455 { 456 jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); 457 458 if (m_useLinearReferenceFrameA) 459 linear_axis = m_calculatedTransformA.getBasis().getColumn(i); 460 else 461 linear_axis = m_calculatedTransformB.getBasis().getColumn(i); 462 463 m_linearLimits.solveLinearAxis( 464 m_timeStep, 465 jacDiagABInv, 466 m_rbA,pointInA, 467 m_rbB,pointInB, 468 i,linear_axis, m_AnchorPos); 469 470 } 471 } 472 473 // angular 474 btVector3 angular_axis; 475 btScalar angularJacDiagABInv; 476 for (i=0;i<3;i++) 477 { 478 if (m_angularLimits[i].needApplyTorques()) 479 { 480 481 // get axis 482 angular_axis = getAxis(i); 483 484 angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); 485 486 m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,&m_rbB); 487 } 488 } 489 } 430 if (m_useSolveConstraintObsolete) 431 { 432 433 // Clear accumulated impulses for the next simulation step 434 m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); 435 int i; 436 for(i = 0; i < 3; i++) 437 { 438 m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); 439 } 440 //calculates transform 441 calculateTransforms(); 442 443 // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); 444 // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); 445 calcAnchorPos(); 446 btVector3 pivotAInW = m_AnchorPos; 447 btVector3 pivotBInW = m_AnchorPos; 448 449 // not used here 450 // btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 451 // btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 452 453 btVector3 normalWorld; 454 //linear part 455 for (i=0;i<3;i++) 456 { 457 if (m_linearLimits.isLimited(i)) 458 { 459 if (m_useLinearReferenceFrameA) 460 normalWorld = m_calculatedTransformA.getBasis().getColumn(i); 461 else 462 normalWorld = m_calculatedTransformB.getBasis().getColumn(i); 463 464 buildLinearJacobian( 465 m_jacLinear[i],normalWorld , 466 pivotAInW,pivotBInW); 467 468 } 469 } 470 471 // angular part 472 for (i=0;i<3;i++) 473 { 474 //calculates error angle 475 if (testAngularLimitMotor(i)) 476 { 477 normalWorld = this->getAxis(i); 478 // Create angular atom 479 buildAngularJacobian(m_jacAng[i],normalWorld); 480 } 481 } 482 483 } 484 } 485 486 //----------------------------------------------------------------------------- 487 488 void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info) 489 { 490 if (m_useSolveConstraintObsolete) 491 { 492 info->m_numConstraintRows = 0; 493 info->nub = 0; 494 } else 495 { 496 //prepare constraint 497 calculateTransforms(); 498 info->m_numConstraintRows = 0; 499 info->nub = 6; 500 int i; 501 //test linear limits 502 for(i = 0; i < 3; i++) 503 { 504 if(m_linearLimits.needApplyForce(i)) 505 { 506 info->m_numConstraintRows++; 507 info->nub--; 508 } 509 } 510 //test angular limits 511 for (i=0;i<3 ;i++ ) 512 { 513 if(testAngularLimitMotor(i)) 514 { 515 info->m_numConstraintRows++; 516 info->nub--; 517 } 518 } 519 } 520 } 521 522 //----------------------------------------------------------------------------- 523 524 void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info) 525 { 526 btAssert(!m_useSolveConstraintObsolete); 527 int row = setLinearLimits(info); 528 setAngularLimits(info, row); 529 } 530 531 //----------------------------------------------------------------------------- 532 533 int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info) 534 { 535 btGeneric6DofConstraint * d6constraint = this; 536 int row = 0; 537 //solve linear limits 538 btRotationalLimitMotor limot; 539 for (int i=0;i<3 ;i++ ) 540 { 541 if(m_linearLimits.needApplyForce(i)) 542 { // re-use rotational motor code 543 limot.m_bounce = btScalar(0.f); 544 limot.m_currentLimit = m_linearLimits.m_currentLimit[i]; 545 limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; 546 limot.m_damping = m_linearLimits.m_damping; 547 limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; 548 limot.m_ERP = m_linearLimits.m_restitution; 549 limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; 550 limot.m_limitSoftness = m_linearLimits.m_limitSoftness; 551 limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; 552 limot.m_maxLimitForce = btScalar(0.f); 553 limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; 554 limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; 555 btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i); 556 row += get_limit_motor_info2(&limot, &m_rbA, &m_rbB, info, row, axis, 0); 557 } 558 } 559 return row; 560 } 561 562 //----------------------------------------------------------------------------- 563 564 int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset) 565 { 566 btGeneric6DofConstraint * d6constraint = this; 567 int row = row_offset; 568 //solve angular limits 569 for (int i=0;i<3 ;i++ ) 570 { 571 if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques()) 572 { 573 btVector3 axis = d6constraint->getAxis(i); 574 row += get_limit_motor_info2( 575 d6constraint->getRotationalLimitMotor(i), 576 &m_rbA, 577 &m_rbB, 578 info,row,axis,1); 579 } 580 } 581 582 return row; 583 } 584 585 //----------------------------------------------------------------------------- 586 587 void btGeneric6DofConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) 588 { 589 if (m_useSolveConstraintObsolete) 590 { 591 592 593 m_timeStep = timeStep; 594 595 //calculateTransforms(); 596 597 int i; 598 599 // linear 600 601 btVector3 pointInA = m_calculatedTransformA.getOrigin(); 602 btVector3 pointInB = m_calculatedTransformB.getOrigin(); 603 604 btScalar jacDiagABInv; 605 btVector3 linear_axis; 606 for (i=0;i<3;i++) 607 { 608 if (m_linearLimits.isLimited(i)) 609 { 610 jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); 611 612 if (m_useLinearReferenceFrameA) 613 linear_axis = m_calculatedTransformA.getBasis().getColumn(i); 614 else 615 linear_axis = m_calculatedTransformB.getBasis().getColumn(i); 616 617 m_linearLimits.solveLinearAxis( 618 m_timeStep, 619 jacDiagABInv, 620 m_rbA,bodyA,pointInA, 621 m_rbB,bodyB,pointInB, 622 i,linear_axis, m_AnchorPos); 623 624 } 625 } 626 627 // angular 628 btVector3 angular_axis; 629 btScalar angularJacDiagABInv; 630 for (i=0;i<3;i++) 631 { 632 if (m_angularLimits[i].needApplyTorques()) 633 { 634 635 // get axis 636 angular_axis = getAxis(i); 637 638 angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); 639 640 m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,bodyA,&m_rbB,bodyB); 641 } 642 } 643 } 644 } 645 646 //----------------------------------------------------------------------------- 490 647 491 648 void btGeneric6DofConstraint::updateRHS(btScalar timeStep) 492 649 { 493 (void)timeStep; 494 495 } 650 (void)timeStep; 651 652 } 653 654 //----------------------------------------------------------------------------- 496 655 497 656 btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const 498 657 { 499 return m_calculatedAxis[axis_index]; 500 } 658 return m_calculatedAxis[axis_index]; 659 } 660 661 //----------------------------------------------------------------------------- 501 662 502 663 btScalar btGeneric6DofConstraint::getAngle(int axis_index) const 503 664 { 504 return m_calculatedAxisAngleDiff[axis_index]; 505 } 665 return m_calculatedAxisAngleDiff[axis_index]; 666 } 667 668 //----------------------------------------------------------------------------- 506 669 507 670 void btGeneric6DofConstraint::calcAnchorPos(void) … … 524 687 } // btGeneric6DofConstraint::calcAnchorPos() 525 688 689 //----------------------------------------------------------------------------- 690 691 void btGeneric6DofConstraint::calculateLinearInfo() 692 { 693 m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin(); 694 m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff; 695 for(int i = 0; i < 3; i++) 696 { 697 m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]); 698 } 699 } // btGeneric6DofConstraint::calculateLinearInfo() 700 701 //----------------------------------------------------------------------------- 702 703 int btGeneric6DofConstraint::get_limit_motor_info2( 704 btRotationalLimitMotor * limot, 705 btRigidBody * body0, btRigidBody * body1, 706 btConstraintInfo2 *info, int row, btVector3& ax1, int rotational) 707 { 708 int srow = row * info->rowskip; 709 int powered = limot->m_enableMotor; 710 int limit = limot->m_currentLimit; 711 if (powered || limit) 712 { // if the joint is powered, or has joint limits, add in the extra row 713 btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; 714 btScalar *J2 = rotational ? info->m_J2angularAxis : 0; 715 J1[srow+0] = ax1[0]; 716 J1[srow+1] = ax1[1]; 717 J1[srow+2] = ax1[2]; 718 if(rotational) 719 { 720 J2[srow+0] = -ax1[0]; 721 J2[srow+1] = -ax1[1]; 722 J2[srow+2] = -ax1[2]; 723 } 724 if((!rotational) && limit) 725 { 726 btVector3 ltd; // Linear Torque Decoupling vector 727 btVector3 c = m_calculatedTransformB.getOrigin() - body0->getCenterOfMassPosition(); 728 ltd = c.cross(ax1); 729 info->m_J1angularAxis[srow+0] = ltd[0]; 730 info->m_J1angularAxis[srow+1] = ltd[1]; 731 info->m_J1angularAxis[srow+2] = ltd[2]; 732 733 c = m_calculatedTransformB.getOrigin() - body1->getCenterOfMassPosition(); 734 ltd = -c.cross(ax1); 735 info->m_J2angularAxis[srow+0] = ltd[0]; 736 info->m_J2angularAxis[srow+1] = ltd[1]; 737 info->m_J2angularAxis[srow+2] = ltd[2]; 738 } 739 // if we're limited low and high simultaneously, the joint motor is 740 // ineffective 741 if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0; 742 info->m_constraintError[srow] = btScalar(0.f); 743 if (powered) 744 { 745 info->cfm[srow] = 0.0f; 746 if(!limit) 747 { 748 info->m_constraintError[srow] += limot->m_targetVelocity; 749 info->m_lowerLimit[srow] = -limot->m_maxMotorForce; 750 info->m_upperLimit[srow] = limot->m_maxMotorForce; 751 } 752 } 753 if(limit) 754 { 755 btScalar k = info->fps * limot->m_ERP; 756 if(!rotational) 757 { 758 info->m_constraintError[srow] += k * limot->m_currentLimitError; 759 } 760 else 761 { 762 info->m_constraintError[srow] += -k * limot->m_currentLimitError; 763 } 764 info->cfm[srow] = 0.0f; 765 if (limot->m_loLimit == limot->m_hiLimit) 766 { // limited low and high simultaneously 767 info->m_lowerLimit[srow] = -SIMD_INFINITY; 768 info->m_upperLimit[srow] = SIMD_INFINITY; 769 } 770 else 771 { 772 if (limit == 1) 773 { 774 info->m_lowerLimit[srow] = 0; 775 info->m_upperLimit[srow] = SIMD_INFINITY; 776 } 777 else 778 { 779 info->m_lowerLimit[srow] = -SIMD_INFINITY; 780 info->m_upperLimit[srow] = 0; 781 } 782 // deal with bounce 783 if (limot->m_bounce > 0) 784 { 785 // calculate joint velocity 786 btScalar vel; 787 if (rotational) 788 { 789 vel = body0->getAngularVelocity().dot(ax1); 790 if (body1) 791 vel -= body1->getAngularVelocity().dot(ax1); 792 } 793 else 794 { 795 vel = body0->getLinearVelocity().dot(ax1); 796 if (body1) 797 vel -= body1->getLinearVelocity().dot(ax1); 798 } 799 // only apply bounce if the velocity is incoming, and if the 800 // resulting c[] exceeds what we already have. 801 if (limit == 1) 802 { 803 if (vel < 0) 804 { 805 btScalar newc = -limot->m_bounce* vel; 806 if (newc > info->m_constraintError[srow]) 807 info->m_constraintError[srow] = newc; 808 } 809 } 810 else 811 { 812 if (vel > 0) 813 { 814 btScalar newc = -limot->m_bounce * vel; 815 if (newc < info->m_constraintError[srow]) 816 info->m_constraintError[srow] = newc; 817 } 818 } 819 } 820 } 821 } 822 return 1; 823 } 824 else return 0; 825 } 826 827 //----------------------------------------------------------------------------- 828 //----------------------------------------------------------------------------- 829 //----------------------------------------------------------------------------- -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
r2662 r2882 29 29 30 30 class btRigidBody; 31 32 31 33 32 34 … … 93 95 bool isLimited() 94 96 { 95 if(m_loLimit >=m_hiLimit) return false;97 if(m_loLimit > m_hiLimit) return false; 96 98 return true; 97 99 } … … 111 113 112 114 //! apply the correction impulses for two bodies 113 btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); 114 115 btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btSolverBody& bodyA,btRigidBody * body1,btSolverBody& bodyB); 115 116 116 117 }; … … 130 131 btScalar m_restitution;//! Bounce parameter for linear limit 131 132 //!@} 133 bool m_enableMotor[3]; 134 btVector3 m_targetVelocity;//!< target motor velocity 135 btVector3 m_maxMotorForce;//!< max force on motor 136 btVector3 m_currentLimitError;//! How much is violated this limit 137 int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit 132 138 133 139 btTranslationalLimitMotor() … … 140 146 m_damping = btScalar(1.0f); 141 147 m_restitution = btScalar(0.5f); 148 for(int i=0; i < 3; i++) 149 { 150 m_enableMotor[i] = false; 151 m_targetVelocity[i] = btScalar(0.f); 152 m_maxMotorForce[i] = btScalar(0.f); 153 } 142 154 } 143 155 … … 151 163 m_damping = other.m_damping; 152 164 m_restitution = other.m_restitution; 165 for(int i=0; i < 3; i++) 166 { 167 m_enableMotor[i] = other.m_enableMotor[i]; 168 m_targetVelocity[i] = other.m_targetVelocity[i]; 169 m_maxMotorForce[i] = other.m_maxMotorForce[i]; 170 } 153 171 } 154 172 … … 164 182 return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); 165 183 } 184 inline bool needApplyForce(int limitIndex) 185 { 186 if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false; 187 return true; 188 } 189 int testLimitValue(int limitIndex, btScalar test_value); 166 190 167 191 … … 169 193 btScalar timeStep, 170 194 btScalar jacDiagABInv, 171 btRigidBody& body1, const btVector3 &pointInA,172 btRigidBody& body2, const btVector3 &pointInB,195 btRigidBody& body1,btSolverBody& bodyA,const btVector3 &pointInA, 196 btRigidBody& body2,btSolverBody& bodyB,const btVector3 &pointInB, 173 197 int limit_index, 174 198 const btVector3 & axis_normal_on_a, … … 248 272 btVector3 m_calculatedAxisAngleDiff; 249 273 btVector3 m_calculatedAxis[3]; 274 btVector3 m_calculatedLinearDiff; 250 275 251 276 btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes … … 263 288 264 289 290 int setAngularLimits(btConstraintInfo2 *info, int row_offset); 291 292 int setLinearLimits(btConstraintInfo2 *info); 265 293 266 294 void buildLinearJacobian( … … 270 298 void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); 271 299 300 // tests linear limits 301 void calculateLinearInfo(); 272 302 273 303 //! calcs the euler angles between the two bodies. … … 277 307 278 308 public: 309 310 ///for backwards compatibility during the transition to 'getInfo/getInfo2' 311 bool m_useSolveConstraintObsolete; 312 279 313 btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); 280 314 … … 331 365 virtual void buildJacobian(); 332 366 333 virtual void solveConstraint(btScalar timeStep); 367 virtual void getInfo1 (btConstraintInfo1* info); 368 369 virtual void getInfo2 (btConstraintInfo2* info); 370 371 virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); 334 372 335 373 void updateRHS(btScalar timeStep); … … 433 471 virtual void calcAnchorPos(void); // overridable 434 472 473 int get_limit_motor_info2( btRotationalLimitMotor * limot, 474 btRigidBody * body0, btRigidBody * body1, 475 btConstraintInfo2 *info, int row, btVector3& ax1, int rotational); 476 477 435 478 }; 436 479 -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
r2662 r2882 20 20 #include "LinearMath/btMinMax.h" 21 21 #include <new> 22 #include "btSolverBody.h" 23 24 //----------------------------------------------------------------------------- 25 26 #define HINGE_USE_OBSOLETE_SOLVER false 27 28 //----------------------------------------------------------------------------- 22 29 23 30 24 31 btHingeConstraint::btHingeConstraint() 25 32 : btTypedConstraint (HINGE_CONSTRAINT_TYPE), 26 m_enableAngularMotor(false) 27 { 28 } 33 m_enableAngularMotor(false), 34 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), 35 m_useReferenceFrameA(false) 36 { 37 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); 38 } 39 40 //----------------------------------------------------------------------------- 29 41 30 42 btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, 31 btVector3& axisInA,btVector3& axisInB )43 btVector3& axisInA,btVector3& axisInB, bool useReferenceFrameA) 32 44 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), 33 45 m_angularOnly(false), 34 m_enableAngularMotor(false) 46 m_enableAngularMotor(false), 47 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), 48 m_useReferenceFrameA(useReferenceFrameA) 35 49 { 36 50 m_rbAFrame.getOrigin() = pivotInA; … … 61 75 62 76 m_rbBFrame.getOrigin() = pivotInB; 63 m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(), -axisInB.getX(),64 rbAxisB1.getY(),rbAxisB2.getY(), -axisInB.getY(),65 rbAxisB1.getZ(),rbAxisB2.getZ(), -axisInB.getZ() );77 m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), 78 rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), 79 rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); 66 80 67 81 //start with free … … 72 86 m_limitSoftness = 0.9f; 73 87 m_solveLimit = false; 74 75 } 76 77 78 79 btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA) 80 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false) 88 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); 89 } 90 91 //----------------------------------------------------------------------------- 92 93 btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA, bool useReferenceFrameA) 94 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false), 95 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), 96 m_useReferenceFrameA(useReferenceFrameA) 81 97 { 82 98 … … 91 107 rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); 92 108 93 btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * -axisInA;109 btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA; 94 110 95 111 btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); … … 110 126 m_limitSoftness = 0.9f; 111 127 m_solveLimit = false; 112 } 128 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); 129 } 130 131 //----------------------------------------------------------------------------- 113 132 114 133 btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, 115 const btTransform& rbAFrame, const btTransform& rbBFrame )134 const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) 116 135 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), 117 136 m_angularOnly(false), 118 m_enableAngularMotor(false) 119 { 120 // flip axis 121 m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); 122 m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); 123 m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); 124 137 m_enableAngularMotor(false), 138 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), 139 m_useReferenceFrameA(useReferenceFrameA) 140 { 125 141 //start with free 126 142 m_lowerLimit = btScalar(1e30); … … 130 146 m_limitSoftness = 0.9f; 131 147 m_solveLimit = false; 148 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); 132 149 } 133 150 134 135 136 btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame )151 //----------------------------------------------------------------------------- 152 153 btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA) 137 154 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), 138 155 m_angularOnly(false), 139 m_enableAngularMotor(false) 156 m_enableAngularMotor(false), 157 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), 158 m_useReferenceFrameA(useReferenceFrameA) 140 159 { 141 160 ///not providing rigidbody B means implicitly using worldspace for body B 142 143 // flip axis144 m_rbBFrame.getBasis()[0][2] *= btScalar(-1.);145 m_rbBFrame.getBasis()[1][2] *= btScalar(-1.);146 m_rbBFrame.getBasis()[2][2] *= btScalar(-1.);147 161 148 162 m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); … … 155 169 m_limitSoftness = 0.9f; 156 170 m_solveLimit = false; 157 } 171 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); 172 } 173 174 //----------------------------------------------------------------------------- 158 175 159 176 void btHingeConstraint::buildJacobian() 160 177 { 161 m_appliedImpulse = btScalar(0.); 162 163 if (!m_angularOnly) 164 { 165 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); 166 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); 167 btVector3 relPos = pivotBInW - pivotAInW; 168 169 btVector3 normal[3]; 170 if (relPos.length2() > SIMD_EPSILON) 171 { 172 normal[0] = relPos.normalized(); 173 } 174 else 175 { 176 normal[0].setValue(btScalar(1.0),0,0); 177 } 178 179 btPlaneSpace1(normal[0], normal[1], normal[2]); 180 181 for (int i=0;i<3;i++) 182 { 183 new (&m_jac[i]) btJacobianEntry( 178 if (m_useSolveConstraintObsolete) 179 { 180 m_appliedImpulse = btScalar(0.); 181 182 if (!m_angularOnly) 183 { 184 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); 185 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); 186 btVector3 relPos = pivotBInW - pivotAInW; 187 188 btVector3 normal[3]; 189 if (relPos.length2() > SIMD_EPSILON) 190 { 191 normal[0] = relPos.normalized(); 192 } 193 else 194 { 195 normal[0].setValue(btScalar(1.0),0,0); 196 } 197 198 btPlaneSpace1(normal[0], normal[1], normal[2]); 199 200 for (int i=0;i<3;i++) 201 { 202 new (&m_jac[i]) btJacobianEntry( 184 203 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 185 204 m_rbB.getCenterOfMassTransform().getBasis().transpose(), … … 191 210 m_rbB.getInvInertiaDiagLocal(), 192 211 m_rbB.getInvMass()); 212 } 193 213 } 194 } 195 196 //calculate two perpendicular jointAxis, orthogonal to hingeAxis 197 //these two jointAxis require equal angular velocities for both bodies 198 199 //this is unused for now, it's a todo 200 btVector3 jointAxis0local; 201 btVector3 jointAxis1local; 202 203 btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); 204 205 getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 206 btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; 207 btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; 208 btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 214 215 //calculate two perpendicular jointAxis, orthogonal to hingeAxis 216 //these two jointAxis require equal angular velocities for both bodies 217 218 //this is unused for now, it's a todo 219 btVector3 jointAxis0local; 220 btVector3 jointAxis1local; 209 221 210 new (&m_jacAng[0]) btJacobianEntry(jointAxis0, 211 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 212 m_rbB.getCenterOfMassTransform().getBasis().transpose(), 213 m_rbA.getInvInertiaDiagLocal(), 214 m_rbB.getInvInertiaDiagLocal()); 215 216 new (&m_jacAng[1]) btJacobianEntry(jointAxis1, 217 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 218 m_rbB.getCenterOfMassTransform().getBasis().transpose(), 219 m_rbA.getInvInertiaDiagLocal(), 220 m_rbB.getInvInertiaDiagLocal()); 221 222 new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, 223 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 224 m_rbB.getCenterOfMassTransform().getBasis().transpose(), 225 m_rbA.getInvInertiaDiagLocal(), 226 m_rbB.getInvInertiaDiagLocal()); 227 228 222 btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); 223 224 getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 225 btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; 226 btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; 227 btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 228 229 new (&m_jacAng[0]) btJacobianEntry(jointAxis0, 230 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 231 m_rbB.getCenterOfMassTransform().getBasis().transpose(), 232 m_rbA.getInvInertiaDiagLocal(), 233 m_rbB.getInvInertiaDiagLocal()); 234 235 new (&m_jacAng[1]) btJacobianEntry(jointAxis1, 236 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 237 m_rbB.getCenterOfMassTransform().getBasis().transpose(), 238 m_rbA.getInvInertiaDiagLocal(), 239 m_rbB.getInvInertiaDiagLocal()); 240 241 new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, 242 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 243 m_rbB.getCenterOfMassTransform().getBasis().transpose(), 244 m_rbA.getInvInertiaDiagLocal(), 245 m_rbB.getInvInertiaDiagLocal()); 246 247 // clear accumulator 248 m_accLimitImpulse = btScalar(0.); 249 250 // test angular limit 251 testLimit(); 252 253 //Compute K = J*W*J' for hinge axis 254 btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 255 m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + 256 getRigidBodyB().computeAngularImpulseDenominator(axisA)); 257 258 } 259 } 260 261 //----------------------------------------------------------------------------- 262 263 void btHingeConstraint::getInfo1(btConstraintInfo1* info) 264 { 265 if (m_useSolveConstraintObsolete) 266 { 267 info->m_numConstraintRows = 0; 268 info->nub = 0; 269 } 270 else 271 { 272 info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular 273 info->nub = 1; 274 //prepare constraint 275 testLimit(); 276 if(getSolveLimit() || getEnableAngularMotor()) 277 { 278 info->m_numConstraintRows++; // limit 3rd anguar as well 279 info->nub--; 280 } 281 } 282 } // btHingeConstraint::getInfo1 () 283 284 //----------------------------------------------------------------------------- 285 286 void btHingeConstraint::getInfo2 (btConstraintInfo2* info) 287 { 288 btAssert(!m_useSolveConstraintObsolete); 289 int i, s = info->rowskip; 290 // transforms in world space 291 btTransform trA = m_rbA.getCenterOfMassTransform()*m_rbAFrame; 292 btTransform trB = m_rbB.getCenterOfMassTransform()*m_rbBFrame; 293 // pivot point 294 btVector3 pivotAInW = trA.getOrigin(); 295 btVector3 pivotBInW = trB.getOrigin(); 296 // linear (all fixed) 297 info->m_J1linearAxis[0] = 1; 298 info->m_J1linearAxis[s + 1] = 1; 299 info->m_J1linearAxis[2 * s + 2] = 1; 300 btVector3 a1 = pivotAInW - m_rbA.getCenterOfMassTransform().getOrigin(); 301 { 302 btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); 303 btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + s); 304 btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * s); 305 btVector3 a1neg = -a1; 306 a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); 307 } 308 btVector3 a2 = pivotBInW - m_rbB.getCenterOfMassTransform().getOrigin(); 309 { 310 btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); 311 btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + s); 312 btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * s); 313 a2.getSkewSymmetricMatrix(angular0,angular1,angular2); 314 } 315 // linear RHS 316 btScalar k = info->fps * info->erp; 317 for(i = 0; i < 3; i++) 318 { 319 info->m_constraintError[i * s] = k * (pivotBInW[i] - pivotAInW[i]); 320 } 321 // make rotations around X and Y equal 322 // the hinge axis should be the only unconstrained 323 // rotational axis, the angular velocity of the two bodies perpendicular to 324 // the hinge axis should be equal. thus the constraint equations are 325 // p*w1 - p*w2 = 0 326 // q*w1 - q*w2 = 0 327 // where p and q are unit vectors normal to the hinge axis, and w1 and w2 328 // are the angular velocity vectors of the two bodies. 329 // get hinge axis (Z) 330 btVector3 ax1 = trA.getBasis().getColumn(2); 331 // get 2 orthos to hinge axis (X, Y) 332 btVector3 p = trA.getBasis().getColumn(0); 333 btVector3 q = trA.getBasis().getColumn(1); 334 // set the two hinge angular rows 335 int s3 = 3 * info->rowskip; 336 int s4 = 4 * info->rowskip; 337 338 info->m_J1angularAxis[s3 + 0] = p[0]; 339 info->m_J1angularAxis[s3 + 1] = p[1]; 340 info->m_J1angularAxis[s3 + 2] = p[2]; 341 info->m_J1angularAxis[s4 + 0] = q[0]; 342 info->m_J1angularAxis[s4 + 1] = q[1]; 343 info->m_J1angularAxis[s4 + 2] = q[2]; 344 345 info->m_J2angularAxis[s3 + 0] = -p[0]; 346 info->m_J2angularAxis[s3 + 1] = -p[1]; 347 info->m_J2angularAxis[s3 + 2] = -p[2]; 348 info->m_J2angularAxis[s4 + 0] = -q[0]; 349 info->m_J2angularAxis[s4 + 1] = -q[1]; 350 info->m_J2angularAxis[s4 + 2] = -q[2]; 351 // compute the right hand side of the constraint equation. set relative 352 // body velocities along p and q to bring the hinge back into alignment. 353 // if ax1,ax2 are the unit length hinge axes as computed from body1 and 354 // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). 355 // if `theta' is the angle between ax1 and ax2, we need an angular velocity 356 // along u to cover angle erp*theta in one step : 357 // |angular_velocity| = angle/time = erp*theta / stepsize 358 // = (erp*fps) * theta 359 // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| 360 // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) 361 // ...as ax1 and ax2 are unit length. if theta is smallish, 362 // theta ~= sin(theta), so 363 // angular_velocity = (erp*fps) * (ax1 x ax2) 364 // ax1 x ax2 is in the plane space of ax1, so we project the angular 365 // velocity to p and q to find the right hand side. 366 btVector3 ax2 = trB.getBasis().getColumn(2); 367 btVector3 u = ax1.cross(ax2); 368 info->m_constraintError[s3] = k * u.dot(p); 369 info->m_constraintError[s4] = k * u.dot(q); 370 // check angular limits 371 int nrow = 4; // last filled row 372 int srow; 373 btScalar limit_err = btScalar(0.0); 374 int limit = 0; 375 if(getSolveLimit()) 376 { 377 limit_err = m_correction * m_referenceSign; 378 limit = (limit_err > btScalar(0.0)) ? 1 : 2; 379 } 380 // if the hinge has joint limits or motor, add in the extra row 381 int powered = 0; 382 if(getEnableAngularMotor()) 383 { 384 powered = 1; 385 } 386 if(limit || powered) 387 { 388 nrow++; 389 srow = nrow * info->rowskip; 390 info->m_J1angularAxis[srow+0] = ax1[0]; 391 info->m_J1angularAxis[srow+1] = ax1[1]; 392 info->m_J1angularAxis[srow+2] = ax1[2]; 393 394 info->m_J2angularAxis[srow+0] = -ax1[0]; 395 info->m_J2angularAxis[srow+1] = -ax1[1]; 396 info->m_J2angularAxis[srow+2] = -ax1[2]; 397 398 btScalar lostop = getLowerLimit(); 399 btScalar histop = getUpperLimit(); 400 if(limit && (lostop == histop)) 401 { // the joint motor is ineffective 402 powered = 0; 403 } 404 info->m_constraintError[srow] = btScalar(0.0f); 405 if(powered) 406 { 407 info->cfm[srow] = btScalar(0.0); 408 btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * info->erp); 409 info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign; 410 info->m_lowerLimit[srow] = - m_maxMotorImpulse; 411 info->m_upperLimit[srow] = m_maxMotorImpulse; 412 } 413 if(limit) 414 { 415 k = info->fps * info->erp; 416 info->m_constraintError[srow] += k * limit_err; 417 info->cfm[srow] = btScalar(0.0); 418 if(lostop == histop) 419 { 420 // limited low and high simultaneously 421 info->m_lowerLimit[srow] = -SIMD_INFINITY; 422 info->m_upperLimit[srow] = SIMD_INFINITY; 423 } 424 else if(limit == 1) 425 { // low limit 426 info->m_lowerLimit[srow] = 0; 427 info->m_upperLimit[srow] = SIMD_INFINITY; 428 } 429 else 430 { // high limit 431 info->m_lowerLimit[srow] = -SIMD_INFINITY; 432 info->m_upperLimit[srow] = 0; 433 } 434 // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) 435 btScalar bounce = m_relaxationFactor; 436 if(bounce > btScalar(0.0)) 437 { 438 btScalar vel = m_rbA.getAngularVelocity().dot(ax1); 439 vel -= m_rbB.getAngularVelocity().dot(ax1); 440 // only apply bounce if the velocity is incoming, and if the 441 // resulting c[] exceeds what we already have. 442 if(limit == 1) 443 { // low limit 444 if(vel < 0) 445 { 446 btScalar newc = -bounce * vel; 447 if(newc > info->m_constraintError[srow]) 448 { 449 info->m_constraintError[srow] = newc; 450 } 451 } 452 } 453 else 454 { // high limit - all those computations are reversed 455 if(vel > 0) 456 { 457 btScalar newc = -bounce * vel; 458 if(newc < info->m_constraintError[srow]) 459 { 460 info->m_constraintError[srow] = newc; 461 } 462 } 463 } 464 } 465 info->m_constraintError[srow] *= m_biasFactor; 466 } // if(limit) 467 } // if angular limit or powered 468 } 469 470 //----------------------------------------------------------------------------- 471 472 void btHingeConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) 473 { 474 475 ///for backwards compatibility during the transition to 'getInfo/getInfo2' 476 if (m_useSolveConstraintObsolete) 477 { 478 479 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); 480 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); 481 482 btScalar tau = btScalar(0.3); 483 484 //linear part 485 if (!m_angularOnly) 486 { 487 btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 488 btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 489 490 btVector3 vel1,vel2; 491 bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); 492 bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); 493 btVector3 vel = vel1 - vel2; 494 495 for (int i=0;i<3;i++) 496 { 497 const btVector3& normal = m_jac[i].m_linearJointAxis; 498 btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); 499 500 btScalar rel_vel; 501 rel_vel = normal.dot(vel); 502 //positional error (zeroth order error) 503 btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal 504 btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; 505 m_appliedImpulse += impulse; 506 btVector3 impulse_vector = normal * impulse; 507 btVector3 ftorqueAxis1 = rel_pos1.cross(normal); 508 btVector3 ftorqueAxis2 = rel_pos2.cross(normal); 509 bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); 510 bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); 511 } 512 } 513 514 515 { 516 ///solve angular part 517 518 // get axes in world space 519 btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 520 btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); 521 522 btVector3 angVelA; 523 bodyA.getAngularVelocity(angVelA); 524 btVector3 angVelB; 525 bodyB.getAngularVelocity(angVelB); 526 527 btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); 528 btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); 529 530 btVector3 angAorthog = angVelA - angVelAroundHingeAxisA; 531 btVector3 angBorthog = angVelB - angVelAroundHingeAxisB; 532 btVector3 velrelOrthog = angAorthog-angBorthog; 533 { 534 535 536 //solve orthogonal angular velocity correction 537 btScalar relaxation = btScalar(1.); 538 btScalar len = velrelOrthog.length(); 539 if (len > btScalar(0.00001)) 540 { 541 btVector3 normal = velrelOrthog.normalized(); 542 btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) + 543 getRigidBodyB().computeAngularImpulseDenominator(normal); 544 // scale for mass and relaxation 545 //velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; 546 547 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*velrelOrthog,-(btScalar(1.)/denom)); 548 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*velrelOrthog,(btScalar(1.)/denom)); 549 550 } 551 552 //solve angular positional correction 553 btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/timeStep); 554 btScalar len2 = angularError.length(); 555 if (len2>btScalar(0.00001)) 556 { 557 btVector3 normal2 = angularError.normalized(); 558 btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) + 559 getRigidBodyB().computeAngularImpulseDenominator(normal2); 560 //angularError *= (btScalar(1.)/denom2) * relaxation; 561 562 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*angularError,(btScalar(1.)/denom2)); 563 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*angularError,-(btScalar(1.)/denom2)); 564 565 } 566 567 568 569 570 571 // solve limit 572 if (m_solveLimit) 573 { 574 btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; 575 576 btScalar impulseMag = amplitude * m_kHinge; 577 578 // Clamp the accumulated impulse 579 btScalar temp = m_accLimitImpulse; 580 m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); 581 impulseMag = m_accLimitImpulse - temp; 582 583 584 585 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,impulseMag * m_limitSign); 586 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-(impulseMag * m_limitSign)); 587 588 } 589 } 590 591 //apply motor 592 if (m_enableAngularMotor) 593 { 594 //todo: add limits too 595 btVector3 angularLimit(0,0,0); 596 597 btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; 598 btScalar projRelVel = velrel.dot(axisA); 599 600 btScalar desiredMotorVel = m_motorTargetVelocity; 601 btScalar motor_relvel = desiredMotorVel - projRelVel; 602 603 btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; 604 //todo: should clip against accumulated impulse 605 btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; 606 clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; 607 btVector3 motorImp = clippedMotorImpulse * axisA; 608 609 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,clippedMotorImpulse); 610 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-clippedMotorImpulse); 611 612 } 613 } 614 } 615 616 } 617 618 //----------------------------------------------------------------------------- 619 620 void btHingeConstraint::updateRHS(btScalar timeStep) 621 { 622 (void)timeStep; 623 624 } 625 626 //----------------------------------------------------------------------------- 627 628 btScalar btHingeConstraint::getHingeAngle() 629 { 630 const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); 631 const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); 632 const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1); 633 btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); 634 return m_referenceSign * angle; 635 } 636 637 //----------------------------------------------------------------------------- 638 639 void btHingeConstraint::testLimit() 640 { 229 641 // Compute limit information 230 btScalar hingeAngle = getHingeAngle(); 231 232 //set bias, sign, clear accumulator 642 m_hingeAngle = getHingeAngle(); 233 643 m_correction = btScalar(0.); 234 644 m_limitSign = btScalar(0.); 235 645 m_solveLimit = false; 236 m_accLimitImpulse = btScalar(0.);237 238 // if (m_lowerLimit < m_upperLimit)239 646 if (m_lowerLimit <= m_upperLimit) 240 647 { 241 // if (hingeAngle <= m_lowerLimit*m_limitSoftness) 242 if (hingeAngle <= m_lowerLimit) 243 { 244 m_correction = (m_lowerLimit - hingeAngle); 648 if (m_hingeAngle <= m_lowerLimit) 649 { 650 m_correction = (m_lowerLimit - m_hingeAngle); 245 651 m_limitSign = 1.0f; 246 652 m_solveLimit = true; 247 653 } 248 // else if (hingeAngle >= m_upperLimit*m_limitSoftness) 249 else if (hingeAngle >= m_upperLimit) 250 { 251 m_correction = m_upperLimit - hingeAngle; 654 else if (m_hingeAngle >= m_upperLimit) 655 { 656 m_correction = m_upperLimit - m_hingeAngle; 252 657 m_limitSign = -1.0f; 253 658 m_solveLimit = true; 254 659 } 255 660 } 256 257 //Compute K = J*W*J' for hinge axis 258 btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 259 m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + 260 getRigidBodyB().computeAngularImpulseDenominator(axisA)); 261 262 } 263 264 void btHingeConstraint::solveConstraint(btScalar timeStep) 265 { 266 267 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); 268 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); 269 270 btScalar tau = btScalar(0.3); 271 272 //linear part 273 if (!m_angularOnly) 274 { 275 btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 276 btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 277 278 btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); 279 btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); 280 btVector3 vel = vel1 - vel2; 281 282 for (int i=0;i<3;i++) 283 { 284 const btVector3& normal = m_jac[i].m_linearJointAxis; 285 btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); 286 287 btScalar rel_vel; 288 rel_vel = normal.dot(vel); 289 //positional error (zeroth order error) 290 btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal 291 btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; 292 m_appliedImpulse += impulse; 293 btVector3 impulse_vector = normal * impulse; 294 m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); 295 m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); 296 } 297 } 298 299 300 { 301 ///solve angular part 302 303 // get axes in world space 304 btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); 305 btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); 306 307 const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); 308 const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); 309 310 btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); 311 btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); 312 313 btVector3 angAorthog = angVelA - angVelAroundHingeAxisA; 314 btVector3 angBorthog = angVelB - angVelAroundHingeAxisB; 315 btVector3 velrelOrthog = angAorthog-angBorthog; 316 { 317 //solve orthogonal angular velocity correction 318 btScalar relaxation = btScalar(1.); 319 btScalar len = velrelOrthog.length(); 320 if (len > btScalar(0.00001)) 321 { 322 btVector3 normal = velrelOrthog.normalized(); 323 btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) + 324 getRigidBodyB().computeAngularImpulseDenominator(normal); 325 // scale for mass and relaxation 326 velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; 327 } 328 329 //solve angular positional correction 330 btVector3 angularError = -axisA.cross(axisB) *(btScalar(1.)/timeStep); 331 btScalar len2 = angularError.length(); 332 if (len2>btScalar(0.00001)) 333 { 334 btVector3 normal2 = angularError.normalized(); 335 btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) + 336 getRigidBodyB().computeAngularImpulseDenominator(normal2); 337 angularError *= (btScalar(1.)/denom2) * relaxation; 338 } 339 340 m_rbA.applyTorqueImpulse(-velrelOrthog+angularError); 341 m_rbB.applyTorqueImpulse(velrelOrthog-angularError); 342 343 // solve limit 344 if (m_solveLimit) 345 { 346 btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; 347 348 btScalar impulseMag = amplitude * m_kHinge; 349 350 // Clamp the accumulated impulse 351 btScalar temp = m_accLimitImpulse; 352 m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); 353 impulseMag = m_accLimitImpulse - temp; 354 355 356 btVector3 impulse = axisA * impulseMag * m_limitSign; 357 m_rbA.applyTorqueImpulse(impulse); 358 m_rbB.applyTorqueImpulse(-impulse); 359 } 360 } 361 362 //apply motor 363 if (m_enableAngularMotor) 364 { 365 //todo: add limits too 366 btVector3 angularLimit(0,0,0); 367 368 btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; 369 btScalar projRelVel = velrel.dot(axisA); 370 371 btScalar desiredMotorVel = m_motorTargetVelocity; 372 btScalar motor_relvel = desiredMotorVel - projRelVel; 373 374 btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; 375 //todo: should clip against accumulated impulse 376 btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; 377 clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; 378 btVector3 motorImp = clippedMotorImpulse * axisA; 379 380 m_rbA.applyTorqueImpulse(motorImp+angularLimit); 381 m_rbB.applyTorqueImpulse(-motorImp-angularLimit); 382 383 } 384 } 385 386 } 387 388 void btHingeConstraint::updateRHS(btScalar timeStep) 389 { 390 (void)timeStep; 391 392 } 393 394 btScalar btHingeConstraint::getHingeAngle() 395 { 396 const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); 397 const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); 398 const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1); 399 400 return btAtan2Fast( swingAxis.dot(refAxis0), swingAxis.dot(refAxis1) ); 401 } 402 661 return; 662 } // btHingeConstraint::testLimit() 663 664 //----------------------------------------------------------------------------- 665 //----------------------------------------------------------------------------- 666 //----------------------------------------------------------------------------- -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h
r2662 r2882 54 54 55 55 btScalar m_accLimitImpulse; 56 btScalar m_hingeAngle; 57 btScalar m_referenceSign; 56 58 57 59 bool m_angularOnly; 58 60 bool m_enableAngularMotor; 59 61 bool m_solveLimit; 62 bool m_useSolveConstraintObsolete; 63 bool m_useReferenceFrameA; 60 64 61 65 62 66 public: 63 67 64 btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, btVector3& axisInA,btVector3& axisInB );68 btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, btVector3& axisInA,btVector3& axisInB, bool useReferenceFrameA = false); 65 69 66 btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA );70 btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA, bool useReferenceFrameA = false); 67 71 68 btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame );72 btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false); 69 73 70 btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame );74 btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false); 71 75 72 76 btHingeConstraint(); … … 74 78 virtual void buildJacobian(); 75 79 76 virtual void solveConstraint(btScalar timeStep); 80 virtual void getInfo1 (btConstraintInfo1* info); 81 82 virtual void getInfo2 (btConstraintInfo2* info); 83 84 virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); 77 85 78 86 void updateRHS(btScalar timeStep); … … 87 95 } 88 96 97 btRigidBody& getRigidBodyA() 98 { 99 return m_rbA; 100 } 101 102 btRigidBody& getRigidBodyB() 103 { 104 return m_rbB; 105 } 106 89 107 void setAngularOnly(bool angularOnly) 90 108 { … … 123 141 btScalar getHingeAngle(); 124 142 143 void testLimit(); 144 125 145 126 146 const btTransform& getAFrame() { return m_rbAFrame; }; -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
r2662 r2882 22 22 23 23 btPoint2PointConstraint::btPoint2PointConstraint() 24 :btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE) 24 :btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE), 25 m_useSolveConstraintObsolete(false) 25 26 { 26 27 } 27 28 28 29 btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) 29 :btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) 30 :btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), 31 m_useSolveConstraintObsolete(false) 30 32 { 31 33 … … 34 36 35 37 btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) 36 :btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) 38 :btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), 39 m_useSolveConstraintObsolete(false) 37 40 { 38 41 … … 41 44 void btPoint2PointConstraint::buildJacobian() 42 45 { 43 m_appliedImpulse = btScalar(0.); 44 45 btVector3 normal(0,0,0); 46 47 for (int i=0;i<3;i++) 48 { 49 normal[i] = 1; 50 new (&m_jac[i]) btJacobianEntry( 46 ///we need it for both methods 47 { 48 m_appliedImpulse = btScalar(0.); 49 50 btVector3 normal(0,0,0); 51 52 for (int i=0;i<3;i++) 53 { 54 normal[i] = 1; 55 new (&m_jac[i]) btJacobianEntry( 51 56 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 52 57 m_rbB.getCenterOfMassTransform().getBasis().transpose(), … … 59 64 m_rbB.getInvMass()); 60 65 normal[i] = 0; 61 } 62 63 } 64 65 void btPoint2PointConstraint::solveConstraint(btScalar timeStep) 66 { 67 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; 68 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; 69 70 71 btVector3 normal(0,0,0); 72 73 74 // btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); 75 // btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); 76 77 for (int i=0;i<3;i++) 78 { 79 normal[i] = 1; 80 btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); 81 82 btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 83 btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 84 //this jacobian entry could be re-used for all iterations 85 86 btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); 87 btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); 88 btVector3 vel = vel1 - vel2; 89 90 btScalar rel_vel; 91 rel_vel = normal.dot(vel); 92 93 /* 94 //velocity error (first order error) 95 btScalar rel_vel = m_jac[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, 96 m_rbB.getLinearVelocity(),angvelB); 66 } 67 } 68 69 } 70 71 72 void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info) 73 { 74 if (m_useSolveConstraintObsolete) 75 { 76 info->m_numConstraintRows = 0; 77 info->nub = 0; 78 } else 79 { 80 info->m_numConstraintRows = 3; 81 info->nub = 3; 82 } 83 } 84 85 void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info) 86 { 87 btAssert(!m_useSolveConstraintObsolete); 88 89 //retrieve matrices 90 btTransform body0_trans; 91 body0_trans = m_rbA.getCenterOfMassTransform(); 92 btTransform body1_trans; 93 body1_trans = m_rbB.getCenterOfMassTransform(); 94 95 // anchor points in global coordinates with respect to body PORs. 96 97 // set jacobian 98 info->m_J1linearAxis[0] = 1; 99 info->m_J1linearAxis[info->rowskip+1] = 1; 100 info->m_J1linearAxis[2*info->rowskip+2] = 1; 101 102 btVector3 a1 = body0_trans.getBasis()*getPivotInA(); 103 { 104 btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); 105 btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); 106 btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); 107 btVector3 a1neg = -a1; 108 a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); 109 } 110 111 /*info->m_J2linearAxis[0] = -1; 112 info->m_J2linearAxis[s+1] = -1; 113 info->m_J2linearAxis[2*s+2] = -1; 97 114 */ 98 115 99 //positional error (zeroth order error) 100 btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal 116 btVector3 a2 = body1_trans.getBasis()*getPivotInB(); 117 118 { 119 btVector3 a2n = -a2; 120 btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); 121 btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); 122 btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); 123 a2.getSkewSymmetricMatrix(angular0,angular1,angular2); 124 } 125 126 127 128 // set right hand side 129 btScalar k = info->fps * info->erp; 130 int j; 131 132 for (j=0; j<3; j++) 133 { 134 info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); 135 //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]); 136 } 137 138 btScalar impulseClamp = m_setting.m_impulseClamp;// 139 for (j=0; j<3; j++) 140 { 141 if (m_setting.m_impulseClamp > 0) 142 { 143 info->m_lowerLimit[j*info->rowskip] = -impulseClamp; 144 info->m_upperLimit[j*info->rowskip] = impulseClamp; 145 } 146 } 147 148 } 149 150 151 void btPoint2PointConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) 152 { 153 if (m_useSolveConstraintObsolete) 154 { 155 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; 156 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; 157 158 159 btVector3 normal(0,0,0); 101 160 102 btScalar impulse = depth*m_setting.m_tau/timeStep * jacDiagABInv - m_setting.m_damping * rel_vel * jacDiagABInv; 103 104 btScalar impulseClamp = m_setting.m_impulseClamp; 105 if (impulseClamp > 0) 106 { 107 if (impulse < -impulseClamp) 108 impulse = -impulseClamp; 109 if (impulse > impulseClamp) 110 impulse = impulseClamp; 161 162 // btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); 163 // btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); 164 165 for (int i=0;i<3;i++) 166 { 167 normal[i] = 1; 168 btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); 169 170 btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 171 btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 172 //this jacobian entry could be re-used for all iterations 173 174 btVector3 vel1,vel2; 175 bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); 176 bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); 177 btVector3 vel = vel1 - vel2; 178 179 btScalar rel_vel; 180 rel_vel = normal.dot(vel); 181 182 /* 183 //velocity error (first order error) 184 btScalar rel_vel = m_jac[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, 185 m_rbB.getLinearVelocity(),angvelB); 186 */ 187 188 //positional error (zeroth order error) 189 btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal 190 191 btScalar deltaImpulse = depth*m_setting.m_tau/timeStep * jacDiagABInv - m_setting.m_damping * rel_vel * jacDiagABInv; 192 193 btScalar impulseClamp = m_setting.m_impulseClamp; 194 195 const btScalar sum = btScalar(m_appliedImpulse) + deltaImpulse; 196 if (sum < -impulseClamp) 197 { 198 deltaImpulse = -impulseClamp-m_appliedImpulse; 199 m_appliedImpulse = -impulseClamp; 200 } 201 else if (sum > impulseClamp) 202 { 203 deltaImpulse = impulseClamp-m_appliedImpulse; 204 m_appliedImpulse = impulseClamp; 205 } 206 else 207 { 208 m_appliedImpulse = sum; 209 } 210 211 212 btVector3 impulse_vector = normal * deltaImpulse; 213 214 btVector3 ftorqueAxis1 = rel_pos1.cross(normal); 215 btVector3 ftorqueAxis2 = rel_pos2.cross(normal); 216 bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,deltaImpulse); 217 bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-deltaImpulse); 218 219 220 normal[i] = 0; 111 221 } 112 113 m_appliedImpulse+=impulse;114 btVector3 impulse_vector = normal * impulse;115 m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition());116 m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition());117 118 normal[i] = 0;119 222 } 120 223 } -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
r2662 r2882 51 51 public: 52 52 53 ///for backwards compatibility during the transition to 'getInfo/getInfo2' 54 bool m_useSolveConstraintObsolete; 55 53 56 btConstraintSetting m_setting; 54 57 … … 61 64 virtual void buildJacobian(); 62 65 66 virtual void getInfo1 (btConstraintInfo1* info); 63 67 64 virtual void solveConstraint(btScalar timeStep); 68 virtual void getInfo2 (btConstraintInfo2* info); 69 70 71 virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); 65 72 66 73 void updateRHS(btScalar timeStep); -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
r2662 r2882 16 16 //#define COMPUTE_IMPULSE_DENOM 1 17 17 //It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms. 18 //#define FORCE_REFESH_CONTACT_MANIFOLDS 119 18 20 19 #include "btSequentialImpulseConstraintSolver.h" … … 33 32 #include "btSolverBody.h" 34 33 #include "btSolverConstraint.h" 35 36 37 34 #include "LinearMath/btAlignedObjectArray.h" 38 39 40 int totalCpd = 0; 41 42 int gTotalContactPoints = 0; 43 44 struct btOrderIndex 45 { 46 int m_manifoldIndex; 47 int m_pointIndex; 48 }; 49 50 51 52 #define SEQUENTIAL_IMPULSE_MAX_SOLVER_POINTS 16384 53 static btOrderIndex gOrder[SEQUENTIAL_IMPULSE_MAX_SOLVER_POINTS]; 35 #include <string.h> //for memset 36 37 btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() 38 :m_btSeed2(0) 39 { 40 41 } 42 43 btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() 44 { 45 } 46 47 #ifdef USE_SIMD 48 #include <emmintrin.h> 49 #define vec_splat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) 50 static inline __m128 _vmathVfDot3( __m128 vec0, __m128 vec1 ) 51 { 52 __m128 result = _mm_mul_ps( vec0, vec1); 53 return _mm_add_ps( vec_splat( result, 0 ), _mm_add_ps( vec_splat( result, 1 ), vec_splat( result, 2 ) ) ); 54 } 55 #endif//USE_SIMD 56 57 // Project Gauss Seidel or the equivalent Sequential Impulse 58 void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) 59 { 60 #ifdef USE_SIMD 61 __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); 62 __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); 63 __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); 64 __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm))); 65 __m128 deltaVel1Dotn = _mm_add_ps(_vmathVfDot3(c.m_contactNormal.mVec128,body1.m_deltaLinearVelocity.mVec128), _vmathVfDot3(c.m_relpos1CrossNormal.mVec128,body1.m_deltaAngularVelocity.mVec128)); 66 __m128 deltaVel2Dotn = _mm_sub_ps(_vmathVfDot3(c.m_relpos2CrossNormal.mVec128,body2.m_deltaAngularVelocity.mVec128),_vmathVfDot3((c.m_contactNormal).mVec128,body2.m_deltaLinearVelocity.mVec128)); 67 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); 68 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); 69 btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); 70 btSimdScalar resultLowerLess,resultUpperLess; 71 resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); 72 resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); 73 __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); 74 deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); 75 c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); 76 __m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp); 77 deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) ); 78 c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) ); 79 __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,_mm_set1_ps(body1.m_invMass)); 80 __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,_mm_set1_ps(body2.m_invMass)); 81 __m128 impulseMagnitude = deltaImpulse; 82 body1.m_deltaLinearVelocity.mVec128 = _mm_add_ps(body1.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); 83 body1.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body1.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); 84 body2.m_deltaLinearVelocity.mVec128 = _mm_sub_ps(body2.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); 85 body2.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body2.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); 86 #else 87 resolveSingleConstraintRowGeneric(body1,body2,c); 88 #endif 89 } 90 91 // Project Gauss Seidel or the equivalent Sequential Impulse 92 void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) 93 { 94 btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; 95 const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.m_deltaLinearVelocity) + c.m_relpos1CrossNormal.dot(body1.m_deltaAngularVelocity); 96 const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.m_deltaLinearVelocity) + c.m_relpos2CrossNormal.dot(body2.m_deltaAngularVelocity); 97 98 const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn; 99 deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; 100 deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; 101 102 const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; 103 if (sum < c.m_lowerLimit) 104 { 105 deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; 106 c.m_appliedImpulse = c.m_lowerLimit; 107 } 108 else if (sum > c.m_upperLimit) 109 { 110 deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; 111 c.m_appliedImpulse = c.m_upperLimit; 112 } 113 else 114 { 115 c.m_appliedImpulse = sum; 116 } 117 if (body1.m_invMass) 118 body1.applyImpulse(c.m_contactNormal*body1.m_invMass,c.m_angularComponentA,deltaImpulse); 119 if (body2.m_invMass) 120 body2.applyImpulse(-c.m_contactNormal*body2.m_invMass,c.m_angularComponentB,deltaImpulse); 121 } 122 123 void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) 124 { 125 #ifdef USE_SIMD 126 __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); 127 __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); 128 __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); 129 __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm))); 130 __m128 deltaVel1Dotn = _mm_add_ps(_vmathVfDot3(c.m_contactNormal.mVec128,body1.m_deltaLinearVelocity.mVec128), _vmathVfDot3(c.m_relpos1CrossNormal.mVec128,body1.m_deltaAngularVelocity.mVec128)); 131 __m128 deltaVel2Dotn = _mm_sub_ps(_vmathVfDot3(c.m_relpos2CrossNormal.mVec128,body2.m_deltaAngularVelocity.mVec128),_vmathVfDot3((c.m_contactNormal).mVec128,body2.m_deltaLinearVelocity.mVec128)); 132 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); 133 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); 134 btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); 135 btSimdScalar resultLowerLess,resultUpperLess; 136 resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); 137 resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); 138 __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); 139 deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); 140 c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); 141 __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,_mm_set1_ps(body1.m_invMass)); 142 __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,_mm_set1_ps(body2.m_invMass)); 143 __m128 impulseMagnitude = deltaImpulse; 144 body1.m_deltaLinearVelocity.mVec128 = _mm_add_ps(body1.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); 145 body1.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body1.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); 146 body2.m_deltaLinearVelocity.mVec128 = _mm_sub_ps(body2.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); 147 body2.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body2.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); 148 #else 149 resolveSingleConstraintRowLowerLimit(body1,body2,c); 150 #endif 151 } 152 153 // Project Gauss Seidel or the equivalent Sequential Impulse 154 void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) 155 { 156 btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; 157 const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.m_deltaLinearVelocity) + c.m_relpos1CrossNormal.dot(body1.m_deltaAngularVelocity); 158 const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.m_deltaLinearVelocity) + c.m_relpos2CrossNormal.dot(body2.m_deltaAngularVelocity); 159 160 deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; 161 deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; 162 const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; 163 if (sum < c.m_lowerLimit) 164 { 165 deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; 166 c.m_appliedImpulse = c.m_lowerLimit; 167 } 168 else 169 { 170 c.m_appliedImpulse = sum; 171 } 172 if (body1.m_invMass) 173 body1.applyImpulse(c.m_contactNormal*body1.m_invMass,c.m_angularComponentA,deltaImpulse); 174 if (body2.m_invMass) 175 body2.applyImpulse(-c.m_contactNormal*body2.m_invMass,c.m_angularComponentB,deltaImpulse); 176 } 177 54 178 55 179 56 180 unsigned long btSequentialImpulseConstraintSolver::btRand2() 57 181 { 58 59 182 m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff; 183 return m_btSeed2; 60 184 } 61 185 … … 65 189 int btSequentialImpulseConstraintSolver::btRandInt2 (int n) 66 190 { 67 // seems good; xor-fold and modulus 68 const unsigned long un = static_cast<unsigned long>(n); 69 unsigned long r = btRand2(); 70 71 // note: probably more aggressive than it needs to be -- might be 72 // able to get away without one or two of the innermost branches. 73 if (un <= 0x00010000UL) { 74 r ^= (r >> 16); 75 if (un <= 0x00000100UL) { 76 r ^= (r >> 8); 77 if (un <= 0x00000010UL) { 78 r ^= (r >> 4); 79 if (un <= 0x00000004UL) { 80 r ^= (r >> 2); 81 if (un <= 0x00000002UL) { 82 r ^= (r >> 1); 83 } 84 } 85 } 86 } 87 } 88 89 return (int) (r % un); 90 } 91 92 93 94 95 bool MyContactDestroyedCallback(void* userPersistentData); 96 bool MyContactDestroyedCallback(void* userPersistentData) 97 { 98 assert (userPersistentData); 99 btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData; 100 btAlignedFree(cpd); 101 totalCpd--; 102 //printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData); 103 return true; 104 } 105 106 107 108 btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() 109 :m_btSeed2(0) 110 { 111 gContactDestroyedCallback = &MyContactDestroyedCallback; 112 113 //initialize default friction/contact funcs 114 int i,j; 115 for (i=0;i<MAX_CONTACT_SOLVER_TYPES;i++) 116 for (j=0;j<MAX_CONTACT_SOLVER_TYPES;j++) 117 { 118 119 m_contactDispatch[i][j] = resolveSingleCollision; 120 m_frictionDispatch[i][j] = resolveSingleFriction; 121 } 122 } 123 124 btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() 125 { 126 127 } 128 129 void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject); 130 void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject) 131 { 132 btRigidBody* rb = btRigidBody::upcast(collisionObject); 191 // seems good; xor-fold and modulus 192 const unsigned long un = static_cast<unsigned long>(n); 193 unsigned long r = btRand2(); 194 195 // note: probably more aggressive than it needs to be -- might be 196 // able to get away without one or two of the innermost branches. 197 if (un <= 0x00010000UL) { 198 r ^= (r >> 16); 199 if (un <= 0x00000100UL) { 200 r ^= (r >> 8); 201 if (un <= 0x00000010UL) { 202 r ^= (r >> 4); 203 if (un <= 0x00000004UL) { 204 r ^= (r >> 2); 205 if (un <= 0x00000002UL) { 206 r ^= (r >> 1); 207 } 208 } 209 } 210 } 211 } 212 213 return (int) (r % un); 214 } 215 216 217 218 void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject) 219 { 220 btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0; 221 222 solverBody->m_deltaLinearVelocity.setValue(0.f,0.f,0.f); 223 solverBody->m_deltaAngularVelocity.setValue(0.f,0.f,0.f); 224 133 225 if (rb) 134 226 { 135 solverBody->m_angularVelocity = rb->getAngularVelocity() ;136 solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin();137 solverBody->m_friction = collisionObject->getFriction();138 227 solverBody->m_invMass = rb->getInvMass(); 139 solverBody->m_linearVelocity = rb->getLinearVelocity();140 228 solverBody->m_originalBody = rb; 141 229 solverBody->m_angularFactor = rb->getAngularFactor(); 142 230 } else 143 231 { 144 solverBody->m_angularVelocity.setValue(0,0,0);145 solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin();146 solverBody->m_friction = collisionObject->getFriction();147 232 solverBody->m_invMass = 0.f; 148 solverBody->m_linearVelocity.setValue(0,0,0);149 233 solverBody->m_originalBody = 0; 150 234 solverBody->m_angularFactor = 1.f; 151 235 } 152 solverBody->m_pushVelocity.setValue(0.f,0.f,0.f);153 solverBody->m_turnVelocity.setValue(0.f,0.f,0.f);154 236 } 155 237 … … 157 239 int gNumSplitImpulseRecoveries = 0; 158 240 159 btScalar restitutionCurve(btScalar rel_vel, btScalar restitution); 160 btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) 241 btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution) 161 242 { 162 243 btScalar rest = restitution * -rel_vel; … … 165 246 166 247 167 void resolveSplitPenetrationImpulseCacheFriendly( 168 btSolverBody& body1, 169 btSolverBody& body2, 170 const btSolverConstraint& contactConstraint, 171 const btContactSolverInfo& solverInfo); 172 173 //SIMD_FORCE_INLINE 174 void resolveSplitPenetrationImpulseCacheFriendly( 175 btSolverBody& body1, 176 btSolverBody& body2, 177 const btSolverConstraint& contactConstraint, 178 const btContactSolverInfo& solverInfo) 179 { 180 (void)solverInfo; 181 182 if (contactConstraint.m_penetration < solverInfo.m_splitImpulsePenetrationThreshold) 183 { 184 185 gNumSplitImpulseRecoveries++; 186 btScalar normalImpulse; 187 188 // Optimized version of projected relative velocity, use precomputed cross products with normal 189 // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); 190 // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); 191 // btVector3 vel = vel1 - vel2; 192 // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); 193 194 btScalar rel_vel; 195 btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_pushVelocity) 196 + contactConstraint.m_relpos1CrossNormal.dot(body1.m_turnVelocity); 197 btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_pushVelocity) 198 + contactConstraint.m_relpos2CrossNormal.dot(body2.m_turnVelocity); 199 200 rel_vel = vel1Dotn-vel2Dotn; 201 202 203 btScalar positionalError = -contactConstraint.m_penetration * solverInfo.m_erp2/solverInfo.m_timeStep; 204 // btScalar positionalError = contactConstraint.m_penetration; 205 206 btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; 207 208 btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; 209 btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; 210 normalImpulse = penetrationImpulse+velocityImpulse; 211 212 // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse 213 btScalar oldNormalImpulse = contactConstraint.m_appliedPushImpulse; 214 btScalar sum = oldNormalImpulse + normalImpulse; 215 contactConstraint.m_appliedPushImpulse = btScalar(0.) > sum ? btScalar(0.): sum; 216 217 normalImpulse = contactConstraint.m_appliedPushImpulse - oldNormalImpulse; 218 219 body1.internalApplyPushImpulse(contactConstraint.m_contactNormal*body1.m_invMass, contactConstraint.m_angularComponentA,normalImpulse); 220 221 body2.internalApplyPushImpulse(contactConstraint.m_contactNormal*body2.m_invMass, contactConstraint.m_angularComponentB,-normalImpulse); 222 223 } 224 225 } 226 227 228 //velocity + friction 229 //response between two dynamic objects with friction 230 231 btScalar resolveSingleCollisionCombinedCacheFriendly( 232 btSolverBody& body1, 233 btSolverBody& body2, 234 const btSolverConstraint& contactConstraint, 235 const btContactSolverInfo& solverInfo); 236 237 //SIMD_FORCE_INLINE 238 btScalar resolveSingleCollisionCombinedCacheFriendly( 239 btSolverBody& body1, 240 btSolverBody& body2, 241 const btSolverConstraint& contactConstraint, 242 const btContactSolverInfo& solverInfo) 243 { 244 (void)solverInfo; 245 246 btScalar normalImpulse; 247 248 { 249 250 251 // Optimized version of projected relative velocity, use precomputed cross products with normal 252 // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); 253 // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); 254 // btVector3 vel = vel1 - vel2; 255 // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); 256 257 btScalar rel_vel; 258 btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) 259 + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); 260 btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) 261 + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); 262 263 rel_vel = vel1Dotn-vel2Dotn; 264 265 btScalar positionalError = 0.f; 266 if (!solverInfo.m_splitImpulse || (contactConstraint.m_penetration > solverInfo.m_splitImpulsePenetrationThreshold)) 267 { 268 positionalError = -contactConstraint.m_penetration * solverInfo.m_erp/solverInfo.m_timeStep; 269 } 270 271 btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; 272 273 btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; 274 btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; 275 normalImpulse = penetrationImpulse+velocityImpulse; 276 277 278 // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse 279 btScalar oldNormalImpulse = contactConstraint.m_appliedImpulse; 280 btScalar sum = oldNormalImpulse + normalImpulse; 281 contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; 282 283 normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; 284 285 body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, 286 contactConstraint.m_angularComponentA,normalImpulse); 287 288 body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, 289 contactConstraint.m_angularComponentB,-normalImpulse); 290 } 291 292 return normalImpulse; 293 } 294 295 296 #ifndef NO_FRICTION_TANGENTIALS 297 298 btScalar resolveSingleFrictionCacheFriendly( 299 btSolverBody& body1, 300 btSolverBody& body2, 301 const btSolverConstraint& contactConstraint, 302 const btContactSolverInfo& solverInfo, 303 btScalar appliedNormalImpulse); 304 305 //SIMD_FORCE_INLINE 306 btScalar resolveSingleFrictionCacheFriendly( 307 btSolverBody& body1, 308 btSolverBody& body2, 309 const btSolverConstraint& contactConstraint, 310 const btContactSolverInfo& solverInfo, 311 btScalar appliedNormalImpulse) 312 { 313 (void)solverInfo; 314 315 316 const btScalar combinedFriction = contactConstraint.m_friction; 317 318 const btScalar limit = appliedNormalImpulse * combinedFriction; 319 320 if (appliedNormalImpulse>btScalar(0.)) 321 //friction 322 { 323 324 btScalar j1; 325 { 326 327 btScalar rel_vel; 328 const btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) 329 + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); 330 const btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) 331 + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); 332 rel_vel = vel1Dotn-vel2Dotn; 333 334 // calculate j that moves us to zero relative velocity 335 j1 = -rel_vel * contactConstraint.m_jacDiagABInv; 336 #define CLAMP_ACCUMULATED_FRICTION_IMPULSE 1 337 #ifdef CLAMP_ACCUMULATED_FRICTION_IMPULSE 338 btScalar oldTangentImpulse = contactConstraint.m_appliedImpulse; 339 contactConstraint.m_appliedImpulse = oldTangentImpulse + j1; 340 341 if (limit < contactConstraint.m_appliedImpulse) 342 { 343 contactConstraint.m_appliedImpulse = limit; 344 } else 345 { 346 if (contactConstraint.m_appliedImpulse < -limit) 347 contactConstraint.m_appliedImpulse = -limit; 348 } 349 j1 = contactConstraint.m_appliedImpulse - oldTangentImpulse; 350 #else 351 if (limit < j1) 352 { 353 j1 = limit; 354 } else 355 { 356 if (j1 < -limit) 357 j1 = -limit; 358 } 359 360 #endif //CLAMP_ACCUMULATED_FRICTION_IMPULSE 361 362 //GEN_set_min(contactConstraint.m_appliedImpulse, limit); 363 //GEN_set_max(contactConstraint.m_appliedImpulse, -limit); 364 365 366 367 } 368 369 body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); 370 371 body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); 372 373 } 374 return 0.f; 375 } 376 377 378 #else 379 380 //velocity + friction 381 //response between two dynamic objects with friction 382 btScalar resolveSingleFrictionCacheFriendly( 383 btSolverBody& body1, 384 btSolverBody& body2, 385 btSolverConstraint& contactConstraint, 386 const btContactSolverInfo& solverInfo) 387 { 388 389 btVector3 vel1; 390 btVector3 vel2; 391 btScalar normalImpulse(0.f); 392 393 { 394 const btVector3& normal = contactConstraint.m_contactNormal; 395 if (contactConstraint.m_penetration < 0.f) 396 return 0.f; 397 398 399 body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); 400 body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); 401 btVector3 vel = vel1 - vel2; 402 btScalar rel_vel; 403 rel_vel = normal.dot(vel); 404 405 btVector3 lat_vel = vel - normal * rel_vel; 406 btScalar lat_rel_vel = lat_vel.length2(); 407 408 btScalar combinedFriction = contactConstraint.m_friction; 409 const btVector3& rel_pos1 = contactConstraint.m_rel_posA; 410 const btVector3& rel_pos2 = contactConstraint.m_rel_posB; 411 412 413 if (lat_rel_vel > SIMD_EPSILON*SIMD_EPSILON) 414 { 415 lat_rel_vel = btSqrt(lat_rel_vel); 416 417 lat_vel /= lat_rel_vel; 418 btVector3 temp1 = body1.m_invInertiaWorld * rel_pos1.cross(lat_vel); 419 btVector3 temp2 = body2.m_invInertiaWorld * rel_pos2.cross(lat_vel); 420 btScalar friction_impulse = lat_rel_vel / 421 (body1.m_invMass + body2.m_invMass + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); 422 btScalar normal_impulse = contactConstraint.m_appliedImpulse * combinedFriction; 423 424 GEN_set_min(friction_impulse, normal_impulse); 425 GEN_set_max(friction_impulse, -normal_impulse); 426 body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); 427 body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); 428 } 429 } 430 431 return normalImpulse; 432 } 433 434 #endif //NO_FRICTION_TANGENTIALS 435 436 248 249 void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection); 250 void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection) 251 { 252 if (colObj && colObj->hasAnisotropicFriction()) 253 { 254 // transform to local coordinates 255 btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis(); 256 const btVector3& friction_scaling = colObj->getAnisotropicFriction(); 257 //apply anisotropic friction 258 loc_lateral *= friction_scaling; 259 // ... and transform it back to global coordinates 260 frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral; 261 } 262 } 437 263 438 264 … … 440 266 btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation) 441 267 { 268 442 269 443 270 btRigidBody* body0=btRigidBody::upcast(colObj0); 444 271 btRigidBody* body1=btRigidBody::upcast(colObj1); 445 272 446 btSolverConstraint& solverConstraint = m_tmpSolverFrictionConstraintPool.expand(); 273 btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expand(); 274 memset(&solverConstraint,0xff,sizeof(btSolverConstraint)); 447 275 solverConstraint.m_contactNormal = normalAxis; 448 276 449 277 solverConstraint.m_solverBodyIdA = solverBodyIdA; 450 278 solverConstraint.m_solverBodyIdB = solverBodyIdB; 451 solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D;452 279 solverConstraint.m_frictionIndex = frictionIndex; 453 280 … … 455 282 solverConstraint.m_originalContactPoint = 0; 456 283 457 solverConstraint.m_appliedImpulse = btScalar(0.);458 solverConstraint.m_appliedPushImpulse = 0.f;459 solverConstraint.m_penetration = 0.f; 284 solverConstraint.m_appliedImpulse = 0.f; 285 // solverConstraint.m_appliedPushImpulse = 0.f; 286 460 287 { 461 288 btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); 462 289 solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; 463 solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0);464 } 465 { 466 btVector3 ftorqueAxis1 = rel_pos2.cross( solverConstraint.m_contactNormal);290 solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0); 291 } 292 { 293 btVector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal); 467 294 solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; 468 solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0);295 solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0); 469 296 } 470 297 … … 483 310 if (body1) 484 311 { 485 vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2);312 vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); 486 313 denom1 = body1->getInvMass() + normalAxis.dot(vec); 487 314 } … … 492 319 solverConstraint.m_jacDiagABInv = denom; 493 320 321 #ifdef _USE_JACOBIAN 322 solverConstraint.m_jac = btJacobianEntry ( 323 rel_pos1,rel_pos2,solverConstraint.m_contactNormal, 324 body0->getInvInertiaDiagLocal(), 325 body0->getInvMass(), 326 body1->getInvInertiaDiagLocal(), 327 body1->getInvMass()); 328 #endif //_USE_JACOBIAN 329 330 331 { 332 btScalar rel_vel; 333 btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?body0->getLinearVelocity():btVector3(0,0,0)) 334 + solverConstraint.m_relpos1CrossNormal.dot(body0?body0->getAngularVelocity():btVector3(0,0,0)); 335 btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?body1->getLinearVelocity():btVector3(0,0,0)) 336 + solverConstraint.m_relpos2CrossNormal.dot(body1?body1->getAngularVelocity():btVector3(0,0,0)); 337 338 rel_vel = vel1Dotn+vel2Dotn; 339 340 btScalar positionalError = 0.f; 341 342 btSimdScalar velocityError = - rel_vel; 343 btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv); 344 solverConstraint.m_rhs = velocityImpulse; 345 solverConstraint.m_cfm = 0.f; 346 solverConstraint.m_lowerLimit = 0; 347 solverConstraint.m_upperLimit = 1e10f; 348 } 349 494 350 return solverConstraint; 495 351 } 496 352 353 int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body) 354 { 355 int solverBodyIdA = -1; 356 357 if (body.getCompanionId() >= 0) 358 { 359 //body has already been converted 360 solverBodyIdA = body.getCompanionId(); 361 } else 362 { 363 btRigidBody* rb = btRigidBody::upcast(&body); 364 if (rb && rb->getInvMass()) 365 { 366 solverBodyIdA = m_tmpSolverBodyPool.size(); 367 btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); 368 initSolverBody(&solverBody,&body); 369 body.setCompanionId(solverBodyIdA); 370 } else 371 { 372 return 0;//assume first one is a fixed solver body 373 } 374 } 375 return solverBodyIdA; 376 } 377 #include <stdio.h> 378 379 380 381 void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal) 382 { 383 btCollisionObject* colObj0=0,*colObj1=0; 384 385 colObj0 = (btCollisionObject*)manifold->getBody0(); 386 colObj1 = (btCollisionObject*)manifold->getBody1(); 387 388 int solverBodyIdA=-1; 389 int solverBodyIdB=-1; 390 391 if (manifold->getNumContacts()) 392 { 393 solverBodyIdA = getOrInitSolverBody(*colObj0); 394 solverBodyIdB = getOrInitSolverBody(*colObj1); 395 } 396 397 ///avoid collision response between two static objects 398 if (!solverBodyIdA && !solverBodyIdB) 399 return; 400 401 btVector3 rel_pos1; 402 btVector3 rel_pos2; 403 btScalar relaxation; 404 405 for (int j=0;j<manifold->getNumContacts();j++) 406 { 407 408 btManifoldPoint& cp = manifold->getContactPoint(j); 409 410 if (cp.getDistance() <= manifold->getContactProcessingThreshold()) 411 { 412 413 const btVector3& pos1 = cp.getPositionWorldOnA(); 414 const btVector3& pos2 = cp.getPositionWorldOnB(); 415 416 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); 417 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); 418 419 420 relaxation = 1.f; 421 btScalar rel_vel; 422 btVector3 vel; 423 424 int frictionIndex = m_tmpSolverContactConstraintPool.size(); 425 426 { 427 btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expand(); 428 btRigidBody* rb0 = btRigidBody::upcast(colObj0); 429 btRigidBody* rb1 = btRigidBody::upcast(colObj1); 430 431 solverConstraint.m_solverBodyIdA = solverBodyIdA; 432 solverConstraint.m_solverBodyIdB = solverBodyIdB; 433 434 solverConstraint.m_originalContactPoint = &cp; 435 436 btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); 437 solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); 438 btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); 439 solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); 440 { 441 #ifdef COMPUTE_IMPULSE_DENOM 442 btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); 443 btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); 444 #else 445 btVector3 vec; 446 btScalar denom0 = 0.f; 447 btScalar denom1 = 0.f; 448 if (rb0) 449 { 450 vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); 451 denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); 452 } 453 if (rb1) 454 { 455 vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); 456 denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); 457 } 458 #endif //COMPUTE_IMPULSE_DENOM 459 460 btScalar denom = relaxation/(denom0+denom1); 461 solverConstraint.m_jacDiagABInv = denom; 462 } 463 464 solverConstraint.m_contactNormal = cp.m_normalWorldOnB; 465 solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB); 466 solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(-cp.m_normalWorldOnB); 467 468 469 btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); 470 btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); 471 472 vel = vel1 - vel2; 473 474 rel_vel = cp.m_normalWorldOnB.dot(vel); 475 476 btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop; 477 478 479 solverConstraint.m_friction = cp.m_combinedFriction; 480 481 btScalar restitution = 0.f; 482 483 if (cp.m_lifeTime>infoGlobal.m_restingContactRestitutionThreshold) 484 { 485 restitution = 0.f; 486 } else 487 { 488 restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); 489 if (restitution <= btScalar(0.)) 490 { 491 restitution = 0.f; 492 }; 493 } 494 495 496 ///warm starting (or zero if disabled) 497 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) 498 { 499 solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; 500 if (rb0) 501 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].applyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); 502 if (rb1) 503 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass(),-solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse); 504 } else 505 { 506 solverConstraint.m_appliedImpulse = 0.f; 507 } 508 509 // solverConstraint.m_appliedPushImpulse = 0.f; 510 511 { 512 btScalar rel_vel; 513 btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0?rb0->getLinearVelocity():btVector3(0,0,0)) 514 + solverConstraint.m_relpos1CrossNormal.dot(rb0?rb0->getAngularVelocity():btVector3(0,0,0)); 515 btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1?rb1->getLinearVelocity():btVector3(0,0,0)) 516 + solverConstraint.m_relpos2CrossNormal.dot(rb1?rb1->getAngularVelocity():btVector3(0,0,0)); 517 518 rel_vel = vel1Dotn+vel2Dotn; 519 520 btScalar positionalError = 0.f; 521 positionalError = -penetration * infoGlobal.m_erp/infoGlobal.m_timeStep; 522 btScalar velocityError = restitution - rel_vel;// * damping; 523 btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; 524 btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; 525 solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; 526 solverConstraint.m_cfm = 0.f; 527 solverConstraint.m_lowerLimit = 0; 528 solverConstraint.m_upperLimit = 1e10f; 529 } 530 531 532 /////setup the friction constraints 533 534 535 536 if (1) 537 { 538 solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size(); 539 if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized) 540 { 541 cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; 542 btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); 543 if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON) 544 { 545 cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel); 546 applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1); 547 applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1); 548 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 549 if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) 550 { 551 cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); 552 cp.m_lateralFrictionDir2.normalize();//?? 553 applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2); 554 applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2); 555 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 556 } 557 cp.m_lateralFrictionInitialized = true; 558 } else 559 { 560 //re-calculate friction direction every frame, todo: check if this is really needed 561 btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); 562 applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1); 563 applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1); 564 565 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 566 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) 567 { 568 applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2); 569 applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2); 570 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 571 } 572 cp.m_lateralFrictionInitialized = true; 573 } 574 575 } else 576 { 577 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 578 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) 579 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 580 } 581 582 if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) 583 { 584 { 585 btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex]; 586 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) 587 { 588 frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; 589 if (rb0) 590 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].applyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); 591 if (rb1) 592 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass(),-frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse); 593 } else 594 { 595 frictionConstraint1.m_appliedImpulse = 0.f; 596 } 597 } 598 599 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) 600 { 601 btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; 602 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) 603 { 604 frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; 605 if (rb0) 606 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].applyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); 607 if (rb1) 608 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-frictionConstraint2.m_appliedImpulse); 609 } else 610 { 611 frictionConstraint2.m_appliedImpulse = 0.f; 612 } 613 } 614 } else 615 { 616 btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex]; 617 frictionConstraint1.m_appliedImpulse = 0.f; 618 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) 619 { 620 btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; 621 frictionConstraint2.m_appliedImpulse = 0.f; 622 } 623 } 624 } 625 } 626 627 628 } 629 } 630 } 497 631 498 632 … … 506 640 if (!(numConstraints + numManifolds)) 507 641 { 508 // printf("empty\n");642 // printf("empty\n"); 509 643 return 0.f; 510 644 } 511 btPersistentManifold* manifold = 0; 512 btCollisionObject* colObj0=0,*colObj1=0; 513 514 //btRigidBody* rb0=0,*rb1=0; 515 516 517 #ifdef FORCE_REFESH_CONTACT_MANIFOLDS 518 519 BEGIN_PROFILE("refreshManifolds"); 520 521 int i; 522 523 524 525 for (i=0;i<numManifolds;i++) 526 { 527 manifold = manifoldPtr[i]; 528 rb1 = (btRigidBody*)manifold->getBody1(); 529 rb0 = (btRigidBody*)manifold->getBody0(); 530 531 manifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); 532 533 } 534 535 END_PROFILE("refreshManifolds"); 536 #endif //FORCE_REFESH_CONTACT_MANIFOLDS 537 538 539 540 541 542 //int sizeofSB = sizeof(btSolverBody); 543 //int sizeofSC = sizeof(btSolverConstraint); 544 545 546 //if (1) 547 { 548 //if m_stackAlloc, try to pack bodies/constraints to speed up solving 549 // btBlock* sablock; 550 // sablock = stackAlloc->beginBlock(); 551 552 // int memsize = 16; 553 // unsigned char* stackMemory = stackAlloc->allocate(memsize); 554 555 556 //todo: use stack allocator for this temp memory 557 // int minReservation = numManifolds*2; 558 559 //m_tmpSolverBodyPool.reserve(minReservation); 560 561 //don't convert all bodies, only the one we need so solver the constraints 562 /* 563 { 564 for (int i=0;i<numBodies;i++) 565 { 566 btRigidBody* rb = btRigidBody::upcast(bodies[i]); 567 if (rb && (rb->getIslandTag() >= 0)) 568 { 569 btAssert(rb->getCompanionId() < 0); 570 int solverBodyId = m_tmpSolverBodyPool.size(); 571 btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); 572 initSolverBody(&solverBody,rb); 573 rb->setCompanionId(solverBodyId); 574 } 575 } 576 } 577 */ 578 579 //m_tmpSolverConstraintPool.reserve(minReservation); 580 //m_tmpSolverFrictionConstraintPool.reserve(minReservation); 581 582 { 583 int i; 584 585 for (i=0;i<numManifolds;i++) 586 { 587 manifold = manifoldPtr[i]; 588 colObj0 = (btCollisionObject*)manifold->getBody0(); 589 colObj1 = (btCollisionObject*)manifold->getBody1(); 590 591 int solverBodyIdA=-1; 592 int solverBodyIdB=-1; 593 594 if (manifold->getNumContacts()) 595 { 596 597 598 599 if (colObj0->getIslandTag() >= 0) 600 { 601 if (colObj0->getCompanionId() >= 0) 602 { 603 //body has already been converted 604 solverBodyIdA = colObj0->getCompanionId(); 605 } else 606 { 607 solverBodyIdA = m_tmpSolverBodyPool.size(); 608 btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); 609 initSolverBody(&solverBody,colObj0); 610 colObj0->setCompanionId(solverBodyIdA); 611 } 612 } else 613 { 614 //create a static body 615 solverBodyIdA = m_tmpSolverBodyPool.size(); 616 btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); 617 initSolverBody(&solverBody,colObj0); 618 } 619 620 if (colObj1->getIslandTag() >= 0) 621 { 622 if (colObj1->getCompanionId() >= 0) 623 { 624 solverBodyIdB = colObj1->getCompanionId(); 625 } else 626 { 627 solverBodyIdB = m_tmpSolverBodyPool.size(); 628 btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); 629 initSolverBody(&solverBody,colObj1); 630 colObj1->setCompanionId(solverBodyIdB); 631 } 632 } else 633 { 634 //create a static body 635 solverBodyIdB = m_tmpSolverBodyPool.size(); 636 btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); 637 initSolverBody(&solverBody,colObj1); 638 } 639 } 640 641 btVector3 rel_pos1; 642 btVector3 rel_pos2; 643 btScalar relaxation; 644 645 for (int j=0;j<manifold->getNumContacts();j++) 646 { 647 648 btManifoldPoint& cp = manifold->getContactPoint(j); 649 650 if (cp.getDistance() <= btScalar(0.)) 651 { 652 653 const btVector3& pos1 = cp.getPositionWorldOnA(); 654 const btVector3& pos2 = cp.getPositionWorldOnB(); 655 656 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); 657 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); 658 659 660 relaxation = 1.f; 661 btScalar rel_vel; 662 btVector3 vel; 663 664 int frictionIndex = m_tmpSolverConstraintPool.size(); 665 666 { 667 btSolverConstraint& solverConstraint = m_tmpSolverConstraintPool.expand(); 668 btRigidBody* rb0 = btRigidBody::upcast(colObj0); 669 btRigidBody* rb1 = btRigidBody::upcast(colObj1); 670 671 solverConstraint.m_solverBodyIdA = solverBodyIdA; 672 solverConstraint.m_solverBodyIdB = solverBodyIdB; 673 solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D; 674 675 solverConstraint.m_originalContactPoint = &cp; 676 677 btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); 678 solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0 : btVector3(0,0,0); 679 btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); 680 solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1 : btVector3(0,0,0); 681 { 682 #ifdef COMPUTE_IMPULSE_DENOM 683 btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); 684 btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); 685 #else 686 btVector3 vec; 687 btScalar denom0 = 0.f; 688 btScalar denom1 = 0.f; 689 if (rb0) 690 { 691 vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); 692 denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); 693 } 694 if (rb1) 695 { 696 vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); 697 denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); 698 } 699 #endif //COMPUTE_IMPULSE_DENOM 700 701 btScalar denom = relaxation/(denom0+denom1); 702 solverConstraint.m_jacDiagABInv = denom; 703 } 704 705 solverConstraint.m_contactNormal = cp.m_normalWorldOnB; 706 solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB); 707 solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB); 708 709 710 btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); 711 btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); 712 713 vel = vel1 - vel2; 714 715 rel_vel = cp.m_normalWorldOnB.dot(vel); 716 717 solverConstraint.m_penetration = btMin(cp.getDistance()+infoGlobal.m_linearSlop,btScalar(0.)); 718 //solverConstraint.m_penetration = cp.getDistance(); 719 720 solverConstraint.m_friction = cp.m_combinedFriction; 721 722 723 if (cp.m_lifeTime>infoGlobal.m_restingContactRestitutionThreshold) 724 { 725 solverConstraint.m_restitution = 0.f; 726 } else 727 { 728 solverConstraint.m_restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); 729 if (solverConstraint.m_restitution <= btScalar(0.)) 730 { 731 solverConstraint.m_restitution = 0.f; 732 }; 733 } 734 735 736 btScalar penVel = -solverConstraint.m_penetration/infoGlobal.m_timeStep; 737 738 739 740 if (solverConstraint.m_restitution > penVel) 741 { 742 solverConstraint.m_penetration = btScalar(0.); 743 } 744 745 746 747 ///warm starting (or zero if disabled) 748 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) 749 { 750 solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; 751 if (rb0) 752 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); 753 if (rb1) 754 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass(),solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse); 755 } else 756 { 757 solverConstraint.m_appliedImpulse = 0.f; 758 } 759 760 solverConstraint.m_appliedPushImpulse = 0.f; 761 762 solverConstraint.m_frictionIndex = m_tmpSolverFrictionConstraintPool.size(); 763 if (!cp.m_lateralFrictionInitialized) 764 { 765 cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; 766 btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); 767 if (lat_rel_vel > SIMD_EPSILON)//0.0f) 768 { 769 cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel); 770 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 771 if(infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) 772 { 773 cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); 774 cp.m_lateralFrictionDir2.normalize();//?? 775 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 776 cp.m_lateralFrictionInitialized = true; 777 } 778 } else 779 { 780 //re-calculate friction direction every frame, todo: check if this is really needed 781 btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); 782 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 783 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 784 if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) 785 { 786 cp.m_lateralFrictionInitialized = true; 787 } 788 } 789 790 } else 791 { 792 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 793 if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) 794 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); 795 } 796 797 if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) 798 { 799 { 800 btSolverConstraint& frictionConstraint1 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex]; 801 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) 802 { 803 frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; 804 if (rb0) 805 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); 806 if (rb1) 807 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass(),frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse); 808 } else 809 { 810 frictionConstraint1.m_appliedImpulse = 0.f; 811 } 812 } 813 { 814 btSolverConstraint& frictionConstraint2 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; 815 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) 816 { 817 frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; 818 if (rb0) 819 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); 820 if (rb1) 821 m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),frictionConstraint2.m_angularComponentB,-frictionConstraint2.m_appliedImpulse); 822 } else 823 { 824 frictionConstraint2.m_appliedImpulse = 0.f; 825 } 826 } 827 } 828 } 829 830 831 } 832 } 833 } 834 } 835 } 836 837 btContactSolverInfo info = infoGlobal; 838 645 646 if (1) 839 647 { 840 648 int j; … … 845 653 } 846 654 } 847 848 849 850 int numConstraintPool = m_tmpSolverConstraintPool.size(); 851 int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); 655 656 btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); 657 initSolverBody(&fixedBody,0); 658 659 //btRigidBody* rb0=0,*rb1=0; 660 661 //if (1) 662 { 663 { 664 665 int totalNumRows = 0; 666 int i; 667 //calculate the total number of contraint rows 668 for (i=0;i<numConstraints;i++) 669 { 670 671 btTypedConstraint::btConstraintInfo1 info1; 672 constraints[i]->getInfo1(&info1); 673 totalNumRows += info1.m_numConstraintRows; 674 } 675 m_tmpSolverNonContactConstraintPool.resize(totalNumRows); 676 677 btTypedConstraint::btConstraintInfo1 info1; 678 info1.m_numConstraintRows = 0; 679 680 681 ///setup the btSolverConstraints 682 int currentRow = 0; 683 684 for (i=0;i<numConstraints;i++,currentRow+=info1.m_numConstraintRows) 685 { 686 constraints[i]->getInfo1(&info1); 687 if (info1.m_numConstraintRows) 688 { 689 btAssert(currentRow<totalNumRows); 690 691 btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow]; 692 btTypedConstraint* constraint = constraints[i]; 693 694 695 696 btRigidBody& rbA = constraint->getRigidBodyA(); 697 btRigidBody& rbB = constraint->getRigidBodyB(); 698 699 int solverBodyIdA = getOrInitSolverBody(rbA); 700 int solverBodyIdB = getOrInitSolverBody(rbB); 701 702 btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA]; 703 btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB]; 704 705 int j; 706 for ( j=0;j<info1.m_numConstraintRows;j++) 707 { 708 memset(¤tConstraintRow[j],0,sizeof(btSolverConstraint)); 709 currentConstraintRow[j].m_lowerLimit = -FLT_MAX; 710 currentConstraintRow[j].m_upperLimit = FLT_MAX; 711 currentConstraintRow[j].m_appliedImpulse = 0.f; 712 currentConstraintRow[j].m_appliedPushImpulse = 0.f; 713 currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA; 714 currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB; 715 } 716 717 bodyAPtr->m_deltaLinearVelocity.setValue(0.f,0.f,0.f); 718 bodyAPtr->m_deltaAngularVelocity.setValue(0.f,0.f,0.f); 719 bodyBPtr->m_deltaLinearVelocity.setValue(0.f,0.f,0.f); 720 bodyBPtr->m_deltaAngularVelocity.setValue(0.f,0.f,0.f); 721 722 723 724 btTypedConstraint::btConstraintInfo2 info2; 725 info2.fps = 1.f/infoGlobal.m_timeStep; 726 info2.erp = infoGlobal.m_erp; 727 info2.m_J1linearAxis = currentConstraintRow->m_contactNormal; 728 info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; 729 info2.m_J2linearAxis = 0; 730 info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; 731 info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this 732 ///the size of btSolverConstraint needs be a multiple of btScalar 733 btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); 734 info2.m_constraintError = ¤tConstraintRow->m_rhs; 735 info2.cfm = ¤tConstraintRow->m_cfm; 736 info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit; 737 info2.m_upperLimit = ¤tConstraintRow->m_upperLimit; 738 constraints[i]->getInfo2(&info2); 739 740 ///finalize the constraint setup 741 for ( j=0;j<info1.m_numConstraintRows;j++) 742 { 743 btSolverConstraint& solverConstraint = currentConstraintRow[j]; 744 745 { 746 const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal; 747 solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); 748 } 749 { 750 const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; 751 solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); 752 } 753 754 { 755 btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass(); 756 btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; 757 btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal? 758 btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; 759 760 btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal); 761 sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); 762 sum += iMJlB.dot(solverConstraint.m_contactNormal); 763 sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); 764 765 solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; 766 } 767 768 769 ///fix rhs 770 ///todo: add force/torque accelerators 771 { 772 btScalar rel_vel; 773 btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()); 774 btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()); 775 776 rel_vel = vel1Dotn+vel2Dotn; 777 778 btScalar restitution = 0.f; 779 btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 780 btScalar velocityError = restitution - rel_vel;// * damping; 781 btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; 782 btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; 783 solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; 784 solverConstraint.m_appliedImpulse = 0.f; 785 786 } 787 } 788 } 789 } 790 } 791 792 { 793 int i; 794 btPersistentManifold* manifold = 0; 795 btCollisionObject* colObj0=0,*colObj1=0; 796 797 798 for (i=0;i<numManifolds;i++) 799 { 800 manifold = manifoldPtr[i]; 801 convertContact(manifold,infoGlobal); 802 } 803 } 804 } 805 806 btContactSolverInfo info = infoGlobal; 807 808 809 810 int numConstraintPool = m_tmpSolverContactConstraintPool.size(); 811 int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size(); 852 812 853 813 ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints … … 866 826 } 867 827 868 869 870 828 return 0.f; 871 829 … … 875 833 { 876 834 BT_PROFILE("solveGroupCacheFriendlyIterations"); 877 int numConstraintPool = m_tmpSolverConstraintPool.size(); 878 int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); 835 836 int numConstraintPool = m_tmpSolverContactConstraintPool.size(); 837 int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size(); 879 838 880 839 //should traverse the contacts random order... … … 904 863 } 905 864 906 for (j=0;j<numConstraints;j++)865 if (infoGlobal.m_solverMode & SOLVER_SIMD) 907 866 { 908 btTypedConstraint* constraint = constraints[j]; 909 ///todo: use solver bodies, so we don't need to copy from/to btRigidBody 910 911 if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) 912 { 913 m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); 914 } 915 if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) 916 { 917 m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); 918 } 919 920 constraint->solveConstraint(infoGlobal.m_timeStep); 921 922 if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) 923 { 924 m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); 925 } 926 if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) 927 { 928 m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); 929 } 930 867 ///solve all joint constraints, using SIMD, if available 868 for (j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) 869 { 870 btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j]; 871 resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint); 872 } 873 874 for (j=0;j<numConstraints;j++) 875 { 876 int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA()); 877 int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB()); 878 btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; 879 btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; 880 constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep); 881 } 882 883 ///solve all contact constraints using SIMD, if available 884 int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); 885 for (j=0;j<numPoolConstraints;j++) 886 { 887 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]]; 888 resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); 889 890 } 891 ///solve all friction constraints, using SIMD, if available 892 int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size(); 893 for (j=0;j<numFrictionPoolConstraints;j++) 894 { 895 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]]; 896 btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; 897 898 if (totalImpulse>btScalar(0)) 899 { 900 solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); 901 solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; 902 903 resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); 904 } 905 } 906 } else 907 { 908 909 ///solve all joint constraints 910 for (j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) 911 { 912 btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j]; 913 resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint); 914 } 915 916 for (j=0;j<numConstraints;j++) 917 { 918 int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA()); 919 int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB()); 920 btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; 921 btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; 922 923 constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep); 924 } 925 926 ///solve all contact constraints 927 int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); 928 for (j=0;j<numPoolConstraints;j++) 929 { 930 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]]; 931 resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); 932 } 933 ///solve all friction constraints 934 int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size(); 935 for (j=0;j<numFrictionPoolConstraints;j++) 936 { 937 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]]; 938 btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; 939 940 if (totalImpulse>btScalar(0)) 941 { 942 solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); 943 solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; 944 945 resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); 946 } 947 } 931 948 } 932 949 933 { 934 int numPoolConstraints = m_tmpSolverConstraintPool.size(); 935 for (j=0;j<numPoolConstraints;j++) 936 { 937 938 const btSolverConstraint& solveManifold = m_tmpSolverConstraintPool[m_orderTmpConstraintPool[j]]; 939 resolveSingleCollisionCombinedCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], 940 m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal); 941 } 942 } 943 944 { 945 int numFrictionPoolConstraints = m_tmpSolverFrictionConstraintPool.size(); 946 947 for (j=0;j<numFrictionPoolConstraints;j++) 948 { 949 const btSolverConstraint& solveManifold = m_tmpSolverFrictionConstraintPool[m_orderFrictionConstraintPool[j]]; 950 btScalar totalImpulse = m_tmpSolverConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse+ 951 m_tmpSolverConstraintPool[solveManifold.m_frictionIndex].m_appliedPushImpulse; 952 953 resolveSingleFrictionCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], 954 m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal, 955 totalImpulse); 956 } 957 } 958 959 960 961 } 950 951 952 } 953 } 954 return 0.f; 955 } 956 957 958 959 /// btSequentialImpulseConstraintSolver Sequentially applies impulses 960 btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* /*dispatcher*/) 961 { 962 962 963 963 if (infoGlobal.m_splitImpulse) 964 { 965 966 for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++) 967 { 968 { 969 int numPoolConstraints = m_tmpSolverConstraintPool.size(); 970 int j; 971 for (j=0;j<numPoolConstraints;j++) 972 { 973 const btSolverConstraint& solveManifold = m_tmpSolverConstraintPool[m_orderTmpConstraintPool[j]]; 974 975 resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], 976 m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal); 977 } 978 } 979 } 980 981 } 982 983 } 984 985 return 0.f; 986 } 987 988 989 btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) 990 { 964 965 BT_PROFILE("solveGroup"); 966 //we only implement SOLVER_CACHE_FRIENDLY now 967 //you need to provide at least some bodies 968 btAssert(bodies); 969 btAssert(numBodies); 970 991 971 int i; 992 972 … … 994 974 solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc); 995 975 996 int numPoolConstraints = m_tmpSolverCon straintPool.size();976 int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); 997 977 int j; 978 998 979 for (j=0;j<numPoolConstraints;j++) 999 980 { 1000 1001 const btSolverConstraint& solveManifold = m_tmpSolverCon straintPool[j];981 982 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j]; 1002 983 btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint; 1003 984 btAssert(pt); … … 1005 986 if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) 1006 987 { 1007 pt->m_appliedImpulseLateral1 = m_tmpSolver FrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;1008 pt->m_appliedImpulseLateral2 = m_tmpSolver FrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;988 pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; 989 pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; 1009 990 } 1010 991 1011 992 //do a callback here? 1012 1013 993 } 1014 994 … … 1022 1002 { 1023 1003 for ( i=0;i<m_tmpSolverBodyPool.size();i++) 1024 { 1025 m_tmpSolverBodyPool[i].writebackVelocity(); 1026 } 1027 } 1028 1029 // printf("m_tmpSolverConstraintPool.size() = %i\n",m_tmpSolverConstraintPool.size()); 1030 1031 /* 1032 printf("m_tmpSolverBodyPool.size() = %i\n",m_tmpSolverBodyPool.size()); 1033 printf("m_tmpSolverConstraintPool.size() = %i\n",m_tmpSolverConstraintPool.size()); 1034 printf("m_tmpSolverFrictionConstraintPool.size() = %i\n",m_tmpSolverFrictionConstraintPool.size()); 1035 1036 1037 printf("m_tmpSolverBodyPool.capacity() = %i\n",m_tmpSolverBodyPool.capacity()); 1038 printf("m_tmpSolverConstraintPool.capacity() = %i\n",m_tmpSolverConstraintPool.capacity()); 1039 printf("m_tmpSolverFrictionConstraintPool.capacity() = %i\n",m_tmpSolverFrictionConstraintPool.capacity()); 1040 */ 1004 { 1005 m_tmpSolverBodyPool[i].writebackVelocity(); 1006 } 1007 } 1008 1041 1009 1042 1010 m_tmpSolverBodyPool.resize(0); 1043 m_tmpSolverCon straintPool.resize(0);1044 m_tmpSolver FrictionConstraintPool.resize(0);1045 1011 m_tmpSolverContactConstraintPool.resize(0); 1012 m_tmpSolverNonContactConstraintPool.resize(0); 1013 m_tmpSolverContactFrictionConstraintPool.resize(0); 1046 1014 1047 1015 return 0.f; 1048 1016 } 1049 1017 1050 /// btSequentialImpulseConstraintSolver Sequentially applies impulses 1051 btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* /*dispatcher*/) 1052 { 1053 BT_PROFILE("solveGroup"); 1054 if (infoGlobal.m_solverMode & SOLVER_CACHE_FRIENDLY) 1055 { 1056 //you need to provide at least some bodies 1057 //btSimpleDynamicsWorld needs to switch off SOLVER_CACHE_FRIENDLY 1058 btAssert(bodies); 1059 btAssert(numBodies); 1060 return solveGroupCacheFriendly(bodies,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc); 1061 } 1062 1063 1064 1065 btContactSolverInfo info = infoGlobal; 1066 1067 int numiter = infoGlobal.m_numIterations; 1068 1069 int totalPoints = 0; 1070 1071 1072 { 1073 short j; 1074 for (j=0;j<numManifolds;j++) 1075 { 1076 btPersistentManifold* manifold = manifoldPtr[j]; 1077 prepareConstraints(manifold,info,debugDrawer); 1078 1079 for (short p=0;p<manifoldPtr[j]->getNumContacts();p++) 1080 { 1081 gOrder[totalPoints].m_manifoldIndex = j; 1082 gOrder[totalPoints].m_pointIndex = p; 1083 totalPoints++; 1084 } 1085 } 1086 } 1087 1088 { 1089 int j; 1090 for (j=0;j<numConstraints;j++) 1091 { 1092 btTypedConstraint* constraint = constraints[j]; 1093 constraint->buildJacobian(); 1094 } 1095 } 1096 1097 1098 //should traverse the contacts random order... 1099 int iteration; 1100 1101 { 1102 for ( iteration = 0;iteration<numiter;iteration++) 1103 { 1104 int j; 1105 if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER) 1106 { 1107 if ((iteration & 7) == 0) { 1108 for (j=0; j<totalPoints; ++j) { 1109 btOrderIndex tmp = gOrder[j]; 1110 int swapi = btRandInt2(j+1); 1111 gOrder[j] = gOrder[swapi]; 1112 gOrder[swapi] = tmp; 1113 } 1114 } 1115 } 1116 1117 for (j=0;j<numConstraints;j++) 1118 { 1119 btTypedConstraint* constraint = constraints[j]; 1120 constraint->solveConstraint(info.m_timeStep); 1121 } 1122 1123 for (j=0;j<totalPoints;j++) 1124 { 1125 btPersistentManifold* manifold = manifoldPtr[gOrder[j].m_manifoldIndex]; 1126 solve( (btRigidBody*)manifold->getBody0(), 1127 (btRigidBody*)manifold->getBody1() 1128 ,manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); 1129 } 1130 1131 for (j=0;j<totalPoints;j++) 1132 { 1133 btPersistentManifold* manifold = manifoldPtr[gOrder[j].m_manifoldIndex]; 1134 solveFriction((btRigidBody*)manifold->getBody0(), 1135 (btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); 1136 } 1137 1138 } 1139 } 1140 1141 1142 1143 1144 return btScalar(0.); 1145 } 1146 1147 1148 1149 1150 1151 1152 1153 void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer) 1154 { 1155 1156 (void)debugDrawer; 1157 1158 btRigidBody* body0 = (btRigidBody*)manifoldPtr->getBody0(); 1159 btRigidBody* body1 = (btRigidBody*)manifoldPtr->getBody1(); 1160 1161 1162 //only necessary to refresh the manifold once (first iteration). The integration is done outside the loop 1163 { 1164 #ifdef FORCE_REFESH_CONTACT_MANIFOLDS 1165 manifoldPtr->refreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform()); 1166 #endif //FORCE_REFESH_CONTACT_MANIFOLDS 1167 int numpoints = manifoldPtr->getNumContacts(); 1168 1169 gTotalContactPoints += numpoints; 1170 1171 1172 for (int i=0;i<numpoints ;i++) 1173 { 1174 btManifoldPoint& cp = manifoldPtr->getContactPoint(i); 1175 if (cp.getDistance() <= btScalar(0.)) 1176 { 1177 const btVector3& pos1 = cp.getPositionWorldOnA(); 1178 const btVector3& pos2 = cp.getPositionWorldOnB(); 1179 1180 btVector3 rel_pos1 = pos1 - body0->getCenterOfMassPosition(); 1181 btVector3 rel_pos2 = pos2 - body1->getCenterOfMassPosition(); 1182 1183 1184 //this jacobian entry is re-used for all iterations 1185 btJacobianEntry jac(body0->getCenterOfMassTransform().getBasis().transpose(), 1186 body1->getCenterOfMassTransform().getBasis().transpose(), 1187 rel_pos1,rel_pos2,cp.m_normalWorldOnB,body0->getInvInertiaDiagLocal(),body0->getInvMass(), 1188 body1->getInvInertiaDiagLocal(),body1->getInvMass()); 1189 1190 1191 btScalar jacDiagAB = jac.getDiagonal(); 1192 1193 btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; 1194 if (cpd) 1195 { 1196 //might be invalid 1197 cpd->m_persistentLifeTime++; 1198 if (cpd->m_persistentLifeTime != cp.getLifeTime()) 1199 { 1200 //printf("Invalid: cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd->m_persistentLifeTime,cp.getLifeTime()); 1201 new (cpd) btConstraintPersistentData; 1202 cpd->m_persistentLifeTime = cp.getLifeTime(); 1203 1204 } else 1205 { 1206 //printf("Persistent: cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd->m_persistentLifeTime,cp.getLifeTime()); 1207 1208 } 1209 } else 1210 { 1211 1212 //todo: should this be in a pool? 1213 void* mem = btAlignedAlloc(sizeof(btConstraintPersistentData),16); 1214 cpd = new (mem)btConstraintPersistentData; 1215 assert(cpd); 1216 1217 totalCpd ++; 1218 //printf("totalCpd = %i Created Ptr %x\n",totalCpd,cpd); 1219 cp.m_userPersistentData = cpd; 1220 cpd->m_persistentLifeTime = cp.getLifeTime(); 1221 //printf("CREATED: %x . cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd,cpd->m_persistentLifeTime,cp.getLifeTime()); 1222 1223 } 1224 assert(cpd); 1225 1226 cpd->m_jacDiagABInv = btScalar(1.) / jacDiagAB; 1227 1228 //Dependent on Rigidbody A and B types, fetch the contact/friction response func 1229 //perhaps do a similar thing for friction/restutution combiner funcs... 1230 1231 cpd->m_frictionSolverFunc = m_frictionDispatch[body0->m_frictionSolverType][body1->m_frictionSolverType]; 1232 cpd->m_contactSolverFunc = m_contactDispatch[body0->m_contactSolverType][body1->m_contactSolverType]; 1233 1234 btVector3 vel1 = body0->getVelocityInLocalPoint(rel_pos1); 1235 btVector3 vel2 = body1->getVelocityInLocalPoint(rel_pos2); 1236 btVector3 vel = vel1 - vel2; 1237 btScalar rel_vel; 1238 rel_vel = cp.m_normalWorldOnB.dot(vel); 1239 1240 btScalar combinedRestitution = cp.m_combinedRestitution; 1241 1242 cpd->m_penetration = cp.getDistance();///btScalar(info.m_numIterations); 1243 cpd->m_friction = cp.m_combinedFriction; 1244 if (cp.m_lifeTime>info.m_restingContactRestitutionThreshold) 1245 { 1246 cpd->m_restitution = 0.f; 1247 } else 1248 { 1249 cpd->m_restitution = restitutionCurve(rel_vel, combinedRestitution); 1250 if (cpd->m_restitution <= btScalar(0.)) 1251 { 1252 cpd->m_restitution = btScalar(0.0); 1253 }; 1254 } 1255 1256 //restitution and penetration work in same direction so 1257 //rel_vel 1258 1259 btScalar penVel = -cpd->m_penetration/info.m_timeStep; 1260 1261 if (cpd->m_restitution > penVel) 1262 { 1263 cpd->m_penetration = btScalar(0.); 1264 } 1265 1266 1267 btScalar relaxation = info.m_damping; 1268 if (info.m_solverMode & SOLVER_USE_WARMSTARTING) 1269 { 1270 cpd->m_appliedImpulse *= relaxation; 1271 } else 1272 { 1273 cpd->m_appliedImpulse =btScalar(0.); 1274 } 1275 1276 //for friction 1277 cpd->m_prevAppliedImpulse = cpd->m_appliedImpulse; 1278 1279 //re-calculate friction direction every frame, todo: check if this is really needed 1280 btPlaneSpace1(cp.m_normalWorldOnB,cpd->m_frictionWorldTangential0,cpd->m_frictionWorldTangential1); 1281 1282 1283 #define NO_FRICTION_WARMSTART 1 1284 1285 #ifdef NO_FRICTION_WARMSTART 1286 cpd->m_accumulatedTangentImpulse0 = btScalar(0.); 1287 cpd->m_accumulatedTangentImpulse1 = btScalar(0.); 1288 #endif //NO_FRICTION_WARMSTART 1289 btScalar denom0 = body0->computeImpulseDenominator(pos1,cpd->m_frictionWorldTangential0); 1290 btScalar denom1 = body1->computeImpulseDenominator(pos2,cpd->m_frictionWorldTangential0); 1291 btScalar denom = relaxation/(denom0+denom1); 1292 cpd->m_jacDiagABInvTangent0 = denom; 1293 1294 1295 denom0 = body0->computeImpulseDenominator(pos1,cpd->m_frictionWorldTangential1); 1296 denom1 = body1->computeImpulseDenominator(pos2,cpd->m_frictionWorldTangential1); 1297 denom = relaxation/(denom0+denom1); 1298 cpd->m_jacDiagABInvTangent1 = denom; 1299 1300 btVector3 totalImpulse = 1301 #ifndef NO_FRICTION_WARMSTART 1302 cpd->m_frictionWorldTangential0*cpd->m_accumulatedTangentImpulse0+ 1303 cpd->m_frictionWorldTangential1*cpd->m_accumulatedTangentImpulse1+ 1304 #endif //NO_FRICTION_WARMSTART 1305 cp.m_normalWorldOnB*cpd->m_appliedImpulse; 1306 1307 1308 1309 /// 1310 { 1311 btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); 1312 cpd->m_angularComponentA = body0->getInvInertiaTensorWorld()*torqueAxis0; 1313 btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); 1314 cpd->m_angularComponentB = body1->getInvInertiaTensorWorld()*torqueAxis1; 1315 } 1316 { 1317 btVector3 ftorqueAxis0 = rel_pos1.cross(cpd->m_frictionWorldTangential0); 1318 cpd->m_frictionAngularComponent0A = body0->getInvInertiaTensorWorld()*ftorqueAxis0; 1319 } 1320 { 1321 btVector3 ftorqueAxis1 = rel_pos1.cross(cpd->m_frictionWorldTangential1); 1322 cpd->m_frictionAngularComponent1A = body0->getInvInertiaTensorWorld()*ftorqueAxis1; 1323 } 1324 { 1325 btVector3 ftorqueAxis0 = rel_pos2.cross(cpd->m_frictionWorldTangential0); 1326 cpd->m_frictionAngularComponent0B = body1->getInvInertiaTensorWorld()*ftorqueAxis0; 1327 } 1328 { 1329 btVector3 ftorqueAxis1 = rel_pos2.cross(cpd->m_frictionWorldTangential1); 1330 cpd->m_frictionAngularComponent1B = body1->getInvInertiaTensorWorld()*ftorqueAxis1; 1331 } 1332 1333 /// 1334 1335 1336 1337 //apply previous frames impulse on both bodies 1338 body0->applyImpulse(totalImpulse, rel_pos1); 1339 body1->applyImpulse(-totalImpulse, rel_pos2); 1340 } 1341 1342 } 1343 } 1344 } 1345 1346 1347 btScalar btSequentialImpulseConstraintSolver::solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) 1348 { 1349 btScalar maxImpulse = btScalar(0.); 1350 1351 { 1352 1353 1354 { 1355 if (cp.getDistance() <= btScalar(0.)) 1356 { 1357 1358 1359 1360 { 1361 1362 //btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; 1363 btScalar impulse = resolveSingleCollisionCombined( 1364 *body0,*body1, 1365 cp, 1366 info); 1367 1368 if (maxImpulse < impulse) 1369 maxImpulse = impulse; 1370 1371 } 1372 } 1373 } 1374 } 1375 return maxImpulse; 1376 } 1377 1378 1379 1380 btScalar btSequentialImpulseConstraintSolver::solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) 1381 { 1382 1383 btScalar maxImpulse = btScalar(0.); 1384 1385 { 1386 1387 1388 { 1389 if (cp.getDistance() <= btScalar(0.)) 1390 { 1391 1392 1393 1394 { 1395 1396 btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; 1397 btScalar impulse = cpd->m_contactSolverFunc( 1398 *body0,*body1, 1399 cp, 1400 info); 1401 1402 if (maxImpulse < impulse) 1403 maxImpulse = impulse; 1404 1405 } 1406 } 1407 } 1408 } 1409 return maxImpulse; 1410 } 1411 1412 btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) 1413 { 1414 1415 (void)debugDrawer; 1416 (void)iter; 1417 1418 1419 { 1420 1421 1422 { 1423 1424 if (cp.getDistance() <= btScalar(0.)) 1425 { 1426 1427 btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; 1428 cpd->m_frictionSolverFunc( 1429 *body0,*body1, 1430 cp, 1431 info); 1432 1433 1434 } 1435 } 1436 1437 1438 } 1439 return btScalar(0.); 1440 } 1018 1019 1020 1021 1022 1023 1441 1024 1442 1025 -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
r2662 r2882 24 24 25 25 26 ///The btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses 27 ///The approach is the 3D version of Erin Catto's GDC 2006 tutorial. See http://www.gphysics.com 28 ///Although Sequential Impulse is more intuitive, it is mathematically equivalent to Projected Successive Overrelaxation (iterative LCP) 29 ///Applies impulses for combined restitution and penetration recovery and to simulate friction 26 27 ///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method. 30 28 class btSequentialImpulseConstraintSolver : public btConstraintSolver 31 29 { 30 protected: 32 31 33 32 btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool; 34 btAlignedObjectArray<btSolverConstraint> m_tmpSolverConstraintPool; 35 btAlignedObjectArray<btSolverConstraint> m_tmpSolverFrictionConstraintPool; 33 btConstraintArray m_tmpSolverContactConstraintPool; 34 btConstraintArray m_tmpSolverNonContactConstraintPool; 35 btConstraintArray m_tmpSolverContactFrictionConstraintPool; 36 36 btAlignedObjectArray<int> m_orderTmpConstraintPool; 37 37 btAlignedObjectArray<int> m_orderFrictionConstraintPool; 38 38 39 40 protected:41 btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);42 btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);43 void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer);44 39 btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation); 45 46 ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES];47 ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES];48 49 40 50 41 ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction 51 42 unsigned long m_btSeed2; 52 43 44 void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject); 45 btScalar restitutionCurve(btScalar rel_vel, btScalar restitution); 46 47 void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal); 48 49 void resolveSplitPenetrationImpulseCacheFriendly( 50 btSolverBody& body1, 51 btSolverBody& body2, 52 const btSolverConstraint& contactConstraint, 53 const btContactSolverInfo& solverInfo); 54 55 //internal method 56 int getOrInitSolverBody(btCollisionObject& body); 57 58 void resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& contactConstraint); 59 60 void resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& contactConstraint); 61 62 void resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& contactConstraint); 63 64 void resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& contactConstraint); 65 53 66 public: 54 67 55 68 56 69 btSequentialImpulseConstraintSolver(); 70 virtual ~btSequentialImpulseConstraintSolver(); 57 71 58 ///Advanced: Override the default contact solving function for contacts, for certain types of rigidbody 59 ///See btRigidBody::m_contactSolverType and btRigidBody::m_frictionSolverType 60 void setContactSolverFunc(ContactSolverFunc func,int type0,int type1) 61 { 62 m_contactDispatch[type0][type1] = func; 63 } 72 virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); 64 73 65 ///Advanced: Override the default friction solving function for contacts, for certain types of rigidbody 66 ///See btRigidBody::m_contactSolverType and btRigidBody::m_frictionSolverType 67 void SetFrictionSolverFunc(ContactSolverFunc func,int type0,int type1) 68 { 69 m_frictionDispatch[type0][type1] = func; 70 } 71 72 virtual ~btSequentialImpulseConstraintSolver(); 73 74 virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); 75 76 virtual btScalar solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); 74 btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); 77 75 btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); 78 btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);79 80 76 81 77 ///clear internal cached data and reset random seed 82 78 virtual void reset(); 83 84 btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);85 86 87 79 88 80 unsigned long btRand2(); -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
r2662 r2882 69 69 btSliderConstraint::btSliderConstraint() 70 70 :btTypedConstraint(SLIDER_CONSTRAINT_TYPE), 71 m_useLinearReferenceFrameA(true) 71 m_useLinearReferenceFrameA(true), 72 m_useSolveConstraintObsolete(false) 73 // m_useSolveConstraintObsolete(true) 72 74 { 73 75 initParams(); … … 80 82 , m_frameInA(frameInA) 81 83 , m_frameInB(frameInB), 82 m_useLinearReferenceFrameA(useLinearReferenceFrameA) 84 m_useLinearReferenceFrameA(useLinearReferenceFrameA), 85 m_useSolveConstraintObsolete(false) 86 // m_useSolveConstraintObsolete(true) 83 87 { 84 88 initParams(); … … 89 93 void btSliderConstraint::buildJacobian() 90 94 { 95 if (!m_useSolveConstraintObsolete) 96 { 97 return; 98 } 91 99 if(m_useLinearReferenceFrameA) 92 100 { … … 156 164 //----------------------------------------------------------------------------- 157 165 158 void btSliderConstraint:: solveConstraint(btScalar timeStep)159 { 160 m_timeStep = timeStep; 161 if(m_useLinearReferenceFrameA)162 {163 solveConstraintInt(m_rbA, m_rbB);166 void btSliderConstraint::getInfo1(btConstraintInfo1* info) 167 { 168 if (m_useSolveConstraintObsolete) 169 { 170 info->m_numConstraintRows = 0; 171 info->nub = 0; 164 172 } 165 173 else 166 174 { 167 solveConstraintInt(m_rbB, m_rbA); 175 info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular 176 info->nub = 2; 177 //prepare constraint 178 calculateTransforms(); 179 testLinLimits(); 180 if(getSolveLinLimit() || getPoweredLinMotor()) 181 { 182 info->m_numConstraintRows++; // limit 3rd linear as well 183 info->nub--; 184 } 185 testAngLimits(); 186 if(getSolveAngLimit() || getPoweredAngMotor()) 187 { 188 info->m_numConstraintRows++; // limit 3rd angular as well 189 info->nub--; 190 } 191 } 192 } // btSliderConstraint::getInfo1() 193 194 //----------------------------------------------------------------------------- 195 196 void btSliderConstraint::getInfo2(btConstraintInfo2* info) 197 { 198 btAssert(!m_useSolveConstraintObsolete); 199 int i, s = info->rowskip; 200 const btTransform& trA = getCalculatedTransformA(); 201 const btTransform& trB = getCalculatedTransformB(); 202 btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f); 203 // make rotations around Y and Z equal 204 // the slider axis should be the only unconstrained 205 // rotational axis, the angular velocity of the two bodies perpendicular to 206 // the slider axis should be equal. thus the constraint equations are 207 // p*w1 - p*w2 = 0 208 // q*w1 - q*w2 = 0 209 // where p and q are unit vectors normal to the slider axis, and w1 and w2 210 // are the angular velocity vectors of the two bodies. 211 // get slider axis (X) 212 btVector3 ax1 = trA.getBasis().getColumn(0); 213 // get 2 orthos to slider axis (Y, Z) 214 btVector3 p = trA.getBasis().getColumn(1); 215 btVector3 q = trA.getBasis().getColumn(2); 216 // set the two slider rows 217 info->m_J1angularAxis[0] = p[0]; 218 info->m_J1angularAxis[1] = p[1]; 219 info->m_J1angularAxis[2] = p[2]; 220 info->m_J1angularAxis[s+0] = q[0]; 221 info->m_J1angularAxis[s+1] = q[1]; 222 info->m_J1angularAxis[s+2] = q[2]; 223 224 info->m_J2angularAxis[0] = -p[0]; 225 info->m_J2angularAxis[1] = -p[1]; 226 info->m_J2angularAxis[2] = -p[2]; 227 info->m_J2angularAxis[s+0] = -q[0]; 228 info->m_J2angularAxis[s+1] = -q[1]; 229 info->m_J2angularAxis[s+2] = -q[2]; 230 // compute the right hand side of the constraint equation. set relative 231 // body velocities along p and q to bring the slider back into alignment. 232 // if ax1,ax2 are the unit length slider axes as computed from body1 and 233 // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). 234 // if "theta" is the angle between ax1 and ax2, we need an angular velocity 235 // along u to cover angle erp*theta in one step : 236 // |angular_velocity| = angle/time = erp*theta / stepsize 237 // = (erp*fps) * theta 238 // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| 239 // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) 240 // ...as ax1 and ax2 are unit length. if theta is smallish, 241 // theta ~= sin(theta), so 242 // angular_velocity = (erp*fps) * (ax1 x ax2) 243 // ax1 x ax2 is in the plane space of ax1, so we project the angular 244 // velocity to p and q to find the right hand side. 245 btScalar k = info->fps * info->erp * getSoftnessOrthoAng(); 246 btVector3 ax2 = trB.getBasis().getColumn(0); 247 btVector3 u = ax1.cross(ax2); 248 info->m_constraintError[0] = k * u.dot(p); 249 info->m_constraintError[s] = k * u.dot(q); 250 // pull out pos and R for both bodies. also get the connection 251 // vector c = pos2-pos1. 252 // next two rows. we want: vel2 = vel1 + w1 x c ... but this would 253 // result in three equations, so we project along the planespace vectors 254 // so that sliding along the slider axis is disregarded. for symmetry we 255 // also consider rotation around center of mass of two bodies (factA and factB). 256 btTransform bodyA_trans = m_rbA.getCenterOfMassTransform(); 257 btTransform bodyB_trans = m_rbB.getCenterOfMassTransform(); 258 int s2 = 2 * s, s3 = 3 * s; 259 btVector3 c; 260 btScalar miA = m_rbA.getInvMass(); 261 btScalar miB = m_rbB.getInvMass(); 262 btScalar miS = miA + miB; 263 btScalar factA, factB; 264 if(miS > btScalar(0.f)) 265 { 266 factA = miB / miS; 267 } 268 else 269 { 270 factA = btScalar(0.5f); 271 } 272 if(factA > 0.99f) factA = 0.99f; 273 if(factA < 0.01f) factA = 0.01f; 274 factB = btScalar(1.0f) - factA; 275 c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin(); 276 btVector3 tmp = c.cross(p); 277 for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i]; 278 for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i]; 279 tmp = c.cross(q); 280 for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i]; 281 for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i]; 282 283 for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; 284 for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; 285 // compute two elements of right hand side. we want to align the offset 286 // point (in body 2's frame) with the center of body 1. 287 btVector3 ofs; // offset point in global coordinates 288 ofs = trB.getOrigin() - trA.getOrigin(); 289 k = info->fps * info->erp * getSoftnessOrthoLin(); 290 info->m_constraintError[s2] = k * p.dot(ofs); 291 info->m_constraintError[s3] = k * q.dot(ofs); 292 int nrow = 3; // last filled row 293 int srow; 294 // check linear limits linear 295 btScalar limit_err = btScalar(0.0); 296 int limit = 0; 297 if(getSolveLinLimit()) 298 { 299 limit_err = getLinDepth() * signFact; 300 limit = (limit_err > btScalar(0.0)) ? 2 : 1; 301 } 302 int powered = 0; 303 if(getPoweredLinMotor()) 304 { 305 powered = 1; 306 } 307 // if the slider has joint limits or motor, add in the extra row 308 if (limit || powered) 309 { 310 nrow++; 311 srow = nrow * info->rowskip; 312 info->m_J1linearAxis[srow+0] = ax1[0]; 313 info->m_J1linearAxis[srow+1] = ax1[1]; 314 info->m_J1linearAxis[srow+2] = ax1[2]; 315 // linear torque decoupling step: 316 // 317 // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies 318 // do not create a torque couple. in other words, the points that the 319 // constraint force is applied at must lie along the same ax1 axis. 320 // a torque couple will result in limited slider-jointed free 321 // bodies from gaining angular momentum. 322 // the solution used here is to apply the constraint forces at the center of mass of the two bodies 323 btVector3 ltd; // Linear Torque Decoupling vector (a torque) 324 // c = btScalar(0.5) * c; 325 ltd = c.cross(ax1); 326 info->m_J1angularAxis[srow+0] = factA*ltd[0]; 327 info->m_J1angularAxis[srow+1] = factA*ltd[1]; 328 info->m_J1angularAxis[srow+2] = factA*ltd[2]; 329 info->m_J2angularAxis[srow+0] = factB*ltd[0]; 330 info->m_J2angularAxis[srow+1] = factB*ltd[1]; 331 info->m_J2angularAxis[srow+2] = factB*ltd[2]; 332 // right-hand part 333 btScalar lostop = getLowerLinLimit(); 334 btScalar histop = getUpperLinLimit(); 335 if(limit && (lostop == histop)) 336 { // the joint motor is ineffective 337 powered = 0; 338 } 339 info->m_constraintError[srow] = 0.; 340 info->m_lowerLimit[srow] = 0.; 341 info->m_upperLimit[srow] = 0.; 342 if(powered) 343 { 344 info->cfm[nrow] = btScalar(0.0); 345 btScalar tag_vel = getTargetLinMotorVelocity(); 346 btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * info->erp); 347 // info->m_constraintError[srow] += mot_fact * getTargetLinMotorVelocity(); 348 info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity(); 349 info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps; 350 info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps; 351 } 352 if(limit) 353 { 354 k = info->fps * info->erp; 355 info->m_constraintError[srow] += k * limit_err; 356 info->cfm[srow] = btScalar(0.0); // stop_cfm; 357 if(lostop == histop) 358 { // limited low and high simultaneously 359 info->m_lowerLimit[srow] = -SIMD_INFINITY; 360 info->m_upperLimit[srow] = SIMD_INFINITY; 361 } 362 else if(limit == 1) 363 { // low limit 364 info->m_lowerLimit[srow] = -SIMD_INFINITY; 365 info->m_upperLimit[srow] = 0; 366 } 367 else 368 { // high limit 369 info->m_lowerLimit[srow] = 0; 370 info->m_upperLimit[srow] = SIMD_INFINITY; 371 } 372 // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that) 373 btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin()); 374 if(bounce > btScalar(0.0)) 375 { 376 btScalar vel = m_rbA.getLinearVelocity().dot(ax1); 377 vel -= m_rbB.getLinearVelocity().dot(ax1); 378 vel *= signFact; 379 // only apply bounce if the velocity is incoming, and if the 380 // resulting c[] exceeds what we already have. 381 if(limit == 1) 382 { // low limit 383 if(vel < 0) 384 { 385 btScalar newc = -bounce * vel; 386 if (newc > info->m_constraintError[srow]) 387 { 388 info->m_constraintError[srow] = newc; 389 } 390 } 391 } 392 else 393 { // high limit - all those computations are reversed 394 if(vel > 0) 395 { 396 btScalar newc = -bounce * vel; 397 if(newc < info->m_constraintError[srow]) 398 { 399 info->m_constraintError[srow] = newc; 400 } 401 } 402 } 403 } 404 info->m_constraintError[srow] *= getSoftnessLimLin(); 405 } // if(limit) 406 } // if linear limit 407 // check angular limits 408 limit_err = btScalar(0.0); 409 limit = 0; 410 if(getSolveAngLimit()) 411 { 412 limit_err = getAngDepth(); 413 limit = (limit_err > btScalar(0.0)) ? 1 : 2; 414 } 415 // if the slider has joint limits, add in the extra row 416 powered = 0; 417 if(getPoweredAngMotor()) 418 { 419 powered = 1; 420 } 421 if(limit || powered) 422 { 423 nrow++; 424 srow = nrow * info->rowskip; 425 info->m_J1angularAxis[srow+0] = ax1[0]; 426 info->m_J1angularAxis[srow+1] = ax1[1]; 427 info->m_J1angularAxis[srow+2] = ax1[2]; 428 429 info->m_J2angularAxis[srow+0] = -ax1[0]; 430 info->m_J2angularAxis[srow+1] = -ax1[1]; 431 info->m_J2angularAxis[srow+2] = -ax1[2]; 432 433 btScalar lostop = getLowerAngLimit(); 434 btScalar histop = getUpperAngLimit(); 435 if(limit && (lostop == histop)) 436 { // the joint motor is ineffective 437 powered = 0; 438 } 439 if(powered) 440 { 441 info->cfm[srow] = btScalar(0.0); 442 btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * info->erp); 443 info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity(); 444 info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps; 445 info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps; 446 } 447 if(limit) 448 { 449 k = info->fps * info->erp; 450 info->m_constraintError[srow] += k * limit_err; 451 info->cfm[srow] = btScalar(0.0); // stop_cfm; 452 if(lostop == histop) 453 { 454 // limited low and high simultaneously 455 info->m_lowerLimit[srow] = -SIMD_INFINITY; 456 info->m_upperLimit[srow] = SIMD_INFINITY; 457 } 458 else if(limit == 1) 459 { // low limit 460 info->m_lowerLimit[srow] = 0; 461 info->m_upperLimit[srow] = SIMD_INFINITY; 462 } 463 else 464 { // high limit 465 info->m_lowerLimit[srow] = -SIMD_INFINITY; 466 info->m_upperLimit[srow] = 0; 467 } 468 // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) 469 btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng()); 470 if(bounce > btScalar(0.0)) 471 { 472 btScalar vel = m_rbA.getAngularVelocity().dot(ax1); 473 vel -= m_rbB.getAngularVelocity().dot(ax1); 474 // only apply bounce if the velocity is incoming, and if the 475 // resulting c[] exceeds what we already have. 476 if(limit == 1) 477 { // low limit 478 if(vel < 0) 479 { 480 btScalar newc = -bounce * vel; 481 if(newc > info->m_constraintError[srow]) 482 { 483 info->m_constraintError[srow] = newc; 484 } 485 } 486 } 487 else 488 { // high limit - all those computations are reversed 489 if(vel > 0) 490 { 491 btScalar newc = -bounce * vel; 492 if(newc < info->m_constraintError[srow]) 493 { 494 info->m_constraintError[srow] = newc; 495 } 496 } 497 } 498 } 499 info->m_constraintError[srow] *= getSoftnessLimAng(); 500 } // if(limit) 501 } // if angular limit or powered 502 } // btSliderConstraint::getInfo2() 503 504 //----------------------------------------------------------------------------- 505 506 void btSliderConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) 507 { 508 if (m_useSolveConstraintObsolete) 509 { 510 m_timeStep = timeStep; 511 if(m_useLinearReferenceFrameA) 512 { 513 solveConstraintInt(m_rbA,bodyA, m_rbB,bodyB); 514 } 515 else 516 { 517 solveConstraintInt(m_rbB,bodyB, m_rbA,bodyA); 518 } 168 519 } 169 520 } // btSliderConstraint::solveConstraint() … … 171 522 //----------------------------------------------------------------------------- 172 523 173 void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, bt RigidBody& rbB)524 void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB) 174 525 { 175 526 int i; 176 527 // linear 177 btVector3 velA = rbA.getVelocityInLocalPoint(m_relPosA); 178 btVector3 velB = rbB.getVelocityInLocalPoint(m_relPosB); 528 btVector3 velA; 529 bodyA.getVelocityInLocalPointObsolete(m_relPosA,velA); 530 btVector3 velB; 531 bodyB.getVelocityInLocalPointObsolete(m_relPosB,velB); 179 532 btVector3 vel = velA - velB; 180 533 for(i = 0; i < 3; i++) … … 191 544 btScalar normalImpulse = softness * (restitution * depth / m_timeStep - damping * rel_vel) * m_jacLinDiagABInv[i]; 192 545 btVector3 impulse_vector = normal * normalImpulse; 193 rbA.applyImpulse( impulse_vector, m_relPosA); 194 rbB.applyImpulse(-impulse_vector, m_relPosB); 546 547 //rbA.applyImpulse( impulse_vector, m_relPosA); 548 //rbB.applyImpulse(-impulse_vector, m_relPosB); 549 { 550 btVector3 ftorqueAxis1 = m_relPosA.cross(normal); 551 btVector3 ftorqueAxis2 = m_relPosB.cross(normal); 552 bodyA.applyImpulse(normal*rbA.getInvMass(), rbA.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse); 553 bodyB.applyImpulse(normal*rbB.getInvMass(), rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse); 554 } 555 556 557 195 558 if(m_poweredLinMotor && (!i)) 196 559 { // apply linear motor … … 218 581 // apply clamped impulse 219 582 impulse_vector = normal * normalImpulse; 220 rbA.applyImpulse( impulse_vector, m_relPosA); 221 rbB.applyImpulse(-impulse_vector, m_relPosB); 583 //rbA.applyImpulse( impulse_vector, m_relPosA); 584 //rbB.applyImpulse(-impulse_vector, m_relPosB); 585 586 { 587 btVector3 ftorqueAxis1 = m_relPosA.cross(normal); 588 btVector3 ftorqueAxis2 = m_relPosB.cross(normal); 589 bodyA.applyImpulse(normal*rbA.getInvMass(), rbA.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse); 590 bodyB.applyImpulse(normal*rbB.getInvMass(), rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse); 591 } 592 593 594 222 595 } 223 596 } … … 228 601 btVector3 axisB = m_calculatedTransformB.getBasis().getColumn(0); 229 602 230 const btVector3& angVelA = rbA.getAngularVelocity(); 231 const btVector3& angVelB = rbB.getAngularVelocity(); 603 btVector3 angVelA; 604 bodyA.getAngularVelocity(angVelA); 605 btVector3 angVelB; 606 bodyB.getAngularVelocity(angVelB); 232 607 233 608 btVector3 angVelAroundAxisA = axisA * axisA.dot(angVelA); … … 239 614 //solve orthogonal angular velocity correction 240 615 btScalar len = velrelOrthog.length(); 616 btScalar orthorImpulseMag = 0.f; 617 241 618 if (len > btScalar(0.00001)) 242 619 { 243 620 btVector3 normal = velrelOrthog.normalized(); 244 621 btScalar denom = rbA.computeAngularImpulseDenominator(normal) + rbB.computeAngularImpulseDenominator(normal); 245 velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng; 622 //velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng; 623 orthorImpulseMag = (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng; 246 624 } 247 625 //solve angular positional correction 248 626 btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/m_timeStep); 627 btVector3 angularAxis = angularError; 628 btScalar angularImpulseMag = 0; 629 249 630 btScalar len2 = angularError.length(); 250 631 if (len2>btScalar(0.00001)) … … 252 633 btVector3 normal2 = angularError.normalized(); 253 634 btScalar denom2 = rbA.computeAngularImpulseDenominator(normal2) + rbB.computeAngularImpulseDenominator(normal2); 254 angularError *= (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng; 635 angularImpulseMag = (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng; 636 angularError *= angularImpulseMag; 255 637 } 256 638 // apply impulse 257 rbA.applyTorqueImpulse(-velrelOrthog+angularError); 258 rbB.applyTorqueImpulse(velrelOrthog-angularError); 639 //rbA.applyTorqueImpulse(-velrelOrthog+angularError); 640 //rbB.applyTorqueImpulse(velrelOrthog-angularError); 641 642 bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*velrelOrthog,-orthorImpulseMag); 643 bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*velrelOrthog,orthorImpulseMag); 644 bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*angularAxis,angularImpulseMag); 645 bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*angularAxis,-angularImpulseMag); 646 647 259 648 btScalar impulseMag; 260 649 //solve angular limits … … 270 659 } 271 660 btVector3 impulse = axisA * impulseMag; 272 rbA.applyTorqueImpulse(impulse); 273 rbB.applyTorqueImpulse(-impulse); 661 //rbA.applyTorqueImpulse(impulse); 662 //rbB.applyTorqueImpulse(-impulse); 663 664 bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*axisA,impulseMag); 665 bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*axisA,-impulseMag); 666 667 668 274 669 //apply angular motor 275 670 if(m_poweredAngMotor) … … 302 697 // apply clamped impulse 303 698 btVector3 motorImp = angImpulse * axisA; 304 m_rbA.applyTorqueImpulse(motorImp); 305 m_rbB.applyTorqueImpulse(-motorImp); 699 //rbA.applyTorqueImpulse(motorImp); 700 //rbB.applyTorqueImpulse(-motorImp); 701 702 bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*axisA,angImpulse); 703 bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*axisA,-angImpulse); 306 704 } 307 705 } … … 313 711 314 712 void btSliderConstraint::calculateTransforms(void){ 315 if(m_useLinearReferenceFrameA )713 if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete)) 316 714 { 317 715 m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; … … 326 724 m_realPivotBInW = m_calculatedTransformB.getOrigin(); 327 725 m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X 328 m_delta = m_realPivotBInW - m_realPivotAInW; 726 if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete) 727 { 728 m_delta = m_realPivotBInW - m_realPivotAInW; 729 } 730 else 731 { 732 m_delta = m_realPivotAInW - m_realPivotBInW; 733 } 329 734 m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; 330 735 btVector3 normalWorld; … … 368 773 369 774 //----------------------------------------------------------------------------- 370 371 775 372 776 void btSliderConstraint::testAngLimits(void) … … 380 784 const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1); 381 785 btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); 786 m_angPos = rot; 382 787 if(rot < m_lowerAngLimit) 383 788 { … … 392 797 } 393 798 } // btSliderConstraint::testAngLimits() 394 395 799 396 800 //----------------------------------------------------------------------------- 397 398 399 801 400 802 btVector3 btSliderConstraint::getAncorInA(void) -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h
r2662 r2882 47 47 { 48 48 protected: 49 ///for backwards compatibility during the transition to 'getInfo/getInfo2' 50 bool m_useSolveConstraintObsolete; 49 51 btTransform m_frameInA; 50 52 btTransform m_frameInB; … … 105 107 106 108 btScalar m_linPos; 109 btScalar m_angPos; 107 110 108 111 btScalar m_angDepth; … … 127 130 // overrides 128 131 virtual void buildJacobian(); 129 virtual void solveConstraint(btScalar timeStep); 132 virtual void getInfo1 (btConstraintInfo1* info); 133 134 virtual void getInfo2 (btConstraintInfo2* info); 135 136 virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); 137 138 130 139 // access 131 140 const btRigidBody& getRigidBodyA() const { return m_rbA; } … … 195 204 btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; } 196 205 btScalar getLinearPos() { return m_linPos; } 206 197 207 198 208 // access for ODE solver … … 203 213 // internal 204 214 void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB); 205 void solveConstraintInt(btRigidBody& rbA, bt RigidBody& rbB);215 void solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB); 206 216 // shared code used by ODE solver 207 217 void calculateTransforms(void); 208 218 void testLinLimits(void); 219 void testLinLimits2(btConstraintInfo2* info); 209 220 void testAngLimits(void); 210 221 // access for PE Solver -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h
r2662 r2882 24 24 #include "LinearMath/btTransformUtil.h" 25 25 26 ///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision 27 #ifdef BT_USE_SSE 28 #define USE_SIMD 1 29 #endif // 30 31 32 #ifdef USE_SIMD 33 34 struct btSimdScalar 35 { 36 SIMD_FORCE_INLINE btSimdScalar() 37 { 38 39 } 40 41 SIMD_FORCE_INLINE btSimdScalar(float fl) 42 :m_vec128 (_mm_set1_ps(fl)) 43 { 44 } 45 46 SIMD_FORCE_INLINE btSimdScalar(__m128 v128) 47 :m_vec128(v128) 48 { 49 } 50 union 51 { 52 __m128 m_vec128; 53 float m_floats[4]; 54 int m_ints[4]; 55 btScalar m_unusedPadding; 56 }; 57 SIMD_FORCE_INLINE __m128 get128() 58 { 59 return m_vec128; 60 } 61 62 SIMD_FORCE_INLINE const __m128 get128() const 63 { 64 return m_vec128; 65 } 66 67 SIMD_FORCE_INLINE void set128(__m128 v128) 68 { 69 m_vec128 = v128; 70 } 71 72 SIMD_FORCE_INLINE operator __m128() 73 { 74 return m_vec128; 75 } 76 SIMD_FORCE_INLINE operator const __m128() const 77 { 78 return m_vec128; 79 } 80 81 SIMD_FORCE_INLINE operator float() const 82 { 83 return m_floats[0]; 84 } 85 86 }; 87 88 ///@brief Return the elementwise product of two btSimdScalar 89 SIMD_FORCE_INLINE btSimdScalar 90 operator*(const btSimdScalar& v1, const btSimdScalar& v2) 91 { 92 return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128())); 93 } 94 95 ///@brief Return the elementwise product of two btSimdScalar 96 SIMD_FORCE_INLINE btSimdScalar 97 operator+(const btSimdScalar& v1, const btSimdScalar& v2) 98 { 99 return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128())); 100 } 101 102 103 #else 104 #define btSimdScalar btScalar 105 #endif 26 106 27 107 ///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. … … 29 109 { 30 110 BT_DECLARE_ALIGNED_ALLOCATOR(); 111 btVector3 m_deltaLinearVelocity; 112 btVector3 m_deltaAngularVelocity; 113 btScalar m_angularFactor; 114 btScalar m_invMass; 115 btScalar m_friction; 116 btRigidBody* m_originalBody; 117 btVector3 m_pushVelocity; 118 //btVector3 m_turnVelocity; 119 31 120 32 btMatrix3x3 m_worldInvInertiaTensor; 33 34 btVector3 m_angularVelocity; 35 btVector3 m_linearVelocity; 36 btVector3 m_centerOfMassPosition; 37 btVector3 m_pushVelocity; 38 btVector3 m_turnVelocity; 39 40 float m_angularFactor; 41 float m_invMass; 42 float m_friction; 43 btRigidBody* m_originalBody; 44 45 46 SIMD_FORCE_INLINE void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const 121 SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const 47 122 { 48 velocity = m_linearVelocity + m_angularVelocity.cross(rel_pos); 123 if (m_originalBody) 124 velocity = m_originalBody->getLinearVelocity()+m_deltaLinearVelocity + (m_originalBody->getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos); 125 else 126 velocity.setValue(0,0,0); 49 127 } 50 128 129 SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const 130 { 131 if (m_originalBody) 132 angVel = m_originalBody->getAngularVelocity()+m_deltaAngularVelocity; 133 else 134 angVel.setValue(0,0,0); 135 } 136 137 51 138 //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position 52 SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)139 SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude) 53 140 { 54 if (m_invMass)141 //if (m_invMass) 55 142 { 56 m_linearVelocity += linearComponent*impulseMagnitude; 57 m_angularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); 58 } 59 } 60 61 SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) 62 { 63 if (m_invMass) 64 { 65 m_pushVelocity += linearComponent*impulseMagnitude; 66 m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor); 143 m_deltaLinearVelocity += linearComponent*impulseMagnitude; 144 m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); 67 145 } 68 146 } 69 147 148 149 /* 70 150 71 151 void writebackVelocity() … … 73 153 if (m_invMass) 74 154 { 75 m_originalBody->setLinearVelocity(m_ linearVelocity);76 m_originalBody->setAngularVelocity(m_ angularVelocity);155 m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity); 156 m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity); 77 157 78 158 //m_originalBody->setCompanionId(-1); 79 159 } 80 160 } 81 161 */ 82 162 83 void writebackVelocity(btScalar timeStep )163 void writebackVelocity(btScalar timeStep=0) 84 164 { 85 165 if (m_invMass) 86 166 { 87 m_originalBody->setLinearVelocity(m_linearVelocity); 88 m_originalBody->setAngularVelocity(m_angularVelocity); 89 90 //correct the position/orientation based on push/turn recovery 91 btTransform newTransform; 92 btTransformUtil::integrateTransform(m_originalBody->getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform); 93 m_originalBody->setWorldTransform(newTransform); 94 167 m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+m_deltaLinearVelocity); 168 m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity); 95 169 //m_originalBody->setCompanionId(-1); 96 170 } 97 171 } 98 99 void readVelocity()100 {101 if (m_invMass)102 {103 m_linearVelocity = m_originalBody->getLinearVelocity();104 m_angularVelocity = m_originalBody->getAngularVelocity();105 }106 }107 108 172 109 173 -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h
r2662 r2882 20 20 #include "LinearMath/btVector3.h" 21 21 #include "LinearMath/btMatrix3x3.h" 22 #include "btJacobianEntry.h" 22 23 23 24 //#define NO_FRICTION_TANGENTIALS 1 25 #include "btSolverBody.h" 26 24 27 25 28 ///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. … … 28 31 BT_DECLARE_ALIGNED_ALLOCATOR(); 29 32 30 btVector3 m_relpos1CrossNormal;31 btVector3 m_contactNormal;33 btVector3 m_relpos1CrossNormal; 34 btVector3 m_contactNormal; 32 35 33 btVector3 m_relpos2CrossNormal;34 btVector3 m_angularComponentA;36 btVector3 m_relpos2CrossNormal; 37 //btVector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal 35 38 36 btVector3 m_angularComponentB; 37 38 mutable btScalar m_appliedPushImpulse; 39 btVector3 m_angularComponentA; 40 btVector3 m_angularComponentB; 39 41 40 mutable btS calar m_appliedImpulse;41 int m_solverBodyIdA;42 int m_solverBodyIdB;42 mutable btSimdScalar m_appliedPushImpulse; 43 mutable btSimdScalar m_appliedImpulse; 44 43 45 44 46 btScalar m_friction; 45 btScalar m_restitution;46 47 btScalar m_jacDiagABInv; 47 btScalar m_penetration; 48 union 49 { 50 int m_numConsecutiveRowsPerKernel; 51 btScalar m_unusedPadding0; 52 }; 53 54 union 55 { 56 int m_frictionIndex; 57 btScalar m_unusedPadding1; 58 }; 59 union 60 { 61 int m_solverBodyIdA; 62 btScalar m_unusedPadding2; 63 }; 64 union 65 { 66 int m_solverBodyIdB; 67 btScalar m_unusedPadding3; 68 }; 48 69 70 union 71 { 72 void* m_originalContactPoint; 73 btScalar m_unusedPadding4; 74 }; 49 75 50 51 int m_constraintType; 52 int m_frictionIndex; 53 void* m_originalContactPoint; 54 int m_unusedPadding[1]; 55 76 btScalar m_rhs; 77 btScalar m_cfm; 78 btScalar m_lowerLimit; 79 btScalar m_upperLimit; 56 80 57 81 enum btSolverConstraintType … … 62 86 }; 63 87 64 65 66 88 typedef btAlignedObjectArray<btSolverConstraint> btConstraintArray; 67 89 68 90 -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
r2662 r2882 20 20 static btRigidBody s_fixed(0, 0,0); 21 21 22 #define DEFAULT_DEBUGDRAW_SIZE btScalar(0.3f) 23 22 24 btTypedConstraint::btTypedConstraint(btTypedConstraintType type) 23 25 :m_userConstraintType(-1), … … 26 28 m_rbA(s_fixed), 27 29 m_rbB(s_fixed), 28 m_appliedImpulse(btScalar(0.)) 30 m_appliedImpulse(btScalar(0.)), 31 m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE) 29 32 { 30 33 s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); … … 36 39 m_rbA(rbA), 37 40 m_rbB(s_fixed), 38 m_appliedImpulse(btScalar(0.)) 41 m_appliedImpulse(btScalar(0.)), 42 m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE) 39 43 { 40 44 s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); … … 49 53 m_rbA(rbA), 50 54 m_rbB(rbB), 51 m_appliedImpulse(btScalar(0.)) 55 m_appliedImpulse(btScalar(0.)), 56 m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE) 52 57 { 53 58 s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); … … 55 60 } 56 61 62 63 //----------------------------------------------------------------------------- 64 65 btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact) 66 { 67 if(lowLim > uppLim) 68 { 69 return btScalar(1.0f); 70 } 71 else if(lowLim == uppLim) 72 { 73 return btScalar(0.0f); 74 } 75 btScalar lim_fact = btScalar(1.0f); 76 btScalar delta_max = vel / timeFact; 77 if(delta_max < btScalar(0.0f)) 78 { 79 if((pos >= lowLim) && (pos < (lowLim - delta_max))) 80 { 81 lim_fact = (lowLim - pos) / delta_max; 82 } 83 else if(pos < lowLim) 84 { 85 lim_fact = btScalar(0.0f); 86 } 87 else 88 { 89 lim_fact = btScalar(1.0f); 90 } 91 } 92 else if(delta_max > btScalar(0.0f)) 93 { 94 if((pos <= uppLim) && (pos > (uppLim - delta_max))) 95 { 96 lim_fact = (uppLim - pos) / delta_max; 97 } 98 else if(pos > uppLim) 99 { 100 lim_fact = btScalar(0.0f); 101 } 102 else 103 { 104 lim_fact = btScalar(1.0f); 105 } 106 } 107 else 108 { 109 lim_fact = btScalar(0.0f); 110 } 111 return lim_fact; 112 } // btTypedConstraint::getMotorFactor() 113 114 -
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h
r2662 r2882 19 19 class btRigidBody; 20 20 #include "LinearMath/btScalar.h" 21 #include "btSolverConstraint.h" 22 struct btSolverBody; 23 24 25 21 26 22 27 enum btTypedConstraintType … … 26 31 CONETWIST_CONSTRAINT_TYPE, 27 32 D6_CONSTRAINT_TYPE, 28 VEHICLE_CONSTRAINT_TYPE,29 33 SLIDER_CONSTRAINT_TYPE 30 34 }; … … 49 53 btRigidBody& m_rbB; 50 54 btScalar m_appliedImpulse; 55 btScalar m_dbgDrawSize; 51 56 52 57 … … 56 61 virtual ~btTypedConstraint() {}; 57 62 btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); 63 btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); 58 64 59 btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); 65 struct btConstraintInfo1 { 66 int m_numConstraintRows,nub; 67 }; 68 69 struct btConstraintInfo2 { 70 // integrator parameters: frames per second (1/stepsize), default error 71 // reduction parameter (0..1). 72 btScalar fps,erp; 73 74 // for the first and second body, pointers to two (linear and angular) 75 // n*3 jacobian sub matrices, stored by rows. these matrices will have 76 // been initialized to 0 on entry. if the second body is zero then the 77 // J2xx pointers may be 0. 78 btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis; 79 80 // elements to jump from one row to the next in J's 81 int rowskip; 82 83 // right hand sides of the equation J*v = c + cfm * lambda. cfm is the 84 // "constraint force mixing" vector. c is set to zero on entry, cfm is 85 // set to a constant value (typically very small or zero) value on entry. 86 btScalar *m_constraintError,*cfm; 87 88 // lo and hi limits for variables (set to -/+ infinity on entry). 89 btScalar *m_lowerLimit,*m_upperLimit; 90 91 // findex vector for variables. see the LCP solver interface for a 92 // description of what this does. this is set to -1 on entry. 93 // note that the returned indexes are relative to the first index of 94 // the constraint. 95 int *findex; 96 }; 97 60 98 61 99 virtual void buildJacobian() = 0; 62 100 63 virtual void solveConstraint(btScalar timeStep) = 0; 101 virtual void setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep) 102 { 103 } 104 virtual void getInfo1 (btConstraintInfo1* info)=0; 64 105 106 virtual void getInfo2 (btConstraintInfo2* info)=0; 107 108 virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) = 0; 109 110 btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact); 111 65 112 const btRigidBody& getRigidBodyA() const 66 113 { … … 95 142 m_userConstraintId = uid; 96 143 } 97 144 98 145 int getUserConstraintId() const 99 146 { … … 115 162 return m_constraintType; 116 163 } 117 164 165 void setDbgDrawSize(btScalar dbgDrawSize) 166 { 167 m_dbgDrawSize = dbgDrawSize; 168 } 169 btScalar getDbgDrawSize() 170 { 171 return m_dbgDrawSize; 172 } 173 118 174 }; 119 175 -
code/trunk/src/bullet/BulletDynamics/Dynamics/Bullet-C-API.cpp
r2662 r2882 111 111 { 112 112 btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); 113 assert(dynamicsWorld);113 btAssert(dynamicsWorld); 114 114 dynamicsWorld->stepSimulation(timeStep); 115 115 } … … 118 118 { 119 119 btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); 120 assert(dynamicsWorld);121 btRigidBody* body = reinterpret_cast< btRigidBody* >(object); 122 assert(body);120 btAssert(dynamicsWorld); 121 btRigidBody* body = reinterpret_cast< btRigidBody* >(object); 122 btAssert(body); 123 123 124 124 dynamicsWorld->addRigidBody(body); … … 128 128 { 129 129 btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); 130 assert(dynamicsWorld);131 btRigidBody* body = reinterpret_cast< btRigidBody* >(object); 132 assert(body);130 btAssert(dynamicsWorld); 131 btRigidBody* body = reinterpret_cast< btRigidBody* >(object); 132 btAssert(body); 133 133 134 134 dynamicsWorld->removeRigidBody(body); … … 143 143 btVector3 localInertia(0,0,0); 144 144 btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape); 145 assert(shape);145 btAssert(shape); 146 146 if (mass) 147 147 { … … 159 159 { 160 160 btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); 161 assert(body);161 btAssert(body); 162 162 btAlignedFree( body); 163 163 } … … 263 263 { 264 264 btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape); 265 assert(shape);265 btAssert(shape); 266 266 btAlignedFree(shape); 267 267 } … … 269 269 { 270 270 btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape); 271 assert(shape);271 btAssert(shape); 272 272 btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); 273 273 shape->setLocalScaling(scaling); -
code/trunk/src/bullet/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp
r2662 r2882 91 91 92 92 ///update vehicle simulation 93 updateVehicles(timeStep); 94 93 updateActions(timeStep); 95 94 96 95 updateActivationState( timeStep ); -
code/trunk/src/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
r2662 r2882 30 30 #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" 31 31 #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" 32 #include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" 33 #include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" 34 #include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" 35 #include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" 36 #include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" 32 37 33 38 //for debug rendering … … 47 52 48 53 49 50 //vehicle 51 #include "BulletDynamics/Vehicle/btRaycastVehicle.h" 52 #include "BulletDynamics/Vehicle/btVehicleRaycaster.h" 53 #include "BulletDynamics/Vehicle/btWheelInfo.h" 54 //character 55 #include "BulletDynamics/Character/btCharacterControllerInterface.h" 56 57 #include "LinearMath/btIDebugDraw.h" 54 #include "BulletDynamics/Dynamics/btActionInterface.h" 58 55 #include "LinearMath/btQuickprof.h" 59 56 #include "LinearMath/btMotionState.h" … … 114 111 if (body) 115 112 { 116 btTransform predictedTrans;117 113 if (body->getActivationState() != ISLAND_SLEEPING) 118 114 { … … 149 145 } 150 146 } 147 bool drawConstraints = false; 148 if (getDebugDrawer()) 149 { 150 int mode = getDebugDrawer()->getDebugMode(); 151 if(mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits)) 152 { 153 drawConstraints = true; 154 } 155 } 156 if(drawConstraints) 157 { 158 for(int i = getNumConstraints()-1; i>=0 ;i--) 159 { 160 btTypedConstraint* constraint = getConstraint(i); 161 debugDrawConstraint(constraint); 162 } 163 } 164 151 165 152 166 … … 191 205 } 192 206 193 for ( i=0;i<this->m_vehicles.size();i++) 194 { 195 for (int v=0;v<m_vehicles[i]->getNumWheels();v++) 196 { 197 btVector3 wheelColor(0,255,255); 198 if (m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact) 199 { 200 wheelColor.setValue(0,0,255); 201 } else 202 { 203 wheelColor.setValue(255,0,255); 204 } 205 206 btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); 207 208 btVector3 axle = btVector3( 209 m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[0][m_vehicles[i]->getRightAxis()], 210 m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[1][m_vehicles[i]->getRightAxis()], 211 m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[2][m_vehicles[i]->getRightAxis()]); 212 213 214 //m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_wheelAxleWS 215 //debug wheels (cylinders) 216 m_debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); 217 m_debugDrawer->drawLine(wheelPosWS,m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); 218 207 if (getDebugDrawer() && getDebugDrawer()->getDebugMode()) 208 { 209 for (i=0;i<m_actions.size();i++) 210 { 211 m_actions[i]->debugDraw(m_debugDrawer); 219 212 } 220 213 } … … 288 281 } 289 282 } 290 283 /* 291 284 if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) 292 285 { … … 300 293 } 301 294 } 295 */ 296 302 297 303 298 } … … 340 335 if (getDebugDrawer()) 341 336 { 342 gDisableDeactivation = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; 337 btIDebugDraw* debugDrawer = getDebugDrawer (); 338 gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; 343 339 } 344 340 if (numSimulationSubSteps) … … 404 400 405 401 ///update vehicle simulation 406 updateVehicles(timeStep); 407 408 updateCharacters(timeStep); 409 402 updateActions(timeStep); 403 410 404 updateActivationState( timeStep ); 411 405 … … 471 465 472 466 473 void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) 474 { 475 BT_PROFILE("updateVehicles"); 476 477 for ( int i=0;i<m_vehicles.size();i++) 478 { 479 btRaycastVehicle* vehicle = m_vehicles[i]; 480 vehicle->updateVehicle( timeStep); 481 } 482 } 483 484 void btDiscreteDynamicsWorld::updateCharacters(btScalar timeStep) 485 { 486 BT_PROFILE("updateCharacters"); 487 488 for ( int i=0;i<m_characters.size();i++) 489 { 490 btCharacterControllerInterface* character = m_characters[i]; 491 character->preStep (this); 492 character->playerStep (this,timeStep); 493 } 494 } 495 467 void btDiscreteDynamicsWorld::updateActions(btScalar timeStep) 468 { 469 BT_PROFILE("updateActions"); 470 471 for ( int i=0;i<m_actions.size();i++) 472 { 473 m_actions[i]->updateAction( this, timeStep); 474 } 475 } 496 476 497 477 … … 550 530 } 551 531 552 void btDiscreteDynamicsWorld::addVehicle(btRaycastVehicle* vehicle) 553 { 554 m_vehicles.push_back(vehicle); 555 } 556 557 void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) 558 { 559 m_vehicles.remove(vehicle); 560 } 561 562 void btDiscreteDynamicsWorld::addCharacter(btCharacterControllerInterface* character) 563 { 564 m_characters.push_back(character); 565 } 566 567 void btDiscreteDynamicsWorld::removeCharacter(btCharacterControllerInterface* character) 568 { 569 m_characters.remove(character); 532 void btDiscreteDynamicsWorld::addAction(btActionInterface* action) 533 { 534 m_actions.push_back(action); 535 } 536 537 void btDiscreteDynamicsWorld::removeAction(btActionInterface* action) 538 { 539 m_actions.remove(action); 540 } 541 542 543 void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle) 544 { 545 addAction(vehicle); 546 } 547 548 void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle) 549 { 550 removeAction(vehicle); 551 } 552 553 void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character) 554 { 555 addAction(character); 556 } 557 558 void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character) 559 { 560 removeAction(character); 570 561 } 571 562 … … 643 634 if (islandId<0) 644 635 { 645 ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id 646 m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); 636 if (numManifolds + m_numConstraints) 637 { 638 ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id 639 m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); 640 } 647 641 } else 648 642 { … … 690 684 } 691 685 692 // assert(0);686 // btAssert(0); 693 687 694 688 … … 754 748 btScalar m_allowedPenetration; 755 749 btOverlappingPairCache* m_pairCache; 750 btDispatcher* m_dispatcher; 756 751 757 752 758 753 public: 759 btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache ) :754 btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : 760 755 btCollisionWorld::ClosestConvexResultCallback(fromA,toA), 761 756 m_allowedPenetration(0.0f), 762 757 m_me(me), 763 m_pairCache(pairCache) 758 m_pairCache(pairCache), 759 m_dispatcher(dispatcher) 764 760 { 765 761 } … … 796 792 return false; 797 793 798 ///don't do CCD when there are already contact points (touching contact/penetration) 799 btAlignedObjectArray<btPersistentManifold*> manifoldArray; 800 btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); 801 if (collisionPair) 802 { 803 if (collisionPair->m_algorithm) 804 { 805 manifoldArray.resize(0); 806 collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); 807 for (int j=0;j<manifoldArray.size();j++) 808 { 809 btPersistentManifold* manifold = manifoldArray[j]; 810 if (manifold->getNumContacts()>0) 811 return false; 794 btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject; 795 796 //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179 797 if (m_dispatcher->needsResponse(m_me,otherObj)) 798 { 799 ///don't do CCD when there are already contact points (touching contact/penetration) 800 btAlignedObjectArray<btPersistentManifold*> manifoldArray; 801 btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); 802 if (collisionPair) 803 { 804 if (collisionPair->m_algorithm) 805 { 806 manifoldArray.resize(0); 807 collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); 808 for (int j=0;j<manifoldArray.size();j++) 809 { 810 btPersistentManifold* manifold = manifoldArray[j]; 811 if (manifold->getNumContacts()>0) 812 return false; 813 } 812 814 } 813 815 } … … 847 849 gNumClampedCcdMotions++; 848 850 849 btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache() );851 btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); 850 852 btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape()); 851 853 btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape()); … … 1188 1190 1189 1191 1192 void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint) 1193 { 1194 bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0; 1195 bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0; 1196 btScalar dbgDrawSize = constraint->getDbgDrawSize(); 1197 if(dbgDrawSize <= btScalar(0.f)) 1198 { 1199 return; 1200 } 1201 1202 switch(constraint->getConstraintType()) 1203 { 1204 case POINT2POINT_CONSTRAINT_TYPE: 1205 { 1206 btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint; 1207 btTransform tr; 1208 tr.setIdentity(); 1209 btVector3 pivot = p2pC->getPivotInA(); 1210 pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot; 1211 tr.setOrigin(pivot); 1212 getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1213 // that ideally should draw the same frame 1214 pivot = p2pC->getPivotInB(); 1215 pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot; 1216 tr.setOrigin(pivot); 1217 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1218 } 1219 break; 1220 case HINGE_CONSTRAINT_TYPE: 1221 { 1222 btHingeConstraint* pHinge = (btHingeConstraint*)constraint; 1223 btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame(); 1224 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1225 tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame(); 1226 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1227 btScalar minAng = pHinge->getLowerLimit(); 1228 btScalar maxAng = pHinge->getUpperLimit(); 1229 if(minAng == maxAng) 1230 { 1231 break; 1232 } 1233 bool drawSect = true; 1234 if(minAng > maxAng) 1235 { 1236 minAng = btScalar(0.f); 1237 maxAng = SIMD_2_PI; 1238 drawSect = false; 1239 } 1240 if(drawLimits) 1241 { 1242 btVector3& center = tr.getOrigin(); 1243 btVector3 normal = tr.getBasis().getColumn(2); 1244 btVector3 axis = tr.getBasis().getColumn(0); 1245 getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect); 1246 } 1247 } 1248 break; 1249 case CONETWIST_CONSTRAINT_TYPE: 1250 { 1251 btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint; 1252 btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame(); 1253 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1254 tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame(); 1255 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1256 if(drawLimits) 1257 { 1258 //const btScalar length = btScalar(5); 1259 const btScalar length = dbgDrawSize; 1260 static int nSegments = 8*4; 1261 btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments); 1262 btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length); 1263 pPrev = tr * pPrev; 1264 for (int i=0; i<nSegments; i++) 1265 { 1266 fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)i/btScalar(nSegments); 1267 btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length); 1268 pCur = tr * pCur; 1269 getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0)); 1270 1271 if (i%(nSegments/8) == 0) 1272 getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0)); 1273 1274 pPrev = pCur; 1275 } 1276 btScalar tws = pCT->getTwistSpan(); 1277 btScalar twa = pCT->getTwistAngle(); 1278 bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f)); 1279 if(useFrameB) 1280 { 1281 tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame(); 1282 } 1283 else 1284 { 1285 tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame(); 1286 } 1287 btVector3 pivot = tr.getOrigin(); 1288 btVector3 normal = tr.getBasis().getColumn(0); 1289 btVector3 axis1 = tr.getBasis().getColumn(1); 1290 getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true); 1291 1292 } 1293 } 1294 break; 1295 case D6_CONSTRAINT_TYPE: 1296 { 1297 btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint; 1298 btTransform tr = p6DOF->getCalculatedTransformA(); 1299 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1300 tr = p6DOF->getCalculatedTransformB(); 1301 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1302 if(drawLimits) 1303 { 1304 tr = p6DOF->getCalculatedTransformA(); 1305 const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin(); 1306 btVector3 up = tr.getBasis().getColumn(2); 1307 btVector3 axis = tr.getBasis().getColumn(0); 1308 btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit; 1309 btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit; 1310 btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit; 1311 btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit; 1312 getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0)); 1313 axis = tr.getBasis().getColumn(1); 1314 btScalar ay = p6DOF->getAngle(1); 1315 btScalar az = p6DOF->getAngle(2); 1316 btScalar cy = btCos(ay); 1317 btScalar sy = btSin(ay); 1318 btScalar cz = btCos(az); 1319 btScalar sz = btSin(az); 1320 btVector3 ref; 1321 ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2]; 1322 ref[1] = -sz*axis[0] + cz*axis[1]; 1323 ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2]; 1324 tr = p6DOF->getCalculatedTransformB(); 1325 btVector3 normal = -tr.getBasis().getColumn(0); 1326 btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit; 1327 btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit; 1328 if(minFi > maxFi) 1329 { 1330 getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false); 1331 } 1332 else if(minFi < maxFi) 1333 { 1334 getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true); 1335 } 1336 tr = p6DOF->getCalculatedTransformA(); 1337 btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit; 1338 btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit; 1339 getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0)); 1340 } 1341 } 1342 break; 1343 case SLIDER_CONSTRAINT_TYPE: 1344 { 1345 btSliderConstraint* pSlider = (btSliderConstraint*)constraint; 1346 btTransform tr = pSlider->getCalculatedTransformA(); 1347 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1348 tr = pSlider->getCalculatedTransformB(); 1349 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); 1350 if(drawLimits) 1351 { 1352 btTransform tr = pSlider->getCalculatedTransformA(); 1353 btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f); 1354 btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f); 1355 getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0)); 1356 btVector3 normal = tr.getBasis().getColumn(0); 1357 btVector3 axis = tr.getBasis().getColumn(1); 1358 btScalar a_min = pSlider->getLowerAngLimit(); 1359 btScalar a_max = pSlider->getUpperAngLimit(); 1360 const btVector3& center = pSlider->getCalculatedTransformB().getOrigin(); 1361 getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true); 1362 } 1363 } 1364 break; 1365 default : 1366 break; 1367 } 1368 return; 1369 } // btDiscreteDynamicsWorld::debugDrawConstraint() 1370 1371 1372 1373 1374 1190 1375 void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) 1191 1376 { … … 1216 1401 return m_constraints[index]; 1217 1402 } 1403 1404 -
code/trunk/src/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
r2662 r2882 24 24 class btSimulationIslandManager; 25 25 class btTypedConstraint; 26 class btActionInterface; 26 27 27 28 class btRaycastVehicle;29 class btCharacterControllerInterface;30 28 class btIDebugDraw; 31 29 #include "LinearMath/btAlignedObjectArray.h" … … 53 51 bool m_ownsConstraintSolver; 54 52 53 btAlignedObjectArray<btActionInterface*> m_actions; 55 54 56 btAlignedObjectArray<btRaycastVehicle*> m_vehicles;57 58 btAlignedObjectArray<btCharacterControllerInterface*> m_characters;59 60 61 55 int m_profileTimings; 62 56 … … 71 65 void updateActivationState(btScalar timeStep); 72 66 73 void updateVehicles(btScalar timeStep); 74 75 void updateCharacters(btScalar timeStep); 67 void updateActions(btScalar timeStep); 76 68 77 69 void startProfiling(btScalar timeStep); … … 106 98 virtual void removeConstraint(btTypedConstraint* constraint); 107 99 108 virtual void add Vehicle(btRaycastVehicle* vehicle);100 virtual void addAction(btActionInterface*); 109 101 110 virtual void remove Vehicle(btRaycastVehicle* vehicle);102 virtual void removeAction(btActionInterface*); 111 103 112 virtual void addCharacter(btCharacterControllerInterface* character);113 114 virtual void removeCharacter(btCharacterControllerInterface* character);115 116 117 104 btSimulationIslandManager* getSimulationIslandManager() 118 105 { … … 131 118 132 119 virtual void setGravity(const btVector3& gravity); 120 133 121 virtual btVector3 getGravity () const; 134 122 … … 140 128 141 129 void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); 130 131 void debugDrawConstraint(btTypedConstraint* constraint); 142 132 143 133 virtual void debugDrawWorld(); … … 170 160 } 171 161 162 ///obsolete, use updateActions instead 163 virtual void updateVehicles(btScalar timeStep) 164 { 165 updateActions(timeStep); 166 } 167 168 ///obsolete, use addAction instead 169 virtual void addVehicle(btActionInterface* vehicle); 170 ///obsolete, use removeAction instead 171 virtual void removeVehicle(btActionInterface* vehicle); 172 ///obsolete, use addAction instead 173 virtual void addCharacter(btActionInterface* character); 174 ///obsolete, use removeAction instead 175 virtual void removeCharacter(btActionInterface* character); 176 172 177 }; 173 178 -
code/trunk/src/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
r2662 r2882 21 21 22 22 class btTypedConstraint; 23 class bt RaycastVehicle;23 class btActionInterface; 24 24 class btConstraintSolver; 25 25 class btDynamicsWorld; 26 class btCharacterControllerInterface; 26 27 27 28 28 /// Type for the callback for each tick … … 73 73 virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;} 74 74 75 virtual void add Vehicle(btRaycastVehicle* vehicle) {(void)vehicle;}75 virtual void addAction(btActionInterface* action) = 0; 76 76 77 virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} 78 79 virtual void addCharacter(btCharacterControllerInterface* character) {(void)character;} 80 81 virtual void removeCharacter(btCharacterControllerInterface* character) {(void)character;} 82 77 virtual void removeAction(btActionInterface* action) = 0; 83 78 84 79 //once a rigidbody is added to the dynamics world, it will get this gravity assigned … … 130 125 131 126 127 ///obsolete, use addAction instead. 128 virtual void addVehicle(btActionInterface* vehicle) {(void)vehicle;} 129 ///obsolete, use removeAction instead 130 virtual void removeVehicle(btActionInterface* vehicle) {(void)vehicle;} 131 ///obsolete, use addAction instead. 132 virtual void addCharacter(btActionInterface* character) {(void)character;} 133 ///obsolete, use removeAction instead 134 virtual void removeCharacter(btActionInterface* character) {(void)character;} 135 136 132 137 }; 133 138 -
code/trunk/src/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
r2662 r2882 47 47 m_angularFactor = btScalar(1.); 48 48 m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 49 m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 49 50 m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 50 51 m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)), … … 125 126 m_gravity = acceleration * (btScalar(1.0) / m_inverseMass); 126 127 } 128 m_gravity_acceleration = acceleration; 127 129 } 128 130 -
code/trunk/src/bullet/BulletDynamics/Dynamics/btRigidBody.h
r2662 r2882 49 49 50 50 btVector3 m_gravity; 51 btVector3 m_gravity_acceleration; 51 52 btVector3 m_invInertiaLocal; 52 53 btVector3 m_totalForce; … … 182 183 const btVector3& getGravity() const 183 184 { 184 return m_gravity ;185 return m_gravity_acceleration; 185 186 } 186 187 … … 232 233 m_totalForce += force; 233 234 } 235 236 const btVector3& getTotalForce() 237 { 238 return m_totalForce; 239 }; 240 241 const btVector3& getTotalTorque() 242 { 243 return m_totalTorque; 244 }; 234 245 235 const btVector3& getInvInertiaDiagLocal() 246 const btVector3& getInvInertiaDiagLocal() const 236 247 { 237 248 return m_invInertiaLocal; -
code/trunk/src/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp
r2662 r2882 20 20 #include "btWheelInfo.h" 21 21 #include "LinearMath/btMinMax.h" 22 23 22 #include "LinearMath/btIDebugDraw.h" 24 23 #include "BulletDynamics/ConstraintSolver/btContactConstraint.h" 25 24 … … 27 26 28 27 btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) 29 : btTypedConstraint(VEHICLE_CONSTRAINT_TYPE), 30 m_vehicleRaycaster(raycaster), 28 :m_vehicleRaycaster(raycaster), 31 29 m_pitchControl(btScalar(0.)) 32 30 { … … 88 86 const btTransform& btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const 89 87 { 90 assert(wheelIndex < getNumWheels());88 btAssert(wheelIndex < getNumWheels()); 91 89 const btWheelInfo& wheel = m_wheelInfo[wheelIndex]; 92 90 return wheel.m_worldTransform; … … 176 174 btVehicleRaycaster::btVehicleRaycasterResult rayResults; 177 175 178 assert(m_vehicleRaycaster);176 btAssert(m_vehicleRaycaster); 179 177 180 178 void* object = m_vehicleRaycaster->castRay(source,target,rayResults); … … 360 358 void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel) 361 359 { 362 assert(wheel>=0 && wheel < getNumWheels());360 btAssert(wheel>=0 && wheel < getNumWheels()); 363 361 364 362 btWheelInfo& wheelInfo = getWheelInfo(wheel); … … 376 374 void btRaycastVehicle::applyEngineForce(btScalar force, int wheel) 377 375 { 378 assert(wheel>=0 && wheel < getNumWheels());376 btAssert(wheel>=0 && wheel < getNumWheels()); 379 377 btWheelInfo& wheelInfo = getWheelInfo(wheel); 380 378 wheelInfo.m_engineForce = force; … … 705 703 706 704 705 706 void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer) 707 { 708 709 for (int v=0;v<this->getNumWheels();v++) 710 { 711 btVector3 wheelColor(0,255,255); 712 if (getWheelInfo(v).m_raycastInfo.m_isInContact) 713 { 714 wheelColor.setValue(0,0,255); 715 } else 716 { 717 wheelColor.setValue(255,0,255); 718 } 719 720 btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin(); 721 722 btVector3 axle = btVector3( 723 getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()], 724 getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()], 725 getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]); 726 727 //debug wheels (cylinders) 728 debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); 729 debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); 730 731 } 732 } 733 734 707 735 void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) 708 736 { … … 728 756 return 0; 729 757 } 758 -
code/trunk/src/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h
r2662 r2882 18 18 #include "LinearMath/btAlignedObjectArray.h" 19 19 #include "btWheelInfo.h" 20 #include "BulletDynamics/Dynamics/btActionInterface.h" 20 21 21 22 class btVehicleTuning; 22 23 23 24 ///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. 24 class btRaycastVehicle : public bt TypedConstraint25 class btRaycastVehicle : public btActionInterface 25 26 { 26 27 … … 74 75 virtual ~btRaycastVehicle() ; 75 76 76 77 78 ///btActionInterface interface 79 virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step) 80 { 81 updateVehicle(step); 82 } 83 84 85 ///btActionInterface interface 86 void debugDraw(btIDebugDraw* debugDrawer); 87 77 88 const btTransform& getChassisWorldTransform() const; 78 89 … … 80 91 81 92 virtual void updateVehicle(btScalar step); 82 93 94 83 95 void resetSuspension(); 84 96 … … 176 188 } 177 189 178 virtual void buildJacobian()179 {180 //not yet181 }182 183 virtual void solveConstraint(btScalar timeStep)184 {185 (void)timeStep;186 //not yet187 }188 190 189 191 -
code/trunk/src/bullet/LinearMath/btAlignedAllocator.cpp
r2662 r2882 20 20 int gTotalBytesAlignedAllocs = 0;//detect memory leaks 21 21 22 static void *btAllocDefault(size_t size) 23 { 24 return malloc(size); 25 } 26 27 static void btFreeDefault(void *ptr) 28 { 29 free(ptr); 30 } 31 32 static btAllocFunc *sAllocFunc = btAllocDefault; 33 static btFreeFunc *sFreeFunc = btFreeDefault; 34 35 36 22 37 #if defined (BT_HAS_ALIGNED_ALLOCATOR) 23 38 #include <malloc.h> … … 50 65 unsigned long offset; 51 66 52 real = (char *) malloc(size + sizeof(void *) + (alignment-1));67 real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); 53 68 if (real) { 54 69 offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); … … 67 82 if (ptr) { 68 83 real = *((void **)(ptr)-1); 69 free(real);84 sFreeFunc(real); 70 85 } 71 86 } 72 87 #endif 73 88 74 static void *btAllocDefault(size_t size)75 {76 return malloc(size);77 }78 79 static void btFreeDefault(void *ptr)80 {81 free(ptr);82 }83 89 84 90 static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault; 85 91 static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault; 86 static btAllocFunc *sAllocFunc = btAllocDefault;87 static btFreeFunc *sFreeFunc = btFreeDefault;88 92 89 93 void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc) -
code/trunk/src/bullet/LinearMath/btAlignedAllocator.h
r2662 r2882 39 39 void btAlignedFreeInternal (void* ptr); 40 40 41 #define btAlignedAlloc( a,b) btAlignedAllocInternal(a,b)41 #define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment) 42 42 #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) 43 43 … … 50 50 typedef void (btFreeFunc)(void *memblock); 51 51 52 ///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom 53 void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); 54 ///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it. 52 55 void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc); 53 void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); 56 54 57 55 58 ///The btAlignedAllocator is a portable class for aligned memory allocations. -
code/trunk/src/bullet/LinearMath/btAlignedObjectArray.h
r2662 r2882 59 59 return (size ? size*2 : 1); 60 60 } 61 SIMD_FORCE_INLINE void copy(int start,int end, T* dest) 61 SIMD_FORCE_INLINE void copy(int start,int end, T* dest) const 62 62 { 63 63 int i; … … 121 121 } 122 122 123 SIMD_FORCE_INLINE int capacity() const 124 { // return current length of allocated storage 125 return m_capacity; 126 } 127 123 ///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead. 124 btAlignedObjectArray(const btAlignedObjectArray& otherArray) 125 { 126 init(); 127 128 int otherSize = otherArray.size(); 129 resize (otherSize); 130 otherArray.copy(0, otherSize, m_data); 131 } 132 133 134 135 /// return the number of elements in the array 128 136 SIMD_FORCE_INLINE int size() const 129 { // return length of sequence137 { 130 138 return m_size; 131 139 } … … 142 150 143 151 152 ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations. 144 153 SIMD_FORCE_INLINE void clear() 145 154 { … … 157 166 } 158 167 168 ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument. 169 ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations. 159 170 SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T()) 160 171 { … … 220 231 221 232 233 /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve() 234 SIMD_FORCE_INLINE int capacity() const 235 { 236 return m_capacity; 237 } 222 238 223 239 SIMD_FORCE_INLINE void reserve(int _Count) -
code/trunk/src/bullet/LinearMath/btConvexHull.cpp
r2662 r2882 263 263 for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0)) 264 264 { 265 btScalar s = sinf(SIMD_RADS_PER_DEG*(x));266 btScalar c = cosf(SIMD_RADS_PER_DEG*(x));265 btScalar s = btSin(SIMD_RADS_PER_DEG*(x)); 266 btScalar c = btCos(SIMD_RADS_PER_DEG*(x)); 267 267 int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); 268 268 if(ma==m && mb==m) … … 276 276 for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0)) 277 277 { 278 btScalar s = sinf(SIMD_RADS_PER_DEG*(xx));279 btScalar c = cosf(SIMD_RADS_PER_DEG*(xx));278 btScalar s = btSin(SIMD_RADS_PER_DEG*(xx)); 279 btScalar c = btCos(SIMD_RADS_PER_DEG*(xx)); 280 280 int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); 281 281 if(mc==m && md==m) -
code/trunk/src/bullet/LinearMath/btIDebugDraw.h
r2662 r2882 30 30 31 31 #include "btVector3.h" 32 #include "btTransform.h" 32 33 33 34 … … 53 54 DBG_DisableBulletLCP = 512, 54 55 DBG_EnableCCD = 1024, 56 DBG_DrawConstraints = (1 << 11), 57 DBG_DrawConstraintLimits = (1 << 12), 55 58 DBG_MAX_DEBUG_DRAW_MODE 56 59 }; 57 60 58 61 virtual ~btIDebugDraw() {}; 62 63 virtual void drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor) 64 { 65 drawLine (from, to, fromColor); 66 } 67 68 virtual void drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha) 69 { 70 } 71 72 virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color) 73 { 74 } 59 75 60 76 virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0; … … 110 126 } 111 127 } 128 void drawTransform(const btTransform& transform, btScalar orthoLen) 129 { 130 btVector3 start = transform.getOrigin(); 131 drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(0.7f,0,0)); 132 drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0,0.7f,0)); 133 drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0,0,0.7f)); 134 } 135 136 void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle, 137 const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f)) 138 { 139 const btVector3& vx = axis; 140 btVector3 vy = normal.cross(axis); 141 btScalar step = stepDegrees * SIMD_RADS_PER_DEG; 142 int nSteps = (int)((maxAngle - minAngle) / step); 143 if(!nSteps) nSteps = 1; 144 btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle); 145 if(drawSect) 146 { 147 drawLine(center, prev, color); 148 } 149 for(int i = 1; i <= nSteps; i++) 150 { 151 btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps); 152 btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle); 153 drawLine(prev, next, color); 154 prev = next; 155 } 156 if(drawSect) 157 { 158 drawLine(center, prev, color); 159 } 160 } 161 void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius, 162 btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f)) 163 { 164 btVector3 vA[74]; 165 btVector3 vB[74]; 166 btVector3 *pvA = vA, *pvB = vB, *pT; 167 btVector3 npole = center + up * radius; 168 btVector3 spole = center - up * radius; 169 btVector3 arcStart; 170 btScalar step = stepDegrees * SIMD_RADS_PER_DEG; 171 const btVector3& kv = up; 172 const btVector3& iv = axis; 173 btVector3 jv = kv.cross(iv); 174 bool drawN = false; 175 bool drawS = false; 176 if(minTh <= -SIMD_HALF_PI) 177 { 178 minTh = -SIMD_HALF_PI + step; 179 drawN = true; 180 } 181 if(maxTh >= SIMD_HALF_PI) 182 { 183 maxTh = SIMD_HALF_PI - step; 184 drawS = true; 185 } 186 if(minTh > maxTh) 187 { 188 minTh = -SIMD_HALF_PI + step; 189 maxTh = SIMD_HALF_PI - step; 190 drawN = drawS = true; 191 } 192 int n_hor = (int)((maxTh - minTh) / step) + 1; 193 if(n_hor < 2) n_hor = 2; 194 btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1); 195 bool isClosed = false; 196 if(minPs > maxPs) 197 { 198 minPs = -SIMD_PI + step; 199 maxPs = SIMD_PI; 200 isClosed = true; 201 } 202 else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f)) 203 { 204 isClosed = true; 205 } 206 else 207 { 208 isClosed = false; 209 } 210 int n_vert = (int)((maxPs - minPs) / step) + 1; 211 if(n_vert < 2) n_vert = 2; 212 btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1); 213 for(int i = 0; i < n_hor; i++) 214 { 215 btScalar th = minTh + btScalar(i) * step_h; 216 btScalar sth = radius * btSin(th); 217 btScalar cth = radius * btCos(th); 218 for(int j = 0; j < n_vert; j++) 219 { 220 btScalar psi = minPs + btScalar(j) * step_v; 221 btScalar sps = btSin(psi); 222 btScalar cps = btCos(psi); 223 pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv; 224 if(i) 225 { 226 drawLine(pvA[j], pvB[j], color); 227 } 228 else if(drawS) 229 { 230 drawLine(spole, pvB[j], color); 231 } 232 if(j) 233 { 234 drawLine(pvB[j-1], pvB[j], color); 235 } 236 else 237 { 238 arcStart = pvB[j]; 239 } 240 if((i == (n_hor - 1)) && drawN) 241 { 242 drawLine(npole, pvB[j], color); 243 } 244 if(isClosed) 245 { 246 if(j == (n_vert-1)) 247 { 248 drawLine(arcStart, pvB[j], color); 249 } 250 } 251 else 252 { 253 if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1)))) 254 { 255 drawLine(center, pvB[j], color); 256 } 257 } 258 } 259 pT = pvA; pvA = pvB; pvB = pT; 260 } 261 } 262 263 void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color) 264 { 265 drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color); 266 drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color); 267 drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color); 268 drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color); 269 drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color); 270 drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color); 271 drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color); 272 drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color); 273 drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color); 274 drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color); 275 drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color); 276 drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color); 277 } 278 void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color) 279 { 280 drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color); 281 drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color); 282 drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color); 283 drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color); 284 drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color); 285 drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color); 286 drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color); 287 drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color); 288 drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color); 289 drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color); 290 drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color); 291 drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color); 292 } 112 293 }; 113 294 -
code/trunk/src/bullet/LinearMath/btMatrix3x3.h
r2662 r2882 193 193 btScalar(0.0), btScalar(0.0), btScalar(1.0)); 194 194 } 195 196 static const btMatrix3x3& getIdentity() 197 { 198 static const btMatrix3x3 identityMatrix(btScalar(1.0), btScalar(0.0), btScalar(0.0), 199 btScalar(0.0), btScalar(1.0), btScalar(0.0), 200 btScalar(0.0), btScalar(0.0), btScalar(1.0)); 201 return identityMatrix; 202 } 203 195 204 /**@brief Fill the values of the matrix into a 9 element array 196 205 * @param m The array to be filled */ -
code/trunk/src/bullet/LinearMath/btQuadWord.h
r2662 r2882 25 25 #endif 26 26 27 /**@brief The btQuadWord Storageclass is base class for btVector3 and btQuaternion.27 /**@brief The btQuadWord class is base class for btVector3 and btQuaternion. 28 28 * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. 29 29 */ 30 30 #ifndef USE_LIBSPE2 31 ATTRIBUTE_ALIGNED16(class) btQuadWord Storage31 ATTRIBUTE_ALIGNED16(class) btQuadWord 32 32 #else 33 class btQuadWord Storage33 class btQuadWord 34 34 #endif 35 35 { … … 46 46 return mVec128; 47 47 } 48 protected: 48 49 #else //__CELLOS_LV2__ __SPU__ 49 50 btScalar m_floats[4]; 50 51 #endif //__CELLOS_LV2__ __SPU__ 51 52 52 };53 54 /** @brief The btQuadWord is base-class for vectors, points */55 class btQuadWord : public btQuadWordStorage56 {57 53 public: 58 54 … … 135 131 { 136 132 } 137 /**@brief Copy constructor */ 138 SIMD_FORCE_INLINE btQuadWord(const btQuadWordStorage& q) 139 { 140 *((btQuadWordStorage*)this) = q; 141 } 133 142 134 /**@brief Three argument constructor (zeros w) 143 135 * @param x Value of x -
code/trunk/src/bullet/LinearMath/btQuaternion.h
r2662 r2882 20 20 21 21 #include "btVector3.h" 22 #include "btQuadWord.h" 22 23 23 24 /**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */ … … 58 59 { 59 60 btScalar d = axis.length(); 60 assert(d != btScalar(0.0));61 btAssert(d != btScalar(0.0)); 61 62 btScalar s = btSin(angle * btScalar(0.5)) / d; 62 63 setValue(axis.x() * s, axis.y() * s, axis.z() * s, … … 177 178 btQuaternion operator/(const btScalar& s) const 178 179 { 179 assert(s != btScalar(0.0));180 btAssert(s != btScalar(0.0)); 180 181 return *this * (btScalar(1.0) / s); 181 182 } … … 185 186 btQuaternion& operator/=(const btScalar& s) 186 187 { 187 assert(s != btScalar(0.0));188 btAssert(s != btScalar(0.0)); 188 189 return *this *= btScalar(1.0) / s; 189 190 } … … 199 200 { 200 201 btScalar s = btSqrt(length2() * q.length2()); 201 assert(s != btScalar(0.0));202 btAssert(s != btScalar(0.0)); 202 203 return btAcos(dot(q) / s); 203 204 } … … 275 276 } 276 277 278 static const btQuaternion& getIdentity() 279 { 280 static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.)); 281 return identityQuat; 282 } 283 277 284 SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; } 278 285 -
code/trunk/src/bullet/LinearMath/btScalar.h
r2662 r2882 26 26 #include <float.h> 27 27 28 #define BT_BULLET_VERSION 27 328 #define BT_BULLET_VERSION 274 29 29 30 30 inline int btGetVersion() … … 46 46 #define ATTRIBUTE_ALIGNED128(a) a 47 47 #else 48 #define BT_HAS_ALIGNED_ALLOCATOR48 //#define BT_HAS_ALIGNED_ALLOCATOR 49 49 #pragma warning(disable : 4324) // disable padding warning 50 50 // #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. … … 62 62 #define btFsel(a,b,c) __fsel((a),(b),(c)) 63 63 #else 64 65 #if (defined (WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION)) 64 66 #define BT_USE_SSE 65 #endif 67 #include <emmintrin.h> 68 #endif 69 70 #endif//_XBOX 71 66 72 #endif //__MINGW32__ 67 73 … … 125 131 126 132 #define SIMD_FORCE_INLINE inline 133 ///@todo: check out alignment methods for other platforms/compilers 134 ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 135 ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 127 136 #define ATTRIBUTE_ALIGNED16(a) a 128 137 #define ATTRIBUTE_ALIGNED128(a) a … … 228 237 SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); } 229 238 SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); } 230 #if defined( __MINGW32__ ) 231 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } 232 #else 233 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } 234 #endif 235 239 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } 240 236 241 #endif 237 242 -
code/trunk/src/bullet/LinearMath/btTransform.h
r2662 r2882 191 191 192 192 /**@brief Return an identity transform */ 193 static btTransform getIdentity() 194 { 195 btTransform tr; 196 tr.setIdentity(); 197 return tr; 193 static const btTransform& getIdentity() 194 { 195 static const btTransform identityTransform(btMatrix3x3::getIdentity()); 196 return identityTransform; 198 197 } 199 198 -
code/trunk/src/bullet/LinearMath/btVector3.h
r2662 r2882 18 18 #define SIMD__VECTOR3_H 19 19 20 #include "btQuadWord.h" 21 20 21 #include "btScalar.h" 22 #include "btScalar.h" 23 #include "btMinMax.h" 22 24 /**@brief btVector3 can be used to represent 3D points and vectors. 23 25 * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user 24 26 * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers 25 27 */ 26 class btVector3 : public btQuadWord { 27 28 29 ATTRIBUTE_ALIGNED16(class) btVector3 30 { 28 31 public: 32 33 #if defined (__SPU__) && defined (__CELLOS_LV2__) 34 union { 35 vec_float4 mVec128; 36 btScalar m_floats[4]; 37 }; 38 public: 39 vec_float4 get128() const 40 { 41 return mVec128; 42 } 43 public: 44 #else //__CELLOS_LV2__ __SPU__ 45 #ifdef BT_USE_SSE // WIN32 46 union { 47 __m128 mVec128; 48 btScalar m_floats[4]; 49 }; 50 SIMD_FORCE_INLINE __m128 get128() const 51 { 52 return mVec128; 53 } 54 SIMD_FORCE_INLINE void set128(__m128 v128) 55 { 56 mVec128 = v128; 57 } 58 #else 59 btScalar m_floats[4]; 60 #endif 61 #endif //__CELLOS_LV2__ __SPU__ 62 63 public: 64 29 65 /**@brief No initialization constructor */ 30 66 SIMD_FORCE_INLINE btVector3() {} 31 67 32 /**@brief Constructor from btQuadWordStorage (btVector3 inherits from this so is also valid) 33 * Note: Vector3 derives from btQuadWordStorage*/ 34 SIMD_FORCE_INLINE btVector3(const btQuadWordStorage& q) 35 : btQuadWord(q) 36 { 37 } 68 38 69 39 70 /**@brief Constructor from scalars … … 42 73 * @param z Z value 43 74 */ 44 SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) 45 :btQuadWord(x,y,z,btScalar(0.)) 46 { 47 } 48 49 // SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) 50 // : btQuadWord(x,y,z,w) 51 // { 52 // } 75 SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) 76 { 77 m_floats[0] = x; 78 m_floats[1] = y; 79 m_floats[2] = z; 80 m_floats[3] = btScalar(0.); 81 } 53 82 54 83 … … 58 87 { 59 88 60 m_floats[0] += v. x(); m_floats[1] += v.y(); m_floats[2] += v.z();89 m_floats[0] += v.m_floats[0]; m_floats[1] += v.m_floats[1];m_floats[2] += v.m_floats[2]; 61 90 return *this; 62 91 } … … 67 96 SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) 68 97 { 69 m_floats[0] -= v. x(); m_floats[1] -= v.y(); m_floats[2] -= v.z();98 m_floats[0] -= v.m_floats[0]; m_floats[1] -= v.m_floats[1];m_floats[2] -= v.m_floats[2]; 70 99 return *this; 71 100 } … … 74 103 SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s) 75 104 { 76 m_floats[0] *= s; m_floats[1] *= s; 105 m_floats[0] *= s; m_floats[1] *= s;m_floats[2] *= s; 77 106 return *this; 78 107 } … … 90 119 SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const 91 120 { 92 return m_floats[0] * v. x() + m_floats[1] * v.y() + m_floats[2] * v.z();121 return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] +m_floats[2] * v.m_floats[2]; 93 122 } 94 123 … … 149 178 { 150 179 return btVector3( 151 m_floats[1] * v. z() - m_floats[2] * v.y(),152 m_floats[2] * v. x() - m_floats[0] * v.z(),153 m_floats[0] * v. y() - m_floats[1] * v.x());180 m_floats[1] * v.m_floats[2] -m_floats[2] * v.m_floats[1], 181 m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2], 182 m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]); 154 183 } 155 184 156 185 SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const 157 186 { 158 return m_floats[0] * (v1. y() * v2.z() - v1.z() * v2.y()) +159 m_floats[1] * (v1. z() * v2.x() - v1.x() * v2.z()) +160 m_floats[2] * (v1. x() * v2.y() - v1.y() * v2.x());187 return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) + 188 m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) + 189 m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]); 161 190 } 162 191 … … 165 194 SIMD_FORCE_INLINE int minAxis() const 166 195 { 167 return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2);196 return m_floats[0] < m_floats[1] ? (m_floats[0] <m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2); 168 197 } 169 198 … … 172 201 SIMD_FORCE_INLINE int maxAxis() const 173 202 { 174 return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0);203 return m_floats[0] < m_floats[1] ? (m_floats[1] <m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0); 175 204 } 176 205 … … 188 217 { 189 218 btScalar s = btScalar(1.0) - rt; 190 m_floats[0] = s * v0. x() + rt * v1.x();191 m_floats[1] = s * v0. y() + rt * v1.y();192 m_floats[2] = s * v0. z() + rt * v1.z();219 m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0]; 220 m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1]; 221 m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2]; 193 222 //don't do the unused w component 194 223 // m_co[3] = s * v0[3] + rt * v1[3]; … … 200 229 SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const 201 230 { 202 return btVector3(m_floats[0] + (v. x()- m_floats[0]) * t,203 m_floats[1] + (v. y()- m_floats[1]) * t,204 m_floats[2] + (v. z() -m_floats[2]) * t);231 return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t, 232 m_floats[1] + (v.m_floats[1] - m_floats[1]) * t, 233 m_floats[2] + (v.m_floats[2] -m_floats[2]) * t); 205 234 } 206 235 … … 209 238 SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v) 210 239 { 211 m_floats[0] *= v. x(); m_floats[1] *= v.y(); m_floats[2] *= v.z();240 m_floats[0] *= v.m_floats[0]; m_floats[1] *= v.m_floats[1];m_floats[2] *= v.m_floats[2]; 212 241 return *this; 213 242 } 214 243 215 244 /**@brief Return the x value */ 245 SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; } 246 /**@brief Return the y value */ 247 SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; } 248 /**@brief Return the z value */ 249 SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; } 250 /**@brief Set the x value */ 251 SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;}; 252 /**@brief Set the y value */ 253 SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;}; 254 /**@brief Set the z value */ 255 SIMD_FORCE_INLINE void setZ(btScalar z) {m_floats[2] = z;}; 256 /**@brief Set the w value */ 257 SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;}; 258 /**@brief Return the x value */ 259 SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; } 260 /**@brief Return the y value */ 261 SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; } 262 /**@brief Return the z value */ 263 SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; } 264 /**@brief Return the w value */ 265 SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; } 266 267 //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; } 268 //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; } 269 ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons. 270 SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; } 271 SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; } 272 273 SIMD_FORCE_INLINE bool operator==(const btVector3& other) const 274 { 275 return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0])); 276 } 277 278 SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const 279 { 280 return !(*this == other); 281 } 282 283 /**@brief Set each element to the max of the current values and the values of another btVector3 284 * @param other The other btVector3 to compare with 285 */ 286 SIMD_FORCE_INLINE void setMax(const btVector3& other) 287 { 288 btSetMax(m_floats[0], other.m_floats[0]); 289 btSetMax(m_floats[1], other.m_floats[1]); 290 btSetMax(m_floats[2], other.m_floats[2]); 291 btSetMax(m_floats[3], other.w()); 292 } 293 /**@brief Set each element to the min of the current values and the values of another btVector3 294 * @param other The other btVector3 to compare with 295 */ 296 SIMD_FORCE_INLINE void setMin(const btVector3& other) 297 { 298 btSetMin(m_floats[0], other.m_floats[0]); 299 btSetMin(m_floats[1], other.m_floats[1]); 300 btSetMin(m_floats[2], other.m_floats[2]); 301 btSetMin(m_floats[3], other.w()); 302 } 303 304 SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) 305 { 306 m_floats[0]=x; 307 m_floats[1]=y; 308 m_floats[2]=z; 309 m_floats[3] = 0.f; 310 } 311 312 void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const 313 { 314 v0->setValue(0. ,-z() ,y()); 315 v1->setValue(z() ,0. ,-x()); 316 v2->setValue(-y() ,x() ,0.); 317 } 216 318 217 319 }; … … 221 323 operator+(const btVector3& v1, const btVector3& v2) 222 324 { 223 return btVector3(v1. x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z());325 return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]); 224 326 } 225 327 … … 228 330 operator*(const btVector3& v1, const btVector3& v2) 229 331 { 230 return btVector3(v1. x() * v2.x(), v1.y() * v2.y(), v1.z() * v2.z());332 return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]); 231 333 } 232 334 … … 235 337 operator-(const btVector3& v1, const btVector3& v2) 236 338 { 237 return btVector3(v1. x() - v2.x(), v1.y() - v2.y(), v1.z() - v2.z());339 return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]); 238 340 } 239 341 /**@brief Return the negative of the vector */ … … 241 343 operator-(const btVector3& v) 242 344 { 243 return btVector3(-v. x(), -v.y(), -v.z());345 return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]); 244 346 } 245 347 … … 248 350 operator*(const btVector3& v, const btScalar& s) 249 351 { 250 return btVector3(v. x() * s, v.y() * s, v.z()* s);352 return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s); 251 353 } 252 354 … … 270 372 operator/(const btVector3& v1, const btVector3& v2) 271 373 { 272 return btVector3(v1. x() / v2.x(),v1.y() / v2.y(),v1.z() / v2.z());374 return btVector3(v1.m_floats[0] / v2.m_floats[0],v1.m_floats[1] / v2.m_floats[1],v1.m_floats[2] / v2.m_floats[2]); 273 375 } 274 376 … … 326 428 } 327 429 328 /**@brief Test if each element of the vector is equivalent */ 329 SIMD_FORCE_INLINE bool operator==(const btVector3& p1, const btVector3& p2) 330 { 331 return p1.x() == p2.x() && p1.y() == p2.y() && p1.z() == p2.z(); 332 } 430 333 431 334 432 SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const … … 405 503 { 406 504 maxIndex = 2; 407 maxVal = 505 maxVal =m_floats[2]; 408 506 } 409 507 if (m_floats[3] > maxVal) … … 438 536 { 439 537 minIndex = 2; 440 minVal = 538 minVal =m_floats[2]; 441 539 } 442 540 if (m_floats[3] < minVal) … … 455 553 return absolute4().maxAxis4(); 456 554 } 555 556 557 558 559 /**@brief Set x,y,z and zero w 560 * @param x Value of x 561 * @param y Value of y 562 * @param z Value of z 563 */ 564 565 566 /* void getValue(btScalar *m) const 567 { 568 m[0] = m_floats[0]; 569 m[1] = m_floats[1]; 570 m[2] =m_floats[2]; 571 } 572 */ 573 /**@brief Set the values 574 * @param x Value of x 575 * @param y Value of y 576 * @param z Value of z 577 * @param w Value of w 578 */ 579 SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) 580 { 581 m_floats[0]=x; 582 m_floats[1]=y; 583 m_floats[2]=z; 584 m_floats[3]=w; 585 } 586 587 588 457 589 458 590 };
Note: See TracChangeset
for help on using the changeset viewer.