1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 subject to the following restrictions: 10 11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 3. This notice may not be removed or altered from any source distribution. 14 */ 15 16 #ifndef BT_COLLISION_OBJECT_H 17 #define BT_COLLISION_OBJECT_H 18 19 #include "LinearMath/btTransform.h" 20 21 //island management, m_activationState1 22 #define ACTIVE_TAG 1 23 #define ISLAND_SLEEPING 2 24 #define WANTS_DEACTIVATION 3 25 #define DISABLE_DEACTIVATION 4 26 #define DISABLE_SIMULATION 5 27 28 struct btBroadphaseProxy; 29 class btCollisionShape; 30 struct btCollisionShapeData; 31 #include "LinearMath/btMotionState.h" 32 #include "LinearMath/btAlignedAllocator.h" 33 #include "LinearMath/btAlignedObjectArray.h" 34 35 typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray; 36 37 #ifdef BT_USE_DOUBLE_PRECISION 38 #define btCollisionObjectData btCollisionObjectDoubleData 39 #define btCollisionObjectDataName "btCollisionObjectDoubleData" 40 #else 41 #define btCollisionObjectData btCollisionObjectFloatData 42 #define btCollisionObjectDataName "btCollisionObjectFloatData" 43 #endif 44 45 46 /// btCollisionObject can be used to manage collision detection objects. 47 /// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy. 48 /// They can be added to the btCollisionWorld. 49 ATTRIBUTE_ALIGNED16(class) btCollisionObject 50 { 51 52 protected: 53 54 btTransform m_worldTransform; 55 56 ///m_interpolationWorldTransform is used for CCD and interpolation 57 ///it can be either previous or future (predicted) transform 58 btTransform m_interpolationWorldTransform; 59 //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities) 60 //without destroying the continuous interpolated motion (which uses this interpolation velocities) 61 btVector3 m_interpolationLinearVelocity; 62 btVector3 m_interpolationAngularVelocity; 63 64 btVector3 m_anisotropicFriction; 65 int m_hasAnisotropicFriction; 66 btScalar m_contactProcessingThreshold; 67 68 btBroadphaseProxy* m_broadphaseHandle; 69 btCollisionShape* m_collisionShape; 70 ///m_extensionPointer is used by some internal low-level Bullet extensions. 71 void* m_extensionPointer; 72 73 ///m_rootCollisionShape is temporarily used to store the original collision shape 74 ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes 75 ///If it is NULL, the m_collisionShape is not temporarily replaced. 76 btCollisionShape* m_rootCollisionShape; 77 78 int m_collisionFlags; 79 80 int m_islandTag1; 81 int m_companionId; 82 83 mutable int m_activationState1; 84 mutable btScalar m_deactivationTime; 85 86 btScalar m_friction; 87 btScalar m_restitution; 88 btScalar m_rollingFriction; 89 90 ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc. 91 ///do not assign your own m_internalType unless you write a new dynamics object class. 92 int m_internalType; 93 94 ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer 95 96 void* m_userObjectPointer; 97 98 int m_userIndex; 99 100 ///time of impact calculation 101 btScalar m_hitFraction; 102 103 ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: 104 btScalar m_ccdSweptSphereRadius; 105 106 /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold 107 btScalar m_ccdMotionThreshold; 108 109 /// If some object should have elaborate collision filtering by sub-classes 110 int m_checkCollideWith; 111 112 btAlignedObjectArray<const btCollisionObject*> m_objectsWithoutCollisionCheck; 113 114 ///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation. 115 int m_updateRevision; 116 117 118 public: 119 120 BT_DECLARE_ALIGNED_ALLOCATOR(); 121 122 enum CollisionFlags 123 { 124 CF_STATIC_OBJECT= 1, 125 CF_KINEMATIC_OBJECT= 2, 126 CF_NO_CONTACT_RESPONSE = 4, 127 CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution) 128 CF_CHARACTER_OBJECT = 16, 129 CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing 130 CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing 131 }; 132 133 enum CollisionObjectTypes 134 { 135 CO_COLLISION_OBJECT =1, 136 CO_RIGID_BODY=2, 137 ///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter 138 ///It is useful for collision sensors, explosion objects, character controller etc. 139 CO_GHOST_OBJECT=4, 140 CO_SOFT_BODY=8, 141 CO_HF_FLUID=16, 142 CO_USER_TYPE=32, 143 CO_FEATHERSTONE_LINK=64 144 }; 145 146 enum AnisotropicFrictionFlags 147 { 148 CF_ANISOTROPIC_FRICTION_DISABLED=0, 149 CF_ANISOTROPIC_FRICTION = 1, 150 CF_ANISOTROPIC_ROLLING_FRICTION = 2 151 }; 152 153 SIMD_FORCE_INLINE bool mergesSimulationIslands() const 154 { 155 ///static objects, kinematic and object without contact response don't merge islands 156 return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); 157 } 158 159 const btVector3& getAnisotropicFriction() const 160 { 161 return m_anisotropicFriction; 162 } 163 void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION) 164 { 165 m_anisotropicFriction = anisotropicFriction; 166 bool isUnity = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f); 167 m_hasAnisotropicFriction = isUnity?frictionMode : 0; 168 } 169 bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const 170 { 171 return (m_hasAnisotropicFriction&frictionMode)!=0; 172 } 173 174 ///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default. 175 ///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 176 void setContactProcessingThreshold( btScalar contactProcessingThreshold) 177 { 178 m_contactProcessingThreshold = contactProcessingThreshold; 179 } 180 btScalar getContactProcessingThreshold() const 181 { 182 return m_contactProcessingThreshold; 183 } 184 185 SIMD_FORCE_INLINE bool isStaticObject() const { 186 return (m_collisionFlags & CF_STATIC_OBJECT) != 0; 187 } 188 189 SIMD_FORCE_INLINE bool isKinematicObject() const 190 { 191 return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; 192 } 193 194 SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const 195 { 196 return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; 197 } 198 199 SIMD_FORCE_INLINE bool hasContactResponse() const { 200 return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; 201 } 202 203 204 btCollisionObject(); 205 206 virtual ~btCollisionObject(); 207 208 virtual void setCollisionShape(btCollisionShape* collisionShape) 209 { 210 m_updateRevision++; 211 m_collisionShape = collisionShape; 212 m_rootCollisionShape = collisionShape; 213 } 214 215 SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const 216 { 217 return m_collisionShape; 218 } 219 220 SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() 221 { 222 return m_collisionShape; 223 } 224 225 void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck) 226 { 227 if (ignoreCollisionCheck) 228 { 229 //We don't check for duplicates. Is it ok to leave that up to the user of this API? 230 //int index = m_objectsWithoutCollisionCheck.findLinearSearch(co); 231 //if (index == m_objectsWithoutCollisionCheck.size()) 232 //{ 233 m_objectsWithoutCollisionCheck.push_back(co); 234 //} 235 } 236 else 237 { 238 m_objectsWithoutCollisionCheck.remove(co); 239 } 240 m_checkCollideWith = m_objectsWithoutCollisionCheck.size() > 0; 241 } 242 243 virtual bool checkCollideWithOverride(const btCollisionObject* co) const 244 { 245 int index = m_objectsWithoutCollisionCheck.findLinearSearch(co); 246 if (index < m_objectsWithoutCollisionCheck.size()) 247 { 248 return false; 249 } 250 return true; 251 } 252 253 254 255 256 ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions. 257 ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead. 258 void* internalGetExtensionPointer() const 259 { 260 return m_extensionPointer; 261 } 262 ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions 263 ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead. 264 void internalSetExtensionPointer(void* pointer) 265 { 266 m_extensionPointer = pointer; 267 } 268 269 SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;} 270 271 void setActivationState(int newState) const; 272 273 void setDeactivationTime(btScalar time) 274 { 275 m_deactivationTime = time; 276 } 277 btScalar getDeactivationTime() const 278 { 279 return m_deactivationTime; 280 } 281 282 void forceActivationState(int newState) const; 283 284 void activate(bool forceActivation = false) const; 285 286 SIMD_FORCE_INLINE bool isActive() const 287 { 288 return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION)); 289 } 290 291 void setRestitution(btScalar rest) 292 { 293 m_updateRevision++; 294 m_restitution = rest; 295 } 296 btScalar getRestitution() const 297 { 298 return m_restitution; 299 } 300 void setFriction(btScalar frict) 301 { 302 m_updateRevision++; 303 m_friction = frict; 304 } 305 btScalar getFriction() const 306 { 307 return m_friction; 308 } 309 310 void setRollingFriction(btScalar frict) 311 { 312 m_updateRevision++; 313 m_rollingFriction = frict; 314 } 315 btScalar getRollingFriction() const 316 { 317 return m_rollingFriction; 318 } 319 320 321 ///reserved for Bullet internal usage 322 int getInternalType() const 323 { 324 return m_internalType; 325 } 326 327 btTransform& getWorldTransform() 328 { 329 return m_worldTransform; 330 } 331 332 const btTransform& getWorldTransform() const 333 { 334 return m_worldTransform; 335 } 336 337 void setWorldTransform(const btTransform& worldTrans) 338 { 339 m_updateRevision++; 340 m_worldTransform = worldTrans; 341 } 342 343 344 SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle() 345 { 346 return m_broadphaseHandle; 347 } 348 349 SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const 350 { 351 return m_broadphaseHandle; 352 } 353 354 void setBroadphaseHandle(btBroadphaseProxy* handle) 355 { 356 m_broadphaseHandle = handle; 357 } 358 359 360 const btTransform& getInterpolationWorldTransform() const 361 { 362 return m_interpolationWorldTransform; 363 } 364 365 btTransform& getInterpolationWorldTransform() 366 { 367 return m_interpolationWorldTransform; 368 } 369 370 void setInterpolationWorldTransform(const btTransform& trans) 371 { 372 m_updateRevision++; 373 m_interpolationWorldTransform = trans; 374 } 375 376 void setInterpolationLinearVelocity(const btVector3& linvel) 377 { 378 m_updateRevision++; 379 m_interpolationLinearVelocity = linvel; 380 } 381 382 void setInterpolationAngularVelocity(const btVector3& angvel) 383 { 384 m_updateRevision++; 385 m_interpolationAngularVelocity = angvel; 386 } 387 388 const btVector3& getInterpolationLinearVelocity() const 389 { 390 return m_interpolationLinearVelocity; 391 } 392 393 const btVector3& getInterpolationAngularVelocity() const 394 { 395 return m_interpolationAngularVelocity; 396 } 397 398 SIMD_FORCE_INLINE int getIslandTag() const 399 { 400 return m_islandTag1; 401 } 402 403 void setIslandTag(int tag) 404 { 405 m_islandTag1 = tag; 406 } 407 408 SIMD_FORCE_INLINE int getCompanionId() const 409 { 410 return m_companionId; 411 } 412 413 void setCompanionId(int id) 414 { 415 m_companionId = id; 416 } 417 418 SIMD_FORCE_INLINE btScalar getHitFraction() const 419 { 420 return m_hitFraction; 421 } 422 423 void setHitFraction(btScalar hitFraction) 424 { 425 m_hitFraction = hitFraction; 426 } 427 428 429 SIMD_FORCE_INLINE int getCollisionFlags() const 430 { 431 return m_collisionFlags; 432 } 433 434 void setCollisionFlags(int flags) 435 { 436 m_collisionFlags = flags; 437 } 438 439 ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: 440 btScalar getCcdSweptSphereRadius() const 441 { 442 return m_ccdSweptSphereRadius; 443 } 444 445 ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: 446 void setCcdSweptSphereRadius(btScalar radius) 447 { 448 m_ccdSweptSphereRadius = radius; 449 } 450 451 btScalar getCcdMotionThreshold() const 452 { 453 return m_ccdMotionThreshold; 454 } 455 456 btScalar getCcdSquareMotionThreshold() const 457 { 458 return m_ccdMotionThreshold*m_ccdMotionThreshold; 459 } 460 461 462 463 /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold 464 void setCcdMotionThreshold(btScalar ccdMotionThreshold) 465 { 466 m_ccdMotionThreshold = ccdMotionThreshold; 467 } 468 469 ///users can point to their objects, userPointer is not used by Bullet 470 void* getUserPointer() const 471 { 472 return m_userObjectPointer; 473 } 474 475 int getUserIndex() const 476 { 477 return m_userIndex; 478 } 479 ///users can point to their objects, userPointer is not used by Bullet 480 void setUserPointer(void* userPointer) 481 { 482 m_userObjectPointer = userPointer; 483 } 484 485 ///users can point to their objects, userPointer is not used by Bullet 486 void setUserIndex(int index) 487 { 488 m_userIndex = index; 489 } 490 491 int getUpdateRevisionInternal() const 492 { 493 return m_updateRevision; 494 } 495 496 497 inline bool checkCollideWith(const btCollisionObject* co) const 498 { 499 if (m_checkCollideWith) 500 return checkCollideWithOverride(co); 501 502 return true; 503 } 504 505 virtual int calculateSerializeBufferSize() const; 506 507 ///fills the dataBuffer and returns the struct name (and 0 on failure) 508 virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; 509 510 virtual void serializeSingleObject(class btSerializer* serializer) const; 511 512 }; 513 514 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 515 struct btCollisionObjectDoubleData 516 { 517 void *m_broadphaseHandle; 518 void *m_collisionShape; 519 btCollisionShapeData *m_rootCollisionShape; 520 char *m_name; 521 522 btTransformDoubleData m_worldTransform; 523 btTransformDoubleData m_interpolationWorldTransform; 524 btVector3DoubleData m_interpolationLinearVelocity; 525 btVector3DoubleData m_interpolationAngularVelocity; 526 btVector3DoubleData m_anisotropicFriction; 527 double m_contactProcessingThreshold; 528 double m_deactivationTime; 529 double m_friction; 530 double m_rollingFriction; 531 double m_restitution; 532 double m_hitFraction; 533 double m_ccdSweptSphereRadius; 534 double m_ccdMotionThreshold; 535 536 int m_hasAnisotropicFriction; 537 int m_collisionFlags; 538 int m_islandTag1; 539 int m_companionId; 540 int m_activationState1; 541 int m_internalType; 542 int m_checkCollideWith; 543 544 char m_padding[4]; 545 }; 546 547 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 548 struct btCollisionObjectFloatData 549 { 550 void *m_broadphaseHandle; 551 void *m_collisionShape; 552 btCollisionShapeData *m_rootCollisionShape; 553 char *m_name; 554 555 btTransformFloatData m_worldTransform; 556 btTransformFloatData m_interpolationWorldTransform; 557 btVector3FloatData m_interpolationLinearVelocity; 558 btVector3FloatData m_interpolationAngularVelocity; 559 btVector3FloatData m_anisotropicFriction; 560 float m_contactProcessingThreshold; 561 float m_deactivationTime; 562 float m_friction; 563 float m_rollingFriction; 564 565 float m_restitution; 566 float m_hitFraction; 567 float m_ccdSweptSphereRadius; 568 float m_ccdMotionThreshold; 569 570 int m_hasAnisotropicFriction; 571 int m_collisionFlags; 572 int m_islandTag1; 573 int m_companionId; 574 int m_activationState1; 575 int m_internalType; 576 int m_checkCollideWith; 577 char m_padding[4]; 578 }; 579 580 581 582 SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const 583 { 584 return sizeof(btCollisionObjectData); 585 } 586 587 588 589 #endif //BT_COLLISION_OBJECT_H 590