mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 22:15:37 +00:00
Physics: Create actor shapes outside of BulletNifLoader
This will allow to create a specialised shape instead, such as a capsule, which tends to work better for character controllers.
This commit is contained in:
parent
98329a94b4
commit
e002acdeae
8 changed files with 183 additions and 150 deletions
|
@ -175,7 +175,7 @@ namespace MWWorld
|
||||||
|
|
||||||
const int maxHeight = 200.f;
|
const int maxHeight = 200.f;
|
||||||
OEngine::Physic::ActorTracer tracer;
|
OEngine::Physic::ActorTracer tracer;
|
||||||
tracer.findGround(physicActor->getCollisionBody(), position, position-Ogre::Vector3(0,0,maxHeight), engine);
|
tracer.findGround(physicActor, position, position-Ogre::Vector3(0,0,maxHeight), engine);
|
||||||
if(tracer.mFraction >= 1.0f)
|
if(tracer.mFraction >= 1.0f)
|
||||||
{
|
{
|
||||||
physicActor->setOnGround(false);
|
physicActor->setOnGround(false);
|
||||||
|
@ -607,9 +607,10 @@ namespace MWWorld
|
||||||
Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
|
Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
|
||||||
const std::string &handle = node->getName();
|
const std::string &handle = node->getName();
|
||||||
const Ogre::Quaternion &rotation = node->getOrientation();
|
const Ogre::Quaternion &rotation = node->getOrientation();
|
||||||
|
|
||||||
|
// TODO: map to MWWorld::Ptr for faster access
|
||||||
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
|
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
|
||||||
{
|
{
|
||||||
//Needs to be changed
|
|
||||||
act->setRotation(rotation);
|
act->setRotation(rotation);
|
||||||
}
|
}
|
||||||
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle))
|
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle))
|
||||||
|
@ -740,8 +741,9 @@ namespace MWWorld
|
||||||
btCollisionObject object;
|
btCollisionObject object;
|
||||||
object.setCollisionShape(&planeShape);
|
object.setCollisionShape(&planeShape);
|
||||||
|
|
||||||
|
// TODO: this seems to have a slight performance impact
|
||||||
if (waterCollision)
|
if (waterCollision)
|
||||||
mEngine->dynamicsWorld->addCollisionObject(&object);
|
mEngine->mDynamicsWorld->addCollisionObject(&object);
|
||||||
|
|
||||||
// 100 points of slowfall reduce gravity by 90% (this is just a guess)
|
// 100 points of slowfall reduce gravity by 90% (this is just a guess)
|
||||||
float slowFall = 1-std::min(std::max(0.f, (effects.get(ESM::MagicEffect::SlowFall).mMagnitude / 100.f) * 0.9f), 0.9f);
|
float slowFall = 1-std::min(std::max(0.f, (effects.get(ESM::MagicEffect::SlowFall).mMagnitude / 100.f) * 0.9f), 0.9f);
|
||||||
|
@ -751,7 +753,7 @@ namespace MWWorld
|
||||||
waterlevel, slowFall, mEngine);
|
waterlevel, slowFall, mEngine);
|
||||||
|
|
||||||
if (waterCollision)
|
if (waterCollision)
|
||||||
mEngine->dynamicsWorld->removeCollisionObject(&object);
|
mEngine->mDynamicsWorld->removeCollisionObject(&object);
|
||||||
|
|
||||||
float heightDiff = newpos.z - oldHeight;
|
float heightDiff = newpos.z - oldHeight;
|
||||||
|
|
||||||
|
|
|
@ -1847,7 +1847,7 @@ namespace MWWorld
|
||||||
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos);
|
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos);
|
||||||
OEngine::Physic::ActorTracer tracer;
|
OEngine::Physic::ActorTracer tracer;
|
||||||
// a small distance above collision object is considered "on ground"
|
// a small distance above collision object is considered "on ground"
|
||||||
tracer.findGround(physactor->getCollisionBody(),
|
tracer.findGround(physactor,
|
||||||
pos,
|
pos,
|
||||||
pos - Ogre::Vector3(0, 0, 1.5f), // trace a small amount down
|
pos - Ogre::Vector3(0, 0, 1.5f), // trace a small amount down
|
||||||
mPhysEngine);
|
mPhysEngine);
|
||||||
|
|
|
@ -304,4 +304,53 @@ void ManualBulletShapeLoader::load(const std::string &name,const std::string &gr
|
||||||
OEngine::Physic::BulletShapeManager::getSingleton().create(name,group,true,this);
|
OEngine::Physic::BulletShapeManager::getSingleton().create(name,group,true,this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool findBoundingBox (const Nif::Node* node, Ogre::Vector3& halfExtents, Ogre::Vector3& translation, Ogre::Quaternion& orientation)
|
||||||
|
{
|
||||||
|
if(node->hasBounds)
|
||||||
|
{
|
||||||
|
if (!(node->flags & Nif::NiNode::Flag_Hidden))
|
||||||
|
{
|
||||||
|
translation = node->boundPos;
|
||||||
|
orientation = node->boundRot;
|
||||||
|
halfExtents = node->boundXYZ;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
|
||||||
|
if(ninode)
|
||||||
|
{
|
||||||
|
const Nif::NodeList &list = ninode->children;
|
||||||
|
for(size_t i = 0;i < list.length();i++)
|
||||||
|
{
|
||||||
|
if(!list[i].empty())
|
||||||
|
if (findBoundingBox(list[i].getPtr(), halfExtents, translation, orientation))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getBoundingBox(const std::string& nifFile, Ogre::Vector3& halfExtents, Ogre::Vector3& translation, Ogre::Quaternion& orientation)
|
||||||
|
{
|
||||||
|
Nif::NIFFile::ptr pnif (Nif::NIFFile::create (nifFile));
|
||||||
|
Nif::NIFFile & nif = *pnif.get ();
|
||||||
|
|
||||||
|
if (nif.numRoots() < 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nif::Record *r = nif.getRoot(0);
|
||||||
|
assert(r != NULL);
|
||||||
|
|
||||||
|
Nif::Node *node = dynamic_cast<Nif::Node*>(r);
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return findBoundingBox(node, halfExtents, translation, orientation);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace NifBullet
|
} // namespace NifBullet
|
||||||
|
|
|
@ -108,6 +108,11 @@ private:
|
||||||
bool mHasShape;
|
bool mHasShape;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool getBoundingBox(const std::string& nifFile, Ogre::Vector3& halfExtents, Ogre::Vector3& translation, Ogre::Quaternion& orientation);
|
||||||
|
|
||||||
|
bool findBoundingBox(const Nif::Node* node, Ogre::Vector3& halfExtents, Ogre::Vector3& translation, Ogre::Quaternion& orientation);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,115 +16,93 @@ namespace Physic
|
||||||
{
|
{
|
||||||
|
|
||||||
PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale)
|
PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale)
|
||||||
: mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0)
|
: mName(name), mEngine(engine), mMesh(mesh)
|
||||||
, mBody(0), mRaycastingBody(0), mOnGround(false), mCollisionMode(true), mBoxRotation(0,0,0,0)
|
, mBody(0), mOnGround(false), mInternalCollisionMode(true)
|
||||||
, mCollisionBody(true)
|
, mExternalCollisionMode(true)
|
||||||
, mForce(0.0f)
|
, mForce(0.0f)
|
||||||
|
, mScale(scale)
|
||||||
{
|
{
|
||||||
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation);
|
if (!NifBullet::getBoundingBox(mMesh, mHalfExtents, mMeshTranslation, mMeshOrientation))
|
||||||
mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation, true);
|
{
|
||||||
Ogre::Quaternion inverse = mBoxRotation.Inverse();
|
mHalfExtents = Ogre::Vector3(0.f);
|
||||||
mBoxRotationInverse = Ogre::Quaternion(inverse.w, inverse.x, inverse.y,inverse.z);
|
mMeshTranslation = Ogre::Vector3(0.f);
|
||||||
mEngine->addRigidBody(mBody, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map
|
mMeshOrientation = Ogre::Quaternion::IDENTITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
mShape.reset(new btBoxShape(BtOgre::Convert::toBullet(mHalfExtents)));
|
||||||
|
mShape->setLocalScaling(btVector3(scale,scale,scale));
|
||||||
|
|
||||||
|
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo
|
||||||
|
(0,0, mShape.get());
|
||||||
|
mBody = new RigidBody(CI, name);
|
||||||
|
mBody->mPlaceable = false;
|
||||||
|
|
||||||
|
setPosition(position);
|
||||||
|
setRotation(rotation);
|
||||||
|
|
||||||
|
mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor,
|
||||||
|
CollisionType_Actor|CollisionType_World|CollisionType_HeightMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicActor::~PhysicActor()
|
PhysicActor::~PhysicActor()
|
||||||
{
|
{
|
||||||
if(mBody)
|
if(mBody)
|
||||||
{
|
{
|
||||||
mEngine->dynamicsWorld->removeRigidBody(mBody);
|
mEngine->mDynamicsWorld->removeRigidBody(mBody);
|
||||||
delete mBody;
|
delete mBody;
|
||||||
}
|
}
|
||||||
if(mRaycastingBody)
|
|
||||||
{
|
|
||||||
mEngine->dynamicsWorld->removeRigidBody(mRaycastingBody);
|
|
||||||
delete mRaycastingBody;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicActor::enableCollisionMode(bool collision)
|
void PhysicActor::enableCollisionMode(bool collision)
|
||||||
{
|
{
|
||||||
mCollisionMode = collision;
|
mInternalCollisionMode = collision;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicActor::enableCollisionBody(bool collision)
|
void PhysicActor::enableCollisionBody(bool collision)
|
||||||
{
|
{
|
||||||
assert(mBody);
|
assert(mBody);
|
||||||
if(collision && !mCollisionBody) enableCollisionBody();
|
if(collision && !mExternalCollisionMode) enableCollisionBody();
|
||||||
if(!collision && mCollisionBody) disableCollisionBody();
|
if(!collision && mExternalCollisionMode) disableCollisionBody();
|
||||||
mCollisionBody = collision;
|
mExternalCollisionMode = collision;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicActor::setPosition(const Ogre::Vector3 &pos)
|
const Ogre::Vector3& PhysicActor::getPosition() const
|
||||||
|
{
|
||||||
|
return mPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicActor::setPosition(const Ogre::Vector3 &position)
|
||||||
{
|
{
|
||||||
assert(mBody);
|
assert(mBody);
|
||||||
if(pos != getPosition())
|
|
||||||
{
|
mPosition = position;
|
||||||
mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
|
|
||||||
mEngine->adjustRigidBody(mRaycastingBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
|
btTransform tr = mBody->getWorldTransform();
|
||||||
}
|
Ogre::Quaternion meshrot = mMeshOrientation;
|
||||||
|
Ogre::Vector3 transrot = meshrot * (mMeshTranslation * mScale);
|
||||||
|
Ogre::Vector3 newPosition = transrot + position;
|
||||||
|
|
||||||
|
tr.setOrigin(BtOgre::Convert::toBullet(newPosition));
|
||||||
|
mBody->setWorldTransform(tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicActor::setRotation(const Ogre::Quaternion &quat)
|
void PhysicActor::setRotation (const Ogre::Quaternion& rotation)
|
||||||
{
|
{
|
||||||
assert(mBody);
|
btTransform tr = mBody->getWorldTransform();
|
||||||
if(!quat.equals(getRotation(), Ogre::Radian(0))){
|
tr.setRotation(BtOgre::Convert::toBullet(mMeshOrientation * rotation));
|
||||||
mEngine->adjustRigidBody(mBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation);
|
mBody->setWorldTransform(tr);
|
||||||
mEngine->adjustRigidBody(mRaycastingBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicActor::setScale(float scale)
|
||||||
Ogre::Vector3 PhysicActor::getPosition()
|
|
||||||
{
|
{
|
||||||
assert(mBody);
|
mScale = scale;
|
||||||
btVector3 vec = mBody->getWorldTransform().getOrigin();
|
mShape->setLocalScaling(btVector3(scale,scale,scale));
|
||||||
Ogre::Quaternion rotation = Ogre::Quaternion(mBody->getWorldTransform().getRotation().getW(), mBody->getWorldTransform().getRotation().getX(),
|
setPosition(mPosition);
|
||||||
mBody->getWorldTransform().getRotation().getY(), mBody->getWorldTransform().getRotation().getZ());
|
|
||||||
Ogre::Vector3 transrot = rotation * mBoxScaledTranslation;
|
|
||||||
Ogre::Vector3 visualPosition = Ogre::Vector3(vec.getX(), vec.getY(), vec.getZ()) - transrot;
|
|
||||||
return visualPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ogre::Quaternion PhysicActor::getRotation()
|
|
||||||
{
|
|
||||||
assert(mBody);
|
|
||||||
btQuaternion quat = mBody->getWorldTransform().getRotation();
|
|
||||||
return Ogre::Quaternion(quat.getW(), quat.getX(), quat.getY(), quat.getZ()) * mBoxRotationInverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhysicActor::setScale(float scale){
|
|
||||||
//We only need to change the scaled box translation, box rotations remain the same.
|
|
||||||
assert(mBody);
|
|
||||||
mBoxScaledTranslation = mBoxScaledTranslation / mBody->getCollisionShape()->getLocalScaling().getX();
|
|
||||||
mBoxScaledTranslation *= scale;
|
|
||||||
Ogre::Vector3 pos = getPosition();
|
|
||||||
Ogre::Quaternion rot = getRotation();
|
|
||||||
if(mBody){
|
|
||||||
mEngine->dynamicsWorld->removeRigidBody(mBody);
|
|
||||||
mEngine->dynamicsWorld->removeRigidBody(mRaycastingBody);
|
|
||||||
delete mBody;
|
|
||||||
delete mRaycastingBody;
|
|
||||||
}
|
|
||||||
//Create the newly scaled rigid body
|
|
||||||
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, pos, rot);
|
|
||||||
mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, pos, rot, 0, 0, true);
|
|
||||||
mEngine->addRigidBody(mCollisionBody ? mBody : 0, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::Vector3 PhysicActor::getHalfExtents() const
|
Ogre::Vector3 PhysicActor::getHalfExtents() const
|
||||||
{
|
{
|
||||||
if(mBody)
|
return mHalfExtents;
|
||||||
{
|
|
||||||
btBoxShape *box = static_cast<btBoxShape*>(mBody->getCollisionShape());
|
|
||||||
if(box != NULL)
|
|
||||||
{
|
|
||||||
btVector3 size = box->getHalfExtentsWithMargin();
|
|
||||||
return Ogre::Vector3(size.getX(), size.getY(), size.getZ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ogre::Vector3(0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicActor::setInertialForce(const Ogre::Vector3 &force)
|
void PhysicActor::setInertialForce(const Ogre::Vector3 &force)
|
||||||
|
@ -139,12 +117,16 @@ namespace Physic
|
||||||
|
|
||||||
void PhysicActor::disableCollisionBody()
|
void PhysicActor::disableCollisionBody()
|
||||||
{
|
{
|
||||||
mEngine->dynamicsWorld->removeRigidBody(mBody);
|
mEngine->mDynamicsWorld->removeRigidBody(mBody);
|
||||||
|
mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor,
|
||||||
|
CollisionType_Raycasting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicActor::enableCollisionBody()
|
void PhysicActor::enableCollisionBody()
|
||||||
{
|
{
|
||||||
mEngine->dynamicsWorld->addRigidBody(mBody,CollisionType_Actor,CollisionType_World|CollisionType_HeightMap);
|
mEngine->mDynamicsWorld->removeRigidBody(mBody);
|
||||||
|
mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor,
|
||||||
|
CollisionType_Actor|CollisionType_World|CollisionType_HeightMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -189,8 +171,8 @@ namespace Physic
|
||||||
broadphase = new btDbvtBroadphase();
|
broadphase = new btDbvtBroadphase();
|
||||||
|
|
||||||
// The world.
|
// The world.
|
||||||
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
|
mDynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
|
||||||
dynamicsWorld->setGravity(btVector3(0,0,-10));
|
mDynamicsWorld->setGravity(btVector3(0,0,-10));
|
||||||
|
|
||||||
if(BulletShapeManager::getSingletonPtr() == NULL)
|
if(BulletShapeManager::getSingletonPtr() == NULL)
|
||||||
{
|
{
|
||||||
|
@ -208,10 +190,10 @@ namespace Physic
|
||||||
if(!isDebugCreated)
|
if(!isDebugCreated)
|
||||||
{
|
{
|
||||||
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
|
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
|
||||||
mDebugDrawer = new BtOgre::DebugDrawer(node, dynamicsWorld);
|
mDebugDrawer = new BtOgre::DebugDrawer(node, mDynamicsWorld);
|
||||||
dynamicsWorld->setDebugDrawer(mDebugDrawer);
|
mDynamicsWorld->setDebugDrawer(mDebugDrawer);
|
||||||
isDebugCreated = true;
|
isDebugCreated = true;
|
||||||
dynamicsWorld->debugDrawWorld();
|
mDynamicsWorld->debugDrawWorld();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +223,7 @@ namespace Physic
|
||||||
HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin();
|
HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin();
|
||||||
for (; hf_it != mHeightFieldMap.end(); ++hf_it)
|
for (; hf_it != mHeightFieldMap.end(); ++hf_it)
|
||||||
{
|
{
|
||||||
dynamicsWorld->removeRigidBody(hf_it->second.mBody);
|
mDynamicsWorld->removeRigidBody(hf_it->second.mBody);
|
||||||
delete hf_it->second.mShape;
|
delete hf_it->second.mShape;
|
||||||
delete hf_it->second.mBody;
|
delete hf_it->second.mBody;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +233,7 @@ namespace Physic
|
||||||
{
|
{
|
||||||
if (rb_it->second != NULL)
|
if (rb_it->second != NULL)
|
||||||
{
|
{
|
||||||
dynamicsWorld->removeRigidBody(rb_it->second);
|
mDynamicsWorld->removeRigidBody(rb_it->second);
|
||||||
|
|
||||||
delete rb_it->second;
|
delete rb_it->second;
|
||||||
rb_it->second = NULL;
|
rb_it->second = NULL;
|
||||||
|
@ -262,7 +244,7 @@ namespace Physic
|
||||||
{
|
{
|
||||||
if (rb_it->second != NULL)
|
if (rb_it->second != NULL)
|
||||||
{
|
{
|
||||||
dynamicsWorld->removeRigidBody(rb_it->second);
|
mDynamicsWorld->removeRigidBody(rb_it->second);
|
||||||
|
|
||||||
delete rb_it->second;
|
delete rb_it->second;
|
||||||
rb_it->second = NULL;
|
rb_it->second = NULL;
|
||||||
|
@ -281,7 +263,7 @@ namespace Physic
|
||||||
|
|
||||||
delete mDebugDrawer;
|
delete mDebugDrawer;
|
||||||
|
|
||||||
delete dynamicsWorld;
|
delete mDynamicsWorld;
|
||||||
delete solver;
|
delete solver;
|
||||||
delete collisionConfiguration;
|
delete collisionConfiguration;
|
||||||
delete dispatcher;
|
delete dispatcher;
|
||||||
|
@ -331,7 +313,7 @@ namespace Physic
|
||||||
|
|
||||||
mHeightFieldMap [name] = hf;
|
mHeightFieldMap [name] = hf;
|
||||||
|
|
||||||
dynamicsWorld->addRigidBody(body,CollisionType_HeightMap|CollisionType_Raycasting,
|
mDynamicsWorld->addRigidBody(body,CollisionType_HeightMap,
|
||||||
CollisionType_World|CollisionType_Actor|CollisionType_Raycasting);
|
CollisionType_World|CollisionType_Actor|CollisionType_Raycasting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +325,7 @@ namespace Physic
|
||||||
|
|
||||||
HeightField hf = mHeightFieldMap [name];
|
HeightField hf = mHeightFieldMap [name];
|
||||||
|
|
||||||
dynamicsWorld->removeRigidBody(hf.mBody);
|
mDynamicsWorld->removeRigidBody(hf.mBody);
|
||||||
delete hf.mShape;
|
delete hf.mShape;
|
||||||
delete hf.mBody;
|
delete hf.mBody;
|
||||||
|
|
||||||
|
@ -367,7 +349,6 @@ namespace Physic
|
||||||
{
|
{
|
||||||
std::string sid = (boost::format("%07.3f") % scale).str();
|
std::string sid = (boost::format("%07.3f") % scale).str();
|
||||||
std::string outputstring = mesh + sid;
|
std::string outputstring = mesh + sid;
|
||||||
//std::cout << "The string" << outputstring << "\n";
|
|
||||||
|
|
||||||
//get the shape from the .nif
|
//get the shape from the .nif
|
||||||
mShapeLoader->load(outputstring,"General");
|
mShapeLoader->load(outputstring,"General");
|
||||||
|
@ -419,7 +400,7 @@ namespace Physic
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody,bool actor)
|
void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody)
|
||||||
{
|
{
|
||||||
if(!body && !raycastingBody)
|
if(!body && !raycastingBody)
|
||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
|
@ -427,12 +408,11 @@ namespace Physic
|
||||||
const std::string& name = (body ? body->mName : raycastingBody->mName);
|
const std::string& name = (body ? body->mName : raycastingBody->mName);
|
||||||
|
|
||||||
if (body){
|
if (body){
|
||||||
if(actor) dynamicsWorld->addRigidBody(body,CollisionType_Actor,CollisionType_World|CollisionType_HeightMap);
|
mDynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_Actor|CollisionType_HeightMap);
|
||||||
else dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_Actor|CollisionType_HeightMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (raycastingBody)
|
if (raycastingBody)
|
||||||
dynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_World);
|
mDynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting);
|
||||||
|
|
||||||
if(addToMap){
|
if(addToMap){
|
||||||
removeRigidBody(name);
|
removeRigidBody(name);
|
||||||
|
@ -453,7 +433,7 @@ namespace Physic
|
||||||
RigidBody* body = it->second;
|
RigidBody* body = it->second;
|
||||||
if(body != NULL)
|
if(body != NULL)
|
||||||
{
|
{
|
||||||
dynamicsWorld->removeRigidBody(body);
|
mDynamicsWorld->removeRigidBody(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
it = mRaycastingObjectMap.find(name);
|
it = mRaycastingObjectMap.find(name);
|
||||||
|
@ -462,7 +442,7 @@ namespace Physic
|
||||||
RigidBody* body = it->second;
|
RigidBody* body = it->second;
|
||||||
if(body != NULL)
|
if(body != NULL)
|
||||||
{
|
{
|
||||||
dynamicsWorld->removeRigidBody(body);
|
mDynamicsWorld->removeRigidBody(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -605,7 +585,7 @@ namespace Physic
|
||||||
if (!body) // fall back to raycasting body if there is no collision body
|
if (!body) // fall back to raycasting body if there is no collision body
|
||||||
body = getRigidBody(name, true);
|
body = getRigidBody(name, true);
|
||||||
ContactTestResultCallback callback;
|
ContactTestResultCallback callback;
|
||||||
dynamicsWorld->contactTest(body, callback);
|
mDynamicsWorld->contactTest(body, callback);
|
||||||
return callback.mResult;
|
return callback.mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,8 +595,9 @@ namespace Physic
|
||||||
btCollisionObject *object)
|
btCollisionObject *object)
|
||||||
{
|
{
|
||||||
DeepestNotMeContactTestResultCallback callback(filter, origin);
|
DeepestNotMeContactTestResultCallback callback(filter, origin);
|
||||||
|
callback.m_collisionFilterGroup = 0xff;
|
||||||
callback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor;
|
callback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor;
|
||||||
dynamicsWorld->contactTest(object, callback);
|
mDynamicsWorld->contactTest(object, callback);
|
||||||
return std::make_pair(callback.mObject, callback.mContactPoint);
|
return std::make_pair(callback.mObject, callback.mContactPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,7 +605,7 @@ namespace Physic
|
||||||
void PhysicEngine::stepSimulation(double deltaT)
|
void PhysicEngine::stepSimulation(double deltaT)
|
||||||
{
|
{
|
||||||
// This seems to be needed for character controller objects
|
// This seems to be needed for character controller objects
|
||||||
dynamicsWorld->stepSimulation(deltaT,10, 1/60.0);
|
mDynamicsWorld->stepSimulation(deltaT,10, 1/60.0);
|
||||||
if(isDebugCreated)
|
if(isDebugCreated)
|
||||||
{
|
{
|
||||||
mDebugDrawer->step();
|
mDebugDrawer->step();
|
||||||
|
@ -684,14 +665,15 @@ namespace Physic
|
||||||
float d = -1;
|
float d = -1;
|
||||||
|
|
||||||
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
||||||
|
resultCallback1.m_collisionFilterGroup = 0xff;
|
||||||
if(raycastingObjectOnly)
|
if(raycastingObjectOnly)
|
||||||
resultCallback1.m_collisionFilterMask = CollisionType_Raycasting;
|
resultCallback1.m_collisionFilterMask = CollisionType_Raycasting|CollisionType_Actor;
|
||||||
else
|
else
|
||||||
resultCallback1.m_collisionFilterMask = CollisionType_World;
|
resultCallback1.m_collisionFilterMask = CollisionType_World;
|
||||||
|
|
||||||
if(!ignoreHeightMap)
|
if(!ignoreHeightMap)
|
||||||
resultCallback1.m_collisionFilterMask = resultCallback1.m_collisionFilterMask | CollisionType_HeightMap;
|
resultCallback1.m_collisionFilterMask = resultCallback1.m_collisionFilterMask | CollisionType_HeightMap;
|
||||||
dynamicsWorld->rayTest(from, to, resultCallback1);
|
mDynamicsWorld->rayTest(from, to, resultCallback1);
|
||||||
if (resultCallback1.hasHit())
|
if (resultCallback1.hasHit())
|
||||||
{
|
{
|
||||||
name = static_cast<const RigidBody&>(*resultCallback1.m_collisionObject).mName;
|
name = static_cast<const RigidBody&>(*resultCallback1.m_collisionObject).mName;
|
||||||
|
@ -724,6 +706,7 @@ namespace Physic
|
||||||
std::pair<bool, float> PhysicEngine::sphereCast (float radius, btVector3& from, btVector3& to)
|
std::pair<bool, float> PhysicEngine::sphereCast (float radius, btVector3& from, btVector3& to)
|
||||||
{
|
{
|
||||||
OurClosestConvexResultCallback callback(from, to);
|
OurClosestConvexResultCallback callback(from, to);
|
||||||
|
callback.m_collisionFilterGroup = 0xff;
|
||||||
callback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap;
|
callback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap;
|
||||||
|
|
||||||
btSphereShape shape(radius);
|
btSphereShape shape(radius);
|
||||||
|
@ -732,7 +715,7 @@ namespace Physic
|
||||||
btTransform from_ (btrot, from);
|
btTransform from_ (btrot, from);
|
||||||
btTransform to_ (btrot, to);
|
btTransform to_ (btrot, to);
|
||||||
|
|
||||||
dynamicsWorld->convexSweepTest(&shape, from_, to_, callback);
|
mDynamicsWorld->convexSweepTest(&shape, from_, to_, callback);
|
||||||
|
|
||||||
if (callback.hasHit())
|
if (callback.hasHit())
|
||||||
return std::make_pair(true, callback.m_closestHitFraction);
|
return std::make_pair(true, callback.m_closestHitFraction);
|
||||||
|
@ -743,8 +726,9 @@ namespace Physic
|
||||||
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
|
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
|
||||||
{
|
{
|
||||||
MyRayResultCallback resultCallback1;
|
MyRayResultCallback resultCallback1;
|
||||||
resultCallback1.m_collisionFilterMask = CollisionType_Raycasting;
|
resultCallback1.m_collisionFilterGroup = 0xff;
|
||||||
dynamicsWorld->rayTest(from, to, resultCallback1);
|
resultCallback1.m_collisionFilterMask = CollisionType_Raycasting|CollisionType_Actor;
|
||||||
|
mDynamicsWorld->rayTest(from, to, resultCallback1);
|
||||||
std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results;
|
std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results;
|
||||||
|
|
||||||
std::vector< std::pair<float, std::string> > results2;
|
std::vector< std::pair<float, std::string> > results2;
|
||||||
|
|
|
@ -76,6 +76,9 @@ namespace Physic
|
||||||
RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name);
|
RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name);
|
||||||
virtual ~RigidBody();
|
virtual ~RigidBody();
|
||||||
std::string mName;
|
std::string mName;
|
||||||
|
|
||||||
|
// Hack: placeable objects (that can be picked up by the player) have different collision behaviour.
|
||||||
|
// This variable needs to be passed to BulletNifLoader.
|
||||||
bool mPlaceable;
|
bool mPlaceable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,13 +95,6 @@ namespace Physic
|
||||||
|
|
||||||
void setPosition(const Ogre::Vector3 &pos);
|
void setPosition(const Ogre::Vector3 &pos);
|
||||||
|
|
||||||
/**
|
|
||||||
* This adjusts the rotation of a PhysicActor
|
|
||||||
* If we have any problems with this (getting stuck in pmove) we should change it
|
|
||||||
* from setting the visual orientation to setting the orientation of the rigid body directly.
|
|
||||||
*/
|
|
||||||
void setRotation(const Ogre::Quaternion &quat);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry.
|
* Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry.
|
||||||
*/
|
*/
|
||||||
|
@ -111,26 +107,18 @@ namespace Physic
|
||||||
|
|
||||||
bool getCollisionMode() const
|
bool getCollisionMode() const
|
||||||
{
|
{
|
||||||
return mCollisionMode;
|
return mInternalCollisionMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This returns the visual position of the PhysicActor (used to position a scenenode).
|
|
||||||
* Note - this is different from the position of the contained mBody.
|
|
||||||
*/
|
|
||||||
Ogre::Vector3 getPosition();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the visual orientation of the PhysicActor
|
|
||||||
*/
|
|
||||||
Ogre::Quaternion getRotation();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the scale of the PhysicActor
|
* Sets the scale of the PhysicActor
|
||||||
*/
|
*/
|
||||||
void setScale(float scale);
|
void setScale(float scale);
|
||||||
|
|
||||||
|
void setRotation (const Ogre::Quaternion& rotation);
|
||||||
|
|
||||||
|
const Ogre::Vector3& getPosition() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the half extents for this PhysiActor
|
* Returns the half extents for this PhysiActor
|
||||||
*/
|
*/
|
||||||
|
@ -153,7 +141,7 @@ namespace Physic
|
||||||
|
|
||||||
bool getOnGround() const
|
bool getOnGround() const
|
||||||
{
|
{
|
||||||
return mCollisionMode && mOnGround;
|
return mInternalCollisionMode && mOnGround;
|
||||||
}
|
}
|
||||||
|
|
||||||
btCollisionObject *getCollisionBody() const
|
btCollisionObject *getCollisionBody() const
|
||||||
|
@ -165,17 +153,21 @@ namespace Physic
|
||||||
void disableCollisionBody();
|
void disableCollisionBody();
|
||||||
void enableCollisionBody();
|
void enableCollisionBody();
|
||||||
|
|
||||||
OEngine::Physic::RigidBody* mBody;
|
boost::shared_ptr<btCollisionShape> mShape;
|
||||||
OEngine::Physic::RigidBody* mRaycastingBody;
|
|
||||||
|
|
||||||
Ogre::Vector3 mBoxScaledTranslation;
|
OEngine::Physic::RigidBody* mBody;
|
||||||
Ogre::Quaternion mBoxRotation;
|
|
||||||
Ogre::Quaternion mBoxRotationInverse;
|
Ogre::Quaternion mMeshOrientation;
|
||||||
|
Ogre::Vector3 mMeshTranslation;
|
||||||
|
Ogre::Vector3 mHalfExtents;
|
||||||
|
|
||||||
|
float mScale;
|
||||||
|
Ogre::Vector3 mPosition;
|
||||||
|
|
||||||
Ogre::Vector3 mForce;
|
Ogre::Vector3 mForce;
|
||||||
bool mOnGround;
|
bool mOnGround;
|
||||||
bool mCollisionMode;
|
bool mInternalCollisionMode;
|
||||||
bool mCollisionBody;
|
bool mExternalCollisionMode;
|
||||||
|
|
||||||
std::string mMesh;
|
std::string mMesh;
|
||||||
std::string mName;
|
std::string mName;
|
||||||
|
@ -242,7 +234,7 @@ namespace Physic
|
||||||
/**
|
/**
|
||||||
* Add a RigidBody to the simulation
|
* Add a RigidBody to the simulation
|
||||||
*/
|
*/
|
||||||
void addRigidBody(RigidBody* body, bool addToMap = true, RigidBody* raycastingBody = NULL,bool actor = false);
|
void addRigidBody(RigidBody* body, bool addToMap = true, RigidBody* raycastingBody = NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap.
|
* Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap.
|
||||||
|
@ -335,7 +327,7 @@ namespace Physic
|
||||||
btDefaultCollisionConfiguration* collisionConfiguration;
|
btDefaultCollisionConfiguration* collisionConfiguration;
|
||||||
btSequentialImpulseConstraintSolver* solver;
|
btSequentialImpulseConstraintSolver* solver;
|
||||||
btCollisionDispatcher* dispatcher;
|
btCollisionDispatcher* dispatcher;
|
||||||
btDiscreteDynamicsWorld* dynamicsWorld;
|
btDiscreteDynamicsWorld* mDynamicsWorld;
|
||||||
|
|
||||||
//the NIF file loader.
|
//the NIF file loader.
|
||||||
BulletShapeLoader* mShapeLoader;
|
BulletShapeLoader* mShapeLoader;
|
||||||
|
|
|
@ -65,12 +65,13 @@ void ActorTracer::doTrace(btCollisionObject *actor, const Ogre::Vector3 &start,
|
||||||
to.setOrigin(btend);
|
to.setOrigin(btend);
|
||||||
|
|
||||||
ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0));
|
ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0));
|
||||||
|
newTraceCallback.m_collisionFilterGroup = CollisionType_Actor;
|
||||||
newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap |
|
newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap |
|
||||||
CollisionType_Actor;
|
CollisionType_Actor;
|
||||||
|
|
||||||
btCollisionShape *shape = actor->getCollisionShape();
|
btCollisionShape *shape = actor->getCollisionShape();
|
||||||
assert(shape->isConvex());
|
assert(shape->isConvex());
|
||||||
enginePass->dynamicsWorld->convexSweepTest(static_cast<btConvexShape*>(shape),
|
enginePass->mDynamicsWorld->convexSweepTest(static_cast<btConvexShape*>(shape),
|
||||||
from, to, newTraceCallback);
|
from, to, newTraceCallback);
|
||||||
|
|
||||||
// Copy the hit data over to our trace results struct:
|
// Copy the hit data over to our trace results struct:
|
||||||
|
@ -89,27 +90,26 @@ void ActorTracer::doTrace(btCollisionObject *actor, const Ogre::Vector3 &start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorTracer::findGround(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, const PhysicEngine *enginePass)
|
void ActorTracer::findGround(const OEngine::Physic::PhysicActor* actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, const PhysicEngine *enginePass)
|
||||||
{
|
{
|
||||||
const btVector3 btstart(start.x, start.y, start.z+1.0f);
|
const btVector3 btstart(start.x, start.y, start.z+1.0f);
|
||||||
const btVector3 btend(end.x, end.y, end.z+1.0f);
|
const btVector3 btend(end.x, end.y, end.z+1.0f);
|
||||||
|
|
||||||
const btTransform &trans = actor->getWorldTransform();
|
const btTransform &trans = actor->getCollisionBody()->getWorldTransform();
|
||||||
btTransform from(trans.getBasis(), btstart);
|
btTransform from(trans.getBasis(), btstart);
|
||||||
btTransform to(trans.getBasis(), btend);
|
btTransform to(trans.getBasis(), btend);
|
||||||
|
|
||||||
ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0));
|
ClosestNotMeConvexResultCallback newTraceCallback(actor->getCollisionBody(), btstart-btend, btScalar(0.0));
|
||||||
|
newTraceCallback.m_collisionFilterGroup = CollisionType_Actor;
|
||||||
newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap |
|
newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap |
|
||||||
CollisionType_Actor;
|
CollisionType_Actor;
|
||||||
|
|
||||||
const btBoxShape *shape = dynamic_cast<btBoxShape*>(actor->getCollisionShape());
|
btVector3 halfExtents(actor->getHalfExtents().x, actor->getHalfExtents().y, actor->getHalfExtents().z);
|
||||||
assert(shape);
|
|
||||||
|
|
||||||
btVector3 halfExtents = shape->getHalfExtentsWithMargin();
|
|
||||||
halfExtents[2] = 1.0f;
|
halfExtents[2] = 1.0f;
|
||||||
btBoxShape box(halfExtents);
|
btBoxShape base(halfExtents);
|
||||||
|
|
||||||
enginePass->dynamicsWorld->convexSweepTest(&box, from, to, newTraceCallback);
|
enginePass->mDynamicsWorld->convexSweepTest(&base, from, to, newTraceCallback);
|
||||||
if(newTraceCallback.hasHit())
|
if(newTraceCallback.hasHit())
|
||||||
{
|
{
|
||||||
const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld;
|
const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld;
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace OEngine
|
||||||
namespace Physic
|
namespace Physic
|
||||||
{
|
{
|
||||||
class PhysicEngine;
|
class PhysicEngine;
|
||||||
|
class PhysicActor;
|
||||||
|
|
||||||
struct ActorTracer
|
struct ActorTracer
|
||||||
{
|
{
|
||||||
|
@ -22,7 +23,7 @@ namespace Physic
|
||||||
|
|
||||||
void doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end,
|
void doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end,
|
||||||
const PhysicEngine *enginePass);
|
const PhysicEngine *enginePass);
|
||||||
void findGround(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end,
|
void findGround(const OEngine::Physic::PhysicActor* actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end,
|
||||||
const PhysicEngine *enginePass);
|
const PhysicEngine *enginePass);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue