diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 2c561eb85..851a5ae36 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -35,7 +35,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Apparatus::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 654cb87fd..fdf211c28 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -38,7 +38,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Armor::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 6c3b7b86c..4e29fa684 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -33,7 +33,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Book::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 892ac091c..dfced6daa 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -36,7 +36,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Clothing::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index bbba45df5..14cf6ff6f 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -46,7 +46,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Ingredient::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 200f6e2d4..746665772 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -50,7 +50,7 @@ namespace MWClass const std::string &model = ref->mBase->mModel; if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,ref->mBase->mData.mFlags & ESM::Light::Carry); if (!ref->mBase->mSound.empty()) MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0, MWBase::SoundManager::Play_Loop); diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 7e909437c..665644736 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -36,7 +36,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Lockpick::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index d43a44359..07e41bcfa 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -39,7 +39,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Miscellaneous::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 0ac78a2e4..37461ed90 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -38,7 +38,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Potion::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index a28be17e7..5b1b55bd3 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -36,7 +36,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Probe::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 39a7f65e0..d6afe9319 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -34,7 +34,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Repair::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index d8c11558c..475c08ccb 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -36,7 +36,7 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) - physics.addObject(ptr); + physics.addObject(ptr,true); } std::string Weapon::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 7edd20293..28f331706 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -364,14 +364,15 @@ namespace MWWorld mEngine->removeHeightField(x, y); } - void PhysicsSystem::addObject (const Ptr& ptr) + void PhysicsSystem::addObject (const Ptr& ptr, bool placeable) { std::string mesh = MWWorld::Class::get(ptr).getModel(ptr); Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); handleToMesh[node->getName()] = mesh; - OEngine::Physic::RigidBody* body = mEngine->createAndAdjustRigidBody(mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation()); - OEngine::Physic::RigidBody* raycastingBody = mEngine->createAndAdjustRigidBody - (mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, true); + OEngine::Physic::RigidBody* body = mEngine->createAndAdjustRigidBody( + mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, false, placeable); + OEngine::Physic::RigidBody* raycastingBody = mEngine->createAndAdjustRigidBody( + mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, true, placeable); mEngine->addRigidBody(body, true, raycastingBody); } @@ -440,8 +441,13 @@ namespace MWWorld const std::string &handle = node->getName(); if(handleToMesh.find(handle) != handleToMesh.end()) { + bool placeable = false; + if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle,true)) + placeable = body->mPlaceable; + else if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle,false)) + placeable = body->mPlaceable; removeObject(handle); - addObject(ptr); + addObject(ptr, placeable); } if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 60c8246ae..2e48be407 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -29,7 +29,7 @@ namespace MWWorld PhysicsSystem (OEngine::Render::OgreRenderer &_rend); ~PhysicsSystem (); - void addObject (const MWWorld::Ptr& ptr); + void addObject (const MWWorld::Ptr& ptr, bool placeable=false); void addActor (const MWWorld::Ptr& ptr); diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index af1243346..04ac3d141 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -109,17 +109,17 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) return; } - bool hasCollisionNode = hasRootCollisionNode(node); + cShape->mHasCollisionNode = hasRootCollisionNode(node); //do a first pass - handleNode(mesh1, node,0,hasCollisionNode,false,false); + handleNode(mesh1, node,0,false,false); if(mBoundingBox != NULL) { cShape->mCollisionShape = mBoundingBox; delete mesh1; } - else if (mHasShape && !cShape->mIgnore && cShape->mCollide) + else if (mHasShape && cShape->mCollide) { cShape->mCollisionShape = new TriangleMeshShape(mesh1,true); } @@ -136,14 +136,14 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) btTriangleMesh* mesh2 = new btTriangleMesh(); - handleNode(mesh2, node,0,hasCollisionNode,true,true); + handleNode(mesh2, node,0,true,true); if(mBoundingBox != NULL) { cShape->mRaycastingShape = mBoundingBox; delete mesh2; } - else if (mHasShape && !cShape->mIgnore) + else if (mHasShape) { cShape->mRaycastingShape = new TriangleMeshShape(mesh2,true); } @@ -174,7 +174,7 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node) } void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node *node, int flags, - bool hasCollisionNode, bool isCollisionNode, + bool isCollisionNode, bool raycasting) { // Accumulate the flags from all the child nodes. This works for all @@ -223,7 +223,7 @@ void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node * } } - if (isCollisionNode || (!hasCollisionNode && !raycasting)) + if (isCollisionNode || (!cShape->mHasCollisionNode && !raycasting)) { if(node->hasBounds) { @@ -246,7 +246,7 @@ void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node * for(size_t i = 0;i < list.length();i++) { if(!list[i].empty()) - handleNode(mesh, list[i].getPtr(), flags, hasCollisionNode, isCollisionNode, raycasting); + handleNode(mesh, list[i].getPtr(), flags, isCollisionNode, raycasting); } } } diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index 9cb5a3e86..c231b75b6 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -82,7 +82,7 @@ private: /** *Parse a node. */ - void handleNode(btTriangleMesh* mesh, Nif::Node const *node, int flags, bool hasCollisionNode, bool isCollisionNode, bool raycasting); + void handleNode(btTriangleMesh* mesh, Nif::Node const *node, int flags, bool isCollisionNode, bool raycasting); /** *Helper function diff --git a/libs/openengine/bullet/BulletShapeLoader.cpp b/libs/openengine/bullet/BulletShapeLoader.cpp index 8744c4e4d..431d2b91b 100644 --- a/libs/openengine/bullet/BulletShapeLoader.cpp +++ b/libs/openengine/bullet/BulletShapeLoader.cpp @@ -19,8 +19,8 @@ Ogre::Resource(creator, name, handle, group, isManual, loader) */ mCollisionShape = NULL; mRaycastingShape = NULL; + mHasCollisionNode = false; mCollide = true; - mIgnore = false; createParamDictionary("BulletShape"); } diff --git a/libs/openengine/bullet/BulletShapeLoader.h b/libs/openengine/bullet/BulletShapeLoader.h index fa03b0276..a6591010a 100644 --- a/libs/openengine/bullet/BulletShapeLoader.h +++ b/libs/openengine/bullet/BulletShapeLoader.h @@ -35,12 +35,14 @@ public: btCollisionShape* mCollisionShape; btCollisionShape* mRaycastingShape; + // Whether or not a NiRootCollisionNode was present in the .nif. If there is none, the collision behaviour + // depends on object type, so we need to expose this variable. + bool mHasCollisionNode; + Ogre::Vector3 mBoxTranslation; Ogre::Quaternion mBoxRotation; //this flag indicate if the shape is used for collision or if it's for raycasting only. bool mCollide; - - bool mIgnore; }; /** diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index c4947af1e..6e6490a41 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -144,6 +144,7 @@ namespace Physic RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name) : btRigidBody(CI) , mName(name) + , mPlaceable(false) { } @@ -368,7 +369,7 @@ namespace Physic RigidBody* PhysicEngine::createAndAdjustRigidBody(const std::string &mesh, const std::string &name, float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, - Ogre::Vector3* scaledBoxTranslation, Ogre::Quaternion* boxRotation, bool raycasting) + Ogre::Vector3* scaledBoxTranslation, Ogre::Quaternion* boxRotation, bool raycasting, bool placeable) { std::string sid = (boost::format("%07.3f") % scale).str(); std::string outputstring = mesh + sid; @@ -378,6 +379,9 @@ namespace Physic BulletShapeManager::getSingletonPtr()->load(outputstring,"General"); BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General"); + if (placeable && !raycasting && shape->mCollisionShape && !shape->mHasCollisionNode) + return NULL; + if (!shape->mCollisionShape && !raycasting) return NULL; if (!shape->mRaycastingShape && raycasting) @@ -395,6 +399,7 @@ namespace Physic btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo (0,newMotionState, raycasting ? shape->mRaycastingShape : shape->mCollisionShape); RigidBody* body = new RigidBody(CI,name); + body->mPlaceable = placeable; if(scaledBoxTranslation != 0) *scaledBoxTranslation = shape->mBoxTranslation * scale; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 367db261f..6ce4edba3 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -164,6 +164,7 @@ namespace Physic RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); virtual ~RigidBody(); std::string mName; + bool mPlaceable; }; struct HeightField @@ -197,7 +198,7 @@ namespace Physic */ RigidBody* createAndAdjustRigidBody(const std::string &mesh, const std::string &name, float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, - Ogre::Vector3* scaledBoxTranslation = 0, Ogre::Quaternion* boxRotation = 0, bool raycasting=false); + Ogre::Vector3* scaledBoxTranslation = 0, Ogre::Quaternion* boxRotation = 0, bool raycasting=false, bool placeable=false); /** * Adjusts a rigid body to the right position and rotation