void BenchmarkDemo::initPhysics() { setCameraDistance(btScalar(100.)); ///collision configuration contains default setup for memory, collision setup btDefaultCollisionConstructionInfo cci; cci.m_defaultMaxPersistentManifoldPoolSize = 32768; m_collisionConfiguration = new btDefaultCollisionConfiguration(cci); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION); #if USE_PARALLEL_DISPATCHER_BENCHMARK int maxNumOutstandingTasks = 4; #ifdef _WIN32 Win32ThreadSupport* threadSupportCollision = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( "collision",processCollisionTask, createCollisionLocalStoreMemory,maxNumOutstandingTasks)); #elif defined (USE_PTHREADS) PosixThreadSupport::ThreadConstructionInfo collisionConstructionInfo( "collision",processCollisionTask, createCollisionLocalStoreMemory,maxNumOutstandingTasks); PosixThreadSupport* threadSupportCollision = new PosixThreadSupport(collisionConstructionInfo); #endif //SequentialThreadSupport::SequentialThreadConstructionInfo sci("spuCD", processCollisionTask, createCollisionLocalStoreMemory); //SequentialThreadSupport* seq = new SequentialThreadSupport(sci); m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupportCollision,1,m_collisionConfiguration); #endif ///the maximum size of the collision world. Make sure objects stay within these boundaries ///Don't make the world AABB size too large, it will harm simulation quality and performance btVector3 worldAabbMin(-1000,-1000,-1000); btVector3 worldAabbMax(1000,1000,1000); btHashedOverlappingPairCache* pairCache = new btHashedOverlappingPairCache(); m_overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,3500,pairCache); // m_overlappingPairCache = new btSimpleBroadphase(); // m_overlappingPairCache = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) #ifdef USE_PARALLEL_DISPATCHER_BENCHMARK btThreadSupportInterface* thread = createSolverThreadSupport(4); btConstraintSolver* sol = new btParallelConstraintSolver(thread); #else btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; #endif //USE_PARALLEL_DISPATCHER_BENCHMARK m_solver = sol; btDiscreteDynamicsWorld* dynamicsWorld; m_dynamicsWorld = dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_solver,m_collisionConfiguration); #ifdef USE_PARALLEL_DISPATCHER_BENCHMARK dynamicsWorld->getSimulationIslandManager()->setSplitIslands(false); #endif //USE_PARALLEL_DISPATCHER_BENCHMARK ///the following 3 lines increase the performance dramatically, with a little bit of loss of quality m_dynamicsWorld->getSolverInfo().m_solverMode |=SOLVER_ENABLE_FRICTION_DIRECTION_CACHING; //don't recalculate friction values each frame dynamicsWorld->getSolverInfo().m_numIterations = 5; //few solver iterations m_defaultContactProcessingThreshold = 0.f;//used when creating bodies: body->setContactProcessingThreshold(...); m_dynamicsWorld->setGravity(btVector3(0,-10,0)); if (m_benchmark<5) { ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(250.),btScalar(50.),btScalar(250.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-50,0)); //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: { btScalar mass(0.); //rigidbody is dynamic if and only if mass is non zero, otherwise static bool isDynamic = (mass != 0.f); btVector3 localInertia(0,0,0); if (isDynamic) groundShape->calculateLocalInertia(mass,localInertia); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } } switch (m_benchmark) { case 1: { createTest1(); break; } case 2: { createTest2(); break; } case 3: { createTest3(); break; } case 4: { createTest4(); break; } case 5: { createTest5(); break; } case 6: { createTest6(); break; } case 7: { createTest7(); break; } default: { } } clientResetScene(); }
DynamicsWorld::DynamicsWorld() { m_threadSupportSolver = 0; m_threadSupportCollision = 0; int maxNumOutstandingTasks = std::thread::hardware_concurrency(); if (maxNumOutstandingTasks == 0) maxNumOutstandingTasks = 4; Debug::Log("Hardware Concurrency: " + std::to_string(std::thread::hardware_concurrency())); #ifdef SEQUENTIAL SequentialThreadSupport::SequentialThreadConstructionInfo colCI("collision", processCollisionTask, createCollisionLocalStoreMemory); m_threadSupportCollision = new SequentialThreadSupport(colCI); #else m_threadSupportCollision = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( "collision", processCollisionTask, createCollisionLocalStoreMemory, maxNumOutstandingTasks)); #endif ///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration. btDefaultCollisionConstructionInfo cci; cci.m_defaultMaxPersistentManifoldPoolSize = 32768; collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(cci); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) //dispatcher = new btCollisionDispatcher(collisionConfiguration); dispatcher = new SpuGatheringCollisionDispatcher(m_threadSupportCollision, maxNumOutstandingTasks, collisionConfiguration); softBodyWorldInfo.m_dispatcher = dispatcher; ///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep. overlappingPairCache = new btDbvtBroadphase(); softBodyWorldInfo.m_broadphase = overlappingPairCache; ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) //solver = new btSequentialImpulseConstraintSolver; #ifdef SEQUENTIAL solver = new btSequentialImpulseConstraintSolver(); #else m_threadSupportSolver = createSolverThreadSupport(maxNumOutstandingTasks); solver = new btParallelConstraintSolver(m_threadSupportSolver); //this solver requires the contacts to be in a contiguous pool, so avoid dynamic allocation dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION); #endif dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration); // , softBodySolver); dynamicsWorld->getSimulationIslandManager()->setSplitIslands(false); dynamicsWorld->getSolverInfo().m_numIterations = 4; dynamicsWorld->getSolverInfo().m_solverMode = SOLVER_SIMD + SOLVER_USE_WARMSTARTING;//+SOLVER_RANDMIZE_ORDER; dynamicsWorld->getDispatchInfo().m_enableSPU = true; dynamicsWorld->setGravity(btVector3(0,-9.8f,0)); softBodyWorldInfo.m_gravity.setValue(0, -9.8f, 0); softBodyWorldInfo.m_sparsesdf.Initialize(); }
void jmePhysicsSpace::createPhysicsSpace(jfloat minX, jfloat minY, jfloat minZ, jfloat maxX, jfloat maxY, jfloat maxZ, jint broadphaseId, jboolean threading) { // collision configuration contains default setup for memory, collision setup btDefaultCollisionConstructionInfo cci; // if(threading){ // cci.m_defaultMaxPersistentManifoldPoolSize = 32768; // } collisionConfiguration = new btDefaultCollisionConfiguration(cci); btVector3 min = btVector3(minX, minY, minZ); btVector3 max = btVector3(maxX, maxY, maxZ); // btBroadphaseInterface* broadphase; switch (broadphaseId) { case 0: broadphase = new btSimpleBroadphase(); break; case 1: broadphase = new btAxisSweep3(min, max); break; case 2: //TODO: 32bit! broadphase = new btAxisSweep3(min, max); break; case 3: broadphase = new btDbvtBroadphase(); break; case 4: // broadphase = new btGpu3DGridBroadphase( // min, max, // 20, 20, 20, // 10000, 1000, 25); break; } // btCollisionDispatcher* dispatcher; // btConstraintSolver* solver; // use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) if (threading) { btThreadSupportInterface* dispatchThreads = createDispatchThreadSupport(4); dispatcher = new SpuGatheringCollisionDispatcher(dispatchThreads, 4, collisionConfiguration); dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION); } else { dispatcher = new btCollisionDispatcher(collisionConfiguration); } // the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) if (threading) { btThreadSupportInterface* solverThreads = createSolverThreadSupport(4); solver = new btParallelConstraintSolver(solverThreads); } else { solver = new btSequentialImpulseConstraintSolver; } //create dynamics world btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); dynamicsWorld = world; dynamicsWorld->setWorldUserInfo(this); //parallel solver requires the contacts to be in a contiguous pool, so avoid dynamic allocation if (threading) { world->getSimulationIslandManager()->setSplitIslands(false); world->getSolverInfo().m_numIterations = 4; world->getSolverInfo().m_solverMode = SOLVER_SIMD + SOLVER_USE_WARMSTARTING; //+SOLVER_RANDMIZE_ORDER; world->getDispatchInfo().m_enableSPU = true; } ghostPairCallback = new btGhostPairCallback(); broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(ghostPairCallback); dynamicsWorld->setGravity(btVector3(0, -9.81f, 0)); struct jmeFilterCallback : public btOverlapFilterCallback { // return true when pairs need collision virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy * proxy1) const { // bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; // collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); if (collides) { btCollisionObject* co0 = (btCollisionObject*)proxy0->m_clientObject; btCollisionObject* co1 = (btCollisionObject*)proxy1->m_clientObject; jmeUserPointer *up0 = (jmeUserPointer*)co0 -> getUserPointer(); jmeUserPointer *up1 = (jmeUserPointer*)co1 -> getUserPointer(); if (up0 != NULL && up1 != NULL) { collides = (up0->group & up1->groups) != 0; collides = collides && (up1->group & up0->groups); //add some additional logic here that modified 'collides' return collides; } return false; } return collides; } }; dynamicsWorld->getPairCache()->setOverlapFilterCallback(new jmeFilterCallback()); dynamicsWorld->setInternalTickCallback(&jmePhysicsSpace::preTickCallback, static_cast<void *> (this), true); dynamicsWorld->setInternalTickCallback(&jmePhysicsSpace::postTickCallback, static_cast<void *> (this)); if (gContactProcessedCallback == NULL) { gContactProcessedCallback = &jmePhysicsSpace::contactProcessedCallback; } }