void SerializeDemo::initPhysics() { setTexturing(true); setShadows(true); setCameraDistance(btScalar(SCALING*50.)); setupEmptyDynamicsWorld(); btBulletWorldImporter* fileLoader = new btBulletWorldImporter(m_dynamicsWorld); // fileLoader->setVerboseMode(true); if (!fileLoader->loadFile("testFile.bullet")) { ///create a few basic rigid bodies and save them to testFile.bullet btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); btCollisionObject* groundObject = 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); groundObject = body; } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance int numSpheres = 2; btVector3 positions[2] = {btVector3(0.1f,0.2f,0.3f),btVector3(0.4f,0.5f,0.6f)}; btScalar radii[2] = {0.3f,0.4f}; btMultiSphereShape* colShape = new btMultiSphereShape(positions,radii,numSpheres); //btCollisionShape* colShape = new btCapsuleShapeZ(SCALING*1,SCALING*1); //btCollisionShape* colShape = new btCylinderShapeZ(btVector3(SCALING*1,SCALING*1,SCALING*1)); //btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); float start_x = START_POS_X - ARRAY_SIZE_X/2; float start_y = START_POS_Y; float start_z = START_POS_Z - ARRAY_SIZE_Z/2; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { startTransform.setOrigin(SCALING*btVector3( btScalar(2.0*i + start_x), btScalar(20+2.0*k + start_y), btScalar(2.0*j + start_z))); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); body->setActivationState(ISLAND_SLEEPING); m_dynamicsWorld->addRigidBody(body); body->setActivationState(ISLAND_SLEEPING); } } } } int maxSerializeBufferSize = 1024*1024*5; btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize); static char* groundName = "GroundName"; serializer->registerNameForPointer(groundObject, groundName); for (int i=0;i<m_collisionShapes.size();i++) { char* name = new char[20]; sprintf(name,"name%d",i); serializer->registerNameForPointer(m_collisionShapes[i],name); } btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*(btRigidBody*)getDynamicsWorld()->getCollisionObjectArray()[2],btVector3(0,1,0)); m_dynamicsWorld->addConstraint(p2p); const char* name = "constraintje"; serializer->registerNameForPointer(p2p,name); m_dynamicsWorld->serialize(serializer); FILE* f2 = fopen("testFile.bullet","wb"); fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1,f2); fclose(f2); } clientResetScene(); }
void BasicDemo::initPhysics() { setTexturing(true); setShadows(true); m_acceleratedRigidBodies = 0; setCameraDistance(btScalar(SCALING*20.)); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); #ifdef CL_PLATFORM_AMD m_dispatcher = new CustomCollisionDispatcher(m_collisionConfiguration, g_cxMainContext,g_clDevice,g_cqCommandQue); m_dispatcher->registerCollisionCreateFunc(CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_POLYHEDRAL_SHAPE_TYPE,new CustomConvexConvexPairCollision::CreateFunc(m_collisionConfiguration->getSimplexSolver(), m_collisionConfiguration->getPenetrationDepthSolver())); #else m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); #endif m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld->setGravity(btVector3(0,-10,0)); m_dynamicsWorld->setDebugDrawer(&sDebugDraw); ///create a few basic rigid bodies //btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); #ifdef CL_PLATFORM_AMD CustomConvexShape* groundShape = new CustomConvexShape(BoxVtx2,BoxVtxCount,3*sizeof(float)); #else btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0); #endif m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-1,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); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance //btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); #ifdef USE_CUSTOM_HEIGHTFIELD_SHAPE CustomConvexShape* colShape = new CustomConvexShape(BarrelVtx2,BarrelVtxCount2,6*sizeof(float)); //CustomConvexShape* colShape = new CustomConvexShape(BoxVtx,BoxVtxCount,3*sizeof(float)); #else btConvexHullShape* colShape = new btConvexHullShape(BarrelVtx2,BarrelVtxCount2,6*sizeof(float)); colShape->setLocalScaling(btVector3(0.9,0.9,0.9)); #endif //USE_CUSTOM_HEIGHTFIELD_SHAPE btScalar scale = 0.5f; //btScalar scale = 1.f; //next line is already called inside the CustomConvexShape constructor //colShape->initializePolyhedralFeatures(); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); float start_x = START_POS_X - ARRAY_SIZE_X/2; float start_y = START_POS_Y; float start_z = START_POS_Z - ARRAY_SIZE_Z/2; for (int k=0;k<ARRAY_SIZE_Y;k++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { for (int i=0;i<ARRAY_SIZE_X;i++) { { // if ((k>0) && ((j<2) || (j>(ARRAY_SIZE_Z-3)))) // continue; // if ((k>0) && ((i<2) || (i>(ARRAY_SIZE_X-3)))) // continue; startTransform.setOrigin(SCALING*btVector3( btScalar(scale*2.0*i + start_x), btScalar(scale*1+scale*2.0*k + start_y), btScalar(scale*2.0*j + start_z))); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody* body=0; if (0)//k==0) { btVector3 zeroInertia(0,0,0); btRigidBody::btRigidBodyConstructionInfo rbInfo(0.f,myMotionState,colShape,zeroInertia); body = new btRigidBody(rbInfo); } else { btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); body = new btRigidBody(rbInfo); } //m_acceleratedRigidBodies is used as a mapping to the accelerated rigid body index body->setCompanionId(m_acceleratedRigidBodies++); m_dynamicsWorld->addRigidBody(body); } } } } } }
void MultiDofDemo::initPhysics() { m_guiHelper->setUpAxis(1); if(g_firstInit) { m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraDistance(btScalar(10.*scaling)); m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraPitch(50); g_firstInit = false; } ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); //Use the btMultiBodyConstraintSolver for Featherstone btMultiBody support btMultiBodyConstraintSolver* sol = new btMultiBodyConstraintSolver; m_solver = sol; //use btMultiBodyDynamicsWorld for Featherstone btMultiBody support btMultiBodyDynamicsWorld* world = new btMultiBodyDynamicsWorld(m_dispatcher,m_broadphase,sol,m_collisionConfiguration); m_dynamicsWorld = world; // m_dynamicsWorld->setDebugDrawer(&gDebugDraw); m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); m_dynamicsWorld->setGravity(btVector3(0,-10,0)); ///create a few basic rigid bodies btVector3 groundHalfExtents(50,50,50); btCollisionShape* groundShape = new btBoxShape(groundHalfExtents); //groundShape->initializePolyhedralFeatures(); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-50,00)); ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// bool damping = true; bool gyro = true; int numLinks = 5; bool spherical = true; //set it ot false -to use 1DoF hinges instead of 3DoF sphericals bool multibodyOnly = false; bool canSleep = true; bool selfCollide = true; bool multibodyConstraint = false; btVector3 linkHalfExtents(0.05, 0.37, 0.1); btVector3 baseHalfExtents(0.05, 0.37, 0.1); btMultiBody* mbC = createFeatherstoneMultiBody_testMultiDof(world, numLinks, btVector3(-0.4f, 3.f, 0.f), linkHalfExtents, baseHalfExtents, spherical, g_floatingBase); //mbC->forceMultiDof(); //if !spherical, you can comment this line to check the 1DoF algorithm g_floatingBase = ! g_floatingBase; mbC->setCanSleep(canSleep); mbC->setHasSelfCollision(selfCollide); mbC->setUseGyroTerm(gyro); // if(!damping) { mbC->setLinearDamping(0.f); mbC->setAngularDamping(0.f); }else { mbC->setLinearDamping(0.1f); mbC->setAngularDamping(0.9f); } // m_dynamicsWorld->setGravity(btVector3(0, -9.81 ,0)); //m_dynamicsWorld->getSolverInfo().m_numIterations = 100; ////////////////////////////////////////////// if(numLinks > 0) { btScalar q0 = 45.f * SIMD_PI/ 180.f; if(!spherical) { mbC->setJointPosMultiDof(0, &q0); } else { btQuaternion quat0(btVector3(1, 1, 0).normalized(), q0); quat0.normalize(); mbC->setJointPosMultiDof(0, quat0); } } /// addColliders_testMultiDof(mbC, world, baseHalfExtents, linkHalfExtents); ///////////////////////////////////////////////////////////////// btScalar groundHeight = -51.55; if (!multibodyOnly) { 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 groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,groundHeight,0)); 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,1,1+2);//,1,1+2); } ///////////////////////////////////////////////////////////////// if(!multibodyOnly) { btVector3 halfExtents(.5,.5,.5); btBoxShape* colShape = new btBoxShape(halfExtents); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); startTransform.setOrigin(btVector3( btScalar(0.0), 0.0, btScalar(0.0))); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body);//,1,1+2); if (multibodyConstraint) { btVector3 pointInA = -linkHalfExtents; // btVector3 pointInB = halfExtents; btMatrix3x3 frameInA; btMatrix3x3 frameInB; frameInA.setIdentity(); frameInB.setIdentity(); btVector3 jointAxis(1.0,0.0,0.0); //btMultiBodySliderConstraint* p2p = new btMultiBodySliderConstraint(mbC,numLinks-1,body,pointInA,pointInB,frameInA,frameInB,jointAxis); btMultiBodyFixedConstraint* p2p = new btMultiBodyFixedConstraint(mbC,numLinks-1,mbC,numLinks-4,pointInA,pointInA,frameInA,frameInB); p2p->setMaxAppliedImpulse(2.0); m_dynamicsWorld->addMultiBodyConstraint(p2p); } } m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); ///////////////////////////////////////////////////////////////// }
int main() { btDefaultCollisionConfiguration *collisionConfiguration = new btDefaultCollisionConfiguration(); btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration); btBroadphaseInterface *overlappingPairCache = new btDbvtBroadphase(); btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver; btDiscreteDynamicsWorld *dynamicsWorld = new btDiscreteDynamicsWorld( dispatcher, overlappingPairCache, solver, collisionConfiguration); dynamicsWorld->setGravity(btVector3(0, gravity, 0)); dynamicsWorld->setInternalTickCallback(myTickCallback); btAlignedObjectArray<btCollisionShape*> collisionShapes; // Ground. { btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0, 0, 0)); btCollisionShape* groundShape; #if 0 // x / z plane at y = -1 (not 0 to compensate the radius of the falling object). groundShape = new btStaticPlaneShape(btVector3(groundXNormal, 1, 0), -1); #else // A cube of width 10 at y = -6 (upper surface at -1). // Does not fall because we won't call: // colShape->calculateLocalInertia // TODO: remove this from this example into a collision shape example. groundTransform.setOrigin(btVector3(-5, -6, 0)); groundShape = new btBoxShape( btVector3(btScalar(5.0), btScalar(5.0), btScalar(5.0))); #endif collisionShapes.push_back(groundShape); btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(0, myMotionState, groundShape, btVector3(0, 0, 0)); btRigidBody* body = new btRigidBody(rbInfo); body->setRestitution(groundRestitution); dynamicsWorld->addRigidBody(body); } // Object. { btCollisionShape *colShape; #if 0 colShape = new btSphereShape(btScalar(1.0)); #else // Because of numerical instabilities, the cube bumps all over, // moving on the x and z directions as well as y. colShape = new btBoxShape( btVector3(btScalar(1.0), btScalar(1.0), btScalar(1.0))); #endif collisionShapes.push_back(colShape); btTransform startTransform; startTransform.setIdentity(); startTransform.setOrigin(btVector3(initialX, initialY, initialZ)); btVector3 localInertia(0, 0, 0); btScalar mass(1.0f); colShape->calculateLocalInertia(mass, localInertia); btDefaultMotionState *myMotionState = new btDefaultMotionState(startTransform); btRigidBody *body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo( mass, myMotionState, colShape, localInertia)); body->setRestitution(objectRestitution); body->setLinearVelocity(btVector3(initialLinearVelocityX, initialLinearVelocityY, initialLinearVelocityZ)); dynamicsWorld->addRigidBody(body); } // Main loop. std::printf(COMMON_PRINTF_HEADER " collision a b normal\n"); for (std::remove_const<decltype(nSteps)>::type step = 0; step < nSteps; ++step) { dynamicsWorld->stepSimulation(timeStep); auto nCollisionObjects = dynamicsWorld->getNumCollisionObjects(); for (decltype(nCollisionObjects) objectIndex = 0; objectIndex < nCollisionObjects; ++objectIndex) { btRigidBody *body = btRigidBody::upcast(dynamicsWorld->getCollisionObjectArray()[objectIndex]); commonPrintBodyState(body, step, objectIndex); auto& manifoldPoints = objectsCollisions[body]; if (manifoldPoints.empty()) { std::printf("0 "); } else { std::printf("1 "); for (auto& pt : manifoldPoints) { std::vector<btVector3> data; data.push_back(pt->getPositionWorldOnA()); data.push_back(pt->getPositionWorldOnB()); data.push_back(pt->m_normalWorldOnB); for (auto& v : data) { std::printf( COMMON_PRINTF_FLOAT " " COMMON_PRINTF_FLOAT " " COMMON_PRINTF_FLOAT " ", v.getX(), v.getY(), v.getZ() ); } } } std::printf("\n"); } } // Cleanup. for (int i = dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; --i) { btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i]; btRigidBody* body = btRigidBody::upcast(obj); if (body && body->getMotionState()) { delete body->getMotionState(); } dynamicsWorld->removeCollisionObject(obj); delete obj; } for (int i = 0; i < collisionShapes.size(); ++i) { delete collisionShapes[i]; } delete dynamicsWorld; delete solver; delete overlappingPairCache; delete dispatcher; delete collisionConfiguration; collisionShapes.clear(); }
void Dof6Spring2Setup::initPhysics() { // Setup the basic world m_guiHelper->setUpAxis(1); m_collisionConfiguration = new btDefaultCollisionConfiguration(); m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); btVector3 worldAabbMin(-10000,-10000,-10000); btVector3 worldAabbMax(10000,10000,10000); m_broadphase = new btAxisSweep3 (worldAabbMin, worldAabbMax); /////// uncomment the corresponding line to test a solver. //m_solver = new btSequentialImpulseConstraintSolver; m_solver = new btNNCGConstraintSolver; //m_solver = new btMLCPSolver(new btSolveProjectedGaussSeidel()); //m_solver = new btMLCPSolver(new btDantzigSolver()); //m_solver = new btMLCPSolver(new btLemkeSolver()); m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld->getDispatchInfo().m_useContinuous = true; m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); m_dynamicsWorld->setGravity(btVector3(0,0,0)); // Setup a big ground box { btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(200.),btScalar(5.),btScalar(200.))); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-10,0)); #define CREATE_GROUND_COLLISION_OBJECT 1 #ifdef CREATE_GROUND_COLLISION_OBJECT btCollisionObject* fixedGround = new btCollisionObject(); fixedGround->setCollisionShape(groundShape); fixedGround->setWorldTransform(groundTransform); m_dynamicsWorld->addCollisionObject(fixedGround); #else localCreateRigidBody(btScalar(0.),groundTransform,groundShape); #endif //CREATE_GROUND_COLLISION_OBJECT } m_dynamicsWorld->getSolverInfo().m_numIterations = 100; btCollisionShape* shape; btVector3 localInertia(0,0,0); btDefaultMotionState* motionState; btTransform bodyTransform; btScalar mass; btTransform localA; btTransform localB; CONSTRAINT_TYPE* constraint; //static body centered in the origo mass = 0.0; shape= new btBoxShape(btVector3(0.5,0.5,0.5)); localInertia = btVector3(0,0,0); bodyTransform.setIdentity(); motionState = new btDefaultMotionState(bodyTransform); btRigidBody* staticBody = new btRigidBody(mass,motionState,shape,localInertia); /////////// box with undamped translate spring attached to static body /////////// the box should oscillate left-to-right forever { mass = 1.0; shape= new btBoxShape(btVector3(0.5,0.5,0.5)); shape->calculateLocalInertia(mass,localInertia); bodyTransform.setIdentity(); bodyTransform.setOrigin(btVector3(-2,0,-5)); motionState = new btDefaultMotionState(bodyTransform); m_data->m_TranslateSpringBody = new btRigidBody(mass,motionState,shape,localInertia); m_data->m_TranslateSpringBody->setActivationState(DISABLE_DEACTIVATION); m_dynamicsWorld->addRigidBody(m_data->m_TranslateSpringBody); localA.setIdentity();localA.getOrigin() = btVector3(0,0,-5); localB.setIdentity(); constraint = new CONSTRAINT_TYPE(*staticBody, *m_data->m_TranslateSpringBody, localA, localB EXTRAPARAMS); constraint->setLimit(0, 1,-1); constraint->setLimit(1, 0, 0); constraint->setLimit(2, 0, 0); constraint->setLimit(3, 0, 0); constraint->setLimit(4, 0, 0); constraint->setLimit(5, 0, 0); constraint->enableSpring(0, true); constraint->setStiffness(0, 100); #ifdef USE_6DOF2 constraint->setDamping(0, 0); #else constraint->setDamping(0, 1); #endif constraint->setEquilibriumPoint(0, 0); constraint->setDbgDrawSize(btScalar(2.f)); m_dynamicsWorld->addConstraint(constraint, true); } /////////// box with rotate spring, attached to static body /////////// box should swing (rotate) left-to-right forever { mass = 1.0; shape= new btBoxShape(btVector3(0.5,0.5,0.5)); shape->calculateLocalInertia(mass,localInertia); bodyTransform.setIdentity(); bodyTransform.getBasis().setEulerZYX(0,0,M_PI_2); motionState = new btDefaultMotionState(bodyTransform); m_data->m_RotateSpringBody = new btRigidBody(mass,motionState,shape,localInertia); m_data->m_RotateSpringBody->setActivationState(DISABLE_DEACTIVATION); m_dynamicsWorld->addRigidBody(m_data->m_RotateSpringBody); localA.setIdentity();localA.getOrigin() = btVector3(0,0,0); localB.setIdentity();localB.setOrigin(btVector3(0,0.5,0)); constraint = new CONSTRAINT_TYPE(*staticBody, *m_data->m_RotateSpringBody, localA, localB EXTRAPARAMS); constraint->setLimit(0, 0, 0); constraint->setLimit(1, 0, 0); constraint->setLimit(2, 0, 0); constraint->setLimit(3, 0, 0); constraint->setLimit(4, 0, 0); constraint->setLimit(5, 1, -1); constraint->enableSpring(5, true); constraint->setStiffness(5, 100); #ifdef USE_6DOF2 constraint->setDamping(5, 0); #else constraint->setDamping(5, 1); #endif constraint->setEquilibriumPoint(0, 0); constraint->setDbgDrawSize(btScalar(2.f)); m_dynamicsWorld->addConstraint(constraint, true); } /////////// box with bouncing constraint, translation is bounced at the positive x limit, but not at the negative limit /////////// bouncing can not be set independently at low and high limits, so two constraints will be created: one that defines the low (non bouncing) limit, and one that defines the high (bouncing) limit /////////// the box should move to the left (as an impulse will be applied to it periodically) until it reaches its limit, then bounce back { mass = 1.0; shape= new btBoxShape(btVector3(0.5,0.5,0.5)); shape->calculateLocalInertia(mass,localInertia); bodyTransform.setIdentity(); bodyTransform.setOrigin(btVector3(0,0,-3)); motionState = new btDefaultMotionState(bodyTransform); m_data->m_BouncingTranslateBody = new btRigidBody(mass,motionState,shape,localInertia); m_data->m_BouncingTranslateBody->setActivationState(DISABLE_DEACTIVATION); m_data->m_BouncingTranslateBody->setDeactivationTime(btScalar(20000000)); m_dynamicsWorld->addRigidBody(m_data->m_BouncingTranslateBody); localA.setIdentity();localA.getOrigin() = btVector3(0,0,0); localB.setIdentity(); constraint = new CONSTRAINT_TYPE(*staticBody, *m_data->m_BouncingTranslateBody, localA, localB EXTRAPARAMS); constraint->setLimit(0, -2, SIMD_INFINITY); constraint->setLimit(1, 0, 0); constraint->setLimit(2, -3, -3); constraint->setLimit(3, 0, 0); constraint->setLimit(4, 0, 0); constraint->setLimit(5, 0, 0); #ifdef USE_6DOF2 constraint->setBounce(0,0); #else //bounce is named restitution in 6dofspring, but not implemented for translational limit motor, so the following line has no effect constraint->getTranslationalLimitMotor()->m_restitution = 0.0; #endif constraint->setParam(BT_CONSTRAINT_STOP_ERP,0.995,0); constraint->setParam(BT_CONSTRAINT_STOP_CFM,0.0,0); constraint->setDbgDrawSize(btScalar(2.f)); m_dynamicsWorld->addConstraint(constraint, true); constraint = new CONSTRAINT_TYPE(*staticBody, *m_data->m_BouncingTranslateBody, localA, localB EXTRAPARAMS); constraint->setLimit(0, -SIMD_INFINITY, 2); constraint->setLimit(1, 0, 0); constraint->setLimit(2, -3, -3); constraint->setLimit(3, 0, 0); constraint->setLimit(4, 0, 0); constraint->setLimit(5, 0, 0); #ifdef USE_6DOF2 constraint->setBounce(0,1); #else //bounce is named restitution in 6dofspring, but not implemented for translational limit motor, so the following line has no effect constraint->getTranslationalLimitMotor()->m_restitution = 1.0; #endif constraint->setParam(BT_CONSTRAINT_STOP_ERP,0.995,0); constraint->setParam(BT_CONSTRAINT_STOP_CFM,0.0,0); constraint->setDbgDrawSize(btScalar(2.f)); m_dynamicsWorld->addConstraint(constraint, true); } /////////// box with rotational motor, attached to static body /////////// the box should rotate around the y axis { mass = 1.0; shape= new btBoxShape(btVector3(0.5,0.5,0.5)); shape->calculateLocalInertia(mass,localInertia); bodyTransform.setIdentity(); bodyTransform.setOrigin(btVector3(4,0,0)); motionState = new btDefaultMotionState(bodyTransform); m_data->m_MotorBody = new btRigidBody(mass,motionState,shape,localInertia); m_data->m_MotorBody->setActivationState(DISABLE_DEACTIVATION); m_dynamicsWorld->addRigidBody(m_data->m_MotorBody); localA.setIdentity();localA.getOrigin() = btVector3(4,0,0); localB.setIdentity(); constraint = new CONSTRAINT_TYPE(*staticBody, *m_data->m_MotorBody, localA, localB EXTRAPARAMS); constraint->setLimit(0, 0, 0); constraint->setLimit(1, 0, 0); constraint->setLimit(2, 0, 0); constraint->setLimit(3, 0, 0); constraint->setLimit(4, 0, 0); constraint->setLimit(5, 1,-1); #ifdef USE_6DOF2 constraint->enableMotor(5,true); constraint->setTargetVelocity(5,3.f); constraint->setMaxMotorForce(5,10.f); #else constraint->getRotationalLimitMotor(2)->m_enableMotor = true; constraint->getRotationalLimitMotor(2)->m_targetVelocity = 3.f; constraint->getRotationalLimitMotor(2)->m_maxMotorForce = 10; #endif constraint->setDbgDrawSize(btScalar(2.f)); m_dynamicsWorld->addConstraint(constraint, true); } /////////// box with rotational servo motor, attached to static body /////////// the box should rotate around the y axis until it reaches its target /////////// the target will be negated periodically { mass = 1.0; shape= new btBoxShape(btVector3(0.5,0.5,0.5)); shape->calculateLocalInertia(mass,localInertia); bodyTransform.setIdentity(); bodyTransform.setOrigin(btVector3(7,0,0)); motionState = new btDefaultMotionState(bodyTransform); m_data->m_ServoMotorBody = new btRigidBody(mass,motionState,shape,localInertia); m_data->m_ServoMotorBody->setActivationState(DISABLE_DEACTIVATION); m_dynamicsWorld->addRigidBody(m_data->m_ServoMotorBody); localA.setIdentity();localA.getOrigin() = btVector3(7,0,0); localB.setIdentity(); constraint = new CONSTRAINT_TYPE(*staticBody, *m_data->m_ServoMotorBody, localA, localB EXTRAPARAMS); constraint->setLimit(0, 0, 0); constraint->setLimit(1, 0, 0); constraint->setLimit(2, 0, 0); constraint->setLimit(3, 0, 0); constraint->setLimit(4, 0, 0); constraint->setLimit(5, 1,-1); #ifdef USE_6DOF2 constraint->enableMotor(5,true); constraint->setTargetVelocity(5,3.f); constraint->setMaxMotorForce(5,10.f); constraint->setServo(5,true); constraint->setServoTarget(5, M_PI_2); #else constraint->getRotationalLimitMotor(2)->m_enableMotor = true; constraint->getRotationalLimitMotor(2)->m_targetVelocity = 3.f; constraint->getRotationalLimitMotor(2)->m_maxMotorForce = 10; //servo motor is not implemented in 6dofspring constraint #endif constraint->setDbgDrawSize(btScalar(2.f)); m_dynamicsWorld->addConstraint(constraint, true); m_data->m_ServoMotorConstraint = constraint; } ////////// chain of boxes linked together with fully limited rotational and translational constraints ////////// the chain will be pulled to the left and to the right periodically. They should strictly stick together. { btScalar limitConstraintStrength = 0.6; int bodycount = 10; btRigidBody* prevBody = 0; for(int i = 0; i < bodycount; ++i) { mass = 1.0; shape= new btBoxShape(btVector3(0.5,0.5,0.5)); shape->calculateLocalInertia(mass,localInertia); bodyTransform.setIdentity(); bodyTransform.setOrigin(btVector3(- i,0,3)); motionState = new btDefaultMotionState(bodyTransform); btRigidBody* body = new btRigidBody(mass,motionState,shape,localInertia); body->setActivationState(DISABLE_DEACTIVATION); m_dynamicsWorld->addRigidBody(body); if(prevBody != 0) { localB.setIdentity(); localB.setOrigin(btVector3(0.5,0,0)); btTransform localA; localA.setIdentity(); localA.setOrigin(btVector3(-0.5,0,0)); CONSTRAINT_TYPE* constraint = new CONSTRAINT_TYPE(*prevBody, *body, localA, localB EXTRAPARAMS); constraint->setLimit(0, -0.01, 0.01); constraint->setLimit(1, 0, 0); constraint->setLimit(2, 0, 0); constraint->setLimit(3, 0, 0); constraint->setLimit(4, 0, 0); constraint->setLimit(5, 0, 0); for(int a = 0; a < 6; ++a) { constraint->setParam(BT_CONSTRAINT_STOP_ERP,0.9,a); constraint->setParam(BT_CONSTRAINT_STOP_CFM,0.0,a); } constraint->setDbgDrawSize(btScalar(1.f)); m_dynamicsWorld->addConstraint(constraint, true); if(i < bodycount - 1) { localA.setIdentity();localA.getOrigin() = btVector3(0,0,3); localB.setIdentity(); CONSTRAINT_TYPE* constraintZY = new CONSTRAINT_TYPE(*staticBody, *body, localA, localB EXTRAPARAMS); constraintZY->setLimit(0, 1, -1); constraintZY->setDbgDrawSize(btScalar(1.f)); m_dynamicsWorld->addConstraint(constraintZY, true); } } else { localA.setIdentity();localA.getOrigin() = btVector3(bodycount,0,3); localB.setIdentity(); localB.setOrigin(btVector3(0,0,0)); m_data->m_ChainLeftBody = body; m_data->m_ChainLeftConstraint = new CONSTRAINT_TYPE(*staticBody, *body, localA, localB EXTRAPARAMS); m_data->m_ChainLeftConstraint->setLimit(3,0,0); m_data->m_ChainLeftConstraint->setLimit(4,0,0); m_data->m_ChainLeftConstraint->setLimit(5,0,0); for(int a = 0; a < 6; ++a) { m_data->m_ChainLeftConstraint->setParam(BT_CONSTRAINT_STOP_ERP,limitConstraintStrength,a); m_data->m_ChainLeftConstraint->setParam(BT_CONSTRAINT_STOP_CFM,0.0,a); } m_data->m_ChainLeftConstraint->setDbgDrawSize(btScalar(1.f)); m_dynamicsWorld->addConstraint(m_data->m_ChainLeftConstraint, true); } prevBody = body; } m_data->m_ChainRightBody = prevBody; localA.setIdentity();localA.getOrigin() = btVector3(-bodycount,0,3); localB.setIdentity(); localB.setOrigin(btVector3(0,0,0)); m_data->m_ChainRightConstraint = new CONSTRAINT_TYPE(*staticBody, *m_data->m_ChainRightBody, localA, localB EXTRAPARAMS); m_data->m_ChainRightConstraint->setLimit(3,0,0); m_data->m_ChainRightConstraint->setLimit(4,0,0); m_data->m_ChainRightConstraint->setLimit(5,0,0); for(int a = 0; a < 6; ++a) { m_data->m_ChainRightConstraint->setParam(BT_CONSTRAINT_STOP_ERP,limitConstraintStrength,a); m_data->m_ChainRightConstraint->setParam(BT_CONSTRAINT_STOP_CFM,0.0,a); } } m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); }
void initBullet() { int i; ///collision configuration contains default setup for memory, collision setup. // Advanced users can create their own configuration. collisionConfiguration = new btDefaultCollisionConfiguration(); ///use the default collision dispatcher. For parallel processing you can // use a diffent dispatcher (see Extras/BulletMultiThreaded) dispatcher = new btCollisionDispatcher(collisionConfiguration); ///btDbvtBroadphase is a good general purpose broadphase. // You can also try out btAxis3Sweep. overlappingPairCache = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different // solver (see Extras/BulletMultiThreaded) solver = new btSequentialImpulseConstraintSolver; dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration); dynamicsWorld->setGravity(btVector3(0,-10,0)); ///create a few basic rigid bodies groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-56,0)); { 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 dynamicsWorld->addRigidBody(body); } { //create a dynamic rigidbody //btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); btCollisionShape* colShape = new btSphereShape(btScalar(1.)); collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); startTransform.setOrigin(btVector3(2,10,0)); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); dynamicsWorld->addRigidBody(body); } /// Do some simulation for (i=0;i<100;i++) { dynamicsWorld->stepSimulation(1.f/60.f,10); //print positions of all objects for (int j=dynamicsWorld->getNumCollisionObjects()-1; j>=0 ;j--) { btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j]; btRigidBody* body = btRigidBody::upcast(obj); if (body && body->getMotionState()) { btTransform trans; body->getMotionState()->getWorldTransform(trans); printf("world pos = %f,%f,%f\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ())); } } } //cleanup in the reverse order of creation/initialization //remove the rigidbodies from the dynamics world and delete them for (i=dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) { btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i]; btRigidBody* body = btRigidBody::upcast(obj); if (body && body->getMotionState()) { delete body->getMotionState(); } dynamicsWorld->removeCollisionObject( obj ); delete obj; } finishBullet(); }
void BasicDemo::initPhysics() { #ifdef FORCE_ZAXIS_UP m_cameraUp = btVector3(0,0,1); m_forwardAxis = 1; #endif gContactAddedCallback = CustomMaterialCombinerCallback; setTexturing(true); setShadows(false); setCameraDistance(btScalar(SCALING*20.)); this->m_azi = 90; ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); #ifdef FORCE_ZAXIS_UP m_dynamicsWorld->setGravity(btVector3(0,0,-10)); #else m_dynamicsWorld->setGravity(btVector3(0,-10,0)); #endif m_dynamicsWorld->getSolverInfo().m_solverMode |= SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION+SOLVER_USE_2_FRICTION_DIRECTIONS; m_dynamicsWorld->getSolverInfo().m_solverMode |= SOLVER_ENABLE_FRICTION_DIRECTION_CACHING; #if 1 m_blendReader = new BasicBlendReader(m_dynamicsWorld,this); //const char* fileName = "clubsilo_packed.blend"; const char* fileName = "PhysicsAnimationBakingDemo.blend"; char fullPath[512]; if(!m_blendReader->openFile(fileName)) { sprintf(fullPath,"../../%s",fileName); m_blendReader->openFile(fullPath); } if (m_blendReader) { m_blendReader->convertAllObjects(); } else { printf("file not found\n"); } #endif ///create a few basic rigid bodies #if 0 btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-60,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); //enable custom material callback body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } #endif #if 0 { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance //btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); //btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*.1,SCALING*.1,SCALING*.1)); btCollisionShape* colShape = new btSphereShape(SCALING*btScalar(1.)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); float start_x = -ARRAY_SIZE_X; float start_y = -ARRAY_SIZE_Y; float start_z = - ARRAY_SIZE_Z; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { startTransform.setOrigin(1.*SCALING*btVector3( 2.0*i + start_x, 2.0*k + start_y, 2.0*j + start_z)); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); //body->setContactProcessingThreshold(colShape->getContactBreakingThreshold()); body->setActivationState(ISLAND_SLEEPING); body->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE); // m_dynamicsWorld->addRigidBody(body); body->setActivationState(ISLAND_SLEEPING); } } } } btTriangleIndexVertexArray* meshInterface = new btTriangleIndexVertexArray(); btIndexedMesh indexMesh; indexMesh.m_numTriangles = BUNNY_NUM_TRIANGLES ; indexMesh.m_numVertices = BUNNY_NUM_VERTICES; indexMesh.m_vertexBase = (const unsigned char*) &gVerticesBunny[0]; indexMesh.m_vertexStride = 3*sizeof(REAL); indexMesh.m_triangleIndexBase = (const unsigned char*)&gIndicesBunny[0]; indexMesh.m_triangleIndexStride = 3*sizeof(int); meshInterface->addIndexedMesh(indexMesh); btBvhTriangleMeshShape* bunny = new btBvhTriangleMeshShape(meshInterface,true); bunny->setLocalScaling(btVector3(2,2,2)); btCollisionObject* obj = new btCollisionObject(); btTransform tr; tr.setIdentity(); tr.setOrigin(btVector3(0,2,-20)); obj ->setWorldTransform(tr); obj->setCollisionShape(bunny); m_dynamicsWorld->addCollisionObject(obj); #endif #if 0 btConvexTriangleMeshShape* convexBun = new btConvexTriangleMeshShape(meshInterface); obj = new btCollisionObject(); tr.setOrigin(btVector3(0,2,-14)); obj ->setWorldTransform(tr); obj->setCollisionShape(convexBun); m_dynamicsWorld->addCollisionObject(obj); #endif #if 0 btConvexTriangleMeshShape* convexBun = new btConvexTriangleMeshShape(meshInterface); obj = new btCollisionObject(); tr.setOrigin(btVector3(0,2,-14)); obj ->setWorldTransform(tr); obj->setCollisionShape(convexBun); m_dynamicsWorld->addCollisionObject(obj); //btDiscreteCollisionDetectorInterface::ClosestPointInput input; //input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds //input.m_transformA = sphereObj->getWorldTransform(); //input.m_transformB = triObj->getWorldTransform(); //bool swapResults = m_swapped; //detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults); for (int v=1;v<10;v++) { float VOXEL_SIZE = VOXEL_SIZE_START * v; btVoxelizationCallback voxelizationCallback; btCompoundShape* compoundBunny = new btCompoundShape(); voxelizationCallback.m_bunnyCompound = compoundBunny; voxelizationCallback.m_sphereChildShape = new btSphereShape(VOXEL_SIZE); #if 1 float start_x = -ARRAY_SIZE_X; float start_y = -ARRAY_SIZE_Y; float start_z = - ARRAY_SIZE_Z; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { btVector3 pos =VOXEL_SIZE*SCALING*btVector3( 2.0*i + start_x, 2.0*k + start_y, 2.0*j + start_z); btVector3 aabbMin(pos-btVector3(VOXEL_SIZE,VOXEL_SIZE,VOXEL_SIZE)); btVector3 aabbMax(pos+btVector3(VOXEL_SIZE,VOXEL_SIZE,VOXEL_SIZE)); voxelizationCallback.m_curSpherePos = pos; voxelizationCallback.m_oncePerSphere = false; bunny->processAllTriangles(&voxelizationCallback,aabbMin,aabbMax); } } } //btCollisionObject* obj2 = new btCollisionObject(); //obj2->setCollisionShape(compoundBunny); //m_dynamicsWorld->addCollisionObject(obj2); btVector3 localInertia; compoundBunny->calculateLocalInertia(1,localInertia); btRigidBody* body = new btRigidBody(1,0,compoundBunny,localInertia); //m_dynamicsWorld->addRigidBody(body); btTransform start; start.setIdentity(); start.setOrigin(btVector3(0,2,-12+6*v)); localCreateRigidBody(1.,start,compoundBunny); printf("compoundBunny with %d spheres\n",compoundBunny->getNumChildShapes()); #endif } #endif clientResetScene(); }
bool csBulletRigidBody::AddBulletObject () { // TODO: don't recompute everything if the internal scale hasn't changed if (insideWorld) RemoveBulletObject (); btVector3 localInertia (0.0f, 0.0f, 0.0f); float mass = GetMass (); btCollisionShape* shape; btTransform principalAxis; principalAxis.setIdentity (); btVector3 principalInertia(0,0,0); //Create btRigidBody if (compoundShape) { int shapeCount = compoundShape->getNumChildShapes (); CS_ALLOC_STACK_ARRAY(btScalar, masses, shapeCount); for (int i = 0; i < shapeCount; i++) masses[i] = density * colliders[i]->GetVolume (); if (shapeChanged) { compoundShape->calculatePrincipalAxisTransform (masses, principalAxis, principalInertia); // apply principal axis // creation is faster using a new compound to store the shifted children btCompoundShape* newCompoundShape = new btCompoundShape(); for (int i = 0; i < shapeCount; i++) { btTransform newChildTransform = principalAxis.inverse() * compoundShape->getChildTransform (i); newCompoundShape->addChildShape(newChildTransform, compoundShape->getChildShape (i)); shapeChanged = false; } delete compoundShape; compoundShape = newCompoundShape; } shape = compoundShape; } else { shape = colliders[0]->shape; principalAxis = CSToBullet (relaTransforms[0], system->getInternalScale ()); } // create new motion state btTransform trans; motionState->getWorldTransform (trans); trans = trans * motionState->inversePrincipalAxis; delete motionState; motionState = new csBulletMotionState (this, trans * principalAxis, principalAxis); //shape->calculateLocalInertia (mass, localInertia); btRigidBody::btRigidBodyConstructionInfo infos (mass, motionState, shape, localInertia); infos.m_friction = friction; infos.m_restitution = elasticity; infos.m_linearDamping = linearDampening; infos.m_angularDamping = angularDampening; // create new rigid body btBody = new btRigidBody (infos); btObject = btBody; if (haveStaticColliders > 0) physicalState = CS::Physics::STATE_STATIC; SetState (physicalState); sector->bulletWorld->addRigidBody (btBody, collGroup.value, collGroup.mask); btBody->setUserPointer (dynamic_cast<CS::Collisions::iCollisionObject*> ( dynamic_cast<csBulletCollisionObject*>(this))); insideWorld = true; return true; }
bool csBulletRigidBody::SetState (CS::Physics::RigidBodyState state) { if (physicalState != state || !insideWorld) { CS::Physics::RigidBodyState previousState = physicalState; physicalState = state; if (!btBody) return false; if (haveStaticColliders > 0 && state != CS::Physics::STATE_STATIC) return false; if (insideWorld) sector->bulletWorld->removeRigidBody (btBody); btVector3 linearVelo = CSToBullet (linearVelocity, system->getInternalScale ()); btVector3 angularVelo = btVector3 (angularVelocity.x, angularVelocity.y, angularVelocity.z); if (previousState == CS::Physics::STATE_KINEMATIC && insideWorld) { btBody->setCollisionFlags (btBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); linearVelo = btBody->getInterpolationLinearVelocity (); angularVelo = btBody->getInterpolationAngularVelocity (); // create new motion state btTransform principalAxis = motionState->inversePrincipalAxis.inverse (); btTransform trans; motionState->getWorldTransform (trans); trans = trans * motionState->inversePrincipalAxis; delete motionState; motionState = new csBulletMotionState (this, trans * principalAxis, principalAxis); btBody->setMotionState (motionState); } if (state == CS::Physics::STATE_DYNAMIC) { btBody->setCollisionFlags (btBody->getCollisionFlags() & ~btCollisionObject::CF_STATIC_OBJECT); float mass = GetMass (); btVector3 localInertia (0.0f, 0.0f, 0.0f); if (compoundShape) compoundShape->calculateLocalInertia (mass, localInertia); else colliders[0]->shape->calculateLocalInertia (mass, localInertia); btBody->setMassProps (mass, localInertia); btBody->forceActivationState (ACTIVE_TAG); btBody->setLinearVelocity (linearVelo); btBody->setAngularVelocity (angularVelo); btBody->updateInertiaTensor (); } else if (state == CS::Physics::STATE_KINEMATIC) { if (!kinematicCb) kinematicCb.AttachNew (new csBulletDefaultKinematicCallback ()); // create new motion state btTransform principalAxis = motionState->inversePrincipalAxis.inverse (); btTransform trans; motionState->getWorldTransform (trans); delete motionState; motionState = new csBulletKinematicMotionState (this, trans, principalAxis); btBody->setMotionState (motionState); // set body kinematic btBody->setMassProps (0.0f, btVector3 (0.0f, 0.0f, 0.0f)); btBody->setCollisionFlags (btBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT & ~btCollisionObject::CF_STATIC_OBJECT); btBody->setActivationState (DISABLE_DEACTIVATION); btBody->updateInertiaTensor (); btBody->setInterpolationWorldTransform (btBody->getWorldTransform ()); btBody->setInterpolationLinearVelocity (btVector3(0.0f, 0.0f, 0.0f)); btBody->setInterpolationAngularVelocity (btVector3(0.0f, 0.0f, 0.0f)); } else if (state == CS::Physics::STATE_STATIC) { btBody->setCollisionFlags (btBody->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT & ~btCollisionObject::CF_KINEMATIC_OBJECT); btBody->setActivationState (ISLAND_SLEEPING); btBody->setMassProps (0.0f, btVector3 (0.0f, 0.0f, 0.0f)); btBody->updateInertiaTensor (); } if (insideWorld) sector->bulletWorld->addRigidBody (btBody); return true; } else return false; }
void BasicGpuDemo::createObjects() { ///create a few basic rigid bodies btBoxShape* groundShape = new btBoxShape(btVector3(btScalar(150.),btScalar(50.),btScalar(150.))); //groundShape->initializePolyhedralFeatures(); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); m_collisionShapes.push_back(groundShape); if (0) { btTransform tr; tr.setIdentity(); btVector3 faraway(-1e30,-1e30,-1e30); tr.setOrigin(faraway); 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(tr); btSphereShape* dummyShape = new btSphereShape(0.f); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,dummyShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } 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,0,groundShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); body->setWorldTransform(groundTransform); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance btBoxShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); //btCollisionShape* colShape = new btSphereShape(btScalar(SCALING*1.f)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); float start_x = START_POS_X - ARRAY_SIZE_X/2; float start_y = START_POS_Y; float start_z = START_POS_Z - ARRAY_SIZE_Z/2; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { startTransform.setOrigin(SCALING*btVector3( btScalar(2.*i + start_x), btScalar(6+2.0*k + start_y), btScalar(2.*j + start_z))); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects //btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); body->setWorldTransform(startTransform); m_dynamicsWorld->addRigidBody(body); } } } } m_np->writeAllBodiesToGpu(); m_bp->writeAabbsToGpu(); m_rbp->writeAllInstancesToGpu(); }
void CcdPhysicsDemo::initPhysics() { setTexturing(true); setShadows(true); m_ShootBoxInitialSpeed = 4000.f; m_defaultContactProcessingThreshold = 0.f; ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); // m_collisionConfiguration->setConvexConvexMultipointIterations(); ///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->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,m_collisionConfiguration->getCollisionAlgorithmCreateFunc(CONVEX_SHAPE_PROXYTYPE,CONVEX_SHAPE_PROXYTYPE)); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld->getSolverInfo().m_solverMode |=SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_RANDMIZE_ORDER; m_dynamicsWorld ->setDebugDrawer(&sDebugDrawer); //m_dynamicsWorld->getSolverInfo().m_splitImpulse=false; if (m_ccdMode==USE_CCD) { m_dynamicsWorld->getDispatchInfo().m_useContinuous=true; } else { m_dynamicsWorld->getDispatchInfo().m_useContinuous=false; } m_dynamicsWorld->setGravity(btVector3(0,-10,0)); ///create a few basic rigid bodies btBoxShape* box = new btBoxShape(btVector3(btScalar(110.),btScalar(1.),btScalar(110.))); // box->initializePolyhedralFeatures(); btCollisionShape* groundShape = box; // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); m_collisionShapes.push_back(groundShape); //m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); m_collisionShapes.push_back(new btBoxShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); btTransform groundTransform; groundTransform.setIdentity(); //groundTransform.setOrigin(btVector3(5,5,5)); //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); body->setFriction(0.5); //body->setRollingFriction(0.3); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); int gNumObjects = 120;//120; int i; for (i=0;i<gNumObjects;i++) { btCollisionShape* shape = m_collisionShapes[1]; btTransform trans; trans.setIdentity(); //stack them int colsize = 10; int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS); int row2 = row; int col = (i)%(colsize)-colsize/2; if (col>3) { col=11; row2 |=1; } btVector3 pos(col*2*CUBE_HALF_EXTENTS + (row2%2)*CUBE_HALF_EXTENTS, row*2*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,0); trans.setOrigin(pos); float mass = 1.f; btRigidBody* body = localCreateRigidBody(mass,trans,shape); body->setAnisotropicFriction(shape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); body->setFriction(0.5); //body->setRollingFriction(.3); ///when using m_ccdMode if (m_ccdMode==USE_CCD) { body->setCcdMotionThreshold(CUBE_HALF_EXTENTS); body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS); } } } }
void FractureDemo::initPhysics() { m_guiHelper->setUpAxis(1); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; //m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); btFractureDynamicsWorld* fractureWorld = new btFractureDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); m_dynamicsWorld = fractureWorld; m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); //m_splitImpulse removes the penetration resolution from the applied impulse, otherwise objects might fracture due to deep penetrations. m_dynamicsWorld->getSolverInfo().m_splitImpulse = true; { ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(50, 1, 50)); /// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0, 0, 0)); createRigidBody(0.f, groundTransform, groundShape); } { ///create a few basic rigid bodies btCollisionShape* shape = new btBoxShape(btVector3(1, 1, 1)); m_collisionShapes.push_back(shape); btTransform tr; tr.setIdentity(); tr.setOrigin(btVector3(5, 2, 0)); createRigidBody(0.f, tr, shape); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance btCollisionShape* colShape = new btBoxShape(btVector3(SCALING * 1, SCALING * 1, SCALING * 1)); //btCollisionShape* colShape = new btCapsuleShape(SCALING*0.4,SCALING*1); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass, localInertia); int gNumObjects = 10; for (int i = 0; i < gNumObjects; i++) { btTransform trans; trans.setIdentity(); btVector3 pos(i * 2 * CUBE_HALF_EXTENTS, 20, 0); trans.setOrigin(pos); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(trans); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, colShape, localInertia); btFractureBody* body = new btFractureBody(rbInfo, m_dynamicsWorld); body->setLinearVelocity(btVector3(0, -10, 0)); m_dynamicsWorld->addRigidBody(body); } } fractureWorld->stepSimulation(1. / 60., 0); fractureWorld->glueCallback(); m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); }
bool BtBody::init( PhysicsCollision *shape, F32 mass, U32 bodyFlags, SceneObject *obj, PhysicsWorld *world ) { AssertFatal( obj, "BtBody::init - Got a null scene object!" ); AssertFatal( world, "BtBody::init - Got a null world!" ); AssertFatal( dynamic_cast<BtWorld*>( world ), "BtBody::init - The world is the wrong type!" ); AssertFatal( shape, "BtBody::init - Got a null collision shape!" ); AssertFatal( dynamic_cast<BtCollision*>( shape ), "BtBody::init - The collision shape is the wrong type!" ); AssertFatal( ((BtCollision*)shape)->getShape(), "BtBody::init - Got empty collision shape!" ); // Cleanup any previous actor. _releaseActor(); mWorld = (BtWorld*)world; mColShape = (BtCollision*)shape; btCollisionShape *btColShape = mColShape->getShape(); MatrixF localXfm = mColShape->getLocalTransform(); btVector3 localInertia( 0, 0, 0 ); // If we have a mass then we're dynamic. mIsDynamic = mass > 0.0f; if ( mIsDynamic ) { if ( btColShape->isCompound() ) { btCompoundShape *btCompound = (btCompoundShape*)btColShape; btScalar *masses = new btScalar[ btCompound->getNumChildShapes() ]; for ( U32 j=0; j < btCompound->getNumChildShapes(); j++ ) masses[j] = mass / btCompound->getNumChildShapes(); btVector3 principalInertia; btTransform principal; btCompound->calculatePrincipalAxisTransform( masses, principal, principalInertia ); delete [] masses; // Create a new compound with the shifted children. btColShape = mCompound = new btCompoundShape(); for ( U32 i=0; i < btCompound->getNumChildShapes(); i++ ) { btTransform newChildTransform = principal.inverse() * btCompound->getChildTransform(i); mCompound->addChildShape( newChildTransform, btCompound->getChildShape(i) ); } localXfm = btCast<MatrixF>( principal ); } // Note... this looks like we're changing the shape, but // we're not. All this does is ask the shape to calculate the // local inertia vector from the mass... the shape doesn't change. btColShape->calculateLocalInertia( mass, localInertia ); } // If we have a local transform then we need to // store it and the inverse to offset the center // of mass from the graphics origin. if ( !localXfm.isIdentity() ) { mCenterOfMass = new MatrixF( localXfm ); mInvCenterOfMass = new MatrixF( *mCenterOfMass ); mInvCenterOfMass->inverse(); } mMass = mass; mActor = new btRigidBody( mass, NULL, btColShape, localInertia ); int btFlags = mActor->getCollisionFlags(); if ( bodyFlags & BF_TRIGGER ) btFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE; if ( bodyFlags & BF_KINEMATIC ) { btFlags &= ~btCollisionObject::CF_STATIC_OBJECT; btFlags |= btCollisionObject::CF_KINEMATIC_OBJECT; } mActor->setCollisionFlags( btFlags ); mWorld->getDynamicsWorld()->addRigidBody( mActor ); mIsEnabled = true; mUserData.setObject( obj ); mUserData.setBody( this ); mActor->setUserPointer( &mUserData ); return true; }
void Box2dDemo::initPhysics() { m_dialogDynamicsWorld = new GL_DialogDynamicsWorld(); //m_dialogDynamicsWorld->createDialog(100,110,200,50); //m_dialogDynamicsWorld->createDialog(100,00,100,100); //m_dialogDynamicsWorld->createDialog(0,0,100,100); GL_DialogWindow* settings = m_dialogDynamicsWorld->createDialog(50,0,200,120,"Settings"); GL_ToggleControl* toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 1"); toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 2"); toggle ->m_active = true; toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 3"); //GL_SliderControl* slider = m_dialogDynamicsWorld->createSlider(settings,"Slider"); GL_DialogWindow* dialog = m_dialogDynamicsWorld->createDialog(0,200,420,300,"Help"); GL_TextControl* txt = new GL_TextControl; dialog->addControl(txt); txt->m_textLines.push_back("Mouse to move"); txt->m_textLines.push_back("Test 2"); txt->m_textLines.push_back("mouse to interact"); txt->m_textLines.push_back("ALT + mouse to move camera"); txt->m_textLines.push_back("space to reset"); txt->m_textLines.push_back("cursor keys and z,x to navigate"); txt->m_textLines.push_back("i to toggle simulation, s single step"); txt->m_textLines.push_back("q to quit"); txt->m_textLines.push_back(". to shoot box"); txt->m_textLines.push_back("d to toggle deactivation"); txt->m_textLines.push_back("g to toggle mesh animation (ConcaveDemo)"); txt->m_textLines.push_back("h to toggle help text"); txt->m_textLines.push_back("o to toggle orthogonal/perspective view"); //txt->m_textLines.push_back("+- shooting speed = %10.2f",m_ShootBoxInitialSpeed); setTexturing(true); setShadows(true); setCameraDistance(btScalar(SCALING*50.)); m_cameraTargetPosition.setValue(0,0,0);//0, ARRAY_SIZE_Y, 0); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); btVoronoiSimplexSolver* simplex = new btVoronoiSimplexSolver(); btMinkowskiPenetrationDepthSolver* pdSolver = new btMinkowskiPenetrationDepthSolver(); btConvex2dConvex2dAlgorithm::CreateFunc* convexAlgo2d = new btConvex2dConvex2dAlgorithm::CreateFunc(simplex,pdSolver); m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,convexAlgo2d); m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,convexAlgo2d); m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,convexAlgo2d); m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,new btBox2dBox2dCollisionAlgorithm::CreateFunc()); m_broadphase = new btDbvtBroadphase(); //m_broadphase = new btSimpleBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); //m_dynamicsWorld->getSolverInfo().m_erp = 1.f; //m_dynamicsWorld->getSolverInfo().m_numIterations = 4; m_dynamicsWorld->setGravity(btVector3(0,-10,0)); ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(150.),btScalar(50.),btScalar(150.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-43,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); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance btScalar u= btScalar(1*SCALING-0.04); btVector3 points[3] = {btVector3(0,u,0),btVector3(-u,-u,0),btVector3(u,-u,0)}; btConvexShape* childShape0 = new btBoxShape(btVector3(btScalar(SCALING*1),btScalar(SCALING*1),btScalar(0.04))); btConvexShape* colShape= new btConvex2dShape(childShape0); //btCollisionShape* colShape = new btBox2dShape(btVector3(SCALING*1,SCALING*1,0.04)); btConvexShape* childShape1 = new btConvexHullShape(&points[0].getX(),3); btConvexShape* colShape2= new btConvex2dShape(childShape1); btConvexShape* childShape2 = new btCylinderShapeZ(btVector3(btScalar(SCALING*1),btScalar(SCALING*1),btScalar(0.04))); btConvexShape* colShape3= new btConvex2dShape(childShape2); m_collisionShapes.push_back(colShape); m_collisionShapes.push_back(colShape2); m_collisionShapes.push_back(colShape3); m_collisionShapes.push_back(childShape0); m_collisionShapes.push_back(childShape1); m_collisionShapes.push_back(childShape2); //btUniformScalingShape* colShape = new btUniformScalingShape(convexColShape,1.f); colShape->setMargin(btScalar(0.03)); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); // float start_x = START_POS_X - ARRAY_SIZE_X/2; // float start_y = START_POS_Y; // float start_z = START_POS_Z - ARRAY_SIZE_Z/2; btVector3 x(-ARRAY_SIZE_X, 8.0f,-20.f); btVector3 y; btVector3 deltaX(SCALING*1, SCALING*2,0.f); btVector3 deltaY(SCALING*2, 0.0f,0.f); for (int i = 0; i < ARRAY_SIZE_X; ++i) { y = x; for (int j = i; j < ARRAY_SIZE_Y; ++j) { startTransform.setOrigin(y-btVector3(-10,0,0)); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(0,0,0); switch (j%3) { #if 1 case 0: rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass,myMotionState,colShape,localInertia); break; case 1: rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass,myMotionState,colShape3,localInertia); break; #endif default: rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass,myMotionState,colShape2,localInertia); } btRigidBody* body = new btRigidBody(rbInfo); //body->setContactProcessingThreshold(colShape->getContactBreakingThreshold()); body->setActivationState(ISLAND_SLEEPING); body->setLinearFactor(btVector3(1,1,0)); body->setAngularFactor(btVector3(0,0,1)); m_dynamicsWorld->addRigidBody(body); body->setActivationState(ISLAND_SLEEPING); // y += -0.8*deltaY; y += deltaY; } x += deltaX; } } clientResetScene(); }
void RigidBody::AddBodyToWorld() { if (!physicsWorld_) return; URHO3D_PROFILE(AddBodyToWorld); if (mass_ < 0.0f) mass_ = 0.0f; if (body_) RemoveBodyFromWorld(); else { // Correct inertia will be calculated below btVector3 localInertia(0.0f, 0.0f, 0.0f); body_ = new btRigidBody(mass_, this, shiftedCompoundShape_, localInertia); body_->setUserPointer(this); // Check for existence of the SmoothedTransform component, which should be created by now in network client mode. // If it exists, subscribe to its change events smoothedTransform_ = GetComponent<SmoothedTransform>(); if (smoothedTransform_) { SubscribeToEvent(smoothedTransform_, E_TARGETPOSITION, URHO3D_HANDLER(RigidBody, HandleTargetPosition)); SubscribeToEvent(smoothedTransform_, E_TARGETROTATION, URHO3D_HANDLER(RigidBody, HandleTargetRotation)); } // Check if CollisionShapes already exist in the node and add them to the compound shape. // Do not update mass yet, but do it once all shapes have been added PODVector<CollisionShape*> shapes; node_->GetComponents<CollisionShape>(shapes); for (PODVector<CollisionShape*>::Iterator i = shapes.Begin(); i != shapes.End(); ++i) (*i)->NotifyRigidBody(false); // Check if this node contains Constraint components that were waiting for the rigid body to be created, and signal them // to create themselves now PODVector<Constraint*> constraints; node_->GetComponents<Constraint>(constraints); for (PODVector<Constraint*>::Iterator i = constraints.Begin(); i != constraints.End(); ++i) (*i)->CreateConstraint(); } UpdateMass(); UpdateGravity(); int flags = body_->getCollisionFlags(); if (trigger_) flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE; else flags &= ~btCollisionObject::CF_NO_CONTACT_RESPONSE; if (kinematic_) flags |= btCollisionObject::CF_KINEMATIC_OBJECT; else flags &= ~btCollisionObject::CF_KINEMATIC_OBJECT; body_->setCollisionFlags(flags); body_->forceActivationState(kinematic_ ? DISABLE_DEACTIVATION : ISLAND_SLEEPING); if (!IsEnabledEffective()) return; btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld(); world->addRigidBody(body_, (short)collisionLayer_, (short)collisionMask_); inWorld_ = true; readdBody_ = false; if (mass_ > 0.0f) Activate(); else { SetLinearVelocity(Vector3::ZERO); SetAngularVelocity(Vector3::ZERO); } }
void RollingFrictionDemo::initPhysics() { m_guiHelper->setUpAxis(2); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); // m_dynamicsWorld->getSolverInfo().m_singleAxisRollingFrictionThreshold = 0.f;//faster but lower quality m_dynamicsWorld->setGravity(btVector3(0,0,-10)); m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); { ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(10.),btScalar(5.),btScalar(25.))); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,0,-28)); groundTransform.setRotation(btQuaternion(btVector3(0,1,0),SIMD_PI*0.03)); //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); body->setFriction(1); body->setRollingFriction(1); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } { ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(100.),btScalar(100.),btScalar(50.))); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,0,-54)); //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); body->setFriction(1); body->setRollingFriction(1); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance #define NUM_SHAPES 10 btCollisionShape* colShapes[NUM_SHAPES] = { new btSphereShape(btScalar(0.5)), new btCapsuleShape(0.25,0.5), new btCapsuleShapeX(0.25,0.5), new btCapsuleShapeZ(0.25,0.5), new btConeShape(0.25,0.5), new btConeShapeX(0.25,0.5), new btConeShapeZ(0.25,0.5), new btCylinderShape(btVector3(0.25,0.5,0.25)), new btCylinderShapeX(btVector3(0.5,0.25,0.25)), new btCylinderShapeZ(btVector3(0.25,0.25,0.5)), }; for (int i=0; i<NUM_SHAPES; i++) m_collisionShapes.push_back(colShapes[i]); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //rigidbody is dynamic if and only if mass is non zero, otherwise static float start_x = START_POS_X - ARRAY_SIZE_X/2; float start_y = START_POS_Y; float start_z = START_POS_Z - ARRAY_SIZE_Z/2; { int shapeIndex = 0; for (int k=0; k<ARRAY_SIZE_Y; k++) { for (int i=0; i<ARRAY_SIZE_X; i++) { for(int j = 0; j<ARRAY_SIZE_Z; j++) { startTransform.setOrigin(SCALING*btVector3( btScalar(2.0*i + start_x), btScalar(2.0*j + start_z), btScalar(20+2.0*k + start_y))); shapeIndex++; btCollisionShape* colShape = colShapes[shapeIndex%NUM_SHAPES]; bool isDynamic = (mass != 0.f); btVector3 localInertia(0,0,0); if (isDynamic) colShape->calculateLocalInertia(mass,localInertia); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); body->setFriction(1.f); body->setRollingFriction(.3); body->setAnisotropicFriction(colShape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); m_dynamicsWorld->addRigidBody(body); } } } } } m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); if (0) { btSerializer* s = new btDefaultSerializer; m_dynamicsWorld->serialize(s); b3ResourcePath p; char resourcePath[1024]; if (p.findResourcePath("slope.bullet",resourcePath,1024)) { FILE* f = fopen(resourcePath,"wb"); fwrite(s->getBufferPointer(),s->getCurrentBufferSize(),1,f); fclose(f); } } }
void BasicDemo3D::initPhysics() { setTexturing(true); setShadows(false); // setCameraDistance(btScalar(SCALING*50.)); #if LARGE_DEMO setCameraDistance(btScalar(SCALING*50.)); #else setCameraDistance(btScalar(SCALING*20.)); #endif m_cameraTargetPosition.setValue(START_POS_X, -START_POS_Y-20, START_POS_Z); m_azi = btScalar(0.f); m_ele = btScalar(0.f); ///collision configuration contains default setup for memory, collision setup btDefaultCollisionConstructionInfo dci; dci.m_defaultMaxPersistentManifoldPoolSize=100000; dci.m_defaultMaxCollisionAlgorithmPoolSize=100000; dci.m_customCollisionAlgorithmMaxElementSize = sizeof(SpuContactManifoldCollisionAlgorithm); ///SpuContactManifoldCollisionAlgorithm is larger than any of the other collision algorithms //@@ dci.m_customMaxCollisionAlgorithmSize = sizeof(SpuContactManifoldCollisionAlgorithm); m_collisionConfiguration = new btDefaultCollisionConfiguration(dci); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) //m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); #ifndef WIN32 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); #else unsigned int maxNumOutstandingTasks =4; //createCollisionLocalStoreMemory(); //processSolverTask Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("narrowphase_multi",processCollisionTask,createCollisionLocalStoreMemory,maxNumOutstandingTasks); class btThreadSupportInterface* threadInterface = new Win32ThreadSupport(threadConstructionInfo); m_dispatcher = new SpuGatheringCollisionDispatcher(threadInterface,maxNumOutstandingTasks,m_collisionConfiguration); #endif //SINGLE_THREADED_NARROWPHASE //## m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,new btEmptyAlgorithm::CreateFunc); //## m_dispatcher->registerCollisionCreateFunc(CUSTOM_CONVEX_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE,new btBox2dBox2dCollisionAlgorithm::CreateFunc); // m_broadphase = new btDbvtBroadphase(); //## gPairCache = new (btAlignedAlloc(sizeof(btCudaDemoPairCache),16)) btCudaDemoPairCache(MAX_PROXIES, 24, MAX_SMALL_PROXIES); // gPairCache = NULL; gPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); //m_broadphase = new btSimpleBroadphase(16384, gPairCache); /* btCudaBroadphase::btCudaBroadphase( btOverlappingPairCache* overlappingPairCache, const btVector3& worldAabbMin,const btVector3& worldAabbMax, int gridSizeX, int gridSizeY, int gridSizeZ, int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, int maxBodiesPerCell, btScalar cellFactorAABB) */ // btVector3 numOfCells = (gWorldMax - gWorldMin) / (2. * SCALING * 0.7); btVector3 numOfCells = (gWorldMax - gWorldMin) / (2. * SCALING); int numOfCellsX = (int)numOfCells[0]; int numOfCellsY = (int)numOfCells[1]; int numOfCellsZ = (int)numOfCells[2]; // m_broadphase = new bt3DGridBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,8,8,1./1.5); //#define USE_CUDA_BROADPHASE 1 #ifdef USE_CUDA_BROADPHASE m_broadphase = new btCudaBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,20,18,8,1./1.5); #else #if DBVT btDbvtBroadphase* dbvt = new btDbvtBroadphase(gPairCache); m_broadphase = dbvt; dbvt->m_deferedcollide=false; dbvt->m_prediction = 0.f; #else m_broadphase = new btAxisSweep3(gWorldMin,gWorldMax,32000,gPairCache,true);//(btDbvtBroadphase(gPairCache); #endif //DBVT #endif // create solvers for tests ///the default constraint solver sConstraintSolvers[0] = new btSequentialImpulseConstraintSolver(); /* sConstraintSolvers[1] = new btParallelBatchConstraintSolver(); sConstraintSolvers[2] = new btCudaConstraintSolver(); sConstraintSolvers[3] = new btParallelBatchConstraintSolver2(); sConstraintSolvers[4] = new btParallelBatchConstraintSolver3(); sConstraintSolvers[5] = new btCudaConstraintSolver3(); sConstraintSolvers[6] = new btParallelBatchConstraintSolver4(); sConstraintSolvers[7] = new btCudaConstraintSolver4(); sConstraintSolvers[8] = new btParallelBatchConstraintSolver5(); sConstraintSolvers[9] = new btParallelBatchConstraintSolver6(); sConstraintSolvers[10] = new btCudaConstraintSolver6(); */ sCurrSolverIndex = 0; m_solver = sConstraintSolvers[sCurrSolverIndex]; printf("\nUsing %s\n", sConstraintSolverNames[sCurrSolverIndex]); // sCudaMotionInterface = new btCudaMotionInterface(MAX_PROXIES); // m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, sCudaMotionInterface); // m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); //## btCudaDemoDynamicsWorld* pDdw = new btCudaDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); btCudaDemoDynamicsWorld3D* pDdw = new btCudaDemoDynamicsWorld3D(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld = pDdw; pDdw->getDispatchInfo().m_enableSPU=true; pDdw->getSimulationIslandManager()->setSplitIslands(sCurrSolverIndex == 0); pDdw->setObjRad(SCALING); pDdw->setWorldMin(gWorldMin); pDdw->setWorldMax(gWorldMax); #ifdef BT_USE_CUDA gUseCPUSolver = false; #else gUseCPUSolver = true; #endif pDdw->setUseCPUSolver(gUseCPUSolver); // pDdw->setUseSolver2(gUseSolver2); // m_dynamicsWorld->setGravity(btVector3(0,0,0)); m_dynamicsWorld->setGravity(btVector3(0.f,-10.f,0.f)); m_dynamicsWorld->getSolverInfo().m_numIterations = 4; { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance //btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,0.1));//SCALING*1)); //## btCollisionShape* colShape = new btBox2dShape(btVector3(SCALING*.7,SCALING*.7,0.1));//SCALING*1)); btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*.7,SCALING*.7, SCALING*.7)); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); #if (!SPEC_TEST) float start_x = START_POS_X - ARRAY_SIZE_X * SCALING; float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING; float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { startTransform.setOrigin(SCALING*btVector3( 2.0*SCALING*i + start_x, 2.0*SCALING*k + start_y, 2.0*SCALING*j + start_z)); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects //btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); rbInfo.m_startWorldTransform=startTransform; btRigidBody* body = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body); } } } #else // narrowphase test - 2 bodies at the same position float start_x = START_POS_X; float start_y = START_POS_Y; float start_z = START_POS_Z; // startTransform.setOrigin(SCALING*btVector3(start_x,start_y-14.f,start_z)); startTransform.setOrigin(SCALING*btVector3(start_x,start_y-11.f,start_z)); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); rbInfo.m_startWorldTransform=startTransform; btRigidBody* body = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body); // startTransform.setOrigin(SCALING*btVector3(start_x+1.2f,start_y+1.4f-14.f,start_z)); startTransform.setOrigin(SCALING*btVector3(start_x,start_y + 1.5f -11.f, start_z)); rbInfo.m_startWorldTransform=startTransform; body = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body); #endif } #if 0 ///create a few basic rigid bodies // btCollisionShape* groundShape = new btBox2dShape(btVector3(btScalar(50.),btScalar(1.),btScalar(50.))); // btCollisionShape* groundShape = new btBox2dShape(btVector3(btScalar(228.),btScalar(1.),btScalar(228.))); // btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(228.),btScalar(1.),btScalar(228.))); // btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); btCollisionShape* groundShape = new btBoxShape(btVector3(POS_OFFS_X, btScalar(1.), POS_OFFS_Z)); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0, gWorldMin[1], 0)); // groundTransform.setOrigin(btVector3(0,-5,0)); // 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); } #endif //clientResetScene(); }
void Fenettre::Init() { /// Initialisation d'OpenGL // On active la lumière 0 glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); // Quelques autres options OpenGL glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_COLOR_MATERIAL); glEnable(GL_NORMALIZE); glEnable(GL_COLOR); glEnable(GL_TEXTURE_2D); // Couleur de fond d'écran glClearColor(0.0,0.0,0.0,0); // l'espace d'affichage glViewport( 0, 0, 1200, 900 ); glewInit(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(70, 800.0/500.0, 0.001f, 1000.0f ); /// Initialisation de Bullet CollisionConfiguration = new btDefaultCollisionConfiguration(); Dispatcher = new btCollisionDispatcher(CollisionConfiguration); Broadphase = new btDbvtBroadphase(); SequentialImpulseConstraintSolver = new btSequentialImpulseConstraintSolver; World = new btDiscreteDynamicsWorld(Dispatcher,Broadphase,SequentialImpulseConstraintSolver,CollisionConfiguration); World->setGravity( btVector3(0,GRAVITEE,0)); btTransform Transform; Transform.setIdentity(); Transform.setOrigin(btVector3(0,0,0)); btDefaultMotionState* MotionState =new btDefaultMotionState(Transform); Terrain = new btStaticPlaneShape(btVector3(0,1,0),0); btVector3 localInertia(0,0,0); float mass=0; Terrain->calculateLocalInertia(mass,localInertia); btRigidBody *body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo(mass, MotionState, Terrain, localInertia)); World->addRigidBody(body); //test = new RenderTerrain(); /// Initialisation des shaders setActive(); Prog[0] = new ShaderProgram("shader/mur.frag",sf::Shader::Fragment); Prog[0]->setTexture("Texture_Col","textures/Fieldstone.jpg"); Prog[0]->setTexture("Texture_Normal","textures/FieldstoneBump.jpg"); Prog[1] = new ShaderProgram("shader/mur.frag",sf::Shader::Fragment); Prog[1]->setTexture("Texture_Col","textures/redwall1_t.png"); Prog[1]->setTexture("Texture_Normal","textures/redwall1_nm.png"); /// Initialisation des truc perso setMouseCursorVisible(false); camera = new FreeFlyCamera(btVector3(-5,20,0)); };
bool Hair::create(HairSetup *setup, std::shared_ptr<Entity> parent_entity) { // No setup or parent to link to - bypass function. if((!parent_entity) || (!setup) || (setup->m_linkBody >= parent_entity->m_bf.bone_tags.size()) || (!(parent_entity->m_bt.bt_body[setup->m_linkBody]))) return false; SkeletalModel* model = engine_world.getModelByID(setup->m_model); // No model to link to - bypass function. if((!model) || (model->mesh_count == 0)) return false; // Setup engine container. FIXME: DOESN'T WORK PROPERLY ATM. m_container.reset(new EngineContainer()); m_container->room = parent_entity->m_self->room; m_container->object_type = OBJECT_HAIR; m_container->object = this; // Setup initial hair parameters. m_ownerChar = parent_entity; // Entity to refer to. m_ownerBody = setup->m_linkBody; // Entity body to refer to. // Setup initial position / angles. btTransform owner_body_transform = parent_entity->m_transform * parent_entity->m_bf.bone_tags[m_ownerBody].full_transform; // Number of elements (bodies) is equal to number of hair meshes. m_elements.clear(); m_elements.resize(model->mesh_count); // Root index should be always zero, as it is how engine determines that it is // connected to head and renders it properly. Tail index should be always the // last element of the hair, as it indicates absence of "child" constraint. m_rootIndex = 0; m_tailIndex = m_elements.size() - 1; // Weight step is needed to determine the weight of each hair body. // It is derived from root body weight and tail body weight. btScalar weight_step = ((setup->m_rootWeight - setup->m_tailWeight) / m_elements.size()); btScalar current_weight = setup->m_rootWeight; for(size_t i = 0; i < m_elements.size(); i++) { // Point to corresponding mesh. m_elements[i].mesh = model->mesh_tree[i].mesh_base; // Begin creating ACTUAL physical hair mesh. btVector3 localInertia(0, 0, 0); btTransform startTransform; // Make collision shape out of mesh. m_elements[i].shape.reset(BT_CSfromMesh(m_elements[i].mesh, true, true, false)); m_elements[i].shape->calculateLocalInertia((current_weight * setup->m_hairInertia), localInertia); // Decrease next body weight to weight_step parameter. current_weight -= weight_step; // Initialize motion state for body. startTransform = owner_body_transform; btDefaultMotionState* motionState = new btDefaultMotionState(startTransform); // Make rigid body. m_elements[i].body.reset(new btRigidBody(current_weight, motionState, m_elements[i].shape.get(), localInertia)); // Damping makes body stop in space by itself, to prevent it from continous movement. m_elements[i].body->setDamping(setup->m_hairDamping[0], setup->m_hairDamping[1]); // Restitution and friction parameters define "bounciness" and "dullness" of hair. m_elements[i].body->setRestitution(setup->m_hairRestitution); m_elements[i].body->setFriction(setup->m_hairFriction); // Since hair is always moving with Lara, even if she's in still state (like, hanging // on a ledge), hair bodies shouldn't deactivate over time. m_elements[i].body->forceActivationState(DISABLE_DEACTIVATION); // Hair bodies must not collide with each other, and also collide ONLY with kinematic // bodies (e. g. animated meshes), or else Lara's ghost object or anything else will be able to // collide with hair! m_elements[i].body->setUserPointer(m_container.get()); bt_engine_dynamicsWorld->addRigidBody(m_elements[i].body.get(), COLLISION_GROUP_CHARACTERS, COLLISION_GROUP_KINEMATIC); m_elements[i].body->activate(); } // GENERATE CONSTRAINTS. // All constraints are generic 6-DOF type, as they seem perfect fit for hair. // Joint count is calculated from overall body amount multiplied by per-body constraint // count. m_joints.resize(m_elements.size()); // If multiple joints per body is specified, joints are placed in circular manner, // with obvious step of (SIMD_2_PI) / joint count. It means that all joints will form // circle-like figure. int curr_joint = 0; for(size_t i = 0; i < m_elements.size(); i++) { btScalar body_length; btTransform localA; localA.setIdentity(); btTransform localB; localB.setIdentity(); btScalar joint_x = 0.0; btScalar joint_y = 0.0; std::shared_ptr<btRigidBody> prev_body; if(i == 0) // First joint group { // Adjust pivot point A to parent body. localA.setOrigin(setup->m_headOffset + btVector3(joint_x, 0.0, joint_y)); localA.getBasis().setEulerZYX(setup->m_rootAngle[0], setup->m_rootAngle[1], setup->m_rootAngle[2]); // Stealing this calculation because I need it for drawing m_ownerBodyHairRoot = localA; localB.setOrigin(btVector3(joint_x, 0.0, joint_y)); localB.getBasis().setEulerZYX(0, -SIMD_HALF_PI, 0); prev_body = parent_entity->m_bt.bt_body[m_ownerBody]; // Previous body is parent body. } else { // Adjust pivot point A to previous mesh's length, considering mesh overlap multiplier. body_length = std::abs(m_elements[i - 1].mesh->m_bbMax[1] - m_elements[i - 1].mesh->m_bbMin[1]) * setup->m_jointOverlap; localA.setOrigin(btVector3(joint_x, body_length, joint_y)); localA.getBasis().setEulerZYX(0, SIMD_HALF_PI, 0); // Pivot point B is automatically adjusted by Bullet. localB.setOrigin(btVector3(joint_x, 0.0, joint_y)); localB.getBasis().setEulerZYX(0, SIMD_HALF_PI, 0); prev_body = m_elements[i - 1].body; // Previous body is preceiding hair mesh. } // Create 6DOF constraint. m_joints[curr_joint].reset(new btGeneric6DofConstraint(*prev_body, *(m_elements[i].body), localA, localB, true)); // CFM and ERP parameters are critical for making joint "hard" and link // to Lara's head. With wrong values, constraints may become "elastic". for(int axis = 0; axis <= 5; axis++) { m_joints[i]->setParam(BT_CONSTRAINT_STOP_CFM, setup->m_jointCfm, axis); m_joints[i]->setParam(BT_CONSTRAINT_STOP_ERP, setup->m_jointErp, axis); } if(i == 0) { // First joint group should be more limited in motion, as it is connected // right to the head. NB: Should we make it scriptable as well? m_joints[curr_joint]->setLinearLowerLimit(btVector3(0., 0., 0.)); m_joints[curr_joint]->setLinearUpperLimit(btVector3(0., 0., 0.)); m_joints[curr_joint]->setAngularLowerLimit(btVector3(-SIMD_HALF_PI, 0., -SIMD_HALF_PI*0.4)); m_joints[curr_joint]->setAngularUpperLimit(btVector3(-SIMD_HALF_PI*0.3, 0., SIMD_HALF_PI*0.4)); // Increased solver iterations make constraint even more stable. m_joints[curr_joint]->setOverrideNumSolverIterations(100); } else { // Normal joint with more movement freedom. m_joints[curr_joint]->setLinearLowerLimit(btVector3(0., 0., 0.)); m_joints[curr_joint]->setLinearUpperLimit(btVector3(0., 0., 0.)); m_joints[curr_joint]->setAngularLowerLimit(btVector3(-SIMD_HALF_PI*0.5, 0., -SIMD_HALF_PI*0.5)); m_joints[curr_joint]->setAngularUpperLimit(btVector3(SIMD_HALF_PI*0.5, 0., SIMD_HALF_PI*0.5)); } m_joints[curr_joint]->setDbgDrawSize(btScalar(5.f)); // Draw constraint axes. // Add constraint to the world. bt_engine_dynamicsWorld->addConstraint(m_joints[curr_joint].get(), true); curr_joint++; // Point to the next joint. } createHairMesh(model); return true; }
int main() { int i, j; btDefaultCollisionConfiguration *collisionConfiguration = new btDefaultCollisionConfiguration(); btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration); btBroadphaseInterface *overlappingPairCache = new btDbvtBroadphase(); btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver; btDiscreteDynamicsWorld *dynamicsWorld = new btDiscreteDynamicsWorld( dispatcher, overlappingPairCache, solver, collisionConfiguration); dynamicsWorld->setGravity(btVector3(0, gravity, 0)); dynamicsWorld->setInternalTickCallback(myTickCallback); btAlignedObjectArray<btCollisionShape*> collisionShapes; // Ground. { btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0, 0, 0)); btCollisionShape* groundShape; #if 1 // x / z plane at y = -1. groundShape = new btStaticPlaneShape(btVector3(groundXNormal, 1, 0), -1); #else // A cube of width 10 at y = -6. // Does not fall because we won't call: // colShape->calculateLocalInertia // TODO: remove this from this example into a collision shape example. groundTransform.setOrigin(btVector3(0, -6, 0)); groundShape = new btBoxShape( btVector3(btScalar(5.0), btScalar(5.0), btScalar(5.0))); #endif collisionShapes.push_back(groundShape); btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(0, myMotionState, groundShape, btVector3(0, 0, 0)); btRigidBody* body = new btRigidBody(rbInfo); body->setRestitution(groundRestitution); dynamicsWorld->addRigidBody(body); } // Object. { btCollisionShape *colShape; #if 1 colShape = new btSphereShape(btScalar(1.0)); #else // Because of numerical instabilities, the cube spins all over, // moving on the x and y directions. colShape = new btBoxShape( btVector3(btScalar(1.0), btScalar(1.0), btScalar(1.0))); #endif collisionShapes.push_back(colShape); btTransform startTransform; startTransform.setIdentity(); startTransform.setOrigin(btVector3(0, initialY, 0)); btVector3 localInertia(0, 0, 0); btScalar mass(1.0f); colShape->calculateLocalInertia(mass, localInertia); btDefaultMotionState *myMotionState = new btDefaultMotionState(startTransform); btRigidBody *body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo( mass, myMotionState, colShape, localInertia)); body->setRestitution(objectRestitution); dynamicsWorld->addRigidBody(body); } // Main loop. std::printf("step body x y z collision a b normal\n"); for (i = 0; i < maxNPoints; ++i) { dynamicsWorld->stepSimulation(timeStep); for (j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; --j) { btCollisionObject *obj = dynamicsWorld->getCollisionObjectArray()[j]; btRigidBody *body = btRigidBody::upcast(obj); btTransform trans; if (body && body->getMotionState()) { body->getMotionState()->getWorldTransform(trans); } else { trans = obj->getWorldTransform(); } btVector3 origin = trans.getOrigin(); std::printf("%d %d " PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " ", i, j, origin.getX(), origin.getY(), origin.getZ()); auto& manifoldPoints = objectsCollisions[body]; if (manifoldPoints.empty()) { std::printf("0 "); } else { std::printf("1 "); for (auto& pt : manifoldPoints) { std::vector<btVector3> data; data.push_back(pt->getPositionWorldOnA()); data.push_back(pt->getPositionWorldOnB()); data.push_back(pt->m_normalWorldOnB); for (auto& v : data) { std::printf( PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " ", v.getX(), v.getY(), v.getZ()); } } } puts(""); } } // Cleanup. for (i = dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; --i) { btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i]; btRigidBody* body = btRigidBody::upcast(obj); if (body && body->getMotionState()) { delete body->getMotionState(); } dynamicsWorld->removeCollisionObject(obj); delete obj; } for (i = 0; i < collisionShapes.size(); ++i) { delete collisionShapes[i]; } delete dynamicsWorld; delete solver; delete overlappingPairCache; delete dispatcher; delete collisionConfiguration; collisionShapes.clear(); }
void RigidBodySoftContact::initPhysics() { m_guiHelper->setUpAxis(1); //createEmptyDynamicsWorld(); { ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; //btMLCPSolver* sol = new btMLCPSolver(new btSolveProjectedGaussSeidel()); m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); m_dynamicsWorld->setGravity(btVector3(0, -10, 0)); } m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); if (m_dynamicsWorld->getDebugDrawer()) m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints); m_dynamicsWorld->getSolverInfo().m_erp2 = 0.f; m_dynamicsWorld->getSolverInfo().m_globalCfm = 0.f; m_dynamicsWorld->getSolverInfo().m_numIterations = 3; m_dynamicsWorld->getSolverInfo().m_solverMode = SOLVER_SIMD;// | SOLVER_RANDMIZE_ORDER; m_dynamicsWorld->getSolverInfo().m_splitImpulse = false; ///create a few basic rigid bodies btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); //groundShape->initializePolyhedralFeatures(); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0,-50,0)); { btScalar mass(0.); btRigidBody* body = createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); body->setContactStiffnessAndDamping(300,10); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance //btBoxShape* colShape = createBoxShape(btVector3(1,1,1)); btCollisionShape* childShape = new btSphereShape(btScalar(0.5)); btCompoundShape* colShape = new btCompoundShape(); colShape->addChildShape(btTransform::getIdentity(),childShape); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); startTransform.setRotation(btQuaternion(btVector3(1,1,1),SIMD_PI/10.)); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { startTransform.setOrigin(btVector3( btScalar(2.0*i+0.1), btScalar(3+2.0*k), btScalar(2.0*j))); btRigidBody* body = createRigidBody(mass,startTransform,colShape); //body->setAngularVelocity(btVector3(1,1,1)); } } } } m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); }
void RaytestDemo::initPhysics() { m_ele = 10; m_azi = 75; setTexturing(true); setShadows(true); setCameraDistance(btScalar(20.)); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld ->setDebugDrawer(&sDebugDraw); m_dynamicsWorld->setGravity(btVector3(0,-10,0)); ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); 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); body->setRollingFriction(1); body->setFriction(1); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } { btVector3 convexPoints[]={ btVector3(-1,-1,-1),btVector3(-1,-1,1),btVector3(-1,1,1),btVector3(-1,1,-1), btVector3(2,0,0)}; btVector3 quad[] = { btVector3(0,1,-1), btVector3(0,1,1), btVector3(0,-1,1), btVector3(0,-1,-1)}; btTriangleMesh* mesh = new btTriangleMesh(); mesh->addTriangle(quad[0],quad[1],quad[2],true); mesh->addTriangle(quad[0],quad[2],quad[3],true); //btBvhTriangleMeshShape* trimesh = new btBvhTriangleMeshShape(mesh,true,true); btGImpactMeshShape * trimesh = new btGImpactMeshShape(mesh); trimesh->updateBound(); #define NUM_SHAPES 6 btCollisionShape* colShapes[NUM_SHAPES] = { trimesh, new btConvexHullShape(&convexPoints[0].getX(),sizeof(convexPoints)/sizeof(btVector3),sizeof(btVector3)), new btSphereShape(1), new btCapsuleShape(0.2,1), new btCylinderShape(btVector3(0.2,1,0.2)), new btBoxShape(btVector3(1,1,1)) }; for (int i=0;i<NUM_SHAPES;i++) m_collisionShapes.push_back(colShapes[i]); for (int i=0;i<6;i++) { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); startTransform.setOrigin(btVector3((i-3)*5,1,0)); btScalar mass(1.f); if (!i) mass=0.f; //rigidbody is dynamic if and only if mass is non zero, otherwise static bool isDynamic = (mass != 0.f); btVector3 localInertia(0,0,0); btCollisionShape* colShape = colShapes[i%NUM_SHAPES]; if (isDynamic) colShape->calculateLocalInertia(mass,localInertia); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); rbInfo.m_startWorldTransform = startTransform; btRigidBody* body = new btRigidBody(rbInfo); body->setRollingFriction(0.03); body->setFriction(1); body->setAnisotropicFriction(colShape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); m_dynamicsWorld->addRigidBody(body); } } }
void BasicDemo::initPhysics() { setTexturing(true); setShadows(true); setCameraDistance(btScalar(SCALING*50.)); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld->setGravity(btVector3(0,-10,0)); ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); 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); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); float start_x = START_POS_X - ARRAY_SIZE_X/2; float start_y = START_POS_Y; float start_z = START_POS_Z - ARRAY_SIZE_Z/2; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { startTransform.setOrigin(SCALING*btVector3( btScalar(2.0*i + start_x), btScalar(20+2.0*k + start_y), btScalar(2.0*j + start_z))); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); body->setActivationState(ISLAND_SLEEPING); m_dynamicsWorld->addRigidBody(body); body->setActivationState(ISLAND_SLEEPING); } } } } clientResetScene(); #ifdef TEST_SERIALIZATION //test serializing this int maxSerializeBufferSize = 1024*1024*5; btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize); m_dynamicsWorld->serialize(serializer); FILE* f2 = fopen("testFile.bullet","wb"); fwrite(serializer->m_buffer,serializer->m_currentSize,1,f2); fclose(f2); #endif #if 0 bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile("testFile.bullet"); bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0; bool verboseDumpAllTypes = true; if (ok) bulletFile2->parse(verboseDumpAllTypes); if (verboseDumpAllTypes) { bulletFile2->dumpChunks(bulletFile2->getFileDNA()); } #endif //TEST_SERIALIZATION }
HeightmapNode::HeightmapNode(EditorScene * _scene, Landscape *_land) : Entity() , position(0,0,0) , rotation(0) { SetName("HeightmapNode"); editorScene = _scene; SetVisible(false); land = _land; DVASSERT(land); //Get LandSize; Vector3 landSize; AABBox3 transformedBox; Matrix4 * worldTransformPtr = land->GetWorldTransformPtr(); land->GetBoundingBox().GetTransformedBox(*worldTransformPtr, transformedBox); landSize = transformedBox.max - transformedBox.min; heightmap = land->GetHeightmap(); sizeInMeters = landSize.x; areaScale = sizeInMeters / heightmap->Size(); maxHeight = landSize.z; heightScale = maxHeight / 65535.f; float32 minHeight = 0.0f; uint16 *dt = heightmap->Data(); size.x = (float32)heightmap->Size(); size.y = (float32)heightmap->Size(); hmap.resize(heightmap->Size() * heightmap->Size()); for (int32 y = 0; y < heightmap->Size(); ++y) { for (int32 x = 0; x < heightmap->Size(); ++x) { int32 index = x + (y) * heightmap->Size(); float32 mapValue = dt[index] * heightScale; SetValueToMap(x, y, mapValue, transformedBox); } } bool flipQuadEdges = true; colShape = new btHeightfieldTerrainShape(heightmap->Size(), heightmap->Size() , &hmap.front(), heightScale, minHeight, maxHeight , 2, PHY_FLOAT , flipQuadEdges); colShape->setLocalScaling(btVector3(areaScale, areaScale, 1.0f)); // Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(0.0f); //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) colShape->calculateLocalInertia(mass,localInertia); startTransform.setOrigin(btVector3( btScalar(position.x), btScalar(position.y), btScalar(maxHeight/2.0f + position.z))); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects motionSate = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,motionSate,colShape,localInertia); rbInfo.m_friction = 0.9f; body = new btRigidBody(rbInfo); collisionObject = new btCollisionObject(); collisionObject->setWorldTransform(startTransform); collisionObject->setCollisionShape(colShape); editorScene->landCollisionWorld->addCollisionObject(collisionObject); editorScene->landCollisionWorld->updateAabbs(); }
void BasicDemo::initPhysics() { setTexturing(false); setShadows(false); #if OECAKE_LOADER setCameraDistance(80.); m_cameraTargetPosition.setValue(50, 10, 0); #else #if LARGE_DEMO setCameraDistance(btScalar(SCALING*100.)); #else setCameraDistance(btScalar(SCALING*20.)); #endif m_cameraTargetPosition.setValue(START_POS_X, -START_POS_Y-20, START_POS_Z); #endif m_azi = btScalar(0.f); m_ele = btScalar(0.f); ///collision configuration contains default setup for memory, collision setup btDefaultCollisionConstructionInfo dci; dci.m_defaultMaxPersistentManifoldPoolSize=50000; dci.m_defaultMaxCollisionAlgorithmPoolSize=50000; m_collisionConfiguration = new btDefaultCollisionConfiguration(dci); ///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->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,new btEmptyAlgorithm::CreateFunc); m_dispatcher->setNearCallback(cudaDemoNearCallback); #if USE_CUDA_DEMO_PAIR_CASHE gPairCache = new (btAlignedAlloc(sizeof(btGpuDemoPairCache),16)) btGpuDemoPairCache(MAX_PROXIES, 24, MAX_SMALL_PROXIES); #else gPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache(); #endif // btVector3 numOfCells = (gWorldMax - gWorldMin) / (2. * SCALING); // btVector3 numOfCells = (gWorldMax - gWorldMin) / CELL_SIZE; // int numOfCellsX = (int)numOfCells[0]; // int numOfCellsY = (int)numOfCells[1]; // int numOfCellsZ = (int)numOfCells[2]; // if(!numOfCellsX) numOfCellsX = 1; // if(!numOfCellsY) numOfCellsY = 1; // if(!numOfCellsZ) numOfCellsZ = 1; btScalar maxDiam = 2.0f * SCALING; btVector3 cellSize(maxDiam, maxDiam, maxDiam); btVector3 numOfCells = (gWorldMax - gWorldMin) / cellSize; int numOfCellsX = btGpu3DGridBroadphase::getFloorPowOfTwo((int)numOfCells[0]); int numOfCellsY = btGpu3DGridBroadphase::getFloorPowOfTwo((int)numOfCells[1]); int numOfCellsZ = btGpu3DGridBroadphase::getFloorPowOfTwo((int)numOfCells[2]); // m_broadphase = new btAxisSweep3(gWorldMin, gWorldMax, MAX_PROXIES,gPairCache); // m_broadphase = new btDbvtBroadphase(gPairCache); // m_broadphase = new btGpu3DGridBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,20,24,24, 1.0f/1.5f); // m_broadphase = new btCudaBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,24,24); // m_broadphase = new bt3dGridBroadphaseOCL(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,20,24,24,1./1.5); m_broadphase = new bt3dGridBroadphaseOCL(gPairCache, cellSize,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,20,24,10.f, 24); ///the default constraint solver m_solver = new btSequentialImpulseConstraintSolver(); btGpuDemoDynamicsWorld* pDdw = new btGpuDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, MAX_PROXIES); m_dynamicsWorld = pDdw; m_pWorld = pDdw; pDdw->getSimulationIslandManager()->setSplitIslands(true); pDdw->setObjRad(SCALING); pDdw->setWorldMin(gWorldMin); pDdw->setWorldMax(gWorldMax); // gUseCPUSolver = true; pDdw->setUseCPUSolver(gUseCPUSolver); gUseBulletNarrowphase = false; pDdw->setUseBulletNarrowphase(gUseBulletNarrowphase); // m_dynamicsWorld->setGravity(btVector3(0,0,0)); m_dynamicsWorld->setGravity(btVector3(0,-10.,0)); m_dynamicsWorld->getSolverInfo().m_numIterations = 4; { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance #if 1 #define SPRADIUS btScalar(SCALING*0.1f) #define SPRPOS btScalar(SCALING*0.05f) static btVector3 sSphPos[8]; for (int k=0;k<8;k++) { sSphPos[k].setValue((k-4)*0.25*SCALING,0,0); } btVector3 inertiaHalfExtents(SPRADIUS, SPRADIUS, SPRADIUS); static btScalar sSphRad[8] = { // SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS,SPRADIUS, SPRADIUS, SPRADIUS, 0.3 SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS,SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS }; // sSphPos[0].setX(sSphPos[0].getX()-0.15); #undef SPR btMultiSphereShape* colShape[2]; colShape[0] = new btMultiSphereShape( sSphPos, sSphRad, 8); colShape[1] = new btMultiSphereShape( sSphPos, sSphRad, 2); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); m_collisionShapes.push_back(colShape[0]); m_collisionShapes.push_back(colShape[1]); #endif /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(0.f); //rigidbody is dynamic if and only if mass is non zero, otherwise static bool isDynamic = (mass != 0.f); btVector3 localInertia(0,0,0); #if OECAKE_LOADER BasicDemoOecakeLoader loader(this); if (!loader.processFile("test1.oec")) { loader.processFile("../../../../../Demos/Gpu2dDemo/test.oec"); } #if 0 // perfomance test : work-in-progress { // add more object, but share their shapes int numNewObjects = 500; mass = 1.f; for(int n_obj = 0; n_obj < numNewObjects; n_obj++) { btDefaultMotionState* myMotionState= 0; btVector3 localInertia(0,0,0); btTransform worldTransform; worldTransform.setIdentity(); btScalar fx = fRandMinMax(-30., 30.); btScalar fy = fRandMinMax(5., 30.); worldTransform.setOrigin(btVector3(fx, fy, 0.f)); int sz = m_collisionShapes.size(); btMultiSphereShape* multiSphere = (btMultiSphereShape*)m_collisionShapes[1]; myMotionState = new btDefaultMotionState(worldTransform); multiSphere->calculateLocalInertia(mass, localInertia); btRigidBody* body = new btRigidBody(mass,myMotionState,multiSphere,localInertia); body->setLinearFactor(btVector3(1,1,0)); body->setAngularFactor(btVector3(0,0,1)); body->setWorldTransform(worldTransform); getDynamicsWorld()->addRigidBody(body); } } #endif #else #if (!SPEC_TEST) float start_x = START_POS_X - ARRAY_SIZE_X * SCALING; float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING; float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING; int collisionShapeIndex = 0; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { float offs = (2. * (float)rand() / (float)RAND_MAX - 1.f) * 0.05f; startTransform.setOrigin(SCALING*btVector3( 2.0*SCALING*i + start_x + offs, 2.0*SCALING*k + start_y + offs, 2.0*SCALING*j + start_z)); if (isDynamic) colShape[collisionShapeIndex]->calculateLocalInertia(mass,localInertia); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects //btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape[collisionShapeIndex],localInertia); collisionShapeIndex = 1 - collisionShapeIndex; rbInfo.m_startWorldTransform=startTransform; btRigidBody* body = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body); } } } #else//SPEC_TEST // narrowphase test - 2 bodies at the same position float start_x = START_POS_X; // float start_y = START_POS_Y; float start_y = gWorldMin[1] + SCALING * 0.7f + 5.f; float start_z = START_POS_Z; startTransform.setOrigin(SCALING*btVector3(start_x,start_y,start_z)); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape[0],localInertia); rbInfo.m_startWorldTransform=startTransform; btRigidBody* body = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body); btPoint2PointConstraint * p2pConstr = new btPoint2PointConstraint(*body, btVector3(1., 0., 0.)); m_dynamicsWorld->addConstraint(p2pConstr); startTransform.setOrigin(SCALING*btVector3(start_x-2.f, start_y,start_z)); rbInfo.m_startWorldTransform=startTransform; btRigidBody* body1 = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body1); p2pConstr = new btPoint2PointConstraint(*body, *body1, btVector3(-1., 0., 0.), btVector3(1., 0., 0.)); m_dynamicsWorld->addConstraint(p2pConstr); #endif//SPEC_TEST #endif //OE_CAKE_LOADER } // now set Ids used by collision detector and constraint solver int numObjects = m_dynamicsWorld->getNumCollisionObjects(); btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray(); for(int i = 0; i < numObjects; i++) { btCollisionObject* colObj = collisionObjects[i]; colObj->setCompanionId(i+1); // 0 reserved for the "world" object btCollisionShape* pShape = colObj->getCollisionShape(); int shapeType = pShape->getShapeType(); if(shapeType == MULTI_SPHERE_SHAPE_PROXYTYPE) { btMultiSphereShape* pMs = (btMultiSphereShape*)pShape; int numSpheres = pMs->getSphereCount(); pDdw->addMultiShereObject(numSpheres, i + 1); for(int j = 0; j < numSpheres; j++) { btVector3 sphPos = pMs->getSpherePosition(j); float sphRad = pMs->getSphereRadius(j); pDdw->addSphere(sphPos, sphRad); } } else { btAssert(0); } } #if OECAKE_LOADER clientResetScene(); #endif }
void BasicDemo::initPhysics() { setTexturing(true); setShadows(true); setCameraDistance(btScalar(SCALING*50.)); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; //btParallelConstraintSolver* sol = new btParallelConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld->setGravity(btVector3(0,-10,0)); ///create a few basic rigid bodies btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); 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); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass,localInertia); float start_x = START_POS_X - ARRAY_SIZE_X/2; float start_y = START_POS_Y; float start_z = START_POS_Z - ARRAY_SIZE_Z/2; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { startTransform.setOrigin(SCALING*btVector3( btScalar(2.0*i + start_x), btScalar(20+2.0*k + start_y), btScalar(2.0*j + start_z))); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body); } } } } }
PintObjectHandle Bullet::CreateObject(const PINT_OBJECT_CREATE& desc) { udword NbShapes = desc.GetNbShapes(); if(!NbShapes) return null; ASSERT(mDynamicsWorld); const PINT_SHAPE_CREATE* CurrentShape = desc.mShapes; float FrictionCoeff = 0.5f; float RestitutionCoeff = 0.0f; btCollisionShape* colShape = null; if(NbShapes>1) { btCompoundShape* CompoundShape = new btCompoundShape(); colShape = CompoundShape; mCollisionShapes.push_back(colShape); while(CurrentShape) { if(CurrentShape->mMaterial) { FrictionCoeff = CurrentShape->mMaterial->mDynamicFriction; RestitutionCoeff = CurrentShape->mMaterial->mRestitution; } const btTransform LocalPose(ToBtQuaternion(CurrentShape->mLocalRot), ToBtVector3(CurrentShape->mLocalPos)); // ### TODO: where is this deleted? btCollisionShape* subShape = CreateBulletShape(*CurrentShape); if(subShape) { CompoundShape->addChildShape(LocalPose, subShape); } CurrentShape = CurrentShape->mNext; } } else { colShape = CreateBulletShape(*CurrentShape); if(CurrentShape->mMaterial) { FrictionCoeff = CurrentShape->mMaterial->mDynamicFriction; RestitutionCoeff = CurrentShape->mMaterial->mRestitution; } } const bool isDynamic = (desc.mMass != 0.0f); btVector3 localInertia(0,0,0); if(isDynamic) colShape->calculateLocalInertia(desc.mMass, localInertia); const btTransform startTransform(ToBtQuaternion(desc.mRotation), ToBtVector3(desc.mPosition)); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(desc.mMass, myMotionState, colShape, localInertia); { rbInfo.m_friction = FrictionCoeff; rbInfo.m_restitution = RestitutionCoeff; // rbInfo.m_startWorldTransform; rbInfo.m_linearDamping = gLinearDamping; rbInfo.m_angularDamping = gAngularDamping; if(!gEnableSleeping) { // rbInfo.m_linearSleepingThreshold = 99999999.0f; // rbInfo.m_angularSleepingThreshold = 99999999.0f; // rbInfo.m_linearSleepingThreshold = 0.0f; // rbInfo.m_angularSleepingThreshold = 0.0f; } // rbInfo.m_additionalDamping; // rbInfo.m_additionalDampingFactor; // rbInfo.m_additionalLinearDampingThresholdSqr; // rbInfo.m_additionalAngularDampingThresholdSqr; // rbInfo.m_additionalAngularDampingFactor; } btRigidBody* body = new btRigidBody(rbInfo); ASSERT(body); if(!gEnableSleeping) body->setActivationState(DISABLE_DEACTIVATION); sword collisionFilterGroup, collisionFilterMask; if(isDynamic) { body->setLinearVelocity(ToBtVector3(desc.mLinearVelocity)); body->setAngularVelocity(ToBtVector3(desc.mAngularVelocity)); collisionFilterGroup = short(btBroadphaseProxy::DefaultFilter); collisionFilterMask = short(btBroadphaseProxy::AllFilter); if(desc.mCollisionGroup) { const udword btGroup = RemapCollisionGroup(desc.mCollisionGroup); ASSERT(btGroup<32); collisionFilterGroup = short(1<<btGroup); collisionFilterMask = short(mGroupMasks[btGroup]); } } else { // body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT); body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT|btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); collisionFilterGroup = short(btBroadphaseProxy::StaticFilter); collisionFilterMask = short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); } if(desc.mAddToWorld) // mDynamicsWorld->addRigidBody(body); mDynamicsWorld->addRigidBody(body, collisionFilterGroup, collisionFilterMask); if(gUseCCD) { // body->setCcdMotionThreshold(1e-7); // body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS); body->setCcdMotionThreshold(0.0001f); body->setCcdSweptSphereRadius(0.4f); } return body; }
void RigidBody::UpdateMass() { if (!body_ || !enableMassUpdate_) return; btTransform principal; principal.setRotation(btQuaternion::getIdentity()); principal.setOrigin(btVector3(0.0f, 0.0f, 0.0f)); // Calculate center of mass shift from all the collision shapes unsigned numShapes = (unsigned)compoundShape_->getNumChildShapes(); if (numShapes) { PODVector<float> masses(numShapes); for (unsigned i = 0; i < numShapes; ++i) { // The actual mass does not matter, divide evenly between child shapes masses[i] = 1.0f; } btVector3 inertia(0.0f, 0.0f, 0.0f); compoundShape_->calculatePrincipalAxisTransform(&masses[0], principal, inertia); } // Add child shapes to shifted compound shape with adjusted offset while (shiftedCompoundShape_->getNumChildShapes()) shiftedCompoundShape_->removeChildShapeByIndex(shiftedCompoundShape_->getNumChildShapes() - 1); for (unsigned i = 0; i < numShapes; ++i) { btTransform adjusted = compoundShape_->getChildTransform(i); adjusted.setOrigin(adjusted.getOrigin() - principal.getOrigin()); shiftedCompoundShape_->addChildShape(adjusted, compoundShape_->getChildShape(i)); } // If shifted compound shape has only one child with no offset/rotation, use the child shape // directly as the rigid body collision shape for better collision detection performance bool useCompound = !numShapes || numShapes > 1; if (!useCompound) { const btTransform& childTransform = shiftedCompoundShape_->getChildTransform(0); if (!ToVector3(childTransform.getOrigin()).Equals(Vector3::ZERO) || !ToQuaternion(childTransform.getRotation()).Equals(Quaternion::IDENTITY)) useCompound = true; } body_->setCollisionShape(useCompound ? shiftedCompoundShape_ : shiftedCompoundShape_->getChildShape(0)); // If we have one shape and this is a triangle mesh, we use a custom material callback in order to adjust internal edges if (!useCompound && body_->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE && physicsWorld_->GetInternalEdge()) body_->setCollisionFlags(body_->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); else body_->setCollisionFlags(body_->getCollisionFlags() & ~btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); // Reapply rigid body position with new center of mass shift Vector3 oldPosition = GetPosition(); centerOfMass_ = ToVector3(principal.getOrigin()); SetPosition(oldPosition); // Calculate final inertia btVector3 localInertia(0.0f, 0.0f, 0.0f); if (mass_ > 0.0f) shiftedCompoundShape_->calculateLocalInertia(mass_, localInertia); body_->setMassProps(mass_, localInertia); body_->updateInertiaTensor(); // Reapply constraint positions for new center of mass shift if (node_) { for (PODVector<Constraint*>::Iterator i = constraints_.Begin(); i != constraints_.End(); ++i) (*i)->ApplyFrames(); } }
CFootballPlayer::CFootballPlayer(CSimulationManager *simulationManager, const CPfTeamPlayers *teamPlayer, int number, CTeam *team, bool sideLeft) :CMovingEntity() { m_simulationManager = simulationManager; Ogre::SceneManager *scnMgr = Ogre::Root::getSingletonPtr()->getSceneManager(SIMULATION_SCENE_MANAGER_NODE_NAME); m_teamPlayer = new CPfTeamPlayers(*teamPlayer); m_stateMachine = new CStateMachine<CFootballPlayer>(this); Ogre::String id; std::ostringstream charId; m_centerOfMassOffset.setOrigin(btVector3(0,-0.9,0)); m_sideLeft = sideLeft; m_team = team; m_number = number; //TODO m_lastKickBallCycle = -1; CSystemOptionManager* optionManager = CSystemOptionManager::getInstance(); int maxPlayerVelocity = optionManager->getSimulationMaxPlayerVelocity(); int maxKickPower = optionManager->getSimulationMaxKickPower(); m_maxVelocity = maxPlayerVelocity * (m_teamPlayer->getNVelocity()/100.0); m_maxKickPower = maxKickPower * (m_teamPlayer->getNKickPower()/100.0); m_maxKickDistance = optionManager->getSimulationMaxKickDistance(); //m_direction.normalize(); charId << team->getName().c_str() << m_number; id = charId.str(); m_entity = scnMgr->createEntity("Player"+id, "Human.mesh"); if(sideLeft) { if(m_number == 1) { m_entity->setMaterialName("goalie_red"); } else { m_entity->setMaterialName("player_red"); } } else { if(m_number == 1) { m_entity->setMaterialName("goalie_yellow"); } else { m_entity->setMaterialName("player_yellow"); } } btVector3 *initialPos = team->getPlayerStrategicPosition(m_number)->getInitialPosition(); btVector3 pos(initialPos->x(), initialPos->y(), initialPos->z()); if(!m_sideLeft) { pos.setX(-pos.x()); pos.setZ(-pos.z()); } m_node = scnMgr->getRootSceneNode()->createChildSceneNode("PlayerNode"+id, Ogre::Vector3(pos.x(), pos.y(), pos.z())); m_node->attachObject(m_entity); m_shape = new btCylinderShape(btVector3(btScalar(0.5),btScalar(0.9),btScalar(0.5))); btScalar mass(70.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) m_shape->calculateLocalInertia(mass,localInertia); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,this,m_shape,localInertia); m_body = new btRigidBody(rbInfo); m_body->setAngularFactor(btScalar(0)); m_body->setActivationState(DISABLE_DEACTIVATION); m_steeringBehavior = new CSteeringBehaviors(this); //Draw Circle Ogre::ManualObject * circle = scnMgr->createManualObject("circle_name"+id); float const radius = 1.5, thickness = 0.7, // Of course this must be less than the radius value. accuracy = 5, height = 0.01; Ogre::MaterialPtr matptr; Ogre::Pass* pass; if(sideLeft) { matptr = Ogre::MaterialManager::getSingleton().createOrRetrieve("Red"+id, "General").first; matptr->setReceiveShadows(true); pass = matptr->getTechnique(0)->getPass(0); Ogre::ColourValue colour = Ogre::ColourValue::Red; pass->setDiffuse(colour); pass->setAmbient(colour); pass->setDepthWriteEnabled(true); } else { matptr = Ogre::MaterialManager::getSingleton().createOrRetrieve("Blue"+id, "General").first; matptr->setReceiveShadows(true); pass = matptr->getTechnique(0)->getPass(0); Ogre::ColourValue colour = Ogre::ColourValue::Blue; pass->setDiffuse(colour); pass->setAmbient(colour); pass->setDepthWriteEnabled(true); } circle->begin(matptr->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST); unsigned point_index = 0; for(float theta = 0; theta <= 2 * Ogre::Math::PI; theta += Ogre::Math::PI / (radius * accuracy)) { circle->position(radius * cos(theta), height, radius * sin(theta)); circle->position(radius * cos(theta - Ogre::Math::PI / (radius * accuracy)), height, radius * sin(theta - Ogre::Math::PI / (radius * accuracy))); circle->position((radius - thickness) * cos(theta - Ogre::Math::PI / (radius * accuracy)), height, (radius - thickness) * sin(theta - Ogre::Math::PI / (radius * accuracy))); circle->position((radius - thickness) * cos(theta), height, (radius - thickness) * sin(theta)); // Join the 4 vertices created above to form a quad. circle->quad(point_index, point_index + 1, point_index + 2, point_index + 3); point_index += 4; } circle->end(); m_ringNode = m_node->createChildSceneNode(); m_ringNode->attachObject(circle); }
void SimpleJointExample::initPhysics() { m_guiHelper->setUpAxis(1); createEmptyDynamicsWorld(); m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); if (m_dynamicsWorld->getDebugDrawer()) m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe + btIDebugDraw::DBG_DrawContactPoints); ///create a few basic rigid bodies btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.), btScalar(50.), btScalar(50.))); m_collisionShapes.push_back(groundShape); btTransform groundTransform; groundTransform.setIdentity(); groundTransform.setOrigin(btVector3(0, -50, 0)); { btScalar mass(0.); createRigidBody(mass, groundTransform, groundShape, btVector4(0, 0, 1, 1)); } { //create a few dynamic rigidbodies // Re-using the same collision is better for memory usage and performance btBoxShape* colShape = createBoxShape(btVector3(1, 1, 1)); m_collisionShapes.push_back(colShape); /// Create Dynamic Objects btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); //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) colShape->calculateLocalInertia(mass, localInertia); startTransform.setOrigin(btVector3( btScalar(0), btScalar(10), btScalar(0))); btRigidBody* dynamicBox = createRigidBody(mass, startTransform, colShape); //create a static rigid body mass = 0; startTransform.setOrigin(btVector3( btScalar(0), btScalar(20), btScalar(0))); btRigidBody* staticBox = createRigidBody(mass, startTransform, colShape); //create a simple p2pjoint constraint btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*dynamicBox, *staticBox, btVector3(0, 3, 0), btVector3(0, 0, 0)); p2p->m_setting.m_damping = 0.0625; p2p->m_setting.m_impulseClamp = 0.95; m_dynamicsWorld->addConstraint(p2p); } m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); }