btCriticalSection* Win32ThreadSupport::createCriticalSection() { unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16); btWin32CriticalSection* cs = new(mem) btWin32CriticalSection(); return cs; }
btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) //btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) { void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); m_simplexSolver = new (mem)btVoronoiSimplexSolver(); #define USE_EPA 1 #ifdef USE_EPA mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; #else mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16); m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver; #endif//USE_EPA //default CreationFunctions, filling the m_doubleDispatch table mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; #ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; m_boxSphereCF->m_swapped = true; #endif //USE_BUGGY_SPHERE_BOX_ALGORITHM mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; m_triangleSphereCF->m_swapped = true; mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16); m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc; //convex versus plane mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; m_planeConvexCF->m_swapped = true; ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool int maxSize = sizeof(btConvexConvexAlgorithm); int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); int maxSize3 = sizeof(btCompoundCollisionAlgorithm); int sl = sizeof(btConvexSeparatingDistanceUtil); sl = sizeof(btGjkPairDetector); int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2); collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); if (constructionInfo.m_stackAlloc) { m_ownsStackAllocator = false; this->m_stackAlloc = constructionInfo.m_stackAlloc; } else { m_ownsStackAllocator = true; void* mem = btAlignedAlloc(sizeof(btStackAlloc),16); m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize); } if (constructionInfo.m_persistentManifoldPool) { m_ownsPersistentManifoldPool = false; m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool; } else { m_ownsPersistentManifoldPool = true; void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize); } if (constructionInfo.m_collisionAlgorithmPool) { m_ownsCollisionAlgorithmPool = false; m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool; } else { m_ownsCollisionAlgorithmPool = true; void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); } }
void ParticlesDemo::initPhysics() { setTexturing(false); setShadows(false); // setCameraDistance(80.f); setCameraDistance(3.0f); // m_cameraTargetPosition.setValue(50, 10, 0); m_cameraTargetPosition.setValue(0, 0, 0); // m_azi = btScalar(0.f); // m_ele = btScalar(0.f); m_azi = btScalar(45.f); m_ele = btScalar(30.f); setFrustumZPlanes(0.1f, 10.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_pairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache(); // m_broadphase = new btDbvtBroadphase(m_pairCache); m_broadphase = new btNullBroadphase(); ///the default constraint solver m_solver = new btSequentialImpulseConstraintSolver(); m_pWorld = new btParticlesDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, 65536); m_dialogDynamicsWorld = new GL_DialogDynamicsWorld(); GL_DialogWindow* settings = m_dialogDynamicsWorld->createDialog(50,0,280,280,"CPU fallback"); m_pWorld->m_useCpuControls[0] = 0; GL_ToggleControl* ctrl = 0; m_pWorld->m_useCpuControls[SIMSTAGE_INTEGRATE_MOTION] = m_dialogDynamicsWorld->createToggle(settings,"Integrate Motion"); m_pWorld->m_useCpuControls[SIMSTAGE_COMPUTE_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Compute Cell ID"); m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Sort Cell ID"); m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START] = m_dialogDynamicsWorld->createToggle(settings,"Find Cell Start"); m_pWorld->m_useCpuControls[SIMSTAGE_COLLIDE_PARTICLES] = m_dialogDynamicsWorld->createToggle(settings,"Collide Particles"); for(int i = 1; i < SIMSTAGE_TOTAL; i++) { m_pWorld->m_useCpuControls[i]->m_active = false; } #if defined(CL_PLATFORM_MINI_CL) // these kernels use barrier() m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active = true; #endif // out of date // m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; //m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active = true; m_dynamicsWorld = m_pWorld; m_pWorld->getSimulationIslandManager()->setSplitIslands(true); m_pWorld->setGravity(btVector3(0,-10.,0)); m_pWorld->getSolverInfo().m_numIterations = 4; { // btCollisionShape* colShape = new btSphereShape(btScalar(1.0f)); /* btCollisionShape* colShape = new btSphereShape(DEF_PARTICLE_RADIUS); m_collisionShapes.push_back(colShape); btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); btVector3 localInertia(0,0,0); colShape->calculateLocalInertia(mass,localInertia); float start_x = START_POS_X - ARRAY_SIZE_X * DIST * btScalar(0.5f); float start_y = START_POS_Y - ARRAY_SIZE_Y * DIST * btScalar(0.5f); float start_z = START_POS_Z - ARRAY_SIZE_Z * DIST * btScalar(0.5f); startTransform.setOrigin(btVector3(start_x, start_y, start_z)); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); rbInfo.m_startWorldTransform = startTransform; btRigidBody* body = new btRigidBody(rbInfo); m_pWorld->addRigidBody(body); */ init_scene_directly(); } clientResetScene(); m_pWorld->initDeviceData(); }
plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height) { void* mem = btAlignedAlloc(sizeof(btCylinderShape),16); return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius)); }
plPhysicsSdkHandle plNewBulletSdk() { void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16); return (plPhysicsSdkHandle)new (mem)btPhysicsSdk; }
btPairCachingGhostObject::btPairCachingGhostObject() { m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); }
plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z) { void* mem = btAlignedAlloc(sizeof(btBoxShape),16); return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z)); }
PlCylinderShape* pl_cylindershape_new(PlReal radius, PlReal height) { void* mem = btAlignedAlloc(sizeof(btCylinderShape),16); return (PlCylinderShape*) new (mem)btCylinderShape(btVector3(radius,height,radius)); }
/* Convex Meshes */ PlConvexHullShape* pl_convexhullshape_new() { void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16); return (PlConvexHullShape*) new (mem)btConvexHullShape(); }
PlBoxShape* pl_boxshape_new(PlReal x, PlReal y, PlReal z) { void* mem = btAlignedAlloc(sizeof(btBoxShape),16); return (PlBoxShape*) new (mem)btBoxShape(btVector3(x,y,z)); }
PlConeShape* pl_coneshape_new(PlReal radius, PlReal height) { void* mem = btAlignedAlloc(sizeof(btConeShape),16); return (PlConeShape*) new (mem)btConeShape(radius,height); }
PlSphereShape* pl_sphereshape_new(PlReal radius) { void* mem = btAlignedAlloc(sizeof(btSphereShape),16); return (PlSphereShape*) new (mem)btSphereShape(radius); }
PlPhysicsSdk* pl_physicssdk_new() { void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16); return (PlPhysicsSdk*)new (mem)btPhysicsSdk; }
PlQuaternion* pl_quaternion_new() { PlQuaternion* mem = (PlQuaternion*)(btAlignedAlloc(4 * sizeof(PlReal),16)); return (PlQuaternion*)mem; }
void InternalEdgeDemo::initPhysics() { setTexturing(true); setShadows(false);//true); #define TRISIZE 10.f gContactAddedCallback = CustomMaterialCombinerCallback; #define USE_TRIMESH_SHAPE 1 #ifdef USE_TRIMESH_SHAPE int vertStride = sizeof(btVector3); int indexStride = 3*sizeof(int); const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); gVertices = new btVector3[totalVerts]; gIndices = new int[totalTriangles*3]; int i; setVertexPositions(waveheight,0.f); //gVertices[1].setY(21.1); //gVertices[1].setY(121.1); gVertices[1].setY(.1f); #ifdef ROTATE_GROUND //gVertices[1].setY(-1.1); #else //gVertices[1].setY(0.1); //gVertices[1].setY(-0.1); //gVertices[1].setY(-20.1); //gVertices[1].setY(-20); #endif int index=0; for ( i=0;i<NUM_VERTS_X-1;i++) { for (int j=0;j<NUM_VERTS_Y-1;j++) { #ifdef SWAP_WINDING #ifdef SHIFT_INDICES gIndices[index++] = j*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; gIndices[index++] = j*NUM_VERTS_X+i+1; gIndices[index++] = j*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; #else gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; gIndices[index++] = j*NUM_VERTS_X+i+1; gIndices[index++] = j*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; gIndices[index++] = j*NUM_VERTS_X+i; #endif //SHIFT_INDICES #else //SWAP_WINDING #ifdef SHIFT_INDICES gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; gIndices[index++] = j*NUM_VERTS_X+i; gIndices[index++] = j*NUM_VERTS_X+i+1; #ifdef TEST_INCONSISTENT_WINDING gIndices[index++] = j*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; #else //TEST_INCONSISTENT_WINDING gIndices[index++] = (j+1)*NUM_VERTS_X+i; gIndices[index++] = j*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; #endif //TEST_INCONSISTENT_WINDING #else //SHIFT_INDICES gIndices[index++] = j*NUM_VERTS_X+i; gIndices[index++] = j*NUM_VERTS_X+i+1; gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; gIndices[index++] = j*NUM_VERTS_X+i; gIndices[index++] = (j+1)*NUM_VERTS_X+i+1; gIndices[index++] = (j+1)*NUM_VERTS_X+i; #endif //SHIFT_INDICES #endif //SWAP_WINDING } } m_indexVertexArrays = new btTriangleIndexVertexArray(totalTriangles, gIndices, indexStride, totalVerts,(btScalar*) &gVertices[0].x(),vertStride); bool useQuantizedAabbCompression = true; //comment out the next line to read the BVH from disk (first run the demo once to create the BVH) #define SERIALIZE_TO_DISK 1 #ifdef SERIALIZE_TO_DISK btVector3 aabbMin(-1000,-1000,-1000),aabbMax(1000,1000,1000); trimeshShape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,aabbMin,aabbMax); m_collisionShapes.push_back(trimeshShape); ///we can serialize the BVH data void* buffer = 0; int numBytes = trimeshShape->getOptimizedBvh()->calculateSerializeBufferSize(); buffer = btAlignedAlloc(numBytes,16); bool swapEndian = false; trimeshShape->getOptimizedBvh()->serialize(buffer,numBytes,swapEndian); #ifdef __QNX__ FILE* file = fopen("app/native/bvh.bin","wb"); #else FILE* file = fopen("bvh.bin","wb"); #endif fwrite(buffer,1,numBytes,file); fclose(file); btAlignedFree(buffer); #else trimeshShape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,false); char* fileName = "bvh.bin"; #ifdef __QNX__ char* fileName = "app/native/bvh.bin"; #else char* fileName = "bvh.bin"; #endif int size=0; btOptimizedBvh* bvh = 0; if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */ printf("Error: cannot get filesize from %s\n", fileName); exit(0); } else { fseek(file, 0, SEEK_SET); int buffersize = size+btOptimizedBvh::getAlignmentSerializationPadding(); void* buffer = btAlignedAlloc(buffersize,16); int read = fread(buffer,1,size,file); fclose(file); bool swapEndian = false; bvh = btOptimizedBvh::deSerializeInPlace(buffer,buffersize,swapEndian); } trimeshShape->setOptimizedBvh(bvh); #endif btCollisionShape* groundShape = trimeshShape; btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap(); btGenerateInternalEdgeInfo(trimeshShape,triangleInfoMap); #else btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50)); m_collisionShapes.push_back(groundShape); #endif //USE_TRIMESH_SHAPE m_collisionConfiguration = new btDefaultCollisionConfiguration(); m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); m_solver = new btSequentialImpulseConstraintSolver(); m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); /* m_dynamicsWorld->getSolverInfo().m_splitImpulse = true; m_dynamicsWorld->getSolverInfo().m_splitImpulsePenetrationThreshold = 1e30f; m_dynamicsWorld->getSolverInfo().m_maxErrorReduction = 1e30f; m_dynamicsWorld->getSolverInfo().m_erp =1.f; m_dynamicsWorld->getSolverInfo().m_erp2 = 1.f; */ m_dynamicsWorld->setGravity(btVector3(0,-10,0)); float mass = 0.f; btTransform startTransform; startTransform.setIdentity(); startTransform.setOrigin(btVector3(0,-2,0)); btConvexHullShape* colShape = new btConvexHullShape(); for (int i=0;i<TaruVtxCount;i++) { btVector3 vtx(TaruVtx[i*3],TaruVtx[i*3+1],TaruVtx[i*3+2]); colShape->addPoint(vtx); } //this will enable polyhedral contact clipping, better quality, slightly slower colShape->initializePolyhedralFeatures(); //the polyhedral contact clipping can use either GJK or SAT test to find the separating axis m_dynamicsWorld->getDispatchInfo().m_enableSatConvex=false; m_collisionShapes.push_back(colShape); { for (int i=0;i<1;i++) { startTransform.setOrigin(btVector3(-10.f+i*3.f,2.2f+btScalar(i)*0.1f,-1.3f)); btRigidBody* body = localCreateRigidBody(10, startTransform,colShape); body->setActivationState(DISABLE_DEACTIVATION); body->setLinearVelocity(btVector3(0,0,-1)); //body->setContactProcessingThreshold(0.f); } } { btBoxShape* colShape = new btBoxShape(btVector3(1,1,1)); colShape->initializePolyhedralFeatures(); m_collisionShapes.push_back(colShape); startTransform.setOrigin(btVector3(-16.f+i*3.f,1.f+btScalar(i)*0.1f,-1.3f)); btRigidBody* body = localCreateRigidBody(10, startTransform,colShape); body->setActivationState(DISABLE_DEACTIVATION); body->setLinearVelocity(btVector3(0,0,-1)); } startTransform.setIdentity(); #ifdef ROTATE_GROUND btQuaternion orn(btVector3(0,0,1),SIMD_PI); startTransform.setOrigin(btVector3(-20,0,0)); startTransform.setRotation(orn); #endif //ROTATE_GROUND staticBody = localCreateRigidBody(mass, startTransform,groundShape); //staticBody->setContactProcessingThreshold(-0.031f); staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);//STATIC_OBJECT); //enable custom material callback staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); setDebugMode(btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_NoHelpText+btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints); #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW btSetDebugDrawer(&gDebugDrawer); #endif //BT_INTERNAL_EDGE_DEBUG_DRAW }
PlCompoundShape* pl_compoundshape_new() { void* mem = btAlignedAlloc(sizeof(btCompoundShape),16); return (PlCompoundShape*) new (mem)btCompoundShape(); }
btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStridingMeshInterfaceData& meshData) { btTriangleIndexVertexArray* meshInterface = createTriangleMeshContainer(); for (int i=0;i<meshData.m_numMeshParts;i++) { btIndexedMesh meshPart; meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles; meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices; if (meshData.m_meshPartsPtr[i].m_indices32) { meshPart.m_indexType = PHY_INTEGER; meshPart.m_triangleIndexStride = 3*sizeof(int); int* indexArray = (int*)btAlignedAlloc(sizeof(int)*3*meshPart.m_numTriangles,16); m_indexArrays.push_back(indexArray); for (int j=0;j<3*meshPart.m_numTriangles;j++) { indexArray[j] = meshData.m_meshPartsPtr[i].m_indices32[j].m_value; } meshPart.m_triangleIndexBase = (const unsigned char*)indexArray; } else { if (meshData.m_meshPartsPtr[i].m_3indices16) { meshPart.m_indexType = PHY_SHORT; meshPart.m_triangleIndexStride = sizeof(short int)*3;//sizeof(btShortIntIndexTripletData); short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int)*3*meshPart.m_numTriangles,16); m_shortIndexArrays.push_back(indexArray); for (int j=0;j<meshPart.m_numTriangles;j++) { indexArray[3*j] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[0]; indexArray[3*j+1] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[1]; indexArray[3*j+2] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[2]; } meshPart.m_triangleIndexBase = (const unsigned char*)indexArray; } if (meshData.m_meshPartsPtr[i].m_indices16) { meshPart.m_indexType = PHY_SHORT; meshPart.m_triangleIndexStride = 3*sizeof(short int); short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int)*3*meshPart.m_numTriangles,16); m_shortIndexArrays.push_back(indexArray); for (int j=0;j<3*meshPart.m_numTriangles;j++) { indexArray[j] = meshData.m_meshPartsPtr[i].m_indices16[j].m_value; } meshPart.m_triangleIndexBase = (const unsigned char*)indexArray; } if (meshData.m_meshPartsPtr[i].m_3indices8) { meshPart.m_indexType = PHY_UCHAR; meshPart.m_triangleIndexStride = sizeof(unsigned char)*3; unsigned char* indexArray = (unsigned char*)btAlignedAlloc(sizeof(unsigned char)*3*meshPart.m_numTriangles,16); m_charIndexArrays.push_back(indexArray); for (int j=0;j<meshPart.m_numTriangles;j++) { indexArray[3*j] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[0]; indexArray[3*j+1] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[1]; indexArray[3*j+2] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[2]; } meshPart.m_triangleIndexBase = (const unsigned char*)indexArray; } } if (meshData.m_meshPartsPtr[i].m_vertices3f) { meshPart.m_vertexType = PHY_FLOAT; meshPart.m_vertexStride = sizeof(btVector3FloatData); btVector3FloatData* vertices = (btVector3FloatData*) btAlignedAlloc(sizeof(btVector3FloatData)*meshPart.m_numVertices,16); m_floatVertexArrays.push_back(vertices); for (int j=0;j<meshPart.m_numVertices;j++) { vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[0]; vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[1]; vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[2]; vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[3]; } meshPart.m_vertexBase = (const unsigned char*)vertices; } else { meshPart.m_vertexType = PHY_DOUBLE; meshPart.m_vertexStride = sizeof(btVector3DoubleData); btVector3DoubleData* vertices = (btVector3DoubleData*) btAlignedAlloc(sizeof(btVector3DoubleData)*meshPart.m_numVertices,16); m_doubleVertexArrays.push_back(vertices); for (int j=0;j<meshPart.m_numVertices;j++) { vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[0]; vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[1]; vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[2]; vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[3]; } meshPart.m_vertexBase = (const unsigned char*)vertices; } if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase) { meshInterface->addIndexedMesh(meshPart,meshPart.m_indexType); } } return meshInterface; }
PlVector3* pl_vector3_new() { PlVector3* mem = (PlVector3*)(btAlignedAlloc(3 * sizeof(PlReal),16)); return mem; }
plCollisionShapeHandle plNewSphereShape(plReal radius) { void* mem = btAlignedAlloc(sizeof(btSphereShape),16); return (plCollisionShapeHandle) new (mem)btSphereShape(radius); }
virtual bool processOverlap(btBroadphasePair& collisionPair) { //PPU version //(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo); //only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE); //by default, Bullet will use this near callback { ///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks) if (!collisionPair.m_internalTmpValue) { collisionPair.m_internalTmpValue = 1; } if (!collisionPair.m_algorithm) { btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; btCollisionAlgorithmConstructionInfo ci; ci.m_dispatcher1 = m_dispatcher; ci.m_manifold = 0; if (m_dispatcher->needsCollision(colObj0,colObj1)) { int proxyType0 = colObj0->getCollisionShape()->getShapeType(); int proxyType1 = colObj1->getCollisionShape()->getShapeType(); bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) && (colObj0->getCollisionFlags() != btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) && (colObj1->getCollisionFlags() != btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING); if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE) { btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape(); if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES) { //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES); supportsSpuDispatch = false; } } if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE) { btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape(); if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES) { //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES); supportsSpuDispatch = false; } } if (supportsSpuDispatch) { int so = sizeof(SpuContactManifoldCollisionAlgorithm); #ifdef ALLOCATE_SEPARATELY void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so); #else void* mem = m_dispatcher->allocateCollisionAlgorithm(so); #endif collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1); collisionPair.m_internalTmpValue = 2; } else { collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1); collisionPair.m_internalTmpValue = 3; } } } } return false; }
plCollisionShapeHandle plNewConeShape(plReal radius, plReal height) { void* mem = btAlignedAlloc(sizeof(btConeShape),16); return (plCollisionShapeHandle) new (mem)btConeShape(radius,height); }
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); int numOfCellsX = (int)numOfCells[0]; int numOfCellsY = (int)numOfCells[1]; int numOfCellsZ = (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,10,24,24); // m_broadphase = new btCudaBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,24,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; 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("../../test1.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 }
plCollisionShapeHandle plNewCompoundShape() { void* mem = btAlignedAlloc(sizeof(btCompoundShape),16); return (plCollisionShapeHandle) new (mem)btCompoundShape(); }
void SpheresGridDemo::initPhysics() { setTexturing(false); setShadows(false); setCameraDistance(80.); m_cameraTargetPosition.setValue(50, 10, 0); 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_pairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache(); // m_broadphase = new btDbvtBroadphase(m_pairCache); m_broadphase = new btNullBroadphase(); ///the default constraint solver m_solver = new btSequentialImpulseConstraintSolver(); #ifdef INTEGRATION_DEMO m_pWorldI = new btIntegrationDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, 65536); #endif #ifdef SPHERES_DEMO m_pWorldS = new btSpheresGridDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, 65536); #endif #ifdef SPHERES_DEMO m_dialogDynamicsWorld = new GL_DialogDynamicsWorld(); GL_DialogWindow* settings = m_dialogDynamicsWorld->createDialog(50,0,280,280,"CPU fallback"); m_pWorldS->m_useCpuControls[0] = 0; GL_ToggleControl* ctrl = 0; m_pWorldS->m_useCpuControls[SIMSTAGE_APPLY_GRAVITY] = m_dialogDynamicsWorld->createToggle(settings,"Apply Gravity"); m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Compute Cell ID"); m_pWorldS->m_useCpuControls[SIMSTAGE_SORT_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Sort Cell ID"); m_pWorldS->m_useCpuControls[SIMSTAGE_FIND_CELL_START] = m_dialogDynamicsWorld->createToggle(settings,"Find Cell Start"); m_pWorldS->m_useCpuControls[SIMSTAGE_FIND_PAIRS] = m_dialogDynamicsWorld->createToggle(settings,"Find Pairs"); m_pWorldS->m_useCpuControls[SIMSTAGE_SCAN_PAIRS] = m_dialogDynamicsWorld->createToggle(settings,"Scan Pairs"); m_pWorldS->m_useCpuControls[SIMSTAGE_COMPACT_PAIRS] = m_dialogDynamicsWorld->createToggle(settings,"Compact Pairs"); m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_BATCHES] = m_dialogDynamicsWorld->createToggle(settings,"Compute Batches"); m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_CONTACTS] = m_dialogDynamicsWorld->createToggle(settings,"Compute Contacts"); m_pWorldS->m_useCpuControls[SIMSTAGE_SOLVE_CONSTRAINTS] = m_dialogDynamicsWorld->createToggle(settings,"Solve Constraints"); m_pWorldS->m_useCpuControls[SIMSTAGE_INTEGRATE_TRANSFORMS] = m_dialogDynamicsWorld->createToggle(settings,"Integrate Transforms"); m_pWorldS->m_useCpuControls[SIMSTAGE_KERNEL_COLLIDE_SPHERE_WALLS] = m_dialogDynamicsWorld->createToggle(settings,"Collide Sphere Walls"); for(int i = 1; i < SIMSTAGE_TOTAL; i++) { m_pWorldS->m_useCpuControls[i]->m_active = false; } #if defined(CL_PLATFORM_MINI_CL) m_pWorldS->m_useCpuControls[SIMSTAGE_SCAN_PAIRS]->m_active = true; m_pWorldS->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_CONTACTS]->m_active = true; #endif #if defined(CL_PLATFORM_AMD) m_pWorldS->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; // sloooow, incorrect, crashes application m_pWorldS->m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active = true; // run-time error "Unimplemented" m_pWorldS->m_useCpuControls[SIMSTAGE_SCAN_PAIRS]->m_active = true; // works, but very slow (up to 100 times) m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_BATCHES]->m_active = true; // run-time error "Unimplemented" #endif #endif //#ifdef SPHERES_DEMO if(m_demoType == DEMO_INTEGRATION) { #ifdef INTEGRATION_DEMO m_dynamicsWorld = m_pWorldI; #endif } else { #ifdef SPHERES_DEMO m_dynamicsWorld = m_pWorldS; #endif //#ifdef SPHERES_DEMO } #ifdef INTEGRATION_DEMO m_pWorldI->getSimulationIslandManager()->setSplitIslands(true); m_pWorldI->setGravity(btVector3(0,-10.,0)); m_pWorldI->getSolverInfo().m_numIterations = 4; #endif //INTEGRATION_DEMO #ifdef SPHERES_DEMO m_pWorldS->getSimulationIslandManager()->setSplitIslands(true); m_pWorldS->setGravity(btVector3(0,-10.,0)); m_pWorldS->getSolverInfo().m_numIterations = 4; #endif //#ifdef SPHERES_DEMO { btCollisionShape* colShape = new btSphereShape(btScalar(1.0f)); m_collisionShapes.push_back(colShape); btTransform startTransform; startTransform.setIdentity(); btScalar mass(1.f); btVector3 localInertia(0,0,0); colShape->calculateLocalInertia(mass,localInertia); float start_x = START_POS_X - ARRAY_SIZE_X * DIST * btScalar(0.5f); float start_y = START_POS_Y - ARRAY_SIZE_Y * DIST * btScalar(0.5f); float start_z = START_POS_Z - ARRAY_SIZE_Z * DIST * btScalar(0.5f); #if USE_BULLET_BODIES // may be very slow for > 10K bodies printf("\nGenerating bodies ...\n"); int total = ARRAY_SIZE_X * ARRAY_SIZE_Y * ARRAY_SIZE_Z; int done = 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(btVector3( DIST*i + start_x, DIST*k + start_y, DIST*j + start_z)); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); rbInfo.m_startWorldTransform = startTransform; btRigidBody* body = new btRigidBody(rbInfo); m_pWorldI->addRigidBody(body); done++; } } printf("%6d of %6d\r", done, total); fflush(stdout); } printf("\n... Done!\n"); #else // add just one sphere #ifdef INTEGRATION_DEMO startTransform.setOrigin(btVector3(start_x, start_y, start_z)); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); rbInfo.m_startWorldTransform = startTransform; btRigidBody* body = new btRigidBody(rbInfo); m_pWorldI->addRigidBody(body); #endif // now fill m_hPos and m_hLinVel directly init_scene_directly(); #endif } btDynamicsWorld* tmpW = m_dynamicsWorld; #ifdef SPHERES_DEMO m_dynamicsWorld = m_pWorldS; SpheresGridDemoOecakeLoader loader(this); //loader.processFile("test1.oec"); #if 1 /// stress test btCompoundShape* compound = new btCompoundShape(); btSphereShape* sphere = new btSphereShape(1.f); btTransform localTrans; localTrans.setIdentity(); localTrans.setOrigin(btVector3(0,0,0)); compound->addChildShape(localTrans,sphere); //localTrans.setOrigin(btVector3(-1,0,0)); //compound->addChildShape(localTrans,sphere); btTransform trans; trans.setIdentity(); btVector3 offset(0.00001,0.00001,0.00001); for (int j=0;j<STRESS_X;j++) for (int i=0;i<STRESS_Y;i++) { trans.setOrigin(offset*i+btVector3(25+j*6,30+i*3,0.)); loader.createBodyForCompoundShape(compound,false,trans,1.); } #endif m_dynamicsWorld = tmpW; #else m_dynamicsWorld = m_pWorldI; #endif//#ifdef SPHERES_DEMO clientResetScene(); #ifdef INTEGRATION_DEMO m_pWorldI->initDeviceData(); #endif #ifdef SPHERES_DEMO m_pWorldS->initDeviceData(); #endif print_used_device(); }
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) */ btScalar maxDiam = 1.76f * 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 bt3dGridBroadphaseOCL(gPairCache, cellSize,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,32,10.f, 32); // m_broadphase = new bt3dGridBroadphaseOCL(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,8,8,1./1.5); // m_broadphase = new btGpu3DGridBroadphaseOCL(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,8,8,1./1.5); // m_broadphase = new btGpu3DGridBroadphase(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_pWorld = pDdw; 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 #if 1 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(); }
/** Creates a collision body only, which can be used for raycasting, but * has no physical properties. * @param serialized_bhv if non-null, load the serialized bhv from file instead * of builing it on the fly */ void TriangleMesh::createCollisionShape(bool create_collision_object, const char* serialized_bhv) { if(m_triangleIndex2Material.size()==0) { m_collision_shape = NULL; m_motion_state = NULL; m_body = NULL; m_collision_object = NULL; return; } // Now convert the triangle mesh into a static rigid body btBvhTriangleMeshShape* bhv_triangle_mesh; if (serialized_bhv != NULL) { FILE *f = fopen(serialized_bhv, "rb"); fseek(f, 0, SEEK_END); long pos = ftell(f); assert(pos != -1L); fseek(f, 0, SEEK_SET); void* bytes = btAlignedAlloc(pos, 16); fread(bytes, pos, 1, f); fclose(f); btOptimizedBvh* bhv = btOptimizedBvh::deSerializeInPlace(bytes, pos, !IS_LITTLE_ENDIAN); if (bhv == NULL) { Log::warn("TriangleMesh", "Failed to load serialized BHV"); bhv_triangle_mesh = new btBvhTriangleMeshShape(&m_mesh, false /* useQuantizedAabbCompression */); } else { bhv_triangle_mesh = new btBvhTriangleMeshShape(&m_mesh, false /* useQuantizedAabbCompression */, false /* buildBvh */); bhv_triangle_mesh->setOptimizedBvh( bhv ); } // Do *NOT* free the bytes, 'deSerializeInPlace' makes the btOptimizedBvh object // directly at this memory location //free(bytes); } else { bhv_triangle_mesh = new btBvhTriangleMeshShape(&m_mesh, false /* useQuantizedAabbCompression */); /* // code to serialize triangle mesh btOptimizedBvh* bvh = bhv_triangle_mesh->getOptimizedBvh(); unsigned int ssize = bvh->calculateSerializeBufferSize(); char* buffer = (char*)btAlignedAlloc(ssize, 16); bool success = bvh->serialize(buffer, ssize, !IS_LITTLE_ENDIAN); printf("serialization success = %i\n", success); std::ofstream fileout("/tmp/btOptimizedBvh"); fileout.write(buffer, ssize); fileout.close(); btAlignedFree(buffer); */ } m_collision_shape = bhv_triangle_mesh; m_collision_shape->setUserPointer(&m_user_pointer); if(create_collision_object) { m_collision_object = new btCollisionObject(); btTransform bt; bt.setIdentity(); m_collision_object->setWorldTransform(bt); } } // createCollisionShape
void btGpu3DGridBroadphase::_initialize( const btVector3& worldAabbMin,const btVector3& worldAabbMax, int gridSizeX, int gridSizeY, int gridSizeZ, int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, int maxBodiesPerCell, btScalar cellFactorAABB) { // set various paramerers m_ownsPairCache = true; m_params.m_gridSizeX = gridSizeX; m_params.m_gridSizeY = gridSizeY; m_params.m_gridSizeZ = gridSizeZ; m_params.m_numCells = m_params.m_gridSizeX * m_params.m_gridSizeY * m_params.m_gridSizeZ; btVector3 w_org = worldAabbMin; m_params.m_worldOriginX = w_org.getX(); m_params.m_worldOriginY = w_org.getY(); m_params.m_worldOriginZ = w_org.getZ(); btVector3 w_size = worldAabbMax - worldAabbMin; m_params.m_cellSizeX = w_size.getX() / m_params.m_gridSizeX; m_params.m_cellSizeY = w_size.getY() / m_params.m_gridSizeY; m_params.m_cellSizeZ = w_size.getZ() / m_params.m_gridSizeZ; m_maxRadius = btMin(btMin(m_params.m_cellSizeX, m_params.m_cellSizeY), m_params.m_cellSizeZ); m_maxRadius *= btScalar(0.5f); m_params.m_numBodies = m_numBodies; m_params.m_maxBodiesPerCell = maxBodiesPerCell; m_numLargeHandles = 0; m_maxLargeHandles = maxLargeProxies; m_maxPairsPerBody = maxPairsPerBody; m_cellFactorAABB = cellFactorAABB; m_LastLargeHandleIndex = -1; btAssert(!m_bInitialized); // allocate host storage m_hBodiesHash = new unsigned int[m_maxHandles * 2]; memset(m_hBodiesHash, 0x00, m_maxHandles*2*sizeof(unsigned int)); m_hCellStart = new unsigned int[m_params.m_numCells]; memset(m_hCellStart, 0x00, m_params.m_numCells * sizeof(unsigned int)); m_hPairBuffStartCurr = new unsigned int[m_maxHandles * 2 + 2]; // --------------- for now, init with m_maxPairsPerBody for each body m_hPairBuffStartCurr[0] = 0; m_hPairBuffStartCurr[1] = 0; for(int i = 1; i <= m_maxHandles; i++) { m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; m_hPairBuffStartCurr[i * 2 + 1] = 0; } //---------------- unsigned int numAABB = m_maxHandles + m_maxLargeHandles; m_hAABB = new bt3DGrid3F1U[numAABB * 2]; // AABB Min & Max m_hPairBuff = new unsigned int[m_maxHandles * m_maxPairsPerBody]; memset(m_hPairBuff, 0x00, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); // needed? m_hPairScan = new unsigned int[m_maxHandles + 1]; m_hPairOut = new unsigned int[m_maxHandles * m_maxPairsPerBody]; // large proxies // allocate handles buffer and put all handles on free list m_pLargeHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * m_maxLargeHandles, 16); m_pLargeHandles = new(m_pLargeHandlesRawPtr) btSimpleBroadphaseProxy[m_maxLargeHandles]; m_firstFreeLargeHandle = 0; { for (int i = m_firstFreeLargeHandle; i < m_maxLargeHandles; i++) { m_pLargeHandles[i].SetNextFree(i + 1); m_pLargeHandles[i].m_uniqueId = m_maxHandles+2+i; } m_pLargeHandles[m_maxLargeHandles - 1].SetNextFree(0); } // debug data m_numPairsAdded = 0; m_numOverflows = 0; m_bInitialized = true; }
virtual bool convertAllObjects( bParse::btBulletFile* bulletFile2) { bool result = btBulletWorldImporter::convertAllObjects(bulletFile2); int i; //now the soft bodies for (i=0;i<bulletFile2->m_softBodies.size();i++) { if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) { btAssert(0); //not yet //btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i]; } else { btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i]; int i; int numNodes = softBodyData->m_numNodes; btSoftBody* psb=new btSoftBody(&m_softRigidWorld->getWorldInfo()); m_softBodyMap.insert(softBodyData,psb); //materials for (i=0;i<softBodyData->m_numMaterials;i++) { SoftBodyMaterialData* matData = softBodyData->m_materials[i]; btSoftBody::Material** matPtr = m_materialMap.find(matData); btSoftBody::Material* mat = 0; if (matPtr&& *matPtr) { mat = *matPtr; } else { mat = psb->appendMaterial(); mat->m_flags = matData->m_flags; mat->m_kAST = matData->m_angularStiffness; mat->m_kLST = matData->m_linearStiffness; mat->m_kVST = matData->m_volumeStiffness; m_materialMap.insert(matData,mat); } } for (i=0;i<numNodes;i++) { SoftBodyNodeData& nodeData = softBodyData->m_nodes[i]; btVector3 position; position.deSerializeFloat(nodeData.m_position); btScalar mass = nodeData.m_inverseMass? 1./nodeData.m_inverseMass : 0.f; psb->appendNode(position,mass); btSoftBody::Node* node = &psb->m_nodes[psb->m_nodes.size()-1]; node->m_area = nodeData.m_area; node->m_battach = nodeData.m_attach; node->m_f.deSerializeFloat(nodeData.m_accumulatedForce); node->m_im = nodeData.m_inverseMass; btSoftBody::Material** matPtr = m_materialMap.find(nodeData.m_material); if (matPtr && *matPtr) { node->m_material = *matPtr; } else { printf("no mat?\n"); } node->m_n.deSerializeFloat(nodeData.m_normal); node->m_q = node->m_x; node->m_v.deSerializeFloat(nodeData.m_velocity); } for (i=0;i<softBodyData->m_numLinks;i++) { SoftBodyLinkData& linkData = softBodyData->m_links[i]; btSoftBody::Material** matPtr = m_materialMap.find(linkData.m_material); if (matPtr && *matPtr) { psb->appendLink(linkData.m_nodeIndices[0],linkData.m_nodeIndices[1],*matPtr); } else { psb->appendLink(linkData.m_nodeIndices[0],linkData.m_nodeIndices[1]); } btSoftBody::Link* link = &psb->m_links[psb->m_links.size()-1]; link->m_bbending = linkData.m_bbending; link->m_rl = linkData.m_restLength; } for (i=0;i<softBodyData->m_numFaces;i++) { SoftBodyFaceData& faceData = softBodyData->m_faces[i]; btSoftBody::Material** matPtr = m_materialMap.find(faceData.m_material); if (matPtr && *matPtr) { psb->appendFace(faceData.m_nodeIndices[0],faceData.m_nodeIndices[1],faceData.m_nodeIndices[2],*matPtr); } else { psb->appendFace(faceData.m_nodeIndices[0],faceData.m_nodeIndices[1],faceData.m_nodeIndices[2]); } btSoftBody::Face* face = &psb->m_faces[psb->m_faces.size()-1]; face->m_normal.deSerializeFloat(faceData.m_normal); face->m_ra = faceData.m_restArea; } //anchors for (i=0;i<softBodyData->m_numAnchors;i++) { btCollisionObject** colAptr = m_bodyMap.find(softBodyData->m_anchors[i].m_rigidBody); if (colAptr && *colAptr) { btRigidBody* body = btRigidBody::upcast(*colAptr); if (body) { bool disableCollision = false; btVector3 localPivot; localPivot.deSerializeFloat(softBodyData->m_anchors[i].m_localFrame); psb->appendAnchor(softBodyData->m_anchors[i].m_nodeIndex,body,localPivot, disableCollision); } } } if (softBodyData->m_pose) { psb->m_pose.m_aqq.deSerializeFloat( softBodyData->m_pose->m_aqq); psb->m_pose.m_bframe = (softBodyData->m_pose->m_bframe!=0); psb->m_pose.m_bvolume = (softBodyData->m_pose->m_bvolume!=0); psb->m_pose.m_com.deSerializeFloat(softBodyData->m_pose->m_com); psb->m_pose.m_pos.resize(softBodyData->m_pose->m_numPositions); for (i=0;i<softBodyData->m_pose->m_numPositions;i++) { psb->m_pose.m_pos[i].deSerializeFloat(softBodyData->m_pose->m_positions[i]); } psb->m_pose.m_rot.deSerializeFloat(softBodyData->m_pose->m_rot); psb->m_pose.m_scl.deSerializeFloat(softBodyData->m_pose->m_scale); psb->m_pose.m_wgh.resize(softBodyData->m_pose->m_numWeigts); for (i=0;i<softBodyData->m_pose->m_numWeigts;i++) { psb->m_pose.m_wgh[i] = softBodyData->m_pose->m_weights[i]; } psb->m_pose.m_volume = softBodyData->m_pose->m_restVolume; } #if 1 psb->m_cfg.piterations=softBodyData->m_config.m_positionIterations; psb->m_cfg.diterations=softBodyData->m_config.m_driftIterations; psb->m_cfg.citerations=softBodyData->m_config.m_clusterIterations; psb->m_cfg.viterations=softBodyData->m_config.m_velocityIterations; //psb->setTotalMass(0.1); psb->m_cfg.aeromodel = (btSoftBody::eAeroModel::_)softBodyData->m_config.m_aeroModel; psb->m_cfg.kLF = softBodyData->m_config.m_lift; psb->m_cfg.kDG = softBodyData->m_config.m_drag; psb->m_cfg.kMT = softBodyData->m_config.m_poseMatch; psb->m_cfg.collisions = softBodyData->m_config.m_collisionFlags; psb->m_cfg.kDF = 1.f;//softBodyData->m_config.m_dynamicFriction; psb->m_cfg.kDP = softBodyData->m_config.m_damping; psb->m_cfg.kPR = softBodyData->m_config.m_pressure; psb->m_cfg.kVC = softBodyData->m_config.m_volume; psb->m_cfg.kAHR = softBodyData->m_config.m_anchorHardness; psb->m_cfg.kKHR = softBodyData->m_config.m_kineticContactHardness; psb->m_cfg.kSHR = softBodyData->m_config.m_softContactHardness; psb->m_cfg.kSRHR_CL = softBodyData->m_config.m_softRigidClusterHardness; psb->m_cfg.kSKHR_CL = softBodyData->m_config.m_softKineticClusterHardness; psb->m_cfg.kSSHR_CL = softBodyData->m_config.m_softSoftClusterHardness; #endif // pm->m_kLST = 1; #if 1 //clusters if (softBodyData->m_numClusters) { m_clusterBodyMap.insert(softBodyData->m_clusters,psb); int j; psb->m_clusters.resize(softBodyData->m_numClusters); for (i=0;i<softBodyData->m_numClusters;i++) { psb->m_clusters[i] = new(btAlignedAlloc(sizeof(btSoftBody::Cluster),16)) btSoftBody::Cluster(); psb->m_clusters[i]->m_adamping = softBodyData->m_clusters[i].m_adamping; psb->m_clusters[i]->m_av.deSerializeFloat(softBodyData->m_clusters[i].m_av); psb->m_clusters[i]->m_clusterIndex = softBodyData->m_clusters[i].m_clusterIndex; psb->m_clusters[i]->m_collide = (softBodyData->m_clusters[i].m_collide!=0); psb->m_clusters[i]->m_com.deSerializeFloat(softBodyData->m_clusters[i].m_com); psb->m_clusters[i]->m_containsAnchor = (softBodyData->m_clusters[i].m_containsAnchor!=0); psb->m_clusters[i]->m_dimpulses[0].deSerializeFloat(softBodyData->m_clusters[i].m_dimpulses[0]); psb->m_clusters[i]->m_dimpulses[1].deSerializeFloat(softBodyData->m_clusters[i].m_dimpulses[1]); psb->m_clusters[i]->m_framerefs.resize(softBodyData->m_clusters[i].m_numFrameRefs); for (j=0;j<softBodyData->m_clusters[i].m_numFrameRefs;j++) { psb->m_clusters[i]->m_framerefs[j].deSerializeFloat(softBodyData->m_clusters[i].m_framerefs[j]); } psb->m_clusters[i]->m_nodes.resize(softBodyData->m_clusters[i].m_numNodes); for (j=0;j<softBodyData->m_clusters[i].m_numNodes;j++) { int nodeIndex = softBodyData->m_clusters[i].m_nodeIndices[j]; psb->m_clusters[i]->m_nodes[j] = &psb->m_nodes[nodeIndex]; } psb->m_clusters[i]->m_masses.resize(softBodyData->m_clusters[i].m_numMasses); for (j=0;j<softBodyData->m_clusters[i].m_numMasses;j++) { psb->m_clusters[i]->m_masses[j] = softBodyData->m_clusters[i].m_masses[j]; } psb->m_clusters[i]->m_framexform.deSerializeFloat(softBodyData->m_clusters[i].m_framexform); psb->m_clusters[i]->m_idmass = softBodyData->m_clusters[i].m_idmass; psb->m_clusters[i]->m_imass = softBodyData->m_clusters[i].m_imass; psb->m_clusters[i]->m_invwi.deSerializeFloat(softBodyData->m_clusters[i].m_invwi); psb->m_clusters[i]->m_ldamping = softBodyData->m_clusters[i].m_ldamping; psb->m_clusters[i]->m_locii.deSerializeFloat(softBodyData->m_clusters[i].m_locii); psb->m_clusters[i]->m_lv.deSerializeFloat(softBodyData->m_clusters[i].m_lv); psb->m_clusters[i]->m_matching = softBodyData->m_clusters[i].m_matching; psb->m_clusters[i]->m_maxSelfCollisionImpulse = 0;//softBodyData->m_clusters[i].m_maxSelfCollisionImpulse; psb->m_clusters[i]->m_ndamping = softBodyData->m_clusters[i].m_ndamping; psb->m_clusters[i]->m_ndimpulses = softBodyData->m_clusters[i].m_ndimpulses; psb->m_clusters[i]->m_nvimpulses = softBodyData->m_clusters[i].m_nvimpulses; psb->m_clusters[i]->m_selfCollisionImpulseFactor = softBodyData->m_clusters[i].m_selfCollisionImpulseFactor; psb->m_clusters[i]->m_vimpulses[0].deSerializeFloat(softBodyData->m_clusters[i].m_vimpulses[0]); psb->m_clusters[i]->m_vimpulses[1].deSerializeFloat(softBodyData->m_clusters[i].m_vimpulses[1]); } //psb->initializeClusters(); //psb->updateClusters(); } #else psb->m_cfg.piterations = 2; psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS; //psb->setTotalMass(50,true); //psb->generateClusters(64); //psb->m_cfg.kDF=1; psb->generateClusters(8); #endif // psb->updateConstants(); m_softRigidWorld->getWorldInfo().m_dispatcher = m_softRigidWorld->getDispatcher(); m_softRigidWorld->addSoftBody(psb); } } //now the soft body joints for (i=0;i<bulletFile2->m_softBodies.size();i++) { if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) { btAssert(0); //not yet //btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i]; } else { btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i]; btSoftBody** sbp = m_softBodyMap.find(softBodyData); if (sbp && *sbp) { btSoftBody* sb = *sbp; for (int i=0;i<softBodyData->m_numJoints;i++) { btSoftBodyJointData* sbjoint = &softBodyData->m_joints[i]; btSoftBody::Body bdyB; btSoftBody* sbB = 0; btTransform transA; transA.setIdentity(); transA = sb->m_clusters[0]->m_framexform; btCollisionObject** colBptr = m_bodyMap.find(sbjoint->m_bodyB); if (colBptr && *colBptr) { btRigidBody* rbB = btRigidBody::upcast(*colBptr); if (rbB) { bdyB = rbB; } else { bdyB = *colBptr; } } btSoftBody** bodyBptr = m_clusterBodyMap.find(sbjoint->m_bodyB); if (bodyBptr && *bodyBptr ) { sbB = *bodyBptr; bdyB = sbB->m_clusters[0]; } if (sbjoint->m_jointType==btSoftBody::Joint::eType::Linear) { btSoftBody::LJoint::Specs specs; specs.cfm = sbjoint->m_cfm; specs.erp = sbjoint->m_erp; specs.split = sbjoint->m_split; btVector3 relA; relA.deSerializeFloat(sbjoint->m_refs[0]); specs.position = transA*relA; sb->appendLinearJoint(specs,sb->m_clusters[0],bdyB); } if (sbjoint->m_jointType==btSoftBody::Joint::eType::Angular) { btSoftBody::AJoint::Specs specs; specs.cfm = sbjoint->m_cfm; specs.erp = sbjoint->m_erp; specs.split = sbjoint->m_split; btVector3 relA; relA.deSerializeFloat(sbjoint->m_refs[0]); specs.axis = transA.getBasis()*relA; sb->appendAngularJoint(specs,sb->m_clusters[0],bdyB); } } } } } return result; }
bool btPolyhedralConvexShape::initializePolyhedralFeatures() { if (m_polyhedron) btAlignedFree(m_polyhedron); void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16); m_polyhedron = new (mem) btConvexPolyhedron; btAlignedObjectArray<btVector3> orgVertices; for (int i=0;i<getNumVertices();i++) { btVector3& newVertex = orgVertices.expand(); getVertex(i,newVertex); } #if 0 btAlignedObjectArray<btVector3> planeEquations; btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations); btAlignedObjectArray<btVector3> shiftedPlaneEquations; for (int p=0;p<planeEquations.size();p++) { btVector3 plane = planeEquations[p]; plane[3] -= getMargin(); shiftedPlaneEquations.push_back(plane); } btAlignedObjectArray<btVector3> tmpVertices; btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices); btConvexHullComputer conv; conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f); #else btConvexHullComputer conv; conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f); #endif btAlignedObjectArray<btVector3> faceNormals; int numFaces = conv.faces.size(); faceNormals.resize(numFaces); btConvexHullComputer* convexUtil = &conv; btAlignedObjectArray<btFace> tmpFaces; tmpFaces.resize(numFaces); int numVertices = convexUtil->vertices.size(); m_polyhedron->m_vertices.resize(numVertices); for (int p=0;p<numVertices;p++) { m_polyhedron->m_vertices[p] = convexUtil->vertices[p]; } for (int i=0;i<numFaces;i++) { int face = convexUtil->faces[i]; //printf("face=%d\n",face); const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face]; const btConvexHullComputer::Edge* edge = firstEdge; btVector3 edges[3]; int numEdges = 0; //compute face normals btScalar maxCross2 = 0.f; int chosenEdge = -1; do { int src = edge->getSourceVertex(); tmpFaces[i].m_indices.push_back(src); int targ = edge->getTargetVertex(); btVector3 wa = convexUtil->vertices[src]; btVector3 wb = convexUtil->vertices[targ]; btVector3 newEdge = wb-wa; newEdge.normalize(); if (numEdges<2) edges[numEdges++] = newEdge; edge = edge->getNextEdgeOfFace(); } while (edge!=firstEdge); btScalar planeEq = 1e30f; if (numEdges==2) { faceNormals[i] = edges[0].cross(edges[1]); faceNormals[i].normalize(); tmpFaces[i].m_plane[0] = faceNormals[i].getX(); tmpFaces[i].m_plane[1] = faceNormals[i].getY(); tmpFaces[i].m_plane[2] = faceNormals[i].getZ(); tmpFaces[i].m_plane[3] = planeEq; } else { btAssert(0);//degenerate? faceNormals[i].setZero(); } for (int v=0;v<tmpFaces[i].m_indices.size();v++) { btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]); if (planeEq>eq) { planeEq=eq; } } tmpFaces[i].m_plane[3] = -planeEq; } //merge coplanar faces and copy them to m_polyhedron btScalar faceWeldThreshold= 0.999f; btAlignedObjectArray<int> todoFaces; for (int i=0;i<tmpFaces.size();i++) todoFaces.push_back(i); while (todoFaces.size()) { btAlignedObjectArray<int> coplanarFaceGroup; int refFace = todoFaces[todoFaces.size()-1]; coplanarFaceGroup.push_back(refFace); btFace& faceA = tmpFaces[refFace]; todoFaces.pop_back(); btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]); for (int j=todoFaces.size()-1;j>=0;j--) { int i = todoFaces[j]; btFace& faceB = tmpFaces[i]; btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]); if (faceNormalA.dot(faceNormalB)>faceWeldThreshold) { coplanarFaceGroup.push_back(i); todoFaces.remove(i); } } bool did_merge = false; if (coplanarFaceGroup.size()>1) { //do the merge: use Graham Scan 2d convex hull btAlignedObjectArray<GrahamVector2> orgpoints; for (int i=0;i<coplanarFaceGroup.size();i++) { // m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); btFace& face = tmpFaces[coplanarFaceGroup[i]]; btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]); btVector3 xyPlaneNormal(0,0,1); btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal); for (int f=0;f<face.m_indices.size();f++) { int orgIndex = face.m_indices[f]; btVector3 pt = m_polyhedron->m_vertices[orgIndex]; btVector3 rotatedPt = quatRotate(rotationArc,pt); rotatedPt.setZ(0); bool found = false; for (int i=0;i<orgpoints.size();i++) { //if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001)) if (orgpoints[i].m_orgIndex == orgIndex) { found=true; break; } } if (!found) orgpoints.push_back(GrahamVector2(rotatedPt,orgIndex)); } } btFace combinedFace; for (int i=0;i<4;i++) combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i]; btAlignedObjectArray<GrahamVector2> hull; GrahamScanConvexHull2D(orgpoints,hull); for (int i=0;i<hull.size();i++) { combinedFace.m_indices.push_back(hull[i].m_orgIndex); for(int k = 0; k < orgpoints.size(); k++) { if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex) { orgpoints[k].m_orgIndex = -1; // invalidate... break; } } } // are there rejected vertices? bool reject_merge = false; for(int i = 0; i < orgpoints.size(); i++) { if(orgpoints[i].m_orgIndex == -1) continue; // this is in the hull... // this vertex is rejected -- is anybody else using this vertex? for(int j = 0; j < tmpFaces.size(); j++) { btFace& face = tmpFaces[j]; // is this a face of the current coplanar group? bool is_in_current_group = false; for(int k = 0; k < coplanarFaceGroup.size(); k++) { if(coplanarFaceGroup[k] == j) { is_in_current_group = true; break; } } if(is_in_current_group) // ignore this face... continue; // does this face use this rejected vertex? for(int v = 0; v < face.m_indices.size(); v++) { if(face.m_indices[v] == orgpoints[i].m_orgIndex) { // this rejected vertex is used in another face -- reject merge reject_merge = true; break; } } if(reject_merge) break; } if(reject_merge) break; } if(!reject_merge) { // do this merge! did_merge = true; m_polyhedron->m_faces.push_back(combinedFace); } } if(!did_merge) { for (int i=0;i<coplanarFaceGroup.size();i++) { m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); } } } m_polyhedron->initialize(); return true; }
bool btPolyhedralConvexShape::initializePolyhedralFeatures() { if (m_polyhedron) btAlignedFree(m_polyhedron); void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16); m_polyhedron = new (mem) btConvexPolyhedron; btAlignedObjectArray<btVector3> tmpVertices; for (int i=0;i<getNumVertices();i++) { btVector3& newVertex = tmpVertices.expand(); getVertex(i,newVertex); } btConvexHullComputer conv; conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f); btAlignedObjectArray<btVector3> faceNormals; int numFaces = conv.faces.size(); faceNormals.resize(numFaces); btConvexHullComputer* convexUtil = &conv; m_polyhedron->m_faces.resize(numFaces); int numVertices = convexUtil->vertices.size(); m_polyhedron->m_vertices.resize(numVertices); for (int p=0;p<numVertices;p++) { m_polyhedron->m_vertices[p] = convexUtil->vertices[p]; } for (int i=0;i<numFaces;i++) { int face = convexUtil->faces[i]; //printf("face=%d\n",face); const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face]; const btConvexHullComputer::Edge* edge = firstEdge; btVector3 edges[3]; int numEdges = 0; //compute face normals //btScalar maxCross2 = 0.f; //int chosenEdge = -1; do { int src = edge->getSourceVertex(); m_polyhedron->m_faces[i].m_indices.push_back(src); int targ = edge->getTargetVertex(); btVector3 wa = convexUtil->vertices[src]; btVector3 wb = convexUtil->vertices[targ]; btVector3 newEdge = wb-wa; newEdge.normalize(); if (numEdges<2) edges[numEdges++] = newEdge; edge = edge->getNextEdgeOfFace(); } while (edge!=firstEdge); btScalar planeEq = 1e30f; if (numEdges==2) { faceNormals[i] = edges[0].cross(edges[1]); faceNormals[i].normalize(); m_polyhedron->m_faces[i].m_plane[0] = -faceNormals[i].getX(); m_polyhedron->m_faces[i].m_plane[1] = -faceNormals[i].getY(); m_polyhedron->m_faces[i].m_plane[2] = -faceNormals[i].getZ(); m_polyhedron->m_faces[i].m_plane[3] = planeEq; } else { btAssert(0);//degenerate? faceNormals[i].setZero(); } for (int v=0;v<m_polyhedron->m_faces[i].m_indices.size();v++) { btScalar eq = m_polyhedron->m_vertices[m_polyhedron->m_faces[i].m_indices[v]].dot(faceNormals[i]); if (planeEq>eq) { planeEq=eq; } } m_polyhedron->m_faces[i].m_plane[3] = planeEq; } if (m_polyhedron->m_faces.size() && conv.vertices.size()) { for (int f=0;f<m_polyhedron->m_faces.size();f++) { btVector3 planeNormal(m_polyhedron->m_faces[f].m_plane[0],m_polyhedron->m_faces[f].m_plane[1],m_polyhedron->m_faces[f].m_plane[2]); btScalar planeEq = m_polyhedron->m_faces[f].m_plane[3]; btVector3 supVec = localGetSupportingVertex(-planeNormal); if (supVec.dot(planeNormal)<planeEq) { m_polyhedron->m_faces[f].m_plane[0] *= -1; m_polyhedron->m_faces[f].m_plane[1] *= -1; m_polyhedron->m_faces[f].m_plane[2] *= -1; m_polyhedron->m_faces[f].m_plane[3] *= -1; int numVerts = m_polyhedron->m_faces[f].m_indices.size(); for (int v=0;v<numVerts/2;v++) { btSwap(m_polyhedron->m_faces[f].m_indices[v],m_polyhedron->m_faces[f].m_indices[numVerts-1-v]); } } } } m_polyhedron->initialize(); return true; }