Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @ 2818

Last change on this file since 2818 was 2662, checked in by rgrieder, 16 years ago

Merged presentation branch back to trunk.

  • Property svn:eol-style set to native
File size: 11.0 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
17#include "LinearMath/btScalar.h"
18#include "btSimulationIslandManager.h"
19#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
20#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
21#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
22#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
23
24//#include <stdio.h>
25#include "LinearMath/btQuickprof.h"
26
27btSimulationIslandManager::btSimulationIslandManager()
28{
29}
30
31btSimulationIslandManager::~btSimulationIslandManager()
32{
33}
34
35
36void btSimulationIslandManager::initUnionFind(int n)
37{
38                m_unionFind.reset(n);
39}
40               
41
42void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
43{
44       
45        {
46                btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr();
47
48                for (int i=0;i<colWorld->getPairCache()->getNumOverlappingPairs();i++)
49                {
50                        const btBroadphasePair& collisionPair = pairPtr[i];
51                        btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
52                        btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
53
54                        if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
55                                ((colObj1) && ((colObj1)->mergesSimulationIslands())))
56                        {
57
58                                m_unionFind.unite((colObj0)->getIslandTag(),
59                                        (colObj1)->getIslandTag());
60                        }
61                }
62        }
63}
64
65
66void    btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
67{
68       
69        initUnionFind( int (colWorld->getCollisionObjectArray().size()));
70       
71        // put the index into m_controllers into m_tag 
72        {
73               
74                int index = 0;
75                int i;
76                for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
77                {
78                        btCollisionObject*      collisionObject= colWorld->getCollisionObjectArray()[i];
79                        collisionObject->setIslandTag(index);
80                        collisionObject->setCompanionId(-1);
81                        collisionObject->setHitFraction(btScalar(1.));
82                        index++;
83                       
84                }
85        }
86        // do the union find
87       
88        findUnions(dispatcher,colWorld);
89       
90
91       
92}
93
94
95
96
97void    btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
98{
99        // put the islandId ('find' value) into m_tag   
100        {
101               
102               
103                int index = 0;
104                int i;
105                for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
106                {
107                        btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
108                        if (!collisionObject->isStaticOrKinematicObject())
109                        {
110                                collisionObject->setIslandTag( m_unionFind.find(index) );
111                                collisionObject->setCompanionId(-1);
112                        } else
113                        {
114                                collisionObject->setIslandTag(-1);
115                                collisionObject->setCompanionId(-2);
116                        }
117                        index++;
118                }
119        }
120}
121
122inline  int     getIslandId(const btPersistentManifold* lhs)
123{
124        int islandId;
125        const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
126        const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
127        islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
128        return islandId;
129
130}
131
132
133
134/// function object that routes calls to operator<
135class btPersistentManifoldSortPredicate
136{
137        public:
138
139                SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs )
140                {
141                        return getIslandId(lhs) < getIslandId(rhs);
142                }
143};
144
145
146void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
147{
148
149        BT_PROFILE("islandUnionFindAndQuickSort");
150       
151        btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
152
153        m_islandmanifold.resize(0);
154
155        //we are going to sort the unionfind array, and store the element id in the size
156        //afterwards, we clean unionfind, to make sure no-one uses it anymore
157       
158        getUnionFind().sortIslands();
159        int numElem = getUnionFind().getNumElements();
160
161        int endIslandIndex=1;
162        int startIslandIndex;
163
164
165        //update the sleeping state for bodies, if all are sleeping
166        for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
167        {
168                int islandId = getUnionFind().getElement(startIslandIndex).m_id;
169                for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
170                {
171                }
172
173                //int numSleeping = 0;
174
175                bool allSleeping = true;
176
177                int idx;
178                for (idx=startIslandIndex;idx<endIslandIndex;idx++)
179                {
180                        int i = getUnionFind().getElement(idx).m_sz;
181
182                        btCollisionObject* colObj0 = collisionObjects[i];
183                        if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
184                        {
185//                              printf("error in island management\n");
186                        }
187
188                        assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
189                        if (colObj0->getIslandTag() == islandId)
190                        {
191                                if (colObj0->getActivationState()== ACTIVE_TAG)
192                                {
193                                        allSleeping = false;
194                                }
195                                if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
196                                {
197                                        allSleeping = false;
198                                }
199                        }
200                }
201                       
202
203                if (allSleeping)
204                {
205                        int idx;
206                        for (idx=startIslandIndex;idx<endIslandIndex;idx++)
207                        {
208                                int i = getUnionFind().getElement(idx).m_sz;
209                                btCollisionObject* colObj0 = collisionObjects[i];
210                                if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
211                                {
212//                                      printf("error in island management\n");
213                                }
214
215                                assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
216
217                                if (colObj0->getIslandTag() == islandId)
218                                {
219                                        colObj0->setActivationState( ISLAND_SLEEPING );
220                                }
221                        }
222                } else
223                {
224
225                        int idx;
226                        for (idx=startIslandIndex;idx<endIslandIndex;idx++)
227                        {
228                                int i = getUnionFind().getElement(idx).m_sz;
229
230                                btCollisionObject* colObj0 = collisionObjects[i];
231                                if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
232                                {
233//                                      printf("error in island management\n");
234                                }
235
236                                assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
237
238                                if (colObj0->getIslandTag() == islandId)
239                                {
240                                        if ( colObj0->getActivationState() == ISLAND_SLEEPING)
241                                        {
242                                                colObj0->setActivationState( WANTS_DEACTIVATION);
243                                                colObj0->setDeactivationTime(0.f);
244                                        }
245                                }
246                        }
247                }
248        }
249
250       
251        int i;
252        int maxNumManifolds = dispatcher->getNumManifolds();
253
254#define SPLIT_ISLANDS 1
255#ifdef SPLIT_ISLANDS
256
257       
258#endif //SPLIT_ISLANDS
259
260       
261        for (i=0;i<maxNumManifolds ;i++)
262        {
263                 btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
264                 
265                 btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0());
266                 btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1());
267               
268                 ///@todo: check sleeping conditions!
269                 if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
270                        ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
271                {
272               
273                        //kinematic objects don't merge islands, but wake up all connected objects
274                        if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
275                        {
276                                colObj1->activate();
277                        }
278                        if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
279                        {
280                                colObj0->activate();
281                        }
282#ifdef SPLIT_ISLANDS
283        //              //filtering for response
284                        if (dispatcher->needsResponse(colObj0,colObj1))
285                                m_islandmanifold.push_back(manifold);
286#endif //SPLIT_ISLANDS
287                }
288        }
289}
290
291
292
293///@todo: this is random access, it can be walked 'cache friendly'!
294void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
295{
296        btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
297
298        buildIslands(dispatcher,collisionWorld);
299
300        int endIslandIndex=1;
301        int startIslandIndex;
302        int numElem = getUnionFind().getNumElements();
303
304        BT_PROFILE("processIslands");
305
306#ifndef SPLIT_ISLANDS
307        btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
308       
309        callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
310#else
311        // Sort manifolds, based on islands
312        // Sort the vector using predicate and std::sort
313        //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
314
315        int numManifolds = int (m_islandmanifold.size());
316
317        //we should do radix sort, it it much faster (O(n) instead of O (n log2(n))
318        m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
319
320        //now process all active islands (sets of manifolds for now)
321
322        int startManifoldIndex = 0;
323        int endManifoldIndex = 1;
324
325        //int islandId;
326
327       
328
329//      printf("Start Islands\n");
330
331        //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
332        for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
333        {
334                int islandId = getUnionFind().getElement(startIslandIndex).m_id;
335
336
337               bool islandSleeping = false;
338               
339                for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
340                {
341                        int i = getUnionFind().getElement(endIslandIndex).m_sz;
342                        btCollisionObject* colObj0 = collisionObjects[i];
343                                                m_islandBodies.push_back(colObj0);
344                        if (!colObj0->isActive())
345                                islandSleeping = true;
346                }
347               
348
349                //find the accompanying contact manifold for this islandId
350                int numIslandManifolds = 0;
351                btPersistentManifold** startManifold = 0;
352
353                if (startManifoldIndex<numManifolds)
354                {
355                        int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
356                        if (curIslandId == islandId)
357                        {
358                                startManifold = &m_islandmanifold[startManifoldIndex];
359                       
360                                for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
361                                {
362
363                                }
364                                /// Process the actual simulation, only if not sleeping/deactivated
365                                numIslandManifolds = endManifoldIndex-startManifoldIndex;
366                        }
367
368                }
369
370                if (!islandSleeping)
371                {
372                        callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
373//                      printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
374                }
375               
376                if (numIslandManifolds)
377                {
378                        startManifoldIndex = endManifoldIndex;
379                }
380
381                m_islandBodies.resize(0);
382        }
383#endif //SPLIT_ISLANDS
384
385
386}
Note: See TracBrowser for help on using the repository browser.