1 #include "Bullet2CollisionSdk.h"
2 #include "btBulletCollisionCommon.h"
3 
4 struct Bullet2CollisionSdkInternalData
5 {
6 	btCollisionConfiguration* m_collisionConfig;
7 	btCollisionDispatcher* m_dispatcher;
8 	btBroadphaseInterface* m_aabbBroadphase;
9 	btCollisionWorld* m_collisionWorld;
10 
Bullet2CollisionSdkInternalDataBullet2CollisionSdkInternalData11 	Bullet2CollisionSdkInternalData()
12 		: m_collisionConfig(0),
13 		  m_dispatcher(0),
14 		  m_aabbBroadphase(0),
15 		  m_collisionWorld(0)
16 	{
17 	}
18 };
19 
Bullet2CollisionSdk()20 Bullet2CollisionSdk::Bullet2CollisionSdk()
21 {
22 	m_internalData = new Bullet2CollisionSdkInternalData;
23 }
24 
~Bullet2CollisionSdk()25 Bullet2CollisionSdk::~Bullet2CollisionSdk()
26 {
27 	delete m_internalData;
28 	m_internalData = 0;
29 }
30 
createCollisionWorld(int,int,int)31 plCollisionWorldHandle Bullet2CollisionSdk::createCollisionWorld(int /*maxNumObjsCapacity*/, int /*maxNumShapesCapacity*/, int /*maxNumPairsCapacity*/)
32 {
33 	m_internalData->m_collisionConfig = new btDefaultCollisionConfiguration;
34 
35 	m_internalData->m_dispatcher = new btCollisionDispatcher(m_internalData->m_collisionConfig);
36 	m_internalData->m_aabbBroadphase = new btDbvtBroadphase();
37 	m_internalData->m_collisionWorld = new btCollisionWorld(m_internalData->m_dispatcher,
38 															m_internalData->m_aabbBroadphase,
39 															m_internalData->m_collisionConfig);
40 	return (plCollisionWorldHandle)m_internalData->m_collisionWorld;
41 }
42 
deleteCollisionWorld(plCollisionWorldHandle worldHandle)43 void Bullet2CollisionSdk::deleteCollisionWorld(plCollisionWorldHandle worldHandle)
44 {
45 	btCollisionWorld* world = (btCollisionWorld*)worldHandle;
46 	btAssert(m_internalData->m_collisionWorld == world);
47 
48 	if (m_internalData->m_collisionWorld == world)
49 	{
50 		delete m_internalData->m_collisionWorld;
51 		m_internalData->m_collisionWorld = 0;
52 		delete m_internalData->m_aabbBroadphase;
53 		m_internalData->m_aabbBroadphase = 0;
54 		delete m_internalData->m_dispatcher;
55 		m_internalData->m_dispatcher = 0;
56 		delete m_internalData->m_collisionConfig;
57 		m_internalData->m_collisionConfig = 0;
58 	}
59 }
60 
createSphereShape(plCollisionWorldHandle,plReal radius)61 plCollisionShapeHandle Bullet2CollisionSdk::createSphereShape(plCollisionWorldHandle /*worldHandle*/, plReal radius)
62 {
63 	btSphereShape* sphereShape = new btSphereShape(radius);
64 	return (plCollisionShapeHandle)sphereShape;
65 }
66 
createPlaneShape(plCollisionWorldHandle worldHandle,plReal planeNormalX,plReal planeNormalY,plReal planeNormalZ,plReal planeConstant)67 plCollisionShapeHandle Bullet2CollisionSdk::createPlaneShape(plCollisionWorldHandle worldHandle,
68 															 plReal planeNormalX,
69 															 plReal planeNormalY,
70 															 plReal planeNormalZ,
71 															 plReal planeConstant)
72 {
73 	btStaticPlaneShape* planeShape = new btStaticPlaneShape(btVector3(planeNormalX, planeNormalY, planeNormalZ), planeConstant);
74 	return (plCollisionShapeHandle)planeShape;
75 }
76 
createCapsuleShape(plCollisionWorldHandle worldHandle,plReal radius,plReal height,int capsuleAxis)77 plCollisionShapeHandle Bullet2CollisionSdk::createCapsuleShape(plCollisionWorldHandle worldHandle,
78 															   plReal radius,
79 															   plReal height,
80 															   int capsuleAxis)
81 {
82 	btCapsuleShape* capsule = 0;
83 
84 	switch (capsuleAxis)
85 	{
86 		case 0:
87 		{
88 			capsule = new btCapsuleShapeX(radius, height);
89 			break;
90 		}
91 		case 1:
92 		{
93 			capsule = new btCapsuleShape(radius, height);
94 			break;
95 		}
96 		case 2:
97 		{
98 			capsule = new btCapsuleShapeZ(radius, height);
99 			break;
100 		}
101 		default:
102 		{
103 			btAssert(0);
104 		}
105 	}
106 	return (plCollisionShapeHandle)capsule;
107 }
108 
createCompoundShape(plCollisionWorldHandle worldHandle)109 plCollisionShapeHandle Bullet2CollisionSdk::createCompoundShape(plCollisionWorldHandle worldHandle)
110 {
111 	return (plCollisionShapeHandle) new btCompoundShape();
112 }
addChildShape(plCollisionWorldHandle worldHandle,plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle,plVector3 childPos,plQuaternion childOrn)113 void Bullet2CollisionSdk::addChildShape(plCollisionWorldHandle worldHandle, plCollisionShapeHandle compoundShapeHandle, plCollisionShapeHandle childShapeHandle, plVector3 childPos, plQuaternion childOrn)
114 {
115 	btCompoundShape* compound = (btCompoundShape*)compoundShapeHandle;
116 	btCollisionShape* childShape = (btCollisionShape*)childShapeHandle;
117 	btTransform localTrans;
118 	localTrans.setOrigin(btVector3(childPos[0], childPos[1], childPos[2]));
119 	localTrans.setRotation(btQuaternion(childOrn[0], childOrn[1], childOrn[2], childOrn[3]));
120 	compound->addChildShape(localTrans, childShape);
121 }
122 
deleteShape(plCollisionWorldHandle,plCollisionShapeHandle shapeHandle)123 void Bullet2CollisionSdk::deleteShape(plCollisionWorldHandle /*worldHandle*/, plCollisionShapeHandle shapeHandle)
124 {
125 	btCollisionShape* shape = (btCollisionShape*)shapeHandle;
126 	delete shape;
127 }
128 
addCollisionObject(plCollisionWorldHandle worldHandle,plCollisionObjectHandle objectHandle)129 void Bullet2CollisionSdk::addCollisionObject(plCollisionWorldHandle worldHandle, plCollisionObjectHandle objectHandle)
130 {
131 	btCollisionWorld* world = (btCollisionWorld*)worldHandle;
132 	btCollisionObject* colObj = (btCollisionObject*)objectHandle;
133 	btAssert(world && colObj);
134 	if (world == m_internalData->m_collisionWorld && colObj)
135 	{
136 		world->addCollisionObject(colObj);
137 	}
138 }
removeCollisionObject(plCollisionWorldHandle worldHandle,plCollisionObjectHandle objectHandle)139 void Bullet2CollisionSdk::removeCollisionObject(plCollisionWorldHandle worldHandle, plCollisionObjectHandle objectHandle)
140 {
141 	btCollisionWorld* world = (btCollisionWorld*)worldHandle;
142 	btCollisionObject* colObj = (btCollisionObject*)objectHandle;
143 	btAssert(world && colObj);
144 	if (world == m_internalData->m_collisionWorld && colObj)
145 	{
146 		world->removeCollisionObject(colObj);
147 	}
148 }
149 
createCollisionObject(plCollisionWorldHandle worldHandle,void * userPointer,int userIndex,plCollisionShapeHandle shapeHandle,plVector3 startPosition,plQuaternion startOrientation)150 plCollisionObjectHandle Bullet2CollisionSdk::createCollisionObject(plCollisionWorldHandle worldHandle, void* userPointer, int userIndex, plCollisionShapeHandle shapeHandle,
151 																   plVector3 startPosition, plQuaternion startOrientation)
152 
153 {
154 	btCollisionShape* colShape = (btCollisionShape*)shapeHandle;
155 	btAssert(colShape);
156 	if (colShape)
157 	{
158 		btCollisionObject* colObj = new btCollisionObject;
159 		colObj->setUserIndex(userIndex);
160 		colObj->setUserPointer(userPointer);
161 		colObj->setCollisionShape(colShape);
162 		btTransform tr;
163 		tr.setOrigin(btVector3(startPosition[0], startPosition[1], startPosition[2]));
164 		tr.setRotation(btQuaternion(startOrientation[0], startOrientation[1], startOrientation[2], startOrientation[3]));
165 		colObj->setWorldTransform(tr);
166 		return (plCollisionObjectHandle)colObj;
167 	}
168 	return 0;
169 }
170 
deleteCollisionObject(plCollisionObjectHandle bodyHandle)171 void Bullet2CollisionSdk::deleteCollisionObject(plCollisionObjectHandle bodyHandle)
172 {
173 	btCollisionObject* colObj = (btCollisionObject*)bodyHandle;
174 	delete colObj;
175 }
setCollisionObjectTransform(plCollisionWorldHandle,plCollisionObjectHandle bodyHandle,plVector3 position,plQuaternion orientation)176 void Bullet2CollisionSdk::setCollisionObjectTransform(plCollisionWorldHandle /*worldHandle*/, plCollisionObjectHandle bodyHandle,
177 													  plVector3 position, plQuaternion orientation)
178 {
179 	btCollisionObject* colObj = (btCollisionObject*)bodyHandle;
180 	btTransform tr;
181 	tr.setOrigin(btVector3(position[0], position[1], position[2]));
182 	tr.setRotation(btQuaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
183 	colObj->setWorldTransform(tr);
184 }
185 
186 struct Bullet2ContactResultCallback : public btCollisionWorld::ContactResultCallback
187 {
188 	int m_numContacts;
189 	lwContactPoint* m_pointsOut;
190 	int m_pointCapacity;
191 
Bullet2ContactResultCallbackBullet2ContactResultCallback192 	Bullet2ContactResultCallback(lwContactPoint* pointsOut, int pointCapacity) : m_numContacts(0),
193 																				 m_pointsOut(pointsOut),
194 																				 m_pointCapacity(pointCapacity)
195 	{
196 	}
addSingleResultBullet2ContactResultCallback197 	virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1)
198 	{
199 		if (m_numContacts < m_pointCapacity)
200 		{
201 			lwContactPoint& ptOut = m_pointsOut[m_numContacts];
202 			ptOut.m_distance = cp.m_distance1;
203 			ptOut.m_normalOnB[0] = cp.m_normalWorldOnB.getX();
204 			ptOut.m_normalOnB[1] = cp.m_normalWorldOnB.getY();
205 			ptOut.m_normalOnB[2] = cp.m_normalWorldOnB.getZ();
206 			ptOut.m_ptOnAWorld[0] = cp.m_positionWorldOnA[0];
207 			ptOut.m_ptOnAWorld[1] = cp.m_positionWorldOnA[1];
208 			ptOut.m_ptOnAWorld[2] = cp.m_positionWorldOnA[2];
209 			ptOut.m_ptOnBWorld[0] = cp.m_positionWorldOnB[0];
210 			ptOut.m_ptOnBWorld[1] = cp.m_positionWorldOnB[1];
211 			ptOut.m_ptOnBWorld[2] = cp.m_positionWorldOnB[2];
212 			m_numContacts++;
213 		}
214 
215 		return 1.f;
216 	}
217 };
218 
collide(plCollisionWorldHandle worldHandle,plCollisionObjectHandle colA,plCollisionObjectHandle colB,lwContactPoint * pointsOut,int pointCapacity)219 int Bullet2CollisionSdk::collide(plCollisionWorldHandle worldHandle, plCollisionObjectHandle colA, plCollisionObjectHandle colB,
220 								 lwContactPoint* pointsOut, int pointCapacity)
221 {
222 	btCollisionWorld* world = (btCollisionWorld*)worldHandle;
223 	btCollisionObject* colObjA = (btCollisionObject*)colA;
224 	btCollisionObject* colObjB = (btCollisionObject*)colB;
225 	btAssert(world && colObjA && colObjB);
226 	if (world == m_internalData->m_collisionWorld && colObjA && colObjB)
227 	{
228 		Bullet2ContactResultCallback cb(pointsOut, pointCapacity);
229 		world->contactPairTest(colObjA, colObjB, cb);
230 		return cb.m_numContacts;
231 	}
232 	return 0;
233 }
234 
235 static plNearCallback gTmpFilter;
236 static int gNearCallbackCount = 0;
237 static plCollisionSdkHandle gCollisionSdk = 0;
238 static plCollisionWorldHandle gCollisionWorldHandle = 0;
239 
240 static void* gUserData = 0;
241 
Bullet2NearCallback(btBroadphasePair & collisionPair,btCollisionDispatcher & dispatcher,const btDispatcherInfo & dispatchInfo)242 void Bullet2NearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
243 {
244 	btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
245 	btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
246 	plCollisionObjectHandle obA = (plCollisionObjectHandle)colObj0;
247 	plCollisionObjectHandle obB = (plCollisionObjectHandle)colObj1;
248 	if (gTmpFilter)
249 	{
250 		gTmpFilter(gCollisionSdk, gCollisionWorldHandle, gUserData, obA, obB);
251 		gNearCallbackCount++;
252 	}
253 }
254 
collideWorld(plCollisionWorldHandle worldHandle,plNearCallback filter,void * userData)255 void Bullet2CollisionSdk::collideWorld(plCollisionWorldHandle worldHandle,
256 									   plNearCallback filter, void* userData)
257 {
258 	btCollisionWorld* world = (btCollisionWorld*)worldHandle;
259 	//chain the near-callback
260 	gTmpFilter = filter;
261 	gNearCallbackCount = 0;
262 	gUserData = userData;
263 	gCollisionSdk = (plCollisionSdkHandle)this;
264 	gCollisionWorldHandle = worldHandle;
265 	m_internalData->m_dispatcher->setNearCallback(Bullet2NearCallback);
266 	world->performDiscreteCollisionDetection();
267 	gTmpFilter = 0;
268 }
269 
createBullet2SdkHandle()270 plCollisionSdkHandle Bullet2CollisionSdk::createBullet2SdkHandle()
271 {
272 	return (plCollisionSdkHandle) new Bullet2CollisionSdk;
273 }
274