Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentationFS14/src/external/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @ 10073

Last change on this file since 10073 was 10073, checked in by smerkli, 10 years ago

Merged modularships branch

  • Property svn:eol-style set to native
File size: 12.6 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
17#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
18#include "BulletCollision/CollisionShapes/btCompoundShape.h"
19#include "BulletCollision/BroadphaseCollision/btDbvt.h"
20#include "LinearMath/btIDebugDraw.h"
21#include "LinearMath/btAabbUtil2.h"
22#include "btManifoldResult.h"
23#include <iostream>
24
25btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
26:btActivatingCollisionAlgorithm(ci,body0,body1),
27m_isSwapped(isSwapped),
28m_sharedManifold(ci.m_manifold)
29{
30        m_ownsManifold = false;
31
32        btCollisionObject* colObj = m_isSwapped? body1 : body0;
33        btAssert (colObj->getCollisionShape()->isCompound());
34       
35        btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
36        m_compoundShapeRevision = compoundShape->getUpdateRevision();
37       
38        preallocateChildAlgorithms(body0,body1);
39}
40
41void    btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1)
42{
43        btCollisionObject* colObj = m_isSwapped? body1 : body0;
44        btCollisionObject* otherObj = m_isSwapped? body0 : body1;
45        btAssert (colObj->getCollisionShape()->isCompound());
46       
47        btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
48
49        int numChildren = compoundShape->getNumChildShapes();
50        int i;
51       
52        m_childCollisionAlgorithms.resize(numChildren);
53        for (i=0;i<numChildren;i++)
54        {
55                if (compoundShape->getDynamicAabbTree())
56                {
57                        m_childCollisionAlgorithms[i] = 0;
58                } else
59                {
60                        btCollisionShape* tmpShape = colObj->getCollisionShape();
61                        btCollisionShape* childShape = compoundShape->getChildShape(i);
62                        colObj->internalSetTemporaryCollisionShape( childShape );
63                        m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold);
64                        colObj->internalSetTemporaryCollisionShape( tmpShape );
65                }
66        }
67}
68
69void    btCompoundCollisionAlgorithm::removeChildAlgorithms()
70{
71        int numChildren = m_childCollisionAlgorithms.size();
72        int i;
73        for (i=0;i<numChildren;i++)
74        {
75                if (m_childCollisionAlgorithms[i])
76                {
77                        m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
78                        m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
79                }
80        }
81}
82
83btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
84{
85        removeChildAlgorithms();
86}
87
88
89
90
91struct  btCompoundLeafCallback : btDbvt::ICollide
92{
93
94public:
95
96        btCollisionObject* m_compoundColObj;
97        btCollisionObject* m_otherObj;
98        btDispatcher* m_dispatcher;
99        const btDispatcherInfo& m_dispatchInfo;
100        btManifoldResult*       m_resultOut;
101        btCollisionAlgorithm**  m_childCollisionAlgorithms;
102        btPersistentManifold*   m_sharedManifold;
103
104
105
106
107        btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult*      resultOut,btCollisionAlgorithm**        childCollisionAlgorithms,btPersistentManifold*  sharedManifold)
108                :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
109                m_childCollisionAlgorithms(childCollisionAlgorithms),
110                m_sharedManifold(sharedManifold)
111        {
112
113        }
114
115
116        void    ProcessChildShape(btCollisionShape* childShape,int index)
117        {
118                // std::cout << "PCS: " << childShape << std::endl; // FIXME: (noep) remove DEBUG
119            btAssert(index>=0);
120                btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
121                btAssert(index<compoundShape->getNumChildShapes());
122
123
124                //backup
125                btTransform     orgTrans = m_compoundColObj->getWorldTransform();
126                btTransform     orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
127                const btTransform& childTrans = compoundShape->getChildTransform(index);
128                btTransform     newChildWorldTrans = orgTrans*childTrans ;
129
130                //perform an AABB check first
131                btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
132                childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
133                m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
134
135                if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
136                {
137
138                        m_compoundColObj->setWorldTransform( newChildWorldTrans);
139                        m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
140
141                        //the contactpoint is still projected back using the original inverted worldtrans
142                        btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
143                        m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
144
145                        if (!m_childCollisionAlgorithms[index])
146                                m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
147
148                        ///detect swapping case
149                        if (m_resultOut->getBody0Internal() == m_compoundColObj)
150                        {
151                                m_resultOut->setShapeIdentifiersA(-1,index);
152                        } else
153                        {
154                                m_resultOut->setShapeIdentifiersB(-1,index);
155                        }
156
157                        m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
158                        if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
159                        {
160                                btVector3 worldAabbMin,worldAabbMax;
161                                m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
162                                m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
163                        }
164                       
165                        //revert back transform
166                        m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
167                        m_compoundColObj->setWorldTransform(  orgTrans );
168                        m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
169                }
170        }
171        void            Process(const btDbvtNode* leaf)
172        {
173                int index = leaf->dataAsInt;
174
175                btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
176                btCollisionShape* childShape = compoundShape->getChildShape(index);
177                if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
178                {
179                        btVector3 worldAabbMin,worldAabbMax;
180                        btTransform     orgTrans = m_compoundColObj->getWorldTransform();
181                        btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
182                        m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
183                }
184                ProcessChildShape(childShape,index);
185
186        }
187};
188
189
190
191
192
193
194void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
195{
196        btCollisionObject* colObj = m_isSwapped? body1 : body0;
197        btCollisionObject* otherObj = m_isSwapped? body0 : body1;
198
199       
200
201        btAssert (colObj->getCollisionShape()->isCompound());
202        btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
203
204        ///btCompoundShape might have changed:
205        ////make sure the internal child collision algorithm caches are still valid
206        if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
207        {
208                ///clear and update all
209                removeChildAlgorithms();
210               
211                preallocateChildAlgorithms(body0,body1);
212        }
213
214
215        btDbvt* tree = compoundShape->getDynamicAabbTree();
216        //use a dynamic aabb tree to cull potential child-overlaps
217        btCompoundLeafCallback  callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
218
219        ///we need to refresh all contact manifolds
220        ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
221        ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
222        {
223                int i;
224                btManifoldArray manifoldArray;
225                for (i=0;i<m_childCollisionAlgorithms.size();i++)
226                {
227                        if (m_childCollisionAlgorithms[i])
228                        {
229                                m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
230                                for (int m=0;m<manifoldArray.size();m++)
231                                {
232                                        if (manifoldArray[m]->getNumContacts())
233                                        {
234                                                resultOut->setPersistentManifold(manifoldArray[m]);
235                                                resultOut->refreshContactPoints();
236                                                resultOut->setPersistentManifold(0);//??necessary?
237                                        }
238                                }
239                                manifoldArray.resize(0);
240                        }
241                }
242        }
243
244        if (tree)
245        {
246
247                btVector3 localAabbMin,localAabbMax;
248                btTransform otherInCompoundSpace;
249                otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
250                otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
251
252                const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
253                //process all children, that overlap with  the given AABB bounds
254                tree->collideTV(tree->m_root,bounds,callback);
255
256        } else
257        {
258                //iterate over all children, perform an AABB check inside ProcessChildShape
259                int numChildren = m_childCollisionAlgorithms.size();
260                int i;
261                for (i=0;i<numChildren;i++)
262                {
263                        callback.ProcessChildShape(compoundShape->getChildShape(i),i);
264                }
265        }
266
267        {
268                                //iterate over all children, perform an AABB check inside ProcessChildShape
269                int numChildren = m_childCollisionAlgorithms.size();
270                int i;
271                btManifoldArray manifoldArray;
272        btCollisionShape* childShape = 0;
273        btTransform     orgTrans;
274        btTransform     orgInterpolationTrans;
275        btTransform     newChildWorldTrans;
276        btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;       
277       
278                for (i=0;i<numChildren;i++)
279                {
280                        if (m_childCollisionAlgorithms[i])
281                        {
282                                childShape = compoundShape->getChildShape(i);
283                        //if not longer overlapping, remove the algorithm
284                orgTrans = colObj->getWorldTransform();
285                orgInterpolationTrans = colObj->getInterpolationWorldTransform();
286                                const btTransform& childTrans = compoundShape->getChildTransform(i);
287                newChildWorldTrans = orgTrans*childTrans ;
288
289                                //perform an AABB check first
290                                childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
291                                otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
292
293                                if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
294                                {
295                                        m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
296                                        m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
297                                        m_childCollisionAlgorithms[i] = 0;
298                                }
299                        }
300                }
301        }
302}
303
304btScalar        btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
305{
306
307        btCollisionObject* colObj = m_isSwapped? body1 : body0;
308        btCollisionObject* otherObj = m_isSwapped? body0 : body1;
309
310        btAssert (colObj->getCollisionShape()->isCompound());
311       
312        btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
313
314        //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
315        //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
316        //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
317        //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
318        //then use each overlapping node AABB against Tree0
319        //and vise versa.
320
321        btScalar hitFraction = btScalar(1.);
322
323        int numChildren = m_childCollisionAlgorithms.size();
324        int i;
325    btTransform orgTrans;
326    btScalar frac;
327        for (i=0;i<numChildren;i++)
328        {
329                //temporarily exchange parent btCollisionShape with childShape, and recurse
330                btCollisionShape* childShape = compoundShape->getChildShape(i);
331
332                //backup
333        orgTrans = colObj->getWorldTransform();
334       
335                const btTransform& childTrans = compoundShape->getChildTransform(i);
336                //btTransform   newChildWorldTrans = orgTrans*childTrans ;
337                colObj->setWorldTransform( orgTrans*childTrans );
338
339                btCollisionShape* tmpShape = colObj->getCollisionShape();
340                colObj->internalSetTemporaryCollisionShape( childShape );
341        frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
342                if (frac<hitFraction)
343                {
344                        hitFraction = frac;
345                }
346                //revert back
347                colObj->internalSetTemporaryCollisionShape( tmpShape);
348                colObj->setWorldTransform( orgTrans);
349        }
350        return hitFraction;
351
352}
353
354
355
Note: See TracBrowser for help on using the repository browser.