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