#include "object.hpp" #include #include #include #include #include #include #include #include #include namespace MWPhysics { Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance) : mShapeInstance(shapeInstance) , mSolid(true) { mPtr = ptr; mCollisionObject.reset(new btCollisionObject); mCollisionObject->setCollisionShape(shapeInstance->getCollisionShape()); mCollisionObject->setUserPointer(static_cast(this)); setScale(ptr.getCellRef().getScale()); setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude())); const float* pos = ptr.getRefData().getPosition().pos; setOrigin(btVector3(pos[0], pos[1], pos[2])); } const Resource::BulletShapeInstance* Object::getShapeInstance() const { return mShapeInstance.get(); } void Object::setScale(float scale) { mShapeInstance->setLocalScaling(btVector3(scale, scale, scale)); } void Object::setRotation(const btQuaternion& quat) { mCollisionObject->getWorldTransform().setRotation(quat); } void Object::setOrigin(const btVector3& vec) { mCollisionObject->getWorldTransform().setOrigin(vec); } btCollisionObject* Object::getCollisionObject() { return mCollisionObject.get(); } const btCollisionObject* Object::getCollisionObject() const { return mCollisionObject.get(); } bool Object::isSolid() const { return mSolid; } void Object::setSolid(bool solid) { mSolid = solid; } bool Object::isAnimated() const { return !mShapeInstance->mAnimatedShapes.empty(); } void Object::animateCollisionShapes(btCollisionWorld* collisionWorld) { if (mShapeInstance->mAnimatedShapes.empty()) return; assert (mShapeInstance->getCollisionShape()->isCompound()); btCompoundShape* compound = static_cast(mShapeInstance->getCollisionShape()); for (std::map::const_iterator it = mShapeInstance->mAnimatedShapes.begin(); it != mShapeInstance->mAnimatedShapes.end(); ++it) { int recIndex = it->first; int shapeIndex = it->second; std::map::iterator nodePathFound = mRecIndexToNodePath.find(recIndex); if (nodePathFound == mRecIndexToNodePath.end()) { NifOsg::FindGroupByRecIndex visitor(recIndex); mPtr.getRefData().getBaseNode()->accept(visitor); if (!visitor.mFound) { Log(Debug::Warning) << "Warning: animateCollisionShapes can't find node " << recIndex << " for " << mPtr.getCellRef().getRefId(); // Remove nonexistent nodes from animated shapes map and early out mShapeInstance->mAnimatedShapes.erase(recIndex); return; } osg::NodePath nodePath = visitor.mFoundPath; nodePath.erase(nodePath.begin()); nodePathFound = mRecIndexToNodePath.insert(std::make_pair(recIndex, nodePath)).first; } osg::NodePath& nodePath = nodePathFound->second; osg::Matrixf matrix = osg::computeLocalToWorld(nodePath); matrix.orthoNormalize(matrix); btTransform transform; transform.setOrigin(Misc::Convert::toBullet(matrix.getTrans()) * compound->getLocalScaling()); for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) transform.getBasis()[i][j] = matrix(j,i); // NB column/row major difference // Note: we can not apply scaling here for now since we treat scaled shapes // as new shapes (btScaledBvhTriangleMeshShape) with 1.0 scale for now if (!(transform == compound->getChildTransform(shapeIndex))) compound->updateChildTransform(shapeIndex, transform); } collisionWorld->updateSingleAabb(mCollisionObject.get()); } }