1 /*
2 This source file is part of GIMPACT Library.
3 
4 For the latest info, see http://gimpact.sourceforge.net/
5 
6 Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
7 email: projectileman@yahoo.com
8 
9 
10 This software is provided 'as-is', without any express or implied warranty.
11 In no event will the authors be held liable for any damages arising from the use of this software.
12 Permission is granted to anyone to use this software for any purpose,
13 including commercial applications, and to alter it and redistribute it freely,
14 subject to the following restrictions:
15 
16 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.
17 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19 */
20 /*
21 Author: Francisco Leon Najera
22 Concave-Concave Collision
23 
24 */
25 
26 #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
27 #include "LinearMath/btIDebugDraw.h"
28 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
29 #include "BulletCollision/CollisionShapes/btBoxShape.h"
30 #include "btGImpactCollisionAlgorithm.h"
31 #include "btContactProcessing.h"
32 #include "LinearMath/btQuickprof.h"
33 
34 //! Class for accessing the plane equation
35 class btPlaneShape : public btStaticPlaneShape
36 {
37 public:
btPlaneShape(const btVector3 & v,float f)38 	btPlaneShape(const btVector3& v, float f)
39 		: btStaticPlaneShape(v, f)
40 	{
41 	}
42 
get_plane_equation(btVector4 & equation)43 	void get_plane_equation(btVector4& equation)
44 	{
45 		equation[0] = m_planeNormal[0];
46 		equation[1] = m_planeNormal[1];
47 		equation[2] = m_planeNormal[2];
48 		equation[3] = m_planeConstant;
49 	}
50 
get_plane_equation_transformed(const btTransform & trans,btVector4 & equation) const51 	void get_plane_equation_transformed(const btTransform& trans, btVector4& equation) const
52 	{
53 		const btVector3 normal = trans.getBasis() * m_planeNormal;
54 		equation[0] = normal[0];
55 		equation[1] = normal[1];
56 		equation[2] = normal[2];
57 		equation[3] = normal.dot(trans * (m_planeConstant * m_planeNormal));
58 	}
59 };
60 
61 //////////////////////////////////////////////////////////////////////////////////////////////
62 #ifdef TRI_COLLISION_PROFILING
63 
64 btClock g_triangle_clock;
65 
66 float g_accum_triangle_collision_time = 0;
67 int g_count_triangle_collision = 0;
68 
bt_begin_gim02_tri_time()69 void bt_begin_gim02_tri_time()
70 {
71 	g_triangle_clock.reset();
72 }
73 
bt_end_gim02_tri_time()74 void bt_end_gim02_tri_time()
75 {
76 	g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
77 	g_count_triangle_collision++;
78 }
79 #endif  //TRI_COLLISION_PROFILING
80 //! Retrieving shapes shapes
81 /*!
82 Declared here due of insuficent space on Pool allocators
83 */
84 //!@{
85 class GIM_ShapeRetriever
86 {
87 public:
88 	const btGImpactShapeInterface* m_gim_shape;
89 	btTriangleShapeEx m_trishape;
90 	btTetrahedronShapeEx m_tetrashape;
91 
92 public:
93 	class ChildShapeRetriever
94 	{
95 	public:
96 		GIM_ShapeRetriever* m_parent;
getChildShape(int index)97 		virtual const btCollisionShape* getChildShape(int index)
98 		{
99 			return m_parent->m_gim_shape->getChildShape(index);
100 		}
~ChildShapeRetriever()101 		virtual ~ChildShapeRetriever() {}
102 	};
103 
104 	class TriangleShapeRetriever : public ChildShapeRetriever
105 	{
106 	public:
getChildShape(int index)107 		virtual btCollisionShape* getChildShape(int index)
108 		{
109 			m_parent->m_gim_shape->getBulletTriangle(index, m_parent->m_trishape);
110 			return &m_parent->m_trishape;
111 		}
~TriangleShapeRetriever()112 		virtual ~TriangleShapeRetriever() {}
113 	};
114 
115 	class TetraShapeRetriever : public ChildShapeRetriever
116 	{
117 	public:
getChildShape(int index)118 		virtual btCollisionShape* getChildShape(int index)
119 		{
120 			m_parent->m_gim_shape->getBulletTetrahedron(index, m_parent->m_tetrashape);
121 			return &m_parent->m_tetrashape;
122 		}
123 	};
124 
125 public:
126 	ChildShapeRetriever m_child_retriever;
127 	TriangleShapeRetriever m_tri_retriever;
128 	TetraShapeRetriever m_tetra_retriever;
129 	ChildShapeRetriever* m_current_retriever;
130 
GIM_ShapeRetriever(const btGImpactShapeInterface * gim_shape)131 	GIM_ShapeRetriever(const btGImpactShapeInterface* gim_shape)
132 	{
133 		m_gim_shape = gim_shape;
134 		//select retriever
135 		if (m_gim_shape->needsRetrieveTriangles())
136 		{
137 			m_current_retriever = &m_tri_retriever;
138 		}
139 		else if (m_gim_shape->needsRetrieveTetrahedrons())
140 		{
141 			m_current_retriever = &m_tetra_retriever;
142 		}
143 		else
144 		{
145 			m_current_retriever = &m_child_retriever;
146 		}
147 
148 		m_current_retriever->m_parent = this;
149 	}
150 
getChildShape(int index)151 	const btCollisionShape* getChildShape(int index)
152 	{
153 		return m_current_retriever->getChildShape(index);
154 	}
155 };
156 
157 //!@}
158 
159 #ifdef TRI_COLLISION_PROFILING
160 
161 //! Gets the average time in miliseconds of tree collisions
getAverageTreeCollisionTime()162 float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
163 {
164 	return btGImpactBoxSet::getAverageTreeCollisionTime();
165 }
166 
167 //! Gets the average time in miliseconds of triangle collisions
getAverageTriangleCollisionTime()168 float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
169 {
170 	if (g_count_triangle_collision == 0) return 0;
171 
172 	float avgtime = g_accum_triangle_collision_time;
173 	avgtime /= (float)g_count_triangle_collision;
174 
175 	g_accum_triangle_collision_time = 0;
176 	g_count_triangle_collision = 0;
177 
178 	return avgtime;
179 }
180 
181 #endif  //TRI_COLLISION_PROFILING
182 
btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo & ci,const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap)183 btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
184 	: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap)
185 {
186 	m_manifoldPtr = NULL;
187 	m_convex_algorithm = NULL;
188 }
189 
~btGImpactCollisionAlgorithm()190 btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
191 {
192 	clearCache();
193 }
194 
addContactPoint(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btVector3 & point,const btVector3 & normal,btScalar distance)195 void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper* body0Wrap,
196 												  const btCollisionObjectWrapper* body1Wrap,
197 												  const btVector3& point,
198 												  const btVector3& normal,
199 												  btScalar distance)
200 {
201 	m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
202 	m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
203 	checkManifold(body0Wrap, body1Wrap);
204 	m_resultOut->addContactPoint(normal, point, distance);
205 }
206 
shape_vs_shape_collision(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btCollisionShape * shape0,const btCollisionShape * shape1)207 void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
208 	const btCollisionObjectWrapper* body0Wrap,
209 	const btCollisionObjectWrapper* body1Wrap,
210 	const btCollisionShape* shape0,
211 	const btCollisionShape* shape1)
212 {
213 	{
214 		btCollisionAlgorithm* algor = newAlgorithm(body0Wrap, body1Wrap);
215 		// post :	checkManifold is called
216 
217 		m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
218 		m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
219 
220 		algor->processCollision(body0Wrap, body1Wrap, *m_dispatchInfo, m_resultOut);
221 
222 		algor->~btCollisionAlgorithm();
223 		m_dispatcher->freeCollisionAlgorithm(algor);
224 	}
225 }
226 
convex_vs_convex_collision(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btCollisionShape * shape0,const btCollisionShape * shape1)227 void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
228 	const btCollisionObjectWrapper* body0Wrap,
229 	const btCollisionObjectWrapper* body1Wrap,
230 	const btCollisionShape* shape0,
231 	const btCollisionShape* shape1)
232 {
233 	m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
234 	m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
235 
236 	btCollisionObjectWrapper ob0(body0Wrap, shape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
237 	btCollisionObjectWrapper ob1(body1Wrap, shape1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), m_part1, m_triface1);
238 	checkConvexAlgorithm(&ob0, &ob1);
239 	m_convex_algorithm->processCollision(&ob0, &ob1, *m_dispatchInfo, m_resultOut);
240 }
241 
gimpact_vs_gimpact_find_pairs(const btTransform & trans0,const btTransform & trans1,const btGImpactShapeInterface * shape0,const btGImpactShapeInterface * shape1,btPairSet & pairset)242 void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
243 	const btTransform& trans0,
244 	const btTransform& trans1,
245 	const btGImpactShapeInterface* shape0,
246 	const btGImpactShapeInterface* shape1, btPairSet& pairset)
247 {
248 	if (shape0->hasBoxSet() && shape1->hasBoxSet())
249 	{
250 		btGImpactBoxSet::find_collision(shape0->getBoxSet(), trans0, shape1->getBoxSet(), trans1, pairset);
251 	}
252 	else
253 	{
254 		btAABB boxshape0;
255 		btAABB boxshape1;
256 		int i = shape0->getNumChildShapes();
257 
258 		while (i--)
259 		{
260 			shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
261 
262 			int j = shape1->getNumChildShapes();
263 			while (j--)
264 			{
265 				shape1->getChildAabb(i, trans1, boxshape1.m_min, boxshape1.m_max);
266 
267 				if (boxshape1.has_collision(boxshape0))
268 				{
269 					pairset.push_pair(i, j);
270 				}
271 			}
272 		}
273 	}
274 }
275 
gimpact_vs_shape_find_pairs(const btTransform & trans0,const btTransform & trans1,const btGImpactShapeInterface * shape0,const btCollisionShape * shape1,btAlignedObjectArray<int> & collided_primitives)276 void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
277 	const btTransform& trans0,
278 	const btTransform& trans1,
279 	const btGImpactShapeInterface* shape0,
280 	const btCollisionShape* shape1,
281 	btAlignedObjectArray<int>& collided_primitives)
282 {
283 	btAABB boxshape;
284 
285 	if (shape0->hasBoxSet())
286 	{
287 		btTransform trans1to0 = trans0.inverse();
288 		trans1to0 *= trans1;
289 
290 		shape1->getAabb(trans1to0, boxshape.m_min, boxshape.m_max);
291 
292 		shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
293 	}
294 	else
295 	{
296 		shape1->getAabb(trans1, boxshape.m_min, boxshape.m_max);
297 
298 		btAABB boxshape0;
299 		int i = shape0->getNumChildShapes();
300 
301 		while (i--)
302 		{
303 			shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
304 
305 			if (boxshape.has_collision(boxshape0))
306 			{
307 				collided_primitives.push_back(i);
308 			}
309 		}
310 	}
311 }
312 
collide_gjk_triangles(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btGImpactMeshShapePart * shape0,const btGImpactMeshShapePart * shape1,const int * pairs,int pair_count)313 void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
314 														const btCollisionObjectWrapper* body1Wrap,
315 														const btGImpactMeshShapePart* shape0,
316 														const btGImpactMeshShapePart* shape1,
317 														const int* pairs, int pair_count)
318 {
319 	btTriangleShapeEx tri0;
320 	btTriangleShapeEx tri1;
321 
322 	shape0->lockChildShapes();
323 	shape1->lockChildShapes();
324 
325 	const int* pair_pointer = pairs;
326 
327 	while (pair_count--)
328 	{
329 		m_triface0 = *(pair_pointer);
330 		m_triface1 = *(pair_pointer + 1);
331 		pair_pointer += 2;
332 
333 		shape0->getBulletTriangle(m_triface0, tri0);
334 		shape1->getBulletTriangle(m_triface1, tri1);
335 
336 		//collide two convex shapes
337 		if (tri0.overlap_test_conservative(tri1))
338 		{
339 			convex_vs_convex_collision(body0Wrap, body1Wrap, &tri0, &tri1);
340 		}
341 	}
342 
343 	shape0->unlockChildShapes();
344 	shape1->unlockChildShapes();
345 }
346 
collide_sat_triangles(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btGImpactMeshShapePart * shape0,const btGImpactMeshShapePart * shape1,const int * pairs,int pair_count)347 void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
348 														const btCollisionObjectWrapper* body1Wrap,
349 														const btGImpactMeshShapePart* shape0,
350 														const btGImpactMeshShapePart* shape1,
351 														const int* pairs, int pair_count)
352 {
353 	btTransform orgtrans0 = body0Wrap->getWorldTransform();
354 	btTransform orgtrans1 = body1Wrap->getWorldTransform();
355 
356 	btPrimitiveTriangle ptri0;
357 	btPrimitiveTriangle ptri1;
358 	GIM_TRIANGLE_CONTACT contact_data;
359 
360 	shape0->lockChildShapes();
361 	shape1->lockChildShapes();
362 
363 	const int* pair_pointer = pairs;
364 
365 	while (pair_count--)
366 	{
367 		m_triface0 = *(pair_pointer);
368 		m_triface1 = *(pair_pointer + 1);
369 		pair_pointer += 2;
370 
371 		shape0->getPrimitiveTriangle(m_triface0, ptri0);
372 		shape1->getPrimitiveTriangle(m_triface1, ptri1);
373 
374 #ifdef TRI_COLLISION_PROFILING
375 		bt_begin_gim02_tri_time();
376 #endif
377 
378 		ptri0.applyTransform(orgtrans0);
379 		ptri1.applyTransform(orgtrans1);
380 
381 		//build planes
382 		ptri0.buildTriPlane();
383 		ptri1.buildTriPlane();
384 		// test conservative
385 
386 		if (ptri0.overlap_test_conservative(ptri1))
387 		{
388 			if (ptri0.find_triangle_collision_clip_method(ptri1, contact_data))
389 			{
390 				int j = contact_data.m_point_count;
391 				while (j--)
392 				{
393 					addContactPoint(body0Wrap, body1Wrap,
394 									contact_data.m_points[j],
395 									contact_data.m_separating_normal,
396 									-contact_data.m_penetration_depth);
397 				}
398 			}
399 		}
400 
401 #ifdef TRI_COLLISION_PROFILING
402 		bt_end_gim02_tri_time();
403 #endif
404 	}
405 
406 	shape0->unlockChildShapes();
407 	shape1->unlockChildShapes();
408 }
409 
gimpact_vs_gimpact(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btGImpactShapeInterface * shape0,const btGImpactShapeInterface * shape1)410 void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
411 	const btCollisionObjectWrapper* body0Wrap,
412 	const btCollisionObjectWrapper* body1Wrap,
413 	const btGImpactShapeInterface* shape0,
414 	const btGImpactShapeInterface* shape1)
415 {
416 	if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
417 	{
418 		const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
419 		m_part0 = meshshape0->getMeshPartCount();
420 
421 		while (m_part0--)
422 		{
423 			gimpact_vs_gimpact(body0Wrap, body1Wrap, meshshape0->getMeshPart(m_part0), shape1);
424 		}
425 
426 		return;
427 	}
428 
429 	if (shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
430 	{
431 		const btGImpactMeshShape* meshshape1 = static_cast<const btGImpactMeshShape*>(shape1);
432 		m_part1 = meshshape1->getMeshPartCount();
433 
434 		while (m_part1--)
435 		{
436 			gimpact_vs_gimpact(body0Wrap, body1Wrap, shape0, meshshape1->getMeshPart(m_part1));
437 		}
438 
439 		return;
440 	}
441 
442 	btTransform orgtrans0 = body0Wrap->getWorldTransform();
443 	btTransform orgtrans1 = body1Wrap->getWorldTransform();
444 
445 	btPairSet pairset;
446 
447 	gimpact_vs_gimpact_find_pairs(orgtrans0, orgtrans1, shape0, shape1, pairset);
448 
449 	if (pairset.size() == 0) return;
450 
451 	if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
452 		shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
453 	{
454 		const btGImpactMeshShapePart* shapepart0 = static_cast<const btGImpactMeshShapePart*>(shape0);
455 		const btGImpactMeshShapePart* shapepart1 = static_cast<const btGImpactMeshShapePart*>(shape1);
456 //specialized function
457 #ifdef BULLET_TRIANGLE_COLLISION
458 		collide_gjk_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
459 #else
460 		collide_sat_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
461 #endif
462 
463 		return;
464 	}
465 
466 	//general function
467 
468 	shape0->lockChildShapes();
469 	shape1->lockChildShapes();
470 
471 	GIM_ShapeRetriever retriever0(shape0);
472 	GIM_ShapeRetriever retriever1(shape1);
473 
474 	bool child_has_transform0 = shape0->childrenHasTransform();
475 	bool child_has_transform1 = shape1->childrenHasTransform();
476 
477 	int i = pairset.size();
478 	while (i--)
479 	{
480 		GIM_PAIR* pair = &pairset[i];
481 		m_triface0 = pair->m_index1;
482 		m_triface1 = pair->m_index2;
483 		const btCollisionShape* colshape0 = retriever0.getChildShape(m_triface0);
484 		const btCollisionShape* colshape1 = retriever1.getChildShape(m_triface1);
485 
486 		btTransform tr0 = body0Wrap->getWorldTransform();
487 		btTransform tr1 = body1Wrap->getWorldTransform();
488 
489 		if (child_has_transform0)
490 		{
491 			tr0 = orgtrans0 * shape0->getChildTransform(m_triface0);
492 		}
493 
494 		if (child_has_transform1)
495 		{
496 			tr1 = orgtrans1 * shape1->getChildTransform(m_triface1);
497 		}
498 
499 		btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), tr0, m_part0, m_triface0);
500 		btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), tr1, m_part1, m_triface1);
501 
502 		//collide two convex shapes
503 		convex_vs_convex_collision(&ob0, &ob1, colshape0, colshape1);
504 	}
505 
506 	shape0->unlockChildShapes();
507 	shape1->unlockChildShapes();
508 }
509 
gimpact_vs_shape(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btGImpactShapeInterface * shape0,const btCollisionShape * shape1,bool swapped)510 void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
511 												   const btCollisionObjectWrapper* body1Wrap,
512 												   const btGImpactShapeInterface* shape0,
513 												   const btCollisionShape* shape1, bool swapped)
514 {
515 	if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
516 	{
517 		const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
518 		int& part = swapped ? m_part1 : m_part0;
519 		part = meshshape0->getMeshPartCount();
520 
521 		while (part--)
522 		{
523 			gimpact_vs_shape(body0Wrap,
524 							 body1Wrap,
525 							 meshshape0->getMeshPart(part),
526 							 shape1, swapped);
527 		}
528 
529 		return;
530 	}
531 
532 #ifdef GIMPACT_VS_PLANE_COLLISION
533 	if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
534 		shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
535 	{
536 		const btGImpactMeshShapePart* shapepart = static_cast<const btGImpactMeshShapePart*>(shape0);
537 		const btStaticPlaneShape* planeshape = static_cast<const btStaticPlaneShape*>(shape1);
538 		gimpacttrimeshpart_vs_plane_collision(body0Wrap, body1Wrap, shapepart, planeshape, swapped);
539 		return;
540 	}
541 
542 #endif
543 
544 	if (shape1->isCompound())
545 	{
546 		const btCompoundShape* compoundshape = static_cast<const btCompoundShape*>(shape1);
547 		gimpact_vs_compoundshape(body0Wrap, body1Wrap, shape0, compoundshape, swapped);
548 		return;
549 	}
550 	else if (shape1->isConcave())
551 	{
552 		const btConcaveShape* concaveshape = static_cast<const btConcaveShape*>(shape1);
553 		gimpact_vs_concave(body0Wrap, body1Wrap, shape0, concaveshape, swapped);
554 		return;
555 	}
556 
557 	btTransform orgtrans0 = body0Wrap->getWorldTransform();
558 
559 	btTransform orgtrans1 = body1Wrap->getWorldTransform();
560 
561 	btAlignedObjectArray<int> collided_results;
562 
563 	gimpact_vs_shape_find_pairs(orgtrans0, orgtrans1, shape0, shape1, collided_results);
564 
565 	if (collided_results.size() == 0) return;
566 
567 	shape0->lockChildShapes();
568 
569 	GIM_ShapeRetriever retriever0(shape0);
570 
571 	bool child_has_transform0 = shape0->childrenHasTransform();
572 
573 	int i = collided_results.size();
574 
575 	while (i--)
576 	{
577 		int child_index = collided_results[i];
578 		if (swapped)
579 			m_triface1 = child_index;
580 		else
581 			m_triface0 = child_index;
582 
583 		const btCollisionShape* colshape0 = retriever0.getChildShape(child_index);
584 
585 		btTransform tr0 = body0Wrap->getWorldTransform();
586 
587 		if (child_has_transform0)
588 		{
589 			tr0 = orgtrans0 * shape0->getChildTransform(child_index);
590 		}
591 
592 		btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
593 		const btCollisionObjectWrapper* prevObj;
594 
595 		if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
596 		{
597 			prevObj = m_resultOut->getBody0Wrap();
598 			m_resultOut->setBody0Wrap(&ob0);
599 		}
600 		else
601 		{
602 			prevObj = m_resultOut->getBody1Wrap();
603 			m_resultOut->setBody1Wrap(&ob0);
604 		}
605 
606 		//collide two shapes
607 		if (swapped)
608 		{
609 			shape_vs_shape_collision(body1Wrap, &ob0, shape1, colshape0);
610 		}
611 		else
612 		{
613 			shape_vs_shape_collision(&ob0, body1Wrap, colshape0, shape1);
614 		}
615 
616 		if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
617 		{
618 			m_resultOut->setBody0Wrap(prevObj);
619 		}
620 		else
621 		{
622 			m_resultOut->setBody1Wrap(prevObj);
623 		}
624 	}
625 
626 	shape0->unlockChildShapes();
627 }
628 
gimpact_vs_compoundshape(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btGImpactShapeInterface * shape0,const btCompoundShape * shape1,bool swapped)629 void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
630 														   const btCollisionObjectWrapper* body1Wrap,
631 														   const btGImpactShapeInterface* shape0,
632 														   const btCompoundShape* shape1, bool swapped)
633 {
634 	btTransform orgtrans1 = body1Wrap->getWorldTransform();
635 
636 	int i = shape1->getNumChildShapes();
637 	while (i--)
638 	{
639 		const btCollisionShape* colshape1 = shape1->getChildShape(i);
640 		btTransform childtrans1 = orgtrans1 * shape1->getChildTransform(i);
641 
642 		btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), childtrans1, -1, i);
643 
644 		const btCollisionObjectWrapper* tmp = 0;
645 		if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
646 		{
647 			tmp = m_resultOut->getBody0Wrap();
648 			m_resultOut->setBody0Wrap(&ob1);
649 		}
650 		else
651 		{
652 			tmp = m_resultOut->getBody1Wrap();
653 			m_resultOut->setBody1Wrap(&ob1);
654 		}
655 		//collide child shape
656 		gimpact_vs_shape(body0Wrap, &ob1,
657 						 shape0, colshape1, swapped);
658 
659 		if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
660 		{
661 			m_resultOut->setBody0Wrap(tmp);
662 		}
663 		else
664 		{
665 			m_resultOut->setBody1Wrap(tmp);
666 		}
667 	}
668 }
669 
gimpacttrimeshpart_vs_plane_collision(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btGImpactMeshShapePart * shape0,const btStaticPlaneShape * shape1,bool swapped)670 void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
671 	const btCollisionObjectWrapper* body0Wrap,
672 	const btCollisionObjectWrapper* body1Wrap,
673 	const btGImpactMeshShapePart* shape0,
674 	const btStaticPlaneShape* shape1, bool swapped)
675 {
676 	btTransform orgtrans0 = body0Wrap->getWorldTransform();
677 	btTransform orgtrans1 = body1Wrap->getWorldTransform();
678 
679 	const btPlaneShape* planeshape = static_cast<const btPlaneShape*>(shape1);
680 	btVector4 plane;
681 	planeshape->get_plane_equation_transformed(orgtrans1, plane);
682 
683 	//test box against plane
684 
685 	btAABB tribox;
686 	shape0->getAabb(orgtrans0, tribox.m_min, tribox.m_max);
687 	tribox.increment_margin(planeshape->getMargin());
688 
689 	if (tribox.plane_classify(plane) != BT_CONST_COLLIDE_PLANE) return;
690 
691 	shape0->lockChildShapes();
692 
693 	btScalar margin = shape0->getMargin() + planeshape->getMargin();
694 
695 	btVector3 vertex;
696 	int vi = shape0->getVertexCount();
697 	while (vi--)
698 	{
699 		shape0->getVertex(vi, vertex);
700 		vertex = orgtrans0(vertex);
701 
702 		btScalar distance = vertex.dot(plane) - plane[3] - margin;
703 
704 		if (distance < 0.0)  //add contact
705 		{
706 			if (swapped)
707 			{
708 				addContactPoint(body1Wrap, body0Wrap,
709 								vertex,
710 								-plane,
711 								distance);
712 			}
713 			else
714 			{
715 				addContactPoint(body0Wrap, body1Wrap,
716 								vertex,
717 								plane,
718 								distance);
719 			}
720 		}
721 	}
722 
723 	shape0->unlockChildShapes();
724 }
725 
726 class btGImpactTriangleCallback : public btTriangleCallback
727 {
728 public:
729 	btGImpactCollisionAlgorithm* algorithm;
730 	const btCollisionObjectWrapper* body0Wrap;
731 	const btCollisionObjectWrapper* body1Wrap;
732 	const btGImpactShapeInterface* gimpactshape0;
733 	bool swapped;
734 	btScalar margin;
735 
processTriangle(btVector3 * triangle,int partId,int triangleIndex)736 	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
737 	{
738 		btTriangleShapeEx tri1(triangle[0], triangle[1], triangle[2]);
739 		tri1.setMargin(margin);
740 		if (swapped)
741 		{
742 			algorithm->setPart0(partId);
743 			algorithm->setFace0(triangleIndex);
744 		}
745 		else
746 		{
747 			algorithm->setPart1(partId);
748 			algorithm->setFace1(triangleIndex);
749 		}
750 
751 		btCollisionObjectWrapper ob1Wrap(body1Wrap, &tri1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), partId, triangleIndex);
752 		const btCollisionObjectWrapper* tmp = 0;
753 
754 		if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
755 		{
756 			tmp = algorithm->internalGetResultOut()->getBody0Wrap();
757 			algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap);
758 		}
759 		else
760 		{
761 			tmp = algorithm->internalGetResultOut()->getBody1Wrap();
762 			algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap);
763 		}
764 
765 		algorithm->gimpact_vs_shape(
766 			body0Wrap, &ob1Wrap, gimpactshape0, &tri1, swapped);
767 
768 		if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
769 		{
770 			algorithm->internalGetResultOut()->setBody0Wrap(tmp);
771 		}
772 		else
773 		{
774 			algorithm->internalGetResultOut()->setBody1Wrap(tmp);
775 		}
776 	}
777 };
778 
gimpact_vs_concave(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btGImpactShapeInterface * shape0,const btConcaveShape * shape1,bool swapped)779 void btGImpactCollisionAlgorithm::gimpact_vs_concave(
780 	const btCollisionObjectWrapper* body0Wrap,
781 	const btCollisionObjectWrapper* body1Wrap,
782 	const btGImpactShapeInterface* shape0,
783 	const btConcaveShape* shape1, bool swapped)
784 {
785 	//create the callback
786 	btGImpactTriangleCallback tricallback;
787 	tricallback.algorithm = this;
788 	tricallback.body0Wrap = body0Wrap;
789 	tricallback.body1Wrap = body1Wrap;
790 	tricallback.gimpactshape0 = shape0;
791 	tricallback.swapped = swapped;
792 	tricallback.margin = shape1->getMargin();
793 
794 	//getting the trimesh AABB
795 	btTransform gimpactInConcaveSpace;
796 
797 	gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
798 
799 	btVector3 minAABB, maxAABB;
800 	shape0->getAabb(gimpactInConcaveSpace, minAABB, maxAABB);
801 
802 	shape1->processAllTriangles(&tricallback, minAABB, maxAABB);
803 }
804 
processCollision(const btCollisionObjectWrapper * body0Wrap,const btCollisionObjectWrapper * body1Wrap,const btDispatcherInfo & dispatchInfo,btManifoldResult * resultOut)805 void btGImpactCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
806 {
807 	clearCache();
808 
809 	m_resultOut = resultOut;
810 	m_dispatchInfo = &dispatchInfo;
811 	const btGImpactShapeInterface* gimpactshape0;
812 	const btGImpactShapeInterface* gimpactshape1;
813 
814 	if (body0Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
815 	{
816 		gimpactshape0 = static_cast<const btGImpactShapeInterface*>(body0Wrap->getCollisionShape());
817 
818 		if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
819 		{
820 			gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
821 
822 			gimpact_vs_gimpact(body0Wrap, body1Wrap, gimpactshape0, gimpactshape1);
823 		}
824 		else
825 		{
826 			gimpact_vs_shape(body0Wrap, body1Wrap, gimpactshape0, body1Wrap->getCollisionShape(), false);
827 		}
828 	}
829 	else if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
830 	{
831 		gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
832 
833 		gimpact_vs_shape(body1Wrap, body0Wrap, gimpactshape1, body0Wrap->getCollisionShape(), true);
834 	}
835 
836 	// Ensure that gContactProcessedCallback is called for concave shapes.
837 	if (getLastManifold())
838 	{
839 		m_resultOut->refreshContactPoints();
840 	}
841 }
842 
calculateTimeOfImpact(btCollisionObject * body0,btCollisionObject * body1,const btDispatcherInfo & dispatchInfo,btManifoldResult * resultOut)843 btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
844 {
845 	return 1.f;
846 }
847 
848 ///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
849 
850 //! Use this function for register the algorithm externally
registerAlgorithm(btCollisionDispatcher * dispatcher)851 void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher* dispatcher)
852 {
853 	static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
854 
855 	int i;
856 
857 	for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
858 	{
859 		dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE, i, &s_gimpact_cf);
860 	}
861 
862 	for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
863 	{
864 		dispatcher->registerCollisionCreateFunc(i, GIMPACT_SHAPE_PROXYTYPE, &s_gimpact_cf);
865 	}
866 }
867