Merge branch 'refactor_bullet_shape' into 'master'

Refactor bullet shape

See merge request OpenMW/openmw!1333
pull/3212/head
psi29a 3 years ago
commit 523289c531

@ -22,7 +22,7 @@ namespace MWPhysics
Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler, bool canWaterWalk)
: mStandingOnPtr(nullptr), mCanWaterWalk(canWaterWalk), mWalkingOnWater(false)
, mMeshTranslation(shape->mCollisionBox.center), mOriginalHalfExtents(shape->mCollisionBox.extents)
, mMeshTranslation(shape->mCollisionBox.mCenter), mOriginalHalfExtents(shape->mCollisionBox.mExtents)
, mStuckFrames(0), mLastStuckPosition{0, 0, 0}
, mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
, mInternalCollisionMode(true)

@ -24,7 +24,7 @@ namespace MWPhysics
, mTaskScheduler(scheduler)
{
mPtr = ptr;
mCollisionObject = BulletHelpers::makeCollisionObject(mShapeInstance->getCollisionShape(),
mCollisionObject = BulletHelpers::makeCollisionObject(mShapeInstance->mCollisionShape.get(),
Misc::Convert::toBullet(mPosition), Misc::Convert::toBullet(rotation));
mCollisionObject->setUserPointer(this);
mShapeInstance->setLocalScaling(mScale);
@ -109,9 +109,9 @@ namespace MWPhysics
if (mShapeInstance->mAnimatedShapes.empty())
return false;
assert (mShapeInstance->getCollisionShape()->isCompound());
assert (mShapeInstance->mCollisionShape->isCompound());
btCompoundShape* compound = static_cast<btCompoundShape*>(mShapeInstance->getCollisionShape());
btCompoundShape* compound = static_cast<btCompoundShape*>(mShapeInstance->mCollisionShape.get());
for (const auto& [recIndex, shapeIndex] : mShapeInstance->mAnimatedShapes)
{
auto nodePathFound = mRecIndexToNodePath.find(recIndex);

@ -481,7 +481,7 @@ namespace MWPhysics
if (ptr.mRef->mData.mPhysicsPostponed)
return;
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->getInstance(mesh);
if (!shapeInstance || !shapeInstance->getCollisionShape())
if (!shapeInstance || !shapeInstance->mCollisionShape)
return;
assert(!getObject(ptr));
@ -618,7 +618,7 @@ namespace MWPhysics
osg::ref_ptr<const Resource::BulletShape> shape = mShapeManager->getShape(mesh);
// Try to get shape from basic model as fallback for creatures
if (!ptr.getClass().isNpc() && shape && shape->mCollisionBox.extents.length2() == 0)
if (!ptr.getClass().isNpc() && shape && shape->mCollisionBox.mExtents.length2() == 0)
{
const std::string fallbackModel = ptr.getClass().getModel(ptr);
if (fallbackModel != mesh)
@ -643,7 +643,7 @@ namespace MWPhysics
{
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->getInstance(mesh);
assert(shapeInstance);
float radius = computeRadius ? shapeInstance->mCollisionBox.extents.length() / 2.f : 1.f;
float radius = computeRadius ? shapeInstance->mCollisionBox.mExtents.length() / 2.f : 1.f;
mProjectileId++;

@ -132,7 +132,7 @@ namespace
{
btVector3 aabbMin;
btVector3 aabbMax;
object->getShapeInstance()->getCollisionShape()->getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
object->getShapeInstance()->mCollisionShape->getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
const auto center = (aabbMax + aabbMin) * 0.5f;

@ -3948,7 +3948,7 @@ namespace MWWorld
btVector3 aabbMin;
btVector3 aabbMax;
object->getShapeInstance()->getCollisionShape()->getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
object->getShapeInstance()->mCollisionShape->getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
const auto toLocal = object->getTransform().inverse();
const auto localFrom = toLocal(Misc::Convert::toBullet(position));

@ -117,7 +117,7 @@ namespace
osg::ref_ptr<const Resource::BulletShapeInstance> makeBulletShapeInstance(std::unique_ptr<T>&& shape)
{
osg::ref_ptr<Resource::BulletShape> bulletShape(new Resource::BulletShape);
bulletShape->mCollisionShape = std::move(shape).release();
bulletShape->mCollisionShape.reset(std::move(shape).release());
return new Resource::BulletShapeInstance(bulletShape);
}
@ -466,7 +466,7 @@ namespace
}};
std::unique_ptr<btHeightfieldTerrainShape> shapePtr = makeSquareHeightfieldTerrainShape(heightfieldData);
shapePtr->setLocalScaling(btVector3(128, 128, 1));
bulletShape->mCollisionShape = shapePtr.release();
bulletShape->mCollisionShape.reset(shapePtr.release());
std::array<btScalar, 5 * 5> heightfieldDataAvoid {{
-25, -25, -25, -25, -25,
@ -477,12 +477,12 @@ namespace
}};
std::unique_ptr<btHeightfieldTerrainShape> shapeAvoidPtr = makeSquareHeightfieldTerrainShape(heightfieldDataAvoid);
shapeAvoidPtr->setLocalScaling(btVector3(128, 128, 1));
bulletShape->mAvoidCollisionShape = shapeAvoidPtr.release();
bulletShape->mAvoidCollisionShape.reset(shapeAvoidPtr.release());
osg::ref_ptr<const Resource::BulletShapeInstance> instance(new Resource::BulletShapeInstance(bulletShape));
mNavigator->addAgent(mAgentHalfExtents);
mNavigator->addObject(ObjectId(instance->getCollisionShape()), ObjectShapes(instance), btTransform::getIdentity());
mNavigator->addObject(ObjectId(instance->mCollisionShape.get()), ObjectShapes(instance), btTransform::getIdentity());
mNavigator->update(mPlayerPosition);
mNavigator->wait(mListener, WaitConditionType::allJobsDone);

@ -160,20 +160,20 @@ namespace Resource
{
static bool operator ==(const Resource::BulletShape& lhs, const Resource::BulletShape& rhs)
{
return compareObjects(lhs.mCollisionShape, rhs.mCollisionShape)
&& compareObjects(lhs.mAvoidCollisionShape, rhs.mAvoidCollisionShape)
&& lhs.mCollisionBox.extents == rhs.mCollisionBox.extents
&& lhs.mCollisionBox.center == rhs.mCollisionBox.center
return compareObjects(lhs.mCollisionShape.get(), rhs.mCollisionShape.get())
&& compareObjects(lhs.mAvoidCollisionShape.get(), rhs.mAvoidCollisionShape.get())
&& lhs.mCollisionBox.mExtents == rhs.mCollisionBox.mExtents
&& lhs.mCollisionBox.mCenter == rhs.mCollisionBox.mCenter
&& lhs.mAnimatedShapes == rhs.mAnimatedShapes;
}
static std::ostream& operator <<(std::ostream& stream, const Resource::BulletShape& value)
{
return stream << "Resource::BulletShape {"
<< value.mCollisionShape << ", "
<< value.mAvoidCollisionShape << ", "
<< "osg::Vec3f {" << value.mCollisionBox.extents << "}" << ", "
<< "osg::Vec3f {" << value.mCollisionBox.center << "}" << ", "
<< value.mCollisionShape.get() << ", "
<< value.mAvoidCollisionShape.get() << ", "
<< "osg::Vec3f {" << value.mCollisionBox.mExtents << "}" << ", "
<< "osg::Vec3f {" << value.mCollisionBox.mCenter << "}" << ", "
<< value.mAnimatedShapes
<< "}";
}
@ -441,12 +441,12 @@ namespace
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
expected.mCollisionBox.extents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.center = osg::Vec3f(-1, -2, -3);
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.mCenter = osg::Vec3f(-1, -2, -3);
std::unique_ptr<btBoxShape> box(new btBoxShape(btVector3(1, 2, 3)));
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(-1, -2, -3)), box.release());
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
EXPECT_EQ(*result, expected);
}
@ -466,12 +466,12 @@ namespace
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
expected.mCollisionBox.extents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.center = osg::Vec3f(-1, -2, -3);
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.mCenter = osg::Vec3f(-1, -2, -3);
std::unique_ptr<btBoxShape> box(new btBoxShape(btVector3(1, 2, 3)));
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(-1, -2, -3)), box.release());
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
EXPECT_EQ(*result, expected);
}
@ -496,12 +496,12 @@ namespace
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
expected.mCollisionBox.extents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.center = osg::Vec3f(-1, -2, -3);
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.mCenter = osg::Vec3f(-1, -2, -3);
std::unique_ptr<btBoxShape> box(new btBoxShape(btVector3(1, 2, 3)));
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(-1, -2, -3)), box.release());
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
EXPECT_EQ(*result, expected);
}
@ -531,12 +531,12 @@ namespace
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
expected.mCollisionBox.extents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.center = osg::Vec3f(-1, -2, -3);
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.mCenter = osg::Vec3f(-1, -2, -3);
std::unique_ptr<btBoxShape> box(new btBoxShape(btVector3(1, 2, 3)));
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(-1, -2, -3)), box.release());
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
EXPECT_EQ(*result, expected);
}
@ -566,12 +566,12 @@ namespace
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
expected.mCollisionBox.extents = osg::Vec3f(4, 5, 6);
expected.mCollisionBox.center = osg::Vec3f(-4, -5, -6);
expected.mCollisionBox.mExtents = osg::Vec3f(4, 5, 6);
expected.mCollisionBox.mCenter = osg::Vec3f(-4, -5, -6);
std::unique_ptr<btBoxShape> box(new btBoxShape(btVector3(4, 5, 6)));
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(-4, -5, -6)), box.release());
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
EXPECT_EQ(*result, expected);
}
@ -589,8 +589,8 @@ namespace
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
expected.mCollisionBox.extents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.center = osg::Vec3f(-1, -2, -3);
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.mCenter = osg::Vec3f(-1, -2, -3);
EXPECT_EQ(*result, expected);
}
@ -605,7 +605,7 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mCollisionShape = new Resource::TriangleMeshShape(triangles.release(), true);
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
EXPECT_EQ(*result, expected);
}
@ -623,8 +623,8 @@ namespace
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
expected.mCollisionBox.extents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.center = osg::Vec3f(-1, -2, -3);
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
expected.mCollisionBox.mCenter = osg::Vec3f(-1, -2, -3);
EXPECT_EQ(*result, expected);
}
@ -641,7 +641,7 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mCollisionShape = new Resource::TriangleMeshShape(triangles.release(), true);
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
EXPECT_EQ(*result, expected);
}
@ -659,7 +659,7 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mCollisionShape = new Resource::TriangleMeshShape(triangles.release(), true);
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
EXPECT_EQ(*result, expected);
}
@ -680,7 +680,7 @@ namespace
triangles->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mCollisionShape = new Resource::TriangleMeshShape(triangles.release(), true);
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
EXPECT_EQ(*result, expected);
}
@ -698,7 +698,7 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mCollisionShape = new Resource::TriangleMeshShape(triangles.release(), true);
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
EXPECT_EQ(*result, expected);
}
@ -720,7 +720,7 @@ namespace
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(mResultTransform, mesh.release());
Resource::BulletShape expected;
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
expected.mAnimatedShapes = {{-1, 0}};
EXPECT_EQ(*result, expected);
@ -746,7 +746,7 @@ namespace
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(mResultTransform2, mesh.release());
Resource::BulletShape expected;
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
expected.mAnimatedShapes = {{-1, 0}};
EXPECT_EQ(*result, expected);
@ -784,7 +784,7 @@ namespace
shape->addChildShape(mResultTransform, mesh.release());
shape->addChildShape(mResultTransform, mesh2.release());
Resource::BulletShape expected;
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
expected.mAnimatedShapes = {{-1, 0}};
EXPECT_EQ(*result, expected);
@ -813,7 +813,7 @@ namespace
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(mResultTransform2, mesh.release());
Resource::BulletShape expected;
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
expected.mAnimatedShapes = {{-1, 0}};
EXPECT_EQ(*result, expected);
@ -854,7 +854,7 @@ namespace
shape->addChildShape(mResultTransform2, mesh2.release());
shape->addChildShape(btTransform::getIdentity(), mesh.release());
Resource::BulletShape expected;
expected.mCollisionShape = shape.release();
expected.mCollisionShape.reset(shape.release());
expected.mAnimatedShapes = {{-1, 0}};
EXPECT_EQ(*result, expected);
@ -873,7 +873,7 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mAvoidCollisionShape = new Resource::TriangleMeshShape(triangles.release(), false);
expected.mAvoidCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), false));
EXPECT_EQ(*result, expected);
}
@ -979,7 +979,7 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mCollisionShape = new Resource::TriangleMeshShape(triangles.release(), true);
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
EXPECT_EQ(*result, expected);
}

@ -34,9 +34,9 @@ namespace DetourNavigator
bool NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
{
CollisionShape collisionShape {shapes.mShapeInstance, *shapes.mShapeInstance->getCollisionShape()};
CollisionShape collisionShape {shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape};
bool result = mNavMeshManager.addObject(id, collisionShape, transform, AreaType_ground);
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->getAvoidCollisionShape())
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get())
{
const ObjectId avoidId(avoidShape);
CollisionShape avoidCollisionShape {shapes.mShapeInstance, *avoidShape};
@ -64,9 +64,9 @@ namespace DetourNavigator
bool NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
{
const CollisionShape collisionShape {shapes.mShapeInstance, *shapes.mShapeInstance->getCollisionShape()};
const CollisionShape collisionShape {shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape};
bool result = mNavMeshManager.updateObject(id, collisionShape, transform, AreaType_ground);
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->getAvoidCollisionShape())
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get())
{
const ObjectId avoidId(avoidShape);
const CollisionShape avoidCollisionShape {shapes.mShapeInstance, *avoidShape};

@ -143,8 +143,8 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
{
if (findBoundingBox(node, filename))
{
const btVector3 extents = Misc::Convert::toBullet(mShape->mCollisionBox.extents);
const btVector3 center = Misc::Convert::toBullet(mShape->mCollisionBox.center);
const btVector3 extents = Misc::Convert::toBullet(mShape->mCollisionBox.mExtents);
const btVector3 center = Misc::Convert::toBullet(mShape->mCollisionBox.mCenter);
std::unique_ptr<btCompoundShape> compound (new btCompoundShape);
std::unique_ptr<btBoxShape> boxShape(new btBoxShape(extents));
btTransform transform = btTransform::getIdentity();
@ -152,7 +152,7 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
compound->addChildShape(transform, boxShape.get());
boxShape.release();
mShape->mCollisionShape = compound.release();
mShape->mCollisionShape.reset(compound.release());
return mShape;
}
}
@ -179,17 +179,17 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
child.release();
mStaticMesh.release();
}
mShape->mCollisionShape = mCompoundShape.release();
mShape->mCollisionShape = std::move(mCompoundShape);
}
else if (mStaticMesh)
{
mShape->mCollisionShape = new Resource::TriangleMeshShape(mStaticMesh.get(), true);
mShape->mCollisionShape.reset(new Resource::TriangleMeshShape(mStaticMesh.get(), true));
mStaticMesh.release();
}
if (mAvoidStaticMesh)
{
mShape->mAvoidCollisionShape = new Resource::TriangleMeshShape(mAvoidStaticMesh.get(), false);
mShape->mAvoidCollisionShape.reset(new Resource::TriangleMeshShape(mAvoidStaticMesh.get(), false));
mAvoidStaticMesh.release();
}
@ -206,8 +206,8 @@ bool BulletNifLoader::findBoundingBox(const Nif::Node* node, const std::string&
switch (type)
{
case Nif::NiBoundingVolume::Type::BOX_BV:
mShape->mCollisionBox.extents = node->bounds.box.extents;
mShape->mCollisionBox.center = node->bounds.box.center;
mShape->mCollisionBox.mExtents = node->bounds.box.extents;
mShape->mCollisionBox.mCenter = node->bounds.box.center;
break;
default:
{

@ -61,7 +61,7 @@ private:
void handleNiTriShape(const Nif::Node *nifNode, int flags, const osg::Matrixf& transform, bool isAnimated, bool avoid);
std::unique_ptr<btCompoundShape> mCompoundShape;
std::unique_ptr<btCompoundShape, Resource::DeleteCollisionShape> mCompoundShape;
std::unique_ptr<btTriangleMesh> mStaticMesh;

@ -10,86 +10,71 @@
namespace Resource
{
BulletShape::BulletShape()
: mCollisionShape(nullptr)
, mAvoidCollisionShape(nullptr)
namespace
{
CollisionShapePtr duplicateCollisionShape(const btCollisionShape *shape)
{
if (shape == nullptr)
return nullptr;
}
if (shape->isCompound())
{
const btCompoundShape *comp = static_cast<const btCompoundShape*>(shape);
std::unique_ptr<btCompoundShape, DeleteCollisionShape> newShape(new btCompoundShape);
BulletShape::BulletShape(const BulletShape &copy, const osg::CopyOp &copyop)
: mCollisionShape(duplicateCollisionShape(copy.mCollisionShape))
, mAvoidCollisionShape(duplicateCollisionShape(copy.mAvoidCollisionShape))
, mCollisionBox(copy.mCollisionBox)
, mAnimatedShapes(copy.mAnimatedShapes)
{
}
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());
}
BulletShape::~BulletShape()
{
deleteShape(mAvoidCollisionShape);
deleteShape(mCollisionShape);
}
return newShape;
}
void BulletShape::deleteShape(btCollisionShape* shape)
{
if(shape!=nullptr)
{
if(shape->isCompound())
if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
btCompoundShape* ms = static_cast<btCompoundShape*>(shape);
int a = ms->getNumChildShapes();
for(int i=0; i <a;i++)
deleteShape(ms->getChildShape(i));
const btBvhTriangleMeshShape* trishape = static_cast<const btBvhTriangleMeshShape*>(shape);
return CollisionShapePtr(new btScaledBvhTriangleMeshShape(const_cast<btBvhTriangleMeshShape*>(trishape), btVector3(1.f, 1.f, 1.f)));
}
delete shape;
}
}
btCollisionShape* BulletShape::duplicateCollisionShape(const btCollisionShape *shape) const
{
if(shape->isCompound())
{
const btCompoundShape *comp = static_cast<const btCompoundShape*>(shape);
btCompoundShape *newShape = new btCompoundShape;
int numShapes = comp->getNumChildShapes();
for(int i = 0;i < numShapes;++i)
if (shape->getShapeType() == BOX_SHAPE_PROXYTYPE)
{
btCollisionShape *child = duplicateCollisionShape(comp->getChildShape(i));
const btTransform& trans = comp->getChildTransform(i);
newShape->addChildShape(trans, child);
const btBoxShape* boxshape = static_cast<const btBoxShape*>(shape);
return CollisionShapePtr(new btBoxShape(*boxshape));
}
return newShape;
}
if (shape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
return CollisionShapePtr(new btHeightfieldTerrainShape(static_cast<const btHeightfieldTerrainShape&>(*shape)));
if(const btBvhTriangleMeshShape* trishape = dynamic_cast<const btBvhTriangleMeshShape*>(shape))
{
btScaledBvhTriangleMeshShape* newShape = new btScaledBvhTriangleMeshShape(const_cast<btBvhTriangleMeshShape*>(trishape), btVector3(1.f, 1.f, 1.f));
return newShape;
throw std::logic_error(std::string("Unhandled Bullet shape duplication: ") + shape->getName());
}
if (const btBoxShape* boxshape = dynamic_cast<const btBoxShape*>(shape))
void deleteShape(btCollisionShape* shape)
{
return new btBoxShape(*boxshape);
}
if (shape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
return new btHeightfieldTerrainShape(static_cast<const btHeightfieldTerrainShape&>(*shape));
if (shape->isCompound())
{
btCompoundShape* compound = static_cast<btCompoundShape*>(shape);
for (int i = 0, n = compound->getNumChildShapes(); i < n; i++)
if (btCollisionShape* child = compound->getChildShape(i))
deleteShape(child);
}
throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName());
delete shape;
}
}
btCollisionShape *BulletShape::getCollisionShape() const
void DeleteCollisionShape::operator()(btCollisionShape* shape) const
{
return mCollisionShape;
deleteShape(shape);
}
btCollisionShape *BulletShape::getAvoidCollisionShape() const
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)
{
return mAvoidCollisionShape;
}
void BulletShape::setLocalScaling(const btVector3& scale)
@ -99,30 +84,18 @@ void BulletShape::setLocalScaling(const btVector3& scale)
mAvoidCollisionShape->setLocalScaling(scale);
}
bool BulletShape::isAnimated() const
osg::ref_ptr<BulletShapeInstance> makeInstance(osg::ref_ptr<const BulletShape> source)
{
return !mAnimatedShapes.empty();
}
osg::ref_ptr<BulletShapeInstance> BulletShape::makeInstance() const
{
osg::ref_ptr<BulletShapeInstance> instance (new BulletShapeInstance(this));
return instance;
return {new BulletShapeInstance(std::move(source))};
}
BulletShapeInstance::BulletShapeInstance(osg::ref_ptr<const BulletShape> source)
: BulletShape()
, mSource(source)
: mSource(std::move(source))
{
mCollisionBox = source->mCollisionBox;
mAnimatedShapes = source->mAnimatedShapes;
if (source->mCollisionShape)
mCollisionShape = duplicateCollisionShape(source->mCollisionShape);
if (source->mAvoidCollisionShape)
mAvoidCollisionShape = duplicateCollisionShape(source->mAvoidCollisionShape);
mCollisionBox = mSource->mCollisionBox;
mAnimatedShapes = mSource->mAnimatedShapes;
mCollisionShape = duplicateCollisionShape(mSource->mCollisionShape.get());
mAvoidCollisionShape = duplicateCollisionShape(mSource->mAvoidCollisionShape.get());
}
}

@ -2,6 +2,7 @@
#define OPENMW_COMPONENTS_RESOURCE_BULLETSHAPE_H
#include <map>
#include <memory>
#include <osg/Object>
#include <osg/ref_ptr>
@ -13,24 +14,28 @@ class btCollisionShape;
namespace Resource
{
struct DeleteCollisionShape
{
void operator()(btCollisionShape* shape) const;
};
using CollisionShapePtr = std::unique_ptr<btCollisionShape, DeleteCollisionShape>;
class BulletShapeInstance;
class BulletShape : public osg::Object
{
public:
BulletShape();
BulletShape() = default;
BulletShape(const BulletShape& copy, const osg::CopyOp& copyop);
virtual ~BulletShape();
META_Object(Resource, BulletShape)
btCollisionShape* mCollisionShape;
btCollisionShape* mAvoidCollisionShape;
CollisionShapePtr mCollisionShape;
CollisionShapePtr mAvoidCollisionShape;
struct CollisionBox
{
osg::Vec3f extents;
osg::Vec3f center;
osg::Vec3f mExtents;
osg::Vec3f mCenter;
};
// Used for actors and projectiles. mCollisionShape is used for actors only when we need to autogenerate collision box for creatures.
// For now, use one file <-> one resource for simplicity.
@ -42,21 +47,9 @@ namespace Resource
// we store the node's record index mapped to the child index of the shape in the btCompoundShape.
std::map<int, int> mAnimatedShapes;
osg::ref_ptr<BulletShapeInstance> makeInstance() const;
btCollisionShape* duplicateCollisionShape(const btCollisionShape* shape) const;
btCollisionShape* getCollisionShape() const;
btCollisionShape* getAvoidCollisionShape() const;
void setLocalScaling(const btVector3& scale);
bool isAnimated() const;
private:
void deleteShape(btCollisionShape* shape);
bool isAnimated() const { return !mAnimatedShapes.empty(); }
};
@ -71,6 +64,8 @@ namespace Resource
osg::ref_ptr<const BulletShape> mSource;
};
osg::ref_ptr<BulletShapeInstance> makeInstance(osg::ref_ptr<const BulletShape> source);
// Subclass btBhvTriangleMeshShape to auto-delete the meshInterface
struct TriangleMeshShape : public btBvhTriangleMeshShape
{

@ -83,16 +83,17 @@ public:
return osg::ref_ptr<BulletShape>();
osg::ref_ptr<BulletShape> shape (new BulletShape);
btBvhTriangleMeshShape* triangleMeshShape = new TriangleMeshShape(mTriangleMesh.release(), true);
auto triangleMeshShape = std::make_unique<TriangleMeshShape>(mTriangleMesh.release(), true);
btVector3 aabbMin = triangleMeshShape->getLocalAabbMin();
btVector3 aabbMax = triangleMeshShape->getLocalAabbMax();
shape->mCollisionBox.extents[0] = (aabbMax[0] - aabbMin[0]) / 2.0f;
shape->mCollisionBox.extents[1] = (aabbMax[1] - aabbMin[1]) / 2.0f;
shape->mCollisionBox.extents[2] = (aabbMax[2] - aabbMin[2]) / 2.0f;
shape->mCollisionBox.center = osg::Vec3f( (aabbMax[0] + aabbMin[0]) / 2.0f,
shape->mCollisionBox.mExtents[0] = (aabbMax[0] - aabbMin[0]) / 2.0f;
shape->mCollisionBox.mExtents[1] = (aabbMax[1] - aabbMin[1]) / 2.0f;
shape->mCollisionBox.mExtents[2] = (aabbMax[2] - aabbMin[2]) / 2.0f;
shape->mCollisionBox.mCenter = osg::Vec3f( (aabbMax[0] + aabbMin[0]) / 2.0f,
(aabbMax[1] + aabbMin[1]) / 2.0f,
(aabbMax[2] + aabbMin[2]) / 2.0f );
shape->mCollisionShape = triangleMeshShape;
shape->mCollisionShape.reset(triangleMeshShape.release());
return shape;
}
@ -193,9 +194,8 @@ osg::ref_ptr<BulletShapeInstance> BulletShapeManager::createInstance(const std::
{
osg::ref_ptr<const BulletShape> shape = getShape(name);
if (shape)
return shape->makeInstance();
else
return osg::ref_ptr<BulletShapeInstance>();
return makeInstance(std::move(shape));
return osg::ref_ptr<BulletShapeInstance>();
}
void BulletShapeManager::updateCache(double referenceTime)

Loading…
Cancel
Save