mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:59:54 +00:00
Readded animated collision shape support
This commit is contained in:
parent
19988d5e45
commit
65f0195c71
9 changed files with 118 additions and 90 deletions
|
@ -25,6 +25,11 @@ namespace MWPhysics
|
|||
public:
|
||||
virtual ~PtrHolder() {}
|
||||
|
||||
void updatePtr(const MWWorld::Ptr& updated)
|
||||
{
|
||||
mPtr = updated;
|
||||
}
|
||||
|
||||
protected:
|
||||
MWWorld::Ptr mPtr;
|
||||
};
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
|
||||
#include <components/nifbullet/bulletshapemanager.hpp>
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
|
||||
#include <components/esm/loadgmst.hpp>
|
||||
|
||||
#include <components/nifosg/particle.hpp> // FindRecIndexVisitor
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
|
@ -24,7 +26,6 @@
|
|||
|
||||
#include "../mwrender/bulletdebugdraw.hpp"
|
||||
|
||||
//#include "../apps/openmw/mwrender/animation.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
|
@ -35,57 +36,6 @@
|
|||
#include "convert.hpp"
|
||||
#include "trace.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/*
|
||||
void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>& map, btDynamicsWorld* dynamicsWorld)
|
||||
{
|
||||
for (std::map<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>::iterator it = map.begin();
|
||||
it != map.end(); ++it)
|
||||
{
|
||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle(it->first->mName);
|
||||
if (ptr.isEmpty()) // Shouldn't happen
|
||||
throw std::runtime_error("can't find Ptr");
|
||||
|
||||
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr);
|
||||
if (!animation)
|
||||
continue;
|
||||
|
||||
OEngine::Physic::AnimatedShapeInstance& instance = it->second;
|
||||
|
||||
std::map<int, int>& shapes = instance.mAnimatedShapes;
|
||||
for (std::map<int, int>::iterator shapeIt = shapes.begin();
|
||||
shapeIt != shapes.end(); ++shapeIt)
|
||||
{
|
||||
|
||||
const std::string& mesh = animation->getObjectRootName();
|
||||
int boneHandle = NifOgre::NIFSkeletonLoader::lookupOgreBoneHandle(mesh, shapeIt->first);
|
||||
Ogre::Node* bone = animation->getNode(boneHandle);
|
||||
|
||||
if (bone == NULL)
|
||||
continue;
|
||||
|
||||
btCompoundShape* compound = static_cast<btCompoundShape*>(instance.mCompound);
|
||||
|
||||
btTransform trans;
|
||||
trans.setOrigin(BtOgre::Convert::toBullet(bone->_getDerivedPosition()) * compound->getLocalScaling());
|
||||
trans.setRotation(BtOgre::Convert::toBullet(bone->_getDerivedOrientation()));
|
||||
|
||||
compound->getChildShape(shapeIt->second)->setLocalScaling(
|
||||
compound->getLocalScaling() *
|
||||
BtOgre::Convert::toBullet(bone->_getDerivedScale()));
|
||||
compound->updateChildTransform(shapeIt->second, trans);
|
||||
}
|
||||
|
||||
// needed because we used btDynamicsWorld::setForceUpdateAllAabbs(false)
|
||||
dynamicsWorld->updateSingleAabb(it->first);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
namespace MWPhysics
|
||||
{
|
||||
|
||||
|
@ -569,11 +519,6 @@ namespace MWPhysics
|
|||
setOrigin(btVector3(pos[0], pos[1], pos[2]));
|
||||
}
|
||||
|
||||
void updatePtr(const MWWorld::Ptr& updated)
|
||||
{
|
||||
mPtr = updated;
|
||||
}
|
||||
|
||||
void setScale(float scale)
|
||||
{
|
||||
mShapeInstance->getCollisionShape()->setLocalScaling(btVector3(scale,scale,scale));
|
||||
|
@ -594,6 +539,47 @@ namespace MWPhysics
|
|||
return mCollisionObject.get();
|
||||
}
|
||||
|
||||
void animateCollisionShapes(btDynamicsWorld* dynamicsWorld)
|
||||
{
|
||||
if (mShapeInstance->mAnimatedShapes.empty())
|
||||
return;
|
||||
|
||||
assert (mShapeInstance->getCollisionShape()->isCompound());
|
||||
|
||||
btCompoundShape* compound = dynamic_cast<btCompoundShape*>(mShapeInstance->getCollisionShape());
|
||||
|
||||
for (std::map<int, int>::const_iterator it = mShapeInstance->mAnimatedShapes.begin(); it != mShapeInstance->mAnimatedShapes.end(); ++it)
|
||||
{
|
||||
int recIndex = it->first;
|
||||
int shapeIndex = it->second;
|
||||
|
||||
NifOsg::FindRecIndexVisitor visitor(recIndex);
|
||||
mPtr.getRefData().getBaseNode()->accept(visitor);
|
||||
if (!visitor.mFound)
|
||||
{
|
||||
std::cerr << "animateCollisionShapes: Can't find node " << recIndex << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
osg::NodePath path = visitor.mFoundPath;
|
||||
path.erase(path.begin());
|
||||
osg::Matrixf matrix = osg::computeLocalToWorld(path);
|
||||
osg::Vec3f scale = matrix.getScale();
|
||||
matrix.orthoNormalize(matrix);
|
||||
|
||||
btTransform transform;
|
||||
transform.setOrigin(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
|
||||
|
||||
compound->getChildShape(shapeIndex)->setLocalScaling(compound->getLocalScaling() * toBullet(scale));
|
||||
compound->updateChildTransform(shapeIndex, transform);
|
||||
}
|
||||
|
||||
dynamicsWorld->updateSingleAabb(mCollisionObject.get());
|
||||
}
|
||||
|
||||
private:
|
||||
std::auto_ptr<btCollisionObject> mCollisionObject;
|
||||
osg::ref_ptr<NifBullet::BulletShapeInstance> mShapeInstance;
|
||||
|
@ -601,8 +587,8 @@ namespace MWPhysics
|
|||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
PhysicsSystem::PhysicsSystem(const VFS::Manager* vfs, osg::ref_ptr<osg::Group> parentNode)
|
||||
: mShapeManager(new NifBullet::BulletShapeManager(vfs))
|
||||
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode)
|
||||
: mShapeManager(new NifBullet::BulletShapeManager(resourceSystem->getVFS(), resourceSystem->getSceneManager()))
|
||||
, mTimeAccum(0.0f)
|
||||
, mWaterEnabled(false)
|
||||
, mWaterHeight(0)
|
||||
|
@ -795,6 +781,27 @@ namespace MWPhysics
|
|||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &updated)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(old);
|
||||
if (found != mObjects.end())
|
||||
{
|
||||
Object* obj = found->second;
|
||||
obj->updatePtr(updated);
|
||||
mObjects.erase(found);
|
||||
mObjects.insert(std::make_pair(updated, obj));
|
||||
}
|
||||
|
||||
ActorMap::iterator foundActor = mActors.find(old);
|
||||
if (foundActor != mActors.end())
|
||||
{
|
||||
Actor* actor = foundActor->second;
|
||||
actor->updatePtr(updated);
|
||||
mActors.erase(foundActor);
|
||||
mActors.insert(std::make_pair(updated, actor));
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::updateScale(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(ptr);
|
||||
|
@ -955,7 +962,8 @@ namespace MWPhysics
|
|||
|
||||
void PhysicsSystem::stepSimulation(float dt)
|
||||
{
|
||||
//animateCollisionShapes(mEngine->mAnimatedShapes, mDynamicsWorld);
|
||||
for (ObjectMap::iterator it = mObjects.begin(); it != mObjects.end(); ++it)
|
||||
it->second->animateCollisionShapes(mDynamicsWorld);
|
||||
|
||||
// We have nothing to simulate, but character controllers aren't working without this call. Might be related to updating AABBs.
|
||||
mDynamicsWorld->stepSimulation(static_cast<btScalar>(dt), 1, 1 / 60.0f);
|
||||
|
|
|
@ -26,9 +26,9 @@ namespace NifBullet
|
|||
class BulletShapeManager;
|
||||
}
|
||||
|
||||
namespace VFS
|
||||
namespace Resource
|
||||
{
|
||||
class Manager;
|
||||
class ResourceSystem;
|
||||
}
|
||||
|
||||
class btSequentialImpulseConstraintSolver;
|
||||
|
@ -45,7 +45,7 @@ namespace MWPhysics
|
|||
class PhysicsSystem
|
||||
{
|
||||
public:
|
||||
PhysicsSystem (const VFS::Manager* vfs, osg::ref_ptr<osg::Group> parentNode);
|
||||
PhysicsSystem (Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode);
|
||||
~PhysicsSystem ();
|
||||
|
||||
void enableWater(float height);
|
||||
|
@ -61,8 +61,7 @@ namespace MWPhysics
|
|||
void updateRotation (const MWWorld::Ptr& ptr);
|
||||
void updatePosition (const MWWorld::Ptr& ptr);
|
||||
|
||||
// TODO
|
||||
//void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated);
|
||||
void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated);
|
||||
|
||||
void addActor (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <components/compiler/locals.hpp>
|
||||
#include <components/esm/cellid.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
|
||||
|
@ -158,7 +157,7 @@ namespace MWWorld
|
|||
mStartCell (startCell), mStartupScript(startupScript),
|
||||
mScriptsEnabled(true)
|
||||
{
|
||||
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem->getVFS(), rootNode);
|
||||
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
|
||||
//mPhysEngine = mPhysics->getEngine();
|
||||
#if 0
|
||||
mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine));
|
||||
|
|
|
@ -46,6 +46,11 @@ BulletNifLoader::~BulletNifLoader()
|
|||
{
|
||||
}
|
||||
|
||||
void BulletNifLoader::setAnimatedNodes(const std::set<std::string> &animatedNodes)
|
||||
{
|
||||
mAnimatedNodes = animatedNodes;
|
||||
}
|
||||
|
||||
osg::ref_ptr<BulletShape> BulletNifLoader::load(const Nif::NIFFilePtr nif)
|
||||
{
|
||||
mShape = new BulletShape;
|
||||
|
@ -84,20 +89,6 @@ osg::ref_ptr<BulletShape> BulletNifLoader::load(const Nif::NIFFilePtr nif)
|
|||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
// Have to load controlled nodes from the .kf
|
||||
mControlledNodes.clear();
|
||||
std::string kfname = mResourceName.substr(0, mResourceName.length()-7);
|
||||
Misc::StringUtils::toLower(kfname);
|
||||
if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0)
|
||||
kfname.replace(kfname.size()-4, 4, ".kf");
|
||||
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(kfname))
|
||||
{
|
||||
Nif::NIFFilePtr kf;// (Nif::Cache::getInstance().load(kfname));
|
||||
//extractControlledNodes(kf, mControlledNodes);
|
||||
}
|
||||
*/
|
||||
|
||||
bool autogenerated = hasAutoGeneratedCollision(node);
|
||||
handleNode(node, 0, autogenerated, false, autogenerated);
|
||||
|
||||
|
@ -181,7 +172,7 @@ void BulletNifLoader::handleNode(const Nif::Node *node, int flags,
|
|||
&& (node->controller->flags & Nif::NiNode::ControllerFlag_Active))
|
||||
isAnimated = true;
|
||||
|
||||
if (mControlledNodes.find(node->name) != mControlledNodes.end())
|
||||
if (mAnimatedNodes.find(node->name) != mAnimatedNodes.end())
|
||||
isAnimated = true;
|
||||
|
||||
isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode);
|
||||
|
@ -238,7 +229,7 @@ void BulletNifLoader::handleNode(const Nif::Node *node, int flags,
|
|||
for(size_t i = 0;i < list.length();i++)
|
||||
{
|
||||
if(!list[i].empty())
|
||||
handleNode(list[i].getPtr(), flags, isCollisionNode, isAnimated);
|
||||
handleNode(list[i].getPtr(), flags, isCollisionNode, isAnimated, autogenerated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +258,6 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags,
|
|||
if (!shape->skin.empty())
|
||||
isAnimated = false;
|
||||
|
||||
/*
|
||||
if (isAnimated)
|
||||
{
|
||||
if (!mCompoundShape)
|
||||
|
@ -311,7 +301,6 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags,
|
|||
mCompoundShape->addChildShape(trans, childShape);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
if (!mStaticMesh)
|
||||
mStaticMesh = new btTriangleMesh(false);
|
||||
|
@ -414,6 +403,8 @@ BulletShapeInstance::BulletShapeInstance(osg::ref_ptr<BulletShape> source)
|
|||
mCollisionBoxHalfExtents = source->mCollisionBoxHalfExtents;
|
||||
mCollisionBoxTranslate = source->mCollisionBoxTranslate;
|
||||
|
||||
mAnimatedShapes = source->mAnimatedShapes;
|
||||
|
||||
if (source->mCollisionShape)
|
||||
mCollisionShape = duplicateCollisionShape(source->mCollisionShape);
|
||||
}
|
||||
|
|
|
@ -107,6 +107,8 @@ public:
|
|||
abort();
|
||||
}
|
||||
|
||||
void setAnimatedNodes(const std::set<std::string>& animatedNodes);
|
||||
|
||||
osg::ref_ptr<BulletShape> load(const Nif::NIFFilePtr file);
|
||||
|
||||
private:
|
||||
|
@ -122,7 +124,7 @@ private:
|
|||
|
||||
btTriangleMesh* mStaticMesh;
|
||||
|
||||
std::set<std::string> mControlledNodes;
|
||||
std::set<std::string> mAnimatedNodes;
|
||||
|
||||
osg::ref_ptr<BulletShape> mShape;
|
||||
};
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
|
||||
namespace NifBullet
|
||||
{
|
||||
|
||||
BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs)
|
||||
BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs, Resource::SceneManager* sceneManager)
|
||||
: mVFS(vfs)
|
||||
, mSceneManager(sceneManager)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -31,7 +34,20 @@ osg::ref_ptr<BulletShapeInstance> BulletShapeManager::createInstance(const std::
|
|||
|
||||
// TODO: add support for non-NIF formats
|
||||
|
||||
std::string kfname = normalized;
|
||||
if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0)
|
||||
kfname.replace(kfname.size()-4, 4, ".kf");
|
||||
std::set<std::string> animatedNodes;
|
||||
if (mVFS->exists(kfname))
|
||||
{
|
||||
osg::ref_ptr<const NifOsg::KeyframeHolder> keyframes = mSceneManager->getKeyframes(normalized);
|
||||
for (NifOsg::KeyframeHolder::KeyframeControllerMap::const_iterator it = keyframes->mKeyframeControllers.begin();
|
||||
it != keyframes->mKeyframeControllers.end(); ++it)
|
||||
animatedNodes.insert(it->first);
|
||||
}
|
||||
|
||||
BulletNifLoader loader;
|
||||
loader.setAnimatedNodes(animatedNodes);
|
||||
// might be worth sharing NIFFiles with SceneManager in some way
|
||||
shape = loader.load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized)));
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ namespace VFS
|
|||
class Manager;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
class SceneManager;
|
||||
}
|
||||
|
||||
namespace NifBullet
|
||||
{
|
||||
|
||||
|
@ -20,13 +25,15 @@ namespace NifBullet
|
|||
class BulletShapeManager
|
||||
{
|
||||
public:
|
||||
BulletShapeManager(const VFS::Manager* vfs);
|
||||
BulletShapeManager(const VFS::Manager* vfs, Resource::SceneManager* sceneManager);
|
||||
~BulletShapeManager();
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> createInstance(const std::string& name);
|
||||
|
||||
private:
|
||||
const VFS::Manager* mVFS;
|
||||
// need to load keyframes to know what nodes are going to be animated
|
||||
Resource::SceneManager* mSceneManager;
|
||||
|
||||
typedef std::map<std::string, osg::ref_ptr<BulletShape> > Index;
|
||||
Index mIndex;
|
||||
|
|
|
@ -18,7 +18,8 @@ namespace SceneUtil
|
|||
{
|
||||
setCopyFlags(osg::CopyOp::DEEP_COPY_NODES
|
||||
// Controller might need different inputs per scene instance
|
||||
| osg::CopyOp::DEEP_COPY_CALLBACKS);
|
||||
| osg::CopyOp::DEEP_COPY_CALLBACKS
|
||||
| osg::CopyOp::DEEP_COPY_USERDATA);
|
||||
}
|
||||
|
||||
osg::StateSet* CopyOp::operator ()(const osg::StateSet* stateset) const
|
||||
|
|
Loading…
Reference in a new issue