add bullet
This commit is contained in:
		| @@ -16,11 +16,13 @@ endif(UNIX) | ||||
| include_directories (${GREMLIN_SOURCE_DIR}/libs/glfw/include) | ||||
| include_directories (${GREMLIN_SOURCE_DIR}/libs/spark/include) | ||||
| include_directories (${GREMLIN_SOURCE_DIR}/libs/enet/include) | ||||
| include_directories (${GREMLIN_SOURCE_DIR}/libs/bullet) | ||||
|  | ||||
| find_package(OpenGL) | ||||
|  | ||||
| add_subdirectory (libs/enet) | ||||
| add_subdirectory (libs/pugixml) | ||||
| add_subdirectory (libs/bullet) | ||||
| add_subdirectory (src/common) | ||||
| add_subdirectory (src/server) | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,37 @@ | ||||
|  | ||||
| //Bullet Continuous Collision Detection and Physics Library | ||||
| //Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
|  | ||||
| // | ||||
| // btAxisSweep3 | ||||
| // | ||||
| // Copyright (c) 2006 Simon Hobbs | ||||
| // | ||||
| // This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| // | ||||
| // Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: | ||||
| // | ||||
| // 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. | ||||
| // | ||||
| // 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| // | ||||
| // 3. This notice may not be removed or altered from any source distribution. | ||||
| #include "btAxisSweep3.h" | ||||
|  | ||||
|  | ||||
| btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator) | ||||
| :btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator) | ||||
| { | ||||
| 	// 1 handle is reserved as sentinel | ||||
| 	btAssert(maxHandles > 1 && maxHandles < 32767); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator) | ||||
| :btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator) | ||||
| { | ||||
| 	// 1 handle is reserved as sentinel | ||||
| 	btAssert(maxHandles > 1 && maxHandles < 2147483647); | ||||
| } | ||||
							
								
								
									
										1051
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1051
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef		BROADPHASE_INTERFACE_H | ||||
| #define 	BROADPHASE_INTERFACE_H | ||||
|  | ||||
|  | ||||
|  | ||||
| struct btDispatcherInfo; | ||||
| class btDispatcher; | ||||
| #include "btBroadphaseProxy.h" | ||||
|  | ||||
| class btOverlappingPairCache; | ||||
|  | ||||
|  | ||||
|  | ||||
| struct	btBroadphaseAabbCallback | ||||
| { | ||||
| 	virtual ~btBroadphaseAabbCallback() {} | ||||
| 	virtual bool	process(const btBroadphaseProxy* proxy) = 0; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct	btBroadphaseRayCallback : public btBroadphaseAabbCallback | ||||
| { | ||||
| 	///added some cached data to accelerate ray-AABB tests | ||||
| 	btVector3		m_rayDirectionInverse; | ||||
| 	unsigned int	m_signs[3]; | ||||
| 	btScalar		m_lambda_max; | ||||
|  | ||||
| 	virtual ~btBroadphaseRayCallback() {} | ||||
| }; | ||||
|  | ||||
| #include "LinearMath/btVector3.h" | ||||
|  | ||||
| ///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs. | ||||
| ///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase. | ||||
| ///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class. | ||||
| class btBroadphaseInterface | ||||
| { | ||||
| public: | ||||
| 	virtual ~btBroadphaseInterface() {} | ||||
|  | ||||
| 	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0; | ||||
| 	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; | ||||
| 	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; | ||||
| 	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0; | ||||
|  | ||||
| 	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0; | ||||
|  | ||||
| 	virtual void	aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0; | ||||
|  | ||||
| 	///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb | ||||
| 	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher)=0; | ||||
|  | ||||
| 	virtual	btOverlappingPairCache*	getOverlappingPairCache()=0; | ||||
| 	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const =0; | ||||
|  | ||||
| 	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame | ||||
| 	///will add some transform later | ||||
| 	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0; | ||||
|  | ||||
| 	///reset broadphase internal structures, to ensure determinism/reproducability | ||||
| 	virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; }; | ||||
|  | ||||
| 	virtual void	printStats() = 0; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BROADPHASE_INTERFACE_H | ||||
| @@ -0,0 +1,17 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btBroadphaseProxy.h" | ||||
|  | ||||
| @@ -0,0 +1,270 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BROADPHASE_PROXY_H | ||||
| #define BROADPHASE_PROXY_H | ||||
|  | ||||
| #include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btAlignedAllocator.h" | ||||
|  | ||||
|  | ||||
| /// btDispatcher uses these types | ||||
| /// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave | ||||
| /// to facilitate type checking | ||||
| /// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code | ||||
| enum BroadphaseNativeTypes | ||||
| { | ||||
| 	// polyhedral convex shapes | ||||
| 	BOX_SHAPE_PROXYTYPE, | ||||
| 	TRIANGLE_SHAPE_PROXYTYPE, | ||||
| 	TETRAHEDRAL_SHAPE_PROXYTYPE, | ||||
| 	CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE, | ||||
| 	CONVEX_HULL_SHAPE_PROXYTYPE, | ||||
| 	CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE, | ||||
| 	CUSTOM_POLYHEDRAL_SHAPE_TYPE, | ||||
| //implicit convex shapes | ||||
| IMPLICIT_CONVEX_SHAPES_START_HERE, | ||||
| 	SPHERE_SHAPE_PROXYTYPE, | ||||
| 	MULTI_SPHERE_SHAPE_PROXYTYPE, | ||||
| 	CAPSULE_SHAPE_PROXYTYPE, | ||||
| 	CONE_SHAPE_PROXYTYPE, | ||||
| 	CONVEX_SHAPE_PROXYTYPE, | ||||
| 	CYLINDER_SHAPE_PROXYTYPE, | ||||
| 	UNIFORM_SCALING_SHAPE_PROXYTYPE, | ||||
| 	MINKOWSKI_SUM_SHAPE_PROXYTYPE, | ||||
| 	MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, | ||||
| 	BOX_2D_SHAPE_PROXYTYPE, | ||||
| 	CONVEX_2D_SHAPE_PROXYTYPE, | ||||
| 	CUSTOM_CONVEX_SHAPE_TYPE, | ||||
| //concave shapes | ||||
| CONCAVE_SHAPES_START_HERE, | ||||
| 	//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! | ||||
| 	TRIANGLE_MESH_SHAPE_PROXYTYPE, | ||||
| 	SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE, | ||||
| 	///used for demo integration FAST/Swift collision library and Bullet | ||||
| 	FAST_CONCAVE_MESH_PROXYTYPE, | ||||
| 	//terrain | ||||
| 	TERRAIN_SHAPE_PROXYTYPE, | ||||
| ///Used for GIMPACT Trimesh integration | ||||
| 	GIMPACT_SHAPE_PROXYTYPE, | ||||
| ///Multimaterial mesh | ||||
|     MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE, | ||||
| 	 | ||||
| 	EMPTY_SHAPE_PROXYTYPE, | ||||
| 	STATIC_PLANE_PROXYTYPE, | ||||
| 	CUSTOM_CONCAVE_SHAPE_TYPE, | ||||
| CONCAVE_SHAPES_END_HERE, | ||||
|  | ||||
| 	COMPOUND_SHAPE_PROXYTYPE, | ||||
|  | ||||
| 	SOFTBODY_SHAPE_PROXYTYPE, | ||||
| 	HFFLUID_SHAPE_PROXYTYPE, | ||||
| 	HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE, | ||||
| 	INVALID_SHAPE_PROXYTYPE, | ||||
|  | ||||
| 	MAX_BROADPHASE_COLLISION_TYPES | ||||
| 	 | ||||
| }; | ||||
|  | ||||
|  | ||||
| ///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.  | ||||
| ///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody. | ||||
| ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy | ||||
| { | ||||
|  | ||||
| BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
| 	 | ||||
| 	///optional filtering to cull potential collisions | ||||
| 	enum CollisionFilterGroups | ||||
| 	{ | ||||
| 	        DefaultFilter = 1, | ||||
| 	        StaticFilter = 2, | ||||
| 	        KinematicFilter = 4, | ||||
| 	        DebrisFilter = 8, | ||||
| 			SensorTrigger = 16, | ||||
| 			CharacterFilter = 32, | ||||
| 	        AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger | ||||
| 	}; | ||||
|  | ||||
| 	//Usually the client btCollisionObject or Rigidbody class | ||||
| 	void*	m_clientObject; | ||||
| 	short int m_collisionFilterGroup; | ||||
| 	short int m_collisionFilterMask; | ||||
| 	void*	m_multiSapParentProxy;		 | ||||
| 	int			m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. | ||||
|  | ||||
| 	btVector3	m_aabbMin; | ||||
| 	btVector3	m_aabbMax; | ||||
|  | ||||
| 	SIMD_FORCE_INLINE int getUid() const | ||||
| 	{ | ||||
| 		return m_uniqueId; | ||||
| 	} | ||||
|  | ||||
| 	//used for memory pools | ||||
| 	btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) | ||||
| 		:m_clientObject(userPtr), | ||||
| 		m_collisionFilterGroup(collisionFilterGroup), | ||||
| 		m_collisionFilterMask(collisionFilterMask), | ||||
| 		m_aabbMin(aabbMin), | ||||
| 		m_aabbMax(aabbMax) | ||||
| 	{ | ||||
| 		m_multiSapParentProxy = multiSapParentProxy; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType) | ||||
| 	{ | ||||
| 		return (proxyType  < IMPLICIT_CONVEX_SHAPES_START_HERE); | ||||
| 	} | ||||
|  | ||||
| 	static SIMD_FORCE_INLINE bool	isConvex(int proxyType) | ||||
| 	{ | ||||
| 		return (proxyType < CONCAVE_SHAPES_START_HERE); | ||||
| 	} | ||||
|  | ||||
| 	static SIMD_FORCE_INLINE bool	isNonMoving(int proxyType) | ||||
| 	{ | ||||
| 		return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE)); | ||||
| 	} | ||||
|  | ||||
| 	static SIMD_FORCE_INLINE bool	isConcave(int proxyType) | ||||
| 	{ | ||||
| 		return ((proxyType > CONCAVE_SHAPES_START_HERE) && | ||||
| 			(proxyType < CONCAVE_SHAPES_END_HERE)); | ||||
| 	} | ||||
| 	static SIMD_FORCE_INLINE bool	isCompound(int proxyType) | ||||
| 	{ | ||||
| 		return (proxyType == COMPOUND_SHAPE_PROXYTYPE); | ||||
| 	} | ||||
|  | ||||
| 	static SIMD_FORCE_INLINE bool	isSoftBody(int proxyType) | ||||
| 	{ | ||||
| 		return (proxyType == SOFTBODY_SHAPE_PROXYTYPE); | ||||
| 	} | ||||
|  | ||||
| 	static SIMD_FORCE_INLINE bool isInfinite(int proxyType) | ||||
| 	{ | ||||
| 		return (proxyType == STATIC_PLANE_PROXYTYPE); | ||||
| 	} | ||||
|  | ||||
| 	static SIMD_FORCE_INLINE bool isConvex2d(int proxyType) | ||||
| 	{ | ||||
| 		return (proxyType == BOX_2D_SHAPE_PROXYTYPE) ||	(proxyType == CONVEX_2D_SHAPE_PROXYTYPE); | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| } | ||||
| ; | ||||
|  | ||||
| class btCollisionAlgorithm; | ||||
|  | ||||
| struct btBroadphaseProxy; | ||||
|  | ||||
|  | ||||
|  | ||||
| ///The btBroadphasePair class contains a pair of aabb-overlapping objects. | ||||
| ///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes. | ||||
| ATTRIBUTE_ALIGNED16(struct) btBroadphasePair | ||||
| { | ||||
| 	btBroadphasePair () | ||||
| 		: | ||||
| 	m_pProxy0(0), | ||||
| 		m_pProxy1(0), | ||||
| 		m_algorithm(0), | ||||
| 		m_internalInfo1(0) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	btBroadphasePair(const btBroadphasePair& other) | ||||
| 		:		m_pProxy0(other.m_pProxy0), | ||||
| 				m_pProxy1(other.m_pProxy1), | ||||
| 				m_algorithm(other.m_algorithm), | ||||
| 				m_internalInfo1(other.m_internalInfo1) | ||||
| 	{ | ||||
| 	} | ||||
| 	btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1) | ||||
| 	{ | ||||
|  | ||||
| 		//keep them sorted, so the std::set operations work | ||||
| 		if (proxy0.m_uniqueId < proxy1.m_uniqueId) | ||||
|         {  | ||||
|             m_pProxy0 = &proxy0;  | ||||
|             m_pProxy1 = &proxy1;  | ||||
|         } | ||||
|         else  | ||||
|         {  | ||||
| 			m_pProxy0 = &proxy1;  | ||||
|             m_pProxy1 = &proxy0;  | ||||
|         } | ||||
|  | ||||
| 		m_algorithm = 0; | ||||
| 		m_internalInfo1 = 0; | ||||
|  | ||||
| 	} | ||||
| 	 | ||||
| 	btBroadphaseProxy* m_pProxy0; | ||||
| 	btBroadphaseProxy* m_pProxy1; | ||||
| 	 | ||||
| 	mutable btCollisionAlgorithm* m_algorithm; | ||||
| 	union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version. | ||||
|  | ||||
| }; | ||||
|  | ||||
| /* | ||||
| //comparison for set operation, see Solid DT_Encounter | ||||
| SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b)  | ||||
| {  | ||||
|     return a.m_pProxy0 < b.m_pProxy0 ||  | ||||
|         (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1);  | ||||
| } | ||||
| */ | ||||
|  | ||||
|  | ||||
|  | ||||
| class btBroadphasePairSortPredicate | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) | ||||
| 		{ | ||||
| 			const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1; | ||||
| 			const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1; | ||||
| 			const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1; | ||||
| 			const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1; | ||||
|  | ||||
| 			 return uidA0 > uidB0 ||  | ||||
| 				(a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) || | ||||
| 				(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);  | ||||
| 		} | ||||
| }; | ||||
|  | ||||
|  | ||||
| SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)  | ||||
| { | ||||
| 	 return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1); | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif //BROADPHASE_PROXY_H | ||||
|  | ||||
| @@ -0,0 +1,23 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btCollisionAlgorithm.h" | ||||
| #include "btDispatcher.h" | ||||
|  | ||||
| btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) | ||||
| { | ||||
| 	m_dispatcher = ci.m_dispatcher1; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,80 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_ALGORITHM_H | ||||
| #define COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "LinearMath/btScalar.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
| struct btBroadphaseProxy; | ||||
| class btDispatcher; | ||||
| class btManifoldResult; | ||||
| class btCollisionObject; | ||||
| struct btDispatcherInfo; | ||||
| class	btPersistentManifold; | ||||
|  | ||||
| typedef btAlignedObjectArray<btPersistentManifold*>	btManifoldArray; | ||||
|  | ||||
| struct btCollisionAlgorithmConstructionInfo | ||||
| { | ||||
| 	btCollisionAlgorithmConstructionInfo() | ||||
| 		:m_dispatcher1(0), | ||||
| 		m_manifold(0) | ||||
| 	{ | ||||
| 	} | ||||
| 	btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) | ||||
| 		:m_dispatcher1(dispatcher) | ||||
| 	{ | ||||
| 		(void)temp; | ||||
| 	} | ||||
|  | ||||
| 	btDispatcher*	m_dispatcher1; | ||||
| 	btPersistentManifold*	m_manifold; | ||||
|  | ||||
| 	int	getDispatcherId(); | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| ///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher. | ||||
| ///It is persistent over frames | ||||
| class btCollisionAlgorithm | ||||
| { | ||||
|  | ||||
| protected: | ||||
|  | ||||
| 	btDispatcher*	m_dispatcher; | ||||
|  | ||||
| protected: | ||||
| 	int	getDispatcherId(); | ||||
| 	 | ||||
| public: | ||||
|  | ||||
| 	btCollisionAlgorithm() {}; | ||||
|  | ||||
| 	btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); | ||||
|  | ||||
| 	virtual ~btCollisionAlgorithm() {}; | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) = 0; | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif //COLLISION_ALGORITHM_H | ||||
							
								
								
									
										1295
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1295
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1256
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1256
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,796 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| ///btDbvtBroadphase implementation by Nathanael Presson | ||||
|  | ||||
| #include "btDbvtBroadphase.h" | ||||
|  | ||||
| // | ||||
| // Profiling | ||||
| // | ||||
|  | ||||
| #if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK | ||||
| #include <stdio.h> | ||||
| #endif | ||||
|  | ||||
| #if DBVT_BP_PROFILE | ||||
| struct	ProfileScope | ||||
| { | ||||
| 	__forceinline ProfileScope(btClock& clock,unsigned long& value) : | ||||
| 	m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds()) | ||||
| 	{ | ||||
| 	} | ||||
| 	__forceinline ~ProfileScope() | ||||
| 	{ | ||||
| 		(*m_value)+=m_clock->getTimeMicroseconds()-m_base; | ||||
| 	} | ||||
| 	btClock*		m_clock; | ||||
| 	unsigned long*	m_value; | ||||
| 	unsigned long	m_base; | ||||
| }; | ||||
| #define	SPC(_value_)	ProfileScope	spc_scope(m_clock,_value_) | ||||
| #else | ||||
| #define	SPC(_value_) | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // Helpers | ||||
| // | ||||
|  | ||||
| // | ||||
| template <typename T> | ||||
| static inline void	listappend(T* item,T*& list) | ||||
| { | ||||
| 	item->links[0]=0; | ||||
| 	item->links[1]=list; | ||||
| 	if(list) list->links[0]=item; | ||||
| 	list=item; | ||||
| } | ||||
|  | ||||
| // | ||||
| template <typename T> | ||||
| static inline void	listremove(T* item,T*& list) | ||||
| { | ||||
| 	if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1]; | ||||
| 	if(item->links[1]) item->links[1]->links[0]=item->links[0]; | ||||
| } | ||||
|  | ||||
| // | ||||
| template <typename T> | ||||
| static inline int	listcount(T* root) | ||||
| { | ||||
| 	int	n=0; | ||||
| 	while(root) { ++n;root=root->links[1]; } | ||||
| 	return(n); | ||||
| } | ||||
|  | ||||
| // | ||||
| template <typename T> | ||||
| static inline void	clear(T& value) | ||||
| { | ||||
| 	static const struct ZeroDummy : T {} zerodummy; | ||||
| 	value=zerodummy; | ||||
| } | ||||
|  | ||||
| // | ||||
| // Colliders | ||||
| // | ||||
|  | ||||
| /* Tree collider	*/  | ||||
| struct	btDbvtTreeCollider : btDbvt::ICollide | ||||
| { | ||||
| 	btDbvtBroadphase*	pbp; | ||||
| 	btDbvtProxy*		proxy; | ||||
| 	btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} | ||||
| 	void	Process(const btDbvtNode* na,const btDbvtNode* nb) | ||||
| 	{ | ||||
| 		if(na!=nb) | ||||
| 		{ | ||||
| 			btDbvtProxy*	pa=(btDbvtProxy*)na->data; | ||||
| 			btDbvtProxy*	pb=(btDbvtProxy*)nb->data; | ||||
| #if DBVT_BP_SORTPAIRS | ||||
| 			if(pa->m_uniqueId>pb->m_uniqueId)  | ||||
| 				btSwap(pa,pb); | ||||
| #endif | ||||
| 			pbp->m_paircache->addOverlappingPair(pa,pb); | ||||
| 			++pbp->m_newpairs; | ||||
| 		} | ||||
| 	} | ||||
| 	void	Process(const btDbvtNode* n) | ||||
| 	{ | ||||
| 		Process(n,proxy->leaf); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| // | ||||
| // btDbvtBroadphase | ||||
| // | ||||
|  | ||||
| // | ||||
| btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) | ||||
| { | ||||
| 	m_deferedcollide	=	false; | ||||
| 	m_needcleanup		=	true; | ||||
| 	m_releasepaircache	=	(paircache!=0)?false:true; | ||||
| 	m_prediction		=	0; | ||||
| 	m_stageCurrent		=	0; | ||||
| 	m_fixedleft			=	0; | ||||
| 	m_fupdates			=	1; | ||||
| 	m_dupdates			=	0; | ||||
| 	m_cupdates			=	10; | ||||
| 	m_newpairs			=	1; | ||||
| 	m_updates_call		=	0; | ||||
| 	m_updates_done		=	0; | ||||
| 	m_updates_ratio		=	0; | ||||
| 	m_paircache			=	paircache? paircache	: new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); | ||||
| 	m_gid				=	0; | ||||
| 	m_pid				=	0; | ||||
| 	m_cid				=	0; | ||||
| 	for(int i=0;i<=STAGECOUNT;++i) | ||||
| 	{ | ||||
| 		m_stageRoots[i]=0; | ||||
| 	} | ||||
| #if DBVT_BP_PROFILE | ||||
| 	clear(m_profiling); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| // | ||||
| btDbvtBroadphase::~btDbvtBroadphase() | ||||
| { | ||||
| 	if(m_releasepaircache)  | ||||
| 	{ | ||||
| 		m_paircache->~btOverlappingPairCache(); | ||||
| 		btAlignedFree(m_paircache); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // | ||||
| btBroadphaseProxy*				btDbvtBroadphase::createProxy(	const btVector3& aabbMin, | ||||
| 															  const btVector3& aabbMax, | ||||
| 															  int /*shapeType*/, | ||||
| 															  void* userPtr, | ||||
| 															  short int collisionFilterGroup, | ||||
| 															  short int collisionFilterMask, | ||||
| 															  btDispatcher* /*dispatcher*/, | ||||
| 															  void* /*multiSapProxy*/) | ||||
| { | ||||
| 	btDbvtProxy*		proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy(	aabbMin,aabbMax,userPtr, | ||||
| 		collisionFilterGroup, | ||||
| 		collisionFilterMask); | ||||
|  | ||||
| 	btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); | ||||
|  | ||||
| 	//bproxy->aabb			=	btDbvtVolume::FromMM(aabbMin,aabbMax); | ||||
| 	proxy->stage		=	m_stageCurrent; | ||||
| 	proxy->m_uniqueId	=	++m_gid; | ||||
| 	proxy->leaf			=	m_sets[0].insert(aabb,proxy); | ||||
| 	listappend(proxy,m_stageRoots[m_stageCurrent]); | ||||
| 	if(!m_deferedcollide) | ||||
| 	{ | ||||
| 		btDbvtTreeCollider	collider(this); | ||||
| 		collider.proxy=proxy; | ||||
| 		m_sets[0].collideTV(m_sets[0].m_root,aabb,collider); | ||||
| 		m_sets[1].collideTV(m_sets[1].m_root,aabb,collider); | ||||
| 	} | ||||
| 	return(proxy); | ||||
| } | ||||
|  | ||||
| // | ||||
| void							btDbvtBroadphase::destroyProxy(	btBroadphaseProxy* absproxy, | ||||
| 															   btDispatcher* dispatcher) | ||||
| { | ||||
| 	btDbvtProxy*	proxy=(btDbvtProxy*)absproxy; | ||||
| 	if(proxy->stage==STAGECOUNT) | ||||
| 		m_sets[1].remove(proxy->leaf); | ||||
| 	else | ||||
| 		m_sets[0].remove(proxy->leaf); | ||||
| 	listremove(proxy,m_stageRoots[proxy->stage]); | ||||
| 	m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher); | ||||
| 	btAlignedFree(proxy); | ||||
| 	m_needcleanup=true; | ||||
| } | ||||
|  | ||||
| void	btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const | ||||
| { | ||||
| 	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy; | ||||
| 	aabbMin = proxy->m_aabbMin; | ||||
| 	aabbMax = proxy->m_aabbMax; | ||||
| } | ||||
|  | ||||
| struct	BroadphaseRayTester : btDbvt::ICollide | ||||
| { | ||||
| 	btBroadphaseRayCallback& m_rayCallback; | ||||
| 	BroadphaseRayTester(btBroadphaseRayCallback& orgCallback) | ||||
| 		:m_rayCallback(orgCallback) | ||||
| 	{ | ||||
| 	} | ||||
| 	void					Process(const btDbvtNode* leaf) | ||||
| 	{ | ||||
| 		btDbvtProxy*	proxy=(btDbvtProxy*)leaf->data; | ||||
| 		m_rayCallback.process(proxy); | ||||
| 	} | ||||
| };	 | ||||
|  | ||||
| void	btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) | ||||
| { | ||||
| 	BroadphaseRayTester callback(rayCallback); | ||||
|  | ||||
| 	m_sets[0].rayTestInternal(	m_sets[0].m_root, | ||||
| 		rayFrom, | ||||
| 		rayTo, | ||||
| 		rayCallback.m_rayDirectionInverse, | ||||
| 		rayCallback.m_signs, | ||||
| 		rayCallback.m_lambda_max, | ||||
| 		aabbMin, | ||||
| 		aabbMax, | ||||
| 		callback); | ||||
|  | ||||
| 	m_sets[1].rayTestInternal(	m_sets[1].m_root, | ||||
| 		rayFrom, | ||||
| 		rayTo, | ||||
| 		rayCallback.m_rayDirectionInverse, | ||||
| 		rayCallback.m_signs, | ||||
| 		rayCallback.m_lambda_max, | ||||
| 		aabbMin, | ||||
| 		aabbMax, | ||||
| 		callback); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| struct	BroadphaseAabbTester : btDbvt::ICollide | ||||
| { | ||||
| 	btBroadphaseAabbCallback& m_aabbCallback; | ||||
| 	BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback) | ||||
| 		:m_aabbCallback(orgCallback) | ||||
| 	{ | ||||
| 	} | ||||
| 	void					Process(const btDbvtNode* leaf) | ||||
| 	{ | ||||
| 		btDbvtProxy*	proxy=(btDbvtProxy*)leaf->data; | ||||
| 		m_aabbCallback.process(proxy); | ||||
| 	} | ||||
| };	 | ||||
|  | ||||
| void	btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback) | ||||
| { | ||||
| 	BroadphaseAabbTester callback(aabbCallback); | ||||
|  | ||||
| 	const ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(aabbMin,aabbMax); | ||||
| 		//process all children, that overlap with  the given AABB bounds | ||||
| 	m_sets[0].collideTV(m_sets[0].m_root,bounds,callback); | ||||
| 	m_sets[1].collideTV(m_sets[1].m_root,bounds,callback); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| // | ||||
| void							btDbvtBroadphase::setAabb(		btBroadphaseProxy* absproxy, | ||||
| 														  const btVector3& aabbMin, | ||||
| 														  const btVector3& aabbMax, | ||||
| 														  btDispatcher* /*dispatcher*/) | ||||
| { | ||||
| 	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy; | ||||
| 	ATTRIBUTE_ALIGNED16(btDbvtVolume)	aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); | ||||
| #if DBVT_BP_PREVENTFALSEUPDATE | ||||
| 	if(NotEqual(aabb,proxy->leaf->volume)) | ||||
| #endif | ||||
| 	{ | ||||
| 		bool	docollide=false; | ||||
| 		if(proxy->stage==STAGECOUNT) | ||||
| 		{/* fixed -> dynamic set	*/  | ||||
| 			m_sets[1].remove(proxy->leaf); | ||||
| 			proxy->leaf=m_sets[0].insert(aabb,proxy); | ||||
| 			docollide=true; | ||||
| 		} | ||||
| 		else | ||||
| 		{/* dynamic set				*/  | ||||
| 			++m_updates_call; | ||||
| 			if(Intersect(proxy->leaf->volume,aabb)) | ||||
| 			{/* Moving				*/  | ||||
|  | ||||
| 				const btVector3	delta=aabbMin-proxy->m_aabbMin; | ||||
| 				btVector3		velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction); | ||||
| 				if(delta[0]<0) velocity[0]=-velocity[0]; | ||||
| 				if(delta[1]<0) velocity[1]=-velocity[1]; | ||||
| 				if(delta[2]<0) velocity[2]=-velocity[2]; | ||||
| 				if	( | ||||
| #ifdef DBVT_BP_MARGIN				 | ||||
| 					m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN) | ||||
| #else | ||||
| 					m_sets[0].update(proxy->leaf,aabb,velocity) | ||||
| #endif | ||||
| 					) | ||||
| 				{ | ||||
| 					++m_updates_done; | ||||
| 					docollide=true; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{/* Teleporting			*/  | ||||
| 				m_sets[0].update(proxy->leaf,aabb); | ||||
| 				++m_updates_done; | ||||
| 				docollide=true; | ||||
| 			}	 | ||||
| 		} | ||||
| 		listremove(proxy,m_stageRoots[proxy->stage]); | ||||
| 		proxy->m_aabbMin = aabbMin; | ||||
| 		proxy->m_aabbMax = aabbMax; | ||||
| 		proxy->stage	=	m_stageCurrent; | ||||
| 		listappend(proxy,m_stageRoots[m_stageCurrent]); | ||||
| 		if(docollide) | ||||
| 		{ | ||||
| 			m_needcleanup=true; | ||||
| 			if(!m_deferedcollide) | ||||
| 			{ | ||||
| 				btDbvtTreeCollider	collider(this); | ||||
| 				m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider); | ||||
| 				m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider); | ||||
| 			} | ||||
| 		}	 | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| // | ||||
| void							btDbvtBroadphase::setAabbForceUpdate(		btBroadphaseProxy* absproxy, | ||||
| 														  const btVector3& aabbMin, | ||||
| 														  const btVector3& aabbMax, | ||||
| 														  btDispatcher* /*dispatcher*/) | ||||
| { | ||||
| 	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy; | ||||
| 	ATTRIBUTE_ALIGNED16(btDbvtVolume)	aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); | ||||
| 	bool	docollide=false; | ||||
| 	if(proxy->stage==STAGECOUNT) | ||||
| 	{/* fixed -> dynamic set	*/  | ||||
| 		m_sets[1].remove(proxy->leaf); | ||||
| 		proxy->leaf=m_sets[0].insert(aabb,proxy); | ||||
| 		docollide=true; | ||||
| 	} | ||||
| 	else | ||||
| 	{/* dynamic set				*/  | ||||
| 		++m_updates_call; | ||||
| 		/* Teleporting			*/  | ||||
| 		m_sets[0].update(proxy->leaf,aabb); | ||||
| 		++m_updates_done; | ||||
| 		docollide=true; | ||||
| 	} | ||||
| 	listremove(proxy,m_stageRoots[proxy->stage]); | ||||
| 	proxy->m_aabbMin = aabbMin; | ||||
| 	proxy->m_aabbMax = aabbMax; | ||||
| 	proxy->stage	=	m_stageCurrent; | ||||
| 	listappend(proxy,m_stageRoots[m_stageCurrent]); | ||||
| 	if(docollide) | ||||
| 	{ | ||||
| 		m_needcleanup=true; | ||||
| 		if(!m_deferedcollide) | ||||
| 		{ | ||||
| 			btDbvtTreeCollider	collider(this); | ||||
| 			m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider); | ||||
| 			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider); | ||||
| 		} | ||||
| 	}	 | ||||
| } | ||||
|  | ||||
| // | ||||
| void							btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) | ||||
| { | ||||
| 	collide(dispatcher); | ||||
| #if DBVT_BP_PROFILE | ||||
| 	if(0==(m_pid%DBVT_BP_PROFILING_RATE)) | ||||
| 	{	 | ||||
| 		printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs()); | ||||
| 		unsigned int	total=m_profiling.m_total; | ||||
| 		if(total<=0) total=1; | ||||
| 		printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE); | ||||
| 		printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE); | ||||
| 		printf("cleanup:   %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE); | ||||
| 		printf("total:     %uus\r\n",total/DBVT_BP_PROFILING_RATE); | ||||
| 		const unsigned long	sum=m_profiling.m_ddcollide+ | ||||
| 			m_profiling.m_fdcollide+ | ||||
| 			m_profiling.m_cleanup; | ||||
| 		printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE); | ||||
| 		printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE)); | ||||
| 		clear(m_profiling); | ||||
| 		m_clock.reset(); | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	performDeferredRemoval(dispatcher); | ||||
|  | ||||
| } | ||||
|  | ||||
| void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	if (m_paircache->hasDeferredRemoval()) | ||||
| 	{ | ||||
|  | ||||
| 		btBroadphasePairArray&	overlappingPairArray = m_paircache->getOverlappingPairArray(); | ||||
|  | ||||
| 		//perform a sort, to find duplicates and to sort 'invalid' pairs to the end | ||||
| 		overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); | ||||
|  | ||||
| 		int invalidPair = 0; | ||||
|  | ||||
| 		 | ||||
| 		int i; | ||||
|  | ||||
| 		btBroadphasePair previousPair; | ||||
| 		previousPair.m_pProxy0 = 0; | ||||
| 		previousPair.m_pProxy1 = 0; | ||||
| 		previousPair.m_algorithm = 0; | ||||
| 		 | ||||
| 		 | ||||
| 		for (i=0;i<overlappingPairArray.size();i++) | ||||
| 		{ | ||||
| 		 | ||||
| 			btBroadphasePair& pair = overlappingPairArray[i]; | ||||
|  | ||||
| 			bool isDuplicate = (pair == previousPair); | ||||
|  | ||||
| 			previousPair = pair; | ||||
|  | ||||
| 			bool needsRemoval = false; | ||||
|  | ||||
| 			if (!isDuplicate) | ||||
| 			{ | ||||
| 				//important to perform AABB check that is consistent with the broadphase | ||||
| 				btDbvtProxy*		pa=(btDbvtProxy*)pair.m_pProxy0; | ||||
| 				btDbvtProxy*		pb=(btDbvtProxy*)pair.m_pProxy1; | ||||
| 				bool hasOverlap = Intersect(pa->leaf->volume,pb->leaf->volume); | ||||
|  | ||||
| 				if (hasOverlap) | ||||
| 				{ | ||||
| 					needsRemoval = false; | ||||
| 				} else | ||||
| 				{ | ||||
| 					needsRemoval = true; | ||||
| 				} | ||||
| 			} else | ||||
| 			{ | ||||
| 				//remove duplicate | ||||
| 				needsRemoval = true; | ||||
| 				//should have no algorithm | ||||
| 				btAssert(!pair.m_algorithm); | ||||
| 			} | ||||
| 			 | ||||
| 			if (needsRemoval) | ||||
| 			{ | ||||
| 				m_paircache->cleanOverlappingPair(pair,dispatcher); | ||||
|  | ||||
| 				pair.m_pProxy0 = 0; | ||||
| 				pair.m_pProxy1 = 0; | ||||
| 				invalidPair++; | ||||
| 			}  | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 		//perform a sort, to sort 'invalid' pairs to the end | ||||
| 		overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); | ||||
| 		overlappingPairArray.resize(overlappingPairArray.size() - invalidPair); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // | ||||
| void							btDbvtBroadphase::collide(btDispatcher* dispatcher) | ||||
| { | ||||
| 	/*printf("---------------------------------------------------------\n"); | ||||
| 	printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves); | ||||
| 	printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves); | ||||
| 	printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs()); | ||||
| 	{ | ||||
| 		int i; | ||||
| 		for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++) | ||||
| 		{ | ||||
| 			printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(), | ||||
| 				getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid()); | ||||
| 		} | ||||
| 		printf("\n"); | ||||
| 	} | ||||
| */ | ||||
|  | ||||
|  | ||||
|  | ||||
| 	SPC(m_profiling.m_total); | ||||
| 	/* optimize				*/  | ||||
| 	m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); | ||||
| 	if(m_fixedleft) | ||||
| 	{ | ||||
| 		const int count=1+(m_sets[1].m_leaves*m_fupdates)/100; | ||||
| 		m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); | ||||
| 		m_fixedleft=btMax<int>(0,m_fixedleft-count); | ||||
| 	} | ||||
| 	/* dynamic -> fixed set	*/  | ||||
| 	m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; | ||||
| 	btDbvtProxy*	current=m_stageRoots[m_stageCurrent]; | ||||
| 	if(current) | ||||
| 	{ | ||||
| 		btDbvtTreeCollider	collider(this); | ||||
| 		do	{ | ||||
| 			btDbvtProxy*	next=current->links[1]; | ||||
| 			listremove(current,m_stageRoots[current->stage]); | ||||
| 			listappend(current,m_stageRoots[STAGECOUNT]); | ||||
| #if DBVT_BP_ACCURATESLEEPING | ||||
| 			m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher); | ||||
| 			collider.proxy=current; | ||||
| 			btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider); | ||||
| 			btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider); | ||||
| #endif | ||||
| 			m_sets[0].remove(current->leaf); | ||||
| 			ATTRIBUTE_ALIGNED16(btDbvtVolume)	curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax); | ||||
| 			current->leaf	=	m_sets[1].insert(curAabb,current); | ||||
| 			current->stage	=	STAGECOUNT;	 | ||||
| 			current			=	next; | ||||
| 		} while(current); | ||||
| 		m_fixedleft=m_sets[1].m_leaves; | ||||
| 		m_needcleanup=true; | ||||
| 	} | ||||
| 	/* collide dynamics		*/  | ||||
| 	{ | ||||
| 		btDbvtTreeCollider	collider(this); | ||||
| 		if(m_deferedcollide) | ||||
| 		{ | ||||
| 			SPC(m_profiling.m_fdcollide); | ||||
| 			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider); | ||||
| 		} | ||||
| 		if(m_deferedcollide) | ||||
| 		{ | ||||
| 			SPC(m_profiling.m_ddcollide); | ||||
| 			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider); | ||||
| 		} | ||||
| 	} | ||||
| 	/* clean up				*/  | ||||
| 	if(m_needcleanup) | ||||
| 	{ | ||||
| 		SPC(m_profiling.m_cleanup); | ||||
| 		btBroadphasePairArray&	pairs=m_paircache->getOverlappingPairArray(); | ||||
| 		if(pairs.size()>0) | ||||
| 		{ | ||||
|  | ||||
| 			int			ni=btMin(pairs.size(),btMax<int>(m_newpairs,(pairs.size()*m_cupdates)/100)); | ||||
| 			for(int i=0;i<ni;++i) | ||||
| 			{ | ||||
| 				btBroadphasePair&	p=pairs[(m_cid+i)%pairs.size()]; | ||||
| 				btDbvtProxy*		pa=(btDbvtProxy*)p.m_pProxy0; | ||||
| 				btDbvtProxy*		pb=(btDbvtProxy*)p.m_pProxy1; | ||||
| 				if(!Intersect(pa->leaf->volume,pb->leaf->volume)) | ||||
| 				{ | ||||
| #if DBVT_BP_SORTPAIRS | ||||
| 					if(pa->m_uniqueId>pb->m_uniqueId)  | ||||
| 						btSwap(pa,pb); | ||||
| #endif | ||||
| 					m_paircache->removeOverlappingPair(pa,pb,dispatcher); | ||||
| 					--ni;--i; | ||||
| 				} | ||||
| 			} | ||||
| 			if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0; | ||||
| 		} | ||||
| 	} | ||||
| 	++m_pid; | ||||
| 	m_newpairs=1; | ||||
| 	m_needcleanup=false; | ||||
| 	if(m_updates_call>0) | ||||
| 	{ m_updates_ratio=m_updates_done/(btScalar)m_updates_call; } | ||||
| 	else | ||||
| 	{ m_updates_ratio=0; } | ||||
| 	m_updates_done/=2; | ||||
| 	m_updates_call/=2; | ||||
| } | ||||
|  | ||||
| // | ||||
| void							btDbvtBroadphase::optimize() | ||||
| { | ||||
| 	m_sets[0].optimizeTopDown(); | ||||
| 	m_sets[1].optimizeTopDown(); | ||||
| } | ||||
|  | ||||
| // | ||||
| btOverlappingPairCache*			btDbvtBroadphase::getOverlappingPairCache() | ||||
| { | ||||
| 	return(m_paircache); | ||||
| } | ||||
|  | ||||
| // | ||||
| const btOverlappingPairCache*	btDbvtBroadphase::getOverlappingPairCache() const | ||||
| { | ||||
| 	return(m_paircache); | ||||
| } | ||||
|  | ||||
| // | ||||
| void							btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const | ||||
| { | ||||
|  | ||||
| 	ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds; | ||||
|  | ||||
| 	if(!m_sets[0].empty()) | ||||
| 		if(!m_sets[1].empty())	Merge(	m_sets[0].m_root->volume, | ||||
| 			m_sets[1].m_root->volume,bounds); | ||||
| 		else | ||||
| 			bounds=m_sets[0].m_root->volume; | ||||
| 	else if(!m_sets[1].empty())	bounds=m_sets[1].m_root->volume; | ||||
| 	else | ||||
| 		bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0); | ||||
| 	aabbMin=bounds.Mins(); | ||||
| 	aabbMax=bounds.Maxs(); | ||||
| } | ||||
|  | ||||
| void btDbvtBroadphase::resetPool(btDispatcher* dispatcher) | ||||
| { | ||||
| 	 | ||||
| 	int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves; | ||||
| 	if (!totalObjects) | ||||
| 	{ | ||||
| 		//reset internal dynamic tree data structures | ||||
| 		m_sets[0].clear(); | ||||
| 		m_sets[1].clear(); | ||||
| 		 | ||||
| 		m_deferedcollide	=	false; | ||||
| 		m_needcleanup		=	true; | ||||
| 		m_stageCurrent		=	0; | ||||
| 		m_fixedleft			=	0; | ||||
| 		m_fupdates			=	1; | ||||
| 		m_dupdates			=	0; | ||||
| 		m_cupdates			=	10; | ||||
| 		m_newpairs			=	1; | ||||
| 		m_updates_call		=	0; | ||||
| 		m_updates_done		=	0; | ||||
| 		m_updates_ratio		=	0; | ||||
| 		 | ||||
| 		m_gid				=	0; | ||||
| 		m_pid				=	0; | ||||
| 		m_cid				=	0; | ||||
| 		for(int i=0;i<=STAGECOUNT;++i) | ||||
| 		{ | ||||
| 			m_stageRoots[i]=0; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // | ||||
| void							btDbvtBroadphase::printStats() | ||||
| {} | ||||
|  | ||||
| // | ||||
| #if DBVT_BP_ENABLE_BENCHMARK | ||||
|  | ||||
| struct	btBroadphaseBenchmark | ||||
| { | ||||
| 	struct	Experiment | ||||
| 	{ | ||||
| 		const char*			name; | ||||
| 		int					object_count; | ||||
| 		int					update_count; | ||||
| 		int					spawn_count; | ||||
| 		int					iterations; | ||||
| 		btScalar			speed; | ||||
| 		btScalar			amplitude; | ||||
| 	}; | ||||
| 	struct	Object | ||||
| 	{ | ||||
| 		btVector3			center; | ||||
| 		btVector3			extents; | ||||
| 		btBroadphaseProxy*	proxy; | ||||
| 		btScalar			time; | ||||
| 		void				update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi) | ||||
| 		{ | ||||
| 			time		+=	speed; | ||||
| 			center[0]	=	btCos(time*(btScalar)2.17)*amplitude+ | ||||
| 				btSin(time)*amplitude/2; | ||||
| 			center[1]	=	btCos(time*(btScalar)1.38)*amplitude+ | ||||
| 				btSin(time)*amplitude; | ||||
| 			center[2]	=	btSin(time*(btScalar)0.777)*amplitude; | ||||
| 			pbi->setAabb(proxy,center-extents,center+extents,0); | ||||
| 		} | ||||
| 	}; | ||||
| 	static int		UnsignedRand(int range=RAND_MAX-1)	{ return(rand()%(range+1)); } | ||||
| 	static btScalar	UnitRand()							{ return(UnsignedRand(16384)/(btScalar)16384); } | ||||
| 	static void		OutputTime(const char* name,btClock& c,unsigned count=0) | ||||
| 	{ | ||||
| 		const unsigned long	us=c.getTimeMicroseconds(); | ||||
| 		const unsigned long	ms=(us+500)/1000; | ||||
| 		const btScalar		sec=us/(btScalar)(1000*1000); | ||||
| 		if(count>0) | ||||
| 			printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec); | ||||
| 		else | ||||
| 			printf("%s : %u us (%u ms)\r\n",name,us,ms); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| void							btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi) | ||||
| { | ||||
| 	static const btBroadphaseBenchmark::Experiment		experiments[]= | ||||
| 	{ | ||||
| 		{"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100}, | ||||
| 		/*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100}, | ||||
| 		{"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/ | ||||
| 	}; | ||||
| 	static const int										nexperiments=sizeof(experiments)/sizeof(experiments[0]); | ||||
| 	btAlignedObjectArray<btBroadphaseBenchmark::Object*>	objects; | ||||
| 	btClock													wallclock; | ||||
| 	/* Begin			*/  | ||||
| 	for(int iexp=0;iexp<nexperiments;++iexp) | ||||
| 	{ | ||||
| 		const btBroadphaseBenchmark::Experiment&	experiment=experiments[iexp]; | ||||
| 		const int									object_count=experiment.object_count; | ||||
| 		const int									update_count=(object_count*experiment.update_count)/100; | ||||
| 		const int									spawn_count=(object_count*experiment.spawn_count)/100; | ||||
| 		const btScalar								speed=experiment.speed;	 | ||||
| 		const btScalar								amplitude=experiment.amplitude; | ||||
| 		printf("Experiment #%u '%s':\r\n",iexp,experiment.name); | ||||
| 		printf("\tObjects: %u\r\n",object_count); | ||||
| 		printf("\tUpdate: %u\r\n",update_count); | ||||
| 		printf("\tSpawn: %u\r\n",spawn_count); | ||||
| 		printf("\tSpeed: %f\r\n",speed); | ||||
| 		printf("\tAmplitude: %f\r\n",amplitude); | ||||
| 		srand(180673); | ||||
| 		/* Create objects	*/  | ||||
| 		wallclock.reset(); | ||||
| 		objects.reserve(object_count); | ||||
| 		for(int i=0;i<object_count;++i) | ||||
| 		{ | ||||
| 			btBroadphaseBenchmark::Object*	po=new btBroadphaseBenchmark::Object(); | ||||
| 			po->center[0]=btBroadphaseBenchmark::UnitRand()*50; | ||||
| 			po->center[1]=btBroadphaseBenchmark::UnitRand()*50; | ||||
| 			po->center[2]=btBroadphaseBenchmark::UnitRand()*50; | ||||
| 			po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2; | ||||
| 			po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2; | ||||
| 			po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2; | ||||
| 			po->time=btBroadphaseBenchmark::UnitRand()*2000; | ||||
| 			po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0); | ||||
| 			objects.push_back(po); | ||||
| 		} | ||||
| 		btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock); | ||||
| 		/* First update		*/  | ||||
| 		wallclock.reset(); | ||||
| 		for(int i=0;i<objects.size();++i) | ||||
| 		{ | ||||
| 			objects[i]->update(speed,amplitude,pbi); | ||||
| 		} | ||||
| 		btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock); | ||||
| 		/* Updates			*/  | ||||
| 		wallclock.reset(); | ||||
| 		for(int i=0;i<experiment.iterations;++i) | ||||
| 		{ | ||||
| 			for(int j=0;j<update_count;++j) | ||||
| 			{				 | ||||
| 				objects[j]->update(speed,amplitude,pbi); | ||||
| 			} | ||||
| 			pbi->calculateOverlappingPairs(0); | ||||
| 		} | ||||
| 		btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations); | ||||
| 		/* Clean up			*/  | ||||
| 		wallclock.reset(); | ||||
| 		for(int i=0;i<objects.size();++i) | ||||
| 		{ | ||||
| 			pbi->destroyProxy(objects[i]->proxy,0); | ||||
| 			delete objects[i]; | ||||
| 		} | ||||
| 		objects.resize(0); | ||||
| 		btBroadphaseBenchmark::OutputTime("\tRelease",wallclock); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| #else | ||||
| void							btDbvtBroadphase::benchmark(btBroadphaseInterface*) | ||||
| {} | ||||
| #endif | ||||
|  | ||||
| #if DBVT_BP_PROFILE | ||||
| #undef	SPC | ||||
| #endif | ||||
|  | ||||
| @@ -0,0 +1,146 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| ///btDbvtBroadphase implementation by Nathanael Presson | ||||
| #ifndef BT_DBVT_BROADPHASE_H | ||||
| #define BT_DBVT_BROADPHASE_H | ||||
|  | ||||
| #include "BulletCollision/BroadphaseCollision/btDbvt.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" | ||||
|  | ||||
| // | ||||
| // Compile time config | ||||
| // | ||||
|  | ||||
| #define	DBVT_BP_PROFILE					0 | ||||
| //#define DBVT_BP_SORTPAIRS				1 | ||||
| #define DBVT_BP_PREVENTFALSEUPDATE		0 | ||||
| #define DBVT_BP_ACCURATESLEEPING		0 | ||||
| #define DBVT_BP_ENABLE_BENCHMARK		0 | ||||
| #define DBVT_BP_MARGIN					(btScalar)0.05 | ||||
|  | ||||
| #if DBVT_BP_PROFILE | ||||
| #define	DBVT_BP_PROFILING_RATE	256 | ||||
| #include "LinearMath/btQuickprof.h" | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // btDbvtProxy | ||||
| // | ||||
| struct btDbvtProxy : btBroadphaseProxy | ||||
| { | ||||
| 	/* Fields		*/  | ||||
| 	//btDbvtAabbMm	aabb; | ||||
| 	btDbvtNode*		leaf; | ||||
| 	btDbvtProxy*	links[2]; | ||||
| 	int				stage; | ||||
| 	/* ctor			*/  | ||||
| 	btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : | ||||
| 	btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask) | ||||
| 	{ | ||||
| 		links[0]=links[1]=0; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| typedef btAlignedObjectArray<btDbvtProxy*>	btDbvtProxyArray; | ||||
|  | ||||
| ///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt). | ||||
| ///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other. | ||||
| ///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3. | ||||
| struct	btDbvtBroadphase : btBroadphaseInterface | ||||
| { | ||||
| 	/* Config		*/  | ||||
| 	enum	{ | ||||
| 		DYNAMIC_SET			=	0,	/* Dynamic set index	*/  | ||||
| 		FIXED_SET			=	1,	/* Fixed set index		*/  | ||||
| 		STAGECOUNT			=	2	/* Number of stages		*/  | ||||
| 	}; | ||||
| 	/* Fields		*/  | ||||
| 	btDbvt					m_sets[2];					// Dbvt sets | ||||
| 	btDbvtProxy*			m_stageRoots[STAGECOUNT+1];	// Stages list | ||||
| 	btOverlappingPairCache*	m_paircache;				// Pair cache | ||||
| 	btScalar				m_prediction;				// Velocity prediction | ||||
| 	int						m_stageCurrent;				// Current stage | ||||
| 	int						m_fupdates;					// % of fixed updates per frame | ||||
| 	int						m_dupdates;					// % of dynamic updates per frame | ||||
| 	int						m_cupdates;					// % of cleanup updates per frame | ||||
| 	int						m_newpairs;					// Number of pairs created | ||||
| 	int						m_fixedleft;				// Fixed optimization left | ||||
| 	unsigned				m_updates_call;				// Number of updates call | ||||
| 	unsigned				m_updates_done;				// Number of updates done | ||||
| 	btScalar				m_updates_ratio;			// m_updates_done/m_updates_call | ||||
| 	int						m_pid;						// Parse id | ||||
| 	int						m_cid;						// Cleanup index | ||||
| 	int						m_gid;						// Gen id | ||||
| 	bool					m_releasepaircache;			// Release pair cache on delete | ||||
| 	bool					m_deferedcollide;			// Defere dynamic/static collision to collide call | ||||
| 	bool					m_needcleanup;				// Need to run cleanup? | ||||
| #if DBVT_BP_PROFILE | ||||
| 	btClock					m_clock; | ||||
| 	struct	{ | ||||
| 		unsigned long		m_total; | ||||
| 		unsigned long		m_ddcollide; | ||||
| 		unsigned long		m_fdcollide; | ||||
| 		unsigned long		m_cleanup; | ||||
| 		unsigned long		m_jobcount; | ||||
| 	}				m_profiling; | ||||
| #endif | ||||
| 	/* Methods		*/  | ||||
| 	btDbvtBroadphase(btOverlappingPairCache* paircache=0); | ||||
| 	~btDbvtBroadphase(); | ||||
| 	void							collide(btDispatcher* dispatcher); | ||||
| 	void							optimize(); | ||||
| 	 | ||||
| 	/* btBroadphaseInterface Implementation	*/ | ||||
| 	btBroadphaseProxy*				createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); | ||||
| 	virtual void					destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); | ||||
| 	virtual void					setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); | ||||
| 	virtual void					rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)); | ||||
| 	virtual void					aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); | ||||
|  | ||||
| 	virtual void					getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; | ||||
| 	virtual	void					calculateOverlappingPairs(btDispatcher* dispatcher); | ||||
| 	virtual	btOverlappingPairCache*	getOverlappingPairCache(); | ||||
| 	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const; | ||||
| 	virtual	void					getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; | ||||
| 	virtual	void					printStats(); | ||||
|  | ||||
|  | ||||
| 	///reset broadphase internal structures, to ensure determinism/reproducability | ||||
| 	virtual void resetPool(btDispatcher* dispatcher); | ||||
|  | ||||
| 	void	performDeferredRemoval(btDispatcher* dispatcher); | ||||
| 	 | ||||
| 	void	setVelocityPrediction(btScalar prediction) | ||||
| 	{ | ||||
| 		m_prediction = prediction; | ||||
| 	} | ||||
| 	btScalar getVelocityPrediction() const | ||||
| 	{ | ||||
| 		return m_prediction; | ||||
| 	} | ||||
|  | ||||
| 	///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.  | ||||
| 	///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase. | ||||
| 	///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see | ||||
| 	///http://code.google.com/p/bullet/issues/detail?id=223 | ||||
| 	void							setAabbForceUpdate(		btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/); | ||||
|  | ||||
| 	static void						benchmark(btBroadphaseInterface*); | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,22 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btDispatcher.h" | ||||
|  | ||||
| btDispatcher::~btDispatcher() | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
							
								
								
									
										108
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef _DISPATCHER_H | ||||
| #define _DISPATCHER_H | ||||
|  | ||||
| #include "LinearMath/btScalar.h" | ||||
|  | ||||
| class btCollisionAlgorithm; | ||||
| struct btBroadphaseProxy; | ||||
| class btRigidBody; | ||||
| class	btCollisionObject; | ||||
| class btOverlappingPairCache; | ||||
|  | ||||
|  | ||||
| class btPersistentManifold; | ||||
| class btStackAlloc; | ||||
|  | ||||
| struct btDispatcherInfo | ||||
| { | ||||
| 	enum DispatchFunc | ||||
| 	{ | ||||
| 		DISPATCH_DISCRETE = 1, | ||||
| 		DISPATCH_CONTINUOUS | ||||
| 	}; | ||||
| 	btDispatcherInfo() | ||||
| 		:m_timeStep(btScalar(0.)), | ||||
| 		m_stepCount(0), | ||||
| 		m_dispatchFunc(DISPATCH_DISCRETE), | ||||
| 		m_timeOfImpact(btScalar(1.)), | ||||
| 		m_useContinuous(false), | ||||
| 		m_debugDraw(0), | ||||
| 		m_enableSatConvex(false), | ||||
| 		m_enableSPU(true), | ||||
| 		m_useEpa(true), | ||||
| 		m_allowedCcdPenetration(btScalar(0.04)), | ||||
| 		m_useConvexConservativeDistanceUtil(false), | ||||
| 		m_convexConservativeDistanceThreshold(0.0f), | ||||
| 		m_convexMaxDistanceUseCPT(false), | ||||
| 		m_stackAllocator(0) | ||||
| 	{ | ||||
|  | ||||
| 	} | ||||
| 	btScalar	m_timeStep; | ||||
| 	int			m_stepCount; | ||||
| 	int			m_dispatchFunc; | ||||
| 	mutable btScalar	m_timeOfImpact; | ||||
| 	bool		m_useContinuous; | ||||
| 	class btIDebugDraw*	m_debugDraw; | ||||
| 	bool		m_enableSatConvex; | ||||
| 	bool		m_enableSPU; | ||||
| 	bool		m_useEpa; | ||||
| 	btScalar	m_allowedCcdPenetration; | ||||
| 	bool		m_useConvexConservativeDistanceUtil; | ||||
| 	btScalar	m_convexConservativeDistanceThreshold; | ||||
| 	bool		m_convexMaxDistanceUseCPT; | ||||
| 	btStackAlloc*	m_stackAllocator; | ||||
| }; | ||||
|  | ||||
| ///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs. | ||||
| ///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic). | ||||
| class btDispatcher | ||||
| { | ||||
|  | ||||
|  | ||||
| public: | ||||
| 	virtual ~btDispatcher() ; | ||||
|  | ||||
| 	virtual btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold=0) = 0; | ||||
|  | ||||
| 	virtual btPersistentManifold*	getNewManifold(void* body0,void* body1)=0; | ||||
|  | ||||
| 	virtual void releaseManifold(btPersistentManifold* manifold)=0; | ||||
|  | ||||
| 	virtual void clearManifold(btPersistentManifold* manifold)=0; | ||||
|  | ||||
| 	virtual bool	needsCollision(btCollisionObject* body0,btCollisionObject* body1) = 0; | ||||
|  | ||||
| 	virtual bool	needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; | ||||
|  | ||||
| 	virtual void	dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)  =0; | ||||
|  | ||||
| 	virtual int getNumManifolds() const = 0; | ||||
|  | ||||
| 	virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; | ||||
|  | ||||
| 	virtual	btPersistentManifold**	getInternalManifoldPointer() = 0; | ||||
|  | ||||
| 	virtual	void* allocateCollisionAlgorithm(int size)  = 0; | ||||
|  | ||||
| 	virtual	void freeCollisionAlgorithm(void* ptr) = 0; | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif //_DISPATCHER_H | ||||
| @@ -0,0 +1,489 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btMultiSapBroadphase.h" | ||||
|  | ||||
| #include "btSimpleBroadphase.h" | ||||
| #include "LinearMath/btAabbUtil2.h" | ||||
| #include "btQuantizedBvh.h" | ||||
|  | ||||
| ///	btSapBroadphaseArray	m_sapBroadphases; | ||||
|  | ||||
| ///	btOverlappingPairCache*	m_overlappingPairs; | ||||
| extern int gOverlappingPairs; | ||||
|  | ||||
| /* | ||||
| class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache | ||||
| { | ||||
| public: | ||||
|  | ||||
| 	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) | ||||
| 	{ | ||||
| 		return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| */ | ||||
|  | ||||
| btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache) | ||||
| :m_overlappingPairs(pairCache), | ||||
| m_optimizedAabbTree(0), | ||||
| m_ownsPairCache(false), | ||||
| m_invalidPair(0) | ||||
| { | ||||
| 	if (!m_overlappingPairs) | ||||
| 	{ | ||||
| 		m_ownsPairCache = true; | ||||
| 		void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16); | ||||
| 		m_overlappingPairs = new (mem)btSortedOverlappingPairCache(); | ||||
| 	} | ||||
|  | ||||
| 	struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback | ||||
| 	{ | ||||
| 		virtual ~btMultiSapOverlapFilterCallback() | ||||
| 		{} | ||||
| 		// return true when pairs need collision | ||||
| 		virtual bool	needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const | ||||
| 		{ | ||||
| 			btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy; | ||||
| 			btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy; | ||||
| 			 | ||||
| 			bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0; | ||||
| 			collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask); | ||||
| 	 | ||||
| 			return collides; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); | ||||
| 	m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); | ||||
|  | ||||
| 	m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); | ||||
| //	mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); | ||||
| //	m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); | ||||
| } | ||||
|  | ||||
| btMultiSapBroadphase::~btMultiSapBroadphase() | ||||
| { | ||||
| 	if (m_ownsPairCache) | ||||
| 	{ | ||||
| 		m_overlappingPairs->~btOverlappingPairCache(); | ||||
| 		btAlignedFree(m_overlappingPairs); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) | ||||
| { | ||||
| 	m_optimizedAabbTree = new btQuantizedBvh(); | ||||
| 	m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax); | ||||
| 	QuantizedNodeArray&	nodes = m_optimizedAabbTree->getLeafNodeArray(); | ||||
| 	for (int i=0;i<m_sapBroadphases.size();i++) | ||||
| 	{ | ||||
| 		btQuantizedBvhNode node; | ||||
| 		btVector3 aabbMin,aabbMax; | ||||
| 		m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax); | ||||
| 		m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); | ||||
| 		m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); | ||||
| 		int partId = 0; | ||||
| 		node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i; | ||||
| 		nodes.push_back(node); | ||||
| 	} | ||||
| 	m_optimizedAabbTree->buildInternal(); | ||||
| } | ||||
|  | ||||
| btBroadphaseProxy*	btMultiSapBroadphase::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/) | ||||
| { | ||||
| 	//void* ignoreMe -> we could think of recursive multi-sap, if someone is interested | ||||
|  | ||||
| 	void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); | ||||
| 	btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin,  aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); | ||||
| 	m_multiSapProxies.push_back(proxy); | ||||
|  | ||||
| 	///this should deal with inserting/removal into child broadphases | ||||
| 	setAabb(proxy,aabbMin,aabbMax,dispatcher); | ||||
| 	return proxy; | ||||
| } | ||||
|  | ||||
| void	btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) | ||||
| { | ||||
| 	///not yet | ||||
| 	btAssert(0); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*	childBroadphase) | ||||
| { | ||||
| 	void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16); | ||||
| 	btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy; | ||||
| 	bridgeProxyRef->m_childProxy = childProxy; | ||||
| 	bridgeProxyRef->m_childBroadphase = childBroadphase; | ||||
| 	parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef); | ||||
| } | ||||
|  | ||||
|  | ||||
| bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax); | ||||
| bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax) | ||||
| { | ||||
| return | ||||
| amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() && | ||||
| amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() && | ||||
| amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const | ||||
| { | ||||
| 	btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy); | ||||
| 	aabbMin = multiProxy->m_aabbMin; | ||||
| 	aabbMax = multiProxy->m_aabbMax; | ||||
| } | ||||
|  | ||||
| void	btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) | ||||
| { | ||||
| 	for (int i=0;i<m_multiSapProxies.size();i++) | ||||
| 	{ | ||||
| 		rayCallback.process(m_multiSapProxies[i]); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| //#include <stdio.h> | ||||
|  | ||||
| void	btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) | ||||
| { | ||||
| 	btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy); | ||||
| 	multiProxy->m_aabbMin = aabbMin; | ||||
| 	multiProxy->m_aabbMax = aabbMax; | ||||
| 	 | ||||
| 	 | ||||
| //	bool fullyContained = false; | ||||
| //	bool alreadyInSimple = false; | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	struct MyNodeOverlapCallback : public btNodeOverlapCallback | ||||
| 	{ | ||||
| 		btMultiSapBroadphase*	m_multiSap; | ||||
| 		btMultiSapProxy*		m_multiProxy; | ||||
| 		btDispatcher*			m_dispatcher; | ||||
|  | ||||
| 		MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher) | ||||
| 			:m_multiSap(multiSap), | ||||
| 			m_multiProxy(multiProxy), | ||||
| 			m_dispatcher(dispatcher) | ||||
| 		{ | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex) | ||||
| 		{ | ||||
| 			btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex]; | ||||
|  | ||||
| 			int containingBroadphaseIndex = -1; | ||||
| 			//already found? | ||||
| 			for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++) | ||||
| 			{ | ||||
|  | ||||
| 				if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) | ||||
| 				{ | ||||
| 					containingBroadphaseIndex = i; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			if (containingBroadphaseIndex<0) | ||||
| 			{ | ||||
| 				//add it | ||||
| 				btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy); | ||||
| 				m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase); | ||||
|  | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	MyNodeOverlapCallback	myNodeCallback(this,multiProxy,dispatcher); | ||||
|  | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	if (m_optimizedAabbTree) | ||||
| 		m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); | ||||
|  | ||||
| 	int i; | ||||
|  | ||||
| 	for ( i=0;i<multiProxy->m_bridgeProxies.size();i++) | ||||
| 	{ | ||||
| 		btVector3 worldAabbMin,worldAabbMax; | ||||
| 		multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); | ||||
| 		bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); | ||||
| 		if (!overlapsBroadphase) | ||||
| 		{ | ||||
| 			//remove it now | ||||
| 			btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i]; | ||||
|  | ||||
| 			btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; | ||||
| 			bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); | ||||
| 			 | ||||
| 			multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1); | ||||
| 			multiProxy->m_bridgeProxies.pop_back(); | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/* | ||||
|  | ||||
| 	if (1) | ||||
| 	{ | ||||
|  | ||||
| 		//find broadphase that contain this multiProxy | ||||
| 		int numChildBroadphases = getBroadphaseArray().size(); | ||||
| 		for (int i=0;i<numChildBroadphases;i++) | ||||
| 		{ | ||||
| 			btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i]; | ||||
| 			btVector3 worldAabbMin,worldAabbMax; | ||||
| 			childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); | ||||
| 			bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); | ||||
| 			 | ||||
| 		//	fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); | ||||
| 			int containingBroadphaseIndex = -1; | ||||
| 			 | ||||
| 			//if already contains this | ||||
| 			 | ||||
| 			for (int i=0;i<multiProxy->m_bridgeProxies.size();i++) | ||||
| 			{ | ||||
| 				if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) | ||||
| 				{ | ||||
| 					containingBroadphaseIndex = i; | ||||
| 				} | ||||
| 				alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase); | ||||
| 			} | ||||
|  | ||||
| 			if (overlapsBroadphase) | ||||
| 			{ | ||||
| 				if (containingBroadphaseIndex<0) | ||||
| 				{ | ||||
| 					btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); | ||||
| 					childProxy->m_multiSapParentProxy = multiProxy; | ||||
| 					addToChildBroadphase(multiProxy,childProxy,childBroadphase); | ||||
| 				} | ||||
| 			} else | ||||
| 			{ | ||||
| 				if (containingBroadphaseIndex>=0) | ||||
| 				{ | ||||
| 					//remove | ||||
| 					btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex]; | ||||
|  | ||||
| 					btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; | ||||
| 					bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); | ||||
| 					 | ||||
| 					multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1); | ||||
| 					multiProxy->m_bridgeProxies.pop_back(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force) | ||||
| 		///hopefully we don't end up with many entries here (can assert/provide feedback on stats) | ||||
| 		if (0)//!multiProxy->m_bridgeProxies.size()) | ||||
| 		{ | ||||
| 			///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision | ||||
| 			///this is needed to be able to calculate the aabb overlap | ||||
| 			btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); | ||||
| 			childProxy->m_multiSapParentProxy = multiProxy; | ||||
| 			addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!multiProxy->m_bridgeProxies.size()) | ||||
| 	{ | ||||
| 		///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision | ||||
| 		///this is needed to be able to calculate the aabb overlap | ||||
| 		btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); | ||||
| 		childProxy->m_multiSapParentProxy = multiProxy; | ||||
| 		addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); | ||||
| 	} | ||||
| */ | ||||
|  | ||||
|  | ||||
| 	//update | ||||
| 	for ( i=0;i<multiProxy->m_bridgeProxies.size();i++) | ||||
| 	{ | ||||
| 		btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i]; | ||||
| 		bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| bool stopUpdating=false; | ||||
|  | ||||
|  | ||||
|  | ||||
| class btMultiSapBroadphasePairSortPredicate | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) | ||||
| 		{ | ||||
| 				btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0; | ||||
| 				btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0; | ||||
| 				btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0; | ||||
| 				btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0; | ||||
|  | ||||
| 				 return aProxy0 > bProxy0 ||  | ||||
| 					(aProxy0 == bProxy0 && aProxy1 > bProxy1) || | ||||
| 					(aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);  | ||||
| 		} | ||||
| }; | ||||
|  | ||||
|  | ||||
|         ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb | ||||
| void    btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| //	m_simpleBroadphase->calculateOverlappingPairs(dispatcher); | ||||
|  | ||||
| 	if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval()) | ||||
| 	{ | ||||
| 	 | ||||
| 		btBroadphasePairArray&	overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray(); | ||||
|  | ||||
| 	//	quicksort(overlappingPairArray,0,overlappingPairArray.size()); | ||||
|  | ||||
| 		overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); | ||||
|  | ||||
| 		//perform a sort, to find duplicates and to sort 'invalid' pairs to the end | ||||
| 	//	overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); | ||||
|  | ||||
| 		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); | ||||
| 		m_invalidPair = 0; | ||||
|  | ||||
| 		 | ||||
| 		int i; | ||||
|  | ||||
| 		btBroadphasePair previousPair; | ||||
| 		previousPair.m_pProxy0 = 0; | ||||
| 		previousPair.m_pProxy1 = 0; | ||||
| 		previousPair.m_algorithm = 0; | ||||
| 		 | ||||
| 		 | ||||
| 		for (i=0;i<overlappingPairArray.size();i++) | ||||
| 		{ | ||||
| 		 | ||||
| 			btBroadphasePair& pair = overlappingPairArray[i]; | ||||
|  | ||||
| 			btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0; | ||||
| 			btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0; | ||||
| 			btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0; | ||||
| 			btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0; | ||||
|  | ||||
| 			bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1); | ||||
| 			 | ||||
| 			previousPair = pair; | ||||
|  | ||||
| 			bool needsRemoval = false; | ||||
|  | ||||
| 			if (!isDuplicate) | ||||
| 			{ | ||||
| 				bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); | ||||
|  | ||||
| 				if (hasOverlap) | ||||
| 				{ | ||||
| 					needsRemoval = false;//callback->processOverlap(pair); | ||||
| 				} else | ||||
| 				{ | ||||
| 					needsRemoval = true; | ||||
| 				} | ||||
| 			} else | ||||
| 			{ | ||||
| 				//remove duplicate | ||||
| 				needsRemoval = true; | ||||
| 				//should have no algorithm | ||||
| 				btAssert(!pair.m_algorithm); | ||||
| 			} | ||||
| 			 | ||||
| 			if (needsRemoval) | ||||
| 			{ | ||||
| 				getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher); | ||||
|  | ||||
| 		//		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); | ||||
| 		//		m_overlappingPairArray.pop_back(); | ||||
| 				pair.m_pProxy0 = 0; | ||||
| 				pair.m_pProxy1 = 0; | ||||
| 				m_invalidPair++; | ||||
| 				gOverlappingPairs--; | ||||
| 			}  | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 	///if you don't like to skip the invalid pairs in the array, execute following code: | ||||
| 	#define CLEAN_INVALID_PAIRS 1 | ||||
| 	#ifdef CLEAN_INVALID_PAIRS | ||||
|  | ||||
| 		//perform a sort, to sort 'invalid' pairs to the end | ||||
| 		//overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); | ||||
| 		overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); | ||||
|  | ||||
| 		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); | ||||
| 		m_invalidPair = 0; | ||||
| 	#endif//CLEAN_INVALID_PAIRS | ||||
| 		 | ||||
| 		//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| bool	btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) | ||||
| { | ||||
| 	btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; | ||||
| 		btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; | ||||
|  | ||||
| 		return	TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, | ||||
| 			multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); | ||||
| 		 | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btMultiSapBroadphase::printStats() | ||||
| { | ||||
| /*	printf("---------------------------------\n"); | ||||
| 	 | ||||
| 		printf("btMultiSapBroadphase.h\n"); | ||||
| 		printf("numHandles = %d\n",m_multiSapProxies.size()); | ||||
| 			//find broadphase that contain this multiProxy | ||||
| 		int numChildBroadphases = getBroadphaseArray().size(); | ||||
| 		for (int i=0;i<numChildBroadphases;i++) | ||||
| 		{ | ||||
|  | ||||
| 			btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i]; | ||||
| 			childBroadphase->printStats(); | ||||
|  | ||||
| 		} | ||||
| 		*/ | ||||
|  | ||||
| } | ||||
|  | ||||
| void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher) | ||||
| { | ||||
| 	// not yet | ||||
| } | ||||
| @@ -0,0 +1,151 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
| #ifndef BT_MULTI_SAP_BROADPHASE | ||||
| #define BT_MULTI_SAP_BROADPHASE | ||||
|  | ||||
| #include "btBroadphaseInterface.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
| #include "btOverlappingPairCache.h" | ||||
|  | ||||
|  | ||||
| class btBroadphaseInterface; | ||||
| class btSimpleBroadphase; | ||||
|  | ||||
|  | ||||
| typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray; | ||||
|  | ||||
| ///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead. | ||||
| ///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases. | ||||
| ///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time. | ||||
| ///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy. | ||||
| ///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 | ||||
| ///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 | ||||
| class btMultiSapBroadphase :public btBroadphaseInterface | ||||
| { | ||||
| 	btSapBroadphaseArray	m_sapBroadphases; | ||||
| 	 | ||||
| 	btSimpleBroadphase*		m_simpleBroadphase; | ||||
|  | ||||
| 	btOverlappingPairCache*	m_overlappingPairs; | ||||
|  | ||||
| 	class btQuantizedBvh*			m_optimizedAabbTree; | ||||
|  | ||||
|  | ||||
| 	bool					m_ownsPairCache; | ||||
| 	 | ||||
| 	btOverlapFilterCallback*	m_filterCallback; | ||||
|  | ||||
| 	int			m_invalidPair; | ||||
|  | ||||
| 	struct	btBridgeProxy | ||||
| 	{ | ||||
| 		btBroadphaseProxy*		m_childProxy; | ||||
| 		btBroadphaseInterface*	m_childBroadphase; | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	struct	btMultiSapProxy	: public btBroadphaseProxy | ||||
| 	{ | ||||
|  | ||||
| 		///array with all the entries that this proxy belongs to | ||||
| 		btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies; | ||||
| 		btVector3	m_aabbMin; | ||||
| 		btVector3	m_aabbMax; | ||||
|  | ||||
| 		int	m_shapeType; | ||||
|  | ||||
| /*		void*	m_userPtr; | ||||
| 		short int	m_collisionFilterGroup; | ||||
| 		short int	m_collisionFilterMask; | ||||
| */ | ||||
| 		btMultiSapProxy(const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) | ||||
| 			:btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask), | ||||
| 			m_aabbMin(aabbMin), | ||||
| 			m_aabbMax(aabbMax), | ||||
| 			m_shapeType(shapeType) | ||||
| 		{ | ||||
| 			m_multiSapParentProxy =this; | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
| 	}; | ||||
|  | ||||
| protected: | ||||
|  | ||||
|  | ||||
| 	btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); | ||||
|  | ||||
|  | ||||
| 	btSapBroadphaseArray&	getBroadphaseArray() | ||||
| 	{ | ||||
| 		return m_sapBroadphases; | ||||
| 	} | ||||
|  | ||||
| 	const btSapBroadphaseArray&	getBroadphaseArray() const | ||||
| 	{ | ||||
| 		return m_sapBroadphases; | ||||
| 	} | ||||
|  | ||||
| 	virtual ~btMultiSapBroadphase(); | ||||
|  | ||||
| 	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); | ||||
| 	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); | ||||
| 	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); | ||||
| 	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; | ||||
|  | ||||
| 	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); | ||||
|  | ||||
| 	void	addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*	childBroadphase); | ||||
|  | ||||
| 	///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb | ||||
| 	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher); | ||||
|  | ||||
| 	bool	testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); | ||||
|  | ||||
| 	virtual	btOverlappingPairCache*	getOverlappingPairCache() | ||||
| 	{ | ||||
| 		return m_overlappingPairs; | ||||
| 	} | ||||
| 	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const | ||||
| 	{ | ||||
| 		return m_overlappingPairs; | ||||
| 	} | ||||
|  | ||||
| 	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame | ||||
| 	///will add some transform later | ||||
| 	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const | ||||
| 	{ | ||||
| 		aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); | ||||
| 		aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); | ||||
| 	} | ||||
|  | ||||
| 	void	buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); | ||||
|  | ||||
| 	virtual void	printStats(); | ||||
|  | ||||
| 	void quicksort (btBroadphasePairArray& a, int lo, int hi); | ||||
|  | ||||
| 	///reset broadphase internal structures, to ensure determinism/reproducability | ||||
| 	virtual void resetPool(btDispatcher* dispatcher); | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BT_MULTI_SAP_BROADPHASE | ||||
| @@ -0,0 +1,633 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
|  | ||||
| #include "btOverlappingPairCache.h" | ||||
|  | ||||
| #include "btDispatcher.h" | ||||
| #include "btCollisionAlgorithm.h" | ||||
| #include "LinearMath/btAabbUtil2.h" | ||||
|  | ||||
| #include <stdio.h> | ||||
|  | ||||
| int	gOverlappingPairs = 0; | ||||
|  | ||||
| int gRemovePairs =0; | ||||
| int gAddedPairs =0; | ||||
| int gFindPairs =0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btHashedOverlappingPairCache::btHashedOverlappingPairCache(): | ||||
| 	m_overlapFilterCallback(0), | ||||
| 	m_blockedForChanges(false), | ||||
| 	m_ghostPairCallback(0) | ||||
| { | ||||
| 	int initialAllocatedSize= 2; | ||||
| 	m_overlappingPairArray.reserve(initialAllocatedSize); | ||||
| 	growTables(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btHashedOverlappingPairCache::~btHashedOverlappingPairCache() | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) | ||||
| { | ||||
| 	if (pair.m_algorithm) | ||||
| 	{ | ||||
| 		{ | ||||
| 			pair.m_algorithm->~btCollisionAlgorithm(); | ||||
| 			dispatcher->freeCollisionAlgorithm(pair.m_algorithm); | ||||
| 			pair.m_algorithm=0; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	class	CleanPairCallback : public btOverlapCallback | ||||
| 	{ | ||||
| 		btBroadphaseProxy* m_cleanProxy; | ||||
| 		btOverlappingPairCache*	m_pairCache; | ||||
| 		btDispatcher* m_dispatcher; | ||||
|  | ||||
| 	public: | ||||
| 		CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) | ||||
| 			:m_cleanProxy(cleanProxy), | ||||
| 			m_pairCache(pairCache), | ||||
| 			m_dispatcher(dispatcher) | ||||
| 		{ | ||||
| 		} | ||||
| 		virtual	bool	processOverlap(btBroadphasePair& pair) | ||||
| 		{ | ||||
| 			if ((pair.m_pProxy0 == m_cleanProxy) || | ||||
| 				(pair.m_pProxy1 == m_cleanProxy)) | ||||
| 			{ | ||||
| 				m_pairCache->cleanOverlappingPair(pair,m_dispatcher); | ||||
| 			} | ||||
| 			return false; | ||||
| 		} | ||||
| 		 | ||||
| 	}; | ||||
|  | ||||
| 	CleanPairCallback cleanPairs(proxy,this,dispatcher); | ||||
|  | ||||
| 	processAllOverlappingPairs(&cleanPairs,dispatcher); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	class	RemovePairCallback : public btOverlapCallback | ||||
| 	{ | ||||
| 		btBroadphaseProxy* m_obsoleteProxy; | ||||
|  | ||||
| 	public: | ||||
| 		RemovePairCallback(btBroadphaseProxy* obsoleteProxy) | ||||
| 			:m_obsoleteProxy(obsoleteProxy) | ||||
| 		{ | ||||
| 		} | ||||
| 		virtual	bool	processOverlap(btBroadphasePair& pair) | ||||
| 		{ | ||||
| 			return ((pair.m_pProxy0 == m_obsoleteProxy) || | ||||
| 				(pair.m_pProxy1 == m_obsoleteProxy)); | ||||
| 		} | ||||
| 		 | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| 	RemovePairCallback removeCallback(proxy); | ||||
|  | ||||
| 	processAllOverlappingPairs(&removeCallback,dispatcher); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) | ||||
| { | ||||
| 	gFindPairs++; | ||||
| 	if(proxy0->m_uniqueId>proxy1->m_uniqueId)  | ||||
| 		btSwap(proxy0,proxy1); | ||||
| 	int proxyId1 = proxy0->getUid(); | ||||
| 	int proxyId2 = proxy1->getUid(); | ||||
|  | ||||
| 	/*if (proxyId1 > proxyId2)  | ||||
| 		btSwap(proxyId1, proxyId2);*/ | ||||
|  | ||||
| 	int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); | ||||
|  | ||||
| 	if (hash >= m_hashTable.size()) | ||||
| 	{ | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	int index = m_hashTable[hash]; | ||||
| 	while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) | ||||
| 	{ | ||||
| 		index = m_next[index]; | ||||
| 	} | ||||
|  | ||||
| 	if (index == BT_NULL_PAIR) | ||||
| 	{ | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	btAssert(index < m_overlappingPairArray.size()); | ||||
|  | ||||
| 	return &m_overlappingPairArray[index]; | ||||
| } | ||||
|  | ||||
| //#include <stdio.h> | ||||
|  | ||||
| void	btHashedOverlappingPairCache::growTables() | ||||
| { | ||||
|  | ||||
| 	int newCapacity = m_overlappingPairArray.capacity(); | ||||
|  | ||||
| 	if (m_hashTable.size() < newCapacity) | ||||
| 	{ | ||||
| 		//grow hashtable and next table | ||||
| 		int curHashtableSize = m_hashTable.size(); | ||||
|  | ||||
| 		m_hashTable.resize(newCapacity); | ||||
| 		m_next.resize(newCapacity); | ||||
|  | ||||
|  | ||||
| 		int i; | ||||
|  | ||||
| 		for (i= 0; i < newCapacity; ++i) | ||||
| 		{ | ||||
| 			m_hashTable[i] = BT_NULL_PAIR; | ||||
| 		} | ||||
| 		for (i = 0; i < newCapacity; ++i) | ||||
| 		{ | ||||
| 			m_next[i] = BT_NULL_PAIR; | ||||
| 		} | ||||
|  | ||||
| 		for(i=0;i<curHashtableSize;i++) | ||||
| 		{ | ||||
| 	 | ||||
| 			const btBroadphasePair& pair = m_overlappingPairArray[i]; | ||||
| 			int proxyId1 = pair.m_pProxy0->getUid(); | ||||
| 			int proxyId2 = pair.m_pProxy1->getUid(); | ||||
| 			/*if (proxyId1 > proxyId2)  | ||||
| 				btSwap(proxyId1, proxyId2);*/ | ||||
| 			int	hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));	// New hash value with new mask | ||||
| 			m_next[i] = m_hashTable[hashValue]; | ||||
| 			m_hashTable[hashValue] = i; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 	} | ||||
| } | ||||
|  | ||||
| btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) | ||||
| { | ||||
| 	if(proxy0->m_uniqueId>proxy1->m_uniqueId)  | ||||
| 		btSwap(proxy0,proxy1); | ||||
| 	int proxyId1 = proxy0->getUid(); | ||||
| 	int proxyId2 = proxy1->getUid(); | ||||
|  | ||||
| 	/*if (proxyId1 > proxyId2)  | ||||
| 		btSwap(proxyId1, proxyId2);*/ | ||||
|  | ||||
| 	int	hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));	// New hash value with new mask | ||||
|  | ||||
|  | ||||
| 	btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); | ||||
| 	if (pair != NULL) | ||||
| 	{ | ||||
| 		return pair; | ||||
| 	} | ||||
| 	/*for(int i=0;i<m_overlappingPairArray.size();++i) | ||||
| 		{ | ||||
| 		if(	(m_overlappingPairArray[i].m_pProxy0==proxy0)&& | ||||
| 			(m_overlappingPairArray[i].m_pProxy1==proxy1)) | ||||
| 			{ | ||||
| 			printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2); | ||||
| 			internalFindPair(proxy0, proxy1, hash); | ||||
| 			} | ||||
| 		}*/ | ||||
| 	int count = m_overlappingPairArray.size(); | ||||
| 	int oldCapacity = m_overlappingPairArray.capacity(); | ||||
| 	void* mem = &m_overlappingPairArray.expandNonInitializing(); | ||||
|  | ||||
| 	//this is where we add an actual pair, so also call the 'ghost' | ||||
| 	if (m_ghostPairCallback) | ||||
| 		m_ghostPairCallback->addOverlappingPair(proxy0,proxy1); | ||||
|  | ||||
| 	int newCapacity = m_overlappingPairArray.capacity(); | ||||
|  | ||||
| 	if (oldCapacity < newCapacity) | ||||
| 	{ | ||||
| 		growTables(); | ||||
| 		//hash with new capacity | ||||
| 		hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); | ||||
| 	} | ||||
| 	 | ||||
| 	pair = new (mem) btBroadphasePair(*proxy0,*proxy1); | ||||
| //	pair->m_pProxy0 = proxy0; | ||||
| //	pair->m_pProxy1 = proxy1; | ||||
| 	pair->m_algorithm = 0; | ||||
| 	pair->m_internalTmpValue = 0; | ||||
| 	 | ||||
|  | ||||
| 	m_next[count] = m_hashTable[hash]; | ||||
| 	m_hashTable[hash] = count; | ||||
|  | ||||
| 	return pair; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) | ||||
| { | ||||
| 	gRemovePairs++; | ||||
| 	if(proxy0->m_uniqueId>proxy1->m_uniqueId)  | ||||
| 		btSwap(proxy0,proxy1); | ||||
| 	int proxyId1 = proxy0->getUid(); | ||||
| 	int proxyId2 = proxy1->getUid(); | ||||
|  | ||||
| 	/*if (proxyId1 > proxyId2)  | ||||
| 		btSwap(proxyId1, proxyId2);*/ | ||||
|  | ||||
| 	int	hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); | ||||
|  | ||||
| 	btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); | ||||
| 	if (pair == NULL) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	cleanOverlappingPair(*pair,dispatcher); | ||||
|  | ||||
| 	void* userData = pair->m_internalInfo1; | ||||
|  | ||||
| 	btAssert(pair->m_pProxy0->getUid() == proxyId1); | ||||
| 	btAssert(pair->m_pProxy1->getUid() == proxyId2); | ||||
|  | ||||
| 	int pairIndex = int(pair - &m_overlappingPairArray[0]); | ||||
| 	btAssert(pairIndex < m_overlappingPairArray.size()); | ||||
|  | ||||
| 	// Remove the pair from the hash table. | ||||
| 	int index = m_hashTable[hash]; | ||||
| 	btAssert(index != BT_NULL_PAIR); | ||||
|  | ||||
| 	int previous = BT_NULL_PAIR; | ||||
| 	while (index != pairIndex) | ||||
| 	{ | ||||
| 		previous = index; | ||||
| 		index = m_next[index]; | ||||
| 	} | ||||
|  | ||||
| 	if (previous != BT_NULL_PAIR) | ||||
| 	{ | ||||
| 		btAssert(m_next[previous] == pairIndex); | ||||
| 		m_next[previous] = m_next[pairIndex]; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		m_hashTable[hash] = m_next[pairIndex]; | ||||
| 	} | ||||
|  | ||||
| 	// We now move the last pair into spot of the | ||||
| 	// pair being removed. We need to fix the hash | ||||
| 	// table indices to support the move. | ||||
|  | ||||
| 	int lastPairIndex = m_overlappingPairArray.size() - 1; | ||||
|  | ||||
| 	if (m_ghostPairCallback) | ||||
| 		m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher); | ||||
|  | ||||
| 	// If the removed pair is the last pair, we are done. | ||||
| 	if (lastPairIndex == pairIndex) | ||||
| 	{ | ||||
| 		m_overlappingPairArray.pop_back(); | ||||
| 		return userData; | ||||
| 	} | ||||
|  | ||||
| 	// Remove the last pair from the hash table. | ||||
| 	const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex]; | ||||
| 		/* missing swap here too, Nat. */  | ||||
| 	int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1)); | ||||
|  | ||||
| 	index = m_hashTable[lastHash]; | ||||
| 	btAssert(index != BT_NULL_PAIR); | ||||
|  | ||||
| 	previous = BT_NULL_PAIR; | ||||
| 	while (index != lastPairIndex) | ||||
| 	{ | ||||
| 		previous = index; | ||||
| 		index = m_next[index]; | ||||
| 	} | ||||
|  | ||||
| 	if (previous != BT_NULL_PAIR) | ||||
| 	{ | ||||
| 		btAssert(m_next[previous] == lastPairIndex); | ||||
| 		m_next[previous] = m_next[lastPairIndex]; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		m_hashTable[lastHash] = m_next[lastPairIndex]; | ||||
| 	} | ||||
|  | ||||
| 	// Copy the last pair into the remove pair's spot. | ||||
| 	m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; | ||||
|  | ||||
| 	// Insert the last pair into the hash table | ||||
| 	m_next[pairIndex] = m_hashTable[lastHash]; | ||||
| 	m_hashTable[lastHash] = pairIndex; | ||||
|  | ||||
| 	m_overlappingPairArray.pop_back(); | ||||
|  | ||||
| 	return userData; | ||||
| } | ||||
| //#include <stdio.h> | ||||
|  | ||||
| void	btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	int i; | ||||
|  | ||||
| //	printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); | ||||
| 	for (i=0;i<m_overlappingPairArray.size();) | ||||
| 	{ | ||||
| 	 | ||||
| 		btBroadphasePair* pair = &m_overlappingPairArray[i]; | ||||
| 		if (callback->processOverlap(*pair)) | ||||
| 		{ | ||||
| 			removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher); | ||||
|  | ||||
| 			gOverlappingPairs--; | ||||
| 		} else | ||||
| 		{ | ||||
| 			i++; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void	btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) | ||||
| { | ||||
| 	///need to keep hashmap in sync with pair address, so rebuild all | ||||
| 	btBroadphasePairArray tmpPairs; | ||||
| 	int i; | ||||
| 	for (i=0;i<m_overlappingPairArray.size();i++) | ||||
| 	{ | ||||
| 		tmpPairs.push_back(m_overlappingPairArray[i]); | ||||
| 	} | ||||
|  | ||||
| 	for (i=0;i<tmpPairs.size();i++) | ||||
| 	{ | ||||
| 		removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher); | ||||
| 	} | ||||
| 	 | ||||
| 	for (i = 0; i < m_next.size(); i++) | ||||
| 	{ | ||||
| 		m_next[i] = BT_NULL_PAIR; | ||||
| 	} | ||||
|  | ||||
| 	tmpPairs.quickSort(btBroadphasePairSortPredicate()); | ||||
|  | ||||
| 	for (i=0;i<tmpPairs.size();i++) | ||||
| 	{ | ||||
| 		addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1); | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| } | ||||
|  | ||||
|  | ||||
| void*	btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher ) | ||||
| { | ||||
| 	if (!hasDeferredRemoval()) | ||||
| 	{ | ||||
| 		btBroadphasePair findPair(*proxy0,*proxy1); | ||||
|  | ||||
| 		int findIndex = m_overlappingPairArray.findLinearSearch(findPair); | ||||
| 		if (findIndex < m_overlappingPairArray.size()) | ||||
| 		{ | ||||
| 			gOverlappingPairs--; | ||||
| 			btBroadphasePair& pair = m_overlappingPairArray[findIndex]; | ||||
| 			void* userData = pair.m_internalInfo1; | ||||
| 			cleanOverlappingPair(pair,dispatcher); | ||||
| 			if (m_ghostPairCallback) | ||||
| 				m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher); | ||||
| 			 | ||||
| 			m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); | ||||
| 			m_overlappingPairArray.pop_back(); | ||||
| 			return userData; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btBroadphasePair*	btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) | ||||
| { | ||||
| 	//don't add overlap with own | ||||
| 	btAssert(proxy0 != proxy1); | ||||
|  | ||||
| 	if (!needsBroadphaseCollision(proxy0,proxy1)) | ||||
| 		return 0; | ||||
| 	 | ||||
| 	void* mem = &m_overlappingPairArray.expandNonInitializing(); | ||||
| 	btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); | ||||
| 	 | ||||
| 	gOverlappingPairs++; | ||||
| 	gAddedPairs++; | ||||
| 	 | ||||
| 	if (m_ghostPairCallback) | ||||
| 		m_ghostPairCallback->addOverlappingPair(proxy0, proxy1); | ||||
| 	return pair; | ||||
| 	 | ||||
| } | ||||
|  | ||||
| ///this findPair becomes really slow. Either sort the list to speedup the query, or | ||||
| ///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. | ||||
| ///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) | ||||
| ///Also we can use a 2D bitmap, which can be useful for a future GPU implementation | ||||
|  btBroadphasePair*	btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) | ||||
| { | ||||
| 	if (!needsBroadphaseCollision(proxy0,proxy1)) | ||||
| 		return 0; | ||||
|  | ||||
| 	btBroadphasePair tmpPair(*proxy0,*proxy1); | ||||
| 	int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); | ||||
|  | ||||
| 	if (findIndex < m_overlappingPairArray.size()) | ||||
| 	{ | ||||
| 		//btAssert(it != m_overlappingPairSet.end()); | ||||
| 		 btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; | ||||
| 		return pair; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| //#include <stdio.h> | ||||
|  | ||||
| void	btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	int i; | ||||
|  | ||||
| 	for (i=0;i<m_overlappingPairArray.size();) | ||||
| 	{ | ||||
| 	 | ||||
| 		btBroadphasePair* pair = &m_overlappingPairArray[i]; | ||||
| 		if (callback->processOverlap(*pair)) | ||||
| 		{ | ||||
| 			cleanOverlappingPair(*pair,dispatcher); | ||||
| 			pair->m_pProxy0 = 0; | ||||
| 			pair->m_pProxy1 = 0; | ||||
| 			m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); | ||||
| 			m_overlappingPairArray.pop_back(); | ||||
| 			gOverlappingPairs--; | ||||
| 		} else | ||||
| 		{ | ||||
| 			i++; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btSortedOverlappingPairCache::btSortedOverlappingPairCache(): | ||||
| 	m_blockedForChanges(false), | ||||
| 	m_hasDeferredRemoval(true), | ||||
| 	m_overlapFilterCallback(0), | ||||
| 	m_ghostPairCallback(0) | ||||
| { | ||||
| 	int initialAllocatedSize= 2; | ||||
| 	m_overlappingPairArray.reserve(initialAllocatedSize); | ||||
| } | ||||
|  | ||||
| btSortedOverlappingPairCache::~btSortedOverlappingPairCache() | ||||
| { | ||||
| } | ||||
|  | ||||
| void	btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) | ||||
| { | ||||
| 	if (pair.m_algorithm) | ||||
| 	{ | ||||
| 		{ | ||||
| 			pair.m_algorithm->~btCollisionAlgorithm(); | ||||
| 			dispatcher->freeCollisionAlgorithm(pair.m_algorithm); | ||||
| 			pair.m_algorithm=0; | ||||
| 			gRemovePairs--; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	class	CleanPairCallback : public btOverlapCallback | ||||
| 	{ | ||||
| 		btBroadphaseProxy* m_cleanProxy; | ||||
| 		btOverlappingPairCache*	m_pairCache; | ||||
| 		btDispatcher* m_dispatcher; | ||||
|  | ||||
| 	public: | ||||
| 		CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) | ||||
| 			:m_cleanProxy(cleanProxy), | ||||
| 			m_pairCache(pairCache), | ||||
| 			m_dispatcher(dispatcher) | ||||
| 		{ | ||||
| 		} | ||||
| 		virtual	bool	processOverlap(btBroadphasePair& pair) | ||||
| 		{ | ||||
| 			if ((pair.m_pProxy0 == m_cleanProxy) || | ||||
| 				(pair.m_pProxy1 == m_cleanProxy)) | ||||
| 			{ | ||||
| 				m_pairCache->cleanOverlappingPair(pair,m_dispatcher); | ||||
| 			} | ||||
| 			return false; | ||||
| 		} | ||||
| 		 | ||||
| 	}; | ||||
|  | ||||
| 	CleanPairCallback cleanPairs(proxy,this,dispatcher); | ||||
|  | ||||
| 	processAllOverlappingPairs(&cleanPairs,dispatcher); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	class	RemovePairCallback : public btOverlapCallback | ||||
| 	{ | ||||
| 		btBroadphaseProxy* m_obsoleteProxy; | ||||
|  | ||||
| 	public: | ||||
| 		RemovePairCallback(btBroadphaseProxy* obsoleteProxy) | ||||
| 			:m_obsoleteProxy(obsoleteProxy) | ||||
| 		{ | ||||
| 		} | ||||
| 		virtual	bool	processOverlap(btBroadphasePair& pair) | ||||
| 		{ | ||||
| 			return ((pair.m_pProxy0 == m_obsoleteProxy) || | ||||
| 				(pair.m_pProxy1 == m_obsoleteProxy)); | ||||
| 		} | ||||
| 		 | ||||
| 	}; | ||||
|  | ||||
| 	RemovePairCallback removeCallback(proxy); | ||||
|  | ||||
| 	processAllOverlappingPairs(&removeCallback,dispatcher); | ||||
| } | ||||
|  | ||||
| void	btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) | ||||
| { | ||||
| 	//should already be sorted | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,469 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef OVERLAPPING_PAIR_CACHE_H | ||||
| #define OVERLAPPING_PAIR_CACHE_H | ||||
|  | ||||
|  | ||||
| #include "btBroadphaseInterface.h" | ||||
| #include "btBroadphaseProxy.h" | ||||
| #include "btOverlappingPairCallback.h" | ||||
|  | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
| class btDispatcher; | ||||
|  | ||||
| typedef btAlignedObjectArray<btBroadphasePair>	btBroadphasePairArray; | ||||
|  | ||||
| struct	btOverlapCallback | ||||
| { | ||||
| 	virtual ~btOverlapCallback() | ||||
| 	{} | ||||
| 	//return true for deletion of the pair | ||||
| 	virtual bool	processOverlap(btBroadphasePair& pair) = 0; | ||||
|  | ||||
| }; | ||||
|  | ||||
| struct btOverlapFilterCallback | ||||
| { | ||||
| 	virtual ~btOverlapFilterCallback() | ||||
| 	{} | ||||
| 	// return true when pairs need collision | ||||
| 	virtual bool	needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| extern int gRemovePairs; | ||||
| extern int gAddedPairs; | ||||
| extern int gFindPairs; | ||||
|  | ||||
| const int BT_NULL_PAIR=0xffffffff; | ||||
|  | ||||
| ///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases. | ||||
| ///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations. | ||||
| class btOverlappingPairCache : public btOverlappingPairCallback | ||||
| { | ||||
| public: | ||||
| 	virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor | ||||
|  | ||||
| 	virtual btBroadphasePair*	getOverlappingPairArrayPtr() = 0; | ||||
| 	 | ||||
| 	virtual const btBroadphasePair*	getOverlappingPairArrayPtr() const = 0; | ||||
|  | ||||
| 	virtual btBroadphasePairArray&	getOverlappingPairArray() = 0; | ||||
|  | ||||
| 	virtual	void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0; | ||||
|  | ||||
| 	virtual int getNumOverlappingPairs() const = 0; | ||||
|  | ||||
| 	virtual void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0; | ||||
|  | ||||
| 	virtual	void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0; | ||||
|  | ||||
| 	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0; | ||||
|  | ||||
| 	virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0; | ||||
|  | ||||
| 	virtual bool	hasDeferredRemoval() = 0; | ||||
|  | ||||
| 	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0; | ||||
|  | ||||
| 	virtual void	sortOverlappingPairs(btDispatcher* dispatcher) = 0; | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| /// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com | ||||
| class btHashedOverlappingPairCache : public btOverlappingPairCache | ||||
| { | ||||
| 	btBroadphasePairArray	m_overlappingPairArray; | ||||
| 	btOverlapFilterCallback* m_overlapFilterCallback; | ||||
| 	bool		m_blockedForChanges; | ||||
|  | ||||
|  | ||||
| public: | ||||
| 	btHashedOverlappingPairCache(); | ||||
| 	virtual ~btHashedOverlappingPairCache(); | ||||
|  | ||||
| 	 | ||||
| 	void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); | ||||
|  | ||||
| 	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); | ||||
| 	 | ||||
| 	SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const | ||||
| 	{ | ||||
| 		if (m_overlapFilterCallback) | ||||
| 			return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); | ||||
|  | ||||
| 		bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; | ||||
| 		collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); | ||||
| 		 | ||||
| 		return collides; | ||||
| 	} | ||||
|  | ||||
| 	// Add a pair and return the new pair. If the pair already exists, | ||||
| 	// no new pair is created and the old one is returned. | ||||
| 	virtual btBroadphasePair* 	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) | ||||
| 	{ | ||||
| 		gAddedPairs++; | ||||
|  | ||||
| 		if (!needsBroadphaseCollision(proxy0,proxy1)) | ||||
| 			return 0; | ||||
|  | ||||
| 		return internalAddPair(proxy0,proxy1); | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); | ||||
|  | ||||
| 	 | ||||
| 	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); | ||||
|  | ||||
| 	virtual btBroadphasePair*	getOverlappingPairArrayPtr() | ||||
| 	{ | ||||
| 		return &m_overlappingPairArray[0]; | ||||
| 	} | ||||
|  | ||||
| 	const btBroadphasePair*	getOverlappingPairArrayPtr() const | ||||
| 	{ | ||||
| 		return &m_overlappingPairArray[0]; | ||||
| 	} | ||||
|  | ||||
| 	btBroadphasePairArray&	getOverlappingPairArray() | ||||
| 	{ | ||||
| 		return m_overlappingPairArray; | ||||
| 	} | ||||
|  | ||||
| 	const btBroadphasePairArray&	getOverlappingPairArray() const | ||||
| 	{ | ||||
| 		return m_overlappingPairArray; | ||||
| 	} | ||||
|  | ||||
| 	void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); | ||||
|  | ||||
|  | ||||
|  | ||||
| 	btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); | ||||
|  | ||||
| 	int GetCount() const { return m_overlappingPairArray.size(); } | ||||
| //	btBroadphasePair* GetPairs() { return m_pairs; } | ||||
|  | ||||
| 	btOverlapFilterCallback* getOverlapFilterCallback() | ||||
| 	{ | ||||
| 		return m_overlapFilterCallback; | ||||
| 	} | ||||
|  | ||||
| 	void setOverlapFilterCallback(btOverlapFilterCallback* callback) | ||||
| 	{ | ||||
| 		m_overlapFilterCallback = callback; | ||||
| 	} | ||||
|  | ||||
| 	int	getNumOverlappingPairs() const | ||||
| 	{ | ||||
| 		return m_overlappingPairArray.size(); | ||||
| 	} | ||||
| private: | ||||
| 	 | ||||
| 	btBroadphasePair* 	internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); | ||||
|  | ||||
| 	void	growTables(); | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) | ||||
| 	{	 | ||||
| 		return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	// Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm | ||||
| 	// This assumes proxyId1 and proxyId2 are 16-bit. | ||||
| 	SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) | ||||
| 	{ | ||||
| 		int key = (proxyId2 << 16) | proxyId1; | ||||
| 		key = ~key + (key << 15); | ||||
| 		key = key ^ (key >> 12); | ||||
| 		key = key + (key << 2); | ||||
| 		key = key ^ (key >> 4); | ||||
| 		key = key * 2057; | ||||
| 		key = key ^ (key >> 16); | ||||
| 		return key; | ||||
| 	} | ||||
| 	*/ | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	SIMD_FORCE_INLINE	unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) | ||||
| 	{ | ||||
| 		int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16)); | ||||
| 		// Thomas Wang's hash | ||||
|  | ||||
| 		key += ~(key << 15); | ||||
| 		key ^=  (key >> 10); | ||||
| 		key +=  (key << 3); | ||||
| 		key ^=  (key >> 6); | ||||
| 		key += ~(key << 11); | ||||
| 		key ^=  (key >> 16); | ||||
| 		return static_cast<unsigned int>(key); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) | ||||
| 	{ | ||||
| 		int proxyId1 = proxy0->getUid(); | ||||
| 		int proxyId2 = proxy1->getUid(); | ||||
| 		#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat. | ||||
| 		if (proxyId1 > proxyId2)  | ||||
| 			btSwap(proxyId1, proxyId2); | ||||
| 		#endif | ||||
|  | ||||
| 		int index = m_hashTable[hash]; | ||||
| 		 | ||||
| 		while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) | ||||
| 		{ | ||||
| 			index = m_next[index]; | ||||
| 		} | ||||
|  | ||||
| 		if ( index == BT_NULL_PAIR ) | ||||
| 		{ | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		btAssert(index < m_overlappingPairArray.size()); | ||||
|  | ||||
| 		return &m_overlappingPairArray[index]; | ||||
| 	} | ||||
|  | ||||
| 	virtual bool	hasDeferredRemoval() | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) | ||||
| 	{ | ||||
| 		m_ghostPairCallback = ghostPairCallback; | ||||
| 	} | ||||
|  | ||||
| 	virtual void	sortOverlappingPairs(btDispatcher* dispatcher); | ||||
| 	 | ||||
|  | ||||
| protected: | ||||
| 	 | ||||
| 	btAlignedObjectArray<int>	m_hashTable; | ||||
| 	btAlignedObjectArray<int>	m_next; | ||||
| 	btOverlappingPairCallback*	m_ghostPairCallback; | ||||
| 	 | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ///btSortedOverlappingPairCache maintains the objects with overlapping AABB | ||||
| ///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase | ||||
| class	btSortedOverlappingPairCache : public btOverlappingPairCache | ||||
| { | ||||
| 	protected: | ||||
| 		//avoid brute-force finding all the time | ||||
| 		btBroadphasePairArray	m_overlappingPairArray; | ||||
|  | ||||
| 		//during the dispatch, check that user doesn't destroy/create proxy | ||||
| 		bool		m_blockedForChanges; | ||||
|  | ||||
| 		///by default, do the removal during the pair traversal | ||||
| 		bool		m_hasDeferredRemoval; | ||||
| 		 | ||||
| 		//if set, use the callback instead of the built in filter in needBroadphaseCollision | ||||
| 		btOverlapFilterCallback* m_overlapFilterCallback; | ||||
|  | ||||
| 		btOverlappingPairCallback*	m_ghostPairCallback; | ||||
|  | ||||
| 	public: | ||||
| 			 | ||||
| 		btSortedOverlappingPairCache();	 | ||||
| 		virtual ~btSortedOverlappingPairCache(); | ||||
|  | ||||
| 		virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); | ||||
|  | ||||
| 		void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); | ||||
|  | ||||
| 		void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); | ||||
| 		 | ||||
| 		btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); | ||||
|  | ||||
| 		btBroadphasePair*	findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); | ||||
| 			 | ||||
| 		 | ||||
| 		void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); | ||||
|  | ||||
| 		void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); | ||||
|  | ||||
|  | ||||
| 		inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const | ||||
| 		{ | ||||
| 			if (m_overlapFilterCallback) | ||||
| 				return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); | ||||
|  | ||||
| 			bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; | ||||
| 			collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); | ||||
| 			 | ||||
| 			return collides; | ||||
| 		} | ||||
| 		 | ||||
| 		btBroadphasePairArray&	getOverlappingPairArray() | ||||
| 		{ | ||||
| 			return m_overlappingPairArray; | ||||
| 		} | ||||
|  | ||||
| 		const btBroadphasePairArray&	getOverlappingPairArray() const | ||||
| 		{ | ||||
| 			return m_overlappingPairArray; | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
|  | ||||
|  | ||||
| 		btBroadphasePair*	getOverlappingPairArrayPtr() | ||||
| 		{ | ||||
| 			return &m_overlappingPairArray[0]; | ||||
| 		} | ||||
|  | ||||
| 		const btBroadphasePair*	getOverlappingPairArrayPtr() const | ||||
| 		{ | ||||
| 			return &m_overlappingPairArray[0]; | ||||
| 		} | ||||
|  | ||||
| 		int	getNumOverlappingPairs() const | ||||
| 		{ | ||||
| 			return m_overlappingPairArray.size(); | ||||
| 		} | ||||
| 		 | ||||
| 		btOverlapFilterCallback* getOverlapFilterCallback() | ||||
| 		{ | ||||
| 			return m_overlapFilterCallback; | ||||
| 		} | ||||
|  | ||||
| 		void setOverlapFilterCallback(btOverlapFilterCallback* callback) | ||||
| 		{ | ||||
| 			m_overlapFilterCallback = callback; | ||||
| 		} | ||||
|  | ||||
| 		virtual bool	hasDeferredRemoval() | ||||
| 		{ | ||||
| 			return m_hasDeferredRemoval; | ||||
| 		} | ||||
|  | ||||
| 		virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) | ||||
| 		{ | ||||
| 			m_ghostPairCallback = ghostPairCallback; | ||||
| 		} | ||||
|  | ||||
| 		virtual void	sortOverlappingPairs(btDispatcher* dispatcher); | ||||
| 		 | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| ///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing. | ||||
| class btNullPairCache : public btOverlappingPairCache | ||||
| { | ||||
|  | ||||
| 	btBroadphasePairArray	m_overlappingPairArray; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	virtual btBroadphasePair*	getOverlappingPairArrayPtr() | ||||
| 	{ | ||||
| 		return &m_overlappingPairArray[0]; | ||||
| 	} | ||||
| 	const btBroadphasePair*	getOverlappingPairArrayPtr() const | ||||
| 	{ | ||||
| 		return &m_overlappingPairArray[0]; | ||||
| 	} | ||||
| 	btBroadphasePairArray&	getOverlappingPairArray() | ||||
| 	{ | ||||
| 		return m_overlappingPairArray; | ||||
| 	} | ||||
| 	 | ||||
| 	virtual	void	cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/) | ||||
| 	{ | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	virtual int getNumOverlappingPairs() const | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	virtual void	cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) | ||||
| 	{ | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	virtual	void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	virtual bool	hasDeferredRemoval() | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */) | ||||
| 	{ | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	virtual void*	removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) | ||||
| 	{ | ||||
| 	} | ||||
| 	 | ||||
| 	virtual void	sortOverlappingPairs(btDispatcher* dispatcher) | ||||
| 	{ | ||||
|         (void) dispatcher; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif //OVERLAPPING_PAIR_CACHE_H | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,40 @@ | ||||
|  | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef OVERLAPPING_PAIR_CALLBACK_H | ||||
| #define OVERLAPPING_PAIR_CALLBACK_H | ||||
|  | ||||
| class btDispatcher; | ||||
| struct  btBroadphasePair; | ||||
|  | ||||
| ///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. | ||||
| class btOverlappingPairCallback | ||||
| { | ||||
| public: | ||||
| 	virtual ~btOverlappingPairCallback() | ||||
| 	{ | ||||
|  | ||||
| 	} | ||||
| 	 | ||||
| 	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; | ||||
|  | ||||
| 	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0; | ||||
|  | ||||
| 	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //OVERLAPPING_PAIR_CALLBACK_H | ||||
							
								
								
									
										1375
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1375
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										579
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										579
									
								
								libs/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,579 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef QUANTIZED_BVH_H | ||||
| #define QUANTIZED_BVH_H | ||||
|  | ||||
| class btSerializer; | ||||
|  | ||||
| //#define DEBUG_CHECK_DEQUANTIZATION 1 | ||||
| #ifdef DEBUG_CHECK_DEQUANTIZATION | ||||
| #ifdef __SPU__ | ||||
| #define printf spu_printf | ||||
| #endif //__SPU__ | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #endif //DEBUG_CHECK_DEQUANTIZATION | ||||
|  | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btAlignedAllocator.h" | ||||
|  | ||||
| #ifdef BT_USE_DOUBLE_PRECISION | ||||
| #define btQuantizedBvhData btQuantizedBvhDoubleData | ||||
| #define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData | ||||
| #define btQuantizedBvhDataName "btQuantizedBvhDoubleData" | ||||
| #else | ||||
| #define btQuantizedBvhData btQuantizedBvhFloatData | ||||
| #define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData | ||||
| #define btQuantizedBvhDataName "btQuantizedBvhFloatData" | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
| //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp | ||||
|  | ||||
|  | ||||
| //Note: currently we have 16 bytes per quantized node | ||||
| #define MAX_SUBTREE_SIZE_IN_BYTES  2048 | ||||
|  | ||||
| // 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one | ||||
| // actually) triangles each (since the sign bit is reserved | ||||
| #define MAX_NUM_PARTS_IN_BITS 10 | ||||
|  | ||||
| ///btQuantizedBvhNode is a compressed aabb node, 16 bytes. | ||||
| ///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). | ||||
| ATTRIBUTE_ALIGNED16	(struct) btQuantizedBvhNode | ||||
| { | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	//12 bytes | ||||
| 	unsigned short int	m_quantizedAabbMin[3]; | ||||
| 	unsigned short int	m_quantizedAabbMax[3]; | ||||
| 	//4 bytes | ||||
| 	int	m_escapeIndexOrTriangleIndex; | ||||
|  | ||||
| 	bool isLeafNode() const | ||||
| 	{ | ||||
| 		//skipindex is negative (internal node), triangleindex >=0 (leafnode) | ||||
| 		return (m_escapeIndexOrTriangleIndex >= 0); | ||||
| 	} | ||||
| 	int getEscapeIndex() const | ||||
| 	{ | ||||
| 		btAssert(!isLeafNode()); | ||||
| 		return -m_escapeIndexOrTriangleIndex; | ||||
| 	} | ||||
| 	int	getTriangleIndex() const | ||||
| 	{ | ||||
| 		btAssert(isLeafNode()); | ||||
| 		// Get only the lower bits where the triangle index is stored | ||||
| 		return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS))); | ||||
| 	} | ||||
| 	int	getPartId() const | ||||
| 	{ | ||||
| 		btAssert(isLeafNode()); | ||||
| 		// Get only the highest bits where the part index is stored | ||||
| 		return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); | ||||
| 	} | ||||
| } | ||||
| ; | ||||
|  | ||||
| /// btOptimizedBvhNode contains both internal and leaf node information. | ||||
| /// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. | ||||
| ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode | ||||
| { | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	//32 bytes | ||||
| 	btVector3	m_aabbMinOrg; | ||||
| 	btVector3	m_aabbMaxOrg; | ||||
|  | ||||
| 	//4 | ||||
| 	int	m_escapeIndex; | ||||
|  | ||||
| 	//8 | ||||
| 	//for child nodes | ||||
| 	int	m_subPart; | ||||
| 	int	m_triangleIndex; | ||||
| 	int	m_padding[5];//bad, due to alignment | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| ///btBvhSubtreeInfo provides info to gather a subtree of limited size | ||||
| ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo | ||||
| { | ||||
| public: | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	//12 bytes | ||||
| 	unsigned short int	m_quantizedAabbMin[3]; | ||||
| 	unsigned short int	m_quantizedAabbMax[3]; | ||||
| 	//4 bytes, points to the root of the subtree | ||||
| 	int			m_rootNodeIndex; | ||||
| 	//4 bytes | ||||
| 	int			m_subtreeSize; | ||||
| 	int			m_padding[3]; | ||||
|  | ||||
| 	btBvhSubtreeInfo() | ||||
| 	{ | ||||
| 		//memset(&m_padding[0], 0, sizeof(m_padding)); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	void	setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) | ||||
| 	{ | ||||
| 		m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; | ||||
| 		m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; | ||||
| 		m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; | ||||
| 		m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; | ||||
| 		m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; | ||||
| 		m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; | ||||
| 	} | ||||
| } | ||||
| ; | ||||
|  | ||||
|  | ||||
| class btNodeOverlapCallback | ||||
| { | ||||
| public: | ||||
| 	virtual ~btNodeOverlapCallback() {}; | ||||
|  | ||||
| 	virtual void processNode(int subPart, int triangleIndex) = 0; | ||||
| }; | ||||
|  | ||||
| #include "LinearMath/btAlignedAllocator.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| ///for code readability: | ||||
| typedef btAlignedObjectArray<btOptimizedBvhNode>	NodeArray; | ||||
| typedef btAlignedObjectArray<btQuantizedBvhNode>	QuantizedNodeArray; | ||||
| typedef btAlignedObjectArray<btBvhSubtreeInfo>		BvhSubtreeInfoArray; | ||||
|  | ||||
|  | ||||
| ///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU. | ||||
| ///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase. | ||||
| ///It is recommended to use quantization for better performance and lower memory requirements. | ||||
| ATTRIBUTE_ALIGNED16(class) btQuantizedBvh | ||||
| { | ||||
| public: | ||||
| 	enum btTraversalMode | ||||
| 	{ | ||||
| 		TRAVERSAL_STACKLESS = 0, | ||||
| 		TRAVERSAL_STACKLESS_CACHE_FRIENDLY, | ||||
| 		TRAVERSAL_RECURSIVE | ||||
| 	}; | ||||
|  | ||||
| protected: | ||||
|  | ||||
|  | ||||
| 	btVector3			m_bvhAabbMin; | ||||
| 	btVector3			m_bvhAabbMax; | ||||
| 	btVector3			m_bvhQuantization; | ||||
|  | ||||
| 	int					m_bulletVersion;	//for serialization versioning. It could also be used to detect endianess. | ||||
|  | ||||
| 	int					m_curNodeIndex; | ||||
| 	//quantization data | ||||
| 	bool				m_useQuantization; | ||||
|  | ||||
|  | ||||
|  | ||||
| 	NodeArray			m_leafNodes; | ||||
| 	NodeArray			m_contiguousNodes; | ||||
| 	QuantizedNodeArray	m_quantizedLeafNodes; | ||||
| 	QuantizedNodeArray	m_quantizedContiguousNodes; | ||||
| 	 | ||||
| 	btTraversalMode	m_traversalMode; | ||||
| 	BvhSubtreeInfoArray		m_SubtreeHeaders; | ||||
|  | ||||
| 	//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray | ||||
| 	mutable int m_subtreeHeaderCount; | ||||
|  | ||||
| 	 | ||||
|  | ||||
|  | ||||
|  | ||||
| 	///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) | ||||
| 	///this might be refactored into a virtual, it is usually not calculated at run-time | ||||
| 	void	setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) | ||||
| 	{ | ||||
| 		if (m_useQuantization) | ||||
| 		{ | ||||
| 			quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0); | ||||
| 		} else | ||||
| 		{ | ||||
| 			m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| 	void	setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) | ||||
| 	{ | ||||
| 		if (m_useQuantization) | ||||
| 		{ | ||||
| 			quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1); | ||||
| 		} else | ||||
| 		{ | ||||
| 			m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	btVector3 getAabbMin(int nodeIndex) const | ||||
| 	{ | ||||
| 		if (m_useQuantization) | ||||
| 		{ | ||||
| 			return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); | ||||
| 		} | ||||
| 		//non-quantized | ||||
| 		return m_leafNodes[nodeIndex].m_aabbMinOrg; | ||||
|  | ||||
| 	} | ||||
| 	btVector3 getAabbMax(int nodeIndex) const | ||||
| 	{ | ||||
| 		if (m_useQuantization) | ||||
| 		{ | ||||
| 			return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); | ||||
| 		}  | ||||
| 		//non-quantized | ||||
| 		return m_leafNodes[nodeIndex].m_aabbMaxOrg; | ||||
| 		 | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	void	setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) | ||||
| 	{ | ||||
| 		if (m_useQuantization) | ||||
| 		{ | ||||
| 			m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; | ||||
| 		}  | ||||
| 		else | ||||
| 		{ | ||||
| 			m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)  | ||||
| 	{ | ||||
| 		if (m_useQuantization) | ||||
| 		{ | ||||
| 			unsigned short int quantizedAabbMin[3]; | ||||
| 			unsigned short int quantizedAabbMax[3]; | ||||
| 			quantize(quantizedAabbMin,newAabbMin,0); | ||||
| 			quantize(quantizedAabbMax,newAabbMax,1); | ||||
| 			for (int i=0;i<3;i++) | ||||
| 			{ | ||||
| 				if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) | ||||
| 					m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; | ||||
|  | ||||
| 				if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) | ||||
| 					m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; | ||||
|  | ||||
| 			} | ||||
| 		} else | ||||
| 		{ | ||||
| 			//non-quantized | ||||
| 			m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); | ||||
| 			m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);		 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	void	swapLeafNodes(int firstIndex,int secondIndex); | ||||
|  | ||||
| 	void	assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); | ||||
|  | ||||
| protected: | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	void	buildTree	(int startIndex,int endIndex); | ||||
|  | ||||
| 	int	calcSplittingAxis(int startIndex,int endIndex); | ||||
|  | ||||
| 	int	sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); | ||||
| 	 | ||||
| 	void	walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; | ||||
|  | ||||
| 	void	walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; | ||||
| 	void	walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; | ||||
| 	void	walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; | ||||
|  | ||||
| 	///tree traversal designed for small-memory processors like PS3 SPU | ||||
| 	void	walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; | ||||
|  | ||||
| 	///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal | ||||
| 	void	walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; | ||||
|  | ||||
| 	///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal | ||||
| 	void	walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; | ||||
| 	 | ||||
|  | ||||
|  | ||||
|  | ||||
| 	void	updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); | ||||
|  | ||||
| public: | ||||
| 	 | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	btQuantizedBvh(); | ||||
|  | ||||
| 	virtual ~btQuantizedBvh(); | ||||
|  | ||||
| 	 | ||||
| 	///***************************************** expert/internal use only ************************* | ||||
| 	void	setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); | ||||
| 	QuantizedNodeArray&	getLeafNodeArray() {			return	m_quantizedLeafNodes;	} | ||||
| 	///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized | ||||
| 	void	buildInternal(); | ||||
| 	///***************************************** expert/internal use only ************************* | ||||
|  | ||||
| 	void	reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; | ||||
| 	void	reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const; | ||||
| 	void	reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const; | ||||
|  | ||||
| 		SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const | ||||
| 	{ | ||||
|  | ||||
| 		btAssert(m_useQuantization); | ||||
|  | ||||
| 		btAssert(point.getX() <= m_bvhAabbMax.getX()); | ||||
| 		btAssert(point.getY() <= m_bvhAabbMax.getY()); | ||||
| 		btAssert(point.getZ() <= m_bvhAabbMax.getZ()); | ||||
|  | ||||
| 		btAssert(point.getX() >= m_bvhAabbMin.getX()); | ||||
| 		btAssert(point.getY() >= m_bvhAabbMin.getY()); | ||||
| 		btAssert(point.getZ() >= m_bvhAabbMin.getZ()); | ||||
|  | ||||
| 		btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization; | ||||
| 		///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative | ||||
| 		///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly) | ||||
| 		///@todo: double-check this | ||||
| 		if (isMax) | ||||
| 		{ | ||||
| 			out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1)); | ||||
| 			out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1)); | ||||
| 			out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1)); | ||||
| 		} else | ||||
| 		{ | ||||
| 			out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe)); | ||||
| 			out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe)); | ||||
| 			out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe)); | ||||
| 		} | ||||
|  | ||||
|  | ||||
| #ifdef DEBUG_CHECK_DEQUANTIZATION | ||||
| 		btVector3 newPoint = unQuantize(out); | ||||
| 		if (isMax) | ||||
| 		{ | ||||
| 			if (newPoint.getX() < point.getX()) | ||||
| 			{ | ||||
| 				printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); | ||||
| 			} | ||||
| 			if (newPoint.getY() < point.getY()) | ||||
| 			{ | ||||
| 				printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); | ||||
| 			} | ||||
| 			if (newPoint.getZ() < point.getZ()) | ||||
| 			{ | ||||
|  | ||||
| 				printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); | ||||
| 			} | ||||
| 		} else | ||||
| 		{ | ||||
| 			if (newPoint.getX() > point.getX()) | ||||
| 			{ | ||||
| 				printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); | ||||
| 			} | ||||
| 			if (newPoint.getY() > point.getY()) | ||||
| 			{ | ||||
| 				printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); | ||||
| 			} | ||||
| 			if (newPoint.getZ() > point.getZ()) | ||||
| 			{ | ||||
| 				printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); | ||||
| 			} | ||||
| 		} | ||||
| #endif //DEBUG_CHECK_DEQUANTIZATION | ||||
|  | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const | ||||
| 	{ | ||||
|  | ||||
| 		btAssert(m_useQuantization); | ||||
|  | ||||
| 		btVector3 clampedPoint(point2); | ||||
| 		clampedPoint.setMax(m_bvhAabbMin); | ||||
| 		clampedPoint.setMin(m_bvhAabbMax); | ||||
|  | ||||
| 		quantize(out,clampedPoint,isMax); | ||||
|  | ||||
| 	} | ||||
| 	 | ||||
| 	SIMD_FORCE_INLINE btVector3	unQuantize(const unsigned short* vecIn) const | ||||
| 	{ | ||||
| 			btVector3	vecOut; | ||||
| 			vecOut.setValue( | ||||
| 			(btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), | ||||
| 			(btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), | ||||
| 			(btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); | ||||
| 			vecOut += m_bvhAabbMin; | ||||
| 			return vecOut; | ||||
| 	} | ||||
|  | ||||
| 	///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. | ||||
| 	void	setTraversalMode(btTraversalMode	traversalMode) | ||||
| 	{ | ||||
| 		m_traversalMode = traversalMode; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	SIMD_FORCE_INLINE QuantizedNodeArray&	getQuantizedNodeArray() | ||||
| 	{	 | ||||
| 		return	m_quantizedContiguousNodes; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	SIMD_FORCE_INLINE BvhSubtreeInfoArray&	getSubtreeInfoArray() | ||||
| 	{ | ||||
| 		return m_SubtreeHeaders; | ||||
| 	} | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| 	/////Calculate space needed to store BVH for serialization | ||||
| 	unsigned calculateSerializeBufferSize() const; | ||||
|  | ||||
| 	/// Data buffer MUST be 16 byte aligned | ||||
| 	virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const; | ||||
|  | ||||
| 	///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' | ||||
| 	static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); | ||||
|  | ||||
| 	static unsigned int getAlignmentSerializationPadding(); | ||||
| ////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| 	 | ||||
| 	virtual	int	calculateSerializeBufferSizeNew() const; | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| 	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const; | ||||
|  | ||||
| 	virtual	void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData); | ||||
|  | ||||
| 	virtual	void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData); | ||||
|  | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool isQuantized() | ||||
| 	{ | ||||
| 		return m_useQuantization; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	// Special "copy" constructor that allows for in-place deserialization | ||||
| 	// Prevents btVector3's default constructor from being called, but doesn't inialize much else | ||||
| 	// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need) | ||||
| 	btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory); | ||||
|  | ||||
| } | ||||
| ; | ||||
|  | ||||
|  | ||||
| struct	btBvhSubtreeInfoData | ||||
| { | ||||
| 	int			m_rootNodeIndex; | ||||
| 	int			m_subtreeSize; | ||||
| 	unsigned short m_quantizedAabbMin[3]; | ||||
| 	unsigned short m_quantizedAabbMax[3]; | ||||
| }; | ||||
|  | ||||
| struct btOptimizedBvhNodeFloatData | ||||
| { | ||||
| 	btVector3FloatData	m_aabbMinOrg; | ||||
| 	btVector3FloatData	m_aabbMaxOrg; | ||||
| 	int	m_escapeIndex; | ||||
| 	int	m_subPart; | ||||
| 	int	m_triangleIndex; | ||||
| 	char m_pad[4]; | ||||
| }; | ||||
|  | ||||
| struct btOptimizedBvhNodeDoubleData | ||||
| { | ||||
| 	btVector3DoubleData	m_aabbMinOrg; | ||||
| 	btVector3DoubleData	m_aabbMaxOrg; | ||||
| 	int	m_escapeIndex; | ||||
| 	int	m_subPart; | ||||
| 	int	m_triangleIndex; | ||||
| 	char	m_pad[4]; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct btQuantizedBvhNodeData | ||||
| { | ||||
| 	unsigned short m_quantizedAabbMin[3]; | ||||
| 	unsigned short m_quantizedAabbMax[3]; | ||||
| 	int	m_escapeIndexOrTriangleIndex; | ||||
| }; | ||||
|  | ||||
| struct	btQuantizedBvhFloatData | ||||
| { | ||||
| 	btVector3FloatData			m_bvhAabbMin; | ||||
| 	btVector3FloatData			m_bvhAabbMax; | ||||
| 	btVector3FloatData			m_bvhQuantization; | ||||
| 	int					m_curNodeIndex; | ||||
| 	int					m_useQuantization; | ||||
| 	int					m_numContiguousLeafNodes; | ||||
| 	int					m_numQuantizedContiguousNodes; | ||||
| 	btOptimizedBvhNodeFloatData	*m_contiguousNodesPtr; | ||||
| 	btQuantizedBvhNodeData		*m_quantizedContiguousNodesPtr; | ||||
| 	btBvhSubtreeInfoData	*m_subTreeInfoPtr; | ||||
| 	int					m_traversalMode; | ||||
| 	int					m_numSubtreeHeaders; | ||||
| 	 | ||||
| }; | ||||
|  | ||||
| struct	btQuantizedBvhDoubleData | ||||
| { | ||||
| 	btVector3DoubleData			m_bvhAabbMin; | ||||
| 	btVector3DoubleData			m_bvhAabbMax; | ||||
| 	btVector3DoubleData			m_bvhQuantization; | ||||
| 	int							m_curNodeIndex; | ||||
| 	int							m_useQuantization; | ||||
| 	int							m_numContiguousLeafNodes; | ||||
| 	int							m_numQuantizedContiguousNodes; | ||||
| 	btOptimizedBvhNodeDoubleData	*m_contiguousNodesPtr; | ||||
| 	btQuantizedBvhNodeData			*m_quantizedContiguousNodesPtr; | ||||
|  | ||||
| 	int							m_traversalMode; | ||||
| 	int							m_numSubtreeHeaders; | ||||
| 	btBvhSubtreeInfoData		*m_subTreeInfoPtr; | ||||
| }; | ||||
|  | ||||
|  | ||||
| SIMD_FORCE_INLINE	int	btQuantizedBvh::calculateSerializeBufferSizeNew() const | ||||
| { | ||||
| 	return sizeof(btQuantizedBvhData); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //QUANTIZED_BVH_H | ||||
| @@ -0,0 +1,349 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btSimpleBroadphase.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDispatcher.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" | ||||
|  | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btTransform.h" | ||||
| #include "LinearMath/btMatrix3x3.h" | ||||
| #include "LinearMath/btAabbUtil2.h" | ||||
|  | ||||
| #include <new> | ||||
|  | ||||
| extern int gOverlappingPairs; | ||||
|  | ||||
| void	btSimpleBroadphase::validate() | ||||
| { | ||||
| 	for (int i=0;i<m_numHandles;i++) | ||||
| 	{ | ||||
| 		for (int j=i+1;j<m_numHandles;j++) | ||||
| 		{ | ||||
| 			btAssert(&m_pHandles[i] != &m_pHandles[j]); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
|  | ||||
| btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache) | ||||
| 	:m_pairCache(overlappingPairCache), | ||||
| 	m_ownsPairCache(false), | ||||
| 	m_invalidPair(0) | ||||
| { | ||||
|  | ||||
| 	if (!overlappingPairCache) | ||||
| 	{ | ||||
| 		void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16); | ||||
| 		m_pairCache = new (mem)btHashedOverlappingPairCache(); | ||||
| 		m_ownsPairCache = true; | ||||
| 	} | ||||
|  | ||||
| 	// allocate handles buffer and put all handles on free list | ||||
| 	m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16); | ||||
| 	m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies]; | ||||
| 	m_maxHandles = maxProxies; | ||||
| 	m_numHandles = 0; | ||||
| 	m_firstFreeHandle = 0; | ||||
| 	m_LastHandleIndex = -1; | ||||
| 	 | ||||
|  | ||||
| 	{ | ||||
| 		for (int i = m_firstFreeHandle; i < maxProxies; i++) | ||||
| 		{ | ||||
| 			m_pHandles[i].SetNextFree(i + 1); | ||||
| 			m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes | ||||
| 		} | ||||
| 		m_pHandles[maxProxies - 1].SetNextFree(0); | ||||
| 	 | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| btSimpleBroadphase::~btSimpleBroadphase() | ||||
| { | ||||
| 	btAlignedFree(m_pHandlesRawPtr); | ||||
|  | ||||
| 	if (m_ownsPairCache) | ||||
| 	{ | ||||
| 		m_pairCache->~btOverlappingPairCache(); | ||||
| 		btAlignedFree(m_pairCache); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| btBroadphaseProxy*	btSimpleBroadphase::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy) | ||||
| { | ||||
| 	if (m_numHandles >= m_maxHandles) | ||||
| 	{ | ||||
| 		btAssert(0); | ||||
| 		return 0; //should never happen, but don't let the game crash ;-) | ||||
| 	} | ||||
| 	btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); | ||||
|  | ||||
| 	int newHandleIndex = allocHandle(); | ||||
| 	btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); | ||||
|  | ||||
| 	return proxy; | ||||
| } | ||||
|  | ||||
| class	RemovingOverlapCallback : public btOverlapCallback | ||||
| { | ||||
| protected: | ||||
| 	virtual bool	processOverlap(btBroadphasePair& pair) | ||||
| 	{ | ||||
| 		(void)pair; | ||||
| 		btAssert(0); | ||||
| 		return false; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class RemovePairContainingProxy | ||||
| { | ||||
|  | ||||
| 	btBroadphaseProxy*	m_targetProxy; | ||||
| 	public: | ||||
| 	virtual ~RemovePairContainingProxy() | ||||
| 	{ | ||||
| 	} | ||||
| protected: | ||||
| 	virtual bool processOverlap(btBroadphasePair& pair) | ||||
| 	{ | ||||
| 		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0); | ||||
| 		btSimpleBroadphaseProxy* proxy1 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1); | ||||
|  | ||||
| 		return ((m_targetProxy == proxy0 || m_targetProxy == proxy1)); | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| void	btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) | ||||
| { | ||||
| 		 | ||||
| 		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg); | ||||
| 		freeHandle(proxy0); | ||||
|  | ||||
| 		m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); | ||||
|  | ||||
| 		//validate(); | ||||
| 		 | ||||
| } | ||||
|  | ||||
| void	btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const | ||||
| { | ||||
| 	const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); | ||||
| 	aabbMin = sbp->m_aabbMin; | ||||
| 	aabbMax = sbp->m_aabbMax; | ||||
| } | ||||
|  | ||||
| void	btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/) | ||||
| { | ||||
| 	btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); | ||||
| 	sbp->m_aabbMin = aabbMin; | ||||
| 	sbp->m_aabbMax = aabbMax; | ||||
| } | ||||
|  | ||||
| void	btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) | ||||
| { | ||||
| 	for (int i=0; i <= m_LastHandleIndex; i++) | ||||
| 	{ | ||||
| 		btSimpleBroadphaseProxy* proxy = &m_pHandles[i]; | ||||
| 		if(!proxy->m_clientObject) | ||||
| 		{ | ||||
| 			continue; | ||||
| 		} | ||||
| 		rayCallback.process(proxy); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) | ||||
| { | ||||
| 	for (int i=0; i <= m_LastHandleIndex; i++) | ||||
| 	{ | ||||
| 		btSimpleBroadphaseProxy* proxy = &m_pHandles[i]; | ||||
| 		if(!proxy->m_clientObject) | ||||
| 		{ | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax)) | ||||
| 		{ | ||||
| 			callback.process(proxy); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| 	 | ||||
|  | ||||
|  | ||||
|  | ||||
| bool	btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1) | ||||
| { | ||||
| 	return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&  | ||||
| 		   proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] && | ||||
| 		   proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2]; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| //then remove non-overlapping ones | ||||
| class CheckOverlapCallback : public btOverlapCallback | ||||
| { | ||||
| public: | ||||
| 	virtual bool processOverlap(btBroadphasePair& pair) | ||||
| 	{ | ||||
| 		return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0),static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1))); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| void	btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) | ||||
| { | ||||
| 	//first check for new overlapping pairs | ||||
| 	int i,j; | ||||
| 	if (m_numHandles >= 0) | ||||
| 	{ | ||||
| 		int new_largest_index = -1; | ||||
| 		for (i=0; i <= m_LastHandleIndex; i++) | ||||
| 		{ | ||||
| 			btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i]; | ||||
| 			if(!proxy0->m_clientObject) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			new_largest_index = i; | ||||
| 			for (j=i+1; j <= m_LastHandleIndex; j++) | ||||
| 			{ | ||||
| 				btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j]; | ||||
| 				btAssert(proxy0 != proxy1); | ||||
| 				if(!proxy1->m_clientObject) | ||||
| 				{ | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); | ||||
| 				btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); | ||||
|  | ||||
| 				if (aabbOverlap(p0,p1)) | ||||
| 				{ | ||||
| 					if ( !m_pairCache->findPair(proxy0,proxy1)) | ||||
| 					{ | ||||
| 						m_pairCache->addOverlappingPair(proxy0,proxy1); | ||||
| 					} | ||||
| 				} else | ||||
| 				{ | ||||
| 					if (!m_pairCache->hasDeferredRemoval()) | ||||
| 					{ | ||||
| 						if ( m_pairCache->findPair(proxy0,proxy1)) | ||||
| 						{ | ||||
| 							m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		m_LastHandleIndex = new_largest_index; | ||||
|  | ||||
| 		if (m_ownsPairCache && m_pairCache->hasDeferredRemoval()) | ||||
| 		{ | ||||
|  | ||||
| 			btBroadphasePairArray&	overlappingPairArray = m_pairCache->getOverlappingPairArray(); | ||||
|  | ||||
| 			//perform a sort, to find duplicates and to sort 'invalid' pairs to the end | ||||
| 			overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); | ||||
|  | ||||
| 			overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); | ||||
| 			m_invalidPair = 0; | ||||
|  | ||||
|  | ||||
| 			btBroadphasePair previousPair; | ||||
| 			previousPair.m_pProxy0 = 0; | ||||
| 			previousPair.m_pProxy1 = 0; | ||||
| 			previousPair.m_algorithm = 0; | ||||
|  | ||||
|  | ||||
| 			for (i=0;i<overlappingPairArray.size();i++) | ||||
| 			{ | ||||
|  | ||||
| 				btBroadphasePair& pair = overlappingPairArray[i]; | ||||
|  | ||||
| 				bool isDuplicate = (pair == previousPair); | ||||
|  | ||||
| 				previousPair = pair; | ||||
|  | ||||
| 				bool needsRemoval = false; | ||||
|  | ||||
| 				if (!isDuplicate) | ||||
| 				{ | ||||
| 					bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); | ||||
|  | ||||
| 					if (hasOverlap) | ||||
| 					{ | ||||
| 						needsRemoval = false;//callback->processOverlap(pair); | ||||
| 					} else | ||||
| 					{ | ||||
| 						needsRemoval = true; | ||||
| 					} | ||||
| 				} else | ||||
| 				{ | ||||
| 					//remove duplicate | ||||
| 					needsRemoval = true; | ||||
| 					//should have no algorithm | ||||
| 					btAssert(!pair.m_algorithm); | ||||
| 				} | ||||
|  | ||||
| 				if (needsRemoval) | ||||
| 				{ | ||||
| 					m_pairCache->cleanOverlappingPair(pair,dispatcher); | ||||
|  | ||||
| 					//		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); | ||||
| 					//		m_overlappingPairArray.pop_back(); | ||||
| 					pair.m_pProxy0 = 0; | ||||
| 					pair.m_pProxy1 = 0; | ||||
| 					m_invalidPair++; | ||||
| 					gOverlappingPairs--; | ||||
| 				}  | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 			///if you don't like to skip the invalid pairs in the array, execute following code: | ||||
| #define CLEAN_INVALID_PAIRS 1 | ||||
| #ifdef CLEAN_INVALID_PAIRS | ||||
|  | ||||
| 			//perform a sort, to sort 'invalid' pairs to the end | ||||
| 			overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); | ||||
|  | ||||
| 			overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); | ||||
| 			m_invalidPair = 0; | ||||
| #endif//CLEAN_INVALID_PAIRS | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) | ||||
| { | ||||
| 	btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); | ||||
| 	btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); | ||||
| 	return aabbOverlap(p0,p1); | ||||
| } | ||||
|  | ||||
| void	btSimpleBroadphase::resetPool(btDispatcher* dispatcher) | ||||
| { | ||||
| 	//not yet | ||||
| } | ||||
| @@ -0,0 +1,171 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SIMPLE_BROADPHASE_H | ||||
| #define SIMPLE_BROADPHASE_H | ||||
|  | ||||
|  | ||||
| #include "btOverlappingPairCache.h" | ||||
|  | ||||
|  | ||||
| struct btSimpleBroadphaseProxy : public btBroadphaseProxy | ||||
| { | ||||
| 	int			m_nextFree; | ||||
| 	 | ||||
| //	int			m_handleId; | ||||
|  | ||||
| 	 | ||||
| 	btSimpleBroadphaseProxy() {}; | ||||
|  | ||||
| 	btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) | ||||
| 	:btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy) | ||||
| 	{ | ||||
| 		(void)shapeType; | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} | ||||
| 	SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} | ||||
|  | ||||
| 	 | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| ///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead. | ||||
| ///It is a brute force aabb culling broadphase based on O(n^2) aabb checks | ||||
| class btSimpleBroadphase : public btBroadphaseInterface | ||||
| { | ||||
|  | ||||
| protected: | ||||
|  | ||||
| 	int		m_numHandles;						// number of active handles | ||||
| 	int		m_maxHandles;						// max number of handles | ||||
| 	int		m_LastHandleIndex;							 | ||||
| 	 | ||||
| 	btSimpleBroadphaseProxy* m_pHandles;						// handles pool | ||||
|  | ||||
| 	void* m_pHandlesRawPtr; | ||||
| 	int		m_firstFreeHandle;		// free handles list | ||||
| 	 | ||||
| 	int allocHandle() | ||||
| 	{ | ||||
| 		btAssert(m_numHandles < m_maxHandles); | ||||
| 		int freeHandle = m_firstFreeHandle; | ||||
| 		m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); | ||||
| 		m_numHandles++; | ||||
| 		if(freeHandle > m_LastHandleIndex) | ||||
| 		{ | ||||
| 			m_LastHandleIndex = freeHandle; | ||||
| 		} | ||||
| 		return freeHandle; | ||||
| 	} | ||||
|  | ||||
| 	void freeHandle(btSimpleBroadphaseProxy* proxy) | ||||
| 	{ | ||||
| 		int handle = int(proxy-m_pHandles); | ||||
| 		btAssert(handle >= 0 && handle < m_maxHandles); | ||||
| 		if(handle == m_LastHandleIndex) | ||||
| 		{ | ||||
| 			m_LastHandleIndex--; | ||||
| 		} | ||||
| 		proxy->SetNextFree(m_firstFreeHandle); | ||||
| 		m_firstFreeHandle = handle; | ||||
|  | ||||
| 		proxy->m_clientObject = 0; | ||||
|  | ||||
| 		m_numHandles--; | ||||
| 	} | ||||
|  | ||||
| 	btOverlappingPairCache*	m_pairCache; | ||||
| 	bool	m_ownsPairCache; | ||||
|  | ||||
| 	int	m_invalidPair; | ||||
|  | ||||
| 	 | ||||
| 	 | ||||
| 	inline btSimpleBroadphaseProxy*	getSimpleProxyFromProxy(btBroadphaseProxy* proxy) | ||||
| 	{ | ||||
| 		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy); | ||||
| 		return proxy0; | ||||
| 	} | ||||
|  | ||||
| 	inline const btSimpleBroadphaseProxy*	getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const | ||||
| 	{ | ||||
| 		const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy); | ||||
| 		return proxy0; | ||||
| 	} | ||||
|  | ||||
| 	///reset broadphase internal structures, to ensure determinism/reproducability | ||||
| 	virtual void resetPool(btDispatcher* dispatcher); | ||||
|  | ||||
|  | ||||
| 	void	validate(); | ||||
|  | ||||
| protected: | ||||
|  | ||||
|  | ||||
| 	 | ||||
|  | ||||
| public: | ||||
| 	btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0); | ||||
| 	virtual ~btSimpleBroadphase(); | ||||
|  | ||||
|  | ||||
| 		static bool	aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); | ||||
|  | ||||
|  | ||||
| 	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); | ||||
|  | ||||
| 	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher); | ||||
|  | ||||
| 	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); | ||||
| 	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); | ||||
| 	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; | ||||
|  | ||||
| 	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); | ||||
| 	virtual void	aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); | ||||
| 		 | ||||
| 	btOverlappingPairCache*	getOverlappingPairCache() | ||||
| 	{ | ||||
| 		return m_pairCache; | ||||
| 	} | ||||
| 	const btOverlappingPairCache*	getOverlappingPairCache() const | ||||
| 	{ | ||||
| 		return m_pairCache; | ||||
| 	} | ||||
|  | ||||
| 	bool	testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); | ||||
|  | ||||
|  | ||||
| 	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame | ||||
| 	///will add some transform later | ||||
| 	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const | ||||
| 	{ | ||||
| 		aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); | ||||
| 		aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); | ||||
| 	} | ||||
|  | ||||
| 	virtual void	printStats() | ||||
| 	{ | ||||
| //		printf("btSimpleBroadphase.h\n"); | ||||
| //		printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //SIMPLE_BROADPHASE_H | ||||
|  | ||||
| @@ -0,0 +1,209 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "LinearMath/btScalar.h" | ||||
| #include "SphereTriangleDetector.h" | ||||
| #include "BulletCollision/CollisionShapes/btTriangleShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btSphereShape.h" | ||||
|  | ||||
|  | ||||
| SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold) | ||||
| :m_sphere(sphere), | ||||
| m_triangle(triangle), | ||||
| m_contactBreakingThreshold(contactBreakingThreshold) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void	SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) | ||||
| { | ||||
|  | ||||
| 	(void)debugDraw; | ||||
| 	const btTransform& transformA = input.m_transformA; | ||||
| 	const btTransform& transformB = input.m_transformB; | ||||
|  | ||||
| 	btVector3 point,normal; | ||||
| 	btScalar timeOfImpact = btScalar(1.); | ||||
| 	btScalar depth = btScalar(0.); | ||||
| //	output.m_distance = btScalar(BT_LARGE_FLOAT); | ||||
| 	//move sphere into triangle space | ||||
| 	btTransform	sphereInTr = transformB.inverseTimes(transformA); | ||||
|  | ||||
| 	if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold)) | ||||
| 	{ | ||||
| 		if (swapResults) | ||||
| 		{ | ||||
| 			btVector3 normalOnB = transformB.getBasis()*normal; | ||||
| 			btVector3 normalOnA = -normalOnB; | ||||
| 			btVector3 pointOnA = transformB*point+normalOnB*depth; | ||||
| 			output.addContactPoint(normalOnA,pointOnA,depth); | ||||
| 		} else | ||||
| 		{ | ||||
| 			output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| #define MAX_OVERLAP btScalar(0.) | ||||
|  | ||||
|  | ||||
|  | ||||
| // See also geometrictools.com | ||||
| // Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv | ||||
| btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest); | ||||
|  | ||||
| btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) { | ||||
| 	btVector3 diff = p - from; | ||||
| 	btVector3 v = to - from; | ||||
| 	btScalar t = v.dot(diff); | ||||
| 	 | ||||
| 	if (t > 0) { | ||||
| 		btScalar dotVV = v.dot(v); | ||||
| 		if (t < dotVV) { | ||||
| 			t /= dotVV; | ||||
| 			diff -= t*v; | ||||
| 		} else { | ||||
| 			t = 1; | ||||
| 			diff -= v; | ||||
| 		} | ||||
| 	} else | ||||
| 		t = 0; | ||||
|  | ||||
| 	nearest = from + t*v; | ||||
| 	return diff.dot(diff);	 | ||||
| } | ||||
|  | ||||
| bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal)  { | ||||
| 	btVector3 lp(p); | ||||
| 	btVector3 lnormal(normal); | ||||
| 	 | ||||
| 	return pointInTriangle(vertices, lnormal, &lp); | ||||
| } | ||||
|  | ||||
| ///combined discrete/continuous sphere-triangle | ||||
| bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold) | ||||
| { | ||||
|  | ||||
| 	const btVector3* vertices = &m_triangle->getVertexPtr(0); | ||||
| 	const btVector3& c = sphereCenter; | ||||
| 	btScalar r = m_sphere->getRadius(); | ||||
|  | ||||
| 	btVector3 delta (0,0,0); | ||||
|  | ||||
| 	btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); | ||||
| 	normal.normalize(); | ||||
| 	btVector3 p1ToCentre = c - vertices[0]; | ||||
| 	btScalar distanceFromPlane = p1ToCentre.dot(normal); | ||||
|  | ||||
| 	if (distanceFromPlane < btScalar(0.)) | ||||
| 	{ | ||||
| 		//triangle facing the other way | ||||
| 	 | ||||
| 		distanceFromPlane *= btScalar(-1.); | ||||
| 		normal *= btScalar(-1.); | ||||
| 	} | ||||
|  | ||||
| 	btScalar contactMargin = contactBreakingThreshold; | ||||
| 	bool isInsideContactPlane = distanceFromPlane < r + contactMargin; | ||||
| 	bool isInsideShellPlane = distanceFromPlane < r; | ||||
| 	 | ||||
| 	btScalar deltaDotNormal = delta.dot(normal); | ||||
| 	if (!isInsideShellPlane && deltaDotNormal >= btScalar(0.0)) | ||||
| 		return false; | ||||
|  | ||||
| 	// Check for contact / intersection | ||||
| 	bool hasContact = false; | ||||
| 	btVector3 contactPoint; | ||||
| 	if (isInsideContactPlane) { | ||||
| 		if (facecontains(c,vertices,normal)) { | ||||
| 			// Inside the contact wedge - touches a point on the shell plane | ||||
| 			hasContact = true; | ||||
| 			contactPoint = c - normal*distanceFromPlane; | ||||
| 		} else { | ||||
| 			// Could be inside one of the contact capsules | ||||
| 			btScalar contactCapsuleRadiusSqr = (r + contactMargin) * (r + contactMargin); | ||||
| 			btVector3 nearestOnEdge; | ||||
| 			for (int i = 0; i < m_triangle->getNumEdges(); i++) { | ||||
| 				 | ||||
| 				btVector3 pa; | ||||
| 				btVector3 pb; | ||||
| 				 | ||||
| 				m_triangle->getEdge(i,pa,pb); | ||||
|  | ||||
| 				btScalar distanceSqr = SegmentSqrDistance(pa,pb,c, nearestOnEdge); | ||||
| 				if (distanceSqr < contactCapsuleRadiusSqr) { | ||||
| 					// Yep, we're inside a capsule | ||||
| 					hasContact = true; | ||||
| 					contactPoint = nearestOnEdge; | ||||
| 				} | ||||
| 				 | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (hasContact) { | ||||
| 		btVector3 contactToCentre = c - contactPoint; | ||||
| 		btScalar distanceSqr = contactToCentre.length2(); | ||||
| 		if (distanceSqr < (r - MAX_OVERLAP)*(r - MAX_OVERLAP)) { | ||||
| 			btScalar distance = btSqrt(distanceSqr); | ||||
| 			resultNormal = contactToCentre; | ||||
| 			resultNormal.normalize(); | ||||
| 			point = contactPoint; | ||||
| 			depth = -(r-distance); | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		if (delta.dot(contactToCentre) >= btScalar(0.0))  | ||||
| 			return false; | ||||
| 		 | ||||
| 		// Moving towards the contact point -> collision | ||||
| 		point = contactPoint; | ||||
| 		timeOfImpact = btScalar(0.0); | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ) | ||||
| { | ||||
| 	const btVector3* p1 = &vertices[0]; | ||||
| 	const btVector3* p2 = &vertices[1]; | ||||
| 	const btVector3* p3 = &vertices[2]; | ||||
|  | ||||
| 	btVector3 edge1( *p2 - *p1 ); | ||||
| 	btVector3 edge2( *p3 - *p2 ); | ||||
| 	btVector3 edge3( *p1 - *p3 ); | ||||
|  | ||||
| 	btVector3 p1_to_p( *p - *p1 ); | ||||
| 	btVector3 p2_to_p( *p - *p2 ); | ||||
| 	btVector3 p3_to_p( *p - *p3 ); | ||||
|  | ||||
| 	btVector3 edge1_normal( edge1.cross(normal)); | ||||
| 	btVector3 edge2_normal( edge2.cross(normal)); | ||||
| 	btVector3 edge3_normal( edge3.cross(normal)); | ||||
| 	 | ||||
| 	btScalar r1, r2, r3; | ||||
| 	r1 = edge1_normal.dot( p1_to_p ); | ||||
| 	r2 = edge2_normal.dot( p2_to_p ); | ||||
| 	r3 = edge3_normal.dot( p3_to_p ); | ||||
| 	if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) || | ||||
| 	     ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) ) | ||||
| 		return true; | ||||
| 	return false; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SPHERE_TRIANGLE_DETECTOR_H | ||||
| #define SPHERE_TRIANGLE_DETECTOR_H | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| class btSphereShape; | ||||
| class btTriangleShape; | ||||
|  | ||||
|  | ||||
|  | ||||
| /// sphere-triangle to match the btDiscreteCollisionDetectorInterface | ||||
| struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface | ||||
| { | ||||
| 	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); | ||||
|  | ||||
| 	SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold); | ||||
|  | ||||
| 	virtual ~SphereTriangleDetector() {}; | ||||
|  | ||||
| 	bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar	contactBreakingThreshold); | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	 | ||||
| 	bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ); | ||||
| 	bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal); | ||||
|  | ||||
| 	btSphereShape* m_sphere; | ||||
| 	btTriangleShape* m_triangle; | ||||
| 	btScalar	m_contactBreakingThreshold; | ||||
| 	 | ||||
| }; | ||||
| #endif //SPHERE_TRIANGLE_DETECTOR_H | ||||
|  | ||||
| @@ -0,0 +1,47 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btActivatingCollisionAlgorithm.h" | ||||
| #include "btCollisionDispatcher.h" | ||||
| #include "btCollisionObject.h" | ||||
|  | ||||
| btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci) | ||||
| :btCollisionAlgorithm(ci) | ||||
| //, | ||||
| //m_colObj0(0), | ||||
| //m_colObj1(0) | ||||
| { | ||||
| } | ||||
| btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1) | ||||
| :btCollisionAlgorithm(ci) | ||||
| //, | ||||
| //m_colObj0(0), | ||||
| //m_colObj1(0) | ||||
| { | ||||
| //	if (ci.m_dispatcher1->needsCollision(colObj0,colObj1)) | ||||
| //	{ | ||||
| //		m_colObj0 = colObj0; | ||||
| //		m_colObj1 = colObj1; | ||||
| //		 | ||||
| //		m_colObj0->activate(); | ||||
| //		m_colObj1->activate(); | ||||
| //	} | ||||
| } | ||||
|  | ||||
| btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm() | ||||
| { | ||||
| //		m_colObj0->activate(); | ||||
| //		m_colObj1->activate(); | ||||
| } | ||||
| @@ -0,0 +1,36 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef __BT_ACTIVATING_COLLISION_ALGORITHM_H | ||||
| #define __BT_ACTIVATING_COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" | ||||
|  | ||||
| ///This class is not enabled yet (work-in-progress) to more aggressively activate objects. | ||||
| class btActivatingCollisionAlgorithm : public btCollisionAlgorithm | ||||
| { | ||||
| //	btCollisionObject* m_colObj0; | ||||
| //	btCollisionObject* m_colObj1; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci); | ||||
|  | ||||
| 	btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1); | ||||
|  | ||||
| 	virtual ~btActivatingCollisionAlgorithm(); | ||||
|  | ||||
| }; | ||||
| #endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H | ||||
| @@ -0,0 +1,435 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| * The b2CollidePolygons routines are Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| ///btBox2dBox2dCollisionAlgorithm, with modified b2CollidePolygons routines from the Box2D library. | ||||
| ///The modifications include: switching from b2Vec to btVector3, redefinition of b2Dot, b2Cross | ||||
|  | ||||
| #include "btBox2dBox2dCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "BulletCollision/CollisionShapes/btBoxShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h" | ||||
| #include "BulletCollision/CollisionShapes/btBox2dShape.h" | ||||
|  | ||||
| #define USE_PERSISTENT_CONTACTS 1 | ||||
|  | ||||
| btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1) | ||||
| : btActivatingCollisionAlgorithm(ci,obj0,obj1), | ||||
| m_ownManifold(false), | ||||
| m_manifoldPtr(mf) | ||||
| { | ||||
| 	if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1)) | ||||
| 	{ | ||||
| 		m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1); | ||||
| 		m_ownManifold = true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm() | ||||
| { | ||||
| 	 | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr) | ||||
| 			m_dispatcher->releaseManifold(m_manifoldPtr); | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
|  | ||||
|  | ||||
| void b2CollidePolygons(btManifoldResult* manifold,  const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB); | ||||
|  | ||||
| //#include <stdio.h> | ||||
| void btBox2dBox2dCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	if (!m_manifoldPtr) | ||||
| 		return; | ||||
|  | ||||
| 	btCollisionObject*	col0 = body0; | ||||
| 	btCollisionObject*	col1 = body1; | ||||
| 	btBox2dShape* box0 = (btBox2dShape*)col0->getCollisionShape(); | ||||
| 	btBox2dShape* box1 = (btBox2dShape*)col1->getCollisionShape(); | ||||
|  | ||||
| 	resultOut->setPersistentManifold(m_manifoldPtr); | ||||
|  | ||||
| 	b2CollidePolygons(resultOut,box0,col0->getWorldTransform(),box1,col1->getWorldTransform()); | ||||
|  | ||||
| 	//  refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		resultOut->refreshContactPoints(); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) | ||||
| { | ||||
| 	//not yet | ||||
| 	return 1.f; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct ClipVertex | ||||
| { | ||||
| 	btVector3 v; | ||||
| 	int id; | ||||
| 	//b2ContactID id; | ||||
| 	//b2ContactID id; | ||||
| }; | ||||
|  | ||||
| #define b2Dot(a,b) (a).dot(b) | ||||
| #define b2Mul(a,b) (a)*(b) | ||||
| #define b2MulT(a,b) (a).transpose()*(b) | ||||
| #define b2Cross(a,b) (a).cross(b) | ||||
| #define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f) | ||||
|  | ||||
| int b2_maxManifoldPoints =2; | ||||
|  | ||||
| static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2], | ||||
| 					  const btVector3& normal, btScalar offset) | ||||
| { | ||||
| 	// Start with no output points | ||||
| 	int numOut = 0; | ||||
|  | ||||
| 	// Calculate the distance of end points to the line | ||||
| 	btScalar distance0 = b2Dot(normal, vIn[0].v) - offset; | ||||
| 	btScalar distance1 = b2Dot(normal, vIn[1].v) - offset; | ||||
|  | ||||
| 	// If the points are behind the plane | ||||
| 	if (distance0 <= 0.0f) vOut[numOut++] = vIn[0]; | ||||
| 	if (distance1 <= 0.0f) vOut[numOut++] = vIn[1]; | ||||
|  | ||||
| 	// If the points are on different sides of the plane | ||||
| 	if (distance0 * distance1 < 0.0f) | ||||
| 	{ | ||||
| 		// Find intersection point of edge and plane | ||||
| 		btScalar interp = distance0 / (distance0 - distance1); | ||||
| 		vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v); | ||||
| 		if (distance0 > 0.0f) | ||||
| 		{ | ||||
| 			vOut[numOut].id = vIn[0].id; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			vOut[numOut].id = vIn[1].id; | ||||
| 		} | ||||
| 		++numOut; | ||||
| 	} | ||||
|  | ||||
| 	return numOut; | ||||
| } | ||||
|  | ||||
| // Find the separation between poly1 and poly2 for a give edge normal on poly1. | ||||
| static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1, | ||||
| 							  const btBox2dShape* poly2, const btTransform& xf2) | ||||
| { | ||||
| 	const btVector3* vertices1 = poly1->getVertices(); | ||||
| 	const btVector3* normals1 = poly1->getNormals(); | ||||
|  | ||||
| 	int count2 = poly2->getVertexCount(); | ||||
| 	const btVector3* vertices2 = poly2->getVertices(); | ||||
|  | ||||
| 	btAssert(0 <= edge1 && edge1 < poly1->getVertexCount()); | ||||
|  | ||||
| 	// Convert normal from poly1's frame into poly2's frame. | ||||
| 	btVector3 normal1World = b2Mul(xf1.getBasis(), normals1[edge1]); | ||||
| 	btVector3 normal1 = b2MulT(xf2.getBasis(), normal1World); | ||||
|  | ||||
| 	// Find support vertex on poly2 for -normal. | ||||
| 	int index = 0; | ||||
| 	btScalar minDot = BT_LARGE_FLOAT; | ||||
|  | ||||
| 	for (int i = 0; i < count2; ++i) | ||||
| 	{ | ||||
| 		btScalar dot = b2Dot(vertices2[i], normal1); | ||||
| 		if (dot < minDot) | ||||
| 		{ | ||||
| 			minDot = dot; | ||||
| 			index = i; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	btVector3 v1 = b2Mul(xf1, vertices1[edge1]); | ||||
| 	btVector3 v2 = b2Mul(xf2, vertices2[index]); | ||||
| 	btScalar separation = b2Dot(v2 - v1, normal1World); | ||||
| 	return separation; | ||||
| } | ||||
|  | ||||
| // Find the max separation between poly1 and poly2 using edge normals from poly1. | ||||
| static btScalar FindMaxSeparation(int* edgeIndex, | ||||
| 								 const btBox2dShape* poly1, const btTransform& xf1, | ||||
| 								 const btBox2dShape* poly2, const btTransform& xf2) | ||||
| { | ||||
| 	int count1 = poly1->getVertexCount(); | ||||
| 	const btVector3* normals1 = poly1->getNormals(); | ||||
|  | ||||
| 	// Vector pointing from the centroid of poly1 to the centroid of poly2. | ||||
| 	btVector3 d = b2Mul(xf2, poly2->getCentroid()) - b2Mul(xf1, poly1->getCentroid()); | ||||
| 	btVector3 dLocal1 = b2MulT(xf1.getBasis(), d); | ||||
|  | ||||
| 	// Find edge normal on poly1 that has the largest projection onto d. | ||||
| 	int edge = 0; | ||||
| 	btScalar maxDot = -BT_LARGE_FLOAT; | ||||
| 	for (int i = 0; i < count1; ++i) | ||||
| 	{ | ||||
| 		btScalar dot = b2Dot(normals1[i], dLocal1); | ||||
| 		if (dot > maxDot) | ||||
| 		{ | ||||
| 			maxDot = dot; | ||||
| 			edge = i; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Get the separation for the edge normal. | ||||
| 	btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2); | ||||
| 	if (s > 0.0f) | ||||
| 	{ | ||||
| 		return s; | ||||
| 	} | ||||
|  | ||||
| 	// Check the separation for the previous edge normal. | ||||
| 	int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1; | ||||
| 	btScalar sPrev = EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2); | ||||
| 	if (sPrev > 0.0f) | ||||
| 	{ | ||||
| 		return sPrev; | ||||
| 	} | ||||
|  | ||||
| 	// Check the separation for the next edge normal. | ||||
| 	int nextEdge = edge + 1 < count1 ? edge + 1 : 0; | ||||
| 	btScalar sNext = EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2); | ||||
| 	if (sNext > 0.0f) | ||||
| 	{ | ||||
| 		return sNext; | ||||
| 	} | ||||
|  | ||||
| 	// Find the best edge and the search direction. | ||||
| 	int bestEdge; | ||||
| 	btScalar bestSeparation; | ||||
| 	int increment; | ||||
| 	if (sPrev > s && sPrev > sNext) | ||||
| 	{ | ||||
| 		increment = -1; | ||||
| 		bestEdge = prevEdge; | ||||
| 		bestSeparation = sPrev; | ||||
| 	} | ||||
| 	else if (sNext > s) | ||||
| 	{ | ||||
| 		increment = 1; | ||||
| 		bestEdge = nextEdge; | ||||
| 		bestSeparation = sNext; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		*edgeIndex = edge; | ||||
| 		return s; | ||||
| 	} | ||||
|  | ||||
| 	// Perform a local search for the best edge normal. | ||||
| 	for ( ; ; ) | ||||
| 	{ | ||||
| 		if (increment == -1) | ||||
| 			edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1; | ||||
| 		else | ||||
| 			edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0; | ||||
|  | ||||
| 		s = EdgeSeparation(poly1, xf1, edge, poly2, xf2); | ||||
| 		if (s > 0.0f) | ||||
| 		{ | ||||
| 			return s; | ||||
| 		} | ||||
|  | ||||
| 		if (s > bestSeparation) | ||||
| 		{ | ||||
| 			bestEdge = edge; | ||||
| 			bestSeparation = s; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	*edgeIndex = bestEdge; | ||||
| 	return bestSeparation; | ||||
| } | ||||
|  | ||||
| static void FindIncidentEdge(ClipVertex c[2], | ||||
| 							 const btBox2dShape* poly1, const btTransform& xf1, int edge1, | ||||
| 							 const btBox2dShape* poly2, const btTransform& xf2) | ||||
| { | ||||
| 	const btVector3* normals1 = poly1->getNormals(); | ||||
|  | ||||
| 	int count2 = poly2->getVertexCount(); | ||||
| 	const btVector3* vertices2 = poly2->getVertices(); | ||||
| 	const btVector3* normals2 = poly2->getNormals(); | ||||
|  | ||||
| 	btAssert(0 <= edge1 && edge1 < poly1->getVertexCount()); | ||||
|  | ||||
| 	// Get the normal of the reference edge in poly2's frame. | ||||
| 	btVector3 normal1 = b2MulT(xf2.getBasis(), b2Mul(xf1.getBasis(), normals1[edge1])); | ||||
|  | ||||
| 	// Find the incident edge on poly2. | ||||
| 	int index = 0; | ||||
| 	btScalar minDot = BT_LARGE_FLOAT; | ||||
| 	for (int i = 0; i < count2; ++i) | ||||
| 	{ | ||||
| 		btScalar dot = b2Dot(normal1, normals2[i]); | ||||
| 		if (dot < minDot) | ||||
| 		{ | ||||
| 			minDot = dot; | ||||
| 			index = i; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Build the clip vertices for the incident edge. | ||||
| 	int i1 = index; | ||||
| 	int i2 = i1 + 1 < count2 ? i1 + 1 : 0; | ||||
|  | ||||
| 	c[0].v = b2Mul(xf2, vertices2[i1]); | ||||
| //	c[0].id.features.referenceEdge = (unsigned char)edge1; | ||||
| //	c[0].id.features.incidentEdge = (unsigned char)i1; | ||||
| //	c[0].id.features.incidentVertex = 0; | ||||
|  | ||||
| 	c[1].v = b2Mul(xf2, vertices2[i2]); | ||||
| //	c[1].id.features.referenceEdge = (unsigned char)edge1; | ||||
| //	c[1].id.features.incidentEdge = (unsigned char)i2; | ||||
| //	c[1].id.features.incidentVertex = 1; | ||||
| } | ||||
|  | ||||
| // Find edge normal of max separation on A - return if separating axis is found | ||||
| // Find edge normal of max separation on B - return if separation axis is found | ||||
| // Choose reference edge as min(minA, minB) | ||||
| // Find incident edge | ||||
| // Clip | ||||
|  | ||||
| // The normal points from 1 to 2 | ||||
| void b2CollidePolygons(btManifoldResult* manifold, | ||||
| 					  const btBox2dShape* polyA, const btTransform& xfA, | ||||
| 					  const btBox2dShape* polyB, const btTransform& xfB) | ||||
| { | ||||
|  | ||||
| 	int edgeA = 0; | ||||
| 	btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB); | ||||
| 	if (separationA > 0.0f) | ||||
| 		return; | ||||
|  | ||||
| 	int edgeB = 0; | ||||
| 	btScalar separationB = FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA); | ||||
| 	if (separationB > 0.0f) | ||||
| 		return; | ||||
|  | ||||
| 	const btBox2dShape* poly1;	// reference poly | ||||
| 	const btBox2dShape* poly2;	// incident poly | ||||
| 	btTransform xf1, xf2; | ||||
| 	int edge1;		// reference edge | ||||
| 	unsigned char flip; | ||||
| 	const btScalar k_relativeTol = 0.98f; | ||||
| 	const btScalar k_absoluteTol = 0.001f; | ||||
|  | ||||
| 	// TODO_ERIN use "radius" of poly for absolute tolerance. | ||||
| 	if (separationB > k_relativeTol * separationA + k_absoluteTol) | ||||
| 	{ | ||||
| 		poly1 = polyB; | ||||
| 		poly2 = polyA; | ||||
| 		xf1 = xfB; | ||||
| 		xf2 = xfA; | ||||
| 		edge1 = edgeB; | ||||
| 		flip = 1; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		poly1 = polyA; | ||||
| 		poly2 = polyB; | ||||
| 		xf1 = xfA; | ||||
| 		xf2 = xfB; | ||||
| 		edge1 = edgeA; | ||||
| 		flip = 0; | ||||
| 	} | ||||
|  | ||||
| 	ClipVertex incidentEdge[2]; | ||||
| 	FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2); | ||||
|  | ||||
| 	int count1 = poly1->getVertexCount(); | ||||
| 	const btVector3* vertices1 = poly1->getVertices(); | ||||
|  | ||||
| 	btVector3 v11 = vertices1[edge1]; | ||||
| 	btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0]; | ||||
|  | ||||
| 	btVector3 dv = v12 - v11; | ||||
| 	btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11); | ||||
| 	sideNormal.normalize(); | ||||
| 	btVector3 frontNormal = btCrossS(sideNormal, 1.0f); | ||||
| 	 | ||||
| 	 | ||||
| 	v11 = b2Mul(xf1, v11); | ||||
| 	v12 = b2Mul(xf1, v12); | ||||
|  | ||||
| 	btScalar frontOffset = b2Dot(frontNormal, v11); | ||||
| 	btScalar sideOffset1 = -b2Dot(sideNormal, v11); | ||||
| 	btScalar sideOffset2 = b2Dot(sideNormal, v12); | ||||
|  | ||||
| 	// Clip incident edge against extruded edge1 side edges. | ||||
| 	ClipVertex clipPoints1[2]; | ||||
| 	clipPoints1[0].v.setValue(0,0,0); | ||||
| 	clipPoints1[1].v.setValue(0,0,0); | ||||
|  | ||||
| 	ClipVertex clipPoints2[2]; | ||||
| 	clipPoints2[0].v.setValue(0,0,0); | ||||
| 	clipPoints2[1].v.setValue(0,0,0); | ||||
|  | ||||
|  | ||||
| 	int np; | ||||
|  | ||||
| 	// Clip to box side 1 | ||||
| 	np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1); | ||||
|  | ||||
| 	if (np < 2) | ||||
| 		return; | ||||
|  | ||||
| 	// Clip to negative box side 1 | ||||
| 	np = ClipSegmentToLine(clipPoints2, clipPoints1,  sideNormal, sideOffset2); | ||||
|  | ||||
| 	if (np < 2) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	// Now clipPoints2 contains the clipped points. | ||||
| 	btVector3 manifoldNormal = flip ? -frontNormal : frontNormal; | ||||
|  | ||||
| 	int pointCount = 0; | ||||
| 	for (int i = 0; i < b2_maxManifoldPoints; ++i) | ||||
| 	{ | ||||
| 		btScalar separation = b2Dot(frontNormal, clipPoints2[i].v) - frontOffset; | ||||
|  | ||||
| 		if (separation <= 0.0f) | ||||
| 		{ | ||||
| 			 | ||||
| 			//b2ManifoldPoint* cp = manifold->points + pointCount; | ||||
| 			//btScalar separation = separation; | ||||
| 			//cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v); | ||||
| 			//cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v); | ||||
|  | ||||
| 			manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation); | ||||
|  | ||||
| //			cp->id = clipPoints2[i].id; | ||||
| //			cp->id.features.flip = flip; | ||||
| 			++pointCount; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| //	manifold->pointCount = pointCount;} | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BOX_2D_BOX_2D__COLLISION_ALGORITHM_H | ||||
| #define BOX_2D_BOX_2D__COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDispatcher.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | ||||
|  | ||||
| class btPersistentManifold; | ||||
|  | ||||
| ///box-box collision detection | ||||
| class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm | ||||
| { | ||||
| 	bool	m_ownManifold; | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
| 	 | ||||
| public: | ||||
| 	btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) | ||||
| 		: btActivatingCollisionAlgorithm(ci) {} | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); | ||||
|  | ||||
| 	virtual ~btBox2dBox2dCollisionAlgorithm(); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr && m_ownManifold) | ||||
| 		{ | ||||
| 			manifoldArray.push_back(m_manifoldPtr); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm); | ||||
| 			void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); | ||||
| 			return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0,body1); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BOX_2D_BOX_2D__COLLISION_ALGORITHM_H | ||||
|  | ||||
| @@ -0,0 +1,85 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btBoxBoxCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "BulletCollision/CollisionShapes/btBoxShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "btBoxBoxDetector.h" | ||||
|  | ||||
| #define USE_PERSISTENT_CONTACTS 1 | ||||
|  | ||||
| btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1) | ||||
| : btActivatingCollisionAlgorithm(ci,obj0,obj1), | ||||
| m_ownManifold(false), | ||||
| m_manifoldPtr(mf) | ||||
| { | ||||
| 	if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1)) | ||||
| 	{ | ||||
| 		m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1); | ||||
| 		m_ownManifold = true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm() | ||||
| { | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr) | ||||
| 			m_dispatcher->releaseManifold(m_manifoldPtr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	if (!m_manifoldPtr) | ||||
| 		return; | ||||
|  | ||||
| 	btCollisionObject*	col0 = body0; | ||||
| 	btCollisionObject*	col1 = body1; | ||||
| 	btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape(); | ||||
| 	btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape(); | ||||
|  | ||||
|  | ||||
|  | ||||
| 	/// report a contact. internally this will be kept persistent, and contact reduction is done | ||||
| 	resultOut->setPersistentManifold(m_manifoldPtr); | ||||
| #ifndef USE_PERSISTENT_CONTACTS	 | ||||
| 	m_manifoldPtr->clearManifold(); | ||||
| #endif //USE_PERSISTENT_CONTACTS | ||||
|  | ||||
| 	btDiscreteCollisionDetectorInterface::ClosestPointInput input; | ||||
| 	input.m_maximumDistanceSquared = BT_LARGE_FLOAT; | ||||
| 	input.m_transformA = body0->getWorldTransform(); | ||||
| 	input.m_transformB = body1->getWorldTransform(); | ||||
|  | ||||
| 	btBoxBoxDetector detector(box0,box1); | ||||
| 	detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); | ||||
|  | ||||
| #ifdef USE_PERSISTENT_CONTACTS | ||||
| 	//  refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		resultOut->refreshContactPoints(); | ||||
| 	} | ||||
| #endif //USE_PERSISTENT_CONTACTS | ||||
|  | ||||
| } | ||||
|  | ||||
| btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) | ||||
| { | ||||
| 	//not yet | ||||
| 	return 1.f; | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BOX_BOX__COLLISION_ALGORITHM_H | ||||
| #define BOX_BOX__COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDispatcher.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | ||||
|  | ||||
| class btPersistentManifold; | ||||
|  | ||||
| ///box-box collision detection | ||||
| class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm | ||||
| { | ||||
| 	bool	m_ownManifold; | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
| 	 | ||||
| public: | ||||
| 	btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) | ||||
| 		: btActivatingCollisionAlgorithm(ci) {} | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); | ||||
|  | ||||
| 	virtual ~btBoxBoxCollisionAlgorithm(); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr && m_ownManifold) | ||||
| 		{ | ||||
| 			manifoldArray.push_back(m_manifoldPtr); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			int bbsize = sizeof(btBoxBoxCollisionAlgorithm); | ||||
| 			void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); | ||||
| 			return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BOX_BOX__COLLISION_ALGORITHM_H | ||||
|  | ||||
| @@ -0,0 +1,718 @@ | ||||
| /* | ||||
|  * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith | ||||
|  * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. | ||||
|  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org | ||||
|  Bullet Continuous Collision Detection and Physics Library | ||||
|  Bullet is Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| ///ODE box-box collision detection is adapted to work with Bullet | ||||
|  | ||||
| #include "btBoxBoxDetector.h" | ||||
| #include "BulletCollision/CollisionShapes/btBoxShape.h" | ||||
|  | ||||
| #include <float.h> | ||||
| #include <string.h> | ||||
|  | ||||
| btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2) | ||||
| : m_box1(box1), | ||||
| m_box2(box2) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| // given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and | ||||
| // generate contact points. this returns 0 if there is no contact otherwise | ||||
| // it returns the number of contacts generated. | ||||
| // `normal' returns the contact normal. | ||||
| // `depth' returns the maximum penetration depth along that normal. | ||||
| // `return_code' returns a number indicating the type of contact that was | ||||
| // detected: | ||||
| //        1,2,3 = box 2 intersects with a face of box 1 | ||||
| //        4,5,6 = box 1 intersects with a face of box 2 | ||||
| //        7..15 = edge-edge contact | ||||
| // `maxc' is the maximum number of contacts allowed to be generated, i.e. | ||||
| // the size of the `contact' array. | ||||
| // `contact' and `skip' are the contact array information provided to the | ||||
| // collision functions. this function only fills in the position and depth | ||||
| // fields. | ||||
| struct dContactGeom; | ||||
| #define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)]) | ||||
| #define dInfinity FLT_MAX | ||||
|  | ||||
|  | ||||
| /*PURE_INLINE btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } | ||||
| PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); } | ||||
| PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); } | ||||
| PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); } | ||||
| */ | ||||
| static btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } | ||||
| static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); } | ||||
| static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); } | ||||
| static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); } | ||||
| #define dMULTIPLYOP1_331(A,op,B,C) \ | ||||
| {\ | ||||
|   (A)[0] op dDOT41((B),(C)); \ | ||||
|   (A)[1] op dDOT41((B+1),(C)); \ | ||||
|   (A)[2] op dDOT41((B+2),(C)); \ | ||||
| } | ||||
|  | ||||
| #define dMULTIPLYOP0_331(A,op,B,C) \ | ||||
| { \ | ||||
|   (A)[0] op dDOT((B),(C)); \ | ||||
|   (A)[1] op dDOT((B+4),(C)); \ | ||||
|   (A)[2] op dDOT((B+8),(C)); \ | ||||
| }  | ||||
|  | ||||
| #define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C) | ||||
| #define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C) | ||||
|  | ||||
| typedef btScalar dMatrix3[4*3]; | ||||
|  | ||||
| void dLineClosestApproach (const btVector3& pa, const btVector3& ua, | ||||
| 			   const btVector3& pb, const btVector3& ub, | ||||
| 			   btScalar *alpha, btScalar *beta); | ||||
| void dLineClosestApproach (const btVector3& pa, const btVector3& ua, | ||||
| 			   const btVector3& pb, const btVector3& ub, | ||||
| 			   btScalar *alpha, btScalar *beta) | ||||
| { | ||||
|   btVector3 p; | ||||
|   p[0] = pb[0] - pa[0]; | ||||
|   p[1] = pb[1] - pa[1]; | ||||
|   p[2] = pb[2] - pa[2]; | ||||
|   btScalar uaub = dDOT(ua,ub); | ||||
|   btScalar q1 =  dDOT(ua,p); | ||||
|   btScalar q2 = -dDOT(ub,p); | ||||
|   btScalar d = 1-uaub*uaub; | ||||
|   if (d <= btScalar(0.0001f)) { | ||||
|     // @@@ this needs to be made more robust | ||||
|     *alpha = 0; | ||||
|     *beta  = 0; | ||||
|   } | ||||
|   else { | ||||
|     d = 1.f/d; | ||||
|     *alpha = (q1 + uaub*q2)*d; | ||||
|     *beta  = (uaub*q1 + q2)*d; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| // find all the intersection points between the 2D rectangle with vertices | ||||
| // at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]), | ||||
| // (p[2],p[3]),(p[4],p[5]),(p[6],p[7]). | ||||
| // | ||||
| // the intersection points are returned as x,y pairs in the 'ret' array. | ||||
| // the number of intersection points is returned by the function (this will | ||||
| // be in the range 0 to 8). | ||||
|  | ||||
| static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16]) | ||||
| { | ||||
|   // q (and r) contain nq (and nr) coordinate points for the current (and | ||||
|   // chopped) polygons | ||||
|   int nq=4,nr=0; | ||||
|   btScalar buffer[16]; | ||||
|   btScalar *q = p; | ||||
|   btScalar *r = ret; | ||||
|   for (int dir=0; dir <= 1; dir++) { | ||||
|     // direction notation: xy[0] = x axis, xy[1] = y axis | ||||
|     for (int sign=-1; sign <= 1; sign += 2) { | ||||
|       // chop q along the line xy[dir] = sign*h[dir] | ||||
|       btScalar *pq = q; | ||||
|       btScalar *pr = r; | ||||
|       nr = 0; | ||||
|       for (int i=nq; i > 0; i--) { | ||||
| 	// go through all points in q and all lines between adjacent points | ||||
| 	if (sign*pq[dir] < h[dir]) { | ||||
| 	  // this point is inside the chopping line | ||||
| 	  pr[0] = pq[0]; | ||||
| 	  pr[1] = pq[1]; | ||||
| 	  pr += 2; | ||||
| 	  nr++; | ||||
| 	  if (nr & 8) { | ||||
| 	    q = r; | ||||
| 	    goto done; | ||||
| 	  } | ||||
| 	} | ||||
| 	btScalar *nextq = (i > 1) ? pq+2 : q; | ||||
| 	if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) { | ||||
| 	  // this line crosses the chopping line | ||||
| 	  pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) / | ||||
| 	    (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]); | ||||
| 	  pr[dir] = sign*h[dir]; | ||||
| 	  pr += 2; | ||||
| 	  nr++; | ||||
| 	  if (nr & 8) { | ||||
| 	    q = r; | ||||
| 	    goto done; | ||||
| 	  } | ||||
| 	} | ||||
| 	pq += 2; | ||||
|       } | ||||
|       q = r; | ||||
|       r = (q==ret) ? buffer : ret; | ||||
|       nq = nr; | ||||
|     } | ||||
|   } | ||||
|  done: | ||||
|   if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar)); | ||||
|   return nr; | ||||
| } | ||||
|  | ||||
|  | ||||
| #define M__PI 3.14159265f | ||||
|  | ||||
| // given n points in the plane (array p, of size 2*n), generate m points that | ||||
| // best represent the whole set. the definition of 'best' here is not | ||||
| // predetermined - the idea is to select points that give good box-box | ||||
| // collision detection behavior. the chosen point indexes are returned in the | ||||
| // array iret (of size m). 'i0' is always the first entry in the array. | ||||
| // n must be in the range [1..8]. m must be in the range [1..n]. i0 must be | ||||
| // in the range [0..n-1]. | ||||
|  | ||||
| void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]); | ||||
| void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) | ||||
| { | ||||
|   // compute the centroid of the polygon in cx,cy | ||||
|   int i,j; | ||||
|   btScalar a,cx,cy,q; | ||||
|   if (n==1) { | ||||
|     cx = p[0]; | ||||
|     cy = p[1]; | ||||
|   } | ||||
|   else if (n==2) { | ||||
|     cx = btScalar(0.5)*(p[0] + p[2]); | ||||
|     cy = btScalar(0.5)*(p[1] + p[3]); | ||||
|   } | ||||
|   else { | ||||
|     a = 0; | ||||
|     cx = 0; | ||||
|     cy = 0; | ||||
|     for (i=0; i<(n-1); i++) { | ||||
|       q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1]; | ||||
|       a += q; | ||||
|       cx += q*(p[i*2]+p[i*2+2]); | ||||
|       cy += q*(p[i*2+1]+p[i*2+3]); | ||||
|     } | ||||
|     q = p[n*2-2]*p[1] - p[0]*p[n*2-1]; | ||||
| 	if (btFabs(a+q) > SIMD_EPSILON) | ||||
| 	{ | ||||
| 		a = 1.f/(btScalar(3.0)*(a+q)); | ||||
| 	} else | ||||
| 	{ | ||||
| 		a=BT_LARGE_FLOAT; | ||||
| 	} | ||||
|     cx = a*(cx + q*(p[n*2-2]+p[0])); | ||||
|     cy = a*(cy + q*(p[n*2-1]+p[1])); | ||||
|   } | ||||
|  | ||||
|   // compute the angle of each point w.r.t. the centroid | ||||
|   btScalar A[8]; | ||||
|   for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx); | ||||
|  | ||||
|   // search for points that have angles closest to A[i0] + i*(2*pi/m). | ||||
|   int avail[8]; | ||||
|   for (i=0; i<n; i++) avail[i] = 1; | ||||
|   avail[i0] = 0; | ||||
|   iret[0] = i0; | ||||
|   iret++; | ||||
|   for (j=1; j<m; j++) { | ||||
|     a = btScalar(j)*(2*M__PI/m) + A[i0]; | ||||
|     if (a > M__PI) a -= 2*M__PI; | ||||
|     btScalar maxdiff=1e9,diff; | ||||
|  | ||||
|     *iret = i0;			// iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0 | ||||
|  | ||||
|     for (i=0; i<n; i++) { | ||||
|       if (avail[i]) { | ||||
| 	diff = btFabs (A[i]-a); | ||||
| 	if (diff > M__PI) diff = 2*M__PI - diff; | ||||
| 	if (diff < maxdiff) { | ||||
| 	  maxdiff = diff; | ||||
| 	  *iret = i; | ||||
| 	} | ||||
|       } | ||||
|     } | ||||
| #if defined(DEBUG) || defined (_DEBUG) | ||||
|     btAssert (*iret != i0);	// ensure iret got set | ||||
| #endif | ||||
|     avail[*iret] = 0; | ||||
|     iret++; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, | ||||
| 	     const btVector3& side1, const btVector3& p2, | ||||
| 	     const dMatrix3 R2, const btVector3& side2, | ||||
| 	     btVector3& normal, btScalar *depth, int *return_code, | ||||
| 		 int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output); | ||||
| int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, | ||||
| 	     const btVector3& side1, const btVector3& p2, | ||||
| 	     const dMatrix3 R2, const btVector3& side2, | ||||
| 	     btVector3& normal, btScalar *depth, int *return_code, | ||||
| 		 int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output) | ||||
| { | ||||
|   const btScalar fudge_factor = btScalar(1.05); | ||||
|   btVector3 p,pp,normalC(0.f,0.f,0.f); | ||||
|   const btScalar *normalR = 0; | ||||
|   btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33, | ||||
|     Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l; | ||||
|   int i,j,invert_normal,code; | ||||
|  | ||||
|   // get vector from centers of box 1 to box 2, relative to box 1 | ||||
|   p = p2 - p1; | ||||
|   dMULTIPLY1_331 (pp,R1,p);		// get pp = p relative to body 1 | ||||
|  | ||||
|   // get side lengths / 2 | ||||
|   A[0] = side1[0]*btScalar(0.5); | ||||
|   A[1] = side1[1]*btScalar(0.5); | ||||
|   A[2] = side1[2]*btScalar(0.5); | ||||
|   B[0] = side2[0]*btScalar(0.5); | ||||
|   B[1] = side2[1]*btScalar(0.5); | ||||
|   B[2] = side2[2]*btScalar(0.5); | ||||
|  | ||||
|   // Rij is R1'*R2, i.e. the relative rotation between R1 and R2 | ||||
|   R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2); | ||||
|   R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2); | ||||
|   R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2); | ||||
|  | ||||
|   Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13); | ||||
|   Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23); | ||||
|   Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33); | ||||
|  | ||||
|   // for all 15 possible separating axes: | ||||
|   //   * see if the axis separates the boxes. if so, return 0. | ||||
|   //   * find the depth of the penetration along the separating axis (s2) | ||||
|   //   * if this is the largest depth so far, record it. | ||||
|   // the normal vector will be set to the separating axis with the smallest | ||||
|   // depth. note: normalR is set to point to a column of R1 or R2 if that is | ||||
|   // the smallest depth normal so far. otherwise normalR is 0 and normalC is | ||||
|   // set to a vector relative to body 1. invert_normal is 1 if the sign of | ||||
|   // the normal should be flipped. | ||||
|  | ||||
| #define TST(expr1,expr2,norm,cc) \ | ||||
|   s2 = btFabs(expr1) - (expr2); \ | ||||
|   if (s2 > 0) return 0; \ | ||||
|   if (s2 > s) { \ | ||||
|     s = s2; \ | ||||
|     normalR = norm; \ | ||||
|     invert_normal = ((expr1) < 0); \ | ||||
|     code = (cc); \ | ||||
|   } | ||||
|  | ||||
|   s = -dInfinity; | ||||
|   invert_normal = 0; | ||||
|   code = 0; | ||||
|  | ||||
|   // separating axis = u1,u2,u3 | ||||
|   TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1); | ||||
|   TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2); | ||||
|   TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3); | ||||
|  | ||||
|   // separating axis = v1,v2,v3 | ||||
|   TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4); | ||||
|   TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5); | ||||
|   TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6); | ||||
|  | ||||
|   // note: cross product axes need to be scaled when s is computed. | ||||
|   // normal (n1,n2,n3) is relative to box 1. | ||||
| #undef TST | ||||
| #define TST(expr1,expr2,n1,n2,n3,cc) \ | ||||
|   s2 = btFabs(expr1) - (expr2); \ | ||||
|   if (s2 > SIMD_EPSILON) return 0; \ | ||||
|   l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \ | ||||
|   if (l > SIMD_EPSILON) { \ | ||||
|     s2 /= l; \ | ||||
|     if (s2*fudge_factor > s) { \ | ||||
|       s = s2; \ | ||||
|       normalR = 0; \ | ||||
|       normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \ | ||||
|       invert_normal = ((expr1) < 0); \ | ||||
|       code = (cc); \ | ||||
|     } \ | ||||
|   } | ||||
|  | ||||
|   btScalar fudge2 (1.0e-5f); | ||||
|  | ||||
|   Q11 += fudge2; | ||||
|   Q12 += fudge2; | ||||
|   Q13 += fudge2; | ||||
|  | ||||
|   Q21 += fudge2; | ||||
|   Q22 += fudge2; | ||||
|   Q23 += fudge2; | ||||
|  | ||||
|   Q31 += fudge2; | ||||
|   Q32 += fudge2; | ||||
|   Q33 += fudge2; | ||||
|  | ||||
|   // separating axis = u1 x (v1,v2,v3) | ||||
|   TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7); | ||||
|   TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8); | ||||
|   TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9); | ||||
|  | ||||
|   // separating axis = u2 x (v1,v2,v3) | ||||
|   TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10); | ||||
|   TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11); | ||||
|   TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12); | ||||
|  | ||||
|   // separating axis = u3 x (v1,v2,v3) | ||||
|   TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13); | ||||
|   TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14); | ||||
|   TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15); | ||||
|  | ||||
| #undef TST | ||||
|  | ||||
|   if (!code) return 0; | ||||
|  | ||||
|   // if we get to this point, the boxes interpenetrate. compute the normal | ||||
|   // in global coordinates. | ||||
|   if (normalR) { | ||||
|     normal[0] = normalR[0]; | ||||
|     normal[1] = normalR[4]; | ||||
|     normal[2] = normalR[8]; | ||||
|   } | ||||
|   else { | ||||
|     dMULTIPLY0_331 (normal,R1,normalC); | ||||
|   } | ||||
|   if (invert_normal) { | ||||
|     normal[0] = -normal[0]; | ||||
|     normal[1] = -normal[1]; | ||||
|     normal[2] = -normal[2]; | ||||
|   } | ||||
|   *depth = -s; | ||||
|  | ||||
|   // compute contact point(s) | ||||
|  | ||||
|   if (code > 6) { | ||||
|     // an edge from box 1 touches an edge from box 2. | ||||
|     // find a point pa on the intersecting edge of box 1 | ||||
|     btVector3 pa; | ||||
|     btScalar sign; | ||||
|     for (i=0; i<3; i++) pa[i] = p1[i]; | ||||
|     for (j=0; j<3; j++) { | ||||
|       sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0); | ||||
|       for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j]; | ||||
|     } | ||||
|  | ||||
|     // find a point pb on the intersecting edge of box 2 | ||||
|     btVector3 pb; | ||||
|     for (i=0; i<3; i++) pb[i] = p2[i]; | ||||
|     for (j=0; j<3; j++) { | ||||
|       sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0); | ||||
|       for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j]; | ||||
|     } | ||||
|  | ||||
|     btScalar alpha,beta; | ||||
|     btVector3 ua,ub; | ||||
|     for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4]; | ||||
|     for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4]; | ||||
|  | ||||
|     dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta); | ||||
|     for (i=0; i<3; i++) pa[i] += ua[i]*alpha; | ||||
|     for (i=0; i<3; i++) pb[i] += ub[i]*beta; | ||||
|  | ||||
| 	{ | ||||
| 		 | ||||
| 		//contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]); | ||||
| 		//contact[0].depth = *depth; | ||||
| 		btVector3 pointInWorld; | ||||
|  | ||||
| #ifdef USE_CENTER_POINT | ||||
| 	    for (i=0; i<3; i++)  | ||||
| 			pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5); | ||||
| 		output.addContactPoint(-normal,pointInWorld,-*depth); | ||||
| #else | ||||
| 		output.addContactPoint(-normal,pb,-*depth); | ||||
|  | ||||
| #endif // | ||||
| 		*return_code = code; | ||||
| 	} | ||||
|     return 1; | ||||
|   } | ||||
|  | ||||
|   // okay, we have a face-something intersection (because the separating | ||||
|   // axis is perpendicular to a face). define face 'a' to be the reference | ||||
|   // face (i.e. the normal vector is perpendicular to this) and face 'b' to be | ||||
|   // the incident face (the closest face of the other box). | ||||
|  | ||||
|   const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb; | ||||
|   if (code <= 3) { | ||||
|     Ra = R1; | ||||
|     Rb = R2; | ||||
|     pa = p1; | ||||
|     pb = p2; | ||||
|     Sa = A; | ||||
|     Sb = B; | ||||
|   } | ||||
|   else { | ||||
|     Ra = R2; | ||||
|     Rb = R1; | ||||
|     pa = p2; | ||||
|     pb = p1; | ||||
|     Sa = B; | ||||
|     Sb = A; | ||||
|   } | ||||
|  | ||||
|   // nr = normal vector of reference face dotted with axes of incident box. | ||||
|   // anr = absolute values of nr. | ||||
|   btVector3 normal2,nr,anr; | ||||
|   if (code <= 3) { | ||||
|     normal2[0] = normal[0]; | ||||
|     normal2[1] = normal[1]; | ||||
|     normal2[2] = normal[2]; | ||||
|   } | ||||
|   else { | ||||
|     normal2[0] = -normal[0]; | ||||
|     normal2[1] = -normal[1]; | ||||
|     normal2[2] = -normal[2]; | ||||
|   } | ||||
|   dMULTIPLY1_331 (nr,Rb,normal2); | ||||
|   anr[0] = btFabs (nr[0]); | ||||
|   anr[1] = btFabs (nr[1]); | ||||
|   anr[2] = btFabs (nr[2]); | ||||
|  | ||||
|   // find the largest compontent of anr: this corresponds to the normal | ||||
|   // for the indident face. the other axis numbers of the indicent face | ||||
|   // are stored in a1,a2. | ||||
|   int lanr,a1,a2; | ||||
|   if (anr[1] > anr[0]) { | ||||
|     if (anr[1] > anr[2]) { | ||||
|       a1 = 0; | ||||
|       lanr = 1; | ||||
|       a2 = 2; | ||||
|     } | ||||
|     else { | ||||
|       a1 = 0; | ||||
|       a2 = 1; | ||||
|       lanr = 2; | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     if (anr[0] > anr[2]) { | ||||
|       lanr = 0; | ||||
|       a1 = 1; | ||||
|       a2 = 2; | ||||
|     } | ||||
|     else { | ||||
|       a1 = 0; | ||||
|       a2 = 1; | ||||
|       lanr = 2; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // compute center point of incident face, in reference-face coordinates | ||||
|   btVector3 center; | ||||
|   if (nr[lanr] < 0) { | ||||
|     for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr]; | ||||
|   } | ||||
|   else { | ||||
|     for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr]; | ||||
|   } | ||||
|  | ||||
|   // find the normal and non-normal axis numbers of the reference box | ||||
|   int codeN,code1,code2; | ||||
|   if (code <= 3) codeN = code-1; else codeN = code-4; | ||||
|   if (codeN==0) { | ||||
|     code1 = 1; | ||||
|     code2 = 2; | ||||
|   } | ||||
|   else if (codeN==1) { | ||||
|     code1 = 0; | ||||
|     code2 = 2; | ||||
|   } | ||||
|   else { | ||||
|     code1 = 0; | ||||
|     code2 = 1; | ||||
|   } | ||||
|  | ||||
|   // find the four corners of the incident face, in reference-face coordinates | ||||
|   btScalar quad[8];	// 2D coordinate of incident face (x,y pairs) | ||||
|   btScalar c1,c2,m11,m12,m21,m22; | ||||
|   c1 = dDOT14 (center,Ra+code1); | ||||
|   c2 = dDOT14 (center,Ra+code2); | ||||
|   // optimize this? - we have already computed this data above, but it is not | ||||
|   // stored in an easy-to-index format. for now it's quicker just to recompute | ||||
|   // the four dot products. | ||||
|   m11 = dDOT44 (Ra+code1,Rb+a1); | ||||
|   m12 = dDOT44 (Ra+code1,Rb+a2); | ||||
|   m21 = dDOT44 (Ra+code2,Rb+a1); | ||||
|   m22 = dDOT44 (Ra+code2,Rb+a2); | ||||
|   { | ||||
|     btScalar k1 = m11*Sb[a1]; | ||||
|     btScalar k2 = m21*Sb[a1]; | ||||
|     btScalar k3 = m12*Sb[a2]; | ||||
|     btScalar k4 = m22*Sb[a2]; | ||||
|     quad[0] = c1 - k1 - k3; | ||||
|     quad[1] = c2 - k2 - k4; | ||||
|     quad[2] = c1 - k1 + k3; | ||||
|     quad[3] = c2 - k2 + k4; | ||||
|     quad[4] = c1 + k1 + k3; | ||||
|     quad[5] = c2 + k2 + k4; | ||||
|     quad[6] = c1 + k1 - k3; | ||||
|     quad[7] = c2 + k2 - k4; | ||||
|   } | ||||
|  | ||||
|   // find the size of the reference face | ||||
|   btScalar rect[2]; | ||||
|   rect[0] = Sa[code1]; | ||||
|   rect[1] = Sa[code2]; | ||||
|  | ||||
|   // intersect the incident and reference faces | ||||
|   btScalar ret[16]; | ||||
|   int n = intersectRectQuad2 (rect,quad,ret); | ||||
|   if (n < 1) return 0;		// this should never happen | ||||
|  | ||||
|   // convert the intersection points into reference-face coordinates, | ||||
|   // and compute the contact position and depth for each point. only keep | ||||
|   // those points that have a positive (penetrating) depth. delete points in | ||||
|   // the 'ret' array as necessary so that 'point' and 'ret' correspond. | ||||
|   btScalar point[3*8];		// penetrating contact points | ||||
|   btScalar dep[8];			// depths for those points | ||||
|   btScalar det1 = 1.f/(m11*m22 - m12*m21); | ||||
|   m11 *= det1; | ||||
|   m12 *= det1; | ||||
|   m21 *= det1; | ||||
|   m22 *= det1; | ||||
|   int cnum = 0;			// number of penetrating contact points found | ||||
|   for (j=0; j < n; j++) { | ||||
|     btScalar k1 =  m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2); | ||||
|     btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2); | ||||
|     for (i=0; i<3; i++) point[cnum*3+i] = | ||||
| 			  center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2]; | ||||
|     dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3); | ||||
|     if (dep[cnum] >= 0) { | ||||
|       ret[cnum*2] = ret[j*2]; | ||||
|       ret[cnum*2+1] = ret[j*2+1]; | ||||
|       cnum++; | ||||
|     } | ||||
|   } | ||||
|   if (cnum < 1) return 0;	// this should never happen | ||||
|  | ||||
|   // we can't generate more contacts than we actually have | ||||
|   if (maxc > cnum) maxc = cnum; | ||||
|   if (maxc < 1) maxc = 1; | ||||
|  | ||||
|   if (cnum <= maxc) { | ||||
|  | ||||
| 	  if (code<4)  | ||||
| 	  { | ||||
|     // we have less contacts than we need, so we use them all | ||||
|     for (j=0; j < cnum; j++)  | ||||
| 	{ | ||||
| 		btVector3 pointInWorld; | ||||
| 		for (i=0; i<3; i++)  | ||||
| 			pointInWorld[i] = point[j*3+i] + pa[i]; | ||||
| 		output.addContactPoint(-normal,pointInWorld,-dep[j]); | ||||
|  | ||||
|     } | ||||
| 	  } else | ||||
| 	  { | ||||
| 		  // we have less contacts than we need, so we use them all | ||||
| 		for (j=0; j < cnum; j++)  | ||||
| 		{ | ||||
| 			btVector3 pointInWorld; | ||||
| 			for (i=0; i<3; i++)  | ||||
| 				pointInWorld[i] = point[j*3+i] + pa[i]-normal[i]*dep[j]; | ||||
| 				//pointInWorld[i] = point[j*3+i] + pa[i]; | ||||
| 			output.addContactPoint(-normal,pointInWorld,-dep[j]); | ||||
| 		} | ||||
| 	  } | ||||
|   } | ||||
|   else { | ||||
|     // we have more contacts than are wanted, some of them must be culled. | ||||
|     // find the deepest point, it is always the first contact. | ||||
|     int i1 = 0; | ||||
|     btScalar maxdepth = dep[0]; | ||||
|     for (i=1; i<cnum; i++) { | ||||
|       if (dep[i] > maxdepth) { | ||||
| 	maxdepth = dep[i]; | ||||
| 	i1 = i; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     int iret[8]; | ||||
|     cullPoints2 (cnum,ret,maxc,i1,iret); | ||||
|  | ||||
|     for (j=0; j < maxc; j++) { | ||||
| //      dContactGeom *con = CONTACT(contact,skip*j); | ||||
|   //    for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i]; | ||||
|     //  con->depth = dep[iret[j]]; | ||||
|  | ||||
| 		btVector3 posInWorld; | ||||
| 		for (i=0; i<3; i++)  | ||||
| 			posInWorld[i] = point[iret[j]*3+i] + pa[i]; | ||||
| 		if (code<4)  | ||||
| 	   { | ||||
| 			output.addContactPoint(-normal,posInWorld,-dep[iret[j]]); | ||||
| 		} else | ||||
| 		{ | ||||
| 			output.addContactPoint(-normal,posInWorld-normal*dep[iret[j]],-dep[iret[j]]); | ||||
| 		} | ||||
|     } | ||||
|     cnum = maxc; | ||||
|   } | ||||
|  | ||||
|   *return_code = code; | ||||
|   return cnum; | ||||
| } | ||||
|  | ||||
| void	btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/) | ||||
| { | ||||
| 	 | ||||
| 	const btTransform& transformA = input.m_transformA; | ||||
| 	const btTransform& transformB = input.m_transformB; | ||||
| 	 | ||||
| 	int skip = 0; | ||||
| 	dContactGeom *contact = 0; | ||||
|  | ||||
| 	dMatrix3 R1; | ||||
| 	dMatrix3 R2; | ||||
|  | ||||
| 	for (int j=0;j<3;j++) | ||||
| 	{ | ||||
| 		R1[0+4*j] = transformA.getBasis()[j].x(); | ||||
| 		R2[0+4*j] = transformB.getBasis()[j].x(); | ||||
|  | ||||
| 		R1[1+4*j] = transformA.getBasis()[j].y(); | ||||
| 		R2[1+4*j] = transformB.getBasis()[j].y(); | ||||
|  | ||||
|  | ||||
| 		R1[2+4*j] = transformA.getBasis()[j].z(); | ||||
| 		R2[2+4*j] = transformB.getBasis()[j].z(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	btVector3 normal; | ||||
| 	btScalar depth; | ||||
| 	int return_code; | ||||
| 	int maxc = 4; | ||||
|  | ||||
|  | ||||
| 	dBoxBox2 (transformA.getOrigin(),  | ||||
| 	R1, | ||||
| 	2.f*m_box1->getHalfExtentsWithMargin(), | ||||
| 	transformB.getOrigin(), | ||||
| 	R2,  | ||||
| 	2.f*m_box2->getHalfExtentsWithMargin(), | ||||
| 	normal, &depth, &return_code, | ||||
| 	maxc, contact, skip, | ||||
| 	output | ||||
| 	); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,44 @@ | ||||
| /* | ||||
|  * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith | ||||
|  * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. | ||||
|  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org | ||||
|  | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
| #ifndef BOX_BOX_DETECTOR_H | ||||
| #define BOX_BOX_DETECTOR_H | ||||
|  | ||||
|  | ||||
| class btBoxShape; | ||||
| #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" | ||||
|  | ||||
|  | ||||
| /// btBoxBoxDetector wraps the ODE box-box collision detector | ||||
| /// re-distributed under the Zlib license with permission from Russell L. Smith | ||||
| struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface | ||||
| { | ||||
| 	btBoxShape* m_box1; | ||||
| 	btBoxShape* m_box2; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2); | ||||
|  | ||||
| 	virtual ~btBoxBoxDetector() {}; | ||||
|  | ||||
| 	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BT_BOX_BOX_DETECTOR_H | ||||
| @@ -0,0 +1,47 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BT_COLLISION_CONFIGURATION | ||||
| #define BT_COLLISION_CONFIGURATION | ||||
| struct btCollisionAlgorithmCreateFunc; | ||||
|  | ||||
| class btStackAlloc; | ||||
| class btPoolAllocator; | ||||
|  | ||||
| ///btCollisionConfiguration allows to configure Bullet collision detection | ||||
| ///stack allocator size, default collision algorithms and persistent manifold pool size | ||||
| ///@todo: describe the meaning | ||||
| class	btCollisionConfiguration | ||||
| { | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	virtual ~btCollisionConfiguration() | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	///memory pools | ||||
| 	virtual btPoolAllocator* getPersistentManifoldPool() = 0; | ||||
|  | ||||
| 	virtual btPoolAllocator* getCollisionAlgorithmPool() = 0; | ||||
|  | ||||
| 	virtual btStackAlloc*	getStackAllocator() = 0; | ||||
|  | ||||
| 	virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BT_COLLISION_CONFIGURATION | ||||
|  | ||||
| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_CREATE_FUNC | ||||
| #define COLLISION_CREATE_FUNC | ||||
|  | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
| class btCollisionAlgorithm; | ||||
| class btCollisionObject; | ||||
|  | ||||
| struct btCollisionAlgorithmConstructionInfo; | ||||
|  | ||||
| ///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm | ||||
| struct btCollisionAlgorithmCreateFunc | ||||
| { | ||||
| 	bool m_swapped; | ||||
| 	 | ||||
| 	btCollisionAlgorithmCreateFunc() | ||||
| 		:m_swapped(false) | ||||
| 	{ | ||||
| 	} | ||||
| 	virtual ~btCollisionAlgorithmCreateFunc(){}; | ||||
|  | ||||
| 	virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , btCollisionObject* body0,btCollisionObject* body1) | ||||
| 	{ | ||||
| 		 | ||||
| 		(void)body0; | ||||
| 		(void)body1; | ||||
| 		return 0; | ||||
| 	} | ||||
| }; | ||||
| #endif //COLLISION_CREATE_FUNC | ||||
|  | ||||
| @@ -0,0 +1,303 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
|  | ||||
| #include "btCollisionDispatcher.h" | ||||
|  | ||||
|  | ||||
| #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" | ||||
|  | ||||
| #include "BulletCollision/CollisionShapes/btCollisionShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" | ||||
| #include "LinearMath/btPoolAllocator.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" | ||||
|  | ||||
| int gNumManifold = 0; | ||||
|  | ||||
| #ifdef BT_DEBUG | ||||
| #include <stdio.h> | ||||
| #endif | ||||
|  | ||||
|  | ||||
| btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):  | ||||
| m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD), | ||||
| 	m_collisionConfiguration(collisionConfiguration) | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| 	setNearCallback(defaultNearCallback); | ||||
| 	 | ||||
| 	m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool(); | ||||
|  | ||||
| 	m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); | ||||
|  | ||||
| 	for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++) | ||||
| 	{ | ||||
| 		for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++) | ||||
| 		{ | ||||
| 			m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j); | ||||
| 			btAssert(m_doubleDispatch[i][j]); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| } | ||||
|  | ||||
|  | ||||
| void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) | ||||
| { | ||||
| 	m_doubleDispatch[proxyType0][proxyType1] = createFunc; | ||||
| } | ||||
|  | ||||
| btCollisionDispatcher::~btCollisionDispatcher() | ||||
| { | ||||
| } | ||||
|  | ||||
| btPersistentManifold*	btCollisionDispatcher::getNewManifold(void* b0,void* b1)  | ||||
| {  | ||||
| 	gNumManifold++; | ||||
| 	 | ||||
| 	//btAssert(gNumManifold < 65535); | ||||
| 	 | ||||
|  | ||||
| 	btCollisionObject* body0 = (btCollisionObject*)b0; | ||||
| 	btCollisionObject* body1 = (btCollisionObject*)b1; | ||||
|  | ||||
| 	//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance) | ||||
| 	 | ||||
| 	btScalar contactBreakingThreshold =  (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ?  | ||||
| 		btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold)) | ||||
| 		: gContactBreakingThreshold ; | ||||
|  | ||||
| 	btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold()); | ||||
| 		 | ||||
| 	void* mem = 0; | ||||
| 	 | ||||
| 	if (m_persistentManifoldPoolAllocator->getFreeCount()) | ||||
| 	{ | ||||
| 		mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); | ||||
| 	} else | ||||
| 	{ | ||||
| 		mem = btAlignedAlloc(sizeof(btPersistentManifold),16); | ||||
|  | ||||
| 	} | ||||
| 	btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold); | ||||
| 	manifold->m_index1a = m_manifoldsPtr.size(); | ||||
| 	m_manifoldsPtr.push_back(manifold); | ||||
|  | ||||
| 	return manifold; | ||||
| } | ||||
|  | ||||
| void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold) | ||||
| { | ||||
| 	manifold->clearManifold(); | ||||
| } | ||||
|  | ||||
| 	 | ||||
| void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) | ||||
| { | ||||
| 	 | ||||
| 	gNumManifold--; | ||||
|  | ||||
| 	//printf("releaseManifold: gNumManifold %d\n",gNumManifold); | ||||
| 	clearManifold(manifold); | ||||
|  | ||||
| 	int findIndex = manifold->m_index1a; | ||||
| 	btAssert(findIndex < m_manifoldsPtr.size()); | ||||
| 	m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); | ||||
| 	m_manifoldsPtr[findIndex]->m_index1a = findIndex; | ||||
| 	m_manifoldsPtr.pop_back(); | ||||
|  | ||||
| 	manifold->~btPersistentManifold(); | ||||
| 	if (m_persistentManifoldPoolAllocator->validPtr(manifold)) | ||||
| 	{ | ||||
| 		m_persistentManifoldPoolAllocator->freeMemory(manifold); | ||||
| 	} else | ||||
| 	{ | ||||
| 		btAlignedFree(manifold); | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
|  | ||||
| 	 | ||||
|  | ||||
| btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) | ||||
| { | ||||
| 	 | ||||
| 	btCollisionAlgorithmConstructionInfo ci; | ||||
|  | ||||
| 	ci.m_dispatcher1 = this; | ||||
| 	ci.m_manifold = sharedManifold; | ||||
| 	btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1); | ||||
|  | ||||
| 	return algo; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| bool	btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) | ||||
| { | ||||
| 	//here you can do filtering | ||||
| 	bool hasResponse =  | ||||
| 		(body0->hasContactResponse() && body1->hasContactResponse()); | ||||
| 	//no response between two static/kinematic bodies: | ||||
| 	hasResponse = hasResponse && | ||||
| 		((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject())); | ||||
| 	return hasResponse; | ||||
| } | ||||
|  | ||||
| bool	btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1) | ||||
| { | ||||
| 	btAssert(body0); | ||||
| 	btAssert(body1); | ||||
|  | ||||
| 	bool needsCollision = true; | ||||
|  | ||||
| #ifdef BT_DEBUG | ||||
| 	if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED)) | ||||
| 	{ | ||||
| 		//broadphase filtering already deals with this | ||||
| 		if ((body0->isStaticObject() || body0->isKinematicObject()) && | ||||
| 			(body1->isStaticObject() || body1->isKinematicObject())) | ||||
| 		{ | ||||
| 			m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED; | ||||
| 			printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); | ||||
| 		} | ||||
| 	} | ||||
| #endif //BT_DEBUG | ||||
|  | ||||
| 	if ((!body0->isActive()) && (!body1->isActive())) | ||||
| 		needsCollision = false; | ||||
| 	else if (!body0->checkCollideWith(body1)) | ||||
| 		needsCollision = false; | ||||
| 	 | ||||
| 	return needsCollision ; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| ///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc) | ||||
| ///this is useful for the collision dispatcher. | ||||
| class btCollisionPairCallback : public btOverlapCallback | ||||
| { | ||||
| 	const btDispatcherInfo& m_dispatchInfo; | ||||
| 	btCollisionDispatcher*	m_dispatcher; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher*	dispatcher) | ||||
| 	:m_dispatchInfo(dispatchInfo), | ||||
| 	m_dispatcher(dispatcher) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	/*btCollisionPairCallback& operator=(btCollisionPairCallback& other) | ||||
| 	{ | ||||
| 		m_dispatchInfo = other.m_dispatchInfo; | ||||
| 		m_dispatcher = other.m_dispatcher; | ||||
| 		return *this; | ||||
| 	} | ||||
| 	*/ | ||||
|  | ||||
|  | ||||
| 	virtual ~btCollisionPairCallback() {} | ||||
|  | ||||
|  | ||||
| 	virtual bool	processOverlap(btBroadphasePair& pair) | ||||
| 	{ | ||||
| 		(*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo); | ||||
|  | ||||
| 		return false; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)  | ||||
| { | ||||
| 	//m_blockedForChanges = true; | ||||
|  | ||||
| 	btCollisionPairCallback	collisionCallback(dispatchInfo,this); | ||||
|  | ||||
| 	pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); | ||||
|  | ||||
| 	//m_blockedForChanges = false; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| //by default, Bullet will use this near callback | ||||
| void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) | ||||
| { | ||||
| 		btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; | ||||
| 		btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; | ||||
|  | ||||
| 		if (dispatcher.needsCollision(colObj0,colObj1)) | ||||
| 		{ | ||||
| 			//dispatcher will keep algorithms persistent in the collision pair | ||||
| 			if (!collisionPair.m_algorithm) | ||||
| 			{ | ||||
| 				collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1); | ||||
| 			} | ||||
|  | ||||
| 			if (collisionPair.m_algorithm) | ||||
| 			{ | ||||
| 				btManifoldResult contactPointResult(colObj0,colObj1); | ||||
| 				 | ||||
| 				if (dispatchInfo.m_dispatchFunc == 		btDispatcherInfo::DISPATCH_DISCRETE) | ||||
| 				{ | ||||
| 					//discrete collision detection query | ||||
| 					collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); | ||||
| 				} else | ||||
| 				{ | ||||
| 					//continuous collision detection query, time of impact (toi) | ||||
| 					btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); | ||||
| 					if (dispatchInfo.m_timeOfImpact > toi) | ||||
| 						dispatchInfo.m_timeOfImpact = toi; | ||||
|  | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) | ||||
| { | ||||
| 	if (m_collisionAlgorithmPoolAllocator->getFreeCount()) | ||||
| 	{ | ||||
| 		return m_collisionAlgorithmPoolAllocator->allocate(size); | ||||
| 	} | ||||
| 	 | ||||
| 	//warn user for overflow? | ||||
| 	return	btAlignedAlloc(static_cast<size_t>(size), 16); | ||||
| } | ||||
|  | ||||
| void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) | ||||
| { | ||||
| 	if (m_collisionAlgorithmPoolAllocator->validPtr(ptr)) | ||||
| 	{ | ||||
| 		m_collisionAlgorithmPoolAllocator->freeMemory(ptr); | ||||
| 	} else | ||||
| 	{ | ||||
| 		btAlignedFree(ptr); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,159 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION__DISPATCHER_H | ||||
| #define COLLISION__DISPATCHER_H | ||||
|  | ||||
| #include "BulletCollision/BroadphaseCollision/btDispatcher.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" | ||||
|  | ||||
| #include "BulletCollision/CollisionDispatch/btManifoldResult.h" | ||||
|  | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
| class btIDebugDraw; | ||||
| class btOverlappingPairCache; | ||||
| class btPoolAllocator; | ||||
| class btCollisionConfiguration; | ||||
|  | ||||
| #include "btCollisionCreateFunc.h" | ||||
|  | ||||
| #define USE_DISPATCH_REGISTRY_ARRAY 1 | ||||
|  | ||||
| class btCollisionDispatcher; | ||||
| ///user can override this nearcallback for collision filtering and more finegrained control over collision detection | ||||
| typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); | ||||
|  | ||||
|  | ||||
| ///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. | ||||
| ///Time of Impact, Closest Points and Penetration Depth. | ||||
| class btCollisionDispatcher : public btDispatcher | ||||
| { | ||||
| 	int		m_dispatcherFlags; | ||||
| 	 | ||||
| 	btAlignedObjectArray<btPersistentManifold*>	m_manifoldsPtr; | ||||
|  | ||||
| 	btManifoldResult	m_defaultManifoldResult; | ||||
|  | ||||
| 	btNearCallback		m_nearCallback; | ||||
| 	 | ||||
| 	btPoolAllocator*	m_collisionAlgorithmPoolAllocator; | ||||
|  | ||||
| 	btPoolAllocator*	m_persistentManifoldPoolAllocator; | ||||
|  | ||||
| 	btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; | ||||
|  | ||||
| 	btCollisionConfiguration*	m_collisionConfiguration; | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	enum DispatcherFlags | ||||
| 	{ | ||||
| 		CD_STATIC_STATIC_REPORTED = 1, | ||||
| 		CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2 | ||||
| 	}; | ||||
|  | ||||
| 	int	getDispatcherFlags() const | ||||
| 	{ | ||||
| 		return m_dispatcherFlags; | ||||
| 	} | ||||
|  | ||||
| 	void	setDispatcherFlags(int flags) | ||||
| 	{ | ||||
|         (void) flags; | ||||
| 		m_dispatcherFlags = 0; | ||||
| 	} | ||||
|  | ||||
| 	///registerCollisionCreateFunc allows registration of custom/alternative collision create functions | ||||
| 	void	registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc); | ||||
|  | ||||
| 	int	getNumManifolds() const | ||||
| 	{  | ||||
| 		return int( m_manifoldsPtr.size()); | ||||
| 	} | ||||
|  | ||||
| 	btPersistentManifold**	getInternalManifoldPointer() | ||||
| 	{ | ||||
| 		return &m_manifoldsPtr[0]; | ||||
| 	} | ||||
|  | ||||
| 	 btPersistentManifold* getManifoldByIndexInternal(int index) | ||||
| 	{ | ||||
| 		return m_manifoldsPtr[index]; | ||||
| 	} | ||||
|  | ||||
| 	 const btPersistentManifold* getManifoldByIndexInternal(int index) const | ||||
| 	{ | ||||
| 		return m_manifoldsPtr[index]; | ||||
| 	} | ||||
|  | ||||
| 	btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration); | ||||
|  | ||||
| 	virtual ~btCollisionDispatcher(); | ||||
|  | ||||
| 	virtual btPersistentManifold*	getNewManifold(void* b0,void* b1); | ||||
| 	 | ||||
| 	virtual void releaseManifold(btPersistentManifold* manifold); | ||||
|  | ||||
|  | ||||
| 	virtual void clearManifold(btPersistentManifold* manifold); | ||||
|  | ||||
| 			 | ||||
| 	btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); | ||||
| 		 | ||||
| 	virtual bool	needsCollision(btCollisionObject* body0,btCollisionObject* body1); | ||||
| 	 | ||||
| 	virtual bool	needsResponse(btCollisionObject* body0,btCollisionObject* body1); | ||||
| 	 | ||||
| 	virtual void	dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; | ||||
|  | ||||
| 	void	setNearCallback(btNearCallback	nearCallback) | ||||
| 	{ | ||||
| 		m_nearCallback = nearCallback;  | ||||
| 	} | ||||
|  | ||||
| 	btNearCallback	getNearCallback() const | ||||
| 	{ | ||||
| 		return m_nearCallback; | ||||
| 	} | ||||
|  | ||||
| 	//by default, Bullet will use this near callback | ||||
| 	static void  defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); | ||||
|  | ||||
| 	virtual	void* allocateCollisionAlgorithm(int size); | ||||
|  | ||||
| 	virtual	void freeCollisionAlgorithm(void* ptr); | ||||
|  | ||||
| 	btCollisionConfiguration*	getCollisionConfiguration() | ||||
| 	{ | ||||
| 		return m_collisionConfiguration; | ||||
| 	} | ||||
|  | ||||
| 	const btCollisionConfiguration*	getCollisionConfiguration() const | ||||
| 	{ | ||||
| 		return m_collisionConfiguration; | ||||
| 	} | ||||
|  | ||||
| 	void	setCollisionConfiguration(btCollisionConfiguration* config) | ||||
| 	{ | ||||
| 		m_collisionConfiguration = config; | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //COLLISION__DISPATCHER_H | ||||
|  | ||||
| @@ -0,0 +1,116 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #include "btCollisionObject.h" | ||||
| #include "LinearMath/btSerializer.h" | ||||
|  | ||||
| btCollisionObject::btCollisionObject() | ||||
| 	:	m_anisotropicFriction(1.f,1.f,1.f), | ||||
| 	m_hasAnisotropicFriction(false), | ||||
| 	m_contactProcessingThreshold(BT_LARGE_FLOAT), | ||||
| 		m_broadphaseHandle(0), | ||||
| 		m_collisionShape(0), | ||||
| 		m_extensionPointer(0), | ||||
| 		m_rootCollisionShape(0), | ||||
| 		m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT), | ||||
| 		m_islandTag1(-1), | ||||
| 		m_companionId(-1), | ||||
| 		m_activationState1(1), | ||||
| 		m_deactivationTime(btScalar(0.)), | ||||
| 		m_friction(btScalar(0.5)), | ||||
| 		m_restitution(btScalar(0.)), | ||||
| 		m_internalType(CO_COLLISION_OBJECT), | ||||
| 		m_userObjectPointer(0), | ||||
| 		m_hitFraction(btScalar(1.)), | ||||
| 		m_ccdSweptSphereRadius(btScalar(0.)), | ||||
| 		m_ccdMotionThreshold(btScalar(0.)), | ||||
| 		m_checkCollideWith(false) | ||||
| { | ||||
| 	m_worldTransform.setIdentity(); | ||||
| } | ||||
|  | ||||
| btCollisionObject::~btCollisionObject() | ||||
| { | ||||
| } | ||||
|  | ||||
| void btCollisionObject::setActivationState(int newState)  | ||||
| {  | ||||
| 	if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION)) | ||||
| 		m_activationState1 = newState; | ||||
| } | ||||
|  | ||||
| void btCollisionObject::forceActivationState(int newState) | ||||
| { | ||||
| 	m_activationState1 = newState; | ||||
| } | ||||
|  | ||||
| void btCollisionObject::activate(bool forceActivation) | ||||
| { | ||||
| 	if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT))) | ||||
| 	{ | ||||
| 		setActivationState(ACTIVE_TAG); | ||||
| 		m_deactivationTime = btScalar(0.); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const | ||||
| { | ||||
|  | ||||
| 	btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer; | ||||
|  | ||||
| 	m_worldTransform.serialize(dataOut->m_worldTransform); | ||||
| 	m_interpolationWorldTransform.serialize(dataOut->m_interpolationWorldTransform); | ||||
| 	m_interpolationLinearVelocity.serialize(dataOut->m_interpolationLinearVelocity); | ||||
| 	m_interpolationAngularVelocity.serialize(dataOut->m_interpolationAngularVelocity); | ||||
| 	m_anisotropicFriction.serialize(dataOut->m_anisotropicFriction); | ||||
| 	dataOut->m_hasAnisotropicFriction = m_hasAnisotropicFriction; | ||||
| 	dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold; | ||||
| 	dataOut->m_broadphaseHandle = 0; | ||||
| 	dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape); | ||||
| 	dataOut->m_rootCollisionShape = 0;//@todo | ||||
| 	dataOut->m_collisionFlags = m_collisionFlags; | ||||
| 	dataOut->m_islandTag1 = m_islandTag1; | ||||
| 	dataOut->m_companionId = m_companionId; | ||||
| 	dataOut->m_activationState1 = m_activationState1; | ||||
| 	dataOut->m_activationState1 = m_activationState1; | ||||
| 	dataOut->m_deactivationTime = m_deactivationTime; | ||||
| 	dataOut->m_friction = m_friction; | ||||
| 	dataOut->m_restitution = m_restitution; | ||||
| 	dataOut->m_internalType = m_internalType; | ||||
| 	 | ||||
| 	char* name = (char*) serializer->findNameForPointer(this); | ||||
| 	dataOut->m_name = (char*)serializer->getUniquePointer(name); | ||||
| 	if (dataOut->m_name) | ||||
| 	{ | ||||
| 		serializer->serializeName(name); | ||||
| 	} | ||||
| 	dataOut->m_hitFraction = m_hitFraction; | ||||
| 	dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius; | ||||
| 	dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold; | ||||
| 	dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold; | ||||
| 	dataOut->m_checkCollideWith = m_checkCollideWith; | ||||
|  | ||||
| 	return btCollisionObjectDataName; | ||||
| } | ||||
|  | ||||
|  | ||||
| void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const | ||||
| { | ||||
| 	int len = calculateSerializeBufferSize(); | ||||
| 	btChunk* chunk = serializer->allocate(len,1); | ||||
| 	const char* structType = serialize(chunk->m_oldPtr, serializer); | ||||
| 	serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this); | ||||
| } | ||||
| @@ -0,0 +1,524 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_OBJECT_H | ||||
| #define COLLISION_OBJECT_H | ||||
|  | ||||
| #include "LinearMath/btTransform.h" | ||||
|  | ||||
| //island management, m_activationState1 | ||||
| #define ACTIVE_TAG 1 | ||||
| #define ISLAND_SLEEPING 2 | ||||
| #define WANTS_DEACTIVATION 3 | ||||
| #define DISABLE_DEACTIVATION 4 | ||||
| #define DISABLE_SIMULATION 5 | ||||
|  | ||||
| struct	btBroadphaseProxy; | ||||
| class	btCollisionShape; | ||||
| struct btCollisionShapeData; | ||||
| #include "LinearMath/btMotionState.h" | ||||
| #include "LinearMath/btAlignedAllocator.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
| typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray; | ||||
|  | ||||
| #ifdef BT_USE_DOUBLE_PRECISION | ||||
| #define btCollisionObjectData btCollisionObjectDoubleData | ||||
| #define btCollisionObjectDataName "btCollisionObjectDoubleData" | ||||
| #else | ||||
| #define btCollisionObjectData btCollisionObjectFloatData | ||||
| #define btCollisionObjectDataName "btCollisionObjectFloatData" | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /// btCollisionObject can be used to manage collision detection objects.  | ||||
| /// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy. | ||||
| /// They can be added to the btCollisionWorld. | ||||
| ATTRIBUTE_ALIGNED16(class)	btCollisionObject | ||||
| { | ||||
|  | ||||
| protected: | ||||
|  | ||||
| 	btTransform	m_worldTransform; | ||||
|  | ||||
| 	///m_interpolationWorldTransform is used for CCD and interpolation | ||||
| 	///it can be either previous or future (predicted) transform | ||||
| 	btTransform	m_interpolationWorldTransform; | ||||
| 	//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)  | ||||
| 	//without destroying the continuous interpolated motion (which uses this interpolation velocities) | ||||
| 	btVector3	m_interpolationLinearVelocity; | ||||
| 	btVector3	m_interpolationAngularVelocity; | ||||
| 	 | ||||
| 	btVector3	m_anisotropicFriction; | ||||
| 	int			m_hasAnisotropicFriction; | ||||
| 	btScalar	m_contactProcessingThreshold;	 | ||||
|  | ||||
| 	btBroadphaseProxy*		m_broadphaseHandle; | ||||
| 	btCollisionShape*		m_collisionShape; | ||||
| 	///m_extensionPointer is used by some internal low-level Bullet extensions. | ||||
| 	void*					m_extensionPointer; | ||||
| 	 | ||||
| 	///m_rootCollisionShape is temporarily used to store the original collision shape | ||||
| 	///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes | ||||
| 	///If it is NULL, the m_collisionShape is not temporarily replaced. | ||||
| 	btCollisionShape*		m_rootCollisionShape; | ||||
|  | ||||
| 	int				m_collisionFlags; | ||||
|  | ||||
| 	int				m_islandTag1; | ||||
| 	int				m_companionId; | ||||
|  | ||||
| 	int				m_activationState1; | ||||
| 	btScalar			m_deactivationTime; | ||||
|  | ||||
| 	btScalar		m_friction; | ||||
| 	btScalar		m_restitution; | ||||
|  | ||||
| 	///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc. | ||||
| 	///do not assign your own m_internalType unless you write a new dynamics object class. | ||||
| 	int				m_internalType; | ||||
|  | ||||
| 	///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer | ||||
| 	void*			m_userObjectPointer; | ||||
|  | ||||
| 	///time of impact calculation | ||||
| 	btScalar		m_hitFraction;  | ||||
| 	 | ||||
| 	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: | ||||
| 	btScalar		m_ccdSweptSphereRadius; | ||||
|  | ||||
| 	/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold | ||||
| 	btScalar		m_ccdMotionThreshold; | ||||
| 	 | ||||
| 	/// If some object should have elaborate collision filtering by sub-classes | ||||
| 	int			m_checkCollideWith; | ||||
|  | ||||
| 	virtual bool	checkCollideWithOverride(btCollisionObject* /* co */) | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	enum CollisionFlags | ||||
| 	{ | ||||
| 		CF_STATIC_OBJECT= 1, | ||||
| 		CF_KINEMATIC_OBJECT= 2, | ||||
| 		CF_NO_CONTACT_RESPONSE = 4, | ||||
| 		CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution) | ||||
| 		CF_CHARACTER_OBJECT = 16, | ||||
| 		CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing | ||||
| 		CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing | ||||
| 	}; | ||||
|  | ||||
| 	enum	CollisionObjectTypes | ||||
| 	{ | ||||
| 		CO_COLLISION_OBJECT =1, | ||||
| 		CO_RIGID_BODY=2, | ||||
| 		///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter | ||||
| 		///It is useful for collision sensors, explosion objects, character controller etc. | ||||
| 		CO_GHOST_OBJECT=4, | ||||
| 		CO_SOFT_BODY=8, | ||||
| 		CO_HF_FLUID=16, | ||||
| 		CO_USER_TYPE=32 | ||||
| 	}; | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool mergesSimulationIslands() const | ||||
| 	{ | ||||
| 		///static objects, kinematic and object without contact response don't merge islands | ||||
| 		return  ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); | ||||
| 	} | ||||
|  | ||||
| 	const btVector3& getAnisotropicFriction() const | ||||
| 	{ | ||||
| 		return m_anisotropicFriction; | ||||
| 	} | ||||
| 	void	setAnisotropicFriction(const btVector3& anisotropicFriction) | ||||
| 	{ | ||||
| 		m_anisotropicFriction = anisotropicFriction; | ||||
| 		m_hasAnisotropicFriction = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f); | ||||
| 	} | ||||
| 	bool	hasAnisotropicFriction() const | ||||
| 	{ | ||||
| 		return m_hasAnisotropicFriction!=0; | ||||
| 	} | ||||
|  | ||||
| 	///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default. | ||||
| 	///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 | ||||
| 	void	setContactProcessingThreshold( btScalar contactProcessingThreshold) | ||||
| 	{ | ||||
| 		m_contactProcessingThreshold = contactProcessingThreshold; | ||||
| 	} | ||||
| 	btScalar	getContactProcessingThreshold() const | ||||
| 	{ | ||||
| 		return m_contactProcessingThreshold; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool		isStaticObject() const { | ||||
| 		return (m_collisionFlags & CF_STATIC_OBJECT) != 0; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool		isKinematicObject() const | ||||
| 	{ | ||||
| 		return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool		isStaticOrKinematicObject() const | ||||
| 	{ | ||||
| 		return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool		hasContactResponse() const { | ||||
| 		return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	btCollisionObject(); | ||||
|  | ||||
| 	virtual ~btCollisionObject(); | ||||
|  | ||||
| 	virtual void	setCollisionShape(btCollisionShape* collisionShape) | ||||
| 	{ | ||||
| 		m_collisionShape = collisionShape; | ||||
| 		m_rootCollisionShape = collisionShape; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE const btCollisionShape*	getCollisionShape() const | ||||
| 	{ | ||||
| 		return m_collisionShape; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE btCollisionShape*	getCollisionShape() | ||||
| 	{ | ||||
| 		return m_collisionShape; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE const btCollisionShape*	getRootCollisionShape() const | ||||
| 	{ | ||||
| 		return m_rootCollisionShape; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE btCollisionShape*	getRootCollisionShape() | ||||
| 	{ | ||||
| 		return m_rootCollisionShape; | ||||
| 	} | ||||
|  | ||||
| 	///Avoid using this internal API call | ||||
| 	///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape. | ||||
| 	void	internalSetTemporaryCollisionShape(btCollisionShape* collisionShape) | ||||
| 	{ | ||||
| 		m_collisionShape = collisionShape; | ||||
| 	} | ||||
|  | ||||
| 	///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.  | ||||
| 	///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead. | ||||
| 	void*		internalGetExtensionPointer() const | ||||
| 	{ | ||||
| 		return m_extensionPointer; | ||||
| 	} | ||||
| 	///Avoid using this internal API call, the extension pointer is used by some Bullet extensions | ||||
| 	///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead. | ||||
| 	void	internalSetExtensionPointer(void* pointer) | ||||
| 	{ | ||||
| 		m_extensionPointer = pointer; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE	int	getActivationState() const { return m_activationState1;} | ||||
| 	 | ||||
| 	void setActivationState(int newState); | ||||
|  | ||||
| 	void	setDeactivationTime(btScalar time) | ||||
| 	{ | ||||
| 		m_deactivationTime = time; | ||||
| 	} | ||||
| 	btScalar	getDeactivationTime() const | ||||
| 	{ | ||||
| 		return m_deactivationTime; | ||||
| 	} | ||||
|  | ||||
| 	void forceActivationState(int newState); | ||||
|  | ||||
| 	void	activate(bool forceActivation = false); | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool isActive() const | ||||
| 	{ | ||||
| 		return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION)); | ||||
| 	} | ||||
|  | ||||
| 	void	setRestitution(btScalar rest) | ||||
| 	{ | ||||
| 		m_restitution = rest; | ||||
| 	} | ||||
| 	btScalar	getRestitution() const | ||||
| 	{ | ||||
| 		return m_restitution; | ||||
| 	} | ||||
| 	void	setFriction(btScalar frict) | ||||
| 	{ | ||||
| 		m_friction = frict; | ||||
| 	} | ||||
| 	btScalar	getFriction() const | ||||
| 	{ | ||||
| 		return m_friction; | ||||
| 	} | ||||
|  | ||||
| 	///reserved for Bullet internal usage | ||||
| 	int	getInternalType() const | ||||
| 	{ | ||||
| 		return m_internalType; | ||||
| 	} | ||||
|  | ||||
| 	btTransform&	getWorldTransform() | ||||
| 	{ | ||||
| 		return m_worldTransform; | ||||
| 	} | ||||
|  | ||||
| 	const btTransform&	getWorldTransform() const | ||||
| 	{ | ||||
| 		return m_worldTransform; | ||||
| 	} | ||||
|  | ||||
| 	void	setWorldTransform(const btTransform& worldTrans) | ||||
| 	{ | ||||
| 		m_worldTransform = worldTrans; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	SIMD_FORCE_INLINE btBroadphaseProxy*	getBroadphaseHandle() | ||||
| 	{ | ||||
| 		return m_broadphaseHandle; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE const btBroadphaseProxy*	getBroadphaseHandle() const | ||||
| 	{ | ||||
| 		return m_broadphaseHandle; | ||||
| 	} | ||||
|  | ||||
| 	void	setBroadphaseHandle(btBroadphaseProxy* handle) | ||||
| 	{ | ||||
| 		m_broadphaseHandle = handle; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	const btTransform&	getInterpolationWorldTransform() const | ||||
| 	{ | ||||
| 		return m_interpolationWorldTransform; | ||||
| 	} | ||||
|  | ||||
| 	btTransform&	getInterpolationWorldTransform() | ||||
| 	{ | ||||
| 		return m_interpolationWorldTransform; | ||||
| 	} | ||||
|  | ||||
| 	void	setInterpolationWorldTransform(const btTransform&	trans) | ||||
| 	{ | ||||
| 		m_interpolationWorldTransform = trans; | ||||
| 	} | ||||
|  | ||||
| 	void	setInterpolationLinearVelocity(const btVector3& linvel) | ||||
| 	{ | ||||
| 		m_interpolationLinearVelocity = linvel; | ||||
| 	} | ||||
|  | ||||
| 	void	setInterpolationAngularVelocity(const btVector3& angvel) | ||||
| 	{ | ||||
| 		m_interpolationAngularVelocity = angvel; | ||||
| 	} | ||||
|  | ||||
| 	const btVector3&	getInterpolationLinearVelocity() const | ||||
| 	{ | ||||
| 		return m_interpolationLinearVelocity; | ||||
| 	} | ||||
|  | ||||
| 	const btVector3&	getInterpolationAngularVelocity() const | ||||
| 	{ | ||||
| 		return m_interpolationAngularVelocity; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE int getIslandTag() const | ||||
| 	{ | ||||
| 		return	m_islandTag1; | ||||
| 	} | ||||
|  | ||||
| 	void	setIslandTag(int tag) | ||||
| 	{ | ||||
| 		m_islandTag1 = tag; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE int getCompanionId() const | ||||
| 	{ | ||||
| 		return	m_companionId; | ||||
| 	} | ||||
|  | ||||
| 	void	setCompanionId(int id) | ||||
| 	{ | ||||
| 		m_companionId = id; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE btScalar			getHitFraction() const | ||||
| 	{ | ||||
| 		return m_hitFraction;  | ||||
| 	} | ||||
|  | ||||
| 	void	setHitFraction(btScalar hitFraction) | ||||
| 	{ | ||||
| 		m_hitFraction = hitFraction; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	SIMD_FORCE_INLINE int	getCollisionFlags() const | ||||
| 	{ | ||||
| 		return m_collisionFlags; | ||||
| 	} | ||||
|  | ||||
| 	void	setCollisionFlags(int flags) | ||||
| 	{ | ||||
| 		m_collisionFlags = flags; | ||||
| 	} | ||||
| 	 | ||||
| 	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: | ||||
| 	btScalar			getCcdSweptSphereRadius() const | ||||
| 	{ | ||||
| 		return m_ccdSweptSphereRadius; | ||||
| 	} | ||||
|  | ||||
| 	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: | ||||
| 	void	setCcdSweptSphereRadius(btScalar radius) | ||||
| 	{ | ||||
| 		m_ccdSweptSphereRadius = radius; | ||||
| 	} | ||||
|  | ||||
| 	btScalar 	getCcdMotionThreshold() const | ||||
| 	{ | ||||
| 		return m_ccdMotionThreshold; | ||||
| 	} | ||||
|  | ||||
| 	btScalar 	getCcdSquareMotionThreshold() const | ||||
| 	{ | ||||
| 		return m_ccdMotionThreshold*m_ccdMotionThreshold; | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| 	/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold | ||||
| 	void	setCcdMotionThreshold(btScalar ccdMotionThreshold) | ||||
| 	{ | ||||
| 		m_ccdMotionThreshold = ccdMotionThreshold; | ||||
| 	} | ||||
|  | ||||
| 	///users can point to their objects, userPointer is not used by Bullet | ||||
| 	void*	getUserPointer() const | ||||
| 	{ | ||||
| 		return m_userObjectPointer; | ||||
| 	} | ||||
| 	 | ||||
| 	///users can point to their objects, userPointer is not used by Bullet | ||||
| 	void	setUserPointer(void* userPointer) | ||||
| 	{ | ||||
| 		m_userObjectPointer = userPointer; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	inline bool checkCollideWith(btCollisionObject* co) | ||||
| 	{ | ||||
| 		if (m_checkCollideWith) | ||||
| 			return checkCollideWithOverride(co); | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	virtual	int	calculateSerializeBufferSize()	const; | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| 	virtual	const char*	serialize(void* dataBuffer, class btSerializer* serializer) const; | ||||
|  | ||||
| 	virtual void serializeSingleObject(class btSerializer* serializer) const; | ||||
|  | ||||
| }; | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct	btCollisionObjectDoubleData | ||||
| { | ||||
| 	void					*m_broadphaseHandle; | ||||
| 	void					*m_collisionShape; | ||||
| 	btCollisionShapeData	*m_rootCollisionShape; | ||||
| 	char					*m_name; | ||||
|  | ||||
| 	btTransformDoubleData	m_worldTransform; | ||||
| 	btTransformDoubleData	m_interpolationWorldTransform; | ||||
| 	btVector3DoubleData		m_interpolationLinearVelocity; | ||||
| 	btVector3DoubleData		m_interpolationAngularVelocity; | ||||
| 	btVector3DoubleData		m_anisotropicFriction; | ||||
| 	double					m_contactProcessingThreshold;	 | ||||
| 	double					m_deactivationTime; | ||||
| 	double					m_friction; | ||||
| 	double					m_restitution; | ||||
| 	double					m_hitFraction;  | ||||
| 	double					m_ccdSweptSphereRadius; | ||||
| 	double					m_ccdMotionThreshold; | ||||
|  | ||||
| 	int						m_hasAnisotropicFriction; | ||||
| 	int						m_collisionFlags; | ||||
| 	int						m_islandTag1; | ||||
| 	int						m_companionId; | ||||
| 	int						m_activationState1; | ||||
| 	int						m_internalType; | ||||
| 	int						m_checkCollideWith; | ||||
|  | ||||
| 	char	m_padding[4]; | ||||
| }; | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct	btCollisionObjectFloatData | ||||
| { | ||||
| 	void					*m_broadphaseHandle; | ||||
| 	void					*m_collisionShape; | ||||
| 	btCollisionShapeData	*m_rootCollisionShape; | ||||
| 	char					*m_name; | ||||
|  | ||||
| 	btTransformFloatData	m_worldTransform; | ||||
| 	btTransformFloatData	m_interpolationWorldTransform; | ||||
| 	btVector3FloatData		m_interpolationLinearVelocity; | ||||
| 	btVector3FloatData		m_interpolationAngularVelocity; | ||||
| 	btVector3FloatData		m_anisotropicFriction; | ||||
| 	float					m_contactProcessingThreshold;	 | ||||
| 	float					m_deactivationTime; | ||||
| 	float					m_friction; | ||||
| 	float					m_restitution; | ||||
| 	float					m_hitFraction;  | ||||
| 	float					m_ccdSweptSphereRadius; | ||||
| 	float					m_ccdMotionThreshold; | ||||
|  | ||||
| 	int						m_hasAnisotropicFriction; | ||||
| 	int						m_collisionFlags; | ||||
| 	int						m_islandTag1; | ||||
| 	int						m_companionId; | ||||
| 	int						m_activationState1; | ||||
| 	int						m_internalType; | ||||
| 	int						m_checkCollideWith; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| SIMD_FORCE_INLINE	int	btCollisionObject::calculateSerializeBufferSize() const | ||||
| { | ||||
| 	return sizeof(btCollisionObjectData); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //COLLISION_OBJECT_H | ||||
							
								
								
									
										1432
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1432
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										509
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										509
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,509 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://bulletphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @mainpage Bullet Documentation | ||||
|  * | ||||
|  * @section intro_sec Introduction | ||||
|  * Bullet Collision Detection & Physics SDK | ||||
|  * | ||||
|  * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ). | ||||
|  * | ||||
|  * The main documentation is Bullet_User_Manual.pdf, included in the source code distribution. | ||||
|  * There is the Physics Forum for feedback and general Collision Detection and Physics discussions. | ||||
|  * Please visit http://www.bulletphysics.com | ||||
|  * | ||||
|  * @section install_sec Installation | ||||
|  * | ||||
|  * @subsection step1 Step 1: Download | ||||
|  * You can download the Bullet Physics Library from the Google Code repository: http://code.google.com/p/bullet/downloads/list | ||||
|  * | ||||
|  * @subsection step2 Step 2: Building | ||||
|  * Bullet main build system for all platforms is cmake, you can download http://www.cmake.org | ||||
|  * cmake can autogenerate projectfiles for Microsoft Visual Studio, Apple Xcode, KDevelop and Unix Makefiles. | ||||
|  * The easiest is to run the CMake cmake-gui graphical user interface and choose the options and generate projectfiles. | ||||
|  * You can also use cmake in the command-line. Here are some examples for various platforms: | ||||
|  * cmake . -G "Visual Studio 9 2008" | ||||
|  * cmake . -G Xcode | ||||
|  * cmake . -G "Unix Makefiles" | ||||
|  * Although cmake is recommended, you can also use autotools for UNIX: ./autogen.sh ./configure to create a Makefile and then run make. | ||||
|  *  | ||||
|  * @subsection step3 Step 3: Testing demos | ||||
|  * Try to run and experiment with BasicDemo executable as a starting point. | ||||
|  * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation. | ||||
|  * The Dependencies can be seen in this documentation under Directories | ||||
|  *  | ||||
|  * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation | ||||
|  * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform. | ||||
|  * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld. | ||||
|  * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras) | ||||
|  * Bullet Collision Detection can also be used without the Dynamics/Extras. | ||||
|  * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo. | ||||
|  * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation. | ||||
|  * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector. | ||||
|  * | ||||
|  * @section copyright Copyright | ||||
|  * For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf | ||||
|  *  | ||||
|  */ | ||||
|   | ||||
|   | ||||
|  | ||||
| #ifndef COLLISION_WORLD_H | ||||
| #define COLLISION_WORLD_H | ||||
|  | ||||
| class btStackAlloc; | ||||
| class btCollisionShape; | ||||
| class btConvexShape; | ||||
| class btBroadphaseInterface; | ||||
| class btSerializer; | ||||
|  | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btTransform.h" | ||||
| #include "btCollisionObject.h" | ||||
| #include "btCollisionDispatcher.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
| ///CollisionWorld is interface and container for the collision detection | ||||
| class btCollisionWorld | ||||
| { | ||||
|  | ||||
| 	 | ||||
| protected: | ||||
|  | ||||
| 	btAlignedObjectArray<btCollisionObject*>	m_collisionObjects; | ||||
| 	 | ||||
| 	btDispatcher*	m_dispatcher1; | ||||
|  | ||||
| 	btDispatcherInfo	m_dispatchInfo; | ||||
|  | ||||
| 	btStackAlloc*	m_stackAlloc; | ||||
|  | ||||
| 	btBroadphaseInterface*	m_broadphasePairCache; | ||||
|  | ||||
| 	btIDebugDraw*	m_debugDrawer; | ||||
|  | ||||
| 	///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs | ||||
| 	///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB) | ||||
| 	bool m_forceUpdateAllAabbs; | ||||
|  | ||||
| 	void	serializeCollisionObjects(btSerializer* serializer); | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	//this constructor doesn't own the dispatcher and paircache/broadphase | ||||
| 	btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration); | ||||
|  | ||||
| 	virtual ~btCollisionWorld(); | ||||
|  | ||||
| 	void	setBroadphase(btBroadphaseInterface*	pairCache) | ||||
| 	{ | ||||
| 		m_broadphasePairCache = pairCache; | ||||
| 	} | ||||
|  | ||||
| 	const btBroadphaseInterface*	getBroadphase() const | ||||
| 	{ | ||||
| 		return m_broadphasePairCache; | ||||
| 	} | ||||
|  | ||||
| 	btBroadphaseInterface*	getBroadphase() | ||||
| 	{ | ||||
| 		return m_broadphasePairCache; | ||||
| 	} | ||||
|  | ||||
| 	btOverlappingPairCache*	getPairCache() | ||||
| 	{ | ||||
| 		return m_broadphasePairCache->getOverlappingPairCache(); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	btDispatcher*	getDispatcher() | ||||
| 	{ | ||||
| 		return m_dispatcher1; | ||||
| 	} | ||||
|  | ||||
| 	const btDispatcher*	getDispatcher() const | ||||
| 	{ | ||||
| 		return m_dispatcher1; | ||||
| 	} | ||||
|  | ||||
| 	void	updateSingleAabb(btCollisionObject* colObj); | ||||
|  | ||||
| 	virtual void	updateAabbs(); | ||||
| 	 | ||||
| 	virtual void	setDebugDrawer(btIDebugDraw*	debugDrawer) | ||||
| 	{ | ||||
| 			m_debugDrawer = debugDrawer; | ||||
| 	} | ||||
|  | ||||
| 	virtual btIDebugDraw*	getDebugDrawer() | ||||
| 	{ | ||||
| 		return m_debugDrawer; | ||||
| 	} | ||||
|  | ||||
| 	virtual void	debugDrawWorld(); | ||||
|  | ||||
| 	virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); | ||||
|  | ||||
|  | ||||
| 	///LocalShapeInfo gives extra information for complex shapes | ||||
| 	///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart | ||||
| 	struct	LocalShapeInfo | ||||
| 	{ | ||||
| 		int	m_shapePart; | ||||
| 		int	m_triangleIndex; | ||||
| 		 | ||||
| 		//const btCollisionShape*	m_shapeTemp; | ||||
| 		//const btTransform*	m_shapeLocalTransform; | ||||
| 	}; | ||||
|  | ||||
| 	struct	LocalRayResult | ||||
| 	{ | ||||
| 		LocalRayResult(btCollisionObject*	collisionObject,  | ||||
| 			LocalShapeInfo*	localShapeInfo, | ||||
| 			const btVector3&		hitNormalLocal, | ||||
| 			btScalar hitFraction) | ||||
| 		:m_collisionObject(collisionObject), | ||||
| 		m_localShapeInfo(localShapeInfo), | ||||
| 		m_hitNormalLocal(hitNormalLocal), | ||||
| 		m_hitFraction(hitFraction) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		btCollisionObject*		m_collisionObject; | ||||
| 		LocalShapeInfo*			m_localShapeInfo; | ||||
| 		btVector3				m_hitNormalLocal; | ||||
| 		btScalar				m_hitFraction; | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	///RayResultCallback is used to report new raycast results | ||||
| 	struct	RayResultCallback | ||||
| 	{ | ||||
| 		btScalar	m_closestHitFraction; | ||||
| 		btCollisionObject*		m_collisionObject; | ||||
| 		short int	m_collisionFilterGroup; | ||||
| 		short int	m_collisionFilterMask; | ||||
|       //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback | ||||
|       unsigned int m_flags; | ||||
|  | ||||
| 		virtual ~RayResultCallback() | ||||
| 		{ | ||||
| 		} | ||||
| 		bool	hasHit() const | ||||
| 		{ | ||||
| 			return (m_collisionObject != 0); | ||||
| 		} | ||||
|  | ||||
| 		RayResultCallback() | ||||
| 			:m_closestHitFraction(btScalar(1.)), | ||||
| 			m_collisionObject(0), | ||||
| 			m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), | ||||
| 			m_collisionFilterMask(btBroadphaseProxy::AllFilter), | ||||
|          //@BP Mod | ||||
|          m_flags(0) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		virtual bool needsCollision(btBroadphaseProxy* proxy0) const | ||||
| 		{ | ||||
| 			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; | ||||
| 			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); | ||||
| 			return collides; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0; | ||||
| 	}; | ||||
|  | ||||
| 	struct	ClosestRayResultCallback : public RayResultCallback | ||||
| 	{ | ||||
| 		ClosestRayResultCallback(const btVector3&	rayFromWorld,const btVector3&	rayToWorld) | ||||
| 		:m_rayFromWorld(rayFromWorld), | ||||
| 		m_rayToWorld(rayToWorld) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		btVector3	m_rayFromWorld;//used to calculate hitPointWorld from hitFraction | ||||
| 		btVector3	m_rayToWorld; | ||||
|  | ||||
| 		btVector3	m_hitNormalWorld; | ||||
| 		btVector3	m_hitPointWorld; | ||||
| 			 | ||||
| 		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) | ||||
| 		{ | ||||
| 			//caller already does the filter on the m_closestHitFraction | ||||
| 			btAssert(rayResult.m_hitFraction <= m_closestHitFraction); | ||||
| 			 | ||||
| 			m_closestHitFraction = rayResult.m_hitFraction; | ||||
| 			m_collisionObject = rayResult.m_collisionObject; | ||||
| 			if (normalInWorldSpace) | ||||
| 			{ | ||||
| 				m_hitNormalWorld = rayResult.m_hitNormalLocal; | ||||
| 			} else | ||||
| 			{ | ||||
| 				///need to transform normal into worldspace | ||||
| 				m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; | ||||
| 			} | ||||
| 			m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); | ||||
| 			return rayResult.m_hitFraction; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	struct	AllHitsRayResultCallback : public RayResultCallback | ||||
| 	{ | ||||
| 		AllHitsRayResultCallback(const btVector3&	rayFromWorld,const btVector3&	rayToWorld) | ||||
| 		:m_rayFromWorld(rayFromWorld), | ||||
| 		m_rayToWorld(rayToWorld) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		btAlignedObjectArray<btCollisionObject*>		m_collisionObjects; | ||||
|  | ||||
| 		btVector3	m_rayFromWorld;//used to calculate hitPointWorld from hitFraction | ||||
| 		btVector3	m_rayToWorld; | ||||
|  | ||||
| 		btAlignedObjectArray<btVector3>	m_hitNormalWorld; | ||||
| 		btAlignedObjectArray<btVector3>	m_hitPointWorld; | ||||
| 		btAlignedObjectArray<btScalar> m_hitFractions; | ||||
| 			 | ||||
| 		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) | ||||
| 		{ | ||||
| 			m_collisionObject = rayResult.m_collisionObject; | ||||
| 			m_collisionObjects.push_back(rayResult.m_collisionObject); | ||||
| 			btVector3 hitNormalWorld; | ||||
| 			if (normalInWorldSpace) | ||||
| 			{ | ||||
| 				hitNormalWorld = rayResult.m_hitNormalLocal; | ||||
| 			} else | ||||
| 			{ | ||||
| 				///need to transform normal into worldspace | ||||
| 				hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; | ||||
| 			} | ||||
| 			m_hitNormalWorld.push_back(hitNormalWorld); | ||||
| 			btVector3 hitPointWorld; | ||||
| 			hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); | ||||
| 			m_hitPointWorld.push_back(hitPointWorld); | ||||
| 			m_hitFractions.push_back(rayResult.m_hitFraction); | ||||
| 			return m_closestHitFraction; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| 	struct LocalConvexResult | ||||
| 	{ | ||||
| 		LocalConvexResult(btCollisionObject*	hitCollisionObject,  | ||||
| 			LocalShapeInfo*	localShapeInfo, | ||||
| 			const btVector3&		hitNormalLocal, | ||||
| 			const btVector3&		hitPointLocal, | ||||
| 			btScalar hitFraction | ||||
| 			) | ||||
| 		:m_hitCollisionObject(hitCollisionObject), | ||||
| 		m_localShapeInfo(localShapeInfo), | ||||
| 		m_hitNormalLocal(hitNormalLocal), | ||||
| 		m_hitPointLocal(hitPointLocal), | ||||
| 		m_hitFraction(hitFraction) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		btCollisionObject*		m_hitCollisionObject; | ||||
| 		LocalShapeInfo*			m_localShapeInfo; | ||||
| 		btVector3				m_hitNormalLocal; | ||||
| 		btVector3				m_hitPointLocal; | ||||
| 		btScalar				m_hitFraction; | ||||
| 	}; | ||||
|  | ||||
| 	///RayResultCallback is used to report new raycast results | ||||
| 	struct	ConvexResultCallback | ||||
| 	{ | ||||
| 		btScalar	m_closestHitFraction; | ||||
| 		short int	m_collisionFilterGroup; | ||||
| 		short int	m_collisionFilterMask; | ||||
| 		 | ||||
| 		ConvexResultCallback() | ||||
| 			:m_closestHitFraction(btScalar(1.)), | ||||
| 			m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), | ||||
| 			m_collisionFilterMask(btBroadphaseProxy::AllFilter) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		virtual ~ConvexResultCallback() | ||||
| 		{ | ||||
| 		} | ||||
| 		 | ||||
| 		bool	hasHit() const | ||||
| 		{ | ||||
| 			return (m_closestHitFraction < btScalar(1.)); | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
|  | ||||
| 		virtual bool needsCollision(btBroadphaseProxy* proxy0) const | ||||
| 		{ | ||||
| 			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; | ||||
| 			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); | ||||
| 			return collides; | ||||
| 		} | ||||
|  | ||||
| 		virtual	btScalar	addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0; | ||||
| 	}; | ||||
|  | ||||
| 	struct	ClosestConvexResultCallback : public ConvexResultCallback | ||||
| 	{ | ||||
| 		ClosestConvexResultCallback(const btVector3&	convexFromWorld,const btVector3&	convexToWorld) | ||||
| 		:m_convexFromWorld(convexFromWorld), | ||||
| 		m_convexToWorld(convexToWorld), | ||||
| 		m_hitCollisionObject(0) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		btVector3	m_convexFromWorld;//used to calculate hitPointWorld from hitFraction | ||||
| 		btVector3	m_convexToWorld; | ||||
|  | ||||
| 		btVector3	m_hitNormalWorld; | ||||
| 		btVector3	m_hitPointWorld; | ||||
| 		btCollisionObject*	m_hitCollisionObject; | ||||
| 		 | ||||
| 		virtual	btScalar	addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) | ||||
| 		{ | ||||
| //caller already does the filter on the m_closestHitFraction | ||||
| 			btAssert(convexResult.m_hitFraction <= m_closestHitFraction); | ||||
| 						 | ||||
| 			m_closestHitFraction = convexResult.m_hitFraction; | ||||
| 			m_hitCollisionObject = convexResult.m_hitCollisionObject; | ||||
| 			if (normalInWorldSpace) | ||||
| 			{ | ||||
| 				m_hitNormalWorld = convexResult.m_hitNormalLocal; | ||||
| 			} else | ||||
| 			{ | ||||
| 				///need to transform normal into worldspace | ||||
| 				m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; | ||||
| 			} | ||||
| 			m_hitPointWorld = convexResult.m_hitPointLocal; | ||||
| 			return convexResult.m_hitFraction; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	///ContactResultCallback is used to report contact points | ||||
| 	struct	ContactResultCallback | ||||
| 	{ | ||||
| 		short int	m_collisionFilterGroup; | ||||
| 		short int	m_collisionFilterMask; | ||||
| 		 | ||||
| 		ContactResultCallback() | ||||
| 			:m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), | ||||
| 			m_collisionFilterMask(btBroadphaseProxy::AllFilter) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		virtual ~ContactResultCallback() | ||||
| 		{ | ||||
| 		} | ||||
| 		 | ||||
| 		virtual bool needsCollision(btBroadphaseProxy* proxy0) const | ||||
| 		{ | ||||
| 			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; | ||||
| 			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); | ||||
| 			return collides; | ||||
| 		} | ||||
|  | ||||
| 		virtual	btScalar	addSingleResult(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) = 0; | ||||
| 	}; | ||||
|  | ||||
|  | ||||
|  | ||||
| 	int	getNumCollisionObjects() const | ||||
| 	{ | ||||
| 		return int(m_collisionObjects.size()); | ||||
| 	} | ||||
|  | ||||
| 	/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback | ||||
| 	/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. | ||||
| 	virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;  | ||||
|  | ||||
| 	/// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback | ||||
| 	/// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. | ||||
| 	void    convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback,  btScalar allowedCcdPenetration = btScalar(0.)) const; | ||||
|  | ||||
| 	///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback. | ||||
| 	///it reports one or more contact points for every overlapping object (including the one with deepest penetration) | ||||
| 	void	contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback); | ||||
|  | ||||
| 	///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected. | ||||
| 	///it reports one or more contact points (including the one with deepest penetration) | ||||
| 	void	contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback); | ||||
|  | ||||
|  | ||||
| 	/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. | ||||
| 	/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. | ||||
| 	/// This allows more customization. | ||||
| 	static void	rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, | ||||
| 					  btCollisionObject* collisionObject, | ||||
| 					  const btCollisionShape* collisionShape, | ||||
| 					  const btTransform& colObjWorldTransform, | ||||
| 					  RayResultCallback& resultCallback); | ||||
|  | ||||
| 	/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. | ||||
| 	static void	objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, | ||||
| 					  btCollisionObject* collisionObject, | ||||
| 					  const btCollisionShape* collisionShape, | ||||
| 					  const btTransform& colObjWorldTransform, | ||||
| 					  ConvexResultCallback& resultCallback, btScalar	allowedPenetration); | ||||
|  | ||||
| 	virtual void	addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); | ||||
|  | ||||
| 	btCollisionObjectArray& getCollisionObjectArray() | ||||
| 	{ | ||||
| 		return m_collisionObjects; | ||||
| 	} | ||||
|  | ||||
| 	const btCollisionObjectArray& getCollisionObjectArray() const | ||||
| 	{ | ||||
| 		return m_collisionObjects; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	virtual void	removeCollisionObject(btCollisionObject* collisionObject); | ||||
|  | ||||
| 	virtual void	performDiscreteCollisionDetection(); | ||||
|  | ||||
| 	btDispatcherInfo& getDispatchInfo() | ||||
| 	{ | ||||
| 		return m_dispatchInfo; | ||||
| 	} | ||||
|  | ||||
| 	const btDispatcherInfo& getDispatchInfo() const | ||||
| 	{ | ||||
| 		return m_dispatchInfo; | ||||
| 	} | ||||
| 	 | ||||
| 	bool	getForceUpdateAllAabbs() const | ||||
| 	{ | ||||
| 		return m_forceUpdateAllAabbs; | ||||
| 	} | ||||
| 	void setForceUpdateAllAabbs( bool forceUpdateAllAabbs) | ||||
| 	{ | ||||
| 		m_forceUpdateAllAabbs = forceUpdateAllAabbs; | ||||
| 	} | ||||
|  | ||||
| 	///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo) | ||||
| 	virtual	void	serialize(btSerializer* serializer); | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif //COLLISION_WORLD_H | ||||
| @@ -0,0 +1,353 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/CollisionShapes/btCompoundShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDbvt.h" | ||||
| #include "LinearMath/btIDebugDraw.h" | ||||
| #include "LinearMath/btAabbUtil2.h" | ||||
| #include "btManifoldResult.h" | ||||
|  | ||||
| btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) | ||||
| :btActivatingCollisionAlgorithm(ci,body0,body1), | ||||
| m_isSwapped(isSwapped), | ||||
| m_sharedManifold(ci.m_manifold) | ||||
| { | ||||
| 	m_ownsManifold = false; | ||||
|  | ||||
| 	btCollisionObject* colObj = m_isSwapped? body1 : body0; | ||||
| 	btAssert (colObj->getCollisionShape()->isCompound()); | ||||
| 	 | ||||
| 	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); | ||||
| 	m_compoundShapeRevision = compoundShape->getUpdateRevision(); | ||||
| 	 | ||||
| 	preallocateChildAlgorithms(body0,body1); | ||||
| } | ||||
|  | ||||
| void	btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1) | ||||
| { | ||||
| 	btCollisionObject* colObj = m_isSwapped? body1 : body0; | ||||
| 	btCollisionObject* otherObj = m_isSwapped? body0 : body1; | ||||
| 	btAssert (colObj->getCollisionShape()->isCompound()); | ||||
| 	 | ||||
| 	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); | ||||
|  | ||||
| 	int numChildren = compoundShape->getNumChildShapes(); | ||||
| 	int i; | ||||
| 	 | ||||
| 	m_childCollisionAlgorithms.resize(numChildren); | ||||
| 	for (i=0;i<numChildren;i++) | ||||
| 	{ | ||||
| 		if (compoundShape->getDynamicAabbTree()) | ||||
| 		{ | ||||
| 			m_childCollisionAlgorithms[i] = 0; | ||||
| 		} else | ||||
| 		{ | ||||
| 			btCollisionShape* tmpShape = colObj->getCollisionShape(); | ||||
| 			btCollisionShape* childShape = compoundShape->getChildShape(i); | ||||
| 			colObj->internalSetTemporaryCollisionShape( childShape ); | ||||
| 			m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold); | ||||
| 			colObj->internalSetTemporaryCollisionShape( tmpShape ); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void	btCompoundCollisionAlgorithm::removeChildAlgorithms() | ||||
| { | ||||
| 	int numChildren = m_childCollisionAlgorithms.size(); | ||||
| 	int i; | ||||
| 	for (i=0;i<numChildren;i++) | ||||
| 	{ | ||||
| 		if (m_childCollisionAlgorithms[i]) | ||||
| 		{ | ||||
| 			m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); | ||||
| 			m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() | ||||
| { | ||||
| 	removeChildAlgorithms(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| struct	btCompoundLeafCallback : btDbvt::ICollide | ||||
| { | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btCollisionObject* m_compoundColObj; | ||||
| 	btCollisionObject* m_otherObj; | ||||
| 	btDispatcher* m_dispatcher; | ||||
| 	const btDispatcherInfo& m_dispatchInfo; | ||||
| 	btManifoldResult*	m_resultOut; | ||||
| 	btCollisionAlgorithm**	m_childCollisionAlgorithms; | ||||
| 	btPersistentManifold*	m_sharedManifold; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult*	resultOut,btCollisionAlgorithm**	childCollisionAlgorithms,btPersistentManifold*	sharedManifold) | ||||
| 		:m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), | ||||
| 		m_childCollisionAlgorithms(childCollisionAlgorithms), | ||||
| 		m_sharedManifold(sharedManifold) | ||||
| 	{ | ||||
|  | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	void	ProcessChildShape(btCollisionShape* childShape,int index) | ||||
| 	{ | ||||
| 		btAssert(index>=0); | ||||
| 		btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape()); | ||||
| 		btAssert(index<compoundShape->getNumChildShapes()); | ||||
|  | ||||
|  | ||||
| 		//backup | ||||
| 		btTransform	orgTrans = m_compoundColObj->getWorldTransform(); | ||||
| 		btTransform	orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform(); | ||||
| 		const btTransform& childTrans = compoundShape->getChildTransform(index); | ||||
| 		btTransform	newChildWorldTrans = orgTrans*childTrans ; | ||||
|  | ||||
| 		//perform an AABB check first | ||||
| 		btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; | ||||
| 		childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); | ||||
| 		m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1); | ||||
|  | ||||
| 		if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) | ||||
| 		{ | ||||
|  | ||||
| 			m_compoundColObj->setWorldTransform( newChildWorldTrans); | ||||
| 			m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans); | ||||
|  | ||||
| 			//the contactpoint is still projected back using the original inverted worldtrans | ||||
| 			btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape(); | ||||
| 			m_compoundColObj->internalSetTemporaryCollisionShape( childShape ); | ||||
|  | ||||
| 			if (!m_childCollisionAlgorithms[index]) | ||||
| 				m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold); | ||||
|  | ||||
| 			///detect swapping case | ||||
| 			if (m_resultOut->getBody0Internal() == m_compoundColObj) | ||||
| 			{ | ||||
| 				m_resultOut->setShapeIdentifiersA(-1,index); | ||||
| 			} else | ||||
| 			{ | ||||
| 				m_resultOut->setShapeIdentifiersB(-1,index); | ||||
| 			} | ||||
|  | ||||
| 			m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut); | ||||
| 			if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) | ||||
| 			{ | ||||
| 				btVector3 worldAabbMin,worldAabbMax; | ||||
| 				m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1)); | ||||
| 				m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1)); | ||||
| 			} | ||||
| 			 | ||||
| 			//revert back transform | ||||
| 			m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape); | ||||
| 			m_compoundColObj->setWorldTransform(  orgTrans ); | ||||
| 			m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans); | ||||
| 		} | ||||
| 	} | ||||
| 	void		Process(const btDbvtNode* leaf) | ||||
| 	{ | ||||
| 		int index = leaf->dataAsInt; | ||||
|  | ||||
| 		btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape()); | ||||
| 		btCollisionShape* childShape = compoundShape->getChildShape(index); | ||||
| 		if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) | ||||
| 		{ | ||||
| 			btVector3 worldAabbMin,worldAabbMax; | ||||
| 			btTransform	orgTrans = m_compoundColObj->getWorldTransform(); | ||||
| 			btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax); | ||||
| 			m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0)); | ||||
| 		} | ||||
| 		ProcessChildShape(childShape,index); | ||||
|  | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	btCollisionObject* colObj = m_isSwapped? body1 : body0; | ||||
| 	btCollisionObject* otherObj = m_isSwapped? body0 : body1; | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	btAssert (colObj->getCollisionShape()->isCompound()); | ||||
| 	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); | ||||
|  | ||||
| 	///btCompoundShape might have changed: | ||||
| 	////make sure the internal child collision algorithm caches are still valid | ||||
| 	if (compoundShape->getUpdateRevision() != m_compoundShapeRevision) | ||||
| 	{ | ||||
| 		///clear and update all | ||||
| 		removeChildAlgorithms(); | ||||
| 		 | ||||
| 		preallocateChildAlgorithms(body0,body1); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	btDbvt* tree = compoundShape->getDynamicAabbTree(); | ||||
| 	//use a dynamic aabb tree to cull potential child-overlaps | ||||
| 	btCompoundLeafCallback  callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold); | ||||
|  | ||||
| 	///we need to refresh all contact manifolds | ||||
| 	///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep | ||||
| 	///so we should add a 'refreshManifolds' in the btCollisionAlgorithm | ||||
| 	{ | ||||
| 		int i; | ||||
| 		btManifoldArray manifoldArray; | ||||
| 		for (i=0;i<m_childCollisionAlgorithms.size();i++) | ||||
| 		{ | ||||
| 			if (m_childCollisionAlgorithms[i]) | ||||
| 			{ | ||||
| 				m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray); | ||||
| 				for (int m=0;m<manifoldArray.size();m++) | ||||
| 				{ | ||||
| 					if (manifoldArray[m]->getNumContacts()) | ||||
| 					{ | ||||
| 						resultOut->setPersistentManifold(manifoldArray[m]); | ||||
| 						resultOut->refreshContactPoints(); | ||||
| 						resultOut->setPersistentManifold(0);//??necessary? | ||||
| 					} | ||||
| 				} | ||||
| 				manifoldArray.clear(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (tree) | ||||
| 	{ | ||||
|  | ||||
| 		btVector3 localAabbMin,localAabbMax; | ||||
| 		btTransform otherInCompoundSpace; | ||||
| 		otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform(); | ||||
| 		otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax); | ||||
|  | ||||
| 		const ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); | ||||
| 		//process all children, that overlap with  the given AABB bounds | ||||
| 		tree->collideTV(tree->m_root,bounds,callback); | ||||
|  | ||||
| 	} else | ||||
| 	{ | ||||
| 		//iterate over all children, perform an AABB check inside ProcessChildShape | ||||
| 		int numChildren = m_childCollisionAlgorithms.size(); | ||||
| 		int i; | ||||
| 		for (i=0;i<numChildren;i++) | ||||
| 		{ | ||||
| 			callback.ProcessChildShape(compoundShape->getChildShape(i),i); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	{ | ||||
| 				//iterate over all children, perform an AABB check inside ProcessChildShape | ||||
| 		int numChildren = m_childCollisionAlgorithms.size(); | ||||
| 		int i; | ||||
| 		btManifoldArray	manifoldArray; | ||||
|         btCollisionShape* childShape = 0; | ||||
|         btTransform	orgTrans; | ||||
|         btTransform	orgInterpolationTrans; | ||||
|         btTransform	newChildWorldTrans; | ||||
|         btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;         | ||||
|          | ||||
| 		for (i=0;i<numChildren;i++) | ||||
| 		{ | ||||
| 			if (m_childCollisionAlgorithms[i]) | ||||
| 			{ | ||||
| 				childShape = compoundShape->getChildShape(i); | ||||
| 			//if not longer overlapping, remove the algorithm | ||||
|                 orgTrans = colObj->getWorldTransform(); | ||||
|                 orgInterpolationTrans = colObj->getInterpolationWorldTransform(); | ||||
| 				const btTransform& childTrans = compoundShape->getChildTransform(i); | ||||
|                 newChildWorldTrans = orgTrans*childTrans ; | ||||
|  | ||||
| 				//perform an AABB check first | ||||
| 				childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); | ||||
| 				otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1); | ||||
|  | ||||
| 				if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) | ||||
| 				{ | ||||
| 					m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); | ||||
| 					m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); | ||||
| 					m_childCollisionAlgorithms[i] = 0; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| btScalar	btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
|  | ||||
| 	btCollisionObject* colObj = m_isSwapped? body1 : body0; | ||||
| 	btCollisionObject* otherObj = m_isSwapped? body0 : body1; | ||||
|  | ||||
| 	btAssert (colObj->getCollisionShape()->isCompound()); | ||||
| 	 | ||||
| 	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); | ||||
|  | ||||
| 	//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps | ||||
| 	//If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals | ||||
| 	//given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: | ||||
| 	//determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 | ||||
| 	//then use each overlapping node AABB against Tree0 | ||||
| 	//and vise versa. | ||||
|  | ||||
| 	btScalar hitFraction = btScalar(1.); | ||||
|  | ||||
| 	int numChildren = m_childCollisionAlgorithms.size(); | ||||
| 	int i; | ||||
|     btTransform	orgTrans; | ||||
|     btScalar frac; | ||||
| 	for (i=0;i<numChildren;i++) | ||||
| 	{ | ||||
| 		//temporarily exchange parent btCollisionShape with childShape, and recurse | ||||
| 		btCollisionShape* childShape = compoundShape->getChildShape(i); | ||||
|  | ||||
| 		//backup | ||||
|         orgTrans = colObj->getWorldTransform(); | ||||
| 	 | ||||
| 		const btTransform& childTrans = compoundShape->getChildTransform(i); | ||||
| 		//btTransform	newChildWorldTrans = orgTrans*childTrans ; | ||||
| 		colObj->setWorldTransform( orgTrans*childTrans ); | ||||
|  | ||||
| 		btCollisionShape* tmpShape = colObj->getCollisionShape(); | ||||
| 		colObj->internalSetTemporaryCollisionShape( childShape ); | ||||
|         frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); | ||||
| 		if (frac<hitFraction) | ||||
| 		{ | ||||
| 			hitFraction = frac; | ||||
| 		} | ||||
| 		//revert back | ||||
| 		colObj->internalSetTemporaryCollisionShape( tmpShape); | ||||
| 		colObj->setWorldTransform( orgTrans); | ||||
| 	} | ||||
| 	return hitFraction; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,86 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COMPOUND_COLLISION_ALGORITHM_H | ||||
| #define COMPOUND_COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDispatcher.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" | ||||
| class btDispatcher; | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "btCollisionCreateFunc.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
| class btDispatcher; | ||||
| class btCollisionObject; | ||||
|  | ||||
| /// btCompoundCollisionAlgorithm  supports collision between CompoundCollisionShapes and other collision shapes | ||||
| class btCompoundCollisionAlgorithm  : public btActivatingCollisionAlgorithm | ||||
| { | ||||
| 	btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms; | ||||
| 	bool m_isSwapped; | ||||
|  | ||||
| 	class btPersistentManifold*	m_sharedManifold; | ||||
| 	bool					m_ownsManifold; | ||||
|  | ||||
| 	int	m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated | ||||
| 	 | ||||
| 	void	removeChildAlgorithms(); | ||||
| 	 | ||||
| 	void	preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1); | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); | ||||
|  | ||||
| 	virtual ~btCompoundCollisionAlgorithm(); | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	btScalar	calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		int i; | ||||
| 		for (i=0;i<m_childCollisionAlgorithms.size();i++) | ||||
| 		{ | ||||
| 			if (m_childCollisionAlgorithms[i]) | ||||
| 				m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); | ||||
| 			return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	struct SwappedCreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); | ||||
| 			return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //COMPOUND_COLLISION_ALGORITHM_H | ||||
| @@ -0,0 +1,247 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btConvex2dConvex2dAlgorithm.h" | ||||
|  | ||||
| //#include <stdio.h> | ||||
| #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/CollisionShapes/btConvexShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btCapsuleShape.h" | ||||
|  | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "BulletCollision/CollisionShapes/btBoxShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btManifoldResult.h" | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" | ||||
| #include "BulletCollision/CollisionShapes/btSphereShape.h" | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" | ||||
|  | ||||
|  | ||||
| btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver) | ||||
| { | ||||
| 	m_numPerturbationIterations = 0; | ||||
| 	m_minimumPointsPerturbationThreshold = 3; | ||||
| 	m_simplexSolver = simplexSolver; | ||||
| 	m_pdSolver = pdSolver; | ||||
| } | ||||
|  | ||||
| btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()  | ||||
| {  | ||||
| } | ||||
|  | ||||
| btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) | ||||
| : btActivatingCollisionAlgorithm(ci,body0,body1), | ||||
| m_simplexSolver(simplexSolver), | ||||
| m_pdSolver(pdSolver), | ||||
| m_ownManifold (false), | ||||
| m_manifoldPtr(mf), | ||||
| m_lowLevelOfDetail(false), | ||||
|  m_numPerturbationIterations(numPerturbationIterations), | ||||
| m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) | ||||
| { | ||||
| 	(void)body0; | ||||
| 	(void)body1; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm() | ||||
| { | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr) | ||||
| 			m_dispatcher->releaseManifold(m_manifoldPtr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void	btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel) | ||||
| { | ||||
| 	m_lowLevelOfDetail = useLowLevel; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| extern btScalar gContactBreakingThreshold; | ||||
|  | ||||
|  | ||||
| // | ||||
| // Convex-Convex collision algorithm | ||||
| // | ||||
| void btConvex2dConvex2dAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
|  | ||||
| 	if (!m_manifoldPtr) | ||||
| 	{ | ||||
| 		//swapped? | ||||
| 		m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); | ||||
| 		m_ownManifold = true; | ||||
| 	} | ||||
| 	resultOut->setPersistentManifold(m_manifoldPtr); | ||||
|  | ||||
| 	//comment-out next line to test multi-contact generation | ||||
| 	//resultOut->getPersistentManifold()->clearManifold(); | ||||
|  | ||||
|  | ||||
| 	btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape()); | ||||
| 	btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape()); | ||||
|  | ||||
| 	btVector3  normalOnB; | ||||
| 	btVector3  pointOnBWorld; | ||||
|  | ||||
| 	{ | ||||
|  | ||||
|  | ||||
| 		btGjkPairDetector::ClosestPointInput input; | ||||
|  | ||||
| 		btGjkPairDetector	gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver); | ||||
| 		//TODO: if (dispatchInfo.m_useContinuous) | ||||
| 		gjkPairDetector.setMinkowskiA(min0); | ||||
| 		gjkPairDetector.setMinkowskiB(min1); | ||||
|  | ||||
| 		{ | ||||
| 			input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); | ||||
| 			input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; | ||||
| 		} | ||||
|  | ||||
| 		input.m_stackAlloc = dispatchInfo.m_stackAllocator; | ||||
| 		input.m_transformA = body0->getWorldTransform(); | ||||
| 		input.m_transformB = body1->getWorldTransform(); | ||||
|  | ||||
| 		gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); | ||||
|  | ||||
| 		btVector3 v0,v1; | ||||
| 		btVector3 sepNormalWorldSpace; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		resultOut->refreshContactPoints(); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btScalar	btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)resultOut; | ||||
| 	(void)dispatchInfo; | ||||
| 	///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold | ||||
|  | ||||
| 	///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold | ||||
| 	///col0->m_worldTransform, | ||||
| 	btScalar resultFraction = btScalar(1.); | ||||
|  | ||||
|  | ||||
| 	btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2(); | ||||
| 	btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2(); | ||||
|  | ||||
| 	if (squareMot0 < col0->getCcdSquareMotionThreshold() && | ||||
| 		squareMot1 < col1->getCcdSquareMotionThreshold()) | ||||
| 		return resultFraction; | ||||
|  | ||||
|  | ||||
| 	//An adhoc way of testing the Continuous Collision Detection algorithms | ||||
| 	//One object is approximated as a sphere, to simplify things | ||||
| 	//Starting in penetration should report no time of impact | ||||
| 	//For proper CCD, better accuracy and handling of 'allowed' penetration should be added | ||||
| 	//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies) | ||||
|  | ||||
|  | ||||
| 	/// Convex0 against sphere for Convex1 | ||||
| 	{ | ||||
| 		btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape()); | ||||
|  | ||||
| 		btSphereShape	sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation | ||||
| 		btConvexCast::CastResult result; | ||||
| 		btVoronoiSimplexSolver voronoiSimplex; | ||||
| 		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); | ||||
| 		///Simplification, one object is simplified as a sphere | ||||
| 		btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex); | ||||
| 		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); | ||||
| 		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), | ||||
| 			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) | ||||
| 		{ | ||||
|  | ||||
| 			//store result.m_fraction in both bodies | ||||
|  | ||||
| 			if (col0->getHitFraction()> result.m_fraction) | ||||
| 				col0->setHitFraction( result.m_fraction ); | ||||
|  | ||||
| 			if (col1->getHitFraction() > result.m_fraction) | ||||
| 				col1->setHitFraction( result.m_fraction); | ||||
|  | ||||
| 			if (resultFraction > result.m_fraction) | ||||
| 				resultFraction = result.m_fraction; | ||||
|  | ||||
| 		} | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	/// Sphere (for convex0) against Convex1 | ||||
| 	{ | ||||
| 		btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape()); | ||||
|  | ||||
| 		btSphereShape	sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation | ||||
| 		btConvexCast::CastResult result; | ||||
| 		btVoronoiSimplexSolver voronoiSimplex; | ||||
| 		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); | ||||
| 		///Simplification, one object is simplified as a sphere | ||||
| 		btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex); | ||||
| 		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); | ||||
| 		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), | ||||
| 			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) | ||||
| 		{ | ||||
|  | ||||
| 			//store result.m_fraction in both bodies | ||||
|  | ||||
| 			if (col0->getHitFraction()	> result.m_fraction) | ||||
| 				col0->setHitFraction( result.m_fraction); | ||||
|  | ||||
| 			if (col1->getHitFraction() > result.m_fraction) | ||||
| 				col1->setHitFraction( result.m_fraction); | ||||
|  | ||||
| 			if (resultFraction > result.m_fraction) | ||||
| 				resultFraction = result.m_fraction; | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return resultFraction; | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,95 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONVEX_2D_CONVEX_2D_ALGORITHM_H | ||||
| #define CONVEX_2D_CONVEX_2D_ALGORITHM_H | ||||
|  | ||||
| #include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil | ||||
|  | ||||
| class btConvexPenetrationDepthSolver; | ||||
|  | ||||
|  | ||||
| ///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape | ||||
| ///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation | ||||
| class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm | ||||
| { | ||||
| 	btSimplexSolverInterface*		m_simplexSolver; | ||||
| 	btConvexPenetrationDepthSolver* m_pdSolver; | ||||
|  | ||||
| 	 | ||||
| 	bool	m_ownManifold; | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
| 	bool			m_lowLevelOfDetail; | ||||
| 	 | ||||
| 	int m_numPerturbationIterations; | ||||
| 	int m_minimumPointsPerturbationThreshold; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); | ||||
|  | ||||
|  | ||||
| 	virtual ~btConvex2dConvex2dAlgorithm(); | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		///should we use m_ownManifold to avoid adding duplicates? | ||||
| 		if (m_manifoldPtr && m_ownManifold) | ||||
| 			manifoldArray.push_back(m_manifoldPtr); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	void	setLowLevelOfDetail(bool useLowLevel); | ||||
|  | ||||
|  | ||||
| 	const btPersistentManifold*	getManifold() | ||||
| 	{ | ||||
| 		return m_manifoldPtr; | ||||
| 	} | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
|  | ||||
| 		btConvexPenetrationDepthSolver*		m_pdSolver; | ||||
| 		btSimplexSolverInterface*			m_simplexSolver; | ||||
| 		int m_numPerturbationIterations; | ||||
| 		int m_minimumPointsPerturbationThreshold; | ||||
|  | ||||
| 		CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver); | ||||
| 		 | ||||
| 		virtual ~CreateFunc(); | ||||
|  | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm)); | ||||
| 			return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //CONVEX_2D_CONVEX_2D_ALGORITHM_H | ||||
| @@ -0,0 +1,321 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #include "btConvexConcaveCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/CollisionShapes/btConcaveShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btManifoldResult.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" | ||||
| #include "BulletCollision/CollisionShapes/btTriangleShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btSphereShape.h" | ||||
| #include "LinearMath/btIDebugDraw.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" | ||||
|  | ||||
| btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) | ||||
| : btActivatingCollisionAlgorithm(ci,body0,body1), | ||||
| m_isSwapped(isSwapped), | ||||
| m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) | ||||
| { | ||||
| } | ||||
|  | ||||
| btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() | ||||
| { | ||||
| } | ||||
|  | ||||
| void	btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| { | ||||
| 	if (m_btConvexTriangleCallback.m_manifoldPtr) | ||||
| 	{ | ||||
| 		manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher*  dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): | ||||
| 	  m_dispatcher(dispatcher), | ||||
| 	m_dispatchInfoPtr(0) | ||||
| { | ||||
| 	m_convexBody = isSwapped? body1:body0; | ||||
| 	m_triBody = isSwapped? body0:body1; | ||||
| 	 | ||||
| 	  // | ||||
| 	  // create the manifold from the dispatcher 'manifold pool' | ||||
| 	  // | ||||
| 	  m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); | ||||
|  | ||||
|   	  clearCache(); | ||||
| } | ||||
|  | ||||
| btConvexTriangleCallback::~btConvexTriangleCallback() | ||||
| { | ||||
| 	clearCache(); | ||||
| 	m_dispatcher->releaseManifold( m_manifoldPtr ); | ||||
|    | ||||
| } | ||||
|    | ||||
|  | ||||
| void	btConvexTriangleCallback::clearCache() | ||||
| { | ||||
| 	m_dispatcher->clearManifold(m_manifoldPtr); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) | ||||
| { | ||||
|   | ||||
| 	//just for debugging purposes | ||||
| 	//printf("triangle %d",m_triangleCount++); | ||||
|  | ||||
|  | ||||
| 	//aabb filter is already applied!	 | ||||
|  | ||||
| 	btCollisionAlgorithmConstructionInfo ci; | ||||
| 	ci.m_dispatcher1 = m_dispatcher; | ||||
|  | ||||
| 	btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody); | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	///debug drawing of the overlapping triangles | ||||
| 	if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe )) | ||||
| 	{ | ||||
| 		btVector3 color(1,1,0); | ||||
| 		btTransform& tr = ob->getWorldTransform(); | ||||
| 		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); | ||||
| 		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); | ||||
| 		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); | ||||
|  | ||||
| 		//btVector3 center = triangle[0] + triangle[1]+triangle[2]; | ||||
| 		//center *= btScalar(0.333333); | ||||
| 		//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color); | ||||
| 		//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color); | ||||
| 		//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color); | ||||
|  | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	//btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject); | ||||
| 	 | ||||
| 	if (m_convexBody->getCollisionShape()->isConvex()) | ||||
| 	{ | ||||
| 		btTriangleShape tm(triangle[0],triangle[1],triangle[2]);	 | ||||
| 		tm.setMargin(m_collisionMarginTriangle); | ||||
| 		 | ||||
| 		btCollisionShape* tmpShape = ob->getCollisionShape(); | ||||
| 		ob->internalSetTemporaryCollisionShape( &tm ); | ||||
| 		 | ||||
| 		btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); | ||||
|  | ||||
| 		if (m_resultOut->getBody0Internal() == m_triBody) | ||||
| 		{ | ||||
| 			m_resultOut->setShapeIdentifiersA(partId,triangleIndex); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			m_resultOut->setShapeIdentifiersB(partId,triangleIndex); | ||||
| 		} | ||||
| 	 | ||||
| 		colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); | ||||
| 		colAlgo->~btCollisionAlgorithm(); | ||||
| 		ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); | ||||
| 		ob->internalSetTemporaryCollisionShape( tmpShape); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	m_dispatchInfoPtr = &dispatchInfo; | ||||
| 	m_collisionMarginTriangle = collisionMarginTriangle; | ||||
| 	m_resultOut = resultOut; | ||||
|  | ||||
| 	//recalc aabbs | ||||
| 	btTransform convexInTriangleSpace; | ||||
| 	convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform(); | ||||
| 	btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape()); | ||||
| 	//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape); | ||||
| 	convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); | ||||
| 	btScalar extraMargin = collisionMarginTriangle; | ||||
| 	btVector3 extra(extraMargin,extraMargin,extraMargin); | ||||
|  | ||||
| 	m_aabbMax += extra; | ||||
| 	m_aabbMin -= extra; | ||||
| 	 | ||||
| } | ||||
|  | ||||
| void btConvexConcaveCollisionAlgorithm::clearCache() | ||||
| { | ||||
| 	m_btConvexTriangleCallback.clearCache(); | ||||
|  | ||||
| } | ||||
|  | ||||
| void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	 | ||||
| 	 | ||||
| 	btCollisionObject* convexBody = m_isSwapped ? body1 : body0; | ||||
| 	btCollisionObject* triBody = m_isSwapped ? body0 : body1; | ||||
|  | ||||
| 	if (triBody->getCollisionShape()->isConcave()) | ||||
| 	{ | ||||
|  | ||||
|  | ||||
| 		btCollisionObject*	triOb = triBody; | ||||
| 		btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape()); | ||||
| 		 | ||||
| 		if (convexBody->getCollisionShape()->isConvex()) | ||||
| 		{ | ||||
| 			btScalar collisionMarginTriangle = concaveShape->getMargin(); | ||||
| 					 | ||||
| 			resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr); | ||||
| 			m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); | ||||
|  | ||||
| 			//Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. | ||||
| 			//m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr); | ||||
|  | ||||
| 			m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); | ||||
|  | ||||
| 			concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); | ||||
| 			 | ||||
| 			resultOut->refreshContactPoints(); | ||||
| 	 | ||||
| 		} | ||||
| 	 | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)resultOut; | ||||
| 	(void)dispatchInfo; | ||||
| 	btCollisionObject* convexbody = m_isSwapped ? body1 : body0; | ||||
| 	btCollisionObject* triBody = m_isSwapped ? body0 : body1; | ||||
|  | ||||
|  | ||||
| 	//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) | ||||
|  | ||||
| 	//only perform CCD above a certain threshold, this prevents blocking on the long run | ||||
| 	//because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... | ||||
| 	btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); | ||||
| 	if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) | ||||
| 	{ | ||||
| 		return btScalar(1.); | ||||
| 	} | ||||
|  | ||||
| 	//const btVector3& from = convexbody->m_worldTransform.getOrigin(); | ||||
| 	//btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); | ||||
| 	//todo: only do if the motion exceeds the 'radius' | ||||
|  | ||||
| 	btTransform triInv = triBody->getWorldTransform().inverse(); | ||||
| 	btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); | ||||
| 	btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); | ||||
|  | ||||
| 	struct LocalTriangleSphereCastCallback	: public btTriangleCallback | ||||
| 	{ | ||||
| 		btTransform m_ccdSphereFromTrans; | ||||
| 		btTransform m_ccdSphereToTrans; | ||||
| 		btTransform	m_meshTransform; | ||||
|  | ||||
| 		btScalar	m_ccdSphereRadius; | ||||
| 		btScalar	m_hitFraction; | ||||
| 	 | ||||
|  | ||||
| 		LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) | ||||
| 			:m_ccdSphereFromTrans(from), | ||||
| 			m_ccdSphereToTrans(to), | ||||
| 			m_ccdSphereRadius(ccdSphereRadius), | ||||
| 			m_hitFraction(hitFraction) | ||||
| 		{			 | ||||
| 		} | ||||
| 		 | ||||
| 		 | ||||
| 		virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) | ||||
| 		{ | ||||
| 			(void)partId; | ||||
| 			(void)triangleIndex; | ||||
| 			//do a swept sphere for now | ||||
| 			btTransform ident; | ||||
| 			ident.setIdentity(); | ||||
| 			btConvexCast::CastResult castResult; | ||||
| 			castResult.m_fraction = m_hitFraction; | ||||
| 			btSphereShape	pointShape(m_ccdSphereRadius); | ||||
| 			btTriangleShape	triShape(triangle[0],triangle[1],triangle[2]); | ||||
| 			btVoronoiSimplexSolver	simplexSolver; | ||||
| 			btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); | ||||
| 			//GjkConvexCast	convexCaster(&pointShape,convexShape,&simplexSolver); | ||||
| 			//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); | ||||
| 			//local space? | ||||
|  | ||||
| 			if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, | ||||
| 				ident,ident,castResult)) | ||||
| 			{ | ||||
| 				if (m_hitFraction > castResult.m_fraction) | ||||
| 					m_hitFraction = castResult.m_fraction; | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	 | ||||
| 	if (triBody->getCollisionShape()->isConcave()) | ||||
| 	{ | ||||
| 		btVector3 rayAabbMin = convexFromLocal.getOrigin(); | ||||
| 		rayAabbMin.setMin(convexToLocal.getOrigin()); | ||||
| 		btVector3 rayAabbMax = convexFromLocal.getOrigin(); | ||||
| 		rayAabbMax.setMax(convexToLocal.getOrigin()); | ||||
| 		btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); | ||||
| 		rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); | ||||
| 		rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); | ||||
|  | ||||
| 		btScalar curHitFraction = btScalar(1.); //is this available? | ||||
| 		LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, | ||||
| 			convexbody->getCcdSweptSphereRadius(),curHitFraction); | ||||
|  | ||||
| 		raycastCallback.m_hitFraction = convexbody->getHitFraction(); | ||||
|  | ||||
| 		btCollisionObject* concavebody = triBody; | ||||
|  | ||||
| 		btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); | ||||
| 		 | ||||
| 		if (triangleMesh) | ||||
| 		{ | ||||
| 			triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); | ||||
| 		} | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 		if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) | ||||
| 		{ | ||||
| 			convexbody->setHitFraction( raycastCallback.m_hitFraction); | ||||
| 			return raycastCallback.m_hitFraction; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return btScalar(1.); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,116 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H | ||||
| #define CONVEX_CONCAVE_COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDispatcher.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" | ||||
| #include "BulletCollision/CollisionShapes/btTriangleCallback.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" | ||||
| class btDispatcher; | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "btCollisionCreateFunc.h" | ||||
|  | ||||
| ///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. | ||||
| class btConvexTriangleCallback : public btTriangleCallback | ||||
| { | ||||
| 	btCollisionObject* m_convexBody; | ||||
| 	btCollisionObject* m_triBody; | ||||
|  | ||||
| 	btVector3	m_aabbMin; | ||||
| 	btVector3	m_aabbMax ; | ||||
|  | ||||
|  | ||||
| 	btManifoldResult* m_resultOut; | ||||
| 	btDispatcher*	m_dispatcher; | ||||
| 	const btDispatcherInfo* m_dispatchInfoPtr; | ||||
| 	btScalar m_collisionMarginTriangle; | ||||
| 	 | ||||
| public: | ||||
| int	m_triangleCount; | ||||
| 	 | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
|  | ||||
| 	btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); | ||||
|  | ||||
| 	void	setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual ~btConvexTriangleCallback(); | ||||
|  | ||||
| 	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); | ||||
| 	 | ||||
| 	void clearCache(); | ||||
|  | ||||
| 	SIMD_FORCE_INLINE const btVector3& getAabbMin() const | ||||
| 	{ | ||||
| 		return m_aabbMin; | ||||
| 	} | ||||
| 	SIMD_FORCE_INLINE const btVector3& getAabbMax() const | ||||
| 	{ | ||||
| 		return m_aabbMax; | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /// btConvexConcaveCollisionAlgorithm  supports collision between convex shapes and (concave) trianges meshes. | ||||
| class btConvexConcaveCollisionAlgorithm  : public btActivatingCollisionAlgorithm | ||||
| { | ||||
|  | ||||
| 	bool	m_isSwapped; | ||||
|  | ||||
| 	btConvexTriangleCallback m_btConvexTriangleCallback; | ||||
|  | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); | ||||
|  | ||||
| 	virtual ~btConvexConcaveCollisionAlgorithm(); | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	btScalar	calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray); | ||||
| 	 | ||||
| 	void	clearCache(); | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); | ||||
| 			return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	struct SwappedCreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); | ||||
| 			return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //CONVEX_CONCAVE_COLLISION_ALGORITHM_H | ||||
| @@ -0,0 +1,580 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| ///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance | ||||
| ///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums | ||||
| ///with reproduction case | ||||
| //define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1 | ||||
|  | ||||
| #include "btConvexConvexAlgorithm.h" | ||||
|  | ||||
| //#include <stdio.h> | ||||
| #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/CollisionShapes/btConvexShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btCapsuleShape.h" | ||||
|  | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "BulletCollision/CollisionShapes/btBoxShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btManifoldResult.h" | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" | ||||
| #include "BulletCollision/CollisionShapes/btSphereShape.h" | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| /////////// | ||||
|  | ||||
|  | ||||
|  | ||||
| static SIMD_FORCE_INLINE void segmentsClosestPoints( | ||||
| 	btVector3& ptsVector, | ||||
| 	btVector3& offsetA, | ||||
| 	btVector3& offsetB, | ||||
| 	btScalar& tA, btScalar& tB, | ||||
| 	const btVector3& translation, | ||||
| 	const btVector3& dirA, btScalar hlenA, | ||||
| 	const btVector3& dirB, btScalar hlenB ) | ||||
| { | ||||
| 	// compute the parameters of the closest points on each line segment | ||||
|  | ||||
| 	btScalar dirA_dot_dirB = btDot(dirA,dirB); | ||||
| 	btScalar dirA_dot_trans = btDot(dirA,translation); | ||||
| 	btScalar dirB_dot_trans = btDot(dirB,translation); | ||||
|  | ||||
| 	btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB; | ||||
|  | ||||
| 	if ( denom == 0.0f ) { | ||||
| 		tA = 0.0f; | ||||
| 	} else { | ||||
| 		tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom; | ||||
| 		if ( tA < -hlenA ) | ||||
| 			tA = -hlenA; | ||||
| 		else if ( tA > hlenA ) | ||||
| 			tA = hlenA; | ||||
| 	} | ||||
|  | ||||
| 	tB = tA * dirA_dot_dirB - dirB_dot_trans; | ||||
|  | ||||
| 	if ( tB < -hlenB ) { | ||||
| 		tB = -hlenB; | ||||
| 		tA = tB * dirA_dot_dirB + dirA_dot_trans; | ||||
|  | ||||
| 		if ( tA < -hlenA ) | ||||
| 			tA = -hlenA; | ||||
| 		else if ( tA > hlenA ) | ||||
| 			tA = hlenA; | ||||
| 	} else if ( tB > hlenB ) { | ||||
| 		tB = hlenB; | ||||
| 		tA = tB * dirA_dot_dirB + dirA_dot_trans; | ||||
|  | ||||
| 		if ( tA < -hlenA ) | ||||
| 			tA = -hlenA; | ||||
| 		else if ( tA > hlenA ) | ||||
| 			tA = hlenA; | ||||
| 	} | ||||
|  | ||||
| 	// compute the closest points relative to segment centers. | ||||
|  | ||||
| 	offsetA = dirA * tA; | ||||
| 	offsetB = dirB * tB; | ||||
|  | ||||
| 	ptsVector = translation - offsetA + offsetB; | ||||
| } | ||||
|  | ||||
|  | ||||
| static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance( | ||||
| 	btVector3& normalOnB, | ||||
| 	btVector3& pointOnB, | ||||
| 	btScalar capsuleLengthA, | ||||
| 	btScalar	capsuleRadiusA, | ||||
| 	btScalar capsuleLengthB, | ||||
| 	btScalar	capsuleRadiusB, | ||||
| 	int capsuleAxisA, | ||||
| 	int capsuleAxisB, | ||||
| 	const btTransform& transformA, | ||||
| 	const btTransform& transformB, | ||||
| 	btScalar distanceThreshold ) | ||||
| { | ||||
| 	btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA); | ||||
| 	btVector3 translationA = transformA.getOrigin(); | ||||
| 	btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB); | ||||
| 	btVector3 translationB = transformB.getOrigin(); | ||||
|  | ||||
| 	// translation between centers | ||||
|  | ||||
| 	btVector3 translation = translationB - translationA; | ||||
|  | ||||
| 	// compute the closest points of the capsule line segments | ||||
|  | ||||
| 	btVector3 ptsVector;           // the vector between the closest points | ||||
| 	 | ||||
| 	btVector3 offsetA, offsetB;    // offsets from segment centers to their closest points | ||||
| 	btScalar tA, tB;              // parameters on line segment | ||||
|  | ||||
| 	segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation, | ||||
| 						   directionA, capsuleLengthA, directionB, capsuleLengthB ); | ||||
|  | ||||
| 	btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB; | ||||
|  | ||||
| 	if ( distance > distanceThreshold ) | ||||
| 		return distance; | ||||
|  | ||||
| 	btScalar lenSqr = ptsVector.length2(); | ||||
| 	if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON)) | ||||
| 	{ | ||||
| 		//degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA' | ||||
| 		btVector3 q; | ||||
| 		btPlaneSpace1(directionA,normalOnB,q); | ||||
| 	} else | ||||
| 	{ | ||||
| 		// compute the contact normal | ||||
| 		normalOnB = ptsVector*-btRecipSqrt(lenSqr); | ||||
| 	} | ||||
| 	pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB; | ||||
|  | ||||
| 	return distance; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ////////// | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver) | ||||
| { | ||||
| 	m_numPerturbationIterations = 0; | ||||
| 	m_minimumPointsPerturbationThreshold = 3; | ||||
| 	m_simplexSolver = simplexSolver; | ||||
| 	m_pdSolver = pdSolver; | ||||
| } | ||||
|  | ||||
| btConvexConvexAlgorithm::CreateFunc::~CreateFunc()  | ||||
| {  | ||||
| } | ||||
|  | ||||
| btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) | ||||
| : btActivatingCollisionAlgorithm(ci,body0,body1), | ||||
| m_simplexSolver(simplexSolver), | ||||
| m_pdSolver(pdSolver), | ||||
| m_ownManifold (false), | ||||
| m_manifoldPtr(mf), | ||||
| m_lowLevelOfDetail(false), | ||||
| #ifdef USE_SEPDISTANCE_UTIL2 | ||||
| m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(), | ||||
| 			  (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()), | ||||
| #endif | ||||
| m_numPerturbationIterations(numPerturbationIterations), | ||||
| m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) | ||||
| { | ||||
| 	(void)body0; | ||||
| 	(void)body1; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btConvexConvexAlgorithm::~btConvexConvexAlgorithm() | ||||
| { | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr) | ||||
| 			m_dispatcher->releaseManifold(m_manifoldPtr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void	btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel) | ||||
| { | ||||
| 	m_lowLevelOfDetail = useLowLevel; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct btPerturbedContactResult : public btManifoldResult | ||||
| { | ||||
| 	btManifoldResult* m_originalManifoldResult; | ||||
| 	btTransform m_transformA; | ||||
| 	btTransform m_transformB; | ||||
| 	btTransform	m_unPerturbedTransform; | ||||
| 	bool	m_perturbA; | ||||
| 	btIDebugDraw*	m_debugDrawer; | ||||
|  | ||||
|  | ||||
| 	btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer) | ||||
| 		:m_originalManifoldResult(originalResult), | ||||
| 		m_transformA(transformA), | ||||
| 		m_transformB(transformB), | ||||
| 		m_unPerturbedTransform(unPerturbedTransform), | ||||
| 		m_perturbA(perturbA), | ||||
| 		m_debugDrawer(debugDrawer) | ||||
| 	{ | ||||
| 	} | ||||
| 	virtual ~ btPerturbedContactResult() | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth) | ||||
| 	{ | ||||
| 		btVector3 endPt,startPt; | ||||
| 		btScalar newDepth; | ||||
| 		btVector3 newNormal; | ||||
|  | ||||
| 		if (m_perturbA) | ||||
| 		{ | ||||
| 			btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth; | ||||
| 			endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg); | ||||
| 			newDepth = (endPt -  pointInWorld).dot(normalOnBInWorld); | ||||
| 			startPt = endPt+normalOnBInWorld*newDepth; | ||||
| 		} else | ||||
| 		{ | ||||
| 			endPt = pointInWorld + normalOnBInWorld*orgDepth; | ||||
| 			startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld); | ||||
| 			newDepth = (endPt -  startPt).dot(normalOnBInWorld); | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| //#define DEBUG_CONTACTS 1 | ||||
| #ifdef DEBUG_CONTACTS | ||||
| 		m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0)); | ||||
| 		m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0)); | ||||
| 		m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1)); | ||||
| #endif //DEBUG_CONTACTS | ||||
|  | ||||
| 		 | ||||
| 		m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth); | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
| extern btScalar gContactBreakingThreshold; | ||||
|  | ||||
|  | ||||
| // | ||||
| // Convex-Convex collision algorithm | ||||
| // | ||||
| void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
|  | ||||
| 	if (!m_manifoldPtr) | ||||
| 	{ | ||||
| 		//swapped? | ||||
| 		m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); | ||||
| 		m_ownManifold = true; | ||||
| 	} | ||||
| 	resultOut->setPersistentManifold(m_manifoldPtr); | ||||
|  | ||||
| 	//comment-out next line to test multi-contact generation | ||||
| 	//resultOut->getPersistentManifold()->clearManifold(); | ||||
| 	 | ||||
|  | ||||
| 	btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape()); | ||||
| 	btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape()); | ||||
|  | ||||
| 	btVector3  normalOnB; | ||||
| 		btVector3  pointOnBWorld; | ||||
| #ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER | ||||
| 	if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		btCapsuleShape* capsuleA = (btCapsuleShape*) min0; | ||||
| 		btCapsuleShape* capsuleB = (btCapsuleShape*) min1; | ||||
| 		btVector3 localScalingA = capsuleA->getLocalScaling(); | ||||
| 		btVector3 localScalingB = capsuleB->getLocalScaling(); | ||||
| 		 | ||||
| 		btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); | ||||
|  | ||||
| 		btScalar dist = capsuleCapsuleDistance(normalOnB,	pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(), | ||||
| 			capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(), | ||||
| 			body0->getWorldTransform(),body1->getWorldTransform(),threshold); | ||||
|  | ||||
| 		if (dist<threshold) | ||||
| 		{ | ||||
| 			btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON)); | ||||
| 			resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);	 | ||||
| 		} | ||||
| 		resultOut->refreshContactPoints(); | ||||
| 		return; | ||||
| 	} | ||||
| #endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER | ||||
|  | ||||
|  | ||||
| #ifdef USE_SEPDISTANCE_UTIL2 | ||||
| 	if (dispatchInfo.m_useConvexConservativeDistanceUtil) | ||||
| 	{ | ||||
| 		m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform()); | ||||
| 	} | ||||
|  | ||||
| 	if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f) | ||||
| #endif //USE_SEPDISTANCE_UTIL2 | ||||
|  | ||||
| 	{ | ||||
|  | ||||
| 	 | ||||
| 	btGjkPairDetector::ClosestPointInput input; | ||||
|  | ||||
| 	btGjkPairDetector	gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver); | ||||
| 	//TODO: if (dispatchInfo.m_useContinuous) | ||||
| 	gjkPairDetector.setMinkowskiA(min0); | ||||
| 	gjkPairDetector.setMinkowskiB(min1); | ||||
|  | ||||
| #ifdef USE_SEPDISTANCE_UTIL2 | ||||
| 	if (dispatchInfo.m_useConvexConservativeDistanceUtil) | ||||
| 	{ | ||||
| 		input.m_maximumDistanceSquared = BT_LARGE_FLOAT; | ||||
| 	} else | ||||
| #endif //USE_SEPDISTANCE_UTIL2 | ||||
| 	{ | ||||
| 		if (dispatchInfo.m_convexMaxDistanceUseCPT) | ||||
| 		{ | ||||
| 			input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold(); | ||||
| 		} else | ||||
| 		{ | ||||
| 			input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); | ||||
| 		} | ||||
| 		input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; | ||||
| 	} | ||||
|  | ||||
| 	input.m_stackAlloc = dispatchInfo.m_stackAllocator; | ||||
| 	input.m_transformA = body0->getWorldTransform(); | ||||
| 	input.m_transformB = body1->getWorldTransform(); | ||||
|  | ||||
| 	gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); | ||||
|  | ||||
| 	 | ||||
|  | ||||
| #ifdef USE_SEPDISTANCE_UTIL2 | ||||
| 	btScalar sepDist = 0.f; | ||||
| 	if (dispatchInfo.m_useConvexConservativeDistanceUtil) | ||||
| 	{ | ||||
| 		sepDist = gjkPairDetector.getCachedSeparatingDistance(); | ||||
| 		if (sepDist>SIMD_EPSILON) | ||||
| 		{ | ||||
| 			sepDist += dispatchInfo.m_convexConservativeDistanceThreshold; | ||||
| 			//now perturbe directions to get multiple contact points | ||||
| 			 | ||||
| 		} | ||||
| 	} | ||||
| #endif //USE_SEPDISTANCE_UTIL2 | ||||
|  | ||||
| 	//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects | ||||
| 	 | ||||
| 	//perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points | ||||
| 	if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold) | ||||
| 	{ | ||||
| 		 | ||||
| 		int i; | ||||
| 		btVector3 v0,v1; | ||||
| 		btVector3 sepNormalWorldSpace; | ||||
| 	 | ||||
| 		sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized(); | ||||
| 		btPlaneSpace1(sepNormalWorldSpace,v0,v1); | ||||
|  | ||||
|  | ||||
| 		bool perturbeA = true; | ||||
| 		const btScalar angleLimit = 0.125f * SIMD_PI; | ||||
| 		btScalar perturbeAngle; | ||||
| 		btScalar radiusA = min0->getAngularMotionDisc(); | ||||
| 		btScalar radiusB = min1->getAngularMotionDisc(); | ||||
| 		if (radiusA < radiusB) | ||||
| 		{ | ||||
| 			perturbeAngle = gContactBreakingThreshold /radiusA; | ||||
| 			perturbeA = true; | ||||
| 		} else | ||||
| 		{ | ||||
| 			perturbeAngle = gContactBreakingThreshold / radiusB; | ||||
| 			perturbeA = false; | ||||
| 		} | ||||
| 		if ( perturbeAngle > angleLimit )  | ||||
| 				perturbeAngle = angleLimit; | ||||
|  | ||||
| 		btTransform unPerturbedTransform; | ||||
| 		if (perturbeA) | ||||
| 		{ | ||||
| 			unPerturbedTransform = input.m_transformA; | ||||
| 		} else | ||||
| 		{ | ||||
| 			unPerturbedTransform = input.m_transformB; | ||||
| 		} | ||||
| 		 | ||||
| 		for ( i=0;i<m_numPerturbationIterations;i++) | ||||
| 		{ | ||||
| 			if (v0.length2()>SIMD_EPSILON) | ||||
| 			{ | ||||
| 			btQuaternion perturbeRot(v0,perturbeAngle); | ||||
| 			btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); | ||||
| 			btQuaternion rotq(sepNormalWorldSpace,iterationAngle); | ||||
| 			 | ||||
| 			 | ||||
| 			if (perturbeA) | ||||
| 			{ | ||||
| 				input.m_transformA.setBasis(  btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis()); | ||||
| 				input.m_transformB = body1->getWorldTransform(); | ||||
| #ifdef DEBUG_CONTACTS | ||||
| 				dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0); | ||||
| #endif //DEBUG_CONTACTS | ||||
| 			} else | ||||
| 			{ | ||||
| 				input.m_transformA = body0->getWorldTransform(); | ||||
| 				input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis()); | ||||
| #ifdef DEBUG_CONTACTS | ||||
| 				dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0); | ||||
| #endif | ||||
| 			} | ||||
| 			 | ||||
| 			btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw); | ||||
| 			gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw); | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
| #ifdef USE_SEPDISTANCE_UTIL2 | ||||
| 	if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON)) | ||||
| 	{ | ||||
| 		m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform()); | ||||
| 	} | ||||
| #endif //USE_SEPDISTANCE_UTIL2 | ||||
|  | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		resultOut->refreshContactPoints(); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| bool disableCcd = false; | ||||
| btScalar	btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)resultOut; | ||||
| 	(void)dispatchInfo; | ||||
| 	///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold | ||||
|      | ||||
| 	///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold | ||||
| 	///col0->m_worldTransform, | ||||
| 	btScalar resultFraction = btScalar(1.); | ||||
|  | ||||
|  | ||||
| 	btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2(); | ||||
| 	btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2(); | ||||
|      | ||||
| 	if (squareMot0 < col0->getCcdSquareMotionThreshold() && | ||||
| 		squareMot1 < col1->getCcdSquareMotionThreshold()) | ||||
| 		return resultFraction; | ||||
|  | ||||
| 	if (disableCcd) | ||||
| 		return btScalar(1.); | ||||
|  | ||||
|  | ||||
| 	//An adhoc way of testing the Continuous Collision Detection algorithms | ||||
| 	//One object is approximated as a sphere, to simplify things | ||||
| 	//Starting in penetration should report no time of impact | ||||
| 	//For proper CCD, better accuracy and handling of 'allowed' penetration should be added | ||||
| 	//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies) | ||||
|  | ||||
| 		 | ||||
| 	/// Convex0 against sphere for Convex1 | ||||
| 	{ | ||||
| 		btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape()); | ||||
|  | ||||
| 		btSphereShape	sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation | ||||
| 		btConvexCast::CastResult result; | ||||
| 		btVoronoiSimplexSolver voronoiSimplex; | ||||
| 		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); | ||||
| 		///Simplification, one object is simplified as a sphere | ||||
| 		btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex); | ||||
| 		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); | ||||
| 		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), | ||||
| 			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) | ||||
| 		{ | ||||
| 		 | ||||
| 			//store result.m_fraction in both bodies | ||||
| 		 | ||||
| 			if (col0->getHitFraction()> result.m_fraction) | ||||
| 				col0->setHitFraction( result.m_fraction ); | ||||
|  | ||||
| 			if (col1->getHitFraction() > result.m_fraction) | ||||
| 				col1->setHitFraction( result.m_fraction); | ||||
|  | ||||
| 			if (resultFraction > result.m_fraction) | ||||
| 				resultFraction = result.m_fraction; | ||||
|  | ||||
| 		} | ||||
| 		 | ||||
| 		 | ||||
|  | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	/// Sphere (for convex0) against Convex1 | ||||
| 	{ | ||||
| 		btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape()); | ||||
|  | ||||
| 		btSphereShape	sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation | ||||
| 		btConvexCast::CastResult result; | ||||
| 		btVoronoiSimplexSolver voronoiSimplex; | ||||
| 		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); | ||||
| 		///Simplification, one object is simplified as a sphere | ||||
| 		btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex); | ||||
| 		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); | ||||
| 		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), | ||||
| 			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) | ||||
| 		{ | ||||
| 		 | ||||
| 			//store result.m_fraction in both bodies | ||||
| 		 | ||||
| 			if (col0->getHitFraction()	> result.m_fraction) | ||||
| 				col0->setHitFraction( result.m_fraction); | ||||
|  | ||||
| 			if (col1->getHitFraction() > result.m_fraction) | ||||
| 				col1->setHitFraction( result.m_fraction); | ||||
|  | ||||
| 			if (resultFraction > result.m_fraction) | ||||
| 				resultFraction = result.m_fraction; | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	return resultFraction; | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,109 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONVEX_CONVEX_ALGORITHM_H | ||||
| #define CONVEX_CONVEX_ALGORITHM_H | ||||
|  | ||||
| #include "btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" | ||||
| #include "btCollisionCreateFunc.h" | ||||
| #include "btCollisionDispatcher.h" | ||||
| #include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil | ||||
|  | ||||
| class btConvexPenetrationDepthSolver; | ||||
|  | ||||
| ///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise | ||||
| ///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions. | ||||
| ///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util | ||||
| ///for certain pairs that have a small size ratio | ||||
|  | ||||
| //#define USE_SEPDISTANCE_UTIL2 1 | ||||
|  | ||||
| ///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects. | ||||
| ///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal. | ||||
| ///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 | ||||
| class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm | ||||
| { | ||||
| #ifdef USE_SEPDISTANCE_UTIL2 | ||||
| 	btConvexSeparatingDistanceUtil	m_sepDistance; | ||||
| #endif | ||||
| 	btSimplexSolverInterface*		m_simplexSolver; | ||||
| 	btConvexPenetrationDepthSolver* m_pdSolver; | ||||
|  | ||||
| 	 | ||||
| 	bool	m_ownManifold; | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
| 	bool			m_lowLevelOfDetail; | ||||
| 	 | ||||
| 	int m_numPerturbationIterations; | ||||
| 	int m_minimumPointsPerturbationThreshold; | ||||
|  | ||||
|  | ||||
| 	///cache separating vector to speedup collision detection | ||||
| 	 | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); | ||||
|  | ||||
|  | ||||
| 	virtual ~btConvexConvexAlgorithm(); | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		///should we use m_ownManifold to avoid adding duplicates? | ||||
| 		if (m_manifoldPtr && m_ownManifold) | ||||
| 			manifoldArray.push_back(m_manifoldPtr); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	void	setLowLevelOfDetail(bool useLowLevel); | ||||
|  | ||||
|  | ||||
| 	const btPersistentManifold*	getManifold() | ||||
| 	{ | ||||
| 		return m_manifoldPtr; | ||||
| 	} | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
|  | ||||
| 		btConvexPenetrationDepthSolver*		m_pdSolver; | ||||
| 		btSimplexSolverInterface*			m_simplexSolver; | ||||
| 		int m_numPerturbationIterations; | ||||
| 		int m_minimumPointsPerturbationThreshold; | ||||
|  | ||||
| 		CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver); | ||||
| 		 | ||||
| 		virtual ~CreateFunc(); | ||||
|  | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); | ||||
| 			return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //CONVEX_CONVEX_ALGORITHM_H | ||||
| @@ -0,0 +1,155 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose, | ||||
| including commercial applications, and to alter it and redistribute it freely, | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btConvexPlaneCollisionAlgorithm.h" | ||||
|  | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/CollisionShapes/btConvexShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" | ||||
|  | ||||
| //#include <stdio.h> | ||||
|  | ||||
| btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold) | ||||
| : btCollisionAlgorithm(ci), | ||||
| m_ownManifold(false), | ||||
| m_manifoldPtr(mf), | ||||
| m_isSwapped(isSwapped), | ||||
| m_numPerturbationIterations(numPerturbationIterations), | ||||
| m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) | ||||
| { | ||||
| 	btCollisionObject* convexObj = m_isSwapped? col1 : col0; | ||||
| 	btCollisionObject* planeObj = m_isSwapped? col0 : col1; | ||||
|  | ||||
| 	if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj)) | ||||
| 	{ | ||||
| 		m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj); | ||||
| 		m_ownManifold = true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm() | ||||
| { | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr) | ||||
| 			m_dispatcher->releaseManifold(m_manifoldPtr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
|     btCollisionObject* convexObj = m_isSwapped? body1 : body0; | ||||
| 	btCollisionObject* planeObj = m_isSwapped? body0: body1; | ||||
|  | ||||
| 	btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); | ||||
| 	btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); | ||||
|  | ||||
|     bool hasCollision = false; | ||||
| 	const btVector3& planeNormal = planeShape->getPlaneNormal(); | ||||
| 	const btScalar& planeConstant = planeShape->getPlaneConstant(); | ||||
| 	 | ||||
| 	btTransform convexWorldTransform = convexObj->getWorldTransform(); | ||||
| 	btTransform convexInPlaneTrans; | ||||
| 	convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform; | ||||
| 	//now perturbe the convex-world transform | ||||
| 	convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot); | ||||
| 	btTransform planeInConvex; | ||||
| 	planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform(); | ||||
| 	 | ||||
| 	btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); | ||||
|  | ||||
| 	btVector3 vtxInPlane = convexInPlaneTrans(vtx); | ||||
| 	btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); | ||||
|  | ||||
| 	btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; | ||||
| 	btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; | ||||
|  | ||||
| 	hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); | ||||
| 	resultOut->setPersistentManifold(m_manifoldPtr); | ||||
| 	if (hasCollision) | ||||
| 	{ | ||||
| 		/// report a contact. internally this will be kept persistent, and contact reduction is done | ||||
| 		btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; | ||||
| 		btVector3 pOnB = vtxInPlaneWorld; | ||||
| 		resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)dispatchInfo; | ||||
| 	if (!m_manifoldPtr) | ||||
| 		return; | ||||
|  | ||||
|     btCollisionObject* convexObj = m_isSwapped? body1 : body0; | ||||
| 	btCollisionObject* planeObj = m_isSwapped? body0: body1; | ||||
|  | ||||
| 	btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); | ||||
| 	btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); | ||||
|  | ||||
|      | ||||
| 	const btVector3& planeNormal = planeShape->getPlaneNormal(); | ||||
| 	//const btScalar& planeConstant = planeShape->getPlaneConstant(); | ||||
|  | ||||
| 	//first perform a collision query with the non-perturbated collision objects | ||||
| 	{ | ||||
| 		btQuaternion rotq(0,0,0,1); | ||||
| 		collideSingleContact(rotq,body0,body1,dispatchInfo,resultOut); | ||||
| 	} | ||||
|  | ||||
| 	if (resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold) | ||||
| 	{ | ||||
| 		btVector3 v0,v1; | ||||
| 		btPlaneSpace1(planeNormal,v0,v1); | ||||
| 		//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects | ||||
|  | ||||
| 		const btScalar angleLimit = 0.125f * SIMD_PI; | ||||
| 		btScalar perturbeAngle; | ||||
| 		btScalar radius = convexShape->getAngularMotionDisc(); | ||||
| 		perturbeAngle = gContactBreakingThreshold / radius; | ||||
| 		if ( perturbeAngle > angleLimit )  | ||||
| 				perturbeAngle = angleLimit; | ||||
|  | ||||
| 		btQuaternion perturbeRot(v0,perturbeAngle); | ||||
| 		for (int i=0;i<m_numPerturbationIterations;i++) | ||||
| 		{ | ||||
| 			btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); | ||||
| 			btQuaternion rotq(planeNormal,iterationAngle); | ||||
| 			collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0,body1,dispatchInfo,resultOut); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr->getNumContacts()) | ||||
| 		{ | ||||
| 			resultOut->refreshContactPoints(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)resultOut; | ||||
| 	(void)dispatchInfo; | ||||
| 	(void)col0; | ||||
| 	(void)col1; | ||||
|  | ||||
| 	//not yet | ||||
| 	return btScalar(1.); | ||||
| } | ||||
| @@ -0,0 +1,84 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose, | ||||
| including commercial applications, and to alter it and redistribute it freely, | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H | ||||
| #define CONVEX_PLANE_COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | ||||
| class btPersistentManifold; | ||||
| #include "btCollisionDispatcher.h" | ||||
|  | ||||
| #include "LinearMath/btVector3.h" | ||||
|  | ||||
| /// btSphereBoxCollisionAlgorithm  provides sphere-box collision detection. | ||||
| /// Other features are frame-coherency (persistent data) and collision response. | ||||
| class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm | ||||
| { | ||||
| 	bool		m_ownManifold; | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
| 	bool		m_isSwapped; | ||||
| 	int			m_numPerturbationIterations; | ||||
| 	int			m_minimumPointsPerturbationThreshold; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold); | ||||
|  | ||||
| 	virtual ~btConvexPlaneCollisionAlgorithm(); | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	void collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr && m_ownManifold) | ||||
| 		{ | ||||
| 			manifoldArray.push_back(m_manifoldPtr); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		int	m_numPerturbationIterations; | ||||
| 		int m_minimumPointsPerturbationThreshold; | ||||
| 			 | ||||
| 		CreateFunc()  | ||||
| 			: m_numPerturbationIterations(1), | ||||
| 			m_minimumPointsPerturbationThreshold(1) | ||||
| 		{ | ||||
| 		} | ||||
| 		 | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm)); | ||||
| 			if (!m_swapped) | ||||
| 			{ | ||||
| 				return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); | ||||
| 			} else | ||||
| 			{ | ||||
| 				return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //CONVEX_PLANE_COLLISION_ALGORITHM_H | ||||
|  | ||||
| @@ -0,0 +1,298 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btDefaultCollisionConfiguration.h" | ||||
|  | ||||
| #include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" | ||||
| #ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
| #include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" | ||||
| #endif //USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
| #include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| #include "LinearMath/btStackAlloc.h" | ||||
| #include "LinearMath/btPoolAllocator.h" | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) | ||||
| //btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc*	stackAlloc,btPoolAllocator*	persistentManifoldPool,btPoolAllocator*	collisionAlgorithmPool) | ||||
| { | ||||
|  | ||||
| 	void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); | ||||
| 	m_simplexSolver = new (mem)btVoronoiSimplexSolver(); | ||||
|  | ||||
| 	if (constructionInfo.m_useEpaPenetrationAlgorithm) | ||||
| 	{ | ||||
| 		mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); | ||||
| 		m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; | ||||
| 	}else | ||||
| 	{ | ||||
| 		mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16); | ||||
| 		m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver; | ||||
| 	} | ||||
| 	 | ||||
| 	//default CreationFunctions, filling the m_doubleDispatch table | ||||
| 	mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); | ||||
| 	m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); | ||||
| 	mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; | ||||
| 	mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; | ||||
| 	mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; | ||||
| 	mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); | ||||
| 	m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; | ||||
| 	mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); | ||||
| 	m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; | ||||
| 	 | ||||
| 	mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; | ||||
| #ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
| 	mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; | ||||
| 	mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; | ||||
| 	m_boxSphereCF->m_swapped = true; | ||||
| #endif //USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
|  | ||||
| 	mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; | ||||
| 	mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; | ||||
| 	m_triangleSphereCF->m_swapped = true; | ||||
| 	 | ||||
| 	mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc; | ||||
|  | ||||
| 	//convex versus plane | ||||
| 	mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; | ||||
| 	mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); | ||||
| 	m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; | ||||
| 	m_planeConvexCF->m_swapped = true; | ||||
| 	 | ||||
| 	///calculate maximum element size, big enough to fit any collision algorithm in the memory pool | ||||
| 	int maxSize = sizeof(btConvexConvexAlgorithm); | ||||
| 	int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); | ||||
| 	int maxSize3 = sizeof(btCompoundCollisionAlgorithm); | ||||
| 	int sl = sizeof(btConvexSeparatingDistanceUtil); | ||||
| 	sl = sizeof(btGjkPairDetector); | ||||
| 	int	collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize); | ||||
| 	collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2); | ||||
| 	collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); | ||||
|  | ||||
| 	if (constructionInfo.m_stackAlloc) | ||||
| 	{ | ||||
| 		m_ownsStackAllocator = false; | ||||
| 		this->m_stackAlloc = constructionInfo.m_stackAlloc; | ||||
| 	} else | ||||
| 	{ | ||||
| 		m_ownsStackAllocator = true; | ||||
| 		void* mem = btAlignedAlloc(sizeof(btStackAlloc),16); | ||||
| 		m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize); | ||||
| 	} | ||||
| 		 | ||||
| 	if (constructionInfo.m_persistentManifoldPool) | ||||
| 	{ | ||||
| 		m_ownsPersistentManifoldPool = false; | ||||
| 		m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool; | ||||
| 	} else | ||||
| 	{ | ||||
| 		m_ownsPersistentManifoldPool = true; | ||||
| 		void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); | ||||
| 		m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize); | ||||
| 	} | ||||
| 	 | ||||
| 	if (constructionInfo.m_collisionAlgorithmPool) | ||||
| 	{ | ||||
| 		m_ownsCollisionAlgorithmPool = false; | ||||
| 		m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool; | ||||
| 	} else | ||||
| 	{ | ||||
| 		m_ownsCollisionAlgorithmPool = true; | ||||
| 		void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); | ||||
| 		m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() | ||||
| { | ||||
| 	if (m_ownsStackAllocator) | ||||
| 	{ | ||||
| 		m_stackAlloc->destroy(); | ||||
| 		m_stackAlloc->~btStackAlloc(); | ||||
| 		btAlignedFree(m_stackAlloc); | ||||
| 	} | ||||
| 	if (m_ownsCollisionAlgorithmPool) | ||||
| 	{ | ||||
| 		m_collisionAlgorithmPool->~btPoolAllocator(); | ||||
| 		btAlignedFree(m_collisionAlgorithmPool); | ||||
| 	} | ||||
| 	if (m_ownsPersistentManifoldPool) | ||||
| 	{ | ||||
| 		m_persistentManifoldPool->~btPoolAllocator(); | ||||
| 		btAlignedFree(m_persistentManifoldPool); | ||||
| 	} | ||||
|  | ||||
| 	m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree(	m_convexConvexCreateFunc); | ||||
|  | ||||
| 	m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_convexConcaveCreateFunc); | ||||
| 	m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_swappedConvexConcaveCreateFunc); | ||||
|  | ||||
| 	m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_compoundCreateFunc); | ||||
|  | ||||
| 	m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_swappedCompoundCreateFunc); | ||||
|  | ||||
| 	m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_emptyCreateFunc); | ||||
|  | ||||
| 	m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_sphereSphereCF); | ||||
|  | ||||
| #ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
| 	m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_sphereBoxCF); | ||||
| 	m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_boxSphereCF); | ||||
| #endif //USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
|  | ||||
| 	m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_sphereTriangleCF); | ||||
| 	m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_triangleSphereCF); | ||||
| 	m_boxBoxCF->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_boxBoxCF); | ||||
|  | ||||
| 	m_convexPlaneCF->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_convexPlaneCF); | ||||
| 	m_planeConvexCF->~btCollisionAlgorithmCreateFunc(); | ||||
| 	btAlignedFree( m_planeConvexCF); | ||||
|  | ||||
| 	m_simplexSolver->~btVoronoiSimplexSolver(); | ||||
| 	btAlignedFree(m_simplexSolver); | ||||
|  | ||||
| 	m_pdSolver->~btConvexPenetrationDepthSolver(); | ||||
| 	 | ||||
| 	btAlignedFree(m_pdSolver); | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) | ||||
| { | ||||
|  | ||||
|  | ||||
|  | ||||
| 	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		return	m_sphereSphereCF; | ||||
| 	} | ||||
| #ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
| 	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		return	m_sphereBoxCF; | ||||
| 	} | ||||
|  | ||||
| 	if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		return	m_boxSphereCF; | ||||
| 	} | ||||
| #endif //USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
|  | ||||
|  | ||||
| 	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		return	m_sphereTriangleCF; | ||||
| 	} | ||||
|  | ||||
| 	if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE  ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		return	m_triangleSphereCF; | ||||
| 	}  | ||||
|  | ||||
| 	if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		return m_boxBoxCF; | ||||
| 	} | ||||
| 	 | ||||
| 	if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		return m_convexPlaneCF; | ||||
| 	} | ||||
|  | ||||
| 	if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE)) | ||||
| 	{ | ||||
| 		return m_planeConvexCF; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 	if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) | ||||
| 	{ | ||||
| 		return m_convexConvexCreateFunc; | ||||
| 	} | ||||
|  | ||||
| 	if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) | ||||
| 	{ | ||||
| 		return m_convexConcaveCreateFunc; | ||||
| 	} | ||||
|  | ||||
| 	if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) | ||||
| 	{ | ||||
| 		return m_swappedConvexConcaveCreateFunc; | ||||
| 	} | ||||
|  | ||||
| 	if (btBroadphaseProxy::isCompound(proxyType0)) | ||||
| 	{ | ||||
| 		return m_compoundCreateFunc; | ||||
| 	} else | ||||
| 	{ | ||||
| 		if (btBroadphaseProxy::isCompound(proxyType1)) | ||||
| 		{ | ||||
| 			return m_swappedCompoundCreateFunc; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//failed to find an algorithm | ||||
| 	return m_emptyCreateFunc; | ||||
| } | ||||
|  | ||||
| void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold) | ||||
| { | ||||
| 	btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc; | ||||
| 	convexConvex->m_numPerturbationIterations = numPerturbationIterations; | ||||
| 	convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; | ||||
| } | ||||
| @@ -0,0 +1,135 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BT_DEFAULT_COLLISION_CONFIGURATION | ||||
| #define BT_DEFAULT_COLLISION_CONFIGURATION | ||||
|  | ||||
| #include "btCollisionConfiguration.h" | ||||
| class btVoronoiSimplexSolver; | ||||
| class btConvexPenetrationDepthSolver; | ||||
|  | ||||
| struct	btDefaultCollisionConstructionInfo | ||||
| { | ||||
| 	btStackAlloc*		m_stackAlloc; | ||||
| 	btPoolAllocator*	m_persistentManifoldPool; | ||||
| 	btPoolAllocator*	m_collisionAlgorithmPool; | ||||
| 	int					m_defaultMaxPersistentManifoldPoolSize; | ||||
| 	int					m_defaultMaxCollisionAlgorithmPoolSize; | ||||
| 	int					m_customCollisionAlgorithmMaxElementSize; | ||||
| 	int					m_defaultStackAllocatorSize; | ||||
| 	int					m_useEpaPenetrationAlgorithm; | ||||
|  | ||||
| 	btDefaultCollisionConstructionInfo() | ||||
| 		:m_stackAlloc(0), | ||||
| 		m_persistentManifoldPool(0), | ||||
| 		m_collisionAlgorithmPool(0), | ||||
| 		m_defaultMaxPersistentManifoldPoolSize(4096), | ||||
| 		m_defaultMaxCollisionAlgorithmPoolSize(4096), | ||||
| 		m_customCollisionAlgorithmMaxElementSize(0), | ||||
| 		m_defaultStackAllocatorSize(0), | ||||
| 		m_useEpaPenetrationAlgorithm(true) | ||||
| 	{ | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| ///btCollisionConfiguration allows to configure Bullet collision detection | ||||
| ///stack allocator, pool memory allocators | ||||
| ///@todo: describe the meaning | ||||
| class	btDefaultCollisionConfiguration : public btCollisionConfiguration | ||||
| { | ||||
|  | ||||
| protected: | ||||
|  | ||||
| 	int	m_persistentManifoldPoolSize; | ||||
| 	 | ||||
| 	btStackAlloc*	m_stackAlloc; | ||||
| 	bool	m_ownsStackAllocator; | ||||
|  | ||||
| 	btPoolAllocator*	m_persistentManifoldPool; | ||||
| 	bool	m_ownsPersistentManifoldPool; | ||||
|  | ||||
|  | ||||
| 	btPoolAllocator*	m_collisionAlgorithmPool; | ||||
| 	bool	m_ownsCollisionAlgorithmPool; | ||||
|  | ||||
| 	//default simplex/penetration depth solvers | ||||
| 	btVoronoiSimplexSolver*	m_simplexSolver; | ||||
| 	btConvexPenetrationDepthSolver*	m_pdSolver; | ||||
| 	 | ||||
| 	//default CreationFunctions, filling the m_doubleDispatch table | ||||
| 	btCollisionAlgorithmCreateFunc*	m_convexConvexCreateFunc; | ||||
| 	btCollisionAlgorithmCreateFunc*	m_convexConcaveCreateFunc; | ||||
| 	btCollisionAlgorithmCreateFunc*	m_swappedConvexConcaveCreateFunc; | ||||
| 	btCollisionAlgorithmCreateFunc*	m_compoundCreateFunc; | ||||
| 	btCollisionAlgorithmCreateFunc*	m_swappedCompoundCreateFunc; | ||||
| 	btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; | ||||
| 	btCollisionAlgorithmCreateFunc* m_sphereSphereCF; | ||||
| #ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
| 	btCollisionAlgorithmCreateFunc* m_sphereBoxCF; | ||||
| 	btCollisionAlgorithmCreateFunc* m_boxSphereCF; | ||||
| #endif //USE_BUGGY_SPHERE_BOX_ALGORITHM | ||||
|  | ||||
| 	btCollisionAlgorithmCreateFunc* m_boxBoxCF; | ||||
| 	btCollisionAlgorithmCreateFunc*	m_sphereTriangleCF; | ||||
| 	btCollisionAlgorithmCreateFunc*	m_triangleSphereCF; | ||||
| 	btCollisionAlgorithmCreateFunc*	m_planeConvexCF; | ||||
| 	btCollisionAlgorithmCreateFunc*	m_convexPlaneCF; | ||||
| 	 | ||||
| public: | ||||
|  | ||||
|  | ||||
| 	btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); | ||||
|  | ||||
| 	virtual ~btDefaultCollisionConfiguration(); | ||||
|  | ||||
| 		///memory pools | ||||
| 	virtual btPoolAllocator* getPersistentManifoldPool() | ||||
| 	{ | ||||
| 		return m_persistentManifoldPool; | ||||
| 	} | ||||
|  | ||||
| 	virtual btPoolAllocator* getCollisionAlgorithmPool() | ||||
| 	{ | ||||
| 		return m_collisionAlgorithmPool; | ||||
| 	} | ||||
|  | ||||
| 	virtual btStackAlloc*	getStackAllocator() | ||||
| 	{ | ||||
| 		return m_stackAlloc; | ||||
| 	} | ||||
|  | ||||
| 	virtual	btVoronoiSimplexSolver*	getSimplexSolver() | ||||
| 	{ | ||||
| 		return m_simplexSolver; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); | ||||
|  | ||||
| 	///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm. | ||||
| 	///By default, this feature is disabled for best performance. | ||||
| 	///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature. | ||||
| 	///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled | ||||
| 	///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. | ||||
| 	///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points. | ||||
| 	///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection. | ||||
| 	void	setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BT_DEFAULT_COLLISION_CONFIGURATION | ||||
|  | ||||
| @@ -0,0 +1,34 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btEmptyCollisionAlgorithm.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) | ||||
| 	: btCollisionAlgorithm(ci) | ||||
| { | ||||
| } | ||||
|  | ||||
| void btEmptyAlgorithm::processCollision (btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) | ||||
| { | ||||
| } | ||||
|  | ||||
| btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) | ||||
| { | ||||
| 	return btScalar(1.); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,54 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef EMPTY_ALGORITH | ||||
| #define EMPTY_ALGORITH | ||||
| #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" | ||||
| #include "btCollisionCreateFunc.h" | ||||
| #include "btCollisionDispatcher.h" | ||||
|  | ||||
| #define ATTRIBUTE_ALIGNED(a) | ||||
|  | ||||
| ///EmptyAlgorithm is a stub for unsupported collision pairs. | ||||
| ///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame. | ||||
| class btEmptyAlgorithm : public btCollisionAlgorithm | ||||
| { | ||||
|  | ||||
| public: | ||||
| 	 | ||||
| 	btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			(void)body0; | ||||
| 			(void)body1; | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm)); | ||||
| 			return new(mem) btEmptyAlgorithm(ci); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| } ATTRIBUTE_ALIGNED(16); | ||||
|  | ||||
| #endif //EMPTY_ALGORITH | ||||
							
								
								
									
										171
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btGhostObject.h" | ||||
| #include "btCollisionWorld.h" | ||||
| #include "BulletCollision/CollisionShapes/btConvexShape.h" | ||||
| #include "LinearMath/btAabbUtil2.h" | ||||
|  | ||||
| btGhostObject::btGhostObject() | ||||
| { | ||||
| 	m_internalType = CO_GHOST_OBJECT; | ||||
| } | ||||
|  | ||||
| btGhostObject::~btGhostObject() | ||||
| { | ||||
| 	///btGhostObject should have been removed from the world, so no overlapping objects | ||||
| 	btAssert(!m_overlappingObjects.size()); | ||||
| } | ||||
|  | ||||
|  | ||||
| void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) | ||||
| { | ||||
| 	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; | ||||
| 	btAssert(otherObject); | ||||
| 	///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure | ||||
| 	int index = m_overlappingObjects.findLinearSearch(otherObject); | ||||
| 	if (index==m_overlappingObjects.size()) | ||||
| 	{ | ||||
| 		//not found | ||||
| 		m_overlappingObjects.push_back(otherObject); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy) | ||||
| { | ||||
| 	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; | ||||
| 	btAssert(otherObject); | ||||
| 	int index = m_overlappingObjects.findLinearSearch(otherObject); | ||||
| 	if (index<m_overlappingObjects.size()) | ||||
| 	{ | ||||
| 		m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1]; | ||||
| 		m_overlappingObjects.pop_back(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| btPairCachingGhostObject::btPairCachingGhostObject() | ||||
| { | ||||
| 	m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); | ||||
| } | ||||
|  | ||||
| btPairCachingGhostObject::~btPairCachingGhostObject() | ||||
| { | ||||
| 	m_hashPairCache->~btHashedOverlappingPairCache(); | ||||
| 	btAlignedFree( m_hashPairCache ); | ||||
| } | ||||
|  | ||||
| void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) | ||||
| { | ||||
| 	btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle(); | ||||
| 	btAssert(actualThisProxy); | ||||
|  | ||||
| 	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; | ||||
| 	btAssert(otherObject); | ||||
| 	int index = m_overlappingObjects.findLinearSearch(otherObject); | ||||
| 	if (index==m_overlappingObjects.size()) | ||||
| 	{ | ||||
| 		m_overlappingObjects.push_back(otherObject); | ||||
| 		m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1) | ||||
| { | ||||
| 	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; | ||||
| 	btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle(); | ||||
| 	btAssert(actualThisProxy); | ||||
|  | ||||
| 	btAssert(otherObject); | ||||
| 	int index = m_overlappingObjects.findLinearSearch(otherObject); | ||||
| 	if (index<m_overlappingObjects.size()) | ||||
| 	{ | ||||
| 		m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1]; | ||||
| 		m_overlappingObjects.pop_back(); | ||||
| 		m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const | ||||
| { | ||||
| 	btTransform	convexFromTrans,convexToTrans; | ||||
| 	convexFromTrans = convexFromWorld; | ||||
| 	convexToTrans = convexToWorld; | ||||
| 	btVector3 castShapeAabbMin, castShapeAabbMax; | ||||
| 	/* Compute AABB that encompasses angular movement */ | ||||
| 	{ | ||||
| 		btVector3 linVel, angVel; | ||||
| 		btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); | ||||
| 		btTransform R; | ||||
| 		R.setIdentity (); | ||||
| 		R.setRotation (convexFromTrans.getRotation()); | ||||
| 		castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); | ||||
| 	} | ||||
|  | ||||
| 	/// go over all objects, and if the ray intersects their aabb + cast shape aabb, | ||||
| 	// do a ray-shape query using convexCaster (CCD) | ||||
| 	int i; | ||||
| 	for (i=0;i<m_overlappingObjects.size();i++) | ||||
| 	{ | ||||
| 		btCollisionObject*	collisionObject= m_overlappingObjects[i]; | ||||
| 		//only perform raycast if filterMask matches | ||||
| 		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { | ||||
| 			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); | ||||
| 			btVector3 collisionObjectAabbMin,collisionObjectAabbMax; | ||||
| 			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); | ||||
| 			AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); | ||||
| 			btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing | ||||
| 			btVector3 hitNormal; | ||||
| 			if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) | ||||
| 			{ | ||||
| 				btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans, | ||||
| 					collisionObject, | ||||
| 						collisionObject->getCollisionShape(), | ||||
| 						collisionObject->getWorldTransform(), | ||||
| 						resultCallback, | ||||
| 						allowedCcdPenetration); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| void	btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const | ||||
| { | ||||
| 	btTransform rayFromTrans; | ||||
| 	rayFromTrans.setIdentity(); | ||||
| 	rayFromTrans.setOrigin(rayFromWorld); | ||||
| 	btTransform  rayToTrans; | ||||
| 	rayToTrans.setIdentity(); | ||||
| 	rayToTrans.setOrigin(rayToWorld); | ||||
|  | ||||
|  | ||||
| 	int i; | ||||
| 	for (i=0;i<m_overlappingObjects.size();i++) | ||||
| 	{ | ||||
| 		btCollisionObject*	collisionObject= m_overlappingObjects[i]; | ||||
| 		//only perform raycast if filterMask matches | ||||
| 		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))  | ||||
| 		{ | ||||
| 			btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, | ||||
| 							collisionObject, | ||||
| 								collisionObject->getCollisionShape(), | ||||
| 								collisionObject->getWorldTransform(), | ||||
| 								resultCallback); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										175
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BT_GHOST_OBJECT_H | ||||
| #define BT_GHOST_OBJECT_H | ||||
|  | ||||
|  | ||||
| #include "btCollisionObject.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h" | ||||
| #include "LinearMath/btAlignedAllocator.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" | ||||
| #include "btCollisionWorld.h" | ||||
|  | ||||
| class btConvexShape; | ||||
|  | ||||
| class btDispatcher; | ||||
|  | ||||
| ///The btGhostObject can keep track of all objects that are overlapping | ||||
| ///By default, this overlap is based on the AABB | ||||
| ///This is useful for creating a character controller, collision sensors/triggers, explosions etc. | ||||
| ///We plan on adding rayTest and other queries for the btGhostObject | ||||
| ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject | ||||
| { | ||||
| protected: | ||||
|  | ||||
| 	btAlignedObjectArray<btCollisionObject*> m_overlappingObjects; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btGhostObject(); | ||||
|  | ||||
| 	virtual ~btGhostObject(); | ||||
|  | ||||
| 	void	convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const; | ||||
|  | ||||
| 	void	rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;  | ||||
|  | ||||
| 	///this method is mainly for expert/internal use only. | ||||
| 	virtual void	addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0); | ||||
| 	///this method is mainly for expert/internal use only. | ||||
| 	virtual void	removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0); | ||||
|  | ||||
| 	int	getNumOverlappingObjects() const | ||||
| 	{ | ||||
| 		return m_overlappingObjects.size(); | ||||
| 	} | ||||
|  | ||||
| 	btCollisionObject*	getOverlappingObject(int index) | ||||
| 	{ | ||||
| 		return m_overlappingObjects[index]; | ||||
| 	} | ||||
|  | ||||
| 	const btCollisionObject*	getOverlappingObject(int index) const | ||||
| 	{ | ||||
| 		return m_overlappingObjects[index]; | ||||
| 	} | ||||
|  | ||||
| 	btAlignedObjectArray<btCollisionObject*>&	getOverlappingPairs() | ||||
| 	{ | ||||
| 		return m_overlappingObjects; | ||||
| 	} | ||||
|  | ||||
| 	const btAlignedObjectArray<btCollisionObject*>	getOverlappingPairs() const | ||||
| 	{ | ||||
| 		return m_overlappingObjects; | ||||
| 	} | ||||
|  | ||||
| 	// | ||||
| 	// internal cast | ||||
| 	// | ||||
|  | ||||
| 	static const btGhostObject*	upcast(const btCollisionObject* colObj) | ||||
| 	{ | ||||
| 		if (colObj->getInternalType()==CO_GHOST_OBJECT) | ||||
| 			return (const btGhostObject*)colObj; | ||||
| 		return 0; | ||||
| 	} | ||||
| 	static btGhostObject*			upcast(btCollisionObject* colObj) | ||||
| 	{ | ||||
| 		if (colObj->getInternalType()==CO_GHOST_OBJECT) | ||||
| 			return (btGhostObject*)colObj; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
| class	btPairCachingGhostObject : public btGhostObject | ||||
| { | ||||
| 	btHashedOverlappingPairCache*	m_hashPairCache; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btPairCachingGhostObject(); | ||||
|  | ||||
| 	virtual ~btPairCachingGhostObject(); | ||||
|  | ||||
| 	///this method is mainly for expert/internal use only. | ||||
| 	virtual void	addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0); | ||||
|  | ||||
| 	virtual void	removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0); | ||||
|  | ||||
| 	btHashedOverlappingPairCache*	getOverlappingPairCache() | ||||
| 	{ | ||||
| 		return m_hashPairCache; | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| ///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject. | ||||
| class btGhostPairCallback : public btOverlappingPairCallback | ||||
| { | ||||
| 	 | ||||
| public: | ||||
| 	btGhostPairCallback() | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	virtual ~btGhostPairCallback() | ||||
| 	{ | ||||
| 		 | ||||
| 	} | ||||
|  | ||||
| 	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) | ||||
| 	{ | ||||
| 		btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject; | ||||
| 		btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject; | ||||
| 		btGhostObject* ghost0 = 		btGhostObject::upcast(colObj0); | ||||
| 		btGhostObject* ghost1 = 		btGhostObject::upcast(colObj1); | ||||
| 		if (ghost0) | ||||
| 			ghost0->addOverlappingObjectInternal(proxy1, proxy0); | ||||
| 		if (ghost1) | ||||
| 			ghost1->addOverlappingObjectInternal(proxy0, proxy1); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) | ||||
| 	{ | ||||
| 		btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject; | ||||
| 		btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject; | ||||
| 		btGhostObject* ghost0 = 		btGhostObject::upcast(colObj0); | ||||
| 		btGhostObject* ghost1 = 		btGhostObject::upcast(colObj1); | ||||
| 		if (ghost0) | ||||
| 			ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0); | ||||
| 		if (ghost1) | ||||
| 			ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) | ||||
| 	{ | ||||
| 		btAssert(0); | ||||
| 		//need to keep track of all ghost objects and call them here | ||||
| 		//m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher); | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @@ -0,0 +1,772 @@ | ||||
| #include "btInternalEdgeUtility.h" | ||||
|  | ||||
| #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btTriangleShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" | ||||
| #include "LinearMath/btIDebugDraw.h" | ||||
|  | ||||
|  | ||||
| //#define DEBUG_INTERNAL_EDGE | ||||
|  | ||||
|  | ||||
| #ifdef DEBUG_INTERNAL_EDGE | ||||
| #include <stdio.h> | ||||
| #endif //DEBUG_INTERNAL_EDGE | ||||
|  | ||||
|  | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| static btIDebugDraw* gDebugDrawer = 0; | ||||
|  | ||||
| void	btSetDebugDrawer(btIDebugDraw* debugDrawer) | ||||
| { | ||||
| 	gDebugDrawer = debugDrawer; | ||||
| } | ||||
|  | ||||
| static void    btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color) | ||||
| { | ||||
| 	if (gDebugDrawer) | ||||
| 		gDebugDrawer->drawLine(from,to,color); | ||||
| } | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
|  | ||||
| static int	btGetHash(int partId, int triangleIndex) | ||||
| { | ||||
| 	int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; | ||||
| 	return hash; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB) | ||||
| { | ||||
| 	const btVector3 refAxis0  = edgeA; | ||||
| 	const btVector3 refAxis1  = normalA; | ||||
| 	const btVector3 swingAxis = normalB; | ||||
| 	btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); | ||||
| 	return  angle; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct btConnectivityProcessor : public btTriangleCallback | ||||
| { | ||||
| 	int				m_partIdA; | ||||
| 	int				m_triangleIndexA; | ||||
| 	btVector3*		m_triangleVerticesA; | ||||
| 	btTriangleInfoMap*	m_triangleInfoMap; | ||||
|  | ||||
|  | ||||
| 	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) | ||||
| 	{ | ||||
| 		//skip self-collisions | ||||
| 		if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex)) | ||||
| 			return; | ||||
|  | ||||
| 		//skip duplicates (disabled for now) | ||||
| 		//if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex)) | ||||
| 		//	return; | ||||
|  | ||||
| 		//search for shared vertices and edges | ||||
| 		int numshared = 0; | ||||
| 		int sharedVertsA[3]={-1,-1,-1}; | ||||
| 		int sharedVertsB[3]={-1,-1,-1}; | ||||
|  | ||||
| 		///skip degenerate triangles | ||||
| 		btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2(); | ||||
| 		if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold) | ||||
| 			return; | ||||
|  | ||||
|  | ||||
| 		btScalar crossASqr = ((m_triangleVerticesA[1]-m_triangleVerticesA[0]).cross(m_triangleVerticesA[2]-m_triangleVerticesA[0])).length2(); | ||||
| 		///skip degenerate triangles | ||||
| 		if (crossASqr< m_triangleInfoMap->m_equalVertexThreshold) | ||||
| 			return; | ||||
|  | ||||
| #if 0 | ||||
| 		printf("triangle A[0]	=	(%f,%f,%f)\ntriangle A[1]	=	(%f,%f,%f)\ntriangle A[2]	=	(%f,%f,%f)\n", | ||||
| 			m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(), | ||||
| 			m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(), | ||||
| 			m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ()); | ||||
|  | ||||
| 		printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex); | ||||
| 		printf("triangle B[0]	=	(%f,%f,%f)\ntriangle B[1]	=	(%f,%f,%f)\ntriangle B[2]	=	(%f,%f,%f)\n", | ||||
| 			triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(), | ||||
| 			triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(), | ||||
| 			triangle[2].getX(),triangle[2].getY(),triangle[2].getZ()); | ||||
| #endif | ||||
|  | ||||
| 		for (int i=0;i<3;i++) | ||||
| 		{ | ||||
| 			for (int j=0;j<3;j++) | ||||
| 			{ | ||||
| 				if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold) | ||||
| 				{ | ||||
| 					sharedVertsA[numshared] = i; | ||||
| 					sharedVertsB[numshared] = j; | ||||
| 					numshared++; | ||||
| 					///degenerate case | ||||
| 					if(numshared >= 3) | ||||
| 						return; | ||||
| 				} | ||||
| 			} | ||||
| 			///degenerate case | ||||
| 			if(numshared >= 3) | ||||
| 				return; | ||||
| 		} | ||||
| 		switch (numshared) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			{ | ||||
| 				break; | ||||
| 			} | ||||
| 		case 1: | ||||
| 			{ | ||||
| 				//shared vertex | ||||
| 				break; | ||||
| 			} | ||||
| 		case 2: | ||||
| 			{ | ||||
| 				//shared edge | ||||
| 				//we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct | ||||
| 				if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2) | ||||
| 				{ | ||||
| 					sharedVertsA[0] = 2; | ||||
| 					sharedVertsA[1] = 0; | ||||
| 					int tmp = sharedVertsB[1]; | ||||
| 					sharedVertsB[1] = sharedVertsB[0]; | ||||
| 					sharedVertsB[0] = tmp; | ||||
| 				} | ||||
|  | ||||
| 				int hash = btGetHash(m_partIdA,m_triangleIndexA); | ||||
|  | ||||
| 				btTriangleInfo* info = m_triangleInfoMap->find(hash); | ||||
| 				if (!info) | ||||
| 				{ | ||||
| 					btTriangleInfo tmp; | ||||
| 					m_triangleInfoMap->insert(hash,tmp); | ||||
| 					info = m_triangleInfoMap->find(hash); | ||||
| 				} | ||||
|  | ||||
| 				int sumvertsA = sharedVertsA[0]+sharedVertsA[1]; | ||||
| 				int otherIndexA = 3-sumvertsA; | ||||
|  | ||||
| 				 | ||||
| 				btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]); | ||||
|  | ||||
| 				btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]); | ||||
| 				int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]); | ||||
|  | ||||
| 				btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]); | ||||
| 				//btTriangleShape tB(triangle[0],triangle[1],triangle[2]); | ||||
|  | ||||
| 				btVector3 normalA; | ||||
| 				btVector3 normalB; | ||||
| 				tA.calcNormal(normalA); | ||||
| 				tB.calcNormal(normalB); | ||||
| 				edge.normalize(); | ||||
| 				btVector3 edgeCrossA = edge.cross(normalA).normalize(); | ||||
|  | ||||
| 				{ | ||||
| 					btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]]; | ||||
| 					if (edgeCrossA.dot(tmp) < 0) | ||||
| 					{ | ||||
| 						edgeCrossA*=-1; | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				btVector3 edgeCrossB = edge.cross(normalB).normalize(); | ||||
|  | ||||
| 				{ | ||||
| 					btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]]; | ||||
| 					if (edgeCrossB.dot(tmp) < 0) | ||||
| 					{ | ||||
| 						edgeCrossB*=-1; | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				btScalar	angle2 = 0; | ||||
| 				btScalar	ang4 = 0.f; | ||||
|  | ||||
|  | ||||
| 				btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB); | ||||
| 				btScalar len2 = calculatedEdge.length2(); | ||||
|  | ||||
| 				btScalar correctedAngle(0); | ||||
| 				btVector3 calculatedNormalB = normalA; | ||||
| 				bool isConvex = false; | ||||
|  | ||||
| 				if (len2<m_triangleInfoMap->m_planarEpsilon) | ||||
| 				{ | ||||
| 					angle2 = 0.f; | ||||
| 					ang4 = 0.f; | ||||
| 				} else | ||||
| 				{ | ||||
|  | ||||
| 					calculatedEdge.normalize(); | ||||
| 					btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA); | ||||
| 					calculatedNormalA.normalize(); | ||||
| 					angle2 = btGetAngle(calculatedNormalA,edgeCrossA,edgeCrossB); | ||||
| 					ang4 = SIMD_PI-angle2; | ||||
| 					btScalar dotA = normalA.dot(edgeCrossB); | ||||
| 					///@todo: check if we need some epsilon, due to floating point imprecision | ||||
| 					isConvex = (dotA<0.); | ||||
|  | ||||
| 					correctedAngle = isConvex ? ang4 : -ang4; | ||||
| 					btQuaternion orn2(calculatedEdge,-correctedAngle); | ||||
| 					calculatedNormalB = btMatrix3x3(orn2)*normalA; | ||||
|  | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				 | ||||
|  | ||||
| 				 | ||||
| 							 | ||||
| 				//alternatively use  | ||||
| 				//btVector3 calculatedNormalB2 = quatRotate(orn,normalA); | ||||
|  | ||||
|  | ||||
| 				switch (sumvertsA) | ||||
| 				{ | ||||
| 				case 1: | ||||
| 					{ | ||||
| 						btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1]; | ||||
| 						btQuaternion orn(edge,-correctedAngle); | ||||
| 						btVector3 computedNormalB = quatRotate(orn,normalA); | ||||
| 						btScalar bla = computedNormalB.dot(normalB); | ||||
| 						if (bla<0) | ||||
| 						{ | ||||
| 							computedNormalB*=-1; | ||||
| 							info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB; | ||||
| 						} | ||||
| #ifdef DEBUG_INTERNAL_EDGE | ||||
| 						if ((computedNormalB-normalB).length()>0.0001) | ||||
| 						{ | ||||
| 							printf("warning: normals not identical\n"); | ||||
| 						} | ||||
| #endif//DEBUG_INTERNAL_EDGE | ||||
|  | ||||
| 						info->m_edgeV0V1Angle = -correctedAngle; | ||||
|  | ||||
| 						if (isConvex) | ||||
| 							info->m_flags |= TRI_INFO_V0V1_CONVEX; | ||||
| 						break; | ||||
| 					} | ||||
| 				case 2: | ||||
| 					{ | ||||
| 						btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0]; | ||||
| 						btQuaternion orn(edge,-correctedAngle); | ||||
| 						btVector3 computedNormalB = quatRotate(orn,normalA); | ||||
| 						if (computedNormalB.dot(normalB)<0) | ||||
| 						{ | ||||
| 							computedNormalB*=-1; | ||||
| 							info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB; | ||||
| 						} | ||||
|  | ||||
| #ifdef DEBUG_INTERNAL_EDGE | ||||
| 						if ((computedNormalB-normalB).length()>0.0001) | ||||
| 						{ | ||||
| 							printf("warning: normals not identical\n"); | ||||
| 						} | ||||
| #endif //DEBUG_INTERNAL_EDGE | ||||
| 						info->m_edgeV2V0Angle = -correctedAngle; | ||||
| 						if (isConvex) | ||||
| 							info->m_flags |= TRI_INFO_V2V0_CONVEX; | ||||
| 						break;	 | ||||
| 					} | ||||
| 				case 3: | ||||
| 					{ | ||||
| 						btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2]; | ||||
| 						btQuaternion orn(edge,-correctedAngle); | ||||
| 						btVector3 computedNormalB = quatRotate(orn,normalA); | ||||
| 						if (computedNormalB.dot(normalB)<0) | ||||
| 						{ | ||||
| 							info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB; | ||||
| 							computedNormalB*=-1; | ||||
| 						} | ||||
| #ifdef DEBUG_INTERNAL_EDGE | ||||
| 						if ((computedNormalB-normalB).length()>0.0001) | ||||
| 						{ | ||||
| 							printf("warning: normals not identical\n"); | ||||
| 						} | ||||
| #endif //DEBUG_INTERNAL_EDGE | ||||
| 						info->m_edgeV1V2Angle = -correctedAngle; | ||||
|  | ||||
| 						if (isConvex) | ||||
| 							info->m_flags |= TRI_INFO_V1V2_CONVEX; | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				break; | ||||
| 			} | ||||
| 		default: | ||||
| 			{ | ||||
| 				//				printf("warning: duplicate triangle\n"); | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
| ///////////////////////////////////////////////////////// | ||||
| ///////////////////////////////////////////////////////// | ||||
|  | ||||
| void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap) | ||||
| { | ||||
| 	//the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there! | ||||
| 	if (trimeshShape->getTriangleInfoMap()) | ||||
| 		return; | ||||
|  | ||||
| 	trimeshShape->setTriangleInfoMap(triangleInfoMap); | ||||
|  | ||||
| 	btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface(); | ||||
| 	const btVector3& meshScaling = meshInterface->getScaling(); | ||||
|  | ||||
| 	for (int partId = 0; partId< meshInterface->getNumSubParts();partId++) | ||||
| 	{ | ||||
| 		const unsigned char *vertexbase = 0; | ||||
| 		int numverts = 0; | ||||
| 		PHY_ScalarType type = PHY_INTEGER; | ||||
| 		int stride = 0; | ||||
| 		const unsigned char *indexbase = 0; | ||||
| 		int indexstride = 0; | ||||
| 		int numfaces = 0; | ||||
| 		PHY_ScalarType indicestype = PHY_INTEGER; | ||||
| 		//PHY_ScalarType indexType=0; | ||||
|  | ||||
| 		btVector3 triangleVerts[3]; | ||||
| 		meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,	type,stride,&indexbase,indexstride,numfaces,indicestype,partId); | ||||
| 		btVector3 aabbMin,aabbMax; | ||||
|  | ||||
| 		for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++) | ||||
| 		{ | ||||
| 			unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride); | ||||
|  | ||||
| 			for (int j=2;j>=0;j--) | ||||
| 			{ | ||||
|  | ||||
| 				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; | ||||
| 				if (type == PHY_FLOAT) | ||||
| 				{ | ||||
| 					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); | ||||
| 					triangleVerts[j] = btVector3( | ||||
| 						graphicsbase[0]*meshScaling.getX(), | ||||
| 						graphicsbase[1]*meshScaling.getY(), | ||||
| 						graphicsbase[2]*meshScaling.getZ()); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); | ||||
| 					triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ())); | ||||
| 				} | ||||
| 			} | ||||
| 			aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | ||||
| 			aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));  | ||||
| 			aabbMin.setMin(triangleVerts[0]); | ||||
| 			aabbMax.setMax(triangleVerts[0]); | ||||
| 			aabbMin.setMin(triangleVerts[1]); | ||||
| 			aabbMax.setMax(triangleVerts[1]); | ||||
| 			aabbMin.setMin(triangleVerts[2]); | ||||
| 			aabbMax.setMax(triangleVerts[2]); | ||||
|  | ||||
| 			btConnectivityProcessor connectivityProcessor; | ||||
| 			connectivityProcessor.m_partIdA = partId; | ||||
| 			connectivityProcessor.m_triangleIndexA = triangleIndex; | ||||
| 			connectivityProcessor.m_triangleVerticesA = &triangleVerts[0]; | ||||
| 			connectivityProcessor.m_triangleInfoMap  = triangleInfoMap; | ||||
|  | ||||
| 			trimeshShape->processAllTriangles(&connectivityProcessor,aabbMin,aabbMax); | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| // Given a point and a line segment (defined by two points), compute the closest point | ||||
| // in the line.  Cap the point at the endpoints of the line segment. | ||||
| void btNearestPointInLineSegment(const btVector3 &point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint) | ||||
| { | ||||
| 	btVector3 lineDelta     = line1 - line0; | ||||
|  | ||||
| 	// Handle degenerate lines | ||||
| 	if ( lineDelta.fuzzyZero()) | ||||
| 	{ | ||||
| 		nearestPoint = line0; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta); | ||||
|  | ||||
| 		// Clamp the point to conform to the segment's endpoints | ||||
| 		if ( delta < 0 ) | ||||
| 			delta = 0; | ||||
| 		else if ( delta > 1 ) | ||||
| 			delta = 1; | ||||
|  | ||||
| 		nearestPoint = line0 + lineDelta*delta; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| bool	btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal) | ||||
| { | ||||
| 	btVector3 tri_normal = tri_normal_org; | ||||
| 	//we only have a local triangle normal, not a local contact normal -> only normal in world space... | ||||
| 	//either compute the current angle all in local space, or all in world space | ||||
|  | ||||
| 	btVector3 edgeCross = edge.cross(tri_normal).normalize(); | ||||
| 	btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB); | ||||
|  | ||||
| 	if (correctedEdgeAngle<0) | ||||
| 	{ | ||||
| 		if (curAngle < correctedEdgeAngle) | ||||
| 		{ | ||||
| 			btScalar diffAngle = correctedEdgeAngle-curAngle; | ||||
| 			btQuaternion rotation(edge,diffAngle ); | ||||
| 			clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (correctedEdgeAngle>=0) | ||||
| 	{ | ||||
| 		if (curAngle > correctedEdgeAngle) | ||||
| 		{ | ||||
| 			btScalar diffAngle = correctedEdgeAngle-curAngle; | ||||
| 			btQuaternion rotation(edge,diffAngle ); | ||||
| 			clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /// Changes a btManifoldPoint collision normal to the normal from the mesh. | ||||
| void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* colObj0,const btCollisionObject* colObj1, int partId0, int index0, int normalAdjustFlags) | ||||
| { | ||||
| 	//btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE); | ||||
| 	if (colObj0->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE) | ||||
| 		return; | ||||
|  | ||||
| 	btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape(); | ||||
| 	btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap(); | ||||
| 	if (!triangleInfoMapPtr) | ||||
| 		return; | ||||
|  | ||||
| 	int hash = btGetHash(partId0,index0); | ||||
|  | ||||
|  | ||||
| 	btTriangleInfo* info = triangleInfoMapPtr->find(hash); | ||||
| 	if (!info) | ||||
| 		return; | ||||
|  | ||||
| 	btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f; | ||||
| 	 | ||||
| 	const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0->getCollisionShape()); | ||||
| 	btVector3 v0,v1,v2; | ||||
| 	tri_shape->getVertex(0,v0); | ||||
| 	tri_shape->getVertex(1,v1); | ||||
| 	tri_shape->getVertex(2,v2); | ||||
|  | ||||
| 	btVector3 center = (v0+v1+v2)*btScalar(1./3.); | ||||
|  | ||||
| 	btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0); | ||||
| 	btVector3 tri_normal; | ||||
| 	tri_shape->calcNormal(tri_normal); | ||||
|  | ||||
| 	//btScalar dot = tri_normal.dot(cp.m_normalWorldOnB); | ||||
| 	btVector3 nearest; | ||||
| 	btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest); | ||||
|  | ||||
| 	btVector3 contact = cp.m_localPointB; | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 	const btTransform& tr = colObj0->getWorldTransform(); | ||||
| 	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,red); | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
|  | ||||
|  | ||||
| 	bool isNearEdge = false; | ||||
|  | ||||
| 	int numConcaveEdgeHits = 0; | ||||
| 	int numConvexEdgeHits = 0; | ||||
|  | ||||
| 	btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; | ||||
| 	localContactNormalOnB.normalize();//is this necessary? | ||||
|  | ||||
| 	if ((info->m_edgeV0V1Angle)< SIMD_2_PI) | ||||
| 	{ | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); | ||||
| #endif | ||||
| 		btScalar len = (contact-nearest).length(); | ||||
| 		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold) | ||||
| 		{ | ||||
| 			btVector3 edge(v0-v1); | ||||
| 			isNearEdge = true; | ||||
|  | ||||
| 			if (info->m_edgeV0V1Angle==btScalar(0)) | ||||
| 			{ | ||||
| 				numConcaveEdgeHits++; | ||||
| 			} else | ||||
| 			{ | ||||
|  | ||||
| 				bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX); | ||||
| 				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); | ||||
| 	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); | ||||
| 	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| 				btVector3 nA = swapFactor * tri_normal; | ||||
|  | ||||
| 				btQuaternion orn(edge,info->m_edgeV0V1Angle); | ||||
| 				btVector3 computedNormalB = quatRotate(orn,tri_normal); | ||||
| 				if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB) | ||||
| 					computedNormalB*=-1; | ||||
| 				btVector3 nB = swapFactor*computedNormalB; | ||||
|  | ||||
| 				btScalar	NdotA = localContactNormalOnB.dot(nA); | ||||
| 				btScalar	NdotB = localContactNormalOnB.dot(nB); | ||||
| 				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon); | ||||
|  | ||||
| #ifdef DEBUG_INTERNAL_EDGE | ||||
| 				{ | ||||
| 					 | ||||
| 					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); | ||||
| 				} | ||||
| #endif //DEBUG_INTERNAL_EDGE | ||||
|  | ||||
|  | ||||
| 				if (backFacingNormal) | ||||
| 				{ | ||||
| 					numConcaveEdgeHits++; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					numConvexEdgeHits++; | ||||
| 					btVector3 clampedLocalNormal; | ||||
| 					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal); | ||||
| 					if (isClamped) | ||||
| 					{ | ||||
| 						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) | ||||
| 						{ | ||||
| 							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; | ||||
| 							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); | ||||
| 							cp.m_normalWorldOnB = newNormal; | ||||
| 							// Reproject collision point along normal. (what about cp.m_distance1?) | ||||
| 							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; | ||||
| 							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); | ||||
| 							 | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	btNearestPointInLineSegment(contact,v1,v2,nearest); | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green); | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| 	if ((info->m_edgeV1V2Angle)< SIMD_2_PI) | ||||
| 	{ | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
|  | ||||
|  | ||||
| 		btScalar len = (contact-nearest).length(); | ||||
| 		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold) | ||||
| 		{ | ||||
| 			isNearEdge = true; | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 			btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white); | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| 			btVector3 edge(v1-v2); | ||||
|  | ||||
| 			isNearEdge = true; | ||||
|  | ||||
| 			if (info->m_edgeV1V2Angle == btScalar(0)) | ||||
| 			{ | ||||
| 				numConcaveEdgeHits++; | ||||
| 			} else | ||||
| 			{ | ||||
| 				bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX)!=0; | ||||
| 				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); | ||||
| 	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); | ||||
| 	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| 				btVector3 nA = swapFactor * tri_normal; | ||||
| 				 | ||||
| 				btQuaternion orn(edge,info->m_edgeV1V2Angle); | ||||
| 				btVector3 computedNormalB = quatRotate(orn,tri_normal); | ||||
| 				if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB) | ||||
| 					computedNormalB*=-1; | ||||
| 				btVector3 nB = swapFactor*computedNormalB; | ||||
|  | ||||
| #ifdef DEBUG_INTERNAL_EDGE | ||||
| 				{ | ||||
| 					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); | ||||
| 				} | ||||
| #endif //DEBUG_INTERNAL_EDGE | ||||
|  | ||||
|  | ||||
| 				btScalar	NdotA = localContactNormalOnB.dot(nA); | ||||
| 				btScalar	NdotB = localContactNormalOnB.dot(nB); | ||||
| 				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon); | ||||
|  | ||||
| 				if (backFacingNormal) | ||||
| 				{ | ||||
| 					numConcaveEdgeHits++; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					numConvexEdgeHits++; | ||||
| 					btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; | ||||
| 					btVector3 clampedLocalNormal; | ||||
| 					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal); | ||||
| 					if (isClamped) | ||||
| 					{ | ||||
| 						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) | ||||
| 						{ | ||||
| 							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; | ||||
| 							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); | ||||
| 							cp.m_normalWorldOnB = newNormal; | ||||
| 							// Reproject collision point along normal. | ||||
| 							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; | ||||
| 							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	btNearestPointInLineSegment(contact,v2,v0,nearest); | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue); | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| 	if ((info->m_edgeV2V0Angle)< SIMD_2_PI) | ||||
| 	{ | ||||
|  | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| 		btScalar len = (contact-nearest).length(); | ||||
| 		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold) | ||||
| 		{ | ||||
| 			isNearEdge = true; | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 			btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white); | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| 			btVector3 edge(v2-v0); | ||||
|  | ||||
| 			if (info->m_edgeV2V0Angle==btScalar(0)) | ||||
| 			{ | ||||
| 				numConcaveEdgeHits++; | ||||
| 			} else | ||||
| 			{ | ||||
|  | ||||
| 				bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX)!=0; | ||||
| 				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); | ||||
| 	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| 				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); | ||||
| 	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| 				btVector3 nA = swapFactor * tri_normal; | ||||
| 				btQuaternion orn(edge,info->m_edgeV2V0Angle); | ||||
| 				btVector3 computedNormalB = quatRotate(orn,tri_normal); | ||||
| 				if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB) | ||||
| 					computedNormalB*=-1; | ||||
| 				btVector3 nB = swapFactor*computedNormalB; | ||||
|  | ||||
| #ifdef DEBUG_INTERNAL_EDGE | ||||
| 				{ | ||||
| 					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); | ||||
| 				} | ||||
| #endif //DEBUG_INTERNAL_EDGE | ||||
|  | ||||
| 				btScalar	NdotA = localContactNormalOnB.dot(nA); | ||||
| 				btScalar	NdotB = localContactNormalOnB.dot(nB); | ||||
| 				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon); | ||||
|  | ||||
| 				if (backFacingNormal) | ||||
| 				{ | ||||
| 					numConcaveEdgeHits++; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					numConvexEdgeHits++; | ||||
| 					//				printf("hitting convex edge\n"); | ||||
|  | ||||
|  | ||||
| 					btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; | ||||
| 					btVector3 clampedLocalNormal; | ||||
| 					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal); | ||||
| 					if (isClamped) | ||||
| 					{ | ||||
| 						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) | ||||
| 						{ | ||||
| 							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; | ||||
| 							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); | ||||
| 							cp.m_normalWorldOnB = newNormal; | ||||
| 							// Reproject collision point along normal. | ||||
| 							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; | ||||
| 							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); | ||||
| 						} | ||||
| 					} | ||||
| 				}  | ||||
| 			} | ||||
| 			 | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| #ifdef DEBUG_INTERNAL_EDGE | ||||
| 	{ | ||||
| 		btVector3 color(0,1,1); | ||||
| 		btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color); | ||||
| 	} | ||||
| #endif //DEBUG_INTERNAL_EDGE | ||||
|  | ||||
| 	if (isNearEdge) | ||||
| 	{ | ||||
|  | ||||
| 		if (numConcaveEdgeHits>0) | ||||
| 		{ | ||||
| 			if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0) | ||||
| 			{ | ||||
| 				//fix tri_normal so it pointing the same direction as the current local contact normal | ||||
| 				if (tri_normal.dot(localContactNormalOnB) < 0) | ||||
| 				{ | ||||
| 					tri_normal *= -1; | ||||
| 				} | ||||
| 				cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis()*tri_normal; | ||||
| 			} else | ||||
| 			{ | ||||
| 				//modify the normal to be the triangle normal (or backfacing normal) | ||||
| 				cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *(tri_normal *frontFacing); | ||||
| 			} | ||||
| 			 | ||||
| 			 | ||||
| 			// Reproject collision point along normal. | ||||
| 			cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; | ||||
| 			cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,46 @@ | ||||
|  | ||||
| #ifndef BT_INTERNAL_EDGE_UTILITY_H | ||||
| #define BT_INTERNAL_EDGE_UTILITY_H | ||||
|  | ||||
| #include "LinearMath/btHashMap.h" | ||||
| #include "LinearMath/btVector3.h" | ||||
|  | ||||
| #include "BulletCollision/CollisionShapes/btTriangleInfoMap.h" | ||||
|  | ||||
| ///The btInternalEdgeUtility helps to avoid or reduce artifacts due to wrong collision normals caused by internal edges. | ||||
| ///See also http://code.google.com/p/bullet/issues/detail?id=27 | ||||
|  | ||||
| class btBvhTriangleMeshShape; | ||||
| class btCollisionObject; | ||||
| class btManifoldPoint; | ||||
| class btIDebugDraw; | ||||
|  | ||||
|  | ||||
|  | ||||
| enum btInternalEdgeAdjustFlags | ||||
| { | ||||
| 	BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1, | ||||
| 	BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended | ||||
| 	BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4 | ||||
| }; | ||||
|  | ||||
|  | ||||
| ///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo' | ||||
| void	btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap); | ||||
|  | ||||
|  | ||||
| ///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo) | ||||
| ///If this info map is missing, or the triangle is not store in this map, nothing will be done | ||||
| void	btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* trimeshColObj0,const btCollisionObject* otherColObj1, int partId0, int index0, int normalAdjustFlags = 0); | ||||
|  | ||||
| ///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly. | ||||
| ///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap | ||||
| //#define BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
| #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
| void	btSetDebugDrawer(btIDebugDraw* debugDrawer); | ||||
| #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | ||||
|  | ||||
|  | ||||
| #endif //BT_INTERNAL_EDGE_UTILITY_H | ||||
|  | ||||
| @@ -0,0 +1,134 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #include "btManifoldResult.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
|  | ||||
|  | ||||
| ///This is to allow MaterialCombiner/Custom Friction/Restitution values | ||||
| ContactAddedCallback		gContactAddedCallback=0; | ||||
|  | ||||
| ///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; | ||||
| inline btScalar	calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1) | ||||
| { | ||||
| 	btScalar friction = body0->getFriction() * body1->getFriction(); | ||||
|  | ||||
| 	const btScalar MAX_FRICTION  = btScalar(10.); | ||||
| 	if (friction < -MAX_FRICTION) | ||||
| 		friction = -MAX_FRICTION; | ||||
| 	if (friction > MAX_FRICTION) | ||||
| 		friction = MAX_FRICTION; | ||||
| 	return friction; | ||||
|  | ||||
| } | ||||
|  | ||||
| inline btScalar	calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1) | ||||
| { | ||||
| 	return body0->getRestitution() * body1->getRestitution(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		:m_manifoldPtr(0), | ||||
| 		m_body0(body0), | ||||
| 		m_body1(body1) | ||||
| #ifdef DEBUG_PART_INDEX | ||||
| 		,m_partId0(-1), | ||||
| 	m_partId1(-1), | ||||
| 	m_index0(-1), | ||||
| 	m_index1(-1) | ||||
| #endif //DEBUG_PART_INDEX | ||||
| { | ||||
| 	m_rootTransA = body0->getWorldTransform(); | ||||
| 	m_rootTransB = body1->getWorldTransform(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) | ||||
| { | ||||
| 	btAssert(m_manifoldPtr); | ||||
| 	//order in manifold needs to match | ||||
| 	 | ||||
| 	if (depth > m_manifoldPtr->getContactBreakingThreshold()) | ||||
| 		return; | ||||
|  | ||||
| 	bool isSwapped = m_manifoldPtr->getBody0() != m_body0; | ||||
|  | ||||
| 	btVector3 pointA = pointInWorld + normalOnBInWorld * depth; | ||||
|  | ||||
| 	btVector3 localA; | ||||
| 	btVector3 localB; | ||||
| 	 | ||||
| 	if (isSwapped) | ||||
| 	{ | ||||
| 		localA = m_rootTransB.invXform(pointA ); | ||||
| 		localB = m_rootTransA.invXform(pointInWorld); | ||||
| 	} else | ||||
| 	{ | ||||
| 		localA = m_rootTransA.invXform(pointA ); | ||||
| 		localB = m_rootTransB.invXform(pointInWorld); | ||||
| 	} | ||||
|  | ||||
| 	btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); | ||||
| 	newPt.m_positionWorldOnA = pointA; | ||||
| 	newPt.m_positionWorldOnB = pointInWorld; | ||||
| 	 | ||||
| 	int insertIndex = m_manifoldPtr->getCacheEntry(newPt); | ||||
|  | ||||
| 	newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); | ||||
| 	newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); | ||||
|  | ||||
|    //BP mod, store contact triangles. | ||||
| 	if (isSwapped) | ||||
| 	{ | ||||
| 		newPt.m_partId0 = m_partId1; | ||||
| 		newPt.m_partId1 = m_partId0; | ||||
| 		newPt.m_index0  = m_index1; | ||||
| 		newPt.m_index1  = m_index0; | ||||
| 	} else | ||||
| 	{ | ||||
| 		newPt.m_partId0 = m_partId0; | ||||
| 		newPt.m_partId1 = m_partId1; | ||||
| 		newPt.m_index0  = m_index0; | ||||
| 		newPt.m_index1  = m_index1; | ||||
| 	} | ||||
| 	//printf("depth=%f\n",depth); | ||||
| 	///@todo, check this for any side effects | ||||
| 	if (insertIndex >= 0) | ||||
| 	{ | ||||
| 		//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); | ||||
| 		m_manifoldPtr->replaceContactPoint(newPt,insertIndex); | ||||
| 	} else | ||||
| 	{ | ||||
| 		insertIndex = m_manifoldPtr->addManifoldPoint(newPt); | ||||
| 	} | ||||
| 	 | ||||
| 	//User can override friction and/or restitution | ||||
| 	if (gContactAddedCallback && | ||||
| 		//and if either of the two bodies requires custom material | ||||
| 		 ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) || | ||||
| 		   (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK))) | ||||
| 	{ | ||||
| 		//experimental feature info, for per-triangle material etc. | ||||
| 		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; | ||||
| 		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; | ||||
| 		(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
							
								
								
									
										128
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #ifndef MANIFOLD_RESULT_H | ||||
| #define MANIFOLD_RESULT_H | ||||
|  | ||||
| class btCollisionObject; | ||||
| #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" | ||||
| class btManifoldPoint; | ||||
|  | ||||
| #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" | ||||
|  | ||||
| #include "LinearMath/btTransform.h" | ||||
|  | ||||
| typedef bool (*ContactAddedCallback)(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); | ||||
| extern ContactAddedCallback		gContactAddedCallback; | ||||
|  | ||||
| //#define DEBUG_PART_INDEX 1 | ||||
|  | ||||
|  | ||||
| ///btManifoldResult is a helper class to manage  contact results. | ||||
| class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result | ||||
| { | ||||
| protected: | ||||
|  | ||||
| 	btPersistentManifold* m_manifoldPtr; | ||||
|  | ||||
| 	//we need this for compounds | ||||
| 	btTransform	m_rootTransA; | ||||
| 	btTransform	m_rootTransB; | ||||
|  | ||||
| 	btCollisionObject* m_body0; | ||||
| 	btCollisionObject* m_body1; | ||||
| 	int	m_partId0; | ||||
| 	int m_partId1; | ||||
| 	int m_index0; | ||||
| 	int m_index1; | ||||
| 	 | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btManifoldResult() | ||||
| #ifdef DEBUG_PART_INDEX | ||||
| 		: | ||||
| 	m_partId0(-1), | ||||
| 	m_partId1(-1), | ||||
| 	m_index0(-1), | ||||
| 	m_index1(-1) | ||||
| #endif //DEBUG_PART_INDEX | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	btManifoldResult(btCollisionObject* body0,btCollisionObject* body1); | ||||
|  | ||||
| 	virtual ~btManifoldResult() {}; | ||||
|  | ||||
| 	void	setPersistentManifold(btPersistentManifold* manifoldPtr) | ||||
| 	{ | ||||
| 		m_manifoldPtr = manifoldPtr; | ||||
| 	} | ||||
|  | ||||
| 	const btPersistentManifold*	getPersistentManifold() const | ||||
| 	{ | ||||
| 		return m_manifoldPtr; | ||||
| 	} | ||||
| 	btPersistentManifold*	getPersistentManifold() | ||||
| 	{ | ||||
| 		return m_manifoldPtr; | ||||
| 	} | ||||
|  | ||||
| 	virtual void setShapeIdentifiersA(int partId0,int index0) | ||||
| 	{ | ||||
| 		m_partId0=partId0; | ||||
| 		m_index0=index0; | ||||
| 	} | ||||
|  | ||||
| 	virtual void setShapeIdentifiersB(	int partId1,int index1) | ||||
| 	{ | ||||
| 		m_partId1=partId1; | ||||
| 		m_index1=index1; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); | ||||
|  | ||||
| 	SIMD_FORCE_INLINE	void refreshContactPoints() | ||||
| 	{ | ||||
| 		btAssert(m_manifoldPtr); | ||||
| 		if (!m_manifoldPtr->getNumContacts()) | ||||
| 			return; | ||||
|  | ||||
| 		bool isSwapped = m_manifoldPtr->getBody0() != m_body0; | ||||
|  | ||||
| 		if (isSwapped) | ||||
| 		{ | ||||
| 			m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA); | ||||
| 		} else | ||||
| 		{ | ||||
| 			m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	const btCollisionObject* getBody0Internal() const | ||||
| 	{ | ||||
| 		return m_body0; | ||||
| 	} | ||||
|  | ||||
| 	const btCollisionObject* getBody1Internal() const | ||||
| 	{ | ||||
| 		return m_body1; | ||||
| 	} | ||||
| 	 | ||||
| }; | ||||
|  | ||||
| #endif //MANIFOLD_RESULT_H | ||||
| @@ -0,0 +1,443 @@ | ||||
|  | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #include "LinearMath/btScalar.h" | ||||
| #include "btSimulationIslandManager.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDispatcher.h" | ||||
| #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionWorld.h" | ||||
|  | ||||
| //#include <stdio.h> | ||||
| #include "LinearMath/btQuickprof.h" | ||||
|  | ||||
| btSimulationIslandManager::btSimulationIslandManager(): | ||||
| m_splitIslands(true) | ||||
| { | ||||
| } | ||||
|  | ||||
| btSimulationIslandManager::~btSimulationIslandManager() | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| void btSimulationIslandManager::initUnionFind(int n) | ||||
| { | ||||
| 		m_unionFind.reset(n); | ||||
| } | ||||
| 		 | ||||
|  | ||||
| void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld) | ||||
| { | ||||
| 	 | ||||
| 	{ | ||||
| 		btOverlappingPairCache* pairCachePtr = colWorld->getPairCache(); | ||||
| 		const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs(); | ||||
| 		btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr(); | ||||
| 		 | ||||
| 		for (int i=0;i<numOverlappingPairs;i++) | ||||
| 		{ | ||||
| 			const btBroadphasePair& collisionPair = pairPtr[i]; | ||||
| 			btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; | ||||
| 			btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; | ||||
|  | ||||
| 			if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && | ||||
| 				((colObj1) && ((colObj1)->mergesSimulationIslands()))) | ||||
| 			{ | ||||
|  | ||||
| 				m_unionFind.unite((colObj0)->getIslandTag(), | ||||
| 					(colObj1)->getIslandTag()); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| #ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION | ||||
| void   btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	// put the index into m_controllers into m_tag    | ||||
| 	int index = 0; | ||||
| 	{ | ||||
|  | ||||
| 		int i; | ||||
| 		for (i=0;i<colWorld->getCollisionObjectArray().size(); i++) | ||||
| 		{ | ||||
| 			btCollisionObject*   collisionObject= colWorld->getCollisionObjectArray()[i]; | ||||
| 			//Adding filtering here | ||||
| 			if (!collisionObject->isStaticOrKinematicObject()) | ||||
| 			{ | ||||
| 				collisionObject->setIslandTag(index++); | ||||
| 			} | ||||
| 			collisionObject->setCompanionId(-1); | ||||
| 			collisionObject->setHitFraction(btScalar(1.)); | ||||
| 		} | ||||
| 	} | ||||
| 	// do the union find | ||||
|  | ||||
| 	initUnionFind( index ); | ||||
|  | ||||
| 	findUnions(dispatcher,colWorld); | ||||
| } | ||||
|  | ||||
| void   btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) | ||||
| { | ||||
| 	// put the islandId ('find' value) into m_tag    | ||||
| 	{ | ||||
| 		int index = 0; | ||||
| 		int i; | ||||
| 		for (i=0;i<colWorld->getCollisionObjectArray().size();i++) | ||||
| 		{ | ||||
| 			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; | ||||
| 			if (!collisionObject->isStaticOrKinematicObject()) | ||||
| 			{ | ||||
| 				collisionObject->setIslandTag( m_unionFind.find(index) ); | ||||
| 				//Set the correct object offset in Collision Object Array | ||||
| 				m_unionFind.getElement(index).m_sz = i; | ||||
| 				collisionObject->setCompanionId(-1); | ||||
| 				index++; | ||||
| 			} else | ||||
| 			{ | ||||
| 				collisionObject->setIslandTag(-1); | ||||
| 				collisionObject->setCompanionId(-2); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| #else //STATIC_SIMULATION_ISLAND_OPTIMIZATION | ||||
| void	btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) | ||||
| { | ||||
|  | ||||
| 	initUnionFind( int (colWorld->getCollisionObjectArray().size())); | ||||
|  | ||||
| 	// put the index into m_controllers into m_tag	 | ||||
| 	{ | ||||
|  | ||||
| 		int index = 0; | ||||
| 		int i; | ||||
| 		for (i=0;i<colWorld->getCollisionObjectArray().size(); i++) | ||||
| 		{ | ||||
| 			btCollisionObject*	collisionObject= colWorld->getCollisionObjectArray()[i]; | ||||
| 			collisionObject->setIslandTag(index); | ||||
| 			collisionObject->setCompanionId(-1); | ||||
| 			collisionObject->setHitFraction(btScalar(1.)); | ||||
| 			index++; | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| 	// do the union find | ||||
|  | ||||
| 	findUnions(dispatcher,colWorld); | ||||
| } | ||||
|  | ||||
| void	btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) | ||||
| { | ||||
| 	// put the islandId ('find' value) into m_tag	 | ||||
| 	{ | ||||
|  | ||||
|  | ||||
| 		int index = 0; | ||||
| 		int i; | ||||
| 		for (i=0;i<colWorld->getCollisionObjectArray().size();i++) | ||||
| 		{ | ||||
| 			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; | ||||
| 			if (!collisionObject->isStaticOrKinematicObject()) | ||||
| 			{ | ||||
| 				collisionObject->setIslandTag( m_unionFind.find(index) ); | ||||
| 				collisionObject->setCompanionId(-1); | ||||
| 			} else | ||||
| 			{ | ||||
| 				collisionObject->setIslandTag(-1); | ||||
| 				collisionObject->setCompanionId(-2); | ||||
| 			} | ||||
| 			index++; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| #endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION | ||||
|  | ||||
| inline	int	getIslandId(const btPersistentManifold* lhs) | ||||
| { | ||||
| 	int islandId; | ||||
| 	const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0()); | ||||
| 	const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1()); | ||||
| 	islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag(); | ||||
| 	return islandId; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /// function object that routes calls to operator< | ||||
| class btPersistentManifoldSortPredicate | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) | ||||
| 		{ | ||||
| 			return getIslandId(lhs) < getIslandId(rhs); | ||||
| 		} | ||||
| }; | ||||
|  | ||||
|  | ||||
| void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld) | ||||
| { | ||||
|  | ||||
| 	BT_PROFILE("islandUnionFindAndQuickSort"); | ||||
| 	 | ||||
| 	btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); | ||||
|  | ||||
| 	m_islandmanifold.resize(0); | ||||
|  | ||||
| 	//we are going to sort the unionfind array, and store the element id in the size | ||||
| 	//afterwards, we clean unionfind, to make sure no-one uses it anymore | ||||
| 	 | ||||
| 	getUnionFind().sortIslands(); | ||||
| 	int numElem = getUnionFind().getNumElements(); | ||||
|  | ||||
| 	int endIslandIndex=1; | ||||
| 	int startIslandIndex; | ||||
|  | ||||
|  | ||||
| 	//update the sleeping state for bodies, if all are sleeping | ||||
| 	for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) | ||||
| 	{ | ||||
| 		int islandId = getUnionFind().getElement(startIslandIndex).m_id; | ||||
| 		for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		//int numSleeping = 0; | ||||
|  | ||||
| 		bool allSleeping = true; | ||||
|  | ||||
| 		int idx; | ||||
| 		for (idx=startIslandIndex;idx<endIslandIndex;idx++) | ||||
| 		{ | ||||
| 			int i = getUnionFind().getElement(idx).m_sz; | ||||
|  | ||||
| 			btCollisionObject* colObj0 = collisionObjects[i]; | ||||
| 			if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) | ||||
| 			{ | ||||
| //				printf("error in island management\n"); | ||||
| 			} | ||||
|  | ||||
| 			btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); | ||||
| 			if (colObj0->getIslandTag() == islandId) | ||||
| 			{ | ||||
| 				if (colObj0->getActivationState()== ACTIVE_TAG) | ||||
| 				{ | ||||
| 					allSleeping = false; | ||||
| 				} | ||||
| 				if (colObj0->getActivationState()== DISABLE_DEACTIVATION) | ||||
| 				{ | ||||
| 					allSleeping = false; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 			 | ||||
|  | ||||
| 		if (allSleeping) | ||||
| 		{ | ||||
| 			int idx; | ||||
| 			for (idx=startIslandIndex;idx<endIslandIndex;idx++) | ||||
| 			{ | ||||
| 				int i = getUnionFind().getElement(idx).m_sz; | ||||
| 				btCollisionObject* colObj0 = collisionObjects[i]; | ||||
| 				if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) | ||||
| 				{ | ||||
| //					printf("error in island management\n"); | ||||
| 				} | ||||
|  | ||||
| 				btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); | ||||
|  | ||||
| 				if (colObj0->getIslandTag() == islandId) | ||||
| 				{ | ||||
| 					colObj0->setActivationState( ISLAND_SLEEPING ); | ||||
| 				} | ||||
| 			} | ||||
| 		} else | ||||
| 		{ | ||||
|  | ||||
| 			int idx; | ||||
| 			for (idx=startIslandIndex;idx<endIslandIndex;idx++) | ||||
| 			{ | ||||
| 				int i = getUnionFind().getElement(idx).m_sz; | ||||
|  | ||||
| 				btCollisionObject* colObj0 = collisionObjects[i]; | ||||
| 				if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) | ||||
| 				{ | ||||
| //					printf("error in island management\n"); | ||||
| 				} | ||||
|  | ||||
| 				btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); | ||||
|  | ||||
| 				if (colObj0->getIslandTag() == islandId) | ||||
| 				{ | ||||
| 					if ( colObj0->getActivationState() == ISLAND_SLEEPING) | ||||
| 					{ | ||||
| 						colObj0->setActivationState( WANTS_DEACTIVATION); | ||||
| 						colObj0->setDeactivationTime(0.f); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	int i; | ||||
| 	int maxNumManifolds = dispatcher->getNumManifolds(); | ||||
|  | ||||
| //#define SPLIT_ISLANDS 1 | ||||
| //#ifdef SPLIT_ISLANDS | ||||
|  | ||||
| 	 | ||||
| //#endif //SPLIT_ISLANDS | ||||
|  | ||||
| 	 | ||||
| 	for (i=0;i<maxNumManifolds ;i++) | ||||
| 	{ | ||||
| 		 btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); | ||||
| 		  | ||||
| 		 btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0()); | ||||
| 		 btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1()); | ||||
| 		 | ||||
| 		 ///@todo: check sleeping conditions! | ||||
| 		 if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) || | ||||
| 			((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING)) | ||||
| 		{ | ||||
| 		 | ||||
| 			//kinematic objects don't merge islands, but wake up all connected objects | ||||
| 			if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) | ||||
| 			{ | ||||
| 				colObj1->activate(); | ||||
| 			} | ||||
| 			if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) | ||||
| 			{ | ||||
| 				colObj0->activate(); | ||||
| 			} | ||||
| 			if(m_splitIslands) | ||||
| 			{  | ||||
| 				//filtering for response | ||||
| 				if (dispatcher->needsResponse(colObj0,colObj1)) | ||||
| 					m_islandmanifold.push_back(manifold); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| ///@todo: this is random access, it can be walked 'cache friendly'! | ||||
| void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback) | ||||
| { | ||||
| 	btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); | ||||
|  | ||||
| 	buildIslands(dispatcher,collisionWorld); | ||||
|  | ||||
| 	int endIslandIndex=1; | ||||
| 	int startIslandIndex; | ||||
| 	int numElem = getUnionFind().getNumElements(); | ||||
|  | ||||
| 	BT_PROFILE("processIslands"); | ||||
|  | ||||
| 	if(!m_splitIslands) | ||||
| 	{ | ||||
| 		btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); | ||||
| 		int maxNumManifolds = dispatcher->getNumManifolds(); | ||||
| 		callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		// Sort manifolds, based on islands | ||||
| 		// Sort the vector using predicate and std::sort | ||||
| 		//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); | ||||
|  | ||||
| 		int numManifolds = int (m_islandmanifold.size()); | ||||
|  | ||||
| 		//we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) | ||||
| 		m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); | ||||
|  | ||||
| 		//now process all active islands (sets of manifolds for now) | ||||
|  | ||||
| 		int startManifoldIndex = 0; | ||||
| 		int endManifoldIndex = 1; | ||||
|  | ||||
| 		//int islandId; | ||||
|  | ||||
| 		 | ||||
|  | ||||
| 	//	printf("Start Islands\n"); | ||||
|  | ||||
| 		//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated | ||||
| 		for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) | ||||
| 		{ | ||||
| 			int islandId = getUnionFind().getElement(startIslandIndex).m_id; | ||||
|  | ||||
|  | ||||
| 			   bool islandSleeping = false; | ||||
| 	                 | ||||
| 					for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) | ||||
| 					{ | ||||
| 							int i = getUnionFind().getElement(endIslandIndex).m_sz; | ||||
| 							btCollisionObject* colObj0 = collisionObjects[i]; | ||||
| 							m_islandBodies.push_back(colObj0); | ||||
| 							if (!colObj0->isActive()) | ||||
| 									islandSleeping = true; | ||||
| 					} | ||||
| 	                 | ||||
|  | ||||
| 			//find the accompanying contact manifold for this islandId | ||||
| 			int numIslandManifolds = 0; | ||||
| 			btPersistentManifold** startManifold = 0; | ||||
|  | ||||
| 			if (startManifoldIndex<numManifolds) | ||||
| 			{ | ||||
| 				int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]); | ||||
| 				if (curIslandId == islandId) | ||||
| 				{ | ||||
| 					startManifold = &m_islandmanifold[startManifoldIndex]; | ||||
| 				 | ||||
| 					for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++) | ||||
| 					{ | ||||
|  | ||||
| 					} | ||||
| 					/// Process the actual simulation, only if not sleeping/deactivated | ||||
| 					numIslandManifolds = endManifoldIndex-startManifoldIndex; | ||||
| 				} | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 			if (!islandSleeping) | ||||
| 			{ | ||||
| 				callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); | ||||
| 	//			printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); | ||||
| 			} | ||||
| 			 | ||||
| 			if (numIslandManifolds) | ||||
| 			{ | ||||
| 				startManifoldIndex = endManifoldIndex; | ||||
| 			} | ||||
|  | ||||
| 			m_islandBodies.resize(0); | ||||
| 		} | ||||
| 	} // else if(!splitIslands)  | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,81 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SIMULATION_ISLAND_MANAGER_H | ||||
| #define SIMULATION_ISLAND_MANAGER_H | ||||
|  | ||||
| #include "BulletCollision/CollisionDispatch/btUnionFind.h" | ||||
| #include "btCollisionCreateFunc.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
| #include "btCollisionObject.h" | ||||
|  | ||||
| class btCollisionObject; | ||||
| class btCollisionWorld; | ||||
| class btDispatcher; | ||||
| class btPersistentManifold; | ||||
|  | ||||
|  | ||||
| ///SimulationIslandManager creates and handles simulation islands, using btUnionFind | ||||
| class btSimulationIslandManager | ||||
| { | ||||
| 	btUnionFind m_unionFind; | ||||
|  | ||||
| 	btAlignedObjectArray<btPersistentManifold*>  m_islandmanifold; | ||||
| 	btAlignedObjectArray<btCollisionObject* >  m_islandBodies; | ||||
| 	 | ||||
| 	bool m_splitIslands; | ||||
| 	 | ||||
| public: | ||||
| 	btSimulationIslandManager(); | ||||
| 	virtual ~btSimulationIslandManager(); | ||||
|  | ||||
|  | ||||
| 	void initUnionFind(int n);	 | ||||
| 	 | ||||
| 		 | ||||
| 	btUnionFind& getUnionFind() { return m_unionFind;} | ||||
|  | ||||
| 	virtual	void	updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher); | ||||
| 	virtual	void	storeIslandActivationState(btCollisionWorld* world); | ||||
|  | ||||
|  | ||||
| 	void	findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld); | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	struct	IslandCallback | ||||
| 	{ | ||||
| 		virtual ~IslandCallback() {}; | ||||
|  | ||||
| 		virtual	void	ProcessIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold**	manifolds,int numManifolds, int islandId) = 0; | ||||
| 	}; | ||||
|  | ||||
| 	void	buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback); | ||||
|  | ||||
| 	void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld); | ||||
|  | ||||
| 	bool getSplitIslands() | ||||
| 	{ | ||||
| 		return m_splitIslands; | ||||
| 	} | ||||
| 	void setSplitIslands(bool doSplitIslands) | ||||
| 	{ | ||||
| 		m_splitIslands = doSplitIslands; | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //SIMULATION_ISLAND_MANAGER_H | ||||
|  | ||||
| @@ -0,0 +1,260 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btSphereBoxCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "BulletCollision/CollisionShapes/btSphereShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btBoxShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| //#include <stdio.h> | ||||
|  | ||||
| btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) | ||||
| : btActivatingCollisionAlgorithm(ci,col0,col1), | ||||
| m_ownManifold(false), | ||||
| m_manifoldPtr(mf), | ||||
| m_isSwapped(isSwapped) | ||||
| { | ||||
| 	btCollisionObject* sphereObj = m_isSwapped? col1 : col0; | ||||
| 	btCollisionObject* boxObj = m_isSwapped? col0 : col1; | ||||
| 	 | ||||
| 	if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj)) | ||||
| 	{ | ||||
| 		m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj); | ||||
| 		m_ownManifold = true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm() | ||||
| { | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr) | ||||
| 			m_dispatcher->releaseManifold(m_manifoldPtr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)dispatchInfo; | ||||
| 	(void)resultOut; | ||||
| 	if (!m_manifoldPtr) | ||||
| 		return; | ||||
|  | ||||
| 	btCollisionObject* sphereObj = m_isSwapped? body1 : body0; | ||||
| 	btCollisionObject* boxObj = m_isSwapped? body0 : body1; | ||||
|  | ||||
|  | ||||
| 	btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape(); | ||||
|  | ||||
| 	btVector3 normalOnSurfaceB; | ||||
| 	btVector3 pOnBox,pOnSphere; | ||||
| 	btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin(); | ||||
| 	btScalar radius = sphere0->getRadius(); | ||||
| 	 | ||||
| 	btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); | ||||
|  | ||||
| 	resultOut->setPersistentManifold(m_manifoldPtr); | ||||
|  | ||||
| 	if (dist < SIMD_EPSILON) | ||||
| 	{ | ||||
| 		btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); | ||||
|  | ||||
| 		/// report a contact. internally this will be kept persistent, and contact reduction is done | ||||
|  | ||||
| 		resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); | ||||
| 		 | ||||
| 	} | ||||
|  | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr->getNumContacts()) | ||||
| 		{ | ||||
| 			resultOut->refreshContactPoints(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)resultOut; | ||||
| 	(void)dispatchInfo; | ||||
| 	(void)col0; | ||||
| 	(void)col1; | ||||
|  | ||||
| 	//not yet | ||||
| 	return btScalar(1.); | ||||
| } | ||||
|  | ||||
|  | ||||
| btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius )  | ||||
| { | ||||
|  | ||||
| 	btScalar margins; | ||||
| 	btVector3 bounds[2]; | ||||
| 	btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); | ||||
| 	 | ||||
| 	bounds[0] = -boxShape->getHalfExtentsWithoutMargin(); | ||||
| 	bounds[1] = boxShape->getHalfExtentsWithoutMargin(); | ||||
|  | ||||
| 	margins = boxShape->getMargin();//also add sphereShape margin? | ||||
|  | ||||
| 	const btTransform&	m44T = boxObj->getWorldTransform(); | ||||
|  | ||||
| 	btVector3	boundsVec[2]; | ||||
| 	btScalar	fPenetration; | ||||
|  | ||||
| 	boundsVec[0] = bounds[0]; | ||||
| 	boundsVec[1] = bounds[1]; | ||||
|  | ||||
| 	btVector3	marginsVec( margins, margins, margins ); | ||||
|  | ||||
| 	// add margins | ||||
| 	bounds[0] += marginsVec; | ||||
| 	bounds[1] -= marginsVec; | ||||
|  | ||||
| 	///////////////////////////////////////////////// | ||||
|  | ||||
| 	btVector3	tmp, prel, n[6], normal, v3P; | ||||
| 	btScalar   fSep = btScalar(10000000.0), fSepThis; | ||||
|  | ||||
| 	n[0].setValue( btScalar(-1.0),  btScalar(0.0),  btScalar(0.0) ); | ||||
| 	n[1].setValue(  btScalar(0.0), btScalar(-1.0),  btScalar(0.0) ); | ||||
| 	n[2].setValue(  btScalar(0.0),  btScalar(0.0), btScalar(-1.0) ); | ||||
| 	n[3].setValue(  btScalar(1.0),  btScalar(0.0),  btScalar(0.0) ); | ||||
| 	n[4].setValue(  btScalar(0.0),  btScalar(1.0),  btScalar(0.0) ); | ||||
| 	n[5].setValue(  btScalar(0.0),  btScalar(0.0),  btScalar(1.0) ); | ||||
|  | ||||
| 	// convert  point in local space | ||||
| 	prel = m44T.invXform( sphereCenter); | ||||
| 	 | ||||
| 	bool	bFound = false; | ||||
|  | ||||
| 	v3P = prel; | ||||
|  | ||||
| 	for (int i=0;i<6;i++) | ||||
| 	{ | ||||
| 		int j = i<3? 0:1; | ||||
| 		if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) ) | ||||
| 		{ | ||||
| 			v3P = v3P - n[i]*fSepThis;		 | ||||
| 			bFound = true; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	// | ||||
|  | ||||
| 	if ( bFound ) | ||||
| 	{ | ||||
| 		bounds[0] = boundsVec[0]; | ||||
| 		bounds[1] = boundsVec[1]; | ||||
|  | ||||
| 		normal = (prel - v3P).normalize(); | ||||
| 		pointOnBox = v3P + normal*margins; | ||||
| 		v3PointOnSphere = prel - normal*fRadius; | ||||
|  | ||||
| 		if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) ) | ||||
| 		{ | ||||
| 			return btScalar(1.0); | ||||
| 		} | ||||
|  | ||||
| 		// transform back in world space | ||||
| 		tmp = m44T( pointOnBox); | ||||
| 		pointOnBox    = tmp; | ||||
| 		tmp  = m44T( v3PointOnSphere);		 | ||||
| 		v3PointOnSphere = tmp; | ||||
| 		btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2(); | ||||
| 		 | ||||
| 		//if this fails, fallback into deeper penetration case, below | ||||
| 		if (fSeps2 > SIMD_EPSILON) | ||||
| 		{ | ||||
| 			fSep = - btSqrt(fSeps2); | ||||
| 			normal = (pointOnBox-v3PointOnSphere); | ||||
| 			normal *= btScalar(1.)/fSep; | ||||
| 		} | ||||
|  | ||||
| 		return fSep; | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////// | ||||
| 	// Deep penetration case | ||||
|  | ||||
| 	fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] ); | ||||
|  | ||||
| 	bounds[0] = boundsVec[0]; | ||||
| 	bounds[1] = boundsVec[1]; | ||||
|  | ||||
| 	if ( fPenetration <= btScalar(0.0) ) | ||||
| 		return (fPenetration-margins); | ||||
| 	else | ||||
| 		return btScalar(1.0); | ||||
| } | ||||
|  | ||||
| btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax)  | ||||
| { | ||||
|  | ||||
| 	btVector3 bounds[2]; | ||||
|  | ||||
| 	bounds[0] = aabbMin; | ||||
| 	bounds[1] = aabbMax; | ||||
|  | ||||
| 	btVector3	p0, tmp, prel, n[6], normal; | ||||
| 	btScalar   fSep = btScalar(-10000000.0), fSepThis; | ||||
|  | ||||
| 	// set p0 and normal to a default value to shup up GCC | ||||
| 	p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); | ||||
| 	normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); | ||||
|  | ||||
| 	n[0].setValue( btScalar(-1.0),  btScalar(0.0),  btScalar(0.0) ); | ||||
| 	n[1].setValue(  btScalar(0.0), btScalar(-1.0),  btScalar(0.0) ); | ||||
| 	n[2].setValue(  btScalar(0.0),  btScalar(0.0), btScalar(-1.0) ); | ||||
| 	n[3].setValue(  btScalar(1.0),  btScalar(0.0),  btScalar(0.0) ); | ||||
| 	n[4].setValue(  btScalar(0.0),  btScalar(1.0),  btScalar(0.0) ); | ||||
| 	n[5].setValue(  btScalar(0.0),  btScalar(0.0),  btScalar(1.0) ); | ||||
|  | ||||
| 	const btTransform&	m44T = boxObj->getWorldTransform(); | ||||
|  | ||||
| 	// convert  point in local space | ||||
| 	prel = m44T.invXform( sphereCenter); | ||||
|  | ||||
| 	/////////// | ||||
|  | ||||
| 	for (int i=0;i<6;i++) | ||||
| 	{ | ||||
| 		int j = i<3 ? 0:1; | ||||
| 		if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) )	return btScalar(1.0); | ||||
| 		if ( fSepThis > fSep ) | ||||
| 		{ | ||||
| 			p0 = bounds[j];	normal = (btVector3&)n[i]; | ||||
| 			fSep = fSepThis; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	pointOnBox = prel - normal*(normal.dot((prel-p0))); | ||||
| 	v3PointOnSphere = pointOnBox + normal*fSep; | ||||
|  | ||||
| 	// transform back in world space | ||||
| 	tmp  = m44T( pointOnBox);		 | ||||
| 	pointOnBox    = tmp; | ||||
| 	tmp  = m44T( v3PointOnSphere);		v3PointOnSphere = tmp; | ||||
| 	normal = (pointOnBox-v3PointOnSphere).normalize(); | ||||
|  | ||||
| 	return fSep; | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,75 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SPHERE_BOX_COLLISION_ALGORITHM_H | ||||
| #define SPHERE_BOX_COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | ||||
| class btPersistentManifold; | ||||
| #include "btCollisionDispatcher.h" | ||||
|  | ||||
| #include "LinearMath/btVector3.h" | ||||
|  | ||||
| /// btSphereBoxCollisionAlgorithm  provides sphere-box collision detection. | ||||
| /// Other features are frame-coherency (persistent data) and collision response. | ||||
| class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm | ||||
| { | ||||
| 	bool	m_ownManifold; | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
| 	bool	m_isSwapped; | ||||
| 	 | ||||
| public: | ||||
|  | ||||
| 	btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); | ||||
|  | ||||
| 	virtual ~btSphereBoxCollisionAlgorithm(); | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr && m_ownManifold) | ||||
| 		{ | ||||
| 			manifoldArray.push_back(m_manifoldPtr); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius ); | ||||
|  | ||||
| 	btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax); | ||||
| 	 | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm)); | ||||
| 			if (!m_swapped) | ||||
| 			{ | ||||
| 				return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); | ||||
| 			} else | ||||
| 			{ | ||||
| 				return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //SPHERE_BOX_COLLISION_ALGORITHM_H | ||||
|  | ||||
| @@ -0,0 +1,105 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btSphereSphereCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "BulletCollision/CollisionShapes/btSphereShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
|  | ||||
| btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1) | ||||
| : btActivatingCollisionAlgorithm(ci,col0,col1), | ||||
| m_ownManifold(false), | ||||
| m_manifoldPtr(mf) | ||||
| { | ||||
| 	if (!m_manifoldPtr) | ||||
| 	{ | ||||
| 		m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1); | ||||
| 		m_ownManifold = true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm() | ||||
| { | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr) | ||||
| 			m_dispatcher->releaseManifold(m_manifoldPtr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)dispatchInfo; | ||||
|  | ||||
| 	if (!m_manifoldPtr) | ||||
| 		return; | ||||
|  | ||||
| 	resultOut->setPersistentManifold(m_manifoldPtr); | ||||
|  | ||||
| 	btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); | ||||
| 	btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); | ||||
|  | ||||
| 	btVector3 diff = col0->getWorldTransform().getOrigin()-  col1->getWorldTransform().getOrigin(); | ||||
| 	btScalar len = diff.length(); | ||||
| 	btScalar radius0 = sphere0->getRadius(); | ||||
| 	btScalar radius1 = sphere1->getRadius(); | ||||
|  | ||||
| #ifdef CLEAR_MANIFOLD | ||||
| 	m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting | ||||
| #endif | ||||
|  | ||||
| 	///iff distance positive, don't generate a new contact | ||||
| 	if ( len > (radius0+radius1)) | ||||
| 	{ | ||||
| #ifndef CLEAR_MANIFOLD | ||||
| 		resultOut->refreshContactPoints(); | ||||
| #endif //CLEAR_MANIFOLD | ||||
| 		return; | ||||
| 	} | ||||
| 	///distance (negative means penetration) | ||||
| 	btScalar dist = len - (radius0+radius1); | ||||
|  | ||||
| 	btVector3 normalOnSurfaceB(1,0,0); | ||||
| 	if (len > SIMD_EPSILON) | ||||
| 	{ | ||||
| 		normalOnSurfaceB = diff / len; | ||||
| 	} | ||||
|  | ||||
| 	///point on A (worldspace) | ||||
| 	///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; | ||||
| 	///point on B (worldspace) | ||||
| 	btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; | ||||
|  | ||||
| 	/// report a contact. internally this will be kept persistent, and contact reduction is done | ||||
| 	 | ||||
| 	 | ||||
| 	resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); | ||||
|  | ||||
| #ifndef CLEAR_MANIFOLD | ||||
| 	resultOut->refreshContactPoints(); | ||||
| #endif //CLEAR_MANIFOLD | ||||
|  | ||||
| } | ||||
|  | ||||
| btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)col0; | ||||
| 	(void)col1; | ||||
| 	(void)dispatchInfo; | ||||
| 	(void)resultOut; | ||||
|  | ||||
| 	//not yet | ||||
| 	return btScalar(1.); | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H | ||||
| #define SPHERE_SPHERE_COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | ||||
| #include "btCollisionDispatcher.h" | ||||
|  | ||||
| class btPersistentManifold; | ||||
|  | ||||
| /// btSphereSphereCollisionAlgorithm  provides sphere-sphere collision detection. | ||||
| /// Other features are frame-coherency (persistent data) and collision response. | ||||
| /// Also provides the most basic sample for custom/user btCollisionAlgorithm | ||||
| class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm | ||||
| { | ||||
| 	bool	m_ownManifold; | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
| 	 | ||||
| public: | ||||
| 	btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); | ||||
|  | ||||
| 	btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) | ||||
| 		: btActivatingCollisionAlgorithm(ci) {} | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr && m_ownManifold) | ||||
| 		{ | ||||
| 			manifoldArray.push_back(m_manifoldPtr); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	virtual ~btSphereSphereCollisionAlgorithm(); | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm)); | ||||
| 			return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //SPHERE_SPHERE_COLLISION_ALGORITHM_H | ||||
|  | ||||
| @@ -0,0 +1,84 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #include "btSphereTriangleCollisionAlgorithm.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" | ||||
| #include "BulletCollision/CollisionShapes/btSphereShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | ||||
| #include "SphereTriangleDetector.h" | ||||
|  | ||||
|  | ||||
| btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped) | ||||
| : btActivatingCollisionAlgorithm(ci,col0,col1), | ||||
| m_ownManifold(false), | ||||
| m_manifoldPtr(mf), | ||||
| m_swapped(swapped) | ||||
| { | ||||
| 	if (!m_manifoldPtr) | ||||
| 	{ | ||||
| 		m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1); | ||||
| 		m_ownManifold = true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm() | ||||
| { | ||||
| 	if (m_ownManifold) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr) | ||||
| 			m_dispatcher->releaseManifold(m_manifoldPtr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	if (!m_manifoldPtr) | ||||
| 		return; | ||||
|  | ||||
| 	btCollisionObject* sphereObj = m_swapped? col1 : col0; | ||||
| 	btCollisionObject* triObj = m_swapped? col0 : col1; | ||||
|  | ||||
| 	btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape(); | ||||
| 	btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape(); | ||||
| 	 | ||||
| 	/// report a contact. internally this will be kept persistent, and contact reduction is done | ||||
| 	resultOut->setPersistentManifold(m_manifoldPtr); | ||||
| 	SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold()); | ||||
| 	 | ||||
| 	btDiscreteCollisionDetectorInterface::ClosestPointInput input; | ||||
| 	input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds | ||||
| 	input.m_transformA = sphereObj->getWorldTransform(); | ||||
| 	input.m_transformB = triObj->getWorldTransform(); | ||||
|  | ||||
| 	bool swapResults = m_swapped; | ||||
|  | ||||
| 	detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults); | ||||
|  | ||||
| 	if (m_ownManifold) | ||||
| 		resultOut->refreshContactPoints(); | ||||
| 	 | ||||
| } | ||||
|  | ||||
| btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) | ||||
| { | ||||
| 	(void)resultOut; | ||||
| 	(void)dispatchInfo; | ||||
| 	(void)col0; | ||||
| 	(void)col1; | ||||
|  | ||||
| 	//not yet | ||||
| 	return btScalar(1.); | ||||
| } | ||||
| @@ -0,0 +1,69 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H | ||||
| #define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H | ||||
|  | ||||
| #include "btActivatingCollisionAlgorithm.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | ||||
| class btPersistentManifold; | ||||
| #include "btCollisionDispatcher.h" | ||||
|  | ||||
| /// btSphereSphereCollisionAlgorithm  provides sphere-sphere collision detection. | ||||
| /// Other features are frame-coherency (persistent data) and collision response. | ||||
| /// Also provides the most basic sample for custom/user btCollisionAlgorithm | ||||
| class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm | ||||
| { | ||||
| 	bool	m_ownManifold; | ||||
| 	btPersistentManifold*	m_manifoldPtr; | ||||
| 	bool	m_swapped; | ||||
| 	 | ||||
| public: | ||||
| 	btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped); | ||||
|  | ||||
| 	btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) | ||||
| 		: btActivatingCollisionAlgorithm(ci) {} | ||||
|  | ||||
| 	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); | ||||
|  | ||||
| 	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) | ||||
| 	{ | ||||
| 		if (m_manifoldPtr && m_ownManifold) | ||||
| 		{ | ||||
| 			manifoldArray.push_back(m_manifoldPtr); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	virtual ~btSphereTriangleCollisionAlgorithm(); | ||||
|  | ||||
| 	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc | ||||
| 	{ | ||||
| 		 | ||||
| 		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) | ||||
| 		{ | ||||
| 			 | ||||
| 			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm)); | ||||
|  | ||||
| 			return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //SPHERE_TRIANGLE_COLLISION_ALGORITHM_H | ||||
|  | ||||
| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btUnionFind.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| btUnionFind::~btUnionFind() | ||||
| { | ||||
| 	Free(); | ||||
|  | ||||
| } | ||||
|  | ||||
| btUnionFind::btUnionFind() | ||||
| {  | ||||
|  | ||||
| } | ||||
|  | ||||
| void	btUnionFind::allocate(int N) | ||||
| { | ||||
| 	m_elements.resize(N); | ||||
| } | ||||
| void	btUnionFind::Free() | ||||
| { | ||||
| 	m_elements.clear(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btUnionFind::reset(int N) | ||||
| { | ||||
| 	allocate(N); | ||||
|  | ||||
| 	for (int i = 0; i < N; i++)  | ||||
| 	{  | ||||
| 		m_elements[i].m_id = i; m_elements[i].m_sz = 1;  | ||||
| 	}  | ||||
| } | ||||
|  | ||||
|  | ||||
| class btUnionFindElementSortPredicate | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		bool operator() ( const btElement& lhs, const btElement& rhs ) | ||||
| 		{ | ||||
| 			return lhs.m_id < rhs.m_id; | ||||
| 		} | ||||
| }; | ||||
|  | ||||
| ///this is a special operation, destroying the content of btUnionFind. | ||||
| ///it sorts the elements, based on island id, in order to make it easy to iterate over islands | ||||
| void	btUnionFind::sortIslands() | ||||
| { | ||||
|  | ||||
| 	//first store the original body index, and islandId | ||||
| 	int numElements = m_elements.size(); | ||||
| 	 | ||||
| 	for (int i=0;i<numElements;i++) | ||||
| 	{ | ||||
| 		m_elements[i].m_id = find(i); | ||||
| #ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION | ||||
| 		m_elements[i].m_sz = i; | ||||
| #endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION | ||||
| 	} | ||||
| 	 | ||||
| 	 // Sort the vector using predicate and std::sort | ||||
| 	  //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate); | ||||
| 	  m_elements.quickSort(btUnionFindElementSortPredicate()); | ||||
|  | ||||
| } | ||||
							
								
								
									
										129
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								libs/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef UNION_FIND_H | ||||
| #define UNION_FIND_H | ||||
|  | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
| #define USE_PATH_COMPRESSION 1 | ||||
|  | ||||
| ///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406 | ||||
| #define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1 | ||||
|  | ||||
| struct	btElement | ||||
| { | ||||
| 	int	m_id; | ||||
| 	int	m_sz; | ||||
| }; | ||||
|  | ||||
| ///UnionFind calculates connected subsets | ||||
| // Implements weighted Quick Union with path compression | ||||
| // optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable) | ||||
| class btUnionFind | ||||
|   { | ||||
|     private: | ||||
| 		btAlignedObjectArray<btElement>	m_elements; | ||||
|  | ||||
|     public: | ||||
| 	   | ||||
| 		btUnionFind(); | ||||
| 		~btUnionFind(); | ||||
|  | ||||
| 	 | ||||
| 		//this is a special operation, destroying the content of btUnionFind. | ||||
| 		//it sorts the elements, based on island id, in order to make it easy to iterate over islands | ||||
| 		void	sortIslands(); | ||||
|  | ||||
| 	  void	reset(int N); | ||||
|  | ||||
| 	  SIMD_FORCE_INLINE int	getNumElements() const | ||||
| 	  { | ||||
| 		  return int(m_elements.size()); | ||||
| 	  } | ||||
| 	  SIMD_FORCE_INLINE bool  isRoot(int x) const | ||||
| 	  { | ||||
| 		  return (x == m_elements[x].m_id); | ||||
| 	  } | ||||
|  | ||||
| 	  btElement&	getElement(int index) | ||||
| 	  { | ||||
| 		  return m_elements[index]; | ||||
| 	  } | ||||
| 	  const btElement& getElement(int index) const | ||||
| 	  { | ||||
| 		  return m_elements[index]; | ||||
| 	  } | ||||
|     | ||||
| 	  void	allocate(int N); | ||||
| 	  void	Free(); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	  int find(int p, int q) | ||||
| 		{  | ||||
| 			return (find(p) == find(q));  | ||||
| 		} | ||||
|  | ||||
| 		void unite(int p, int q) | ||||
| 		{ | ||||
| 			int i = find(p), j = find(q); | ||||
| 			if (i == j)  | ||||
| 				return; | ||||
|  | ||||
| #ifndef USE_PATH_COMPRESSION | ||||
| 			//weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) ) | ||||
| 			if (m_elements[i].m_sz < m_elements[j].m_sz) | ||||
| 			{  | ||||
| 				m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;  | ||||
| 			} | ||||
| 			else  | ||||
| 			{  | ||||
| 				m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz;  | ||||
| 			} | ||||
| #else | ||||
| 			m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;  | ||||
| #endif //USE_PATH_COMPRESSION | ||||
| 		} | ||||
|  | ||||
| 		int find(int x) | ||||
| 		{  | ||||
| 			//btAssert(x < m_N); | ||||
| 			//btAssert(x >= 0); | ||||
|  | ||||
| 			while (x != m_elements[x].m_id)  | ||||
| 			{ | ||||
| 		//not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically | ||||
| 	 | ||||
| 		#ifdef USE_PATH_COMPRESSION | ||||
| 				const btElement* elementPtr = &m_elements[m_elements[x].m_id]; | ||||
| 				m_elements[x].m_id = elementPtr->m_id; | ||||
| 				x = elementPtr->m_id;			 | ||||
| 		#else// | ||||
| 				x = m_elements[x].m_id; | ||||
| 		#endif		 | ||||
| 				//btAssert(x < m_N); | ||||
| 				//btAssert(x >= 0); | ||||
|  | ||||
| 			} | ||||
| 			return x;  | ||||
| 		} | ||||
|  | ||||
|  | ||||
|   }; | ||||
|  | ||||
|  | ||||
| #endif //UNION_FIND_H | ||||
							
								
								
									
										42
									
								
								libs/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								libs/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btBox2dShape.h" | ||||
|  | ||||
|  | ||||
| //{  | ||||
|  | ||||
|  | ||||
| void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const | ||||
| { | ||||
| 	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const | ||||
| { | ||||
| 	//btScalar margin = btScalar(0.); | ||||
| 	btVector3 halfExtents = getHalfExtentsWithMargin(); | ||||
|  | ||||
| 	btScalar lx=btScalar(2.)*(halfExtents.x()); | ||||
| 	btScalar ly=btScalar(2.)*(halfExtents.y()); | ||||
| 	btScalar lz=btScalar(2.)*(halfExtents.z()); | ||||
|  | ||||
| 	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), | ||||
| 					mass/(btScalar(12.0)) * (lx*lx + lz*lz), | ||||
| 					mass/(btScalar(12.0)) * (lx*lx + ly*ly)); | ||||
|  | ||||
| } | ||||
|  | ||||
							
								
								
									
										363
									
								
								libs/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								libs/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,363 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/ | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef OBB_BOX_2D_SHAPE_H | ||||
| #define OBB_BOX_2D_SHAPE_H | ||||
|  | ||||
| #include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btCollisionMargin.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btMinMax.h" | ||||
|  | ||||
| ///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. | ||||
| class btBox2dShape: public btPolyhedralConvexShape | ||||
| { | ||||
|  | ||||
| 	//btVector3	m_boxHalfExtents1; //use m_implicitShapeDimensions instead | ||||
|  | ||||
| 	btVector3 m_centroid; | ||||
| 	btVector3 m_vertices[4]; | ||||
| 	btVector3 m_normals[4]; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btVector3 getHalfExtentsWithMargin() const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
| 		btVector3 margin(getMargin(),getMargin(),getMargin()); | ||||
| 		halfExtents += margin; | ||||
| 		return halfExtents; | ||||
| 	} | ||||
| 	 | ||||
| 	const btVector3& getHalfExtentsWithoutMargin() const | ||||
| 	{ | ||||
| 		return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
| 		btVector3 margin(getMargin(),getMargin(),getMargin()); | ||||
| 		halfExtents += margin; | ||||
| 		 | ||||
| 		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), | ||||
| 			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), | ||||
| 			btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE  btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const | ||||
| 	{ | ||||
| 		const btVector3& halfExtents = getHalfExtentsWithoutMargin(); | ||||
| 		 | ||||
| 		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), | ||||
| 			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), | ||||
| 			btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); | ||||
| 	} | ||||
|  | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||||
| 	{ | ||||
| 		const btVector3& halfExtents = getHalfExtentsWithoutMargin(); | ||||
| 	 | ||||
| 		for (int i=0;i<numVectors;i++) | ||||
| 		{ | ||||
| 			const btVector3& vec = vectors[i]; | ||||
| 			supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), | ||||
| 				btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), | ||||
| 				btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	btBox2dShape( const btVector3& boxHalfExtents)  | ||||
| 		: btPolyhedralConvexShape(), | ||||
| 		m_centroid(0,0,0) | ||||
| 	{ | ||||
| 		m_vertices[0].setValue(-boxHalfExtents.getX(),-boxHalfExtents.getY(),0); | ||||
| 		m_vertices[1].setValue(boxHalfExtents.getX(),-boxHalfExtents.getY(),0); | ||||
| 		m_vertices[2].setValue(boxHalfExtents.getX(),boxHalfExtents.getY(),0); | ||||
| 		m_vertices[3].setValue(-boxHalfExtents.getX(),boxHalfExtents.getY(),0); | ||||
|  | ||||
| 		m_normals[0].setValue(0,-1,0); | ||||
| 		m_normals[1].setValue(1,0,0); | ||||
| 		m_normals[2].setValue(0,1,0); | ||||
| 		m_normals[3].setValue(-1,0,0); | ||||
|  | ||||
| 		m_shapeType = BOX_2D_SHAPE_PROXYTYPE; | ||||
| 		btVector3 margin(getMargin(),getMargin(),getMargin()); | ||||
| 		m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; | ||||
| 	}; | ||||
|  | ||||
| 	virtual void setMargin(btScalar collisionMargin) | ||||
| 	{ | ||||
| 		//correct the m_implicitShapeDimensions for the margin | ||||
| 		btVector3 oldMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; | ||||
| 		 | ||||
| 		btConvexInternalShape::setMargin(collisionMargin); | ||||
| 		btVector3 newMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin; | ||||
|  | ||||
| 	} | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling) | ||||
| 	{ | ||||
| 		btVector3 oldMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; | ||||
| 		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling; | ||||
|  | ||||
| 		btConvexInternalShape::setLocalScaling(scaling); | ||||
|  | ||||
| 		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	int	getVertexCount() const | ||||
| 	{ | ||||
| 		return 4; | ||||
| 	} | ||||
|  | ||||
| 	virtual int getNumVertices()const | ||||
| 	{ | ||||
| 		return 4; | ||||
| 	} | ||||
|  | ||||
| 	const btVector3* getVertices() const | ||||
| 	{ | ||||
| 		return &m_vertices[0]; | ||||
| 	} | ||||
|  | ||||
| 	const btVector3* getNormals() const | ||||
| 	{ | ||||
| 		return &m_normals[0]; | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const | ||||
| 	{ | ||||
| 		//this plane might not be aligned... | ||||
| 		btVector4 plane ; | ||||
| 		getPlaneEquation(plane,i); | ||||
| 		planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ()); | ||||
| 		planeSupport = localGetSupportingVertex(-planeNormal); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	const btVector3& getCentroid() const | ||||
| 	{ | ||||
| 		return m_centroid; | ||||
| 	} | ||||
| 	 | ||||
| 	virtual int getNumPlanes() const | ||||
| 	{ | ||||
| 		return 6; | ||||
| 	}	 | ||||
| 	 | ||||
| 	 | ||||
|  | ||||
| 	virtual int getNumEdges() const | ||||
| 	{ | ||||
| 		return 12; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	virtual void getVertex(int i,btVector3& vtx) const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
|  | ||||
| 		vtx = btVector3( | ||||
| 				halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1), | ||||
| 				halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1), | ||||
| 				halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2)); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	virtual void	getPlaneEquation(btVector4& plane,int i) const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
|  | ||||
| 		switch (i) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x()); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x()); | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y()); | ||||
| 			break; | ||||
| 		case 3: | ||||
| 			plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y()); | ||||
| 			break; | ||||
| 		case 4: | ||||
| 			plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z()); | ||||
| 			break; | ||||
| 		case 5: | ||||
| 			plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z()); | ||||
| 			break; | ||||
| 		default: | ||||
| 			btAssert(0); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const | ||||
| 	//virtual void getEdge(int i,Edge& edge) const | ||||
| 	{ | ||||
| 		int edgeVert0 = 0; | ||||
| 		int edgeVert1 = 0; | ||||
|  | ||||
| 		switch (i) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 				edgeVert0 = 0; | ||||
| 				edgeVert1 = 1; | ||||
| 			break; | ||||
| 		case 1: | ||||
| 				edgeVert0 = 0; | ||||
| 				edgeVert1 = 2; | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			edgeVert0 = 1; | ||||
| 			edgeVert1 = 3; | ||||
|  | ||||
| 			break; | ||||
| 		case 3: | ||||
| 			edgeVert0 = 2; | ||||
| 			edgeVert1 = 3; | ||||
| 			break; | ||||
| 		case 4: | ||||
| 			edgeVert0 = 0; | ||||
| 			edgeVert1 = 4; | ||||
| 			break; | ||||
| 		case 5: | ||||
| 			edgeVert0 = 1; | ||||
| 			edgeVert1 = 5; | ||||
|  | ||||
| 			break; | ||||
| 		case 6: | ||||
| 			edgeVert0 = 2; | ||||
| 			edgeVert1 = 6; | ||||
| 			break; | ||||
| 		case 7: | ||||
| 			edgeVert0 = 3; | ||||
| 			edgeVert1 = 7; | ||||
| 			break; | ||||
| 		case 8: | ||||
| 			edgeVert0 = 4; | ||||
| 			edgeVert1 = 5; | ||||
| 			break; | ||||
| 		case 9: | ||||
| 			edgeVert0 = 4; | ||||
| 			edgeVert1 = 6; | ||||
| 			break; | ||||
| 		case 10: | ||||
| 			edgeVert0 = 5; | ||||
| 			edgeVert1 = 7; | ||||
| 			break; | ||||
| 		case 11: | ||||
| 			edgeVert0 = 6; | ||||
| 			edgeVert1 = 7; | ||||
| 			break; | ||||
| 		default: | ||||
| 			btAssert(0); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		getVertex(edgeVert0,pa ); | ||||
| 		getVertex(edgeVert1,pb ); | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
|  | ||||
| 		//btScalar minDist = 2*tolerance; | ||||
| 		 | ||||
| 		bool result =	(pt.x() <= (halfExtents.x()+tolerance)) && | ||||
| 						(pt.x() >= (-halfExtents.x()-tolerance)) && | ||||
| 						(pt.y() <= (halfExtents.y()+tolerance)) && | ||||
| 						(pt.y() >= (-halfExtents.y()-tolerance)) && | ||||
| 						(pt.z() <= (halfExtents.z()+tolerance)) && | ||||
| 						(pt.z() >= (-halfExtents.z()-tolerance)); | ||||
| 		 | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	//debugging | ||||
| 	virtual const char*	getName()const | ||||
| 	{ | ||||
| 		return "Box2d"; | ||||
| 	} | ||||
|  | ||||
| 	virtual int		getNumPreferredPenetrationDirections() const | ||||
| 	{ | ||||
| 		return 6; | ||||
| 	} | ||||
| 	 | ||||
| 	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const | ||||
| 	{ | ||||
| 		switch (index) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); | ||||
| 			break; | ||||
| 		case 3: | ||||
| 			penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); | ||||
| 			break; | ||||
| 		case 4: | ||||
| 			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); | ||||
| 			break; | ||||
| 		case 5: | ||||
| 			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); | ||||
| 			break; | ||||
| 		default: | ||||
| 			btAssert(0); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //OBB_BOX_2D_SHAPE_H | ||||
|  | ||||
|  | ||||
							
								
								
									
										41
									
								
								libs/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								libs/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
| #include "btBoxShape.h" | ||||
|  | ||||
|  | ||||
| //{  | ||||
|  | ||||
|  | ||||
| void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const | ||||
| { | ||||
| 	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const | ||||
| { | ||||
| 	//btScalar margin = btScalar(0.); | ||||
| 	btVector3 halfExtents = getHalfExtentsWithMargin(); | ||||
|  | ||||
| 	btScalar lx=btScalar(2.)*(halfExtents.x()); | ||||
| 	btScalar ly=btScalar(2.)*(halfExtents.y()); | ||||
| 	btScalar lz=btScalar(2.)*(halfExtents.z()); | ||||
|  | ||||
| 	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), | ||||
| 					mass/(btScalar(12.0)) * (lx*lx + lz*lz), | ||||
| 					mass/(btScalar(12.0)) * (lx*lx + ly*ly)); | ||||
|  | ||||
| } | ||||
|  | ||||
							
								
								
									
										318
									
								
								libs/bullet/BulletCollision/CollisionShapes/btBoxShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								libs/bullet/BulletCollision/CollisionShapes/btBoxShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,318 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef OBB_BOX_MINKOWSKI_H | ||||
| #define OBB_BOX_MINKOWSKI_H | ||||
|  | ||||
| #include "btPolyhedralConvexShape.h" | ||||
| #include "btCollisionMargin.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btMinMax.h" | ||||
|  | ||||
| ///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. | ||||
| class btBoxShape: public btPolyhedralConvexShape | ||||
| { | ||||
|  | ||||
| 	//btVector3	m_boxHalfExtents1; //use m_implicitShapeDimensions instead | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btVector3 getHalfExtentsWithMargin() const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
| 		btVector3 margin(getMargin(),getMargin(),getMargin()); | ||||
| 		halfExtents += margin; | ||||
| 		return halfExtents; | ||||
| 	} | ||||
| 	 | ||||
| 	const btVector3& getHalfExtentsWithoutMargin() const | ||||
| 	{ | ||||
| 		return m_implicitShapeDimensions;//scaling is included, margin is not | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
| 		btVector3 margin(getMargin(),getMargin(),getMargin()); | ||||
| 		halfExtents += margin; | ||||
| 		 | ||||
| 		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), | ||||
| 			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), | ||||
| 			btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE  btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const | ||||
| 	{ | ||||
| 		const btVector3& halfExtents = getHalfExtentsWithoutMargin(); | ||||
| 		 | ||||
| 		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), | ||||
| 			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), | ||||
| 			btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); | ||||
| 	} | ||||
|  | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||||
| 	{ | ||||
| 		const btVector3& halfExtents = getHalfExtentsWithoutMargin(); | ||||
| 	 | ||||
| 		for (int i=0;i<numVectors;i++) | ||||
| 		{ | ||||
| 			const btVector3& vec = vectors[i]; | ||||
| 			supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), | ||||
| 				btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), | ||||
| 				btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	btBoxShape( const btVector3& boxHalfExtents)  | ||||
| 		: btPolyhedralConvexShape() | ||||
| 	{ | ||||
| 		m_shapeType = BOX_SHAPE_PROXYTYPE; | ||||
| 		btVector3 margin(getMargin(),getMargin(),getMargin()); | ||||
| 		m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; | ||||
| 	}; | ||||
|  | ||||
| 	virtual void setMargin(btScalar collisionMargin) | ||||
| 	{ | ||||
| 		//correct the m_implicitShapeDimensions for the margin | ||||
| 		btVector3 oldMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; | ||||
| 		 | ||||
| 		btConvexInternalShape::setMargin(collisionMargin); | ||||
| 		btVector3 newMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin; | ||||
|  | ||||
| 	} | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling) | ||||
| 	{ | ||||
| 		btVector3 oldMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; | ||||
| 		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling; | ||||
|  | ||||
| 		btConvexInternalShape::setLocalScaling(scaling); | ||||
|  | ||||
| 		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const; | ||||
|  | ||||
| 	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const | ||||
| 	{ | ||||
| 		//this plane might not be aligned... | ||||
| 		btVector4 plane ; | ||||
| 		getPlaneEquation(plane,i); | ||||
| 		planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ()); | ||||
| 		planeSupport = localGetSupportingVertex(-planeNormal); | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	virtual int getNumPlanes() const | ||||
| 	{ | ||||
| 		return 6; | ||||
| 	}	 | ||||
| 	 | ||||
| 	virtual int	getNumVertices() const  | ||||
| 	{ | ||||
| 		return 8; | ||||
| 	} | ||||
|  | ||||
| 	virtual int getNumEdges() const | ||||
| 	{ | ||||
| 		return 12; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	virtual void getVertex(int i,btVector3& vtx) const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
|  | ||||
| 		vtx = btVector3( | ||||
| 				halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1), | ||||
| 				halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1), | ||||
| 				halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2)); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	virtual void	getPlaneEquation(btVector4& plane,int i) const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
|  | ||||
| 		switch (i) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x()); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x()); | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y()); | ||||
| 			break; | ||||
| 		case 3: | ||||
| 			plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y()); | ||||
| 			break; | ||||
| 		case 4: | ||||
| 			plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z()); | ||||
| 			break; | ||||
| 		case 5: | ||||
| 			plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z()); | ||||
| 			break; | ||||
| 		default: | ||||
| 			btAssert(0); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const | ||||
| 	//virtual void getEdge(int i,Edge& edge) const | ||||
| 	{ | ||||
| 		int edgeVert0 = 0; | ||||
| 		int edgeVert1 = 0; | ||||
|  | ||||
| 		switch (i) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 				edgeVert0 = 0; | ||||
| 				edgeVert1 = 1; | ||||
| 			break; | ||||
| 		case 1: | ||||
| 				edgeVert0 = 0; | ||||
| 				edgeVert1 = 2; | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			edgeVert0 = 1; | ||||
| 			edgeVert1 = 3; | ||||
|  | ||||
| 			break; | ||||
| 		case 3: | ||||
| 			edgeVert0 = 2; | ||||
| 			edgeVert1 = 3; | ||||
| 			break; | ||||
| 		case 4: | ||||
| 			edgeVert0 = 0; | ||||
| 			edgeVert1 = 4; | ||||
| 			break; | ||||
| 		case 5: | ||||
| 			edgeVert0 = 1; | ||||
| 			edgeVert1 = 5; | ||||
|  | ||||
| 			break; | ||||
| 		case 6: | ||||
| 			edgeVert0 = 2; | ||||
| 			edgeVert1 = 6; | ||||
| 			break; | ||||
| 		case 7: | ||||
| 			edgeVert0 = 3; | ||||
| 			edgeVert1 = 7; | ||||
| 			break; | ||||
| 		case 8: | ||||
| 			edgeVert0 = 4; | ||||
| 			edgeVert1 = 5; | ||||
| 			break; | ||||
| 		case 9: | ||||
| 			edgeVert0 = 4; | ||||
| 			edgeVert1 = 6; | ||||
| 			break; | ||||
| 		case 10: | ||||
| 			edgeVert0 = 5; | ||||
| 			edgeVert1 = 7; | ||||
| 			break; | ||||
| 		case 11: | ||||
| 			edgeVert0 = 6; | ||||
| 			edgeVert1 = 7; | ||||
| 			break; | ||||
| 		default: | ||||
| 			btAssert(0); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		getVertex(edgeVert0,pa ); | ||||
| 		getVertex(edgeVert1,pb ); | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const | ||||
| 	{ | ||||
| 		btVector3 halfExtents = getHalfExtentsWithoutMargin(); | ||||
|  | ||||
| 		//btScalar minDist = 2*tolerance; | ||||
| 		 | ||||
| 		bool result =	(pt.x() <= (halfExtents.x()+tolerance)) && | ||||
| 						(pt.x() >= (-halfExtents.x()-tolerance)) && | ||||
| 						(pt.y() <= (halfExtents.y()+tolerance)) && | ||||
| 						(pt.y() >= (-halfExtents.y()-tolerance)) && | ||||
| 						(pt.z() <= (halfExtents.z()+tolerance)) && | ||||
| 						(pt.z() >= (-halfExtents.z()-tolerance)); | ||||
| 		 | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	//debugging | ||||
| 	virtual const char*	getName()const | ||||
| 	{ | ||||
| 		return "Box"; | ||||
| 	} | ||||
|  | ||||
| 	virtual int		getNumPreferredPenetrationDirections() const | ||||
| 	{ | ||||
| 		return 6; | ||||
| 	} | ||||
| 	 | ||||
| 	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const | ||||
| 	{ | ||||
| 		switch (index) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 			penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); | ||||
| 			break; | ||||
| 		case 3: | ||||
| 			penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); | ||||
| 			break; | ||||
| 		case 4: | ||||
| 			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); | ||||
| 			break; | ||||
| 		case 5: | ||||
| 			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); | ||||
| 			break; | ||||
| 		default: | ||||
| 			btAssert(0); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif //OBB_BOX_MINKOWSKI_H | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,466 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| //#define DISABLE_BVH | ||||
|  | ||||
| #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btOptimizedBvh.h" | ||||
| #include "LinearMath/btSerializer.h" | ||||
|  | ||||
| ///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. | ||||
| ///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. | ||||
| btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh) | ||||
| :btTriangleMeshShape(meshInterface), | ||||
| m_bvh(0), | ||||
| m_triangleInfoMap(0), | ||||
| m_useQuantizedAabbCompression(useQuantizedAabbCompression), | ||||
| m_ownsBvh(false) | ||||
| { | ||||
| 	m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; | ||||
| 	//construct bvh from meshInterface | ||||
| #ifndef DISABLE_BVH | ||||
|  | ||||
| 	if (buildBvh) | ||||
| 	{ | ||||
| 		buildOptimizedBvh(); | ||||
| 	} | ||||
|  | ||||
| #endif //DISABLE_BVH | ||||
|  | ||||
| } | ||||
|  | ||||
| btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh) | ||||
| :btTriangleMeshShape(meshInterface), | ||||
| m_bvh(0), | ||||
| m_triangleInfoMap(0), | ||||
| m_useQuantizedAabbCompression(useQuantizedAabbCompression), | ||||
| m_ownsBvh(false) | ||||
| { | ||||
| 	m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; | ||||
| 	//construct bvh from meshInterface | ||||
| #ifndef DISABLE_BVH | ||||
|  | ||||
| 	if (buildBvh) | ||||
| 	{ | ||||
| 		void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); | ||||
| 		m_bvh = new (mem) btOptimizedBvh(); | ||||
| 		 | ||||
| 		m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); | ||||
| 		m_ownsBvh = true; | ||||
| 	} | ||||
|  | ||||
| #endif //DISABLE_BVH | ||||
|  | ||||
| } | ||||
|  | ||||
| void	btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax) | ||||
| { | ||||
| 	m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax ); | ||||
| 	 | ||||
| 	m_localAabbMin.setMin(aabbMin); | ||||
| 	m_localAabbMax.setMax(aabbMax); | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax) | ||||
| { | ||||
| 	m_bvh->refit( m_meshInterface, aabbMin,aabbMax ); | ||||
| 	 | ||||
| 	recalcLocalAabb(); | ||||
| } | ||||
|  | ||||
| btBvhTriangleMeshShape::~btBvhTriangleMeshShape() | ||||
| { | ||||
| 	if (m_ownsBvh) | ||||
| 	{ | ||||
| 		m_bvh->~btOptimizedBvh(); | ||||
| 		btAlignedFree(m_bvh); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void	btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) | ||||
| { | ||||
| 	struct	MyNodeOverlapCallback : public btNodeOverlapCallback | ||||
| 	{ | ||||
| 		btStridingMeshInterface*	m_meshInterface; | ||||
| 		btTriangleCallback* m_callback; | ||||
|  | ||||
| 		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) | ||||
| 			:m_meshInterface(meshInterface), | ||||
| 			m_callback(callback) | ||||
| 		{ | ||||
| 		} | ||||
| 				 | ||||
| 		virtual void processNode(int nodeSubPart, int nodeTriangleIndex) | ||||
| 		{ | ||||
| 			btVector3 m_triangle[3]; | ||||
| 			const unsigned char *vertexbase; | ||||
| 			int numverts; | ||||
| 			PHY_ScalarType type; | ||||
| 			int stride; | ||||
| 			const unsigned char *indexbase; | ||||
| 			int indexstride; | ||||
| 			int numfaces; | ||||
| 			PHY_ScalarType indicestype; | ||||
|  | ||||
| 			m_meshInterface->getLockedReadOnlyVertexIndexBase( | ||||
| 				&vertexbase, | ||||
| 				numverts, | ||||
| 				type, | ||||
| 				stride, | ||||
| 				&indexbase, | ||||
| 				indexstride, | ||||
| 				numfaces, | ||||
| 				indicestype, | ||||
| 				nodeSubPart); | ||||
|  | ||||
| 			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); | ||||
| 			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); | ||||
| 	 | ||||
| 			const btVector3& meshScaling = m_meshInterface->getScaling(); | ||||
| 			for (int j=2;j>=0;j--) | ||||
| 			{ | ||||
| 				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; | ||||
| 				 | ||||
| 				if (type == PHY_FLOAT) | ||||
| 				{ | ||||
| 					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); | ||||
| 					 | ||||
| 					m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());		 | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); | ||||
| 					 | ||||
| 					m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());		 | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			/* Perform ray vs. triangle collision here */ | ||||
| 			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); | ||||
| 			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface); | ||||
|  | ||||
| 	m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget); | ||||
| } | ||||
|  | ||||
| void	btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) | ||||
| { | ||||
| 	struct	MyNodeOverlapCallback : public btNodeOverlapCallback | ||||
| 	{ | ||||
| 		btStridingMeshInterface*	m_meshInterface; | ||||
| 		btTriangleCallback* m_callback; | ||||
|  | ||||
| 		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) | ||||
| 			:m_meshInterface(meshInterface), | ||||
| 			m_callback(callback) | ||||
| 		{ | ||||
| 		} | ||||
| 				 | ||||
| 		virtual void processNode(int nodeSubPart, int nodeTriangleIndex) | ||||
| 		{ | ||||
| 			btVector3 m_triangle[3]; | ||||
| 			const unsigned char *vertexbase; | ||||
| 			int numverts; | ||||
| 			PHY_ScalarType type; | ||||
| 			int stride; | ||||
| 			const unsigned char *indexbase; | ||||
| 			int indexstride; | ||||
| 			int numfaces; | ||||
| 			PHY_ScalarType indicestype; | ||||
|  | ||||
| 			m_meshInterface->getLockedReadOnlyVertexIndexBase( | ||||
| 				&vertexbase, | ||||
| 				numverts, | ||||
| 				type, | ||||
| 				stride, | ||||
| 				&indexbase, | ||||
| 				indexstride, | ||||
| 				numfaces, | ||||
| 				indicestype, | ||||
| 				nodeSubPart); | ||||
|  | ||||
| 			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); | ||||
| 			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); | ||||
| 	 | ||||
| 			const btVector3& meshScaling = m_meshInterface->getScaling(); | ||||
| 			for (int j=2;j>=0;j--) | ||||
| 			{ | ||||
| 				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; | ||||
|  | ||||
| 				if (type == PHY_FLOAT) | ||||
| 				{ | ||||
| 					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); | ||||
|  | ||||
| 					m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());		 | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); | ||||
| 					 | ||||
| 					m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());		 | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			/* Perform ray vs. triangle collision here */ | ||||
| 			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); | ||||
| 			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface); | ||||
|  | ||||
| 	m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax); | ||||
| } | ||||
|  | ||||
| //perform bvh tree traversal and report overlapping triangles to 'callback' | ||||
| void	btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const | ||||
| { | ||||
|  | ||||
| #ifdef DISABLE_BVH | ||||
| 	//brute force traverse all triangles | ||||
| 	btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax); | ||||
| #else | ||||
|  | ||||
| 	//first get all the nodes | ||||
|  | ||||
| 	 | ||||
| 	struct	MyNodeOverlapCallback : public btNodeOverlapCallback | ||||
| 	{ | ||||
| 		btStridingMeshInterface*	m_meshInterface; | ||||
| 		btTriangleCallback*		m_callback; | ||||
| 		btVector3				m_triangle[3]; | ||||
|  | ||||
|  | ||||
| 		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) | ||||
| 			:m_meshInterface(meshInterface), | ||||
| 			m_callback(callback) | ||||
| 		{ | ||||
| 		} | ||||
| 				 | ||||
| 		virtual void processNode(int nodeSubPart, int nodeTriangleIndex) | ||||
| 		{ | ||||
| 			const unsigned char *vertexbase; | ||||
| 			int numverts; | ||||
| 			PHY_ScalarType type; | ||||
| 			int stride; | ||||
| 			const unsigned char *indexbase; | ||||
| 			int indexstride; | ||||
| 			int numfaces; | ||||
| 			PHY_ScalarType indicestype; | ||||
| 			 | ||||
|  | ||||
| 			m_meshInterface->getLockedReadOnlyVertexIndexBase( | ||||
| 				&vertexbase, | ||||
| 				numverts, | ||||
| 				type, | ||||
| 				stride, | ||||
| 				&indexbase, | ||||
| 				indexstride, | ||||
| 				numfaces, | ||||
| 				indicestype, | ||||
| 				nodeSubPart); | ||||
|  | ||||
| 			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); | ||||
| 			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); | ||||
| 	 | ||||
| 			const btVector3& meshScaling = m_meshInterface->getScaling(); | ||||
| 			for (int j=2;j>=0;j--) | ||||
| 			{ | ||||
| 				 | ||||
| 				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; | ||||
|  | ||||
|  | ||||
| #ifdef DEBUG_TRIANGLE_MESH | ||||
| 				printf("%d ,",graphicsindex); | ||||
| #endif //DEBUG_TRIANGLE_MESH | ||||
| 				if (type == PHY_FLOAT) | ||||
| 				{ | ||||
| 					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); | ||||
| 					 | ||||
| 					m_triangle[j] = btVector3( | ||||
| 																		graphicsbase[0]*meshScaling.getX(), | ||||
| 																		graphicsbase[1]*meshScaling.getY(), | ||||
| 																		graphicsbase[2]*meshScaling.getZ()); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); | ||||
|  | ||||
| 					m_triangle[j] = btVector3( | ||||
| 						btScalar(graphicsbase[0])*meshScaling.getX(), | ||||
| 						btScalar(graphicsbase[1])*meshScaling.getY(), | ||||
| 						btScalar(graphicsbase[2])*meshScaling.getZ()); | ||||
| 				} | ||||
| #ifdef DEBUG_TRIANGLE_MESH | ||||
| 				printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z()); | ||||
| #endif //DEBUG_TRIANGLE_MESH | ||||
| 			} | ||||
|  | ||||
| 			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); | ||||
| 			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); | ||||
| 		} | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface); | ||||
|  | ||||
| 	m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); | ||||
|  | ||||
|  | ||||
| #endif//DISABLE_BVH | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| void   btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) | ||||
| { | ||||
|    if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) | ||||
|    { | ||||
|       btTriangleMeshShape::setLocalScaling(scaling); | ||||
| 	  buildOptimizedBvh(); | ||||
|    } | ||||
| } | ||||
|  | ||||
| void   btBvhTriangleMeshShape::buildOptimizedBvh() | ||||
| { | ||||
| 	if (m_ownsBvh) | ||||
| 	{ | ||||
| 		m_bvh->~btOptimizedBvh(); | ||||
| 		btAlignedFree(m_bvh); | ||||
| 	} | ||||
| 	///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work | ||||
| 	void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); | ||||
| 	m_bvh = new(mem) btOptimizedBvh(); | ||||
| 	//rebuild the bvh... | ||||
| 	m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); | ||||
| 	m_ownsBvh = true; | ||||
| } | ||||
|  | ||||
| void   btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling) | ||||
| { | ||||
|    btAssert(!m_bvh); | ||||
|    btAssert(!m_ownsBvh); | ||||
|  | ||||
|    m_bvh = bvh; | ||||
|    m_ownsBvh = false; | ||||
|    // update the scaling without rebuilding the bvh | ||||
|    if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) | ||||
|    { | ||||
|       btTriangleMeshShape::setLocalScaling(scaling); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| ///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| const char*	btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const | ||||
| { | ||||
| 	btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer; | ||||
|  | ||||
| 	btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer); | ||||
|  | ||||
| 	m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer); | ||||
|  | ||||
| 	trimeshData->m_collisionMargin = float(m_collisionMargin); | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH)) | ||||
| 	{ | ||||
| 		void* chunk = serializer->findPointer(m_bvh); | ||||
| 		if (chunk) | ||||
| 		{ | ||||
| #ifdef BT_USE_DOUBLE_PRECISION | ||||
| 			trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk; | ||||
| 			trimeshData->m_quantizedFloatBvh = 0; | ||||
| #else | ||||
| 			trimeshData->m_quantizedFloatBvh  = (btQuantizedBvhData*)chunk; | ||||
| 			trimeshData->m_quantizedDoubleBvh= 0; | ||||
| #endif //BT_USE_DOUBLE_PRECISION | ||||
| 		} else | ||||
| 		{ | ||||
|  | ||||
| #ifdef BT_USE_DOUBLE_PRECISION | ||||
| 			trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh); | ||||
| 			trimeshData->m_quantizedFloatBvh = 0; | ||||
| #else | ||||
| 			trimeshData->m_quantizedFloatBvh  = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh); | ||||
| 			trimeshData->m_quantizedDoubleBvh= 0; | ||||
| #endif //BT_USE_DOUBLE_PRECISION | ||||
| 	 | ||||
| 			int sz = m_bvh->calculateSerializeBufferSizeNew(); | ||||
| 			btChunk* chunk = serializer->allocate(sz,1); | ||||
| 			const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer); | ||||
| 			serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh); | ||||
| 		} | ||||
| 	} else | ||||
| 	{ | ||||
| 		trimeshData->m_quantizedFloatBvh = 0; | ||||
| 		trimeshData->m_quantizedDoubleBvh = 0; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP)) | ||||
| 	{ | ||||
| 		void* chunk = serializer->findPointer(m_triangleInfoMap); | ||||
| 		if (chunk) | ||||
| 		{ | ||||
| 			trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk; | ||||
| 		} else | ||||
| 		{ | ||||
| 			trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap); | ||||
| 			int sz = m_triangleInfoMap->calculateSerializeBufferSize(); | ||||
| 			btChunk* chunk = serializer->allocate(sz,1); | ||||
| 			const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer); | ||||
| 			serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap); | ||||
| 		} | ||||
| 	} else | ||||
| 	{ | ||||
| 		trimeshData->m_triangleInfoMap = 0; | ||||
| 	} | ||||
|  | ||||
| 	return "btTriangleMeshShapeData"; | ||||
| } | ||||
|  | ||||
| void	btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const | ||||
| { | ||||
| 	if (m_bvh) | ||||
| 	{ | ||||
| 		int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place | ||||
| 		btChunk* chunk = serializer->allocate(len,1); | ||||
| 		const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer); | ||||
| 		serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void	btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const | ||||
| { | ||||
| 	if (m_triangleInfoMap) | ||||
| 	{ | ||||
| 		int len = m_triangleInfoMap->calculateSerializeBufferSize(); | ||||
| 		btChunk* chunk = serializer->allocate(len,1); | ||||
| 		const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer); | ||||
| 		serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,139 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BVH_TRIANGLE_MESH_SHAPE_H | ||||
| #define BVH_TRIANGLE_MESH_SHAPE_H | ||||
|  | ||||
| #include "btTriangleMeshShape.h" | ||||
| #include "btOptimizedBvh.h" | ||||
| #include "LinearMath/btAlignedAllocator.h" | ||||
| #include "btTriangleInfoMap.h" | ||||
|  | ||||
| ///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage. | ||||
| ///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method. | ||||
| ///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk. | ||||
| ///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example. | ||||
| ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape | ||||
| { | ||||
|  | ||||
| 	btOptimizedBvh*	m_bvh; | ||||
| 	btTriangleInfoMap*	m_triangleInfoMap; | ||||
|  | ||||
| 	bool m_useQuantizedAabbCompression; | ||||
| 	bool m_ownsBvh; | ||||
| 	bool m_pad[11];////need padding due to alignment | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	btBvhTriangleMeshShape() : btTriangleMeshShape(0),m_bvh(0),m_triangleInfoMap(0),m_ownsBvh(false) {m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;}; | ||||
| 	btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true); | ||||
|  | ||||
| 	///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb | ||||
| 	btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true); | ||||
| 	 | ||||
| 	virtual ~btBvhTriangleMeshShape(); | ||||
|  | ||||
| 	bool getOwnsBvh () const | ||||
| 	{ | ||||
| 		return m_ownsBvh; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget); | ||||
| 	void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax); | ||||
|  | ||||
| 	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; | ||||
|  | ||||
| 	void	refitTree(const btVector3& aabbMin,const btVector3& aabbMax); | ||||
|  | ||||
| 	///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks | ||||
| 	void	partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); | ||||
|  | ||||
| 	//debugging | ||||
| 	virtual const char*	getName()const {return "BVHTRIANGLEMESH";} | ||||
|  | ||||
|  | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling); | ||||
| 	 | ||||
| 	btOptimizedBvh*	getOptimizedBvh() | ||||
| 	{ | ||||
| 		return m_bvh; | ||||
| 	} | ||||
|  | ||||
| 	void	setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1)); | ||||
|  | ||||
| 	void    buildOptimizedBvh(); | ||||
|  | ||||
| 	bool	usesQuantizedAabbCompression() const | ||||
| 	{ | ||||
| 		return	m_useQuantizedAabbCompression; | ||||
| 	} | ||||
|  | ||||
| 	void	setTriangleInfoMap(btTriangleInfoMap* triangleInfoMap) | ||||
| 	{ | ||||
| 		m_triangleInfoMap = triangleInfoMap; | ||||
| 	} | ||||
|  | ||||
| 	const btTriangleInfoMap*	getTriangleInfoMap() const | ||||
| 	{ | ||||
| 		return m_triangleInfoMap; | ||||
| 	} | ||||
| 	 | ||||
| 	btTriangleInfoMap*	getTriangleInfoMap() | ||||
| 	{ | ||||
| 		return m_triangleInfoMap; | ||||
| 	} | ||||
|  | ||||
| 	virtual	int	calculateSerializeBufferSize() const; | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| 	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const; | ||||
|  | ||||
| 	virtual void	serializeSingleBvh(btSerializer* serializer) const; | ||||
|  | ||||
| 	virtual void	serializeSingleTriangleInfoMap(btSerializer* serializer) const; | ||||
|  | ||||
| }; | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct	btTriangleMeshShapeData | ||||
| { | ||||
| 	btCollisionShapeData	m_collisionShapeData; | ||||
|  | ||||
| 	btStridingMeshInterfaceData m_meshInterface; | ||||
|  | ||||
| 	btQuantizedBvhFloatData		*m_quantizedFloatBvh; | ||||
| 	btQuantizedBvhDoubleData	*m_quantizedDoubleBvh; | ||||
|  | ||||
| 	btTriangleInfoMapData	*m_triangleInfoMap; | ||||
| 	 | ||||
| 	float	m_collisionMargin; | ||||
|  | ||||
| 	char m_pad3[4]; | ||||
| 	 | ||||
| }; | ||||
|  | ||||
|  | ||||
| SIMD_FORCE_INLINE	int	btBvhTriangleMeshShape::calculateSerializeBufferSize() const | ||||
| { | ||||
| 	return sizeof(btTriangleMeshShapeData); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //BVH_TRIANGLE_MESH_SHAPE_H | ||||
							
								
								
									
										171
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #include "btCapsuleShape.h" | ||||
|  | ||||
| #include "BulletCollision/CollisionShapes/btCollisionMargin.h" | ||||
| #include "LinearMath/btQuaternion.h" | ||||
|  | ||||
| btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape () | ||||
| { | ||||
| 	m_shapeType = CAPSULE_SHAPE_PROXYTYPE; | ||||
| 	m_upAxis = 1; | ||||
| 	m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); | ||||
| } | ||||
|  | ||||
|   | ||||
|  btVector3	btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const | ||||
| { | ||||
|  | ||||
| 	btVector3 supVec(0,0,0); | ||||
|  | ||||
| 	btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); | ||||
|  | ||||
| 	btVector3 vec = vec0; | ||||
| 	btScalar lenSqr = vec.length2(); | ||||
| 	if (lenSqr < btScalar(0.0001)) | ||||
| 	{ | ||||
| 		vec.setValue(1,0,0); | ||||
| 	} else | ||||
| 	{ | ||||
| 		btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); | ||||
| 		vec *= rlen; | ||||
| 	} | ||||
|  | ||||
| 	btVector3 vtx; | ||||
| 	btScalar newDot; | ||||
| 	 | ||||
| 	btScalar radius = getRadius(); | ||||
|  | ||||
|  | ||||
| 	{ | ||||
| 		btVector3 pos(0,0,0); | ||||
| 		pos[getUpAxis()] = getHalfHeight(); | ||||
|  | ||||
| 		vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); | ||||
| 		newDot = vec.dot(vtx); | ||||
| 		if (newDot > maxDot) | ||||
| 		{ | ||||
| 			maxDot = newDot; | ||||
| 			supVec = vtx; | ||||
| 		} | ||||
| 	} | ||||
| 	{ | ||||
| 		btVector3 pos(0,0,0); | ||||
| 		pos[getUpAxis()] = -getHalfHeight(); | ||||
|  | ||||
| 		vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); | ||||
| 		newDot = vec.dot(vtx); | ||||
| 		if (newDot > maxDot) | ||||
| 		{ | ||||
| 			maxDot = newDot; | ||||
| 			supVec = vtx; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return supVec; | ||||
|  | ||||
| } | ||||
|  | ||||
|  void	btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||||
| { | ||||
|  | ||||
| 	 | ||||
| 	btScalar radius = getRadius(); | ||||
|  | ||||
| 	for (int j=0;j<numVectors;j++) | ||||
| 	{ | ||||
| 		btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); | ||||
| 		const btVector3& vec = vectors[j]; | ||||
|  | ||||
| 		btVector3 vtx; | ||||
| 		btScalar newDot; | ||||
| 		{ | ||||
| 			btVector3 pos(0,0,0); | ||||
| 			pos[getUpAxis()] = getHalfHeight(); | ||||
| 			vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); | ||||
| 			newDot = vec.dot(vtx); | ||||
| 			if (newDot > maxDot) | ||||
| 			{ | ||||
| 				maxDot = newDot; | ||||
| 				supportVerticesOut[j] = vtx; | ||||
| 			} | ||||
| 		} | ||||
| 		{ | ||||
| 			btVector3 pos(0,0,0); | ||||
| 			pos[getUpAxis()] = -getHalfHeight(); | ||||
| 			vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); | ||||
| 			newDot = vec.dot(vtx); | ||||
| 			if (newDot > maxDot) | ||||
| 			{ | ||||
| 				maxDot = newDot; | ||||
| 				supportVerticesOut[j] = vtx; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const | ||||
| { | ||||
| 	//as an approximation, take the inertia of the box that bounds the spheres | ||||
|  | ||||
| 	btTransform ident; | ||||
| 	ident.setIdentity(); | ||||
|  | ||||
| 	 | ||||
| 	btScalar radius = getRadius(); | ||||
|  | ||||
| 	btVector3 halfExtents(radius,radius,radius); | ||||
| 	halfExtents[getUpAxis()]+=getHalfHeight(); | ||||
|  | ||||
| 	btScalar margin = CONVEX_DISTANCE_MARGIN; | ||||
|  | ||||
| 	btScalar lx=btScalar(2.)*(halfExtents[0]+margin); | ||||
| 	btScalar ly=btScalar(2.)*(halfExtents[1]+margin); | ||||
| 	btScalar lz=btScalar(2.)*(halfExtents[2]+margin); | ||||
| 	const btScalar x2 = lx*lx; | ||||
| 	const btScalar y2 = ly*ly; | ||||
| 	const btScalar z2 = lz*lz; | ||||
| 	const btScalar scaledmass = mass * btScalar(.08333333); | ||||
|  | ||||
| 	inertia[0] = scaledmass * (y2+z2); | ||||
| 	inertia[1] = scaledmass * (x2+z2); | ||||
| 	inertia[2] = scaledmass * (x2+y2); | ||||
|  | ||||
| } | ||||
|  | ||||
| btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height) | ||||
| { | ||||
| 	m_upAxis = 0; | ||||
| 	m_implicitShapeDimensions.setValue(0.5f*height, radius,radius); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height) | ||||
| { | ||||
| 	m_upAxis = 2; | ||||
| 	m_implicitShapeDimensions.setValue(radius,radius,0.5f*height); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										173
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BT_CAPSULE_SHAPE_H | ||||
| #define BT_CAPSULE_SHAPE_H | ||||
|  | ||||
| #include "btConvexInternalShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types | ||||
|  | ||||
|  | ||||
| ///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis. | ||||
| ///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. | ||||
| ///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres. | ||||
| class btCapsuleShape : public btConvexInternalShape | ||||
| { | ||||
| protected: | ||||
| 	int	m_upAxis; | ||||
|  | ||||
| protected: | ||||
| 	///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses. | ||||
| 	btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;}; | ||||
|  | ||||
| public: | ||||
| 	btCapsuleShape(btScalar radius,btScalar height); | ||||
|  | ||||
| 	///CollisionShape Interface | ||||
| 	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const; | ||||
|  | ||||
| 	/// btConvexShape Interface | ||||
| 	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const; | ||||
|  | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; | ||||
| 	 | ||||
| 	virtual void setMargin(btScalar collisionMargin) | ||||
| 	{ | ||||
| 		//correct the m_implicitShapeDimensions for the margin | ||||
| 		btVector3 oldMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; | ||||
| 		 | ||||
| 		btConvexInternalShape::setMargin(collisionMargin); | ||||
| 		btVector3 newMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const | ||||
| 	{ | ||||
| 			btVector3 halfExtents(getRadius(),getRadius(),getRadius()); | ||||
| 			halfExtents[m_upAxis] = getRadius() + getHalfHeight(); | ||||
| 			halfExtents += btVector3(getMargin(),getMargin(),getMargin()); | ||||
| 			btMatrix3x3 abs_b = t.getBasis().absolute();   | ||||
| 			btVector3 center = t.getOrigin(); | ||||
| 			btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));		   | ||||
| 			 | ||||
| 			aabbMin = center - extent; | ||||
| 			aabbMax = center + extent; | ||||
| 	} | ||||
|  | ||||
| 	virtual const char*	getName()const  | ||||
| 	{ | ||||
| 		return "CapsuleShape"; | ||||
| 	} | ||||
|  | ||||
| 	int	getUpAxis() const | ||||
| 	{ | ||||
| 		return m_upAxis; | ||||
| 	} | ||||
|  | ||||
| 	btScalar	getRadius() const | ||||
| 	{ | ||||
| 		int radiusAxis = (m_upAxis+2)%3; | ||||
| 		return m_implicitShapeDimensions[radiusAxis]; | ||||
| 	} | ||||
|  | ||||
| 	btScalar	getHalfHeight() const | ||||
| 	{ | ||||
| 		return m_implicitShapeDimensions[m_upAxis]; | ||||
| 	} | ||||
|  | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling) | ||||
| 	{ | ||||
| 		btVector3 oldMargin(getMargin(),getMargin(),getMargin()); | ||||
| 		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; | ||||
| 		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling; | ||||
|  | ||||
| 		btConvexInternalShape::setLocalScaling(scaling); | ||||
|  | ||||
| 		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	virtual	int	calculateSerializeBufferSize() const; | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| 	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const; | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| ///btCapsuleShapeX represents a capsule around the Z axis | ||||
| ///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. | ||||
| class btCapsuleShapeX : public btCapsuleShape | ||||
| { | ||||
| public: | ||||
|  | ||||
| 	btCapsuleShapeX(btScalar radius,btScalar height); | ||||
| 		 | ||||
| 	//debugging | ||||
| 	virtual const char*	getName()const | ||||
| 	{ | ||||
| 		return "CapsuleX"; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
| }; | ||||
|  | ||||
| ///btCapsuleShapeZ represents a capsule around the Z axis | ||||
| ///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. | ||||
| class btCapsuleShapeZ : public btCapsuleShape | ||||
| { | ||||
| public: | ||||
| 	btCapsuleShapeZ(btScalar radius,btScalar height); | ||||
|  | ||||
| 		//debugging | ||||
| 	virtual const char*	getName()const | ||||
| 	{ | ||||
| 		return "CapsuleZ"; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| }; | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct	btCapsuleShapeData | ||||
| { | ||||
| 	btConvexInternalShapeData	m_convexInternalShapeData; | ||||
|  | ||||
| 	int	m_upAxis; | ||||
|  | ||||
| 	char	m_padding[4]; | ||||
| }; | ||||
|  | ||||
| SIMD_FORCE_INLINE	int	btCapsuleShape::calculateSerializeBufferSize() const | ||||
| { | ||||
| 	return sizeof(btCapsuleShapeData); | ||||
| } | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| SIMD_FORCE_INLINE	const char*	btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const | ||||
| { | ||||
| 	btCapsuleShapeData* shapeData = (btCapsuleShapeData*) dataBuffer; | ||||
| 	 | ||||
| 	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer); | ||||
|  | ||||
| 	shapeData->m_upAxis = m_upAxis; | ||||
| 	 | ||||
| 	return "btCapsuleShapeData"; | ||||
| } | ||||
|  | ||||
| #endif //BT_CAPSULE_SHAPE_H | ||||
| @@ -0,0 +1,26 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_MARGIN_H | ||||
| #define COLLISION_MARGIN_H | ||||
|  | ||||
| //used by Gjk and some other algorithms | ||||
|  | ||||
| #define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01) | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //COLLISION_MARGIN_H | ||||
|  | ||||
							
								
								
									
										119
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
| #include "BulletCollision/CollisionShapes/btCollisionShape.h" | ||||
| #include "LinearMath/btSerializer.h" | ||||
|  | ||||
| /* | ||||
|   Make sure this dummy function never changes so that it | ||||
|   can be used by probes that are checking whether the | ||||
|   library is actually installed. | ||||
| */ | ||||
| extern "C"  | ||||
| { | ||||
| void btBulletCollisionProbe (); | ||||
|  | ||||
| void btBulletCollisionProbe () {} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const | ||||
| { | ||||
| 	btTransform tr; | ||||
| 	tr.setIdentity(); | ||||
| 	btVector3 aabbMin,aabbMax; | ||||
|  | ||||
| 	getAabb(tr,aabbMin,aabbMax); | ||||
|  | ||||
| 	radius = (aabbMax-aabbMin).length()*btScalar(0.5); | ||||
| 	center = (aabbMin+aabbMax)*btScalar(0.5); | ||||
| } | ||||
|  | ||||
|  | ||||
| btScalar	btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const | ||||
| { | ||||
| 	return getAngularMotionDisc() * defaultContactThreshold; | ||||
| } | ||||
|  | ||||
| btScalar	btCollisionShape::getAngularMotionDisc() const | ||||
| { | ||||
| 	///@todo cache this value, to improve performance | ||||
| 	btVector3	center; | ||||
| 	btScalar disc; | ||||
| 	getBoundingSphere(center,disc); | ||||
| 	disc += (center).length(); | ||||
| 	return disc; | ||||
| } | ||||
|  | ||||
| void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const | ||||
| { | ||||
| 	//start with static aabb | ||||
| 	getAabb(curTrans,temporalAabbMin,temporalAabbMax); | ||||
|  | ||||
| 	btScalar temporalAabbMaxx = temporalAabbMax.getX(); | ||||
| 	btScalar temporalAabbMaxy = temporalAabbMax.getY(); | ||||
| 	btScalar temporalAabbMaxz = temporalAabbMax.getZ(); | ||||
| 	btScalar temporalAabbMinx = temporalAabbMin.getX(); | ||||
| 	btScalar temporalAabbMiny = temporalAabbMin.getY(); | ||||
| 	btScalar temporalAabbMinz = temporalAabbMin.getZ(); | ||||
|  | ||||
| 	// add linear motion | ||||
| 	btVector3 linMotion = linvel*timeStep; | ||||
| 	///@todo: simd would have a vector max/min operation, instead of per-element access | ||||
| 	if (linMotion.x() > btScalar(0.)) | ||||
| 		temporalAabbMaxx += linMotion.x();  | ||||
| 	else | ||||
| 		temporalAabbMinx += linMotion.x(); | ||||
| 	if (linMotion.y() > btScalar(0.)) | ||||
| 		temporalAabbMaxy += linMotion.y();  | ||||
| 	else | ||||
| 		temporalAabbMiny += linMotion.y(); | ||||
| 	if (linMotion.z() > btScalar(0.)) | ||||
| 		temporalAabbMaxz += linMotion.z();  | ||||
| 	else | ||||
| 		temporalAabbMinz += linMotion.z(); | ||||
|  | ||||
| 	//add conservative angular motion | ||||
| 	btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep; | ||||
| 	btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); | ||||
| 	temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); | ||||
| 	temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); | ||||
|  | ||||
| 	temporalAabbMin -= angularMotion3d; | ||||
| 	temporalAabbMax += angularMotion3d; | ||||
| } | ||||
|  | ||||
| ///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| const char*	btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const | ||||
| { | ||||
| 	btCollisionShapeData* shapeData = (btCollisionShapeData*) dataBuffer; | ||||
| 	char* name = (char*) serializer->findNameForPointer(this); | ||||
| 	shapeData->m_name = (char*)serializer->getUniquePointer(name); | ||||
| 	if (shapeData->m_name) | ||||
| 	{ | ||||
| 		serializer->serializeName(name); | ||||
| 	} | ||||
| 	shapeData->m_shapeType = m_shapeType; | ||||
| 	//shapeData->m_padding//?? | ||||
| 	return "btCollisionShapeData"; | ||||
| } | ||||
|  | ||||
| void	btCollisionShape::serializeSingleShape(btSerializer* serializer) const | ||||
| { | ||||
| 	int len = calculateSerializeBufferSize(); | ||||
| 	btChunk* chunk = serializer->allocate(len,1); | ||||
| 	const char* structType = serialize(chunk->m_oldPtr, serializer); | ||||
| 	serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,(void*)this); | ||||
| } | ||||
							
								
								
									
										150
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_SHAPE_H | ||||
| #define COLLISION_SHAPE_H | ||||
|  | ||||
| #include "LinearMath/btTransform.h" | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btMatrix3x3.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types | ||||
| class btSerializer; | ||||
|  | ||||
|  | ||||
| ///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects. | ||||
| class btCollisionShape | ||||
| { | ||||
| protected: | ||||
| 	int m_shapeType; | ||||
| 	void* m_userPointer; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	virtual ~btCollisionShape() | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. | ||||
| 	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; | ||||
|  | ||||
| 	virtual void	getBoundingSphere(btVector3& center,btScalar& radius) const; | ||||
|  | ||||
| 	///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations. | ||||
| 	virtual btScalar	getAngularMotionDisc() const; | ||||
|  | ||||
| 	virtual btScalar	getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const; | ||||
|  | ||||
|  | ||||
| 	///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) | ||||
| 	///result is conservative | ||||
| 	void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const; | ||||
|  | ||||
|  | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool	isPolyhedral() const | ||||
| 	{ | ||||
| 		return btBroadphaseProxy::isPolyhedral(getShapeType()); | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool	isConvex2d() const | ||||
| 	{ | ||||
| 		return btBroadphaseProxy::isConvex2d(getShapeType()); | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool	isConvex() const | ||||
| 	{ | ||||
| 		return btBroadphaseProxy::isConvex(getShapeType()); | ||||
| 	} | ||||
| 	SIMD_FORCE_INLINE bool	isNonMoving() const | ||||
| 	{ | ||||
| 		return btBroadphaseProxy::isNonMoving(getShapeType()); | ||||
| 	} | ||||
| 	SIMD_FORCE_INLINE bool	isConcave() const | ||||
| 	{ | ||||
| 		return btBroadphaseProxy::isConcave(getShapeType()); | ||||
| 	} | ||||
| 	SIMD_FORCE_INLINE bool	isCompound() const | ||||
| 	{ | ||||
| 		return btBroadphaseProxy::isCompound(getShapeType()); | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE bool	isSoftBody() const | ||||
| 	{ | ||||
| 		return btBroadphaseProxy::isSoftBody(getShapeType()); | ||||
| 	} | ||||
|  | ||||
| 	///isInfinite is used to catch simulation error (aabb check) | ||||
| 	SIMD_FORCE_INLINE bool isInfinite() const | ||||
| 	{ | ||||
| 		return btBroadphaseProxy::isInfinite(getShapeType()); | ||||
| 	} | ||||
|  | ||||
| #ifndef __SPU__ | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling) =0; | ||||
| 	virtual const btVector3& getLocalScaling() const =0; | ||||
| 	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0; | ||||
|  | ||||
|  | ||||
| //debugging support | ||||
| 	virtual const char*	getName()const =0 ; | ||||
| #endif //__SPU__ | ||||
|  | ||||
| 	 | ||||
| 	int		getShapeType() const { return m_shapeType; } | ||||
| 	virtual void	setMargin(btScalar margin) = 0; | ||||
| 	virtual btScalar	getMargin() const = 0; | ||||
|  | ||||
| 	 | ||||
| 	///optional user data pointer | ||||
| 	void	setUserPointer(void*  userPtr) | ||||
| 	{ | ||||
| 		m_userPointer = userPtr; | ||||
| 	} | ||||
|  | ||||
| 	void*	getUserPointer() const | ||||
| 	{ | ||||
| 		return m_userPointer; | ||||
| 	} | ||||
|  | ||||
| 	virtual	int	calculateSerializeBufferSize() const; | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| 	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const; | ||||
|  | ||||
| 	virtual void	serializeSingleShape(btSerializer* serializer) const; | ||||
|  | ||||
| };	 | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct	btCollisionShapeData | ||||
| { | ||||
| 	char	*m_name; | ||||
| 	int		m_shapeType; | ||||
| 	char	m_padding[4]; | ||||
| }; | ||||
|  | ||||
| SIMD_FORCE_INLINE	int	btCollisionShape::calculateSerializeBufferSize() const | ||||
| { | ||||
| 	return sizeof(btCollisionShapeData); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //COLLISION_SHAPE_H | ||||
|  | ||||
							
								
								
									
										351
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,351 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btCompoundShape.h" | ||||
| #include "btCollisionShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDbvt.h" | ||||
| #include "LinearMath/btSerializer.h" | ||||
|  | ||||
| btCompoundShape::btCompoundShape(bool enableDynamicAabbTree) | ||||
| : m_localAabbMin(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)), | ||||
| m_localAabbMax(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)), | ||||
| m_dynamicAabbTree(0), | ||||
| m_updateRevision(1), | ||||
| m_collisionMargin(btScalar(0.)), | ||||
| m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) | ||||
| { | ||||
| 	m_shapeType = COMPOUND_SHAPE_PROXYTYPE; | ||||
|  | ||||
| 	if (enableDynamicAabbTree) | ||||
| 	{ | ||||
| 		void* mem = btAlignedAlloc(sizeof(btDbvt),16); | ||||
| 		m_dynamicAabbTree = new(mem) btDbvt(); | ||||
| 		btAssert(mem==m_dynamicAabbTree); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| btCompoundShape::~btCompoundShape() | ||||
| { | ||||
| 	if (m_dynamicAabbTree) | ||||
| 	{ | ||||
| 		m_dynamicAabbTree->~btDbvt(); | ||||
| 		btAlignedFree(m_dynamicAabbTree); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void	btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) | ||||
| { | ||||
| 	m_updateRevision++; | ||||
| 	//m_childTransforms.push_back(localTransform); | ||||
| 	//m_childShapes.push_back(shape); | ||||
| 	btCompoundShapeChild child; | ||||
| 	child.m_node = 0; | ||||
| 	child.m_transform = localTransform; | ||||
| 	child.m_childShape = shape; | ||||
| 	child.m_childShapeType = shape->getShapeType(); | ||||
| 	child.m_childMargin = shape->getMargin(); | ||||
|  | ||||
| 	 | ||||
| 	//extend the local aabbMin/aabbMax | ||||
| 	btVector3 localAabbMin,localAabbMax; | ||||
| 	shape->getAabb(localTransform,localAabbMin,localAabbMax); | ||||
| 	for (int i=0;i<3;i++) | ||||
| 	{ | ||||
| 		if (m_localAabbMin[i] > localAabbMin[i]) | ||||
| 		{ | ||||
| 			m_localAabbMin[i] = localAabbMin[i]; | ||||
| 		} | ||||
| 		if (m_localAabbMax[i] < localAabbMax[i]) | ||||
| 		{ | ||||
| 			m_localAabbMax[i] = localAabbMax[i]; | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| 	if (m_dynamicAabbTree) | ||||
| 	{ | ||||
| 		const btDbvtVolume	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); | ||||
| 		int index = m_children.size(); | ||||
| 		child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); | ||||
| 	} | ||||
|  | ||||
| 	m_children.push_back(child); | ||||
|  | ||||
| } | ||||
|  | ||||
| void	btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform) | ||||
| { | ||||
| 	m_children[childIndex].m_transform = newChildTransform; | ||||
|  | ||||
| 	if (m_dynamicAabbTree) | ||||
| 	{ | ||||
| 		///update the dynamic aabb tree | ||||
| 		btVector3 localAabbMin,localAabbMax; | ||||
| 		m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax); | ||||
| 		ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); | ||||
| 		//int index = m_children.size()-1; | ||||
| 		m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds); | ||||
| 	} | ||||
|  | ||||
| 	recalculateLocalAabb(); | ||||
| } | ||||
|  | ||||
| void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) | ||||
| { | ||||
| 	m_updateRevision++; | ||||
| 	btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); | ||||
| 	if (m_dynamicAabbTree) | ||||
| 	{ | ||||
| 		m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node); | ||||
| 	} | ||||
| 	m_children.swap(childShapeIndex,m_children.size()-1); | ||||
|     if (m_dynamicAabbTree)  | ||||
| 		m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex; | ||||
| 	m_children.pop_back(); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void btCompoundShape::removeChildShape(btCollisionShape* shape) | ||||
| { | ||||
| 	m_updateRevision++; | ||||
| 	// Find the children containing the shape specified, and remove those children. | ||||
| 	//note: there might be multiple children using the same shape! | ||||
| 	for(int i = m_children.size()-1; i >= 0 ; i--) | ||||
| 	{ | ||||
| 		if(m_children[i].m_childShape == shape) | ||||
| 		{ | ||||
| 			removeChildShapeByIndex(i); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| 	recalculateLocalAabb(); | ||||
| } | ||||
|  | ||||
| void btCompoundShape::recalculateLocalAabb() | ||||
| { | ||||
| 	// Recalculate the local aabb | ||||
| 	// Brute force, it iterates over all the shapes left. | ||||
|  | ||||
| 	m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | ||||
| 	m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); | ||||
|  | ||||
| 	//extend the local aabbMin/aabbMax | ||||
| 	for (int j = 0; j < m_children.size(); j++) | ||||
| 	{ | ||||
| 		btVector3 localAabbMin,localAabbMax; | ||||
| 		m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax); | ||||
| 		for (int i=0;i<3;i++) | ||||
| 		{ | ||||
| 			if (m_localAabbMin[i] > localAabbMin[i]) | ||||
| 				m_localAabbMin[i] = localAabbMin[i]; | ||||
| 			if (m_localAabbMax[i] < localAabbMax[i]) | ||||
| 				m_localAabbMax[i] = localAabbMax[i]; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version | ||||
| void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const | ||||
| { | ||||
| 	btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); | ||||
| 	btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); | ||||
| 	 | ||||
| 	//avoid an illegal AABB when there are no children | ||||
| 	if (!m_children.size()) | ||||
| 	{ | ||||
| 		localHalfExtents.setValue(0,0,0); | ||||
| 		localCenter.setValue(0,0,0); | ||||
| 	} | ||||
| 	localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); | ||||
| 		 | ||||
|  | ||||
| 	btMatrix3x3 abs_b = trans.getBasis().absolute();   | ||||
|  | ||||
| 	btVector3 center = trans(localCenter); | ||||
|  | ||||
| 	btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), | ||||
| 		abs_b[1].dot(localHalfExtents), | ||||
| 		abs_b[2].dot(localHalfExtents)); | ||||
| 	aabbMin = center-extent; | ||||
| 	aabbMax = center+extent; | ||||
| 	 | ||||
| } | ||||
|  | ||||
| void	btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const | ||||
| { | ||||
| 	//approximation: take the inertia from the aabb for now | ||||
| 	btTransform ident; | ||||
| 	ident.setIdentity(); | ||||
| 	btVector3 aabbMin,aabbMax; | ||||
| 	getAabb(ident,aabbMin,aabbMax); | ||||
|  | ||||
| 	btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); | ||||
|  | ||||
| 	btScalar lx=btScalar(2.)*(halfExtents.x()); | ||||
| 	btScalar ly=btScalar(2.)*(halfExtents.y()); | ||||
| 	btScalar lz=btScalar(2.)*(halfExtents.z()); | ||||
|  | ||||
| 	inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz); | ||||
| 	inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz); | ||||
| 	inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const | ||||
| { | ||||
| 	int n = m_children.size(); | ||||
|  | ||||
| 	btScalar totalMass = 0; | ||||
| 	btVector3 center(0, 0, 0); | ||||
| 	int k; | ||||
|  | ||||
| 	for (k = 0; k < n; k++) | ||||
| 	{ | ||||
| 		btAssert(masses[k]>0); | ||||
| 		center += m_children[k].m_transform.getOrigin() * masses[k]; | ||||
| 		totalMass += masses[k]; | ||||
| 	} | ||||
|  | ||||
| 	btAssert(totalMass>0); | ||||
|  | ||||
| 	center /= totalMass; | ||||
| 	principal.setOrigin(center); | ||||
|  | ||||
| 	btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0); | ||||
| 	for ( k = 0; k < n; k++) | ||||
| 	{ | ||||
| 		btVector3 i; | ||||
| 		m_children[k].m_childShape->calculateLocalInertia(masses[k], i); | ||||
|  | ||||
| 		const btTransform& t = m_children[k].m_transform; | ||||
| 		btVector3 o = t.getOrigin() - center; | ||||
|  | ||||
| 		//compute inertia tensor in coordinate system of compound shape | ||||
| 		btMatrix3x3 j = t.getBasis().transpose(); | ||||
| 		j[0] *= i[0]; | ||||
| 		j[1] *= i[1]; | ||||
| 		j[2] *= i[2]; | ||||
| 		j = t.getBasis() * j; | ||||
|  | ||||
| 		//add inertia tensor | ||||
| 		tensor[0] += j[0]; | ||||
| 		tensor[1] += j[1]; | ||||
| 		tensor[2] += j[2]; | ||||
|  | ||||
| 		//compute inertia tensor of pointmass at o | ||||
| 		btScalar o2 = o.length2(); | ||||
| 		j[0].setValue(o2, 0, 0); | ||||
| 		j[1].setValue(0, o2, 0); | ||||
| 		j[2].setValue(0, 0, o2); | ||||
| 		j[0] += o * -o.x();  | ||||
| 		j[1] += o * -o.y();  | ||||
| 		j[2] += o * -o.z(); | ||||
|  | ||||
| 		//add inertia tensor of pointmass | ||||
| 		tensor[0] += masses[k] * j[0]; | ||||
| 		tensor[1] += masses[k] * j[1]; | ||||
| 		tensor[2] += masses[k] * j[2]; | ||||
| 	} | ||||
|  | ||||
| 	tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20); | ||||
| 	inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void btCompoundShape::setLocalScaling(const btVector3& scaling) | ||||
| { | ||||
|  | ||||
| 	for(int i = 0; i < m_children.size(); i++) | ||||
| 	{ | ||||
| 		btTransform childTrans = getChildTransform(i); | ||||
| 		btVector3 childScale = m_children[i].m_childShape->getLocalScaling(); | ||||
| //		childScale = childScale * (childTrans.getBasis() * scaling); | ||||
| 		childScale = childScale * scaling / m_localScaling; | ||||
| 		m_children[i].m_childShape->setLocalScaling(childScale); | ||||
| 		childTrans.setOrigin((childTrans.getOrigin())*scaling); | ||||
| 		updateChildTransform(i, childTrans); | ||||
| 		recalculateLocalAabb(); | ||||
| 	} | ||||
| 	m_localScaling = scaling; | ||||
| } | ||||
|  | ||||
|  | ||||
| void btCompoundShape::createAabbTreeFromChildren() | ||||
| { | ||||
|     if ( !m_dynamicAabbTree ) | ||||
|     { | ||||
|         void* mem = btAlignedAlloc(sizeof(btDbvt),16); | ||||
|         m_dynamicAabbTree = new(mem) btDbvt(); | ||||
|         btAssert(mem==m_dynamicAabbTree); | ||||
|  | ||||
|         for ( int index = 0; index < m_children.size(); index++ ) | ||||
|         { | ||||
|             btCompoundShapeChild &child = m_children[index]; | ||||
|  | ||||
|             //extend the local aabbMin/aabbMax | ||||
|             btVector3 localAabbMin,localAabbMax; | ||||
|             child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax); | ||||
|  | ||||
|             const btDbvtVolume  bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); | ||||
|             child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| ///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| const char*	btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const | ||||
| { | ||||
|  | ||||
| 	btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer; | ||||
| 	btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer); | ||||
|  | ||||
| 	shapeData->m_collisionMargin = float(m_collisionMargin); | ||||
| 	shapeData->m_numChildShapes = m_children.size(); | ||||
| 	shapeData->m_childShapePtr = 0; | ||||
| 	if (shapeData->m_numChildShapes) | ||||
| 	{ | ||||
| 		btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes); | ||||
| 		btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr; | ||||
| 		shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr); | ||||
|  | ||||
| 		for (int i=0;i<shapeData->m_numChildShapes;i++,memPtr++) | ||||
| 		{ | ||||
| 			memPtr->m_childMargin = float(m_children[i].m_childMargin); | ||||
| 			memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape); | ||||
| 			//don't serialize shapes that already have been serialized | ||||
| 			if (!serializer->findPointer(m_children[i].m_childShape)) | ||||
| 			{ | ||||
| 				btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1); | ||||
| 				const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer); | ||||
| 				serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape); | ||||
| 			}  | ||||
|  | ||||
| 			memPtr->m_childShapeType = m_children[i].m_childShapeType; | ||||
| 			m_children[i].m_transform.serializeFloat(memPtr->m_transform); | ||||
| 		} | ||||
| 		serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr); | ||||
| 	} | ||||
| 	return "btCompoundShapeData"; | ||||
| } | ||||
|  | ||||
							
								
								
									
										208
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								libs/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COMPOUND_SHAPE_H | ||||
| #define COMPOUND_SHAPE_H | ||||
|  | ||||
| #include "btCollisionShape.h" | ||||
|  | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btTransform.h" | ||||
| #include "LinearMath/btMatrix3x3.h" | ||||
| #include "btCollisionMargin.h" | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
| //class btOptimizedBvh; | ||||
| struct btDbvt; | ||||
|  | ||||
| ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild | ||||
| { | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	btTransform			m_transform; | ||||
| 	btCollisionShape*	m_childShape; | ||||
| 	int					m_childShapeType; | ||||
| 	btScalar			m_childMargin; | ||||
| 	struct btDbvtNode*	m_node; | ||||
| }; | ||||
|  | ||||
| SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2) | ||||
| { | ||||
| 	return  ( c1.m_transform      == c2.m_transform && | ||||
| 		c1.m_childShape     == c2.m_childShape && | ||||
| 		c1.m_childShapeType == c2.m_childShapeType && | ||||
| 		c1.m_childMargin    == c2.m_childMargin ); | ||||
| } | ||||
|  | ||||
| /// The btCompoundShape allows to store multiple other btCollisionShapes | ||||
| /// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape. | ||||
| /// It has an (optional) dynamic aabb tree to accelerate early rejection tests.  | ||||
| /// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25 | ||||
| /// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape) | ||||
| ATTRIBUTE_ALIGNED16(class) btCompoundShape	: public btCollisionShape | ||||
| { | ||||
| 	btAlignedObjectArray<btCompoundShapeChild> m_children; | ||||
| 	btVector3						m_localAabbMin; | ||||
| 	btVector3						m_localAabbMax; | ||||
|  | ||||
| 	btDbvt*							m_dynamicAabbTree; | ||||
|  | ||||
| 	///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated | ||||
| 	int								m_updateRevision; | ||||
|  | ||||
| 	btScalar	m_collisionMargin; | ||||
|  | ||||
| protected: | ||||
| 	btVector3	m_localScaling; | ||||
|  | ||||
| public: | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	btCompoundShape(bool enableDynamicAabbTree = true); | ||||
|  | ||||
| 	virtual ~btCompoundShape(); | ||||
|  | ||||
| 	void	addChildShape(const btTransform& localTransform,btCollisionShape* shape); | ||||
|  | ||||
| 	/// Remove all children shapes that contain the specified shape | ||||
| 	virtual void removeChildShape(btCollisionShape* shape); | ||||
|  | ||||
| 	void removeChildShapeByIndex(int childShapeindex); | ||||
|  | ||||
|  | ||||
| 	int		getNumChildShapes() const | ||||
| 	{ | ||||
| 		return int (m_children.size()); | ||||
| 	} | ||||
|  | ||||
| 	btCollisionShape* getChildShape(int index) | ||||
| 	{ | ||||
| 		return m_children[index].m_childShape; | ||||
| 	} | ||||
| 	const btCollisionShape* getChildShape(int index) const | ||||
| 	{ | ||||
| 		return m_children[index].m_childShape; | ||||
| 	} | ||||
|  | ||||
| 	btTransform&	getChildTransform(int index) | ||||
| 	{ | ||||
| 		return m_children[index].m_transform; | ||||
| 	} | ||||
| 	const btTransform&	getChildTransform(int index) const | ||||
| 	{ | ||||
| 		return m_children[index].m_transform; | ||||
| 	} | ||||
|  | ||||
| 	///set a new transform for a child, and update internal data structures (local aabb and dynamic tree) | ||||
| 	void	updateChildTransform(int childIndex, const btTransform& newChildTransform); | ||||
|  | ||||
|  | ||||
| 	btCompoundShapeChild* getChildList() | ||||
| 	{ | ||||
| 		return &m_children[0]; | ||||
| 	} | ||||
|  | ||||
| 	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version | ||||
| 	virtual	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; | ||||
|  | ||||
| 	/** Re-calculate the local Aabb. Is called at the end of removeChildShapes.  | ||||
| 	Use this yourself if you modify the children or their transforms. */ | ||||
| 	virtual void recalculateLocalAabb();  | ||||
|  | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling); | ||||
|  | ||||
| 	virtual const btVector3& getLocalScaling() const  | ||||
| 	{ | ||||
| 		return m_localScaling; | ||||
| 	} | ||||
|  | ||||
| 	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const; | ||||
|  | ||||
| 	virtual void	setMargin(btScalar margin) | ||||
| 	{ | ||||
| 		m_collisionMargin = margin; | ||||
| 	} | ||||
| 	virtual btScalar	getMargin() const | ||||
| 	{ | ||||
| 		return m_collisionMargin; | ||||
| 	} | ||||
| 	virtual const char*	getName()const | ||||
| 	{ | ||||
| 		return "Compound"; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	btDbvt*							getDynamicAabbTree() | ||||
| 	{ | ||||
| 		return m_dynamicAabbTree; | ||||
| 	} | ||||
|  | ||||
| 	void createAabbTreeFromChildren(); | ||||
|  | ||||
| 	///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia | ||||
| 	///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform | ||||
| 	///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound | ||||
| 	///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform | ||||
| 	///of the collision object by the principal transform. | ||||
| 	void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; | ||||
|  | ||||
| 	int	getUpdateRevision() const | ||||
| 	{ | ||||
| 		return m_updateRevision; | ||||
| 	} | ||||
|  | ||||
| 	virtual	int	calculateSerializeBufferSize() const; | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| 	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const; | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct btCompoundShapeChildData | ||||
| { | ||||
| 	btTransformFloatData	m_transform; | ||||
| 	btCollisionShapeData	*m_childShape; | ||||
| 	int						m_childShapeType; | ||||
| 	float					m_childMargin; | ||||
| }; | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct	btCompoundShapeData | ||||
| { | ||||
| 	btCollisionShapeData		m_collisionShapeData; | ||||
|  | ||||
| 	btCompoundShapeChildData	*m_childShapePtr; | ||||
|  | ||||
| 	int							m_numChildShapes; | ||||
|  | ||||
| 	float	m_collisionMargin; | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| SIMD_FORCE_INLINE	int	btCompoundShape::calculateSerializeBufferSize() const | ||||
| { | ||||
| 	return sizeof(btCompoundShapeData); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //COMPOUND_SHAPE_H | ||||
| @@ -0,0 +1,27 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #include "btConcaveShape.h" | ||||
|  | ||||
| btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.)) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| btConcaveShape::~btConcaveShape() | ||||
| { | ||||
|  | ||||
| } | ||||
							
								
								
									
										60
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONCAVE_SHAPE_H | ||||
| #define CONCAVE_SHAPE_H | ||||
|  | ||||
| #include "btCollisionShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types | ||||
| #include "btTriangleCallback.h" | ||||
|  | ||||
| /// PHY_ScalarType enumerates possible scalar types. | ||||
| /// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use | ||||
| typedef enum PHY_ScalarType { | ||||
| 	PHY_FLOAT, | ||||
| 	PHY_DOUBLE, | ||||
| 	PHY_INTEGER, | ||||
| 	PHY_SHORT, | ||||
| 	PHY_FIXEDPOINT88, | ||||
| 	PHY_UCHAR | ||||
| } PHY_ScalarType; | ||||
|  | ||||
| ///The btConcaveShape class provides an interface for non-moving (static) concave shapes. | ||||
| ///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape. | ||||
| class btConcaveShape : public btCollisionShape | ||||
| { | ||||
| protected: | ||||
| 	btScalar m_collisionMargin; | ||||
|  | ||||
| public: | ||||
| 	btConcaveShape(); | ||||
|  | ||||
| 	virtual ~btConcaveShape(); | ||||
|  | ||||
| 	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0; | ||||
|  | ||||
| 	virtual btScalar getMargin() const { | ||||
| 		return m_collisionMargin; | ||||
| 	} | ||||
| 	virtual void setMargin(btScalar collisionMargin) | ||||
| 	{ | ||||
| 		m_collisionMargin = collisionMargin; | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //CONCAVE_SHAPE_H | ||||
							
								
								
									
										133
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btConeShape.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| btConeShape::btConeShape (btScalar radius,btScalar height): btConvexInternalShape (), | ||||
| m_radius (radius), | ||||
| m_height(height) | ||||
| { | ||||
| 	m_shapeType = CONE_SHAPE_PROXYTYPE; | ||||
| 	setConeUpIndex(1); | ||||
| 	btVector3 halfExtents; | ||||
| 	m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height)); | ||||
| } | ||||
|  | ||||
| btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height): | ||||
| btConeShape(radius,height) | ||||
| { | ||||
| 	setConeUpIndex(2); | ||||
| } | ||||
|  | ||||
| btConeShapeX::btConeShapeX (btScalar radius,btScalar height): | ||||
| btConeShape(radius,height) | ||||
| { | ||||
| 	setConeUpIndex(0); | ||||
| } | ||||
|  | ||||
| ///choose upAxis index | ||||
| void	btConeShape::setConeUpIndex(int upIndex) | ||||
| { | ||||
| 	switch (upIndex) | ||||
| 	{ | ||||
| 	case 0: | ||||
| 			m_coneIndices[0] = 1; | ||||
| 			m_coneIndices[1] = 0; | ||||
| 			m_coneIndices[2] = 2; | ||||
| 		break; | ||||
| 	case 1: | ||||
| 			m_coneIndices[0] = 0; | ||||
| 			m_coneIndices[1] = 1; | ||||
| 			m_coneIndices[2] = 2; | ||||
| 		break; | ||||
| 	case 2: | ||||
| 			m_coneIndices[0] = 0; | ||||
| 			m_coneIndices[1] = 2; | ||||
| 			m_coneIndices[2] = 1; | ||||
| 		break; | ||||
| 	default: | ||||
| 		btAssert(0); | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| btVector3 btConeShape::coneLocalSupport(const btVector3& v) const | ||||
| { | ||||
| 	 | ||||
| 	btScalar halfHeight = m_height * btScalar(0.5); | ||||
|  | ||||
|  if (v[m_coneIndices[1]] > v.length() * m_sinAngle) | ||||
|  { | ||||
| 	btVector3 tmp; | ||||
|  | ||||
| 	tmp[m_coneIndices[0]] = btScalar(0.); | ||||
| 	tmp[m_coneIndices[1]] = halfHeight; | ||||
| 	tmp[m_coneIndices[2]] = btScalar(0.); | ||||
| 	return tmp; | ||||
|  } | ||||
|   else { | ||||
|     btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]); | ||||
|     if (s > SIMD_EPSILON) { | ||||
|       btScalar d = m_radius / s; | ||||
| 	  btVector3 tmp; | ||||
| 	  tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d; | ||||
| 	  tmp[m_coneIndices[1]] = -halfHeight; | ||||
| 	  tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d; | ||||
| 	  return tmp; | ||||
|     } | ||||
|     else  { | ||||
| 		btVector3 tmp; | ||||
| 		tmp[m_coneIndices[0]] = btScalar(0.); | ||||
| 		tmp[m_coneIndices[1]] = -halfHeight; | ||||
| 		tmp[m_coneIndices[2]] = btScalar(0.); | ||||
| 		return tmp; | ||||
| 	} | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| btVector3	btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const | ||||
| { | ||||
| 		return coneLocalSupport(vec); | ||||
| } | ||||
|  | ||||
| void	btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||||
| { | ||||
| 	for (int i=0;i<numVectors;i++) | ||||
| 	{ | ||||
| 		const btVector3& vec = vectors[i]; | ||||
| 		supportVerticesOut[i] = coneLocalSupport(vec); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| btVector3	btConeShape::localGetSupportingVertex(const btVector3& vec)  const | ||||
| { | ||||
| 	btVector3 supVertex = coneLocalSupport(vec); | ||||
| 	if ( getMargin()!=btScalar(0.) ) | ||||
| 	{ | ||||
| 		btVector3 vecnorm = vec; | ||||
| 		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) | ||||
| 		{ | ||||
| 			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); | ||||
| 		}  | ||||
| 		vecnorm.normalize(); | ||||
| 		supVertex+= getMargin() * vecnorm; | ||||
| 	} | ||||
| 	return supVertex; | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										100
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConeShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConeShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONE_MINKOWSKI_H | ||||
| #define CONE_MINKOWSKI_H | ||||
|  | ||||
| #include "btConvexInternalShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types | ||||
|  | ||||
| ///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis. | ||||
| class btConeShape : public btConvexInternalShape | ||||
|  | ||||
| { | ||||
|  | ||||
| 	btScalar m_sinAngle; | ||||
| 	btScalar m_radius; | ||||
| 	btScalar m_height; | ||||
| 	int		m_coneIndices[3]; | ||||
| 	btVector3 coneLocalSupport(const btVector3& v) const; | ||||
|  | ||||
|  | ||||
| public: | ||||
| 	btConeShape (btScalar radius,btScalar height); | ||||
| 	 | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const; | ||||
| 	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec) const; | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; | ||||
|  | ||||
| 	btScalar getRadius() const { return m_radius;} | ||||
| 	btScalar getHeight() const { return m_height;} | ||||
|  | ||||
|  | ||||
| 	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const | ||||
| 	{ | ||||
| 		btTransform identity; | ||||
| 		identity.setIdentity(); | ||||
| 		btVector3 aabbMin,aabbMax; | ||||
| 		getAabb(identity,aabbMin,aabbMax); | ||||
|  | ||||
| 		btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); | ||||
|  | ||||
| 		btScalar margin = getMargin(); | ||||
|  | ||||
| 		btScalar lx=btScalar(2.)*(halfExtents.x()+margin); | ||||
| 		btScalar ly=btScalar(2.)*(halfExtents.y()+margin); | ||||
| 		btScalar lz=btScalar(2.)*(halfExtents.z()+margin); | ||||
| 		const btScalar x2 = lx*lx; | ||||
| 		const btScalar y2 = ly*ly; | ||||
| 		const btScalar z2 = lz*lz; | ||||
| 		const btScalar scaledmass = mass * btScalar(0.08333333); | ||||
|  | ||||
| 		inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); | ||||
|  | ||||
| //		inertia.x() = scaledmass * (y2+z2); | ||||
| //		inertia.y() = scaledmass * (x2+z2); | ||||
| //		inertia.z() = scaledmass * (x2+y2); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 		virtual const char*	getName()const  | ||||
| 		{ | ||||
| 			return "Cone"; | ||||
| 		} | ||||
| 		 | ||||
| 		///choose upAxis index | ||||
| 		void	setConeUpIndex(int upIndex); | ||||
| 		 | ||||
| 		int	getConeUpIndex() const | ||||
| 		{ | ||||
| 			return m_coneIndices[1]; | ||||
| 		} | ||||
| }; | ||||
|  | ||||
| ///btConeShape implements a Cone shape, around the X axis | ||||
| class btConeShapeX : public btConeShape | ||||
| { | ||||
| 	public: | ||||
| 		btConeShapeX(btScalar radius,btScalar height); | ||||
| }; | ||||
|  | ||||
| ///btConeShapeZ implements a Cone shape, around the Z axis | ||||
| class btConeShapeZ : public btConeShape | ||||
| { | ||||
| 	public: | ||||
| 		btConeShapeZ(btScalar radius,btScalar height); | ||||
| }; | ||||
| #endif //CONE_MINKOWSKI_H | ||||
|  | ||||
| @@ -0,0 +1,92 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btConvex2dShape.h" | ||||
|  | ||||
| btConvex2dShape::btConvex2dShape(	btConvexShape* convexChildShape): | ||||
| btConvexShape (), m_childConvexShape(convexChildShape) | ||||
| { | ||||
| 	m_shapeType = CONVEX_2D_SHAPE_PROXYTYPE; | ||||
| } | ||||
| 	 | ||||
| btConvex2dShape::~btConvex2dShape() | ||||
| { | ||||
| } | ||||
|  | ||||
| 	 | ||||
|  | ||||
| btVector3	btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const | ||||
| { | ||||
| 	return m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); | ||||
| } | ||||
|  | ||||
| void	btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||||
| { | ||||
| 	m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); | ||||
| } | ||||
|  | ||||
|  | ||||
| btVector3	btConvex2dShape::localGetSupportingVertex(const btVector3& vec)const | ||||
| { | ||||
| 	return m_childConvexShape->localGetSupportingVertex(vec); | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btConvex2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const | ||||
| { | ||||
| 	///this linear upscaling is not realistic, but we don't deal with large mass ratios... | ||||
| 	m_childConvexShape->calculateLocalInertia(mass,inertia); | ||||
| } | ||||
|  | ||||
|  | ||||
| 	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version | ||||
| void btConvex2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const | ||||
| { | ||||
| 	m_childConvexShape->getAabb(t,aabbMin,aabbMax); | ||||
| } | ||||
|  | ||||
| void btConvex2dShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const | ||||
| { | ||||
| 	m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax); | ||||
| } | ||||
|  | ||||
| void	btConvex2dShape::setLocalScaling(const btVector3& scaling)  | ||||
| { | ||||
| 	m_childConvexShape->setLocalScaling(scaling); | ||||
| } | ||||
|  | ||||
| const btVector3& btConvex2dShape::getLocalScaling() const | ||||
| { | ||||
| 	return m_childConvexShape->getLocalScaling(); | ||||
| } | ||||
|  | ||||
| void	btConvex2dShape::setMargin(btScalar margin) | ||||
| { | ||||
| 	m_childConvexShape->setMargin(margin); | ||||
| } | ||||
| btScalar	btConvex2dShape::getMargin() const | ||||
| { | ||||
| 	return m_childConvexShape->getMargin(); | ||||
| } | ||||
|  | ||||
| int		btConvex2dShape::getNumPreferredPenetrationDirections() const | ||||
| { | ||||
| 	return m_childConvexShape->getNumPreferredPenetrationDirections(); | ||||
| } | ||||
| 	 | ||||
| void	btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const | ||||
| { | ||||
| 	m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); | ||||
| } | ||||
| @@ -0,0 +1,80 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BT_CONVEX_2D_SHAPE_H | ||||
| #define BT_CONVEX_2D_SHAPE_H | ||||
|  | ||||
| #include "BulletCollision/CollisionShapes/btConvexShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types | ||||
|  | ||||
| ///The btConvex2dShape allows to use arbitrary convex shapes are 2d convex shapes, with the Z component assumed to be 0. | ||||
| ///For 2d boxes, the btBox2dShape is recommended. | ||||
| class btConvex2dShape : public btConvexShape | ||||
| { | ||||
| 	btConvexShape*	m_childConvexShape; | ||||
|  | ||||
| 	public: | ||||
| 	 | ||||
| 	btConvex2dShape(	btConvexShape* convexChildShape); | ||||
| 	 | ||||
| 	virtual ~btConvex2dShape(); | ||||
| 	 | ||||
| 	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const; | ||||
|  | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const; | ||||
|  | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; | ||||
|  | ||||
| 	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const; | ||||
|  | ||||
| 	btConvexShape*	getChildShape()  | ||||
| 	{ | ||||
| 		return m_childConvexShape; | ||||
| 	} | ||||
|  | ||||
| 	const btConvexShape*	getChildShape() const | ||||
| 	{ | ||||
| 		return m_childConvexShape; | ||||
| 	} | ||||
|  | ||||
| 	virtual const char*	getName()const  | ||||
| 	{ | ||||
| 		return "Convex2dShape"; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 	/////////////////////////// | ||||
|  | ||||
|  | ||||
| 	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version | ||||
| 	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; | ||||
|  | ||||
| 	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; | ||||
|  | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling) ; | ||||
| 	virtual const btVector3& getLocalScaling() const ; | ||||
|  | ||||
| 	virtual void	setMargin(btScalar margin); | ||||
| 	virtual btScalar	getMargin() const; | ||||
|  | ||||
| 	virtual int		getNumPreferredPenetrationDirections() const; | ||||
| 	 | ||||
| 	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BT_CONVEX_2D_SHAPE_H | ||||
| @@ -0,0 +1,211 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btConvexHullShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btCollisionMargin.h" | ||||
|  | ||||
| #include "LinearMath/btQuaternion.h" | ||||
| #include "LinearMath/btSerializer.h" | ||||
|  | ||||
| btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape () | ||||
| { | ||||
| 	m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE; | ||||
| 	m_unscaledPoints.resize(numPoints); | ||||
|  | ||||
| 	unsigned char* pointsAddress = (unsigned char*)points; | ||||
|  | ||||
| 	for (int i=0;i<numPoints;i++) | ||||
| 	{ | ||||
| 		btScalar* point = (btScalar*)pointsAddress; | ||||
| 		m_unscaledPoints[i] = btVector3(point[0], point[1], point[2]); | ||||
| 		pointsAddress += stride; | ||||
| 	} | ||||
|  | ||||
| 	recalcLocalAabb(); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void btConvexHullShape::setLocalScaling(const btVector3& scaling) | ||||
| { | ||||
| 	m_localScaling = scaling; | ||||
| 	recalcLocalAabb(); | ||||
| } | ||||
|  | ||||
| void btConvexHullShape::addPoint(const btVector3& point) | ||||
| { | ||||
| 	m_unscaledPoints.push_back(point); | ||||
| 	recalcLocalAabb(); | ||||
|  | ||||
| } | ||||
|  | ||||
| btVector3	btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const | ||||
| { | ||||
| 	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); | ||||
| 	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT); | ||||
|  | ||||
| 	for (int i=0;i<m_unscaledPoints.size();i++) | ||||
| 	{ | ||||
| 		btVector3 vtx = m_unscaledPoints[i] * m_localScaling; | ||||
|  | ||||
| 		newDot = vec.dot(vtx); | ||||
| 		if (newDot > maxDot) | ||||
| 		{ | ||||
| 			maxDot = newDot; | ||||
| 			supVec = vtx; | ||||
| 		} | ||||
| 	} | ||||
| 	return supVec; | ||||
| } | ||||
|  | ||||
| void	btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||||
| { | ||||
| 	btScalar newDot; | ||||
| 	//use 'w' component of supportVerticesOut? | ||||
| 	{ | ||||
| 		for (int i=0;i<numVectors;i++) | ||||
| 		{ | ||||
| 			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT); | ||||
| 		} | ||||
| 	} | ||||
| 	for (int i=0;i<m_unscaledPoints.size();i++) | ||||
| 	{ | ||||
| 		btVector3 vtx = getScaledPoint(i); | ||||
|  | ||||
| 		for (int j=0;j<numVectors;j++) | ||||
| 		{ | ||||
| 			const btVector3& vec = vectors[j]; | ||||
| 			 | ||||
| 			newDot = vec.dot(vtx); | ||||
| 			if (newDot > supportVerticesOut[j][3]) | ||||
| 			{ | ||||
| 				//WARNING: don't swap next lines, the w component would get overwritten! | ||||
| 				supportVerticesOut[j] = vtx; | ||||
| 				supportVerticesOut[j][3] = newDot; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| 	 | ||||
|  | ||||
|  | ||||
| btVector3	btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const | ||||
| { | ||||
| 	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); | ||||
|  | ||||
| 	if ( getMargin()!=btScalar(0.) ) | ||||
| 	{ | ||||
| 		btVector3 vecnorm = vec; | ||||
| 		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) | ||||
| 		{ | ||||
| 			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); | ||||
| 		}  | ||||
| 		vecnorm.normalize(); | ||||
| 		supVertex+= getMargin() * vecnorm; | ||||
| 	} | ||||
| 	return supVertex; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| //currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection | ||||
| //Please note that you can debug-draw btConvexHullShape with the Raytracer Demo | ||||
| int	btConvexHullShape::getNumVertices() const | ||||
| { | ||||
| 	return m_unscaledPoints.size(); | ||||
| } | ||||
|  | ||||
| int btConvexHullShape::getNumEdges() const | ||||
| { | ||||
| 	return m_unscaledPoints.size(); | ||||
| } | ||||
|  | ||||
| void btConvexHullShape::getEdge(int i,btVector3& pa,btVector3& pb) const | ||||
| { | ||||
|  | ||||
| 	int index0 = i%m_unscaledPoints.size(); | ||||
| 	int index1 = (i+1)%m_unscaledPoints.size(); | ||||
| 	pa = getScaledPoint(index0); | ||||
| 	pb = getScaledPoint(index1); | ||||
| } | ||||
|  | ||||
| void btConvexHullShape::getVertex(int i,btVector3& vtx) const | ||||
| { | ||||
| 	vtx = getScaledPoint(i); | ||||
| } | ||||
|  | ||||
| int	btConvexHullShape::getNumPlanes() const | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void btConvexHullShape::getPlane(btVector3& ,btVector3& ,int ) const | ||||
| { | ||||
|  | ||||
| 	btAssert(0); | ||||
| } | ||||
|  | ||||
| //not yet | ||||
| bool btConvexHullShape::isInside(const btVector3& ,btScalar ) const | ||||
| { | ||||
| 	btAssert(0); | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| ///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| const char*	btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const | ||||
| { | ||||
| 	//int szc = sizeof(btConvexHullShapeData); | ||||
| 	btConvexHullShapeData* shapeData = (btConvexHullShapeData*) dataBuffer; | ||||
| 	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer); | ||||
|  | ||||
| 	int numElem = m_unscaledPoints.size(); | ||||
| 	shapeData->m_numUnscaledPoints = numElem; | ||||
| #ifdef BT_USE_DOUBLE_PRECISION | ||||
| 	shapeData->m_unscaledPointsFloatPtr = 0; | ||||
| 	shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]):  0; | ||||
| #else | ||||
| 	shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]):  0; | ||||
| 	shapeData->m_unscaledPointsDoublePtr = 0; | ||||
| #endif | ||||
| 	 | ||||
| 	if (numElem) | ||||
| 	{ | ||||
| 		int sz = sizeof(btVector3Data); | ||||
| 	//	int sz2 = sizeof(btVector3DoubleData); | ||||
| 	//	int sz3 = sizeof(btVector3FloatData); | ||||
| 		btChunk* chunk = serializer->allocate(sz,numElem); | ||||
| 		btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr; | ||||
| 		for (int i=0;i<numElem;i++,memPtr++) | ||||
| 		{ | ||||
| 			m_unscaledPoints[i].serialize(*memPtr); | ||||
| 		} | ||||
| 		serializer->finalizeChunk(chunk,btVector3DataName,BT_ARRAY_CODE,(void*)&m_unscaledPoints[0]); | ||||
| 	} | ||||
| 	 | ||||
| 	return "btConvexHullShapeData"; | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										120
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONVEX_HULL_SHAPE_H | ||||
| #define CONVEX_HULL_SHAPE_H | ||||
|  | ||||
| #include "btPolyhedralConvexShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
|  | ||||
| ///The btConvexHullShape implements an implicit convex hull of an array of vertices. | ||||
| ///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex. | ||||
| ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexAabbCachingShape | ||||
| { | ||||
| 	btAlignedObjectArray<btVector3>	m_unscaledPoints; | ||||
|  | ||||
| public: | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	 | ||||
| 	///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. | ||||
| 	///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint. | ||||
| 	///btConvexHullShape make an internal copy of the points. | ||||
| 	btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3)); | ||||
|  | ||||
| 	void addPoint(const btVector3& point); | ||||
|  | ||||
| 	 | ||||
| 	btVector3* getUnscaledPoints() | ||||
| 	{ | ||||
| 		return &m_unscaledPoints[0]; | ||||
| 	} | ||||
|  | ||||
| 	const btVector3* getUnscaledPoints() const | ||||
| 	{ | ||||
| 		return &m_unscaledPoints[0]; | ||||
| 	} | ||||
|  | ||||
| 	///getPoints is obsolete, please use getUnscaledPoints | ||||
| 	const btVector3* getPoints() const | ||||
| 	{ | ||||
| 		return getUnscaledPoints(); | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 	SIMD_FORCE_INLINE	btVector3 getScaledPoint(int i) const | ||||
| 	{ | ||||
| 		return m_unscaledPoints[i] * m_localScaling; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE	int getNumPoints() const  | ||||
| 	{ | ||||
| 		return m_unscaledPoints.size(); | ||||
| 	} | ||||
|  | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const; | ||||
| 	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const; | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 	//debugging | ||||
| 	virtual const char*	getName()const {return "Convex";} | ||||
|  | ||||
| 	 | ||||
| 	virtual int	getNumVertices() const; | ||||
| 	virtual int getNumEdges() const; | ||||
| 	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; | ||||
| 	virtual void getVertex(int i,btVector3& vtx) const; | ||||
| 	virtual int	getNumPlanes() const; | ||||
| 	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; | ||||
| 	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const; | ||||
|  | ||||
| 	///in case we receive negative scaling | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling); | ||||
|  | ||||
| 	virtual	int	calculateSerializeBufferSize() const; | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| 	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const; | ||||
|  | ||||
| }; | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct	btConvexHullShapeData | ||||
| { | ||||
| 	btConvexInternalShapeData	m_convexInternalShapeData; | ||||
|  | ||||
| 	btVector3FloatData	*m_unscaledPointsFloatPtr; | ||||
| 	btVector3DoubleData	*m_unscaledPointsDoublePtr; | ||||
|  | ||||
| 	int		m_numUnscaledPoints; | ||||
| 	char m_padding3[4]; | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| SIMD_FORCE_INLINE	int	btConvexHullShape::calculateSerializeBufferSize() const | ||||
| { | ||||
| 	return sizeof(btConvexHullShapeData); | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif //CONVEX_HULL_SHAPE_H | ||||
|  | ||||
| @@ -0,0 +1,151 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #include "btConvexInternalShape.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| btConvexInternalShape::btConvexInternalShape() | ||||
| : m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), | ||||
| m_collisionMargin(CONVEX_DISTANCE_MARGIN) | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btConvexInternalShape::setLocalScaling(const btVector3& scaling) | ||||
| { | ||||
| 	m_localScaling = scaling.absolute(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const | ||||
| { | ||||
| #ifndef __SPU__ | ||||
| 	//use localGetSupportingVertexWithoutMargin? | ||||
| 	btScalar margin = getMargin(); | ||||
| 	for (int i=0;i<3;i++) | ||||
| 	{ | ||||
| 		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); | ||||
| 		vec[i] = btScalar(1.); | ||||
|  | ||||
| 		btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); | ||||
|  | ||||
| 		btVector3 tmp = trans(sv); | ||||
| 		maxAabb[i] = tmp[i]+margin; | ||||
| 		vec[i] = btScalar(-1.); | ||||
| 		tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); | ||||
| 		minAabb[i] = tmp[i]-margin; | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| btVector3	btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const | ||||
| { | ||||
| #ifndef __SPU__ | ||||
|  | ||||
| 	 btVector3	supVertex = localGetSupportingVertexWithoutMargin(vec); | ||||
|  | ||||
| 	if ( getMargin()!=btScalar(0.) ) | ||||
| 	{ | ||||
| 		btVector3 vecnorm = vec; | ||||
| 		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) | ||||
| 		{ | ||||
| 			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); | ||||
| 		}  | ||||
| 		vecnorm.normalize(); | ||||
| 		supVertex+= getMargin() * vecnorm; | ||||
| 	} | ||||
| 	return supVertex; | ||||
|  | ||||
| #else | ||||
| 	btAssert(0); | ||||
| 	return btVector3(0,0,0); | ||||
| #endif //__SPU__ | ||||
|  | ||||
|  } | ||||
|  | ||||
|  | ||||
| btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape() | ||||
| 	:	btConvexInternalShape(), | ||||
| m_localAabbMin(1,1,1), | ||||
| m_localAabbMax(-1,-1,-1), | ||||
| m_isLocalAabbValid(false) | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const | ||||
| { | ||||
| 	getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin()); | ||||
| } | ||||
|  | ||||
| void	btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling) | ||||
| { | ||||
| 	btConvexInternalShape::setLocalScaling(scaling); | ||||
| 	recalcLocalAabb(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void	btConvexInternalAabbCachingShape::recalcLocalAabb() | ||||
| { | ||||
| 	m_isLocalAabbValid = true; | ||||
| 	 | ||||
| 	#if 1 | ||||
| 	static const btVector3 _directions[] = | ||||
| 	{ | ||||
| 		btVector3( 1.,  0.,  0.), | ||||
| 		btVector3( 0.,  1.,  0.), | ||||
| 		btVector3( 0.,  0.,  1.), | ||||
| 		btVector3( -1., 0.,  0.), | ||||
| 		btVector3( 0., -1.,  0.), | ||||
| 		btVector3( 0.,  0., -1.) | ||||
| 	}; | ||||
| 	 | ||||
| 	btVector3 _supporting[] = | ||||
| 	{ | ||||
| 		btVector3( 0., 0., 0.), | ||||
| 		btVector3( 0., 0., 0.), | ||||
| 		btVector3( 0., 0., 0.), | ||||
| 		btVector3( 0., 0., 0.), | ||||
| 		btVector3( 0., 0., 0.), | ||||
| 		btVector3( 0., 0., 0.) | ||||
| 	}; | ||||
| 	 | ||||
| 	batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); | ||||
| 	 | ||||
| 	for ( int i = 0; i < 3; ++i ) | ||||
| 	{ | ||||
| 		m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin; | ||||
| 		m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin; | ||||
| 	} | ||||
| 	 | ||||
| 	#else | ||||
|  | ||||
| 	for (int i=0;i<3;i++) | ||||
| 	{ | ||||
| 		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); | ||||
| 		vec[i] = btScalar(1.); | ||||
| 		btVector3 tmp = localGetSupportingVertex(vec); | ||||
| 		m_localAabbMax[i] = tmp[i]+m_collisionMargin; | ||||
| 		vec[i] = btScalar(-1.); | ||||
| 		tmp = localGetSupportingVertex(vec); | ||||
| 		m_localAabbMin[i] = tmp[i]-m_collisionMargin; | ||||
| 	} | ||||
| 	#endif | ||||
| } | ||||
| @@ -0,0 +1,202 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BT_CONVEX_INTERNAL_SHAPE_H | ||||
| #define BT_CONVEX_INTERNAL_SHAPE_H | ||||
|  | ||||
| #include "btConvexShape.h" | ||||
| #include "LinearMath/btAabbUtil2.h" | ||||
|  | ||||
|  | ||||
| ///The btConvexInternalShape is an internal base class, shared by most convex shape implementations. | ||||
| class btConvexInternalShape : public btConvexShape | ||||
| { | ||||
|  | ||||
| 	protected: | ||||
|  | ||||
| 	//local scaling. collisionMargin is not scaled ! | ||||
| 	btVector3	m_localScaling; | ||||
|  | ||||
| 	btVector3	m_implicitShapeDimensions; | ||||
| 	 | ||||
| 	btScalar	m_collisionMargin; | ||||
|  | ||||
| 	btScalar	m_padding; | ||||
|  | ||||
| 	btConvexInternalShape(); | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 	virtual ~btConvexInternalShape() | ||||
| 	{ | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const; | ||||
|  | ||||
| 	const btVector3& getImplicitShapeDimensions() const | ||||
| 	{ | ||||
| 		return m_implicitShapeDimensions; | ||||
| 	} | ||||
|  | ||||
| 	///warning: use setImplicitShapeDimensions with care | ||||
| 	///changing a collision shape while the body is in the world is not recommended, | ||||
| 	///it is best to remove the body from the world, then make the change, and re-add it | ||||
| 	///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs' | ||||
| 	void	setImplicitShapeDimensions(const btVector3& dimensions) | ||||
| 	{ | ||||
| 		m_implicitShapeDimensions = dimensions; | ||||
| 	} | ||||
|  | ||||
| 	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version | ||||
| 	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const | ||||
| 	{ | ||||
| 		getAabbSlow(t,aabbMin,aabbMax); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; | ||||
|  | ||||
|  | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling); | ||||
| 	virtual const btVector3& getLocalScaling() const  | ||||
| 	{ | ||||
| 		return m_localScaling; | ||||
| 	} | ||||
|  | ||||
| 	const btVector3& getLocalScalingNV() const  | ||||
| 	{ | ||||
| 		return m_localScaling; | ||||
| 	} | ||||
|  | ||||
| 	virtual void	setMargin(btScalar margin) | ||||
| 	{ | ||||
| 		m_collisionMargin = margin; | ||||
| 	} | ||||
| 	virtual btScalar	getMargin() const | ||||
| 	{ | ||||
| 		return m_collisionMargin; | ||||
| 	} | ||||
|  | ||||
| 	btScalar	getMarginNV() const | ||||
| 	{ | ||||
| 		return m_collisionMargin; | ||||
| 	} | ||||
|  | ||||
| 	virtual int		getNumPreferredPenetrationDirections() const | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| 	 | ||||
| 	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const | ||||
| 	{ | ||||
| 		(void)penetrationVector; | ||||
| 		(void)index; | ||||
| 		btAssert(0); | ||||
| 	} | ||||
|  | ||||
| 	virtual	int	calculateSerializeBufferSize() const; | ||||
|  | ||||
| 	///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| 	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const; | ||||
|  | ||||
| 	 | ||||
| }; | ||||
|  | ||||
| ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 | ||||
| struct	btConvexInternalShapeData | ||||
| { | ||||
| 	btCollisionShapeData	m_collisionShapeData; | ||||
|  | ||||
| 	btVector3FloatData	m_localScaling; | ||||
|  | ||||
| 	btVector3FloatData	m_implicitShapeDimensions; | ||||
| 	 | ||||
| 	float			m_collisionMargin; | ||||
|  | ||||
| 	int	m_padding; | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| SIMD_FORCE_INLINE	int	btConvexInternalShape::calculateSerializeBufferSize() const | ||||
| { | ||||
| 	return sizeof(btConvexInternalShapeData); | ||||
| } | ||||
|  | ||||
| ///fills the dataBuffer and returns the struct name (and 0 on failure) | ||||
| SIMD_FORCE_INLINE	const char*	btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const | ||||
| { | ||||
| 	btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*) dataBuffer; | ||||
| 	btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer); | ||||
|  | ||||
| 	m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions); | ||||
| 	m_localScaling.serializeFloat(shapeData->m_localScaling); | ||||
| 	shapeData->m_collisionMargin = float(m_collisionMargin); | ||||
|  | ||||
| 	return "btConvexInternalShapeData"; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations | ||||
| class btConvexInternalAabbCachingShape : public btConvexInternalShape | ||||
| { | ||||
| 	btVector3	m_localAabbMin; | ||||
| 	btVector3	m_localAabbMax; | ||||
| 	bool		m_isLocalAabbValid; | ||||
| 	 | ||||
| protected: | ||||
| 					 | ||||
| 	btConvexInternalAabbCachingShape(); | ||||
| 	 | ||||
| 	void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax) | ||||
| 	{ | ||||
| 		m_isLocalAabbValid = true; | ||||
| 		m_localAabbMin = aabbMin; | ||||
| 		m_localAabbMax = aabbMax; | ||||
| 	} | ||||
|  | ||||
| 	inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const | ||||
| 	{ | ||||
| 		btAssert(m_isLocalAabbValid); | ||||
| 		aabbMin = m_localAabbMin; | ||||
| 		aabbMax = m_localAabbMax; | ||||
| 	} | ||||
|  | ||||
| 	inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const | ||||
| 	{ | ||||
|  | ||||
| 		//lazy evaluation of local aabb | ||||
| 		btAssert(m_isLocalAabbValid); | ||||
| 		btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); | ||||
| 	} | ||||
| 		 | ||||
| public: | ||||
| 		 | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling); | ||||
|  | ||||
| 	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; | ||||
|  | ||||
| 	void	recalcLocalAabb(); | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif //BT_CONVEX_INTERNAL_SHAPE_H | ||||
| @@ -0,0 +1,157 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btConvexPointCloudShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btCollisionMargin.h" | ||||
|  | ||||
| #include "LinearMath/btQuaternion.h" | ||||
|  | ||||
| void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling) | ||||
| { | ||||
| 	m_localScaling = scaling; | ||||
| 	recalcLocalAabb(); | ||||
| } | ||||
|  | ||||
| #ifndef __SPU__ | ||||
| btVector3	btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const | ||||
| { | ||||
| 	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); | ||||
| 	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT); | ||||
|  | ||||
| 	btVector3 vec = vec0; | ||||
| 	btScalar lenSqr = vec.length2(); | ||||
| 	if (lenSqr < btScalar(0.0001)) | ||||
| 	{ | ||||
| 		vec.setValue(1,0,0); | ||||
| 	} else | ||||
| 	{ | ||||
| 		btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); | ||||
| 		vec *= rlen; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	for (int i=0;i<m_numPoints;i++) | ||||
| 	{ | ||||
| 		btVector3 vtx = getScaledPoint(i); | ||||
|  | ||||
| 		newDot = vec.dot(vtx); | ||||
| 		if (newDot > maxDot) | ||||
| 		{ | ||||
| 			maxDot = newDot; | ||||
| 			supVec = vtx; | ||||
| 		} | ||||
| 	} | ||||
| 	return supVec; | ||||
| } | ||||
|  | ||||
| void	btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||||
| { | ||||
| 	btScalar newDot; | ||||
| 	//use 'w' component of supportVerticesOut? | ||||
| 	{ | ||||
| 		for (int i=0;i<numVectors;i++) | ||||
| 		{ | ||||
| 			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT); | ||||
| 		} | ||||
| 	} | ||||
| 	for (int i=0;i<m_numPoints;i++) | ||||
| 	{ | ||||
| 		btVector3 vtx = getScaledPoint(i); | ||||
|  | ||||
| 		for (int j=0;j<numVectors;j++) | ||||
| 		{ | ||||
| 			const btVector3& vec = vectors[j]; | ||||
| 			 | ||||
| 			newDot = vec.dot(vtx); | ||||
| 			if (newDot > supportVerticesOut[j][3]) | ||||
| 			{ | ||||
| 				//WARNING: don't swap next lines, the w component would get overwritten! | ||||
| 				supportVerticesOut[j] = vtx; | ||||
| 				supportVerticesOut[j][3] = newDot; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| 	 | ||||
|  | ||||
|  | ||||
| btVector3	btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const | ||||
| { | ||||
| 	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); | ||||
|  | ||||
| 	if ( getMargin()!=btScalar(0.) ) | ||||
| 	{ | ||||
| 		btVector3 vecnorm = vec; | ||||
| 		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) | ||||
| 		{ | ||||
| 			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); | ||||
| 		}  | ||||
| 		vecnorm.normalize(); | ||||
| 		supVertex+= getMargin() * vecnorm; | ||||
| 	} | ||||
| 	return supVertex; | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| //currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection | ||||
| //Please note that you can debug-draw btConvexHullShape with the Raytracer Demo | ||||
| int	btConvexPointCloudShape::getNumVertices() const | ||||
| { | ||||
| 	return m_numPoints; | ||||
| } | ||||
|  | ||||
| int btConvexPointCloudShape::getNumEdges() const | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const | ||||
| { | ||||
| 	btAssert (0); | ||||
| } | ||||
|  | ||||
| void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const | ||||
| { | ||||
| 	vtx = m_unscaledPoints[i]*m_localScaling; | ||||
| } | ||||
|  | ||||
| int	btConvexPointCloudShape::getNumPlanes() const | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const | ||||
| { | ||||
|  | ||||
| 	btAssert(0); | ||||
| } | ||||
|  | ||||
| //not yet | ||||
| bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const | ||||
| { | ||||
| 	btAssert(0); | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,105 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BT_CONVEX_POINT_CLOUD_SHAPE_H | ||||
| #define BT_CONVEX_POINT_CLOUD_SHAPE_H | ||||
|  | ||||
| #include "btPolyhedralConvexShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types | ||||
| #include "LinearMath/btAlignedObjectArray.h" | ||||
|  | ||||
| ///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices. | ||||
| ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape | ||||
| { | ||||
| 	btVector3* m_unscaledPoints; | ||||
| 	int m_numPoints; | ||||
|  | ||||
| public: | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	btConvexPointCloudShape() | ||||
| 	{ | ||||
| 		m_localScaling.setValue(1.f,1.f,1.f); | ||||
| 		m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE; | ||||
| 		m_unscaledPoints = 0; | ||||
| 		m_numPoints = 0; | ||||
| 	} | ||||
|  | ||||
| 	btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true) | ||||
| 	{ | ||||
| 		m_localScaling = localScaling; | ||||
| 		m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE; | ||||
| 		m_unscaledPoints = points; | ||||
| 		m_numPoints = numPoints; | ||||
|  | ||||
| 		if (computeAabb) | ||||
| 			recalcLocalAabb(); | ||||
| 	} | ||||
|  | ||||
| 	void setPoints (btVector3* points, int numPoints, bool computeAabb = true,const btVector3& localScaling=btVector3(1.f,1.f,1.f)) | ||||
| 	{ | ||||
| 		m_unscaledPoints = points; | ||||
| 		m_numPoints = numPoints; | ||||
| 		m_localScaling = localScaling; | ||||
|  | ||||
| 		if (computeAabb) | ||||
| 			recalcLocalAabb(); | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE	btVector3* getUnscaledPoints() | ||||
| 	{ | ||||
| 		return m_unscaledPoints; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE	const btVector3* getUnscaledPoints() const | ||||
| 	{ | ||||
| 		return m_unscaledPoints; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE	int getNumPoints() const  | ||||
| 	{ | ||||
| 		return m_numPoints; | ||||
| 	} | ||||
|  | ||||
| 	SIMD_FORCE_INLINE	btVector3	getScaledPoint( int index) const | ||||
| 	{ | ||||
| 		return m_unscaledPoints[index] * m_localScaling; | ||||
| 	} | ||||
|  | ||||
| #ifndef __SPU__ | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const; | ||||
| 	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const; | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| 	//debugging | ||||
| 	virtual const char*	getName()const {return "ConvexPointCloud";} | ||||
|  | ||||
| 	virtual int	getNumVertices() const; | ||||
| 	virtual int getNumEdges() const; | ||||
| 	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; | ||||
| 	virtual void getVertex(int i,btVector3& vtx) const; | ||||
| 	virtual int	getNumPlanes() const; | ||||
| 	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; | ||||
| 	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const; | ||||
|  | ||||
| 	///in case we receive negative scaling | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling); | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif //BT_CONVEX_POINT_CLOUD_SHAPE_H | ||||
|  | ||||
							
								
								
									
										429
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,429 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btConvexShape.h" | ||||
| #include "btTriangleShape.h" | ||||
| #include "btSphereShape.h" | ||||
| #include "btCylinderShape.h" | ||||
| #include "btCapsuleShape.h" | ||||
| #include "btConvexHullShape.h" | ||||
| #include "btConvexPointCloudShape.h" | ||||
|  | ||||
| ///not supported on IBM SDK, until we fix the alignment of btVector3 | ||||
| #if defined (__CELLOS_LV2__) && defined (__SPU__) | ||||
| #include <spu_intrinsics.h> | ||||
| static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 ) | ||||
| { | ||||
|     vec_float4 result; | ||||
|     result = spu_mul( vec0, vec1 ); | ||||
|     result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); | ||||
|     return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result ); | ||||
| } | ||||
| #endif //__SPU__ | ||||
|  | ||||
| btConvexShape::btConvexShape () | ||||
| { | ||||
| } | ||||
|  | ||||
| btConvexShape::~btConvexShape() | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling) | ||||
| {	 | ||||
|  | ||||
| 	btVector3 vec = localDirOrg * localScaling; | ||||
|  | ||||
| #if defined (__CELLOS_LV2__) && defined (__SPU__) | ||||
|  | ||||
| 	btVector3 localDir = vec; | ||||
|  | ||||
| 	vec_float4 v_distMax = {-FLT_MAX,0,0,0}; | ||||
| 	vec_int4 v_idxMax = {-999,0,0,0}; | ||||
| 	int v=0; | ||||
| 	int numverts = numPoints; | ||||
|  | ||||
| 	for(;v<(int)numverts-4;v+=4) { | ||||
| 		vec_float4 p0 = vec_dot3(points[v  ].get128(),localDir.get128()); | ||||
| 		vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128()); | ||||
| 		vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128()); | ||||
| 		vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128()); | ||||
| 		const vec_int4 i0 = {v  ,0,0,0}; | ||||
| 		const vec_int4 i1 = {v+1,0,0,0}; | ||||
| 		const vec_int4 i2 = {v+2,0,0,0}; | ||||
| 		const vec_int4 i3 = {v+3,0,0,0}; | ||||
| 		vec_uint4  retGt01 = spu_cmpgt(p0,p1); | ||||
| 		vec_float4 pmax01 = spu_sel(p1,p0,retGt01); | ||||
| 		vec_int4   imax01 = spu_sel(i1,i0,retGt01); | ||||
| 		vec_uint4  retGt23 = spu_cmpgt(p2,p3); | ||||
| 		vec_float4 pmax23 = spu_sel(p3,p2,retGt23); | ||||
| 		vec_int4   imax23 = spu_sel(i3,i2,retGt23); | ||||
| 		vec_uint4  retGt0123 = spu_cmpgt(pmax01,pmax23); | ||||
| 		vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123); | ||||
| 		vec_int4   imax0123 = spu_sel(imax23,imax01,retGt0123); | ||||
| 		vec_uint4  retGtMax = spu_cmpgt(v_distMax,pmax0123); | ||||
| 		v_distMax = spu_sel(pmax0123,v_distMax,retGtMax); | ||||
| 		v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax); | ||||
| 	} | ||||
| 	for(;v<(int)numverts;v++) { | ||||
| 		vec_float4 p = vec_dot3(points[v].get128(),localDir.get128()); | ||||
| 		const vec_int4 i = {v,0,0,0}; | ||||
| 		vec_uint4  retGtMax = spu_cmpgt(v_distMax,p); | ||||
| 		v_distMax = spu_sel(p,v_distMax,retGtMax); | ||||
| 		v_idxMax = spu_sel(i,v_idxMax,retGtMax); | ||||
| 	} | ||||
| 	int ptIndex = spu_extract(v_idxMax,0); | ||||
| 	const btVector3& supVec= points[ptIndex] * localScaling; | ||||
| 	return supVec; | ||||
| #else | ||||
|  | ||||
| 	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT); | ||||
| 	int ptIndex = -1; | ||||
|  | ||||
| 	for (int i=0;i<numPoints;i++) | ||||
| 	{ | ||||
|  | ||||
| 		newDot = vec.dot(points[i]); | ||||
| 		if (newDot > maxDot) | ||||
| 		{ | ||||
| 			maxDot = newDot; | ||||
| 			ptIndex = i; | ||||
| 		} | ||||
| 	} | ||||
| 	btAssert(ptIndex >= 0); | ||||
| 	btVector3 supVec = points[ptIndex] * localScaling; | ||||
| 	return supVec; | ||||
| #endif //__SPU__ | ||||
| } | ||||
|  | ||||
| btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const | ||||
| { | ||||
| 	switch (m_shapeType) | ||||
| 	{ | ||||
|     case SPHERE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		return btVector3(0,0,0); | ||||
|     } | ||||
| 	case BOX_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btBoxShape* convexShape = (btBoxShape*)this; | ||||
| 		const btVector3& halfExtents = convexShape->getImplicitShapeDimensions(); | ||||
|  | ||||
| 		return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()), | ||||
| 			btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()), | ||||
| 			btFsels(localDir.z(), halfExtents.z(), -halfExtents.z())); | ||||
| 	} | ||||
| 	case TRIANGLE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btTriangleShape* triangleShape = (btTriangleShape*)this; | ||||
| 		btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ()); | ||||
| 		btVector3* vertices = &triangleShape->m_vertices1[0]; | ||||
| 		btVector3 dots(dir.dot(vertices[0]), dir.dot(vertices[1]), dir.dot(vertices[2])); | ||||
| 		btVector3 sup = vertices[dots.maxAxis()]; | ||||
| 		return btVector3(sup.getX(),sup.getY(),sup.getZ()); | ||||
| 	} | ||||
| 	case CYLINDER_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btCylinderShape* cylShape = (btCylinderShape*)this; | ||||
| 		//mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis) | ||||
|  | ||||
| 		btVector3 halfExtents = cylShape->getImplicitShapeDimensions(); | ||||
| 		btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ()); | ||||
| 		int cylinderUpAxis = cylShape->getUpAxis(); | ||||
| 		int XX(1),YY(0),ZZ(2); | ||||
|  | ||||
| 		switch (cylinderUpAxis) | ||||
| 		{ | ||||
| 		case 0: | ||||
| 		{ | ||||
| 			XX = 1; | ||||
| 			YY = 0; | ||||
| 			ZZ = 2; | ||||
| 		} | ||||
| 		break; | ||||
| 		case 1: | ||||
| 		{ | ||||
| 			XX = 0; | ||||
| 			YY = 1; | ||||
| 			ZZ = 2;	 | ||||
| 		} | ||||
| 		break; | ||||
| 		case 2: | ||||
| 		{ | ||||
| 			XX = 0; | ||||
| 			YY = 2; | ||||
| 			ZZ = 1; | ||||
| 			 | ||||
| 		} | ||||
| 		break; | ||||
| 		default: | ||||
| 			btAssert(0); | ||||
| 		break; | ||||
| 		}; | ||||
|  | ||||
| 		btScalar radius = halfExtents[XX]; | ||||
| 		btScalar halfHeight = halfExtents[cylinderUpAxis]; | ||||
|  | ||||
| 		btVector3 tmp; | ||||
| 		btScalar d ; | ||||
|  | ||||
| 		btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); | ||||
| 		if (s != btScalar(0.0)) | ||||
| 		{ | ||||
| 			d = radius / s;   | ||||
| 			tmp[XX] = v[XX] * d; | ||||
| 			tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; | ||||
| 			tmp[ZZ] = v[ZZ] * d; | ||||
| 			return btVector3(tmp.getX(),tmp.getY(),tmp.getZ()); | ||||
| 		} else { | ||||
| 			tmp[XX] = radius; | ||||
| 			tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; | ||||
| 			tmp[ZZ] = btScalar(0.0); | ||||
| 			return btVector3(tmp.getX(),tmp.getY(),tmp.getZ()); | ||||
| 		} | ||||
| 	} | ||||
| 	case CAPSULE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ()); | ||||
|  | ||||
| 		btCapsuleShape* capsuleShape = (btCapsuleShape*)this; | ||||
| 		btScalar halfHeight = capsuleShape->getHalfHeight(); | ||||
| 		int capsuleUpAxis = capsuleShape->getUpAxis(); | ||||
|  | ||||
| 		btScalar radius = capsuleShape->getRadius(); | ||||
| 		btVector3 supVec(0,0,0); | ||||
|  | ||||
| 		btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); | ||||
|  | ||||
| 		btVector3 vec = vec0; | ||||
| 		btScalar lenSqr = vec.length2(); | ||||
| 		if (lenSqr < btScalar(0.0001)) | ||||
| 		{ | ||||
| 			vec.setValue(1,0,0); | ||||
| 		} else | ||||
| 		{ | ||||
| 			btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); | ||||
| 			vec *= rlen; | ||||
| 		} | ||||
| 		btVector3 vtx; | ||||
| 		btScalar newDot; | ||||
| 		{ | ||||
| 			btVector3 pos(0,0,0); | ||||
| 			pos[capsuleUpAxis] = halfHeight; | ||||
|  | ||||
| 			//vtx = pos +vec*(radius); | ||||
| 			vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV(); | ||||
| 			newDot = vec.dot(vtx); | ||||
| 			 | ||||
|  | ||||
| 			if (newDot > maxDot) | ||||
| 			{ | ||||
| 				maxDot = newDot; | ||||
| 				supVec = vtx; | ||||
| 			} | ||||
| 		} | ||||
| 		{ | ||||
| 			btVector3 pos(0,0,0); | ||||
| 			pos[capsuleUpAxis] = -halfHeight; | ||||
|  | ||||
| 			//vtx = pos +vec*(radius); | ||||
| 			vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV(); | ||||
| 			newDot = vec.dot(vtx); | ||||
| 			if (newDot > maxDot) | ||||
| 			{ | ||||
| 				maxDot = newDot; | ||||
| 				supVec = vtx; | ||||
| 			} | ||||
| 		} | ||||
| 		return btVector3(supVec.getX(),supVec.getY(),supVec.getZ());	 | ||||
| 	} | ||||
| 	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this; | ||||
| 		btVector3* points = convexPointCloudShape->getUnscaledPoints (); | ||||
| 		int numPoints = convexPointCloudShape->getNumPoints (); | ||||
| 		return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV()); | ||||
| 	} | ||||
| 	case CONVEX_HULL_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btConvexHullShape* convexHullShape = (btConvexHullShape*)this; | ||||
| 		btVector3* points = convexHullShape->getUnscaledPoints(); | ||||
| 		int numPoints = convexHullShape->getNumPoints (); | ||||
| 		return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV()); | ||||
| 	} | ||||
|     default: | ||||
| #ifndef __SPU__ | ||||
| 		return this->localGetSupportingVertexWithoutMargin (localDir); | ||||
| #else | ||||
| 		btAssert (0); | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
| 	// should never reach here | ||||
| 	btAssert (0); | ||||
| 	return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f)); | ||||
| } | ||||
|  | ||||
| btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const | ||||
| { | ||||
| 	btVector3 localDirNorm = localDir; | ||||
| 	if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) | ||||
| 	{ | ||||
| 		localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); | ||||
| 	} | ||||
| 	localDirNorm.normalize (); | ||||
|  | ||||
| 	return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm; | ||||
| } | ||||
|  | ||||
| /* TODO: This should be bumped up to btCollisionShape () */ | ||||
| btScalar btConvexShape::getMarginNonVirtual () const | ||||
| { | ||||
| 	switch (m_shapeType) | ||||
| 	{ | ||||
|     case SPHERE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btSphereShape* sphereShape = (btSphereShape*)this; | ||||
| 		return sphereShape->getRadius (); | ||||
| 	} | ||||
| 	case BOX_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btBoxShape* convexShape = (btBoxShape*)this; | ||||
| 		return convexShape->getMarginNV (); | ||||
| 	} | ||||
| 	case TRIANGLE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btTriangleShape* triangleShape = (btTriangleShape*)this; | ||||
| 		return triangleShape->getMarginNV (); | ||||
| 	} | ||||
| 	case CYLINDER_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btCylinderShape* cylShape = (btCylinderShape*)this; | ||||
| 		return cylShape->getMarginNV(); | ||||
| 	} | ||||
| 	case CAPSULE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btCapsuleShape* capsuleShape = (btCapsuleShape*)this; | ||||
| 		return capsuleShape->getMarginNV(); | ||||
| 	} | ||||
| 	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: | ||||
| 	/* fall through */ | ||||
| 	case CONVEX_HULL_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this; | ||||
| 		return convexHullShape->getMarginNV(); | ||||
| 	} | ||||
|     default: | ||||
| #ifndef __SPU__ | ||||
| 		return this->getMargin (); | ||||
| #else | ||||
| 		btAssert (0); | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
| 	// should never reach here | ||||
| 	btAssert (0); | ||||
| 	return btScalar(0.0f); | ||||
| } | ||||
| #ifndef __SPU__ | ||||
| void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const | ||||
| { | ||||
| 	switch (m_shapeType) | ||||
| 	{ | ||||
|     case SPHERE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btSphereShape* sphereShape = (btSphereShape*)this; | ||||
| 		btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX(); | ||||
| 		btScalar margin = radius + sphereShape->getMarginNonVirtual(); | ||||
| 		const btVector3& center = t.getOrigin(); | ||||
| 		btVector3 extent(margin,margin,margin); | ||||
| 		aabbMin = center - extent; | ||||
| 		aabbMax = center + extent; | ||||
|     } | ||||
| 	break; | ||||
| 	case CYLINDER_SHAPE_PROXYTYPE: | ||||
| 	/* fall through */ | ||||
| 	case BOX_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btBoxShape* convexShape = (btBoxShape*)this; | ||||
| 		btScalar margin=convexShape->getMarginNonVirtual(); | ||||
| 		btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); | ||||
| 		halfExtents += btVector3(margin,margin,margin); | ||||
| 		btMatrix3x3 abs_b = t.getBasis().absolute();   | ||||
| 		btVector3 center = t.getOrigin(); | ||||
| 		btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); | ||||
| 		 | ||||
| 		aabbMin = center - extent; | ||||
| 		aabbMax = center + extent; | ||||
| 		break; | ||||
| 	} | ||||
| 	case TRIANGLE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btTriangleShape* triangleShape = (btTriangleShape*)this; | ||||
| 		btScalar margin = triangleShape->getMarginNonVirtual(); | ||||
| 		for (int i=0;i<3;i++) | ||||
| 		{ | ||||
| 			btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); | ||||
| 			vec[i] = btScalar(1.); | ||||
|  | ||||
| 			btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()); | ||||
|  | ||||
| 			btVector3 tmp = t(sv); | ||||
| 			aabbMax[i] = tmp[i]+margin; | ||||
| 			vec[i] = btScalar(-1.); | ||||
| 			tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis())); | ||||
| 			aabbMin[i] = tmp[i]-margin; | ||||
| 		}	 | ||||
| 	} | ||||
| 	break; | ||||
| 	case CAPSULE_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btCapsuleShape* capsuleShape = (btCapsuleShape*)this; | ||||
| 		btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius()); | ||||
| 		int m_upAxis = capsuleShape->getUpAxis(); | ||||
| 		halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight(); | ||||
| 		halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual()); | ||||
| 		btMatrix3x3 abs_b = t.getBasis().absolute();   | ||||
| 		btVector3 center = t.getOrigin(); | ||||
| 		btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));		  	 | ||||
| 		aabbMin = center - extent; | ||||
| 		aabbMax = center + extent; | ||||
| 	} | ||||
| 	break; | ||||
| 	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: | ||||
| 	case CONVEX_HULL_SHAPE_PROXYTYPE: | ||||
| 	{ | ||||
| 		btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this; | ||||
| 		btScalar margin = convexHullShape->getMarginNonVirtual(); | ||||
| 		convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin); | ||||
| 	} | ||||
| 	break; | ||||
|     default: | ||||
| #ifndef __SPU__ | ||||
| 		this->getAabb (t, aabbMin, aabbMax); | ||||
| #else | ||||
| 		btAssert (0); | ||||
| #endif | ||||
| 	break; | ||||
| 	} | ||||
|  | ||||
| 	// should never reach here | ||||
| 	btAssert (0); | ||||
| } | ||||
|  | ||||
| #endif //__SPU__ | ||||
							
								
								
									
										82
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConvexShape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								libs/bullet/BulletCollision/CollisionShapes/btConvexShape.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONVEX_SHAPE_INTERFACE1 | ||||
| #define CONVEX_SHAPE_INTERFACE1 | ||||
|  | ||||
| #include "btCollisionShape.h" | ||||
|  | ||||
| #include "LinearMath/btVector3.h" | ||||
| #include "LinearMath/btTransform.h" | ||||
| #include "LinearMath/btMatrix3x3.h" | ||||
| #include "btCollisionMargin.h" | ||||
| #include "LinearMath/btAlignedAllocator.h" | ||||
|  | ||||
| #define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 | ||||
|  | ||||
| /// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc. | ||||
| /// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector. | ||||
| ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape | ||||
| { | ||||
|  | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||||
|  | ||||
| 	btConvexShape (); | ||||
|  | ||||
| 	virtual ~btConvexShape(); | ||||
|  | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const = 0; | ||||
|  | ||||
| 	//////// | ||||
| 	#ifndef __SPU__ | ||||
| 	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec) const=0; | ||||
| 	#endif //#ifndef __SPU__ | ||||
|  | ||||
| 	btVector3 localGetSupportVertexWithoutMarginNonVirtual (const btVector3& vec) const; | ||||
| 	btVector3 localGetSupportVertexNonVirtual (const btVector3& vec) const; | ||||
| 	btScalar getMarginNonVirtual () const; | ||||
| 	void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const; | ||||
|  | ||||
| 	 | ||||
| 	//notice that the vectors should be unit length | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; | ||||
|  | ||||
| 	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version | ||||
| 	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; | ||||
|  | ||||
| 	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; | ||||
|  | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling) =0; | ||||
| 	virtual const btVector3& getLocalScaling() const =0; | ||||
|  | ||||
| 	virtual void	setMargin(btScalar margin)=0; | ||||
|  | ||||
| 	virtual btScalar	getMargin() const=0; | ||||
|  | ||||
| 	virtual int		getNumPreferredPenetrationDirections() const=0; | ||||
| 	 | ||||
| 	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; | ||||
|  | ||||
|  | ||||
| 	 | ||||
| 	 | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //CONVEX_SHAPE_INTERFACE1 | ||||
| @@ -0,0 +1,315 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "btConvexTriangleMeshShape.h" | ||||
| #include "BulletCollision/CollisionShapes/btCollisionMargin.h" | ||||
|  | ||||
| #include "LinearMath/btQuaternion.h" | ||||
| #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" | ||||
|  | ||||
|  | ||||
| btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb) | ||||
| : btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface) | ||||
| { | ||||
| 	m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; | ||||
| 	if ( calcAabb ) | ||||
| 		recalcLocalAabb(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once | ||||
| ///but then we are duplicating | ||||
| class LocalSupportVertexCallback: public btInternalTriangleIndexCallback | ||||
| { | ||||
|  | ||||
| 	btVector3 m_supportVertexLocal; | ||||
| public: | ||||
|  | ||||
| 	btScalar m_maxDot; | ||||
| 	btVector3 m_supportVecLocal; | ||||
|  | ||||
| 	LocalSupportVertexCallback(const btVector3& supportVecLocal) | ||||
| 		: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), | ||||
| 		m_maxDot(btScalar(-BT_LARGE_FLOAT)), | ||||
|                 m_supportVecLocal(supportVecLocal) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex) | ||||
| 	{ | ||||
| 		(void)triangleIndex; | ||||
| 		(void)partId; | ||||
|  | ||||
| 		for (int i=0;i<3;i++) | ||||
| 		{ | ||||
| 			btScalar dot = m_supportVecLocal.dot(triangle[i]); | ||||
| 			if (dot > m_maxDot) | ||||
| 			{ | ||||
| 				m_maxDot = dot; | ||||
| 				m_supportVertexLocal = triangle[i]; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	btVector3	GetSupportVertexLocal() | ||||
| 	{ | ||||
| 		return m_supportVertexLocal; | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| btVector3	btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const | ||||
| { | ||||
| 	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); | ||||
|  | ||||
| 	btVector3 vec = vec0; | ||||
| 	btScalar lenSqr = vec.length2(); | ||||
| 	if (lenSqr < btScalar(0.0001)) | ||||
| 	{ | ||||
| 		vec.setValue(1,0,0); | ||||
| 	} else | ||||
| 	{ | ||||
| 		btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); | ||||
| 		vec *= rlen; | ||||
| 	} | ||||
|  | ||||
| 	LocalSupportVertexCallback	supportCallback(vec); | ||||
| 	btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | ||||
| 	m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); | ||||
| 	supVec = supportCallback.GetSupportVertexLocal(); | ||||
|  | ||||
| 	return supVec; | ||||
| } | ||||
|  | ||||
| void	btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||||
| { | ||||
| 	//use 'w' component of supportVerticesOut? | ||||
| 	{ | ||||
| 		for (int i=0;i<numVectors;i++) | ||||
| 		{ | ||||
| 			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	///@todo: could do the batch inside the callback! | ||||
|  | ||||
|  | ||||
| 	for (int j=0;j<numVectors;j++) | ||||
| 	{ | ||||
| 		const btVector3& vec = vectors[j]; | ||||
| 		LocalSupportVertexCallback	supportCallback(vec); | ||||
| 		btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | ||||
| 		m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); | ||||
| 		supportVerticesOut[j] = supportCallback.GetSupportVertexLocal(); | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
| 	 | ||||
|  | ||||
|  | ||||
| btVector3	btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const | ||||
| { | ||||
| 	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); | ||||
|  | ||||
| 	if ( getMargin()!=btScalar(0.) ) | ||||
| 	{ | ||||
| 		btVector3 vecnorm = vec; | ||||
| 		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) | ||||
| 		{ | ||||
| 			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); | ||||
| 		}  | ||||
| 		vecnorm.normalize(); | ||||
| 		supVertex+= getMargin() * vecnorm; | ||||
| 	} | ||||
| 	return supVertex; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| //currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection | ||||
| //Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo | ||||
| int	btConvexTriangleMeshShape::getNumVertices() const | ||||
| { | ||||
| 	//cache this? | ||||
| 	return 0; | ||||
| 	 | ||||
| } | ||||
|  | ||||
| int btConvexTriangleMeshShape::getNumEdges() const | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const | ||||
| { | ||||
| 	btAssert(0);	 | ||||
| } | ||||
|  | ||||
| void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const | ||||
| { | ||||
| 	btAssert(0); | ||||
| } | ||||
|  | ||||
| int	btConvexTriangleMeshShape::getNumPlanes() const | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int  ) const | ||||
| { | ||||
| 	btAssert(0); | ||||
| } | ||||
|  | ||||
| //not yet | ||||
| bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const | ||||
| { | ||||
| 	btAssert(0); | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void	btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling) | ||||
| { | ||||
| 	m_stridingMesh->setScaling(scaling); | ||||
| 	 | ||||
| 	recalcLocalAabb(); | ||||
| 	 | ||||
| } | ||||
|  | ||||
|  | ||||
| const btVector3& btConvexTriangleMeshShape::getLocalScaling() const | ||||
| { | ||||
| 	return m_stridingMesh->getScaling(); | ||||
| } | ||||
|  | ||||
| void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const | ||||
| { | ||||
|    class CenterCallback: public btInternalTriangleIndexCallback | ||||
|    { | ||||
|       bool first; | ||||
|       btVector3 ref; | ||||
|       btVector3 sum; | ||||
|       btScalar volume; | ||||
|  | ||||
|    public: | ||||
|  | ||||
|       CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0) | ||||
|       { | ||||
|       } | ||||
|  | ||||
|       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) | ||||
|       { | ||||
|          (void) triangleIndex; | ||||
|          (void) partId; | ||||
|          if (first) | ||||
|          { | ||||
|             ref = triangle[0]; | ||||
|             first = false; | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref)); | ||||
|             sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref)); | ||||
|             volume += vol; | ||||
|          } | ||||
|       } | ||||
|        | ||||
|       btVector3 getCenter() | ||||
|       { | ||||
|          return (volume > 0) ? sum / volume : ref; | ||||
|       } | ||||
|  | ||||
|       btScalar getVolume() | ||||
|       { | ||||
|          return volume * btScalar(1. / 6); | ||||
|       } | ||||
|  | ||||
|    }; | ||||
|  | ||||
|    class InertiaCallback: public btInternalTriangleIndexCallback | ||||
|    { | ||||
|       btMatrix3x3 sum; | ||||
|       btVector3 center; | ||||
|  | ||||
|    public: | ||||
|  | ||||
|       InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center) | ||||
|       { | ||||
|       } | ||||
|  | ||||
|       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) | ||||
|       { | ||||
|          (void) triangleIndex; | ||||
|          (void) partId; | ||||
|          btMatrix3x3 i; | ||||
|          btVector3 a = triangle[0] - center; | ||||
|          btVector3 b = triangle[1] - center; | ||||
|          btVector3 c = triangle[2] - center; | ||||
|          btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6); | ||||
|          for (int j = 0; j < 3; j++) | ||||
|          { | ||||
|             for (int k = 0; k <= j; k++) | ||||
|             { | ||||
|                i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) | ||||
|                   + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j])); | ||||
|             } | ||||
|          } | ||||
|          btScalar i00 = -i[0][0]; | ||||
|          btScalar i11 = -i[1][1]; | ||||
|          btScalar i22 = -i[2][2]; | ||||
|          i[0][0] = i11 + i22;  | ||||
|          i[1][1] = i22 + i00;  | ||||
|          i[2][2] = i00 + i11; | ||||
|          sum[0] += i[0]; | ||||
|          sum[1] += i[1]; | ||||
|          sum[2] += i[2]; | ||||
|       } | ||||
|        | ||||
|       btMatrix3x3& getInertia() | ||||
|       { | ||||
|          return sum; | ||||
|       } | ||||
|  | ||||
|    }; | ||||
|  | ||||
|    CenterCallback centerCallback; | ||||
|    btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | ||||
|    m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax); | ||||
|    btVector3 center = centerCallback.getCenter(); | ||||
|    principal.setOrigin(center); | ||||
|    volume = centerCallback.getVolume(); | ||||
|  | ||||
|    InertiaCallback inertiaCallback(center); | ||||
|    m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax); | ||||
|  | ||||
|    btMatrix3x3& i = inertiaCallback.getInertia(); | ||||
|    i.diagonalize(principal.getBasis(), btScalar(0.00001), 20); | ||||
|    inertia.setValue(i[0][0], i[1][1], i[2][2]); | ||||
|    inertia /= volume; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,75 @@ | ||||
| /* | ||||
| Bullet Continuous Collision Detection and Physics Library | ||||
| Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied warranty. | ||||
| In no event will the authors be held liable for any damages arising from the use of this software. | ||||
| Permission is granted to anyone to use this software for any purpose,  | ||||
| including commercial applications, and to alter it and redistribute it freely,  | ||||
| subject to the following restrictions: | ||||
|  | ||||
| 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
| #ifndef CONVEX_TRIANGLEMESH_SHAPE_H | ||||
| #define CONVEX_TRIANGLEMESH_SHAPE_H | ||||
|  | ||||
|  | ||||
| #include "btPolyhedralConvexShape.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types | ||||
|  | ||||
|  | ||||
| /// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape. | ||||
| /// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead. | ||||
| class btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape | ||||
| { | ||||
|  | ||||
| 	class btStridingMeshInterface*	m_stridingMesh; | ||||
|  | ||||
| public: | ||||
| 	btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true); | ||||
|  | ||||
| 	class btStridingMeshInterface*	getMeshInterface() | ||||
| 	{ | ||||
| 		return m_stridingMesh; | ||||
| 	} | ||||
| 	const class btStridingMeshInterface* getMeshInterface() const | ||||
| 	{ | ||||
| 		return m_stridingMesh; | ||||
| 	} | ||||
| 	 | ||||
| 	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const; | ||||
| 	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const; | ||||
| 	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; | ||||
| 	 | ||||
| 	//debugging | ||||
| 	virtual const char*	getName()const {return "ConvexTrimesh";} | ||||
| 	 | ||||
| 	virtual int	getNumVertices() const; | ||||
| 	virtual int getNumEdges() const; | ||||
| 	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; | ||||
| 	virtual void getVertex(int i,btVector3& vtx) const; | ||||
| 	virtual int	getNumPlanes() const; | ||||
| 	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; | ||||
| 	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const; | ||||
|  | ||||
| 	 | ||||
| 	virtual void	setLocalScaling(const btVector3& scaling); | ||||
| 	virtual const btVector3& getLocalScaling() const; | ||||
|  | ||||
| 	///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia | ||||
| 	///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia" | ||||
| 	///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the | ||||
| 	///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform | ||||
| 	///of the collision object by the principal transform. This method also computes the volume of the convex mesh. | ||||
| 	void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const; | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif //CONVEX_TRIANGLEMESH_SHAPE_H | ||||
|  | ||||
|  | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 gmueller
					gmueller