2011-02-22 13:02:50 +00:00
|
|
|
#include "physic.hpp"
|
|
|
|
#include <btBulletDynamicsCommon.h>
|
|
|
|
#include <btBulletCollisionCommon.h>
|
2011-02-26 15:34:43 +00:00
|
|
|
#include <components/nifbullet/bullet_nif_loader.hpp>
|
2011-02-22 13:02:50 +00:00
|
|
|
//#include <apps\openmw\mwworld\world.hpp>
|
|
|
|
#include "CMotionState.h"
|
|
|
|
#include "OgreRoot.h"
|
|
|
|
#include "btKinematicCharacterController.h"
|
|
|
|
#include "BtOgrePG.h"
|
|
|
|
#include "BtOgreGP.h"
|
|
|
|
#include "BtOgreExtras.h"
|
|
|
|
|
|
|
|
#define BIT(x) (1<<(x))
|
|
|
|
|
|
|
|
namespace OEngine {
|
|
|
|
namespace Physic
|
|
|
|
{
|
|
|
|
enum collisiontypes {
|
|
|
|
COL_NOTHING = 0, //<Collide with nothing
|
|
|
|
COL_WORLD = BIT(0), //<Collide with world objects
|
2011-02-26 15:34:43 +00:00
|
|
|
COL_ACTOR_INTERNAL = BIT(1), //<Collide internal capsule
|
2011-02-22 13:02:50 +00:00
|
|
|
COL_ACTOR_EXTERNAL = BIT(2) //<collide with external capsule
|
|
|
|
};
|
|
|
|
|
|
|
|
PhysicActor::PhysicActor(std::string name)
|
|
|
|
{
|
|
|
|
mName = name;
|
|
|
|
|
|
|
|
// The capsule is at the origin
|
|
|
|
btTransform transform;
|
|
|
|
transform.setIdentity();
|
|
|
|
|
|
|
|
// External capsule
|
2011-02-22 19:53:02 +00:00
|
|
|
externalGhostObject = new PairCachingGhostObject(name);
|
2011-02-22 13:02:50 +00:00
|
|
|
externalGhostObject->setWorldTransform( transform );
|
|
|
|
|
2011-03-17 10:00:46 +00:00
|
|
|
btScalar externalCapsuleHeight = 130;
|
2011-03-09 17:23:13 +00:00
|
|
|
btScalar externalCapsuleWidth = 16;
|
2011-02-22 13:02:50 +00:00
|
|
|
|
|
|
|
externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight );
|
2011-03-22 20:28:18 +00:00
|
|
|
externalCollisionShape->setMargin( 0.1 );
|
2011-02-22 13:02:50 +00:00
|
|
|
|
|
|
|
externalGhostObject->setCollisionShape( externalCollisionShape );
|
|
|
|
externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT );
|
|
|
|
|
|
|
|
// Internal capsule
|
2011-02-22 19:53:02 +00:00
|
|
|
internalGhostObject = new PairCachingGhostObject(name);
|
2011-02-22 13:02:50 +00:00
|
|
|
internalGhostObject->setWorldTransform( transform );
|
|
|
|
//internalGhostObject->getBroadphaseHandle()->s
|
2011-03-17 10:00:46 +00:00
|
|
|
btScalar internalCapsuleHeight = 120;
|
2011-03-09 17:23:13 +00:00
|
|
|
btScalar internalCapsuleWidth = 15;
|
2011-02-22 13:02:50 +00:00
|
|
|
|
|
|
|
internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight );
|
2011-03-22 20:28:18 +00:00
|
|
|
internalCollisionShape->setMargin( 0.1 );
|
2011-02-22 13:02:50 +00:00
|
|
|
|
|
|
|
internalGhostObject->setCollisionShape( internalCollisionShape );
|
|
|
|
internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT );
|
|
|
|
|
2011-03-22 20:28:18 +00:00
|
|
|
mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 40 ),1,4,20,9.8,0.2 );
|
2011-02-26 23:44:52 +00:00
|
|
|
mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS);
|
2011-03-17 10:00:46 +00:00
|
|
|
mCharacter->setUseGhostSweepTest(false);
|
|
|
|
|
|
|
|
mCharacter->mCollision = false;
|
|
|
|
setGravity(0);
|
2011-02-22 13:02:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PhysicActor::~PhysicActor()
|
|
|
|
{
|
|
|
|
delete mCharacter;
|
|
|
|
delete internalGhostObject;
|
|
|
|
delete internalCollisionShape;
|
|
|
|
delete externalGhostObject;
|
|
|
|
delete externalCollisionShape;
|
|
|
|
}
|
|
|
|
|
2011-03-17 10:00:46 +00:00
|
|
|
void PhysicActor::setGravity(float gravity)
|
|
|
|
{
|
|
|
|
mCharacter->setGravity(gravity);
|
2011-03-20 20:51:40 +00:00
|
|
|
//mCharacter->
|
2011-03-17 10:00:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicActor::enableCollisions(bool collision)
|
|
|
|
{
|
|
|
|
mCharacter->mCollision = collision;
|
|
|
|
}
|
|
|
|
|
2011-03-20 20:51:40 +00:00
|
|
|
void PhysicActor::setVerticalVelocity(float z)
|
|
|
|
{
|
|
|
|
mCharacter->setVerticalVelocity(z);
|
|
|
|
}
|
|
|
|
|
2011-03-18 12:24:47 +00:00
|
|
|
bool PhysicActor::getCollisionMode()
|
|
|
|
{
|
|
|
|
return mCharacter->mCollision;
|
|
|
|
}
|
|
|
|
|
2011-02-26 15:34:43 +00:00
|
|
|
void PhysicActor::setWalkDirection(const btVector3& mvt)
|
2011-02-22 13:02:50 +00:00
|
|
|
{
|
|
|
|
mCharacter->setWalkDirection( mvt );
|
|
|
|
}
|
|
|
|
|
2011-02-26 15:34:43 +00:00
|
|
|
void PhysicActor::Rotate(const btQuaternion& quat)
|
2011-02-22 13:02:50 +00:00
|
|
|
{
|
|
|
|
externalGhostObject->getWorldTransform().setRotation( externalGhostObject->getWorldTransform().getRotation() * quat );
|
|
|
|
internalGhostObject->getWorldTransform().setRotation( internalGhostObject->getWorldTransform().getRotation() * quat );
|
|
|
|
}
|
|
|
|
|
2011-02-26 15:34:43 +00:00
|
|
|
void PhysicActor::setRotation(const btQuaternion& quat)
|
2011-02-22 13:02:50 +00:00
|
|
|
{
|
|
|
|
externalGhostObject->getWorldTransform().setRotation( quat );
|
|
|
|
internalGhostObject->getWorldTransform().setRotation( quat );
|
|
|
|
}
|
|
|
|
|
|
|
|
btVector3 PhysicActor::getPosition(void)
|
|
|
|
{
|
|
|
|
return internalGhostObject->getWorldTransform().getOrigin();
|
|
|
|
}
|
|
|
|
|
|
|
|
btQuaternion PhysicActor::getRotation(void)
|
|
|
|
{
|
|
|
|
return internalGhostObject->getWorldTransform().getRotation();
|
|
|
|
}
|
|
|
|
|
2011-02-26 15:34:43 +00:00
|
|
|
void PhysicActor::setPosition(const btVector3& pos)
|
2011-02-22 13:02:50 +00:00
|
|
|
{
|
|
|
|
internalGhostObject->getWorldTransform().setOrigin(pos);
|
|
|
|
externalGhostObject->getWorldTransform().setOrigin(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name)
|
|
|
|
:btRigidBody(CI),mName(name)
|
|
|
|
{
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-03-18 12:24:47 +00:00
|
|
|
PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader)
|
2011-02-22 13:02:50 +00:00
|
|
|
{
|
|
|
|
// Set up the collision configuration and dispatcher
|
|
|
|
collisionConfiguration = new btDefaultCollisionConfiguration();
|
|
|
|
dispatcher = new btCollisionDispatcher(collisionConfiguration);
|
|
|
|
|
|
|
|
// The actual physics solver
|
|
|
|
solver = new btSequentialImpulseConstraintSolver;
|
|
|
|
|
|
|
|
//TODO: memory leak?
|
|
|
|
btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache();
|
|
|
|
pairCache->setInternalGhostPairCallback( new btGhostPairCallback() );
|
|
|
|
|
|
|
|
broadphase = new btDbvtBroadphase(pairCache);
|
|
|
|
|
|
|
|
// The world.
|
|
|
|
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
|
|
|
|
dynamicsWorld->setGravity(btVector3(0,0,-10));
|
|
|
|
|
|
|
|
if(BulletShapeManager::getSingletonPtr() == NULL)
|
|
|
|
{
|
|
|
|
new BulletShapeManager();
|
|
|
|
}
|
|
|
|
//TODO:singleton?
|
2011-03-18 12:24:47 +00:00
|
|
|
mShapeLoader = shapeLoader;
|
2011-02-22 13:02:50 +00:00
|
|
|
|
|
|
|
isDebugCreated = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicEngine::createDebugRendering()
|
|
|
|
{
|
|
|
|
if(!isDebugCreated)
|
|
|
|
{
|
|
|
|
Ogre::SceneManagerEnumerator::SceneManagerIterator iter = Ogre::Root::getSingleton().getSceneManagerIterator();
|
|
|
|
iter.begin();
|
|
|
|
Ogre::SceneManager* scn = iter.getNext();
|
|
|
|
Ogre::SceneNode* node = scn->getRootSceneNode()->createChildSceneNode();
|
|
|
|
node->pitch(Ogre::Degree(-90));
|
|
|
|
mDebugDrawer = new BtOgre::DebugDrawer(node, dynamicsWorld);
|
|
|
|
dynamicsWorld->setDebugDrawer(mDebugDrawer);
|
|
|
|
isDebugCreated = true;
|
|
|
|
dynamicsWorld->debugDrawWorld();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-18 12:24:47 +00:00
|
|
|
void PhysicEngine::setDebugRenderingMode(int mode)
|
|
|
|
{
|
|
|
|
if(!isDebugCreated)
|
|
|
|
{
|
|
|
|
createDebugRendering();
|
|
|
|
}
|
|
|
|
mDebugDrawer->setDebugMode(mode);
|
|
|
|
}
|
2011-02-22 13:02:50 +00:00
|
|
|
|
|
|
|
PhysicEngine::~PhysicEngine()
|
|
|
|
{
|
|
|
|
delete dynamicsWorld;
|
|
|
|
delete solver;
|
|
|
|
delete collisionConfiguration;
|
|
|
|
delete dispatcher;
|
2011-02-26 15:34:43 +00:00
|
|
|
delete broadphase;
|
2011-03-18 12:24:47 +00:00
|
|
|
delete mShapeLoader;
|
2011-02-22 13:02:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name)
|
|
|
|
{
|
|
|
|
//get the shape from the .nif
|
2011-03-18 12:24:47 +00:00
|
|
|
mShapeLoader->load(mesh,"General");
|
2011-02-22 13:02:50 +00:00
|
|
|
BulletShapeManager::getSingletonPtr()->load(mesh,"General");
|
|
|
|
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General");
|
|
|
|
|
|
|
|
//create the motionState
|
|
|
|
CMotionState* newMotionState = new CMotionState(this,name);
|
|
|
|
|
|
|
|
//create the real body
|
|
|
|
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape);
|
|
|
|
RigidBody* body = new RigidBody(CI,name);
|
2011-02-22 19:53:02 +00:00
|
|
|
body->collide = shape->collide;
|
2011-02-22 13:02:50 +00:00
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicEngine::addRigidBody(RigidBody* body)
|
|
|
|
{
|
2011-02-22 19:53:02 +00:00
|
|
|
if(body->collide)
|
|
|
|
{
|
|
|
|
dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dynamicsWorld->addRigidBody(body,COL_WORLD,COL_NOTHING);
|
|
|
|
}
|
2011-02-22 13:02:50 +00:00
|
|
|
body->setActivationState(DISABLE_DEACTIVATION);
|
|
|
|
RigidBodyMap[body->mName] = body;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicEngine::removeRigidBody(std::string name)
|
|
|
|
{
|
|
|
|
RigidBody* body = RigidBodyMap[name];
|
|
|
|
if(body != NULL)
|
|
|
|
{
|
2011-03-07 13:55:18 +00:00
|
|
|
broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher);
|
|
|
|
std::map<std::string,PhysicActor*>::iterator it = PhysicActorMap.begin();
|
|
|
|
for(;it!=PhysicActorMap.end();it++)
|
|
|
|
{
|
|
|
|
it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher);
|
|
|
|
it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher);
|
|
|
|
}
|
2011-02-22 13:02:50 +00:00
|
|
|
dynamicsWorld->removeRigidBody(RigidBodyMap[name]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicEngine::deleteRigidBody(std::string name)
|
|
|
|
{
|
|
|
|
RigidBody* body = RigidBodyMap[name];
|
|
|
|
if(body != NULL)
|
|
|
|
{
|
|
|
|
delete body;
|
|
|
|
RigidBodyMap[name] = NULL;
|
|
|
|
}
|
|
|
|
}
|
2011-02-26 15:34:43 +00:00
|
|
|
|
2011-02-22 13:02:50 +00:00
|
|
|
RigidBody* PhysicEngine::getRigidBody(std::string name)
|
|
|
|
{
|
|
|
|
RigidBody* body = RigidBodyMap[name];
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicEngine::stepSimulation(double deltaT)
|
|
|
|
{
|
2011-03-22 20:28:18 +00:00
|
|
|
dynamicsWorld->stepSimulation(deltaT,1,1/50.);
|
2011-02-22 13:02:50 +00:00
|
|
|
if(isDebugCreated)
|
|
|
|
{
|
|
|
|
mDebugDrawer->step();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicEngine::addCharacter(std::string name)
|
|
|
|
{
|
|
|
|
PhysicActor* newActor = new PhysicActor(name);
|
|
|
|
dynamicsWorld->addCollisionObject( newActor->externalGhostObject, COL_ACTOR_EXTERNAL, COL_WORLD |COL_ACTOR_EXTERNAL );
|
|
|
|
dynamicsWorld->addCollisionObject( newActor->internalGhostObject, COL_ACTOR_INTERNAL, COL_WORLD |COL_ACTOR_INTERNAL );
|
|
|
|
dynamicsWorld->addAction( newActor->mCharacter );
|
|
|
|
PhysicActorMap[name] = newActor;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicEngine::removeCharacter(std::string name)
|
|
|
|
{
|
|
|
|
PhysicActor* act = PhysicActorMap[name];
|
|
|
|
if(act != NULL)
|
|
|
|
{
|
|
|
|
dynamicsWorld->removeCollisionObject(act->externalGhostObject);
|
|
|
|
dynamicsWorld->removeCollisionObject(act->internalGhostObject);
|
|
|
|
dynamicsWorld->removeAction(act->mCharacter);
|
|
|
|
delete act;
|
|
|
|
PhysicActorMap[name] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PhysicActor* PhysicEngine::getCharacter(std::string name)
|
|
|
|
{
|
|
|
|
PhysicActor* act = PhysicActorMap[name];
|
|
|
|
return act;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicEngine::emptyEventLists(void)
|
|
|
|
{
|
|
|
|
}
|
2011-02-22 19:53:02 +00:00
|
|
|
|
|
|
|
std::pair<std::string,float> PhysicEngine::rayTest(btVector3& from,btVector3& to)
|
|
|
|
{
|
|
|
|
std::string name = "";
|
2011-03-22 20:28:18 +00:00
|
|
|
float d = -1;
|
2011-02-22 19:53:02 +00:00
|
|
|
|
2011-03-22 20:28:18 +00:00
|
|
|
float d1 = 10000.;
|
|
|
|
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
|
|
|
resultCallback1.m_collisionFilterMask = COL_WORLD;
|
|
|
|
dynamicsWorld->rayTest(from, to, resultCallback1);
|
|
|
|
if (resultCallback1.hasHit())
|
2011-02-22 19:53:02 +00:00
|
|
|
{
|
2011-03-22 20:28:18 +00:00
|
|
|
name = static_cast<RigidBody&>(*resultCallback1.m_collisionObject).mName;
|
|
|
|
d1 = resultCallback1.m_closestHitFraction;
|
|
|
|
d = d1;
|
|
|
|
}
|
|
|
|
|
|
|
|
btCollisionWorld::ClosestRayResultCallback resultCallback2(from, to);
|
|
|
|
resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL;
|
|
|
|
dynamicsWorld->rayTest(from, to, resultCallback2);
|
|
|
|
float d2 = 10000.;
|
|
|
|
if (resultCallback2.hasHit())
|
|
|
|
{
|
|
|
|
d2 = resultCallback1.m_closestHitFraction;
|
|
|
|
if(d2<=d1)
|
2011-02-22 19:53:02 +00:00
|
|
|
{
|
2011-03-22 20:28:18 +00:00
|
|
|
name = static_cast<PairCachingGhostObject&>(*resultCallback2.m_collisionObject).mName;
|
|
|
|
d = d2;
|
2011-02-22 19:53:02 +00:00
|
|
|
}
|
|
|
|
}
|
2011-03-22 20:28:18 +00:00
|
|
|
|
2011-02-22 19:53:02 +00:00
|
|
|
return std::pair<std::string,float>(name,d);
|
|
|
|
}
|
2011-02-26 15:34:43 +00:00
|
|
|
}};
|