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