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.
ATTRIBUTE_ALIGNED16(class)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
calculateSerializeBufferSize()582 SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
583 {
584 return sizeof(btCollisionObjectData);
585 }
586
587
588
589 #endif //BT_COLLISION_OBJECT_H
590