/* * Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz> * * Bullet Continuous Collision Detection and Physics Library * Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/ * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 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. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ package com.bulletphysics.collision.dispatch; import java.util.Collections; import com.bulletphysics.util.ObjectPool; import com.bulletphysics.util.Supplier; import com.bulletphysics.collision.broadphase.BroadphaseNativeType; import com.bulletphysics.collision.broadphase.BroadphasePair; import com.bulletphysics.collision.broadphase.CollisionAlgorithm; import com.bulletphysics.collision.broadphase.CollisionAlgorithmConstructionInfo; import com.bulletphysics.collision.broadphase.Dispatcher; import com.bulletphysics.collision.broadphase.DispatcherInfo; import com.bulletphysics.collision.broadphase.OverlapCallback; import com.bulletphysics.collision.broadphase.OverlappingPairCache; import com.bulletphysics.collision.narrowphase.PersistentManifold; import com.bulletphysics.util.ObjectArrayList; /** * CollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. * Time of Impact, Closest Points and Penetration Depth. * * @author jezek2 */ public class CollisionDispatcher extends Dispatcher { protected final ObjectPool<PersistentManifold> manifoldsPool = ObjectPool.get(PersistentManifold.class, new Supplier<PersistentManifold>() { @Override public PersistentManifold get() { return new PersistentManifold(); }}); private static final int MAX_BROADPHASE_COLLISION_TYPES = BroadphaseNativeType.MAX_BROADPHASE_COLLISION_TYPES.ordinal(); private int count = 0; private final ObjectArrayList<PersistentManifold> manifoldsPtr = new ObjectArrayList<PersistentManifold>(); private boolean useIslands = true; private boolean staticWarningReported = false; private ManifoldResult defaultManifoldResult; private NearCallback nearCallback; //private PoolAllocator* m_collisionAlgorithmPoolAllocator; //private PoolAllocator* m_persistentManifoldPoolAllocator; private final CollisionAlgorithmCreateFunc[][] doubleDispatch = new CollisionAlgorithmCreateFunc[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; private CollisionConfiguration collisionConfiguration; //private static int gNumManifold = 0; private CollisionAlgorithmConstructionInfo tmpCI = new CollisionAlgorithmConstructionInfo(); public CollisionDispatcher(CollisionConfiguration collisionConfiguration) { this.collisionConfiguration = collisionConfiguration; setNearCallback(new DefaultNearCallback()); //m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool(); //m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); for (int i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++) { for (int j = 0; j < MAX_BROADPHASE_COLLISION_TYPES; j++) { doubleDispatch[i][j] = collisionConfiguration.getCollisionAlgorithmCreateFunc( BroadphaseNativeType.values()[i], BroadphaseNativeType.values()[j] ); assert (doubleDispatch[i][j] != null); } } } public void registerCollisionCreateFunc(int proxyType0, int proxyType1, CollisionAlgorithmCreateFunc createFunc) { doubleDispatch[proxyType0][proxyType1] = createFunc; } public NearCallback getNearCallback() { return nearCallback; } public void setNearCallback(NearCallback nearCallback) { this.nearCallback = nearCallback; } public CollisionConfiguration getCollisionConfiguration() { return collisionConfiguration; } public void setCollisionConfiguration(CollisionConfiguration collisionConfiguration) { this.collisionConfiguration = collisionConfiguration; } @Override public CollisionAlgorithm findAlgorithm(CollisionObject body0, CollisionObject body1, PersistentManifold sharedManifold) { CollisionAlgorithmConstructionInfo ci = tmpCI; ci.dispatcher1 = this; ci.manifold = sharedManifold; CollisionAlgorithmCreateFunc createFunc = doubleDispatch[body0.getCollisionShape().getShapeType().ordinal()][body1.getCollisionShape().getShapeType().ordinal()]; CollisionAlgorithm algo = createFunc.createCollisionAlgorithm(ci, body0, body1); algo.internalSetCreateFunc(createFunc); return algo; } @Override public void freeCollisionAlgorithm(CollisionAlgorithm algo) { CollisionAlgorithmCreateFunc createFunc = algo.internalGetCreateFunc(); algo.internalSetCreateFunc(null); createFunc.releaseCollisionAlgorithm(algo); algo.destroy(); } @Override public PersistentManifold getNewManifold(Object b0, Object b1) { //gNumManifold++; //btAssert(gNumManifold < 65535); CollisionObject body0 = (CollisionObject)b0; CollisionObject body1 = (CollisionObject)b1; /* void* mem = 0; if (m_persistentManifoldPoolAllocator->getFreeCount()) { mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); } else { mem = btAlignedAlloc(sizeof(btPersistentManifold),16); } btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0); manifold->m_index1a = m_manifoldsPtr.size(); m_manifoldsPtr.push_back(manifold); */ PersistentManifold manifold = manifoldsPool.get(); manifold.init(body0,body1,0); manifold.index1a = manifoldsPtr.size(); manifoldsPtr.add(manifold); return manifold; } @Override public void releaseManifold(PersistentManifold manifold) { //gNumManifold--; //printf("releaseManifold: gNumManifold %d\n",gNumManifold); clearManifold(manifold); // TODO: optimize int findIndex = manifold.index1a; assert (findIndex < manifoldsPtr.size()); Collections.swap(manifoldsPtr, findIndex, manifoldsPtr.size()-1); manifoldsPtr.getQuick(findIndex).index1a = findIndex; manifoldsPtr.removeQuick(manifoldsPtr.size()-1); manifoldsPool.release(manifold); /* manifold->~btPersistentManifold(); if (m_persistentManifoldPoolAllocator->validPtr(manifold)) { m_persistentManifoldPoolAllocator->freeMemory(manifold); } else { btAlignedFree(manifold); } */ } @Override public void clearManifold(PersistentManifold manifold) { manifold.clearManifold(); } @Override public boolean needsCollision(CollisionObject body0, CollisionObject body1) { assert (body0 != null); assert (body1 != null); boolean needsCollision = true; //#ifdef BT_DEBUG if (!staticWarningReported) { // broadphase filtering already deals with this if ((body0.isStaticObject() || body0.isKinematicObject()) && (body1.isStaticObject() || body1.isKinematicObject())) { staticWarningReported = true; System.err.println("warning CollisionDispatcher.needsCollision: static-static collision!"); } } //#endif //BT_DEBUG if ((!body0.isActive()) && (!body1.isActive())) { needsCollision = false; } else if (!body0.checkCollideWith(body1)) { needsCollision = false; } return needsCollision; } @Override public boolean needsResponse(CollisionObject body0, CollisionObject body1) { //here you can do filtering boolean hasResponse = (body0.hasContactResponse() && body1.hasContactResponse()); //no response between two static/kinematic bodies: hasResponse = hasResponse && ((!body0.isStaticOrKinematicObject()) || (!body1.isStaticOrKinematicObject())); return hasResponse; } private static class CollisionPairCallback extends OverlapCallback { private DispatcherInfo dispatchInfo; private CollisionDispatcher dispatcher; public void init(DispatcherInfo dispatchInfo, CollisionDispatcher dispatcher) { this.dispatchInfo = dispatchInfo; this.dispatcher = dispatcher; } public boolean processOverlap(BroadphasePair pair) { dispatcher.getNearCallback().handleCollision(pair, dispatcher, dispatchInfo); return false; } } private CollisionPairCallback collisionPairCallback = new CollisionPairCallback(); @Override public void dispatchAllCollisionPairs(OverlappingPairCache pairCache, DispatcherInfo dispatchInfo, Dispatcher dispatcher) { //m_blockedForChanges = true; collisionPairCallback.init(dispatchInfo, this); pairCache.processAllOverlappingPairs(collisionPairCallback, dispatcher); //m_blockedForChanges = false; } @Override public int getNumManifolds() { return manifoldsPtr.size(); } @Override public PersistentManifold getManifoldByIndexInternal(int index) { return manifoldsPtr.getQuick(index); } @Override public ObjectArrayList<PersistentManifold> getInternalManifoldPointer() { return manifoldsPtr; } }