123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
- 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.
- */
- #include "btCollisionWorld.h"
- #include "btCollisionDispatcher.h"
- #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
- #include "BulletCollision/CollisionShapes/btCollisionShape.h"
- #include "BulletCollision/CollisionShapes/btConvexShape.h"
- #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
- #include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
- #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
- #include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" //for raycasting
- #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" //for raycasting
- #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
- #include "BulletCollision/CollisionShapes/btCompoundShape.h"
- #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
- #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
- #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
- #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
- #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
- #include "BulletCollision/BroadphaseCollision/btDbvt.h"
- #include "LinearMath/btAabbUtil2.h"
- #include "LinearMath/btQuickprof.h"
- #include "LinearMath/btSerializer.h"
- #include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
- #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
- //#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
- //#define USE_BRUTEFORCE_RAYBROADPHASE 1
- //RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest
- //#define RECALCULATE_AABB_RAYCAST 1
- //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
- #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
- #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
- #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
- ///for debug drawing
- //for debug rendering
- #include "BulletCollision/CollisionShapes/btBoxShape.h"
- #include "BulletCollision/CollisionShapes/btCapsuleShape.h"
- #include "BulletCollision/CollisionShapes/btCompoundShape.h"
- #include "BulletCollision/CollisionShapes/btConeShape.h"
- #include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
- #include "BulletCollision/CollisionShapes/btCylinderShape.h"
- #include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
- #include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
- #include "BulletCollision/CollisionShapes/btSphereShape.h"
- #include "BulletCollision/CollisionShapes/btTriangleCallback.h"
- #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
- #include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
- btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
- : m_dispatcher1(dispatcher),
- m_broadphasePairCache(pairCache),
- m_debugDrawer(0),
- m_forceUpdateAllAabbs(true)
- {
- }
- btCollisionWorld::~btCollisionWorld()
- {
- //clean up remaining objects
- int i;
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* collisionObject = m_collisionObjects[i];
- btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
- if (bp)
- {
- //
- // only clear the cached algorithms
- //
- getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
- getBroadphase()->destroyProxy(bp, m_dispatcher1);
- collisionObject->setBroadphaseHandle(0);
- }
- }
- }
- void btCollisionWorld::refreshBroadphaseProxy(btCollisionObject* collisionObject)
- {
- if (collisionObject->getBroadphaseHandle())
- {
- int collisionFilterGroup = collisionObject->getBroadphaseHandle()->m_collisionFilterGroup;
- int collisionFilterMask = collisionObject->getBroadphaseHandle()->m_collisionFilterMask;
- getBroadphase()->destroyProxy(collisionObject->getBroadphaseHandle(), getDispatcher());
- //calculate new AABB
- btTransform trans = collisionObject->getWorldTransform();
- btVector3 minAabb;
- btVector3 maxAabb;
- collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
- int type = collisionObject->getCollisionShape()->getShapeType();
- collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
- minAabb,
- maxAabb,
- type,
- collisionObject,
- collisionFilterGroup,
- collisionFilterMask,
- m_dispatcher1));
- }
- }
- void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
- {
- btAssert(collisionObject);
- //check that the object isn't already added
- btAssert(m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
- btAssert(collisionObject->getWorldArrayIndex() == -1); // do not add the same object to more than one collision world
- collisionObject->setWorldArrayIndex(m_collisionObjects.size());
- m_collisionObjects.push_back(collisionObject);
- //calculate new AABB
- btTransform trans = collisionObject->getWorldTransform();
- btVector3 minAabb;
- btVector3 maxAabb;
- collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
- int type = collisionObject->getCollisionShape()->getShapeType();
- collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
- minAabb,
- maxAabb,
- type,
- collisionObject,
- collisionFilterGroup,
- collisionFilterMask,
- m_dispatcher1));
- }
- void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
- {
- btVector3 minAabb, maxAabb;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
- //need to increase the aabb for contact thresholds
- btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
- minAabb -= contactThreshold;
- maxAabb += contactThreshold;
- if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
- {
- btVector3 minAabb2, maxAabb2;
- colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
- minAabb2 -= contactThreshold;
- maxAabb2 += contactThreshold;
- minAabb.setMin(minAabb2);
- maxAabb.setMax(maxAabb2);
- }
- btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
- //moving objects should be moderately sized, probably something wrong if not
- if (colObj->isStaticObject() || ((maxAabb - minAabb).length2() < btScalar(1e12)))
- {
- bp->setAabb(colObj->getBroadphaseHandle(), minAabb, maxAabb, m_dispatcher1);
- }
- else
- {
- //something went wrong, investigate
- //this assert is unwanted in 3D modelers (danger of loosing work)
- colObj->setActivationState(DISABLE_SIMULATION);
- static bool reportMe = true;
- if (reportMe && m_debugDrawer)
- {
- reportMe = false;
- m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
- m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
- m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
- m_debugDrawer->reportErrorWarning("Thanks.\n");
- }
- }
- }
- void btCollisionWorld::updateAabbs()
- {
- BT_PROFILE("updateAabbs");
- btTransform predictedTrans;
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btAssert(colObj->getWorldArrayIndex() == i);
- //only update aabb of active objects
- if (m_forceUpdateAllAabbs || colObj->isActive())
- {
- updateSingleAabb(colObj);
- }
- }
- }
- void btCollisionWorld::computeOverlappingPairs()
- {
- BT_PROFILE("calculateOverlappingPairs");
- m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
- }
- void btCollisionWorld::performDiscreteCollisionDetection()
- {
- BT_PROFILE("performDiscreteCollisionDetection");
- btDispatcherInfo& dispatchInfo = getDispatchInfo();
- updateAabbs();
- computeOverlappingPairs();
- btDispatcher* dispatcher = getDispatcher();
- {
- BT_PROFILE("dispatchAllCollisionPairs");
- if (dispatcher)
- dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(), dispatchInfo, m_dispatcher1);
- }
- }
- void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
- {
- //bool removeFromBroadphase = false;
- {
- btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
- if (bp)
- {
- //
- // only clear the cached algorithms
- //
- getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
- getBroadphase()->destroyProxy(bp, m_dispatcher1);
- collisionObject->setBroadphaseHandle(0);
- }
- }
- int iObj = collisionObject->getWorldArrayIndex();
- // btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
- if (iObj >= 0 && iObj < m_collisionObjects.size())
- {
- btAssert(collisionObject == m_collisionObjects[iObj]);
- m_collisionObjects.swap(iObj, m_collisionObjects.size() - 1);
- m_collisionObjects.pop_back();
- if (iObj < m_collisionObjects.size())
- {
- m_collisionObjects[iObj]->setWorldArrayIndex(iObj);
- }
- }
- else
- {
- // slow linear search
- //swapremove
- m_collisionObjects.remove(collisionObject);
- }
- collisionObject->setWorldArrayIndex(-1);
- }
- void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback)
- {
- btCollisionObjectWrapper colObWrap(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
- btCollisionWorld::rayTestSingleInternal(rayFromTrans, rayToTrans, &colObWrap, resultCallback);
- }
- void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- const btCollisionObjectWrapper* collisionObjectWrap,
- RayResultCallback& resultCallback)
- {
- btSphereShape pointShape(btScalar(0.0));
- pointShape.setMargin(0.f);
- const btConvexShape* castShape = &pointShape;
- const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape();
- const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform();
- if (collisionShape->isConvex())
- {
- // BT_PROFILE("rayTestConvex");
- btConvexCast::CastResult castResult;
- castResult.m_fraction = resultCallback.m_closestHitFraction;
- btConvexShape* convexShape = (btConvexShape*)collisionShape;
- btVoronoiSimplexSolver simplexSolver;
- btSubsimplexConvexCast subSimplexConvexCaster(castShape, convexShape, &simplexSolver);
- btGjkConvexCast gjkConvexCaster(castShape, convexShape, &simplexSolver);
- //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
- btConvexCast* convexCasterPtr = 0;
- //use kF_UseSubSimplexConvexCastRaytest by default
- if (resultCallback.m_flags & btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest)
- convexCasterPtr = &gjkConvexCaster;
- else
- convexCasterPtr = &subSimplexConvexCaster;
- btConvexCast& convexCaster = *convexCasterPtr;
- if (convexCaster.calcTimeOfImpact(rayFromTrans, rayToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
- {
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- if (castResult.m_fraction < resultCallback.m_closestHitFraction)
- {
- //todo: figure out what this is about. When is rayFromTest.getBasis() not identity?
- #ifdef USE_SUBSIMPLEX_CONVEX_CAST
- //rotate normal into worldspace
- castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
- #endif //USE_SUBSIMPLEX_CONVEX_CAST
- castResult.m_normal.normalize();
- btCollisionWorld::LocalRayResult localRayResult(
- collisionObjectWrap->getCollisionObject(),
- 0,
- castResult.m_normal,
- castResult.m_fraction);
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- if (collisionShape->isConcave())
- {
- //ConvexCast::CastResult
- struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
- {
- btCollisionWorld::RayResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- const btConcaveShape* m_triangleMesh;
- btTransform m_colObjWorldTransform;
- BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
- btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, const btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) : //@BP Mod
- btTriangleRaycastCallback(from, to, resultCallback->m_flags),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh),
- m_colObjWorldTransform(colObjWorldTransform)
- {
- }
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
- btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
- btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
- &shapeInfo,
- hitNormalWorld,
- hitFraction);
- bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
- }
- };
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
- btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
- // BT_PROFILE("rayTestConcave");
- if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- ///optimized version for btBvhTriangleMeshShape
- btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
- BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
- triangleMesh->performRaycast(&rcb, rayFromLocal, rayToLocal);
- }
- else if (collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- ///optimized version for btScaledBvhTriangleMeshShape
- btScaledBvhTriangleMeshShape* scaledTriangleMesh = (btScaledBvhTriangleMeshShape*)collisionShape;
- btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)scaledTriangleMesh->getChildShape();
- //scale the ray positions
- btVector3 scale = scaledTriangleMesh->getLocalScaling();
- btVector3 rayFromLocalScaled = rayFromLocal / scale;
- btVector3 rayToLocalScaled = rayToLocal / scale;
- //perform raycast in the underlying btBvhTriangleMeshShape
- BridgeTriangleRaycastCallback rcb(rayFromLocalScaled, rayToLocalScaled, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
- triangleMesh->performRaycast(&rcb, rayFromLocalScaled, rayToLocalScaled);
- }
- else if (((resultCallback.m_flags&btTriangleRaycastCallback::kF_DisableHeightfieldAccelerator)==0)
- && collisionShape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE
- )
- {
- ///optimized version for btHeightfieldTerrainShape
- btHeightfieldTerrainShape* heightField = (btHeightfieldTerrainShape*)collisionShape;
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
- btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
- BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), heightField, colObjWorldTransform);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
- heightField->performRaycast(&rcb, rayFromLocal, rayToLocal);
- }
- else
- {
- //generic (slower) case
- btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
- btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
- //ConvexCast::CastResult
- struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
- {
- btCollisionWorld::RayResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btConcaveShape* m_triangleMesh;
- btTransform m_colObjWorldTransform;
- BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
- btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) : //@BP Mod
- btTriangleRaycastCallback(from, to, resultCallback->m_flags),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh),
- m_colObjWorldTransform(colObjWorldTransform)
- {
- }
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
- btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
- btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
- &shapeInfo,
- hitNormalWorld,
- hitFraction);
- bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
- }
- };
- BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
- btVector3 rayAabbMinLocal = rayFromLocal;
- rayAabbMinLocal.setMin(rayToLocal);
- btVector3 rayAabbMaxLocal = rayFromLocal;
- rayAabbMaxLocal.setMax(rayToLocal);
- concaveShape->processAllTriangles(&rcb, rayAabbMinLocal, rayAabbMaxLocal);
- }
- }
- else
- {
- // BT_PROFILE("rayTestCompound");
- if (collisionShape->isCompound())
- {
- struct LocalInfoAdder2 : public RayResultCallback
- {
- RayResultCallback* m_userCallback;
- int m_i;
- LocalInfoAdder2(int i, RayResultCallback* user)
- : m_userCallback(user), m_i(i)
- {
- m_closestHitFraction = m_userCallback->m_closestHitFraction;
- m_flags = m_userCallback->m_flags;
- }
- virtual bool needsCollision(btBroadphaseProxy* p) const
- {
- return m_userCallback->needsCollision(p);
- }
- virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& r, bool b)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = -1;
- shapeInfo.m_triangleIndex = m_i;
- if (r.m_localShapeInfo == NULL)
- r.m_localShapeInfo = &shapeInfo;
- const btScalar result = m_userCallback->addSingleResult(r, b);
- m_closestHitFraction = m_userCallback->m_closestHitFraction;
- return result;
- }
- };
- struct RayTester : btDbvt::ICollide
- {
- const btCollisionObject* m_collisionObject;
- const btCompoundShape* m_compoundShape;
- const btTransform& m_colObjWorldTransform;
- const btTransform& m_rayFromTrans;
- const btTransform& m_rayToTrans;
- RayResultCallback& m_resultCallback;
- RayTester(const btCollisionObject* collisionObject,
- const btCompoundShape* compoundShape,
- const btTransform& colObjWorldTransform,
- const btTransform& rayFromTrans,
- const btTransform& rayToTrans,
- RayResultCallback& resultCallback) : m_collisionObject(collisionObject),
- m_compoundShape(compoundShape),
- m_colObjWorldTransform(colObjWorldTransform),
- m_rayFromTrans(rayFromTrans),
- m_rayToTrans(rayToTrans),
- m_resultCallback(resultCallback)
- {
- }
- void ProcessLeaf(int i)
- {
- const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
- const btTransform& childTrans = m_compoundShape->getChildTransform(i);
- btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
- btCollisionObjectWrapper tmpOb(0, childCollisionShape, m_collisionObject, childWorldTrans, -1, i);
- // replace collision shape so that callback can determine the triangle
- LocalInfoAdder2 my_cb(i, &m_resultCallback);
- rayTestSingleInternal(
- m_rayFromTrans,
- m_rayToTrans,
- &tmpOb,
- my_cb);
- }
- void Process(const btDbvtNode* leaf)
- {
- ProcessLeaf(leaf->dataAsInt);
- }
- };
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
- const btDbvt* dbvt = compoundShape->getDynamicAabbTree();
- RayTester rayCB(
- collisionObjectWrap->getCollisionObject(),
- compoundShape,
- colObjWorldTransform,
- rayFromTrans,
- rayToTrans,
- resultCallback);
- #ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
- if (dbvt)
- {
- btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin();
- btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin();
- btDbvt::rayTest(dbvt->m_root, localRayFrom, localRayTo, rayCB);
- }
- else
- #endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
- {
- for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
- {
- rayCB.ProcessLeaf(i);
- }
- }
- }
- }
- }
- }
- void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration)
- {
- btCollisionObjectWrapper tmpOb(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
- btCollisionWorld::objectQuerySingleInternal(castShape, convexFromTrans, convexToTrans, &tmpOb, resultCallback, allowedPenetration);
- }
- void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
- const btCollisionObjectWrapper* colObjWrap,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration)
- {
- const btCollisionShape* collisionShape = colObjWrap->getCollisionShape();
- const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform();
- if (collisionShape->isConvex())
- {
- //BT_PROFILE("convexSweepConvex");
- btConvexCast::CastResult castResult;
- castResult.m_allowedPenetration = allowedPenetration;
- castResult.m_fraction = resultCallback.m_closestHitFraction; //btScalar(1.);//??
- btConvexShape* convexShape = (btConvexShape*)collisionShape;
- btVoronoiSimplexSolver simplexSolver;
- btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
- btContinuousConvexCollision convexCaster1(castShape, convexShape, &simplexSolver, &gjkEpaPenetrationSolver);
- //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
- //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
- btConvexCast* castPtr = &convexCaster1;
- if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
- {
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- if (castResult.m_fraction < resultCallback.m_closestHitFraction)
- {
- castResult.m_normal.normalize();
- btCollisionWorld::LocalConvexResult localConvexResult(
- colObjWrap->getCollisionObject(),
- 0,
- castResult.m_normal,
- castResult.m_hitPoint,
- castResult.m_fraction);
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- if (collisionShape->isConcave())
- {
- if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- //BT_PROFILE("convexSweepbtBvhTriangleMesh");
- btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
- btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
- // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
- btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
- //ConvexCast::CastResult
- struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
- {
- btCollisionWorld::ConvexResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btTriangleMeshShape* m_triangleMesh;
- BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
- btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld) : btTriangleConvexcastCallback(castShape, from, to, triangleToWorld, triangleMesh->getMargin()),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh)
- {
- }
- virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
- if (hitFraction <= m_resultCallback->m_closestHitFraction)
- {
- btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
- &shapeInfo,
- hitNormalLocal,
- hitPointLocal,
- hitFraction);
- bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
- }
- return hitFraction;
- }
- };
- BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
- tccb.m_hitFraction = resultCallback.m_closestHitFraction;
- tccb.m_allowedPenetration = allowedPenetration;
- btVector3 boxMinLocal, boxMaxLocal;
- castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
- triangleMesh->performConvexcast(&tccb, convexFromLocal, convexToLocal, boxMinLocal, boxMaxLocal);
- }
- else
- {
- if (collisionShape->getShapeType() == STATIC_PLANE_PROXYTYPE)
- {
- btConvexCast::CastResult castResult;
- castResult.m_allowedPenetration = allowedPenetration;
- castResult.m_fraction = resultCallback.m_closestHitFraction;
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*)collisionShape;
- btContinuousConvexCollision convexCaster1(castShape, planeShape);
- btConvexCast* castPtr = &convexCaster1;
- if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
- {
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- if (castResult.m_fraction < resultCallback.m_closestHitFraction)
- {
- castResult.m_normal.normalize();
- btCollisionWorld::LocalConvexResult localConvexResult(
- colObjWrap->getCollisionObject(),
- 0,
- castResult.m_normal,
- castResult.m_hitPoint,
- castResult.m_fraction);
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- //BT_PROFILE("convexSweepConcave");
- btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
- btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
- // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
- btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
- //ConvexCast::CastResult
- struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
- {
- btCollisionWorld::ConvexResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btConcaveShape* m_triangleMesh;
- BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
- btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& triangleToWorld) : btTriangleConvexcastCallback(castShape, from, to, triangleToWorld, triangleMesh->getMargin()),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh)
- {
- }
- virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
- if (hitFraction <= m_resultCallback->m_closestHitFraction)
- {
- btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
- &shapeInfo,
- hitNormalLocal,
- hitPointLocal,
- hitFraction);
- bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
- }
- return hitFraction;
- }
- };
- BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
- tccb.m_hitFraction = resultCallback.m_closestHitFraction;
- tccb.m_allowedPenetration = allowedPenetration;
- btVector3 boxMinLocal, boxMaxLocal;
- castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
- btVector3 rayAabbMinLocal = convexFromLocal;
- rayAabbMinLocal.setMin(convexToLocal);
- btVector3 rayAabbMaxLocal = convexFromLocal;
- rayAabbMaxLocal.setMax(convexToLocal);
- rayAabbMinLocal += boxMinLocal;
- rayAabbMaxLocal += boxMaxLocal;
- concaveShape->processAllTriangles(&tccb, rayAabbMinLocal, rayAabbMaxLocal);
- }
- }
- }
- else
- {
- if (collisionShape->isCompound())
- {
- struct btCompoundLeafCallback : btDbvt::ICollide
- {
- btCompoundLeafCallback(
- const btCollisionObjectWrapper* colObjWrap,
- const btConvexShape* castShape,
- const btTransform& convexFromTrans,
- const btTransform& convexToTrans,
- btScalar allowedPenetration,
- const btCompoundShape* compoundShape,
- const btTransform& colObjWorldTransform,
- ConvexResultCallback& resultCallback)
- : m_colObjWrap(colObjWrap),
- m_castShape(castShape),
- m_convexFromTrans(convexFromTrans),
- m_convexToTrans(convexToTrans),
- m_allowedPenetration(allowedPenetration),
- m_compoundShape(compoundShape),
- m_colObjWorldTransform(colObjWorldTransform),
- m_resultCallback(resultCallback)
- {
- }
- const btCollisionObjectWrapper* m_colObjWrap;
- const btConvexShape* m_castShape;
- const btTransform& m_convexFromTrans;
- const btTransform& m_convexToTrans;
- btScalar m_allowedPenetration;
- const btCompoundShape* m_compoundShape;
- const btTransform& m_colObjWorldTransform;
- ConvexResultCallback& m_resultCallback;
- public:
- void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
- {
- btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
- struct LocalInfoAdder : public ConvexResultCallback
- {
- ConvexResultCallback* m_userCallback;
- int m_i;
- LocalInfoAdder(int i, ConvexResultCallback* user)
- : m_userCallback(user), m_i(i)
- {
- m_closestHitFraction = m_userCallback->m_closestHitFraction;
- }
- virtual bool needsCollision(btBroadphaseProxy* p) const
- {
- return m_userCallback->needsCollision(p);
- }
- virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = -1;
- shapeInfo.m_triangleIndex = m_i;
- if (r.m_localShapeInfo == NULL)
- r.m_localShapeInfo = &shapeInfo;
- const btScalar result = m_userCallback->addSingleResult(r, b);
- m_closestHitFraction = m_userCallback->m_closestHitFraction;
- return result;
- }
- };
- LocalInfoAdder my_cb(index, &m_resultCallback);
- btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index);
- objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration);
- }
- void Process(const btDbvtNode* leaf)
- {
- // Processing leaf node
- int index = leaf->dataAsInt;
- btTransform childTrans = m_compoundShape->getChildTransform(index);
- const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index);
- ProcessChild(index, childTrans, childCollisionShape);
- }
- };
- BT_PROFILE("convexSweepCompound");
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
- btVector3 fromLocalAabbMin, fromLocalAabbMax;
- btVector3 toLocalAabbMin, toLocalAabbMax;
- castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax);
- castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax);
- fromLocalAabbMin.setMin(toLocalAabbMin);
- fromLocalAabbMax.setMax(toLocalAabbMax);
- btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans,
- allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
- const btDbvt* tree = compoundShape->getDynamicAabbTree();
- if (tree)
- {
- const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
- tree->collideTV(tree->m_root, bounds, callback);
- }
- else
- {
- int i;
- for (i = 0; i < compoundShape->getNumChildShapes(); i++)
- {
- const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
- btTransform childTrans = compoundShape->getChildTransform(i);
- callback.ProcessChild(i, childTrans, childCollisionShape);
- }
- }
- }
- }
- }
- }
- struct btSingleRayCallback : public btBroadphaseRayCallback
- {
- btVector3 m_rayFromWorld;
- btVector3 m_rayToWorld;
- btTransform m_rayFromTrans;
- btTransform m_rayToTrans;
- btVector3 m_hitNormal;
- const btCollisionWorld* m_world;
- btCollisionWorld::RayResultCallback& m_resultCallback;
- btSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btCollisionWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
- : m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld),
- m_world(world),
- m_resultCallback(resultCallback)
- {
- m_rayFromTrans.setIdentity();
- m_rayFromTrans.setOrigin(m_rayFromWorld);
- m_rayToTrans.setIdentity();
- m_rayToTrans.setOrigin(m_rayToWorld);
- btVector3 rayDir = (rayToWorld - rayFromWorld);
- rayDir.normalize();
- ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
- m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
- m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
- m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- m_signs[0] = m_rayDirectionInverse[0] < 0.0;
- m_signs[1] = m_rayDirectionInverse[1] < 0.0;
- m_signs[2] = m_rayDirectionInverse[2] < 0.0;
- m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
- }
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- ///terminate further ray tests, once the closestHitFraction reached zero
- if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
- return false;
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
- #if 0
- #ifdef RECALCULATE_AABB
- btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
- #else
- //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
- const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
- const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
- #endif
- #endif
- //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
- //culling already done by broadphase
- //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
- {
- m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback);
- }
- }
- return true;
- }
- };
- void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
- {
- //BT_PROFILE("rayTest");
- /// use the broadphase to accelerate the search for objects, based on their aabb
- /// and for each object with ray-aabb overlap, perform an exact ray test
- btSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
- #ifndef USE_BRUTEFORCE_RAYBROADPHASE
- m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
- #else
- for (int i = 0; i < this->getNumCollisionObjects(); i++)
- {
- rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
- }
- #endif //USE_BRUTEFORCE_RAYBROADPHASE
- }
- struct btSingleSweepCallback : public btBroadphaseRayCallback
- {
- btTransform m_convexFromTrans;
- btTransform m_convexToTrans;
- btVector3 m_hitNormal;
- const btCollisionWorld* m_world;
- btCollisionWorld::ConvexResultCallback& m_resultCallback;
- btScalar m_allowedCcdPenetration;
- const btConvexShape* m_castShape;
- btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans, const btCollisionWorld* world, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedPenetration)
- : m_convexFromTrans(convexFromTrans),
- m_convexToTrans(convexToTrans),
- m_world(world),
- m_resultCallback(resultCallback),
- m_allowedCcdPenetration(allowedPenetration),
- m_castShape(castShape)
- {
- btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin() - m_convexFromTrans.getOrigin());
- btVector3 rayDir = unnormalizedRayDir.fuzzyZero() ? btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)) : unnormalizedRayDir.normalized();
- ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
- m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
- m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
- m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- m_signs[0] = m_rayDirectionInverse[0] < 0.0;
- m_signs[1] = m_rayDirectionInverse[1] < 0.0;
- m_signs[2] = m_rayDirectionInverse[2] < 0.0;
- m_lambda_max = rayDir.dot(unnormalizedRayDir);
- }
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- ///terminate further convex sweep tests, once the closestHitFraction reached zero
- if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
- return false;
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- m_world->objectQuerySingle(m_castShape, m_convexFromTrans, m_convexToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback,
- m_allowedCcdPenetration);
- }
- return true;
- }
- };
- void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
- {
- BT_PROFILE("convexSweepTest");
- /// use the broadphase to accelerate the search for objects, based on their aabb
- /// and for each object with ray-aabb overlap, perform an exact ray test
- /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
- btTransform convexFromTrans, convexToTrans;
- convexFromTrans = convexFromWorld;
- convexToTrans = convexToWorld;
- btVector3 castShapeAabbMin, castShapeAabbMax;
- /* Compute AABB that encompasses angular movement */
- {
- btVector3 linVel, angVel;
- btTransformUtil::calculateVelocity(convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
- btVector3 zeroLinVel;
- zeroLinVel.setValue(0, 0, 0);
- btTransform R;
- R.setIdentity();
- R.setRotation(convexFromTrans.getRotation());
- castShape->calculateTemporalAabb(R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
- }
- #ifndef USE_BRUTEFORCE_RAYBROADPHASE
- btSingleSweepCallback convexCB(castShape, convexFromWorld, convexToWorld, this, resultCallback, allowedCcdPenetration);
- m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(), convexToTrans.getOrigin(), convexCB, castShapeAabbMin, castShapeAabbMax);
- #else
- /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
- // do a ray-shape query using convexCaster (CCD)
- int i;
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* collisionObject = m_collisionObjects[i];
- //only perform raycast if filterMask matches
- if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- btVector3 collisionObjectAabbMin, collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(), collisionObjectAabbMin, collisionObjectAabbMax);
- AabbExpand(collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
- btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
- btVector3 hitNormal;
- if (btRayAabb(convexFromWorld.getOrigin(), convexToWorld.getOrigin(), collisionObjectAabbMin, collisionObjectAabbMax, hitLambda, hitNormal))
- {
- objectQuerySingle(castShape, convexFromTrans, convexToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- resultCallback,
- allowedCcdPenetration);
- }
- }
- }
- #endif //USE_BRUTEFORCE_RAYBROADPHASE
- }
- struct btBridgedManifoldResult : public btManifoldResult
- {
- btCollisionWorld::ContactResultCallback& m_resultCallback;
- btBridgedManifoldResult(const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap, btCollisionWorld::ContactResultCallback& resultCallback)
- : btManifoldResult(obj0Wrap, obj1Wrap),
- m_resultCallback(resultCallback)
- {
- }
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
- {
- bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
- btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
- btVector3 localA;
- btVector3 localB;
- if (isSwapped)
- {
- localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
- localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
- }
- else
- {
- localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
- localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
- }
- btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
- newPt.m_positionWorldOnA = pointA;
- newPt.m_positionWorldOnB = pointInWorld;
- //BP mod, store contact triangles.
- if (isSwapped)
- {
- newPt.m_partId0 = m_partId1;
- newPt.m_partId1 = m_partId0;
- newPt.m_index0 = m_index1;
- newPt.m_index1 = m_index0;
- }
- else
- {
- newPt.m_partId0 = m_partId0;
- newPt.m_partId1 = m_partId1;
- newPt.m_index0 = m_index0;
- newPt.m_index1 = m_index1;
- }
- //experimental feature info, for per-triangle material etc.
- const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
- const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
- m_resultCallback.addSingleResult(newPt, obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
- }
- };
- struct btSingleContactCallback : public btBroadphaseAabbCallback
- {
- btCollisionObject* m_collisionObject;
- btCollisionWorld* m_world;
- btCollisionWorld::ContactResultCallback& m_resultCallback;
- btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world, btCollisionWorld::ContactResultCallback& resultCallback)
- : m_collisionObject(collisionObject),
- m_world(world),
- m_resultCallback(resultCallback)
- {
- }
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
- if (collisionObject == m_collisionObject)
- return true;
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- btCollisionObjectWrapper ob0(0, m_collisionObject->getCollisionShape(), m_collisionObject, m_collisionObject->getWorldTransform(), -1, -1);
- btCollisionObjectWrapper ob1(0, collisionObject->getCollisionShape(), collisionObject, collisionObject->getWorldTransform(), -1, -1);
- btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0, &ob1, 0, BT_CLOSEST_POINT_ALGORITHMS);
- if (algorithm)
- {
- btBridgedManifoldResult contactPointResult(&ob0, &ob1, m_resultCallback);
- //discrete collision detection query
- algorithm->processCollision(&ob0, &ob1, m_world->getDispatchInfo(), &contactPointResult);
- algorithm->~btCollisionAlgorithm();
- m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
- }
- }
- return true;
- }
- };
- ///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
- ///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
- void btCollisionWorld::contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback)
- {
- btVector3 aabbMin, aabbMax;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), aabbMin, aabbMax);
- btSingleContactCallback contactCB(colObj, this, resultCallback);
- m_broadphasePairCache->aabbTest(aabbMin, aabbMax, contactCB);
- }
- ///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
- ///it reports one or more contact points (including the one with deepest penetration)
- void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
- {
- btCollisionObjectWrapper obA(0, colObjA->getCollisionShape(), colObjA, colObjA->getWorldTransform(), -1, -1);
- btCollisionObjectWrapper obB(0, colObjB->getCollisionShape(), colObjB, colObjB->getWorldTransform(), -1, -1);
- btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA, &obB, 0, BT_CLOSEST_POINT_ALGORITHMS);
- if (algorithm)
- {
- btBridgedManifoldResult contactPointResult(&obA, &obB, resultCallback);
- contactPointResult.m_closestPointDistanceThreshold = resultCallback.m_closestDistanceThreshold;
- //discrete collision detection query
- algorithm->processCollision(&obA, &obB, getDispatchInfo(), &contactPointResult);
- algorithm->~btCollisionAlgorithm();
- getDispatcher()->freeCollisionAlgorithm(algorithm);
- }
- }
- class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
- {
- btIDebugDraw* m_debugDrawer;
- btVector3 m_color;
- btTransform m_worldTrans;
- public:
- DebugDrawcallback(btIDebugDraw* debugDrawer, const btTransform& worldTrans, const btVector3& color) : m_debugDrawer(debugDrawer),
- m_color(color),
- m_worldTrans(worldTrans)
- {
- }
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- processTriangle(triangle, partId, triangleIndex);
- }
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- (void)partId;
- (void)triangleIndex;
- btVector3 wv0, wv1, wv2;
- wv0 = m_worldTrans * triangle[0];
- wv1 = m_worldTrans * triangle[1];
- wv2 = m_worldTrans * triangle[2];
- btVector3 center = (wv0 + wv1 + wv2) * btScalar(1. / 3.);
- if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
- {
- btVector3 normal = (wv1 - wv0).cross(wv2 - wv0);
- normal.normalize();
- btVector3 normalColor(1, 1, 0);
- m_debugDrawer->drawLine(center, center + normal, normalColor);
- }
- m_debugDrawer->drawTriangle(wv0, wv1, wv2, m_color, 1.0);
- }
- };
- void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
- {
- // Draw a small simplex at the center of the object
- if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames)
- {
- getDebugDrawer()->drawTransform(worldTransform, .1);
- }
- if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
- {
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
- for (int i = compoundShape->getNumChildShapes() - 1; i >= 0; i--)
- {
- btTransform childTrans = compoundShape->getChildTransform(i);
- const btCollisionShape* colShape = compoundShape->getChildShape(i);
- debugDrawObject(worldTransform * childTrans, colShape, color);
- }
- }
- else
- {
- switch (shape->getShapeType())
- {
- case BOX_SHAPE_PROXYTYPE:
- {
- const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
- btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
- getDebugDrawer()->drawBox(-halfExtents, halfExtents, worldTransform, color);
- break;
- }
- case SPHERE_SHAPE_PROXYTYPE:
- {
- const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
- btScalar radius = sphereShape->getMargin(); //radius doesn't include the margin, so draw with margin
- getDebugDrawer()->drawSphere(radius, worldTransform, color);
- break;
- }
- case MULTI_SPHERE_SHAPE_PROXYTYPE:
- {
- const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
- btTransform childTransform;
- childTransform.setIdentity();
- for (int i = multiSphereShape->getSphereCount() - 1; i >= 0; i--)
- {
- childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
- getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform * childTransform, color);
- }
- break;
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
- btScalar radius = capsuleShape->getRadius();
- btScalar halfHeight = capsuleShape->getHalfHeight();
- int upAxis = capsuleShape->getUpAxis();
- getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
- break;
- }
- case CONE_SHAPE_PROXYTYPE:
- {
- const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
- btScalar radius = coneShape->getRadius(); //+coneShape->getMargin();
- btScalar height = coneShape->getHeight(); //+coneShape->getMargin();
- int upAxis = coneShape->getConeUpIndex();
- getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
- break;
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
- int upAxis = cylinder->getUpAxis();
- btScalar radius = cylinder->getRadius();
- btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
- getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
- break;
- }
- case STATIC_PLANE_PROXYTYPE:
- {
- const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
- btScalar planeConst = staticPlaneShape->getPlaneConstant();
- const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
- getDebugDrawer()->drawPlane(planeNormal, planeConst, worldTransform, color);
- break;
- }
- default:
- {
- /// for polyhedral shapes
- if (shape->isPolyhedral())
- {
- btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*)shape;
- int i;
- if (polyshape->getConvexPolyhedron())
- {
- const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
- for (i = 0; i < poly->m_faces.size(); i++)
- {
- btVector3 centroid(0, 0, 0);
- int numVerts = poly->m_faces[i].m_indices.size();
- if (numVerts)
- {
- int lastV = poly->m_faces[i].m_indices[numVerts - 1];
- for (int v = 0; v < poly->m_faces[i].m_indices.size(); v++)
- {
- int curVert = poly->m_faces[i].m_indices[v];
- centroid += poly->m_vertices[curVert];
- getDebugDrawer()->drawLine(worldTransform * poly->m_vertices[lastV], worldTransform * poly->m_vertices[curVert], color);
- lastV = curVert;
- }
- }
- centroid *= btScalar(1.f) / btScalar(numVerts);
- if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
- {
- btVector3 normalColor(1, 1, 0);
- btVector3 faceNormal(poly->m_faces[i].m_plane[0], poly->m_faces[i].m_plane[1], poly->m_faces[i].m_plane[2]);
- getDebugDrawer()->drawLine(worldTransform * centroid, worldTransform * (centroid + faceNormal), normalColor);
- }
- }
- }
- else
- {
- for (i = 0; i < polyshape->getNumEdges(); i++)
- {
- btVector3 a, b;
- polyshape->getEdge(i, a, b);
- btVector3 wa = worldTransform * a;
- btVector3 wb = worldTransform * b;
- getDebugDrawer()->drawLine(wa, wb, color);
- }
- }
- }
- if (shape->isConcave())
- {
- btConcaveShape* concaveMesh = (btConcaveShape*)shape;
- ///@todo pass camera, for some culling? no -> we are not a graphics lib
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
- concaveMesh->processAllTriangles(&drawCallback, aabbMin, aabbMax);
- }
- if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
- {
- btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*)shape;
- //todo: pass camera for some culling
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- //DebugDrawcallback drawCallback;
- DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
- convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback, aabbMin, aabbMax);
- }
- }
- }
- }
- }
- void btCollisionWorld::debugDrawWorld()
- {
- if (getDebugDrawer())
- {
- getDebugDrawer()->clearLines();
- btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors();
- if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
- {
- if (getDispatcher())
- {
- int numManifolds = getDispatcher()->getNumManifolds();
- for (int i = 0; i < numManifolds; i++)
- {
- btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
- //btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
- //btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
- int numContacts = contactManifold->getNumContacts();
- for (int j = 0; j < numContacts; j++)
- {
- btManifoldPoint& cp = contactManifold->getContactPoint(j);
- getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB, cp.m_normalWorldOnB, cp.getDistance(), cp.getLifeTime(), defaultColors.m_contactPoint);
- }
- }
- }
- }
- if ((getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)))
- {
- int i;
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT) == 0)
- {
- if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
- {
- btVector3 color(btScalar(0.4), btScalar(0.4), btScalar(0.4));
- switch (colObj->getActivationState())
- {
- case ACTIVE_TAG:
- color = defaultColors.m_activeObject;
- break;
- case ISLAND_SLEEPING:
- color = defaultColors.m_deactivatedObject;
- break;
- case WANTS_DEACTIVATION:
- color = defaultColors.m_wantsDeactivationObject;
- break;
- case DISABLE_DEACTIVATION:
- color = defaultColors.m_disabledDeactivationObject;
- break;
- case DISABLE_SIMULATION:
- color = defaultColors.m_disabledSimulationObject;
- break;
- default:
- {
- color = btVector3(btScalar(.3), btScalar(0.3), btScalar(0.3));
- }
- };
- colObj->getCustomDebugColor(color);
- debugDrawObject(colObj->getWorldTransform(), colObj->getCollisionShape(), color);
- }
- if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
- {
- btVector3 minAabb, maxAabb;
- btVector3 colorvec = defaultColors.m_aabb;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
- btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
- minAabb -= contactThreshold;
- maxAabb += contactThreshold;
- btVector3 minAabb2, maxAabb2;
- if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
- {
- colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
- minAabb2 -= contactThreshold;
- maxAabb2 += contactThreshold;
- minAabb.setMin(minAabb2);
- maxAabb.setMax(maxAabb2);
- }
- m_debugDrawer->drawAabb(minAabb, maxAabb, colorvec);
- }
- }
- }
- }
- }
- }
- void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
- {
- int i;
- ///keep track of shapes already serialized
- btHashMap<btHashPtr, btCollisionShape*> serializedShapes;
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btCollisionShape* shape = colObj->getCollisionShape();
- if (!serializedShapes.find(shape))
- {
- serializedShapes.insert(shape, shape);
- shape->serializeSingleShape(serializer);
- }
- }
- //serialize all collision objects
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if (colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT)
- {
- colObj->serializeSingleObject(serializer);
- }
- }
- }
- void btCollisionWorld::serializeContactManifolds(btSerializer* serializer)
- {
- if (serializer->getSerializationFlags() & BT_SERIALIZE_CONTACT_MANIFOLDS)
- {
- int numManifolds = getDispatcher()->getNumManifolds();
- for (int i = 0; i < numManifolds; i++)
- {
- const btPersistentManifold* manifold = getDispatcher()->getInternalManifoldPointer()[i];
- //don't serialize empty manifolds, they just take space
- //(may have to do it anyway if it destroys determinism)
- if (manifold->getNumContacts() == 0)
- continue;
- btChunk* chunk = serializer->allocate(manifold->calculateSerializeBufferSize(), 1);
- const char* structType = manifold->serialize(manifold, chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_CONTACTMANIFOLD_CODE, (void*)manifold);
- }
- }
- }
- void btCollisionWorld::serialize(btSerializer* serializer)
- {
- serializer->startSerialization();
- serializeCollisionObjects(serializer);
- serializeContactManifolds(serializer);
- serializer->finishSerialization();
- }
|