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 /// btCollisionObject can be used to manage collision detection objects.
46 /// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
47 /// They can be added to the btCollisionWorld.
ATTRIBUTE_ALIGNED16(class)48 ATTRIBUTE_ALIGNED16(class)
49 btCollisionObject
50 {
51 protected:
52 	btTransform m_worldTransform;
53 
54 	///m_interpolationWorldTransform is used for CCD and interpolation
55 	///it can be either previous or future (predicted) transform
56 	btTransform m_interpolationWorldTransform;
57 	//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
58 	//without destroying the continuous interpolated motion (which uses this interpolation velocities)
59 	btVector3 m_interpolationLinearVelocity;
60 	btVector3 m_interpolationAngularVelocity;
61 
62 	btVector3 m_anisotropicFriction;
63 	int m_hasAnisotropicFriction;
64 	btScalar m_contactProcessingThreshold;
65 
66 	btBroadphaseProxy* m_broadphaseHandle;
67 	btCollisionShape* m_collisionShape;
68 	///m_extensionPointer is used by some internal low-level Bullet extensions.
69 	void* m_extensionPointer;
70 
71 	///m_rootCollisionShape is temporarily used to store the original collision shape
72 	///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
73 	///If it is NULL, the m_collisionShape is not temporarily replaced.
74 	btCollisionShape* m_rootCollisionShape;
75 
76 	int m_collisionFlags;
77 
78 	int m_islandTag1;
79 	int m_companionId;
80 	int m_worldArrayIndex;  // index of object in world's collisionObjects array
81 
82 	mutable int m_activationState1;
83 	mutable btScalar m_deactivationTime;
84 
85 	btScalar m_friction;
86 	btScalar m_restitution;
87 	btScalar m_rollingFriction;   //torsional friction orthogonal to contact normal (useful to stop spheres rolling forever)
88 	btScalar m_spinningFriction;  // torsional friction around the contact normal (useful for grasping)
89 	btScalar m_contactDamping;
90 	btScalar m_contactStiffness;
91 
92 	///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
93 	///do not assign your own m_internalType unless you write a new dynamics object class.
94 	int m_internalType;
95 
96 	///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
97 
98 	void* m_userObjectPointer;
99 
100 	int m_userIndex2;
101 
102 	int m_userIndex;
103 
104 	int m_userIndex3;
105 
106 	///time of impact calculation
107 	btScalar m_hitFraction;
108 
109 	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
110 	btScalar m_ccdSweptSphereRadius;
111 
112 	/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
113 	btScalar m_ccdMotionThreshold;
114 
115 	/// If some object should have elaborate collision filtering by sub-classes
116 	int m_checkCollideWith;
117 
118 	btAlignedObjectArray<const btCollisionObject*> m_objectsWithoutCollisionCheck;
119 
120 	///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation.
121 	int m_updateRevision;
122 
123 	btVector3 m_customDebugColorRGB;
124 
125 public:
126 	BT_DECLARE_ALIGNED_ALLOCATOR();
127 
128 	enum CollisionFlags
129 	{
130 		CF_STATIC_OBJECT = 1,
131 		CF_KINEMATIC_OBJECT = 2,
132 		CF_NO_CONTACT_RESPONSE = 4,
133 		CF_CUSTOM_MATERIAL_CALLBACK = 8,  //this allows per-triangle material (friction/restitution)
134 		CF_CHARACTER_OBJECT = 16,
135 		CF_DISABLE_VISUALIZE_OBJECT = 32,          //disable debug drawing
136 		CF_DISABLE_SPU_COLLISION_PROCESSING = 64,  //disable parallel/SPU processing
137 		CF_HAS_CONTACT_STIFFNESS_DAMPING = 128,
138 		CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256,
139 		CF_HAS_FRICTION_ANCHOR = 512,
140 		CF_HAS_COLLISION_SOUND_TRIGGER = 1024
141 	};
142 
143 	enum CollisionObjectTypes
144 	{
145 		CO_COLLISION_OBJECT = 1,
146 		CO_RIGID_BODY = 2,
147 		///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
148 		///It is useful for collision sensors, explosion objects, character controller etc.
149 		CO_GHOST_OBJECT = 4,
150 		CO_SOFT_BODY = 8,
151 		CO_HF_FLUID = 16,
152 		CO_USER_TYPE = 32,
153 		CO_FEATHERSTONE_LINK = 64
154 	};
155 
156 	enum AnisotropicFrictionFlags
157 	{
158 		CF_ANISOTROPIC_FRICTION_DISABLED = 0,
159 		CF_ANISOTROPIC_FRICTION = 1,
160 		CF_ANISOTROPIC_ROLLING_FRICTION = 2
161 	};
162 
163 	SIMD_FORCE_INLINE bool mergesSimulationIslands() const
164 	{
165 		///static objects, kinematic and object without contact response don't merge islands
166 		return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE)) == 0);
167 	}
168 
169 	const btVector3& getAnisotropicFriction() const
170 	{
171 		return m_anisotropicFriction;
172 	}
173 	void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
174 	{
175 		m_anisotropicFriction = anisotropicFriction;
176 		bool isUnity = (anisotropicFriction[0] != 1.f) || (anisotropicFriction[1] != 1.f) || (anisotropicFriction[2] != 1.f);
177 		m_hasAnisotropicFriction = isUnity ? frictionMode : 0;
178 	}
179 	bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
180 	{
181 		return (m_hasAnisotropicFriction & frictionMode) != 0;
182 	}
183 
184 	///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
185 	///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
186 	void setContactProcessingThreshold(btScalar contactProcessingThreshold)
187 	{
188 		m_contactProcessingThreshold = contactProcessingThreshold;
189 	}
190 	btScalar getContactProcessingThreshold() const
191 	{
192 		return m_contactProcessingThreshold;
193 	}
194 
195 	SIMD_FORCE_INLINE bool isStaticObject() const
196 	{
197 		return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
198 	}
199 
200 	SIMD_FORCE_INLINE bool isKinematicObject() const
201 	{
202 		return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
203 	}
204 
205 	SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
206 	{
207 		return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0;
208 	}
209 
210 	SIMD_FORCE_INLINE bool hasContactResponse() const
211 	{
212 		return (m_collisionFlags & CF_NO_CONTACT_RESPONSE) == 0;
213 	}
214 
215 	btCollisionObject();
216 
217 	virtual ~btCollisionObject();
218 
219 	virtual void setCollisionShape(btCollisionShape * collisionShape)
220 	{
221 		m_updateRevision++;
222 		m_collisionShape = collisionShape;
223 		m_rootCollisionShape = collisionShape;
224 	}
225 
226 	SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
227 	{
228 		return m_collisionShape;
229 	}
230 
231 	SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
232 	{
233 		return m_collisionShape;
234 	}
235 
236 	void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
237 	{
238 		if (ignoreCollisionCheck)
239 		{
240 			//We don't check for duplicates. Is it ok to leave that up to the user of this API?
241 			//int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
242 			//if (index == m_objectsWithoutCollisionCheck.size())
243 			//{
244 			m_objectsWithoutCollisionCheck.push_back(co);
245 			//}
246 		}
247 		else
248 		{
249 			m_objectsWithoutCollisionCheck.remove(co);
250 		}
251 		m_checkCollideWith = m_objectsWithoutCollisionCheck.size() > 0;
252 	}
253 
254 	virtual bool checkCollideWithOverride(const btCollisionObject* co) const
255 	{
256 		int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
257 		if (index < m_objectsWithoutCollisionCheck.size())
258 		{
259 			return false;
260 		}
261 		return true;
262 	}
263 
264 	///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
265 	///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
266 	void* internalGetExtensionPointer() const
267 	{
268 		return m_extensionPointer;
269 	}
270 	///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
271 	///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
272 	void internalSetExtensionPointer(void* pointer)
273 	{
274 		m_extensionPointer = pointer;
275 	}
276 
277 	SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1; }
278 
279 	void setActivationState(int newState) const;
280 
281 	void setDeactivationTime(btScalar time)
282 	{
283 		m_deactivationTime = time;
284 	}
285 	btScalar getDeactivationTime() const
286 	{
287 		return m_deactivationTime;
288 	}
289 
290 	void forceActivationState(int newState) const;
291 
292 	void activate(bool forceActivation = false) const;
293 
294 	SIMD_FORCE_INLINE bool isActive() const
295 	{
296 		return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
297 	}
298 
299 	void setRestitution(btScalar rest)
300 	{
301 		m_updateRevision++;
302 		m_restitution = rest;
303 	}
304 	btScalar getRestitution() const
305 	{
306 		return m_restitution;
307 	}
308 	void setFriction(btScalar frict)
309 	{
310 		m_updateRevision++;
311 		m_friction = frict;
312 	}
313 	btScalar getFriction() const
314 	{
315 		return m_friction;
316 	}
317 
318 	void setRollingFriction(btScalar frict)
319 	{
320 		m_updateRevision++;
321 		m_rollingFriction = frict;
322 	}
323 	btScalar getRollingFriction() const
324 	{
325 		return m_rollingFriction;
326 	}
327 	void setSpinningFriction(btScalar frict)
328 	{
329 		m_updateRevision++;
330 		m_spinningFriction = frict;
331 	}
332 	btScalar getSpinningFriction() const
333 	{
334 		return m_spinningFriction;
335 	}
336 	void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping)
337 	{
338 		m_updateRevision++;
339 		m_contactStiffness = stiffness;
340 		m_contactDamping = damping;
341 
342 		m_collisionFlags |= CF_HAS_CONTACT_STIFFNESS_DAMPING;
343 
344 		//avoid divisions by zero...
345 		if (m_contactStiffness < SIMD_EPSILON)
346 		{
347 			m_contactStiffness = SIMD_EPSILON;
348 		}
349 	}
350 
351 	btScalar getContactStiffness() const
352 	{
353 		return m_contactStiffness;
354 	}
355 
356 	btScalar getContactDamping() const
357 	{
358 		return m_contactDamping;
359 	}
360 
361 	///reserved for Bullet internal usage
362 	int getInternalType() const
363 	{
364 		return m_internalType;
365 	}
366 
367 	btTransform& getWorldTransform()
368 	{
369 		return m_worldTransform;
370 	}
371 
372 	const btTransform& getWorldTransform() const
373 	{
374 		return m_worldTransform;
375 	}
376 
377 	void setWorldTransform(const btTransform& worldTrans)
378 	{
379 		m_updateRevision++;
380 		m_worldTransform = worldTrans;
381 	}
382 
383 	SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
384 	{
385 		return m_broadphaseHandle;
386 	}
387 
388 	SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
389 	{
390 		return m_broadphaseHandle;
391 	}
392 
393 	void setBroadphaseHandle(btBroadphaseProxy * handle)
394 	{
395 		m_broadphaseHandle = handle;
396 	}
397 
398 	const btTransform& getInterpolationWorldTransform() const
399 	{
400 		return m_interpolationWorldTransform;
401 	}
402 
403 	btTransform& getInterpolationWorldTransform()
404 	{
405 		return m_interpolationWorldTransform;
406 	}
407 
408 	void setInterpolationWorldTransform(const btTransform& trans)
409 	{
410 		m_updateRevision++;
411 		m_interpolationWorldTransform = trans;
412 	}
413 
414 	void setInterpolationLinearVelocity(const btVector3& linvel)
415 	{
416 		m_updateRevision++;
417 		m_interpolationLinearVelocity = linvel;
418 	}
419 
420 	void setInterpolationAngularVelocity(const btVector3& angvel)
421 	{
422 		m_updateRevision++;
423 		m_interpolationAngularVelocity = angvel;
424 	}
425 
426 	const btVector3& getInterpolationLinearVelocity() const
427 	{
428 		return m_interpolationLinearVelocity;
429 	}
430 
431 	const btVector3& getInterpolationAngularVelocity() const
432 	{
433 		return m_interpolationAngularVelocity;
434 	}
435 
436 	SIMD_FORCE_INLINE int getIslandTag() const
437 	{
438 		return m_islandTag1;
439 	}
440 
441 	void setIslandTag(int tag)
442 	{
443 		m_islandTag1 = tag;
444 	}
445 
446 	SIMD_FORCE_INLINE int getCompanionId() const
447 	{
448 		return m_companionId;
449 	}
450 
451 	void setCompanionId(int id)
452 	{
453 		m_companionId = id;
454 	}
455 
456 	SIMD_FORCE_INLINE int getWorldArrayIndex() const
457 	{
458 		return m_worldArrayIndex;
459 	}
460 
461 	// only should be called by CollisionWorld
462 	void setWorldArrayIndex(int ix)
463 	{
464 		m_worldArrayIndex = ix;
465 	}
466 
467 	SIMD_FORCE_INLINE btScalar getHitFraction() const
468 	{
469 		return m_hitFraction;
470 	}
471 
472 	void setHitFraction(btScalar hitFraction)
473 	{
474 		m_hitFraction = hitFraction;
475 	}
476 
477 	SIMD_FORCE_INLINE int getCollisionFlags() const
478 	{
479 		return m_collisionFlags;
480 	}
481 
482 	void setCollisionFlags(int flags)
483 	{
484 		m_collisionFlags = flags;
485 	}
486 
487 	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
488 	btScalar getCcdSweptSphereRadius() const
489 	{
490 		return m_ccdSweptSphereRadius;
491 	}
492 
493 	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
494 	void setCcdSweptSphereRadius(btScalar radius)
495 	{
496 		m_ccdSweptSphereRadius = radius;
497 	}
498 
499 	btScalar getCcdMotionThreshold() const
500 	{
501 		return m_ccdMotionThreshold;
502 	}
503 
504 	btScalar getCcdSquareMotionThreshold() const
505 	{
506 		return m_ccdMotionThreshold * m_ccdMotionThreshold;
507 	}
508 
509 	/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
510 	void setCcdMotionThreshold(btScalar ccdMotionThreshold)
511 	{
512 		m_ccdMotionThreshold = ccdMotionThreshold;
513 	}
514 
515 	///users can point to their objects, userPointer is not used by Bullet
516 	void* getUserPointer() const
517 	{
518 		return m_userObjectPointer;
519 	}
520 
521 	int getUserIndex() const
522 	{
523 		return m_userIndex;
524 	}
525 
526 	int getUserIndex2() const
527 	{
528 		return m_userIndex2;
529 	}
530 
531 	int getUserIndex3() const
532 	{
533 		return m_userIndex3;
534 	}
535 
536 	///users can point to their objects, userPointer is not used by Bullet
537 	void setUserPointer(void* userPointer)
538 	{
539 		m_userObjectPointer = userPointer;
540 	}
541 
542 	///users can point to their objects, userPointer is not used by Bullet
543 	void setUserIndex(int index)
544 	{
545 		m_userIndex = index;
546 	}
547 
548 	void setUserIndex2(int index)
549 	{
550 		m_userIndex2 = index;
551 	}
552 
553 	void setUserIndex3(int index)
554 	{
555 		m_userIndex3 = index;
556 	}
557 
558 	int getUpdateRevisionInternal() const
559 	{
560 		return m_updateRevision;
561 	}
562 
563 	void setCustomDebugColor(const btVector3& colorRGB)
564 	{
565 		m_customDebugColorRGB = colorRGB;
566 		m_collisionFlags |= CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
567 	}
568 
569 	void removeCustomDebugColor()
570 	{
571 		m_collisionFlags &= ~CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
572 	}
573 
574 	bool getCustomDebugColor(btVector3 & colorRGB) const
575 	{
576 		bool hasCustomColor = (0 != (m_collisionFlags & CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR));
577 		if (hasCustomColor)
578 		{
579 			colorRGB = m_customDebugColorRGB;
580 		}
581 		return hasCustomColor;
582 	}
583 
584 	inline bool checkCollideWith(const btCollisionObject* co) const
585 	{
586 		if (m_checkCollideWith)
587 			return checkCollideWithOverride(co);
588 
589 		return true;
590 	}
591 
592 	virtual int calculateSerializeBufferSize() const;
593 
594 	///fills the dataBuffer and returns the struct name (and 0 on failure)
595 	virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
596 
597 	virtual void serializeSingleObject(class btSerializer * serializer) const;
598 };
599 
600 // clang-format off
601 
602 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
603 struct	btCollisionObjectDoubleData
604 {
605 	void					*m_broadphaseHandle;
606 	void					*m_collisionShape;
607 	btCollisionShapeData	*m_rootCollisionShape;
608 	char					*m_name;
609 
610 	btTransformDoubleData	m_worldTransform;
611 	btTransformDoubleData	m_interpolationWorldTransform;
612 	btVector3DoubleData		m_interpolationLinearVelocity;
613 	btVector3DoubleData		m_interpolationAngularVelocity;
614 	btVector3DoubleData		m_anisotropicFriction;
615 	double					m_contactProcessingThreshold;
616 	double					m_deactivationTime;
617 	double					m_friction;
618 	double					m_rollingFriction;
619 	double                  m_contactDamping;
620 	double                  m_contactStiffness;
621 	double					m_restitution;
622 	double					m_hitFraction;
623 	double					m_ccdSweptSphereRadius;
624 	double					m_ccdMotionThreshold;
625 	int						m_hasAnisotropicFriction;
626 	int						m_collisionFlags;
627 	int						m_islandTag1;
628 	int						m_companionId;
629 	int						m_activationState1;
630 	int						m_internalType;
631 	int						m_checkCollideWith;
632 	int						m_collisionFilterGroup;
633 	int						m_collisionFilterMask;
634 	int						m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
635 };
636 
637 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
638 struct	btCollisionObjectFloatData
639 {
640 	void					*m_broadphaseHandle;
641 	void					*m_collisionShape;
642 	btCollisionShapeData	*m_rootCollisionShape;
643 	char					*m_name;
644 
645 	btTransformFloatData	m_worldTransform;
646 	btTransformFloatData	m_interpolationWorldTransform;
647 	btVector3FloatData		m_interpolationLinearVelocity;
648 	btVector3FloatData		m_interpolationAngularVelocity;
649 	btVector3FloatData		m_anisotropicFriction;
650 	float					m_contactProcessingThreshold;
651 	float					m_deactivationTime;
652 	float					m_friction;
653 	float					m_rollingFriction;
654 	float                   m_contactDamping;
655     float                   m_contactStiffness;
656 	float					m_restitution;
657 	float					m_hitFraction;
658 	float					m_ccdSweptSphereRadius;
659 	float					m_ccdMotionThreshold;
660 	int						m_hasAnisotropicFriction;
661 	int						m_collisionFlags;
662 	int						m_islandTag1;
663 	int						m_companionId;
664 	int						m_activationState1;
665 	int						m_internalType;
666 	int						m_checkCollideWith;
667 	int						m_collisionFilterGroup;
668 	int						m_collisionFilterMask;
669 	int						m_uniqueId;
670 };
671 // clang-format on
672 
calculateSerializeBufferSize()673 SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
674 {
675 	return sizeof(btCollisionObjectData);
676 }
677 
678 #endif  //BT_COLLISION_OBJECT_H
679