void BulletDynamicsBody::CreateRigidBody( const Integration::DynamicsBodySettings& bodySettings, Dali::Integration::DynamicsShape* shape, const Vector3& startPosition, const Quaternion& startRotation ) { DEBUG_PRINTF("%s\n", __func__ ); Vector3 axis; float angle( 0.0f ); startRotation.ToAxisAngle( axis, angle ); btVector3 inertia( 0.0f ,0.0f ,0.0f ); btCollisionShape* collisionShape( ((BulletDynamicsShape*)shape)->GetShape() ); if( ! EqualsZero( bodySettings.mass ) ) { collisionShape->calculateLocalInertia(bodySettings.mass, inertia); } btRigidBody::btRigidBodyConstructionInfo constructionInfo(bodySettings.mass, NULL, collisionShape, inertia); constructionInfo.m_restitution = bodySettings.elasticity; constructionInfo.m_linearDamping = bodySettings.linearDamping; constructionInfo.m_angularDamping = bodySettings.angularDamping; constructionInfo.m_friction = bodySettings.friction; constructionInfo.m_linearSleepingThreshold = bodySettings.linearSleepVelocity; constructionInfo.m_angularSleepingThreshold = bodySettings.angularSleepVelocity; constructionInfo.m_startWorldTransform.setOrigin(btVector3(startPosition.x, startPosition.y, startPosition.z)); if( axis != Vector3::ZERO ) { constructionInfo.m_startWorldTransform.setRotation( btQuaternion(btVector3(axis.x, axis.y, axis.z), btScalar(angle)) ); } mBody = new btRigidBody( constructionInfo ); mBody->setUserPointer(this); }
void btFluidHfBuoyantConvexShape::generateShape(btScalar collisionRadius, btScalar volumeEstimationRadius) { m_voxelPositions.resize(0); btVoronoiSimplexSolver simplexSolver; btTransform voxelTransform = btTransform::getIdentity(); btVector3 aabbMin, aabbMax; getAabb( btTransform::getIdentity(), aabbMin, aabbMax ); //AABB of the convex shape //Generate voxels for collision { btSphereShape collisionShape(collisionRadius); const btScalar collisionDiameter = btScalar(2.0) * collisionRadius; btVector3 numVoxels = (aabbMax - aabbMin) / collisionDiameter; for(int i = 0; i < ceil( numVoxels.x() ); i++) { for(int j = 0; j < ceil( numVoxels.y() ); j++) { for(int k = 0; k < ceil( numVoxels.z() ); k++) { btVector3 voxelPosition = aabbMin + btVector3(i * collisionDiameter, j * collisionDiameter, k * collisionDiameter); voxelTransform.setOrigin(voxelPosition); if( intersect(&simplexSolver, btTransform::getIdentity(), voxelTransform, m_convexShape, &collisionShape) ) m_voxelPositions.push_back(voxelPosition); } } } const bool CENTER_VOXELS_AABB_ON_ORIGIN = true; if(CENTER_VOXELS_AABB_ON_ORIGIN) { btVector3 diameter(collisionDiameter, collisionDiameter, collisionDiameter); btVector3 voxelAabbMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT); btVector3 voxelAabbMax(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT); for(int i = 0; i < m_voxelPositions.size(); ++i) { voxelAabbMin.setMin(m_voxelPositions[i] - diameter); voxelAabbMax.setMax(m_voxelPositions[i] + diameter); } btVector3 offset = (voxelAabbMax - voxelAabbMin)*btScalar(0.5) - voxelAabbMax; for(int i = 0; i < m_voxelPositions.size(); ++i) m_voxelPositions[i] += offset; } } //Estimate volume with smaller spheres btScalar estimatedVolume; { btSphereShape volumeEstimationShape(volumeEstimationRadius); int numCollidingVoxels = 0; const btScalar estimationDiameter = btScalar(2.0) * volumeEstimationRadius; btVector3 numEstimationVoxels = (aabbMax - aabbMin) / estimationDiameter; for(int i = 0; i < ceil( numEstimationVoxels.x() ); i++) { for(int j = 0; j < ceil( numEstimationVoxels.y() ); j++) { for(int k = 0; k < ceil( numEstimationVoxels.z() ); k++) { btVector3 voxelPosition = aabbMin + btVector3(i * estimationDiameter, j * estimationDiameter, k * estimationDiameter); voxelTransform.setOrigin(voxelPosition); if( intersect(&simplexSolver, btTransform::getIdentity(), voxelTransform, m_convexShape, &volumeEstimationShape) ) ++numCollidingVoxels; } } } //Although the voxels are spherical, it is better to use the volume of a cube //for volume estimation. Since convex shapes are completely solid and the voxels //are generated by moving along a cubic lattice, using the volume of a sphere //would result in gaps. Comparing the volume of a cube with edge length 2(8 m^3) //and the volume of a sphere with diameter 2(~4 m^3), the estimated volume would //be off by about 1/2. btScalar volumePerEstimationVoxel = btPow( estimationDiameter, btScalar(3.0) ); //btScalar volumePerEstimationVoxel = btScalar(4.0/3.0) * SIMD_PI * btPow( volumeEstimationRadius, btScalar(3.0) ); estimatedVolume = static_cast<btScalar>(numCollidingVoxels) * volumePerEstimationVoxel; } m_volumePerVoxel = estimatedVolume / static_cast<btScalar>( getNumVoxels() ); m_totalVolume = estimatedVolume; m_collisionRadius = collisionRadius; }