#include "bulletshape.hpp" #include #include #include #include #include #include namespace Resource { namespace { CollisionShapePtr duplicateCollisionShape(const btCollisionShape* shape) { if (shape == nullptr) return nullptr; if (shape->isCompound()) { const btCompoundShape* comp = static_cast(shape); std::unique_ptr newShape(new btCompoundShape); for (int i = 0, n = comp->getNumChildShapes(); i < n; ++i) { auto child = duplicateCollisionShape(comp->getChildShape(i)); const btTransform& trans = comp->getChildTransform(i); newShape->addChildShape(trans, child.release()); } return newShape; } if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) { const btBvhTriangleMeshShape* trishape = static_cast(shape); return CollisionShapePtr(new btScaledBvhTriangleMeshShape( const_cast(trishape), btVector3(1.f, 1.f, 1.f))); } if (shape->getShapeType() == BOX_SHAPE_PROXYTYPE) { const btBoxShape* boxshape = static_cast(shape); return CollisionShapePtr(new btBoxShape(*boxshape)); } if (shape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE) return CollisionShapePtr( new btHeightfieldTerrainShape(static_cast(*shape))); throw std::logic_error(std::string("Unhandled Bullet shape duplication: ") + shape->getName()); } void deleteShape(btCollisionShape* shape) { if (shape->isCompound()) { btCompoundShape* compound = static_cast(shape); for (int i = 0, n = compound->getNumChildShapes(); i < n; i++) if (btCollisionShape* child = compound->getChildShape(i)) deleteShape(child); } delete shape; } } void DeleteCollisionShape::operator()(btCollisionShape* shape) const { deleteShape(shape); } BulletShape::BulletShape(const BulletShape& copy, const osg::CopyOp& copyop) : mCollisionShape(duplicateCollisionShape(copy.mCollisionShape.get())) , mAvoidCollisionShape(duplicateCollisionShape(copy.mAvoidCollisionShape.get())) , mCollisionBox(copy.mCollisionBox) , mAnimatedShapes(copy.mAnimatedShapes) , mFileName(copy.mFileName) , mFileHash(copy.mFileHash) { } void BulletShape::setLocalScaling(const btVector3& scale) { mCollisionShape->setLocalScaling(scale); if (mAvoidCollisionShape) mAvoidCollisionShape->setLocalScaling(scale); } osg::ref_ptr makeInstance(osg::ref_ptr source) { return { new BulletShapeInstance(std::move(source)) }; } BulletShapeInstance::BulletShapeInstance(osg::ref_ptr source) : mSource(std::move(source)) { mCollisionBox = mSource->mCollisionBox; mAnimatedShapes = mSource->mAnimatedShapes; mVisualCollisionType = mSource->mVisualCollisionType; mCollisionShape = duplicateCollisionShape(mSource->mCollisionShape.get()); mAvoidCollisionShape = duplicateCollisionShape(mSource->mAvoidCollisionShape.get()); } }