forked from teamnwah/openmw-tes3coop
Physics stub in preparation for rewrite
This commit is contained in:
parent
48ffeab191
commit
c843cfc8e2
17 changed files with 80 additions and 1557 deletions
|
@ -455,10 +455,6 @@ if(WIN32)
|
|||
include(CPack)
|
||||
endif(WIN32)
|
||||
|
||||
# Libs
|
||||
include_directories(libs)
|
||||
add_subdirectory(libs/openengine)
|
||||
|
||||
# Extern
|
||||
add_subdirectory (extern/osg-ffmpeg-videoplayer)
|
||||
add_subdirectory (extern/oics)
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/translation/translation.hpp>
|
||||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
|
||||
#include <components/esm/loadcell.hpp>
|
||||
|
||||
#include "mwinput/inputmanagerimp.hpp"
|
||||
|
|
|
@ -2,20 +2,8 @@
|
|||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreRenderWindow.h>
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreViewport.h>
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreTextureManager.h>
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
#include <osg/Group>
|
||||
|
||||
#include <openengine/bullet/trace.h>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
//#include <openengine/bullet/BulletShapeLoader.h>
|
||||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
||||
|
@ -33,20 +21,18 @@
|
|||
#include "../mwrender/bulletdebugdraw.hpp"
|
||||
|
||||
//#include "../apps/openmw/mwrender/animation.hpp"
|
||||
#include "../apps/openmw/mwbase/world.hpp"
|
||||
#include "../apps/openmw/mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
#include "ptr.hpp"
|
||||
#include "class.hpp"
|
||||
|
||||
using namespace Ogre;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -87,41 +73,11 @@ void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Phys
|
|||
// needed because we used btDynamicsWorld::setForceUpdateAllAabbs(false)
|
||||
dynamicsWorld->updateSingleAabb(it->first);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace BtOgre
|
||||
{
|
||||
//Converts from and to Bullet and Ogre stuff. Pretty self-explanatory.
|
||||
class Convert
|
||||
{
|
||||
public:
|
||||
Convert() {};
|
||||
~Convert() {};
|
||||
|
||||
static btQuaternion toBullet(const Ogre::Quaternion &q)
|
||||
{
|
||||
return btQuaternion(q.x, q.y, q.z, q.w);
|
||||
}
|
||||
static btVector3 toBullet(const Ogre::Vector3 &v)
|
||||
{
|
||||
return btVector3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
static Ogre::Quaternion toOgre(const btQuaternion &q)
|
||||
{
|
||||
return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z());
|
||||
}
|
||||
static Ogre::Vector3 toOgre(const btVector3 &v)
|
||||
{
|
||||
return Ogre::Vector3(v.x(), v.y(), v.z());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
||||
|
@ -188,6 +144,8 @@ namespace MWWorld
|
|||
* +--+ +--------
|
||||
* ==============================================
|
||||
*/
|
||||
return false;
|
||||
#if 0
|
||||
OEngine::Physic::ActorTracer tracer, stepper;
|
||||
|
||||
stepper.doTrace(colobj, position, position+Ogre::Vector3(0.0f,0.0f,sStepSizeUp), engine);
|
||||
|
@ -243,6 +201,7 @@ namespace MWWorld
|
|||
|
||||
// moved between 0 and just under sStepSize distance but slope was too great,
|
||||
// or moved full sStepSize distance (FIXME: is this a bug?)
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -266,6 +225,8 @@ namespace MWWorld
|
|||
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
||||
Ogre::Vector3 position(refpos.pos);
|
||||
|
||||
return position;
|
||||
#if 0
|
||||
OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle());
|
||||
if (!physicActor)
|
||||
return position;
|
||||
|
@ -302,6 +263,7 @@ namespace MWWorld
|
|||
|
||||
return tracer.mEndPos;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
|
||||
|
@ -311,7 +273,8 @@ namespace MWWorld
|
|||
{
|
||||
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
||||
Ogre::Vector3 position(refpos.pos);
|
||||
|
||||
return position;
|
||||
#if 0
|
||||
// Early-out for totally static creatures
|
||||
// (Not sure if gravity should still apply?)
|
||||
if (!ptr.getClass().isMobile(ptr))
|
||||
|
@ -526,21 +489,20 @@ namespace MWWorld
|
|||
|
||||
newPosition.z -= halfExtents.z; // remove what was added at the beginning
|
||||
return newPosition;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
PhysicsSystem::PhysicsSystem(osg::ref_ptr<osg::Group> parentNode) :
|
||||
mEngine(0), mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0), mDebugDrawEnabled(false), mParentNode(parentNode)
|
||||
mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0), mDebugDrawEnabled(false), mParentNode(parentNode)
|
||||
{
|
||||
mEngine = new OEngine::Physic::PhysicEngine;
|
||||
}
|
||||
|
||||
PhysicsSystem::~PhysicsSystem()
|
||||
{
|
||||
if (mWaterCollisionObject.get())
|
||||
mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
delete mEngine;
|
||||
//if (mWaterCollisionObject.get())
|
||||
// mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
}
|
||||
|
||||
bool PhysicsSystem::toggleDebugRendering()
|
||||
|
@ -549,25 +511,22 @@ namespace MWWorld
|
|||
|
||||
if (mDebugDrawEnabled && !mDebugDrawer.get())
|
||||
{
|
||||
mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mEngine->mDynamicsWorld));
|
||||
mEngine->mDynamicsWorld->setDebugDrawer(mDebugDrawer.get());
|
||||
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||
//mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mEngine->mDynamicsWorld));
|
||||
//mEngine->mDynamicsWorld->setDebugDrawer(mDebugDrawer.get());
|
||||
//mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||
}
|
||||
else if (mDebugDrawer.get())
|
||||
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||
return mDebugDrawEnabled;
|
||||
}
|
||||
|
||||
OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine()
|
||||
{
|
||||
return mEngine;
|
||||
}
|
||||
|
||||
std::pair<std::string,Ogre::Vector3> PhysicsSystem::getHitContact(const std::string &name,
|
||||
const Ogre::Vector3 &origin,
|
||||
const Ogre::Quaternion &orient,
|
||||
float queryDistance)
|
||||
{
|
||||
return std::make_pair(std::string(), Ogre::Vector3());
|
||||
/*
|
||||
const MWWorld::Store<ESM::GameSetting> &store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
btConeShape shape(Ogre::Degree(store.find("fCombatAngleXY")->getFloat()/2.0f).valueRadians(),
|
||||
|
@ -589,22 +548,28 @@ namespace MWWorld
|
|||
if(!result.first)
|
||||
return std::make_pair(std::string(), Ogre::Vector3(&result.second[0]));
|
||||
return std::make_pair(result.first->mName, Ogre::Vector3(&result.second[0]));
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to, bool ignoreHeightMap)
|
||||
bool PhysicsSystem::castRay(const Ogre::Vector3& from, const Ogre::Vector3& to, bool ignoreHeightMap)
|
||||
{
|
||||
return false;
|
||||
/*
|
||||
btVector3 _from, _to;
|
||||
_from = btVector3(from.x, from.y, from.z);
|
||||
_to = btVector3(to.x, to.y, to.z);
|
||||
|
||||
std::pair<std::string, float> result = mEngine->rayTest(_from, _to,ignoreHeightMap);
|
||||
return !(result.first == "");
|
||||
*/
|
||||
}
|
||||
|
||||
std::pair<bool, Ogre::Vector3>
|
||||
PhysicsSystem::castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len)
|
||||
{
|
||||
return std::make_pair(false, Ogre::Vector3());
|
||||
/*
|
||||
Ogre::Ray ray = Ogre::Ray(orig, dir);
|
||||
Ogre::Vector3 to = ray.getPoint(len);
|
||||
|
||||
|
@ -616,125 +581,42 @@ namespace MWWorld
|
|||
return std::make_pair(false, Ogre::Vector3());
|
||||
}
|
||||
return std::make_pair(true, ray.getPoint(len * test.second));
|
||||
*/
|
||||
}
|
||||
|
||||
std::vector<std::string> PhysicsSystem::getCollisions(const Ptr &ptr, int collisionGroup, int collisionMask)
|
||||
{
|
||||
return mEngine->getCollisions(ptr.getRefData().getBaseNodeOld()->getName(), collisionGroup, collisionMask);
|
||||
return std::vector<std::string>();//mEngine->getCollisions(ptr.getRefData().getBaseNodeOld()->getName(), collisionGroup, collisionMask);
|
||||
}
|
||||
|
||||
Ogre::Vector3 PhysicsSystem::traceDown(const MWWorld::Ptr &ptr, float maxHeight)
|
||||
{
|
||||
return MovementSolver::traceDown(ptr, mEngine, maxHeight);
|
||||
return Ogre::Vector3();//MovementSolver::traceDown(ptr, mEngine, maxHeight);
|
||||
}
|
||||
|
||||
void PhysicsSystem::addHeightField (float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts)
|
||||
{
|
||||
mEngine->addHeightField(heights, x, y, yoffset, triSize, sqrtVerts);
|
||||
}
|
||||
|
||||
void PhysicsSystem::removeHeightField (int x, int y)
|
||||
{
|
||||
mEngine->removeHeightField(x, y);
|
||||
}
|
||||
|
||||
void PhysicsSystem::addObject (const Ptr& ptr, const std::string& mesh, bool placeable)
|
||||
{
|
||||
/*
|
||||
Ogre::SceneNode* node = ptr.getRefData().getBaseNodeOld();
|
||||
handleToMesh[node->getName()] = mesh;
|
||||
mEngine->createAndAdjustRigidBody(
|
||||
mesh, node->getName(), ptr.getCellRef().getScale(), node->getPosition(), node->getOrientation(), 0, 0, false, placeable);
|
||||
mEngine->createAndAdjustRigidBody(
|
||||
mesh, node->getName(), ptr.getCellRef().getScale(), node->getPosition(), node->getOrientation(), 0, 0, true, placeable);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void PhysicsSystem::addActor (const Ptr& ptr, const std::string& mesh)
|
||||
{
|
||||
/*
|
||||
Ogre::SceneNode* node = ptr.getRefData().getBaseNodeOld();
|
||||
//TODO:optimize this. Searching the std::map isn't very efficient i think.
|
||||
mEngine->addCharacter(node->getName(), mesh, node->getPosition(), node->getScale().x, node->getOrientation());
|
||||
*/
|
||||
}
|
||||
|
||||
void PhysicsSystem::removeObject (const std::string& handle)
|
||||
{
|
||||
mEngine->removeCharacter(handle);
|
||||
mEngine->removeRigidBody(handle);
|
||||
mEngine->deleteRigidBody(handle);
|
||||
}
|
||||
|
||||
void PhysicsSystem::moveObject (const Ptr& ptr)
|
||||
{
|
||||
Ogre::SceneNode *node = ptr.getRefData().getBaseNodeOld();
|
||||
const std::string &handle = node->getName();
|
||||
const Ogre::Vector3 &position = node->getPosition();
|
||||
|
||||
if(OEngine::Physic::RigidBody *body = mEngine->getRigidBody(handle))
|
||||
{
|
||||
body->getWorldTransform().setOrigin(btVector3(position.x,position.y,position.z));
|
||||
mEngine->mDynamicsWorld->updateSingleAabb(body);
|
||||
}
|
||||
|
||||
// Actors update their AABBs every frame (DISABLE_DEACTIVATION), so no need to do it manually
|
||||
if(OEngine::Physic::PhysicActor *physact = mEngine->getCharacter(handle))
|
||||
physact->setPosition(position);
|
||||
}
|
||||
|
||||
void PhysicsSystem::rotateObject (const Ptr& ptr)
|
||||
{
|
||||
Ogre::SceneNode* node = ptr.getRefData().getBaseNodeOld();
|
||||
const std::string &handle = node->getName();
|
||||
const Ogre::Quaternion &rotation = node->getOrientation();
|
||||
|
||||
// TODO: map to MWWorld::Ptr for faster access
|
||||
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
|
||||
{
|
||||
act->setRotation(rotation);
|
||||
}
|
||||
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle))
|
||||
{
|
||||
if(dynamic_cast<btBoxShape*>(body->getCollisionShape()) == NULL)
|
||||
body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
|
||||
else
|
||||
mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, node->getPosition(), rotation);
|
||||
mEngine->mDynamicsWorld->updateSingleAabb(body);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::scaleObject (const Ptr& ptr)
|
||||
{
|
||||
Ogre::SceneNode* node = ptr.getRefData().getBaseNodeOld();
|
||||
const std::string &handle = node->getName();
|
||||
if(handleToMesh.find(handle) != handleToMesh.end())
|
||||
{
|
||||
std::string model = ptr.getClass().getModel(ptr);
|
||||
//model = Misc::ResourceHelpers::correctActorModelPath(model); // FIXME: scaling shouldn't require model
|
||||
|
||||
bool placeable = false;
|
||||
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle))
|
||||
placeable = body->mPlaceable;
|
||||
removeObject(handle);
|
||||
addObject(ptr, model, placeable);
|
||||
}
|
||||
|
||||
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
|
||||
{
|
||||
float scale = ptr.getCellRef().getScale();
|
||||
osg::Vec3f scaleVec (scale,scale,scale);
|
||||
if (!ptr.getClass().isNpc())
|
||||
// NOTE: Ignoring Npc::adjustScale (race height) on purpose. This is a bug in MW and must be replicated for compatibility reasons
|
||||
ptr.getClass().adjustScale(ptr, scaleVec);
|
||||
act->setScale(scaleVec.x());
|
||||
}
|
||||
}
|
||||
|
||||
bool PhysicsSystem::toggleCollisionMode()
|
||||
{
|
||||
/*
|
||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->mActorMap.begin(); it != mEngine->mActorMap.end();++it)
|
||||
{
|
||||
if (it->first=="player")
|
||||
|
@ -756,6 +638,8 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
throw std::logic_error ("can't find player");
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
void PhysicsSystem::queueObjectMovement(const Ptr &ptr, const Ogre::Vector3 &movement)
|
||||
|
@ -791,6 +675,8 @@ namespace MWWorld
|
|||
mCollisions.clear();
|
||||
mStandingCollisions.clear();
|
||||
|
||||
/*
|
||||
|
||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
PtrVelocityList::iterator iter = mMovementQueue.begin();
|
||||
for(;iter != mMovementQueue.end();++iter)
|
||||
|
@ -831,6 +717,8 @@ namespace MWWorld
|
|||
mMovementResults.push_back(std::make_pair(iter->first, newpos));
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
mTimeAccum = 0.0f;
|
||||
}
|
||||
mMovementQueue.clear();
|
||||
|
@ -840,9 +728,9 @@ namespace MWWorld
|
|||
|
||||
void PhysicsSystem::stepSimulation(float dt)
|
||||
{
|
||||
animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld);
|
||||
//animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld);
|
||||
|
||||
mEngine->stepSimulation(dt);
|
||||
//mEngine->stepSimulation(dt);
|
||||
|
||||
if (mDebugDrawer.get())
|
||||
mDebugDrawer->step();
|
||||
|
@ -932,7 +820,7 @@ namespace MWWorld
|
|||
{
|
||||
if (mWaterCollisionObject.get())
|
||||
{
|
||||
mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
//mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
}
|
||||
|
||||
if (!mWaterEnabled)
|
||||
|
@ -941,7 +829,7 @@ namespace MWWorld
|
|||
mWaterCollisionObject.reset(new btCollisionObject());
|
||||
mWaterCollisionShape.reset(new btStaticPlaneShape(btVector3(0,0,1), mWaterHeight));
|
||||
mWaterCollisionObject->setCollisionShape(mWaterCollisionShape.get());
|
||||
mEngine->mDynamicsWorld->addCollisionObject(mWaterCollisionObject.get(), OEngine::Physic::CollisionType_Water,
|
||||
OEngine::Physic::CollisionType_Actor);
|
||||
//mEngine->mDynamicsWorld->addCollisionObject(mWaterCollisionObject.get(), OEngine::Physic::CollisionType_Water,
|
||||
// OEngine::Physic::CollisionType_Actor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,15 +55,6 @@ namespace MWWorld
|
|||
|
||||
void removeHeightField (int x, int y);
|
||||
|
||||
// have to keep this as handle for now as unloadcell only knows scenenode names
|
||||
void removeObject (const std::string& handle);
|
||||
|
||||
void moveObject (const MWWorld::Ptr& ptr);
|
||||
|
||||
void rotateObject (const MWWorld::Ptr& ptr);
|
||||
|
||||
void scaleObject (const MWWorld::Ptr& ptr);
|
||||
|
||||
bool toggleCollisionMode();
|
||||
|
||||
void stepSimulation(float dt);
|
||||
|
@ -82,8 +73,6 @@ namespace MWWorld
|
|||
std::pair<bool, Ogre::Vector3>
|
||||
castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len);
|
||||
|
||||
OEngine::Physic::PhysicEngine* getEngine();
|
||||
|
||||
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
|
||||
/// be overwritten. Valid until the next call to applyQueuedMovement.
|
||||
void queueObjectMovement(const Ptr &ptr, const Ogre::Vector3 &velocity);
|
||||
|
@ -117,7 +106,6 @@ namespace MWWorld
|
|||
|
||||
bool mDebugDrawEnabled;
|
||||
|
||||
OEngine::Physic::PhysicEngine* mEngine;
|
||||
std::map<std::string, std::string> handleToMesh;
|
||||
|
||||
// Tracks all movement collisions happening during a single frame. <actor handle, collided handle>
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
|
||||
#include <osg/Group>
|
||||
|
||||
#include <libs/openengine/bullet/trace.h>
|
||||
#include <libs/openengine/bullet/physic.hpp>
|
||||
|
||||
#include <components/misc/rng.hpp>
|
||||
|
||||
#include <components/files/collections.hpp>
|
||||
|
@ -59,8 +56,6 @@
|
|||
#include "contentloader.hpp"
|
||||
#include "esmloader.hpp"
|
||||
|
||||
using namespace Ogre;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
@ -1402,7 +1397,7 @@ namespace MWWorld
|
|||
cellY = static_cast<int>(std::floor(y / cellSize));
|
||||
}
|
||||
|
||||
void World::queueMovement(const Ptr &ptr, const Vector3 &velocity)
|
||||
void World::queueMovement(const Ptr &ptr, const Ogre::Vector3 &velocity)
|
||||
{
|
||||
//mPhysics->queueObjectMovement(ptr, velocity);
|
||||
}
|
||||
|
@ -1630,7 +1625,9 @@ namespace MWWorld
|
|||
|
||||
void World::updateSoundListener()
|
||||
{
|
||||
/*
|
||||
Ogre::Vector3 playerPos = mPlayer->getPlayer().getRefData().getBaseNodeOld()->getPosition();
|
||||
|
||||
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(getPlayerPtr().getRefData().getHandle());
|
||||
if(actor) playerPos.z += 1.85f * actor->getHalfExtents().z;
|
||||
Ogre::Quaternion playerOrient = Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
|
||||
|
@ -1638,6 +1635,7 @@ namespace MWWorld
|
|||
Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y);
|
||||
MWBase::Environment::get().getSoundManager()->setListenerPosDir(playerPos, playerOrient.yAxis(),
|
||||
playerOrient.zAxis());
|
||||
*/
|
||||
}
|
||||
|
||||
void World::updateWindowManager ()
|
||||
|
@ -1654,7 +1652,7 @@ namespace MWWorld
|
|||
Ogre::AxisAlignedBox bounds = node->_getWorldAABB();
|
||||
if (bounds.isFinite())
|
||||
{
|
||||
Vector4 screenCoords;// = mRendering->boundingBoxToScreen(bounds);
|
||||
Ogre::Vector4 screenCoords;// = mRendering->boundingBoxToScreen(bounds);
|
||||
MWBase::Environment::get().getWindowManager()->setFocusObjectScreenCoords(
|
||||
screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]);
|
||||
}
|
||||
|
@ -1746,11 +1744,11 @@ namespace MWWorld
|
|||
MWWorld::CellRefList<ESM::Static>& statics = cell->get<ESM::Static>();
|
||||
MWWorld::LiveCellRef<ESM::Static>* ref = statics.find("northmarker");
|
||||
if (!ref)
|
||||
return Vector2(0, 1);
|
||||
return Ogre::Vector2(0, 1);
|
||||
|
||||
Ogre::Quaternion orient (Ogre::Radian(-ref->mData.getPosition().rot[2]), Ogre::Vector3::UNIT_Z);
|
||||
Vector3 dir = orient * Ogre::Vector3(0,1,0);
|
||||
Vector2 d = Vector2(dir.x, dir.y);
|
||||
Ogre::Vector3 dir = orient * Ogre::Vector3(0,1,0);
|
||||
Ogre::Vector2 d = Ogre::Vector2(dir.x, dir.y);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -2002,9 +2000,9 @@ namespace MWWorld
|
|||
&& isLevitationEnabled())
|
||||
return true;
|
||||
|
||||
const OEngine::Physic::PhysicActor *actor = 0;//mPhysEngine->getCharacter(ptr.getRefData().getHandle());
|
||||
if(!actor || !actor->getCollisionMode())
|
||||
return true;
|
||||
//const OEngine::Physic::PhysicActor *actor = 0;//mPhysEngine->getCharacter(ptr.getRefData().getHandle());
|
||||
//if(!actor || !actor->getCollisionMode())
|
||||
// return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2042,10 +2040,10 @@ namespace MWWorld
|
|||
const float *fpos = object.getRefData().getPosition().pos;
|
||||
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
|
||||
|
||||
const OEngine::Physic::PhysicActor *actor = 0;//mPhysEngine->getCharacter(object.getRefData().getHandle());
|
||||
if (actor)
|
||||
//const OEngine::Physic::PhysicActor *actor = 0;//mPhysEngine->getCharacter(object.getRefData().getHandle());
|
||||
//if (actor)
|
||||
{
|
||||
pos.z += heightRatio*2*actor->getHalfExtents().z;
|
||||
// pos.z += heightRatio*2*actor->getHalfExtents().z;
|
||||
}
|
||||
|
||||
return isUnderwater(object.getCell(), pos);
|
||||
|
@ -2071,6 +2069,8 @@ namespace MWWorld
|
|||
// TODO: There might be better places to update PhysicActor::mOnGround.
|
||||
bool World::isOnGround(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
return true;
|
||||
/*
|
||||
//RefData &refdata = ptr.getRefData();
|
||||
OEngine::Physic::PhysicActor *physactor = 0;//mPhysEngine->getCharacter(refdata.getHandle());
|
||||
|
||||
|
@ -2096,6 +2096,7 @@ namespace MWWorld
|
|||
else
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool World::vanityRotateCamera(float * rot)
|
||||
|
@ -2371,6 +2372,7 @@ namespace MWWorld
|
|||
if (!targetActor.getRefData().getBaseNodeOld() || !targetActor.getRefData().getBaseNodeOld())
|
||||
return false; // not in active cell
|
||||
|
||||
/*
|
||||
OEngine::Physic::PhysicActor* actor1 = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
||||
OEngine::Physic::PhysicActor* actor2 = mPhysEngine->getCharacter(targetActor.getRefData().getHandle());
|
||||
|
||||
|
@ -2387,12 +2389,15 @@ namespace MWWorld
|
|||
|
||||
std::pair<std::string, float> result = mPhysEngine->rayTest(from, to,false);
|
||||
if(result.first == "") return true;
|
||||
*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float World::getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist)
|
||||
{
|
||||
return 0;
|
||||
/*
|
||||
btVector3 btFrom(from.x, from.y, from.z);
|
||||
btVector3 btTo = btVector3(dir.x, dir.y, dir.z);
|
||||
btTo.normalize();
|
||||
|
@ -2402,13 +2407,16 @@ namespace MWWorld
|
|||
|
||||
if(result.second == -1) return maxDist;
|
||||
else return result.second*(btTo-btFrom).length();
|
||||
*/
|
||||
}
|
||||
|
||||
void World::enableActorCollision(const MWWorld::Ptr& actor, bool enable)
|
||||
{
|
||||
/*
|
||||
OEngine::Physic::PhysicActor *physicActor = 0;//mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
||||
if (physicActor)
|
||||
physicActor->enableCollisionBody(enable);
|
||||
*/
|
||||
}
|
||||
|
||||
bool World::findInteriorPosition(const std::string &name, ESM::Position &pos)
|
||||
|
@ -3235,7 +3243,7 @@ namespace MWWorld
|
|||
mRendering->spawnEffect(model, textureOverride, worldPos);
|
||||
}
|
||||
|
||||
void World::explodeSpell(const Vector3 &origin, const ESM::EffectList &effects, const Ptr &caster, ESM::RangeType rangeType,
|
||||
void World::explodeSpell(const Ogre::Vector3 &origin, const ESM::EffectList &effects, const Ptr &caster, ESM::RangeType rangeType,
|
||||
const std::string& id, const std::string& sourceName)
|
||||
{
|
||||
std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply;
|
||||
|
@ -3350,9 +3358,12 @@ namespace MWWorld
|
|||
|
||||
bool World::isWalkingOnWater(const Ptr &actor)
|
||||
{
|
||||
return false;
|
||||
/*
|
||||
OEngine::Physic::PhysicActor* physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
||||
if (physicActor && physicActor->isWalkingOnWater())
|
||||
return true;
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,9 +52,9 @@ add_component_dir (nifosg
|
|||
nifloader controller particle userdata
|
||||
)
|
||||
|
||||
add_component_dir (nifbullet
|
||||
bulletnifloader
|
||||
)
|
||||
#add_component_dir (nifbullet
|
||||
# bulletnifloader
|
||||
# )
|
||||
|
||||
add_component_dir (to_utf8
|
||||
to_utf8
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef OPENENGINE_MYGUI_LOGLISTENER_H
|
||||
#define OPENENGINE_MYGUI_LOGLISTENER_H
|
||||
#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_LOGLISTENER_H
|
||||
#define OPENMW_COMPONENTS_MYGUIPLATFORM_LOGLISTENER_H
|
||||
|
||||
#include <string>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <openengine/bullet/BulletShapeLoader.h>
|
||||
|
||||
#include <osg/Matrixf>
|
||||
|
||||
|
@ -70,8 +70,7 @@ class ManualBulletShapeLoader
|
|||
{
|
||||
public:
|
||||
ManualBulletShapeLoader(bool showMarkers=false)
|
||||
: mShape(NULL)
|
||||
, mCompoundShape(NULL)
|
||||
: mCompoundShape(NULL)
|
||||
, mStaticMesh(NULL)
|
||||
, mBoundingBox(NULL)
|
||||
, mShowMarkers(showMarkers)
|
||||
|
@ -91,11 +90,6 @@ public:
|
|||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
*This function should not be called manualy. Use load instead. (this is called by the BulletShapeManager when you use load).
|
||||
*/
|
||||
void loadResource(Ogre::Resource *resource);
|
||||
|
||||
private:
|
||||
btVector3 getbtVector(Ogre::Vector3 const &v);
|
||||
|
||||
|
@ -116,7 +110,7 @@ private:
|
|||
|
||||
std::string mResourceName;
|
||||
|
||||
OEngine::Physic::BulletShape* mShape;//current shape
|
||||
//OEngine::Physic::BulletShape* mShape;//current shape
|
||||
|
||||
btCompoundShape* mCompoundShape;
|
||||
|
||||
|
|
3
libs/openengine/.gitignore
vendored
3
libs/openengine/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
*~
|
||||
*.o
|
||||
*_test
|
|
@ -1,17 +0,0 @@
|
|||
set(OENGINE_BULLET
|
||||
bullet/physic.cpp
|
||||
bullet/physic.hpp
|
||||
bullet/BulletShapeLoader.cpp
|
||||
bullet/BulletShapeLoader.h
|
||||
bullet/trace.cpp
|
||||
bullet/trace.h
|
||||
)
|
||||
|
||||
set(OENGINE_ALL ${OENGINE_BULLET})
|
||||
|
||||
set(OENGINE_LIBRARY "oengine")
|
||||
set(OENGINE_LIBRARY ${OENGINE_LIBRARY} PARENT_SCOPE)
|
||||
|
||||
source_group(oengine FILES ${OENGINE_ALL})
|
||||
|
||||
add_library(${OENGINE_LIBRARY} STATIC ${OENGINE_ALL})
|
|
@ -1,12 +0,0 @@
|
|||
OpenEngine README
|
||||
=================
|
||||
|
||||
OpenEngine is a bunch of stand-alone game engine modules collected from the OpenMW project (see http://github.com/korslund/openmw or http://openmw.com ) and from certain other projects.
|
||||
|
||||
It is currently a very early work in progress, and development will follow OpenMW closely for a while forward.
|
||||
|
||||
OpenEngine will depend heavily on Mangle ( http://github.com/korslund/mangle/ ) and will thus aim to be backend agnostic. When finished it should work with a variety for free and commercial middleware libraries as backends for graphics, sound, physics, input and so on.
|
||||
|
||||
All questions can be directed to Nicolay Korslund at korslund@gmail.com
|
||||
|
||||
- Nicolay
|
|
@ -1,66 +0,0 @@
|
|||
#include "BulletShapeLoader.h"
|
||||
|
||||
namespace OEngine {
|
||||
namespace Physic
|
||||
{
|
||||
|
||||
BulletShape::BulletShape(Ogre::ResourceManager* creator, const Ogre::String &name,
|
||||
Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual,
|
||||
Ogre::ManualResourceLoader *loader) :
|
||||
Ogre::Resource(creator, name, handle, group, isManual, loader)
|
||||
{
|
||||
/* If you were storing a pointer to an object, then you would set that pointer to NULL here.
|
||||
*/
|
||||
|
||||
/* For consistency with StringInterface, but we don't add any parameters here
|
||||
That's because the Resource implementation of StringInterface is to
|
||||
list all the options that need to be set before loading, of which
|
||||
we have none as such. Full details can be set through scripts.
|
||||
*/
|
||||
mCollisionShape = NULL;
|
||||
mAutogenerated = true;
|
||||
createParamDictionary("BulletShape");
|
||||
}
|
||||
|
||||
BulletShape::~BulletShape()
|
||||
{
|
||||
deleteShape(mCollisionShape);
|
||||
}
|
||||
|
||||
// farm out to BulletShapeLoader
|
||||
void BulletShape::loadImpl()
|
||||
{
|
||||
mLoader->loadResource(this);
|
||||
}
|
||||
|
||||
void BulletShape::deleteShape(btCollisionShape* shape)
|
||||
{
|
||||
if(shape!=NULL)
|
||||
{
|
||||
if(shape->isCompound())
|
||||
{
|
||||
btCompoundShape* ms = static_cast<btCompoundShape*>(shape);
|
||||
int a = ms->getNumChildShapes();
|
||||
for(int i=0; i <a;i++)
|
||||
{
|
||||
deleteShape(ms->getChildShape(i));
|
||||
}
|
||||
}
|
||||
delete shape;
|
||||
}
|
||||
}
|
||||
|
||||
void BulletShape::unloadImpl()
|
||||
{
|
||||
deleteShape(mCollisionShape);
|
||||
mCollisionShape = NULL;
|
||||
}
|
||||
|
||||
//TODO:change this?
|
||||
size_t BulletShape::calculateSize() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
#ifndef OPENMW_BULLET_SHAPE_LOADER_H_
|
||||
#define OPENMW_BULLET_SHAPE_LOADER_H_
|
||||
|
||||
#include <OgreResource.h>
|
||||
#include <OgreResourceManager.h>
|
||||
#include <btBulletCollisionCommon.h>
|
||||
#include <OgreVector3.h>
|
||||
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Quat>
|
||||
|
||||
namespace OEngine {
|
||||
namespace Physic
|
||||
{
|
||||
|
||||
/**
|
||||
*Define a new resource which describe a Shape usable by bullet.See BulletShapeManager for how to get/use them.
|
||||
*/
|
||||
class BulletShape : public Ogre::Resource
|
||||
{
|
||||
protected:
|
||||
void loadImpl();
|
||||
void unloadImpl();
|
||||
size_t calculateSize() const;
|
||||
|
||||
void deleteShape(btCollisionShape* shape);
|
||||
|
||||
public:
|
||||
|
||||
BulletShape(Ogre::ResourceManager *creator, const Ogre::String &name,
|
||||
Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual = false,
|
||||
Ogre::ManualResourceLoader *loader = 0);
|
||||
|
||||
virtual ~BulletShape();
|
||||
|
||||
// Stores animated collision shapes. If any collision nodes in the NIF are animated, then mCollisionShape
|
||||
// will be a btCompoundShape (which consists of one or more child shapes).
|
||||
// In this map, for each animated collision shape,
|
||||
// we store the node's record index mapped to the child index of the shape in the btCompoundShape.
|
||||
std::map<int, int> mAnimatedShapes;
|
||||
|
||||
btCollisionShape* mCollisionShape;
|
||||
|
||||
// Does this .nif have an autogenerated collision mesh?
|
||||
bool mAutogenerated;
|
||||
|
||||
osg::Vec3f mBoxTranslation;
|
||||
osg::Quat mBoxRotation;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
typedef Ogre::SharedPtr<BulletShape> BulletShapePtr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,709 +0,0 @@
|
|||
#include "physic.hpp"
|
||||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <btBulletCollisionCommon.h>
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <OgreSceneManager.h>
|
||||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Create a copy of the given collision shape (responsibility of user to delete the returned shape).
|
||||
btCollisionShape *duplicateCollisionShape(btCollisionShape *shape)
|
||||
{
|
||||
if(shape->isCompound())
|
||||
{
|
||||
btCompoundShape *comp = static_cast<btCompoundShape*>(shape);
|
||||
btCompoundShape *newShape = new btCompoundShape;
|
||||
|
||||
int numShapes = comp->getNumChildShapes();
|
||||
for(int i = 0;i < numShapes;i++)
|
||||
{
|
||||
btCollisionShape *child = duplicateCollisionShape(comp->getChildShape(i));
|
||||
btTransform trans = comp->getChildTransform(i);
|
||||
newShape->addChildShape(trans, child);
|
||||
}
|
||||
|
||||
return newShape;
|
||||
}
|
||||
|
||||
if(btBvhTriangleMeshShape *trishape = dynamic_cast<btBvhTriangleMeshShape*>(shape))
|
||||
{
|
||||
btTriangleMesh* oldMesh = static_cast<btTriangleMesh*>(trishape->getMeshInterface());
|
||||
btTriangleMesh* newMesh = new btTriangleMesh(*oldMesh);
|
||||
NifBullet::TriangleMeshShape *newShape = new NifBullet::TriangleMeshShape(newMesh, true);
|
||||
|
||||
return newShape;
|
||||
}
|
||||
|
||||
throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName());
|
||||
}
|
||||
|
||||
void deleteShape(btCollisionShape* shape)
|
||||
{
|
||||
if(shape!=NULL)
|
||||
{
|
||||
if(shape->isCompound())
|
||||
{
|
||||
btCompoundShape* ms = static_cast<btCompoundShape*>(shape);
|
||||
int a = ms->getNumChildShapes();
|
||||
for(int i=0; i <a;i++)
|
||||
{
|
||||
deleteShape(ms->getChildShape(i));
|
||||
}
|
||||
}
|
||||
delete shape;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace OEngine {
|
||||
namespace Physic
|
||||
{
|
||||
|
||||
PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale)
|
||||
: mCanWaterWalk(false), mWalkingOnWater(false)
|
||||
, mBody(0), mScale(scale), mForce(0.0f), mOnGround(false)
|
||||
, mInternalCollisionMode(true)
|
||||
, mExternalCollisionMode(true)
|
||||
, mMesh(mesh), mName(name), mEngine(engine)
|
||||
{
|
||||
/*
|
||||
if (!NifBullet::getBoundingBox(mMesh, mHalfExtents, mMeshTranslation, mMeshOrientation))
|
||||
{
|
||||
mHalfExtents = Ogre::Vector3(0.f);
|
||||
mMeshTranslation = Ogre::Vector3(0.f);
|
||||
mMeshOrientation = Ogre::Quaternion::IDENTITY;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
// Use capsule shape only if base is square (nonuniform scaling apparently doesn't work on it)
|
||||
if (std::abs(mHalfExtents.x-mHalfExtents.y)<mHalfExtents.x*0.05 && mHalfExtents.z >= mHalfExtents.x)
|
||||
{
|
||||
// Could also be btCapsuleShapeZ, but the movement solver seems to have issues with it (jumping on slopes doesn't work)
|
||||
mShape.reset(new btCylinderShapeZ(BtOgre::Convert::toBullet(mHalfExtents)));
|
||||
}
|
||||
else
|
||||
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;
|
||||
mBody->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
mBody->setActivationState(DISABLE_DEACTIVATION);
|
||||
|
||||
setPosition(position);
|
||||
setRotation(rotation);
|
||||
|
||||
updateCollisionMask();
|
||||
}
|
||||
|
||||
PhysicActor::~PhysicActor()
|
||||
{
|
||||
if(mBody)
|
||||
{
|
||||
mEngine->mDynamicsWorld->removeRigidBody(mBody);
|
||||
delete mBody;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicActor::enableCollisionMode(bool collision)
|
||||
{
|
||||
mInternalCollisionMode = collision;
|
||||
}
|
||||
|
||||
void PhysicActor::enableCollisionBody(bool collision)
|
||||
{
|
||||
if (mExternalCollisionMode != collision)
|
||||
{
|
||||
mExternalCollisionMode = collision;
|
||||
updateCollisionMask();
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicActor::updateCollisionMask()
|
||||
{
|
||||
mEngine->mDynamicsWorld->removeRigidBody(mBody);
|
||||
int collisionMask = CollisionType_World | CollisionType_HeightMap;
|
||||
if (mExternalCollisionMode)
|
||||
collisionMask |= CollisionType_Actor | CollisionType_Projectile;
|
||||
if (mCanWaterWalk)
|
||||
collisionMask |= CollisionType_Water;
|
||||
mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor, collisionMask);
|
||||
}
|
||||
|
||||
const Ogre::Vector3& PhysicActor::getPosition() const
|
||||
{
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
void PhysicActor::setPosition(const Ogre::Vector3 &position)
|
||||
{
|
||||
assert(mBody);
|
||||
|
||||
mPosition = position;
|
||||
|
||||
//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& rotation)
|
||||
{
|
||||
//btTransform tr = mBody->getWorldTransform();
|
||||
//tr.setRotation(BtOgre::Convert::toBullet(mMeshOrientation * rotation));
|
||||
//mBody->setWorldTransform(tr);
|
||||
}
|
||||
|
||||
void PhysicActor::setScale(float scale)
|
||||
{
|
||||
mScale = scale;
|
||||
mShape->setLocalScaling(btVector3(scale,scale,scale));
|
||||
setPosition(mPosition);
|
||||
}
|
||||
|
||||
Ogre::Vector3 PhysicActor::getHalfExtents() const
|
||||
{
|
||||
return mHalfExtents * mScale;
|
||||
}
|
||||
|
||||
void PhysicActor::setInertialForce(const Ogre::Vector3 &force)
|
||||
{
|
||||
mForce = force;
|
||||
}
|
||||
|
||||
void PhysicActor::setOnGround(bool grounded)
|
||||
{
|
||||
mOnGround = grounded;
|
||||
}
|
||||
|
||||
bool PhysicActor::isWalkingOnWater() const
|
||||
{
|
||||
return mWalkingOnWater;
|
||||
}
|
||||
|
||||
void PhysicActor::setWalkingOnWater(bool walkingOnWater)
|
||||
{
|
||||
mWalkingOnWater = walkingOnWater;
|
||||
}
|
||||
|
||||
void PhysicActor::setCanWaterWalk(bool waterWalk)
|
||||
{
|
||||
if (waterWalk != mCanWaterWalk)
|
||||
{
|
||||
mCanWaterWalk = waterWalk;
|
||||
updateCollisionMask();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name)
|
||||
: btRigidBody(CI)
|
||||
, mName(name)
|
||||
, mPlaceable(false)
|
||||
{
|
||||
}
|
||||
|
||||
RigidBody::~RigidBody()
|
||||
{
|
||||
delete getMotionState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
PhysicEngine::PhysicEngine()
|
||||
{
|
||||
// Set up the collision configuration and dispatcher
|
||||
mCollisionConfiguration = new btDefaultCollisionConfiguration();
|
||||
mDispatcher = new btCollisionDispatcher(mCollisionConfiguration);
|
||||
|
||||
// The actual physics solver
|
||||
mSolver = new btSequentialImpulseConstraintSolver;
|
||||
|
||||
mBroadphase = new btDbvtBroadphase();
|
||||
|
||||
// The world.
|
||||
mDynamicsWorld = new btDiscreteDynamicsWorld(mDispatcher,mBroadphase,mSolver,mCollisionConfiguration);
|
||||
|
||||
// Don't update AABBs of all objects every frame. Most objects in MW are static, so we don't need this.
|
||||
// Should a "static" object ever be moved, we have to update its AABB manually using DynamicsWorld::updateSingleAabb.
|
||||
mDynamicsWorld->setForceUpdateAllAabbs(false);
|
||||
|
||||
mDynamicsWorld->setGravity(btVector3(0,0,-10));
|
||||
}
|
||||
|
||||
PhysicEngine::~PhysicEngine()
|
||||
{
|
||||
for (std::map<RigidBody*, AnimatedShapeInstance>::iterator it = mAnimatedShapes.begin(); it != mAnimatedShapes.end(); ++it)
|
||||
deleteShape(it->second.mCompound);
|
||||
|
||||
HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin();
|
||||
for (; hf_it != mHeightFieldMap.end(); ++hf_it)
|
||||
{
|
||||
mDynamicsWorld->removeRigidBody(hf_it->second.mBody);
|
||||
delete hf_it->second.mShape;
|
||||
delete hf_it->second.mBody;
|
||||
}
|
||||
|
||||
RigidBodyContainer::iterator rb_it = mCollisionObjectMap.begin();
|
||||
for (; rb_it != mCollisionObjectMap.end(); ++rb_it)
|
||||
{
|
||||
if (rb_it->second != NULL)
|
||||
{
|
||||
mDynamicsWorld->removeRigidBody(rb_it->second);
|
||||
|
||||
delete rb_it->second;
|
||||
rb_it->second = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PhysicActorContainer::iterator pa_it = mActorMap.begin();
|
||||
for (; pa_it != mActorMap.end(); ++pa_it)
|
||||
{
|
||||
if (pa_it->second != NULL)
|
||||
{
|
||||
delete pa_it->second;
|
||||
pa_it->second = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
delete mDynamicsWorld;
|
||||
delete mSolver;
|
||||
delete mCollisionConfiguration;
|
||||
delete mDispatcher;
|
||||
delete mBroadphase;
|
||||
}
|
||||
|
||||
void PhysicEngine::addHeightField(float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts)
|
||||
{
|
||||
const std::string name = "HeightField_"
|
||||
+ boost::lexical_cast<std::string>(x) + "_"
|
||||
+ boost::lexical_cast<std::string>(y);
|
||||
|
||||
// find the minimum and maximum heights (needed for bullet)
|
||||
float minh = heights[0];
|
||||
float maxh = heights[0];
|
||||
for (int i=0; i<sqrtVerts*sqrtVerts; ++i)
|
||||
{
|
||||
float h = heights[i];
|
||||
|
||||
if (h>maxh) maxh = h;
|
||||
if (h<minh) minh = h;
|
||||
}
|
||||
|
||||
btHeightfieldTerrainShape* hfShape = new btHeightfieldTerrainShape(
|
||||
static_cast<int>(sqrtVerts), static_cast<int>(sqrtVerts), heights, 1,
|
||||
minh, maxh, 2,
|
||||
PHY_FLOAT,true);
|
||||
|
||||
hfShape->setUseDiamondSubdivision(true);
|
||||
|
||||
btVector3 scl(triSize, triSize, 1);
|
||||
hfShape->setLocalScaling(scl);
|
||||
|
||||
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,0,hfShape);
|
||||
RigidBody* body = new RigidBody(CI,name);
|
||||
body->getWorldTransform().setOrigin(btVector3( (x+0.5f)*triSize*(sqrtVerts-1), (y+0.5f)*triSize*(sqrtVerts-1), (maxh+minh)/2.f));
|
||||
|
||||
HeightField hf;
|
||||
hf.mBody = body;
|
||||
hf.mShape = hfShape;
|
||||
|
||||
mHeightFieldMap [name] = hf;
|
||||
|
||||
mDynamicsWorld->addRigidBody(body,CollisionType_HeightMap,
|
||||
CollisionType_Actor|CollisionType_Projectile);
|
||||
}
|
||||
|
||||
void PhysicEngine::removeHeightField(int x, int y)
|
||||
{
|
||||
const std::string name = "HeightField_"
|
||||
+ boost::lexical_cast<std::string>(x) + "_"
|
||||
+ boost::lexical_cast<std::string>(y);
|
||||
|
||||
HeightFieldContainer::iterator it = mHeightFieldMap.find(name);
|
||||
if (it == mHeightFieldMap.end())
|
||||
return;
|
||||
|
||||
const HeightField& hf = it->second;
|
||||
|
||||
mDynamicsWorld->removeRigidBody(hf.mBody);
|
||||
delete hf.mShape;
|
||||
delete hf.mBody;
|
||||
|
||||
mHeightFieldMap.erase(it);
|
||||
}
|
||||
|
||||
void PhysicEngine::adjustRigidBody(RigidBody* body, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
|
||||
const Ogre::Vector3 &scaledBoxTranslation, const Ogre::Quaternion &boxRotation)
|
||||
{
|
||||
btTransform tr;
|
||||
Ogre::Quaternion boxrot = rotation * boxRotation;
|
||||
Ogre::Vector3 transrot = boxrot * scaledBoxTranslation;
|
||||
Ogre::Vector3 newPosition = transrot + position;
|
||||
|
||||
tr.setOrigin(btVector3(newPosition.x, newPosition.y, newPosition.z));
|
||||
tr.setRotation(btQuaternion(boxrot.x,boxrot.y,boxrot.z,boxrot.w));
|
||||
body->setWorldTransform(tr);
|
||||
}
|
||||
void PhysicEngine::boxAdjustExternal(const std::string &mesh, RigidBody* body,
|
||||
float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation)
|
||||
{
|
||||
std::string sid = (boost::format("%07.3f") % scale).str();
|
||||
std::string outputstring = mesh + sid;
|
||||
|
||||
//get the shape from the .nif
|
||||
//mShapeLoader->load(outputstring,"General");
|
||||
//BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General");
|
||||
|
||||
//adjustRigidBody(body, position, rotation, shape->mBoxTranslation * scale, shape->mBoxRotation);
|
||||
}
|
||||
|
||||
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 placeable)
|
||||
{
|
||||
std::string sid = (boost::format("%07.3f") % scale).str();
|
||||
std::string outputstring = mesh + sid;
|
||||
|
||||
//get the shape from the .nif
|
||||
//mShapeLoader->load(outputstring,"General");
|
||||
BulletShapePtr shape;// = BulletShapeManager::getSingleton().getByName(outputstring,"General");
|
||||
|
||||
// TODO: add option somewhere to enable collision for placeable meshes
|
||||
|
||||
if (placeable && shape->mCollisionShape)
|
||||
return NULL;
|
||||
|
||||
if (!shape->mCollisionShape)
|
||||
return NULL;
|
||||
|
||||
btCollisionShape* collisionShape = shape->mCollisionShape;
|
||||
|
||||
// If this is an animated compound shape, we must duplicate it so we can animate
|
||||
// multiple instances independently.
|
||||
if (!shape->mAnimatedShapes.empty())
|
||||
collisionShape = duplicateCollisionShape(collisionShape);
|
||||
|
||||
collisionShape->setLocalScaling( btVector3(scale,scale,scale));
|
||||
|
||||
//create the real body
|
||||
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo
|
||||
(0,0, collisionShape);
|
||||
RigidBody* body = new RigidBody(CI,name);
|
||||
body->mPlaceable = placeable;
|
||||
|
||||
if (!shape->mAnimatedShapes.empty())
|
||||
{
|
||||
AnimatedShapeInstance instance;
|
||||
instance.mAnimatedShapes = shape->mAnimatedShapes;
|
||||
instance.mCompound = collisionShape;
|
||||
mAnimatedShapes[body] = instance;
|
||||
}
|
||||
|
||||
//if(scaledBoxTranslation != 0)
|
||||
// *scaledBoxTranslation = shape->mBoxTranslation * scale;
|
||||
//if(boxRotation != 0)
|
||||
// *boxRotation = shape->mBoxRotation;
|
||||
|
||||
//adjustRigidBody(body, position, rotation, shape->mBoxTranslation * scale, shape->mBoxRotation);
|
||||
|
||||
assert (mCollisionObjectMap.find(name) == mCollisionObjectMap.end());
|
||||
mCollisionObjectMap[name] = body;
|
||||
mDynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_Actor|CollisionType_HeightMap);
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
void PhysicEngine::removeRigidBody(const std::string &name)
|
||||
{
|
||||
RigidBodyContainer::iterator it = mCollisionObjectMap.find(name);
|
||||
if (it != mCollisionObjectMap.end() )
|
||||
{
|
||||
RigidBody* body = it->second;
|
||||
if(body != NULL)
|
||||
{
|
||||
mDynamicsWorld->removeRigidBody(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicEngine::deleteRigidBody(const std::string &name)
|
||||
{
|
||||
RigidBodyContainer::iterator it = mCollisionObjectMap.find(name);
|
||||
if (it != mCollisionObjectMap.end() )
|
||||
{
|
||||
RigidBody* body = it->second;
|
||||
|
||||
if(body != NULL)
|
||||
{
|
||||
if (mAnimatedShapes.find(body) != mAnimatedShapes.end())
|
||||
deleteShape(mAnimatedShapes[body].mCompound);
|
||||
mAnimatedShapes.erase(body);
|
||||
|
||||
delete body;
|
||||
}
|
||||
mCollisionObjectMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
RigidBody* PhysicEngine::getRigidBody(const std::string &name)
|
||||
{
|
||||
RigidBodyContainer::iterator it = mCollisionObjectMap.find(name);
|
||||
if (it != mCollisionObjectMap.end() )
|
||||
{
|
||||
RigidBody* body = mCollisionObjectMap[name];
|
||||
return body;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> mResult;
|
||||
|
||||
// added in bullet 2.81
|
||||
// this is just a quick hack, as there does not seem to be a BULLET_VERSION macro?
|
||||
#if defined(BT_COLLISION_OBJECT_WRAPPER_H)
|
||||
virtual btScalar addSingleResult(btManifoldPoint& cp,
|
||||
const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,
|
||||
const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1)
|
||||
{
|
||||
const RigidBody* body = dynamic_cast<const RigidBody*>(colObj0Wrap->m_collisionObject);
|
||||
if (body)
|
||||
mResult.push_back(body->mName);
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
#else
|
||||
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* col0, int partId0, int index0,
|
||||
const btCollisionObject* col1, int partId1, int index1)
|
||||
{
|
||||
const RigidBody* body = dynamic_cast<const RigidBody*>(col0);
|
||||
if (body)
|
||||
mResult.push_back(body->mName);
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class DeepestNotMeContactTestResultCallback : public btCollisionWorld::ContactResultCallback
|
||||
{
|
||||
const std::string &mFilter;
|
||||
// Store the real origin, since the shape's origin is its center
|
||||
btVector3 mOrigin;
|
||||
|
||||
public:
|
||||
const RigidBody *mObject;
|
||||
btVector3 mContactPoint;
|
||||
btScalar mLeastDistSqr;
|
||||
|
||||
DeepestNotMeContactTestResultCallback(const std::string &filter, const btVector3 &origin)
|
||||
: mFilter(filter), mOrigin(origin), mObject(0), mContactPoint(0,0,0),
|
||||
mLeastDistSqr(std::numeric_limits<float>::max())
|
||||
{ }
|
||||
|
||||
#if defined(BT_COLLISION_OBJECT_WRAPPER_H)
|
||||
virtual btScalar addSingleResult(btManifoldPoint& cp,
|
||||
const btCollisionObjectWrapper* col0Wrap,int partId0,int index0,
|
||||
const btCollisionObjectWrapper* col1Wrap,int partId1,int index1)
|
||||
{
|
||||
const RigidBody* body = dynamic_cast<const RigidBody*>(col1Wrap->m_collisionObject);
|
||||
if(body && body->mName != mFilter)
|
||||
{
|
||||
btScalar distsqr = mOrigin.distance2(cp.getPositionWorldOnA());
|
||||
if(!mObject || distsqr < mLeastDistSqr)
|
||||
{
|
||||
mObject = body;
|
||||
mLeastDistSqr = distsqr;
|
||||
mContactPoint = cp.getPositionWorldOnA();
|
||||
}
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
#else
|
||||
virtual btScalar addSingleResult(btManifoldPoint& cp,
|
||||
const btCollisionObject* col0, int partId0, int index0,
|
||||
const btCollisionObject* col1, int partId1, int index1)
|
||||
{
|
||||
const RigidBody* body = dynamic_cast<const RigidBody*>(col1);
|
||||
if(body && body->mName != mFilter)
|
||||
{
|
||||
btScalar distsqr = mOrigin.distance2(cp.getPositionWorldOnA());
|
||||
if(!mObject || distsqr < mLeastDistSqr)
|
||||
{
|
||||
mObject = body;
|
||||
mLeastDistSqr = distsqr;
|
||||
mContactPoint = cp.getPositionWorldOnA();
|
||||
}
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
std::vector<std::string> PhysicEngine::getCollisions(const std::string& name, int collisionGroup, int collisionMask)
|
||||
{
|
||||
RigidBody* body = getRigidBody(name);
|
||||
ContactTestResultCallback callback;
|
||||
callback.m_collisionFilterGroup = collisionGroup;
|
||||
callback.m_collisionFilterMask = collisionMask;
|
||||
mDynamicsWorld->contactTest(body, callback);
|
||||
return callback.mResult;
|
||||
}
|
||||
|
||||
|
||||
std::pair<const RigidBody*,btVector3> PhysicEngine::getFilteredContact(const std::string &filter,
|
||||
const btVector3 &origin,
|
||||
btCollisionObject *object)
|
||||
{
|
||||
DeepestNotMeContactTestResultCallback callback(filter, origin);
|
||||
callback.m_collisionFilterGroup = CollisionType_Actor;
|
||||
callback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor;
|
||||
mDynamicsWorld->contactTest(object, callback);
|
||||
return std::make_pair(callback.mObject, callback.mContactPoint);
|
||||
}
|
||||
|
||||
void PhysicEngine::stepSimulation(double deltaT)
|
||||
{
|
||||
// This seems to be needed for character controller objects
|
||||
mDynamicsWorld->stepSimulation(static_cast<btScalar>(deltaT), 10, 1 / 60.0f);
|
||||
}
|
||||
|
||||
void PhysicEngine::addCharacter(const std::string &name, const std::string &mesh,
|
||||
const Ogre::Vector3 &position, float scale, const Ogre::Quaternion &rotation)
|
||||
{
|
||||
// Remove character with given name, so we don't make memory
|
||||
// leak when character would be added twice
|
||||
removeCharacter(name);
|
||||
|
||||
PhysicActor* newActor = new PhysicActor(name, mesh, this, position, rotation, scale);
|
||||
|
||||
mActorMap[name] = newActor;
|
||||
}
|
||||
|
||||
void PhysicEngine::removeCharacter(const std::string &name)
|
||||
{
|
||||
PhysicActorContainer::iterator it = mActorMap.find(name);
|
||||
if (it != mActorMap.end() )
|
||||
{
|
||||
PhysicActor* act = it->second;
|
||||
if(act != NULL)
|
||||
{
|
||||
delete act;
|
||||
}
|
||||
mActorMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
PhysicActor* PhysicEngine::getCharacter(const std::string &name)
|
||||
{
|
||||
PhysicActorContainer::iterator it = mActorMap.find(name);
|
||||
if (it != mActorMap.end() )
|
||||
{
|
||||
PhysicActor* act = mActorMap[name];
|
||||
return act;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<std::string,float> PhysicEngine::rayTest(const btVector3 &from, const btVector3 &to, bool ignoreHeightMap, Ogre::Vector3* normal)
|
||||
{
|
||||
std::string name = "";
|
||||
float d = -1;
|
||||
|
||||
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
||||
resultCallback1.m_collisionFilterGroup = 0xff;
|
||||
resultCallback1.m_collisionFilterMask = CollisionType_World;
|
||||
|
||||
if(!ignoreHeightMap)
|
||||
resultCallback1.m_collisionFilterMask = resultCallback1.m_collisionFilterMask | CollisionType_HeightMap;
|
||||
mDynamicsWorld->rayTest(from, to, resultCallback1);
|
||||
if (resultCallback1.hasHit())
|
||||
{
|
||||
name = static_cast<const RigidBody&>(*resultCallback1.m_collisionObject).mName;
|
||||
d = resultCallback1.m_closestHitFraction;
|
||||
if (normal)
|
||||
*normal = Ogre::Vector3(resultCallback1.m_hitNormalWorld.x(),
|
||||
resultCallback1.m_hitNormalWorld.y(),
|
||||
resultCallback1.m_hitNormalWorld.z());
|
||||
}
|
||||
|
||||
return std::pair<std::string,float>(name,d);
|
||||
}
|
||||
|
||||
// callback that ignores player in results
|
||||
struct OurClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
|
||||
{
|
||||
public:
|
||||
OurClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld)
|
||||
: btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld) {}
|
||||
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
|
||||
{
|
||||
if (const RigidBody* body = dynamic_cast<const RigidBody*>(convexResult.m_hitCollisionObject))
|
||||
if (body->mName == "player")
|
||||
return 0;
|
||||
return btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
|
||||
}
|
||||
};
|
||||
|
||||
std::pair<bool, float> PhysicEngine::sphereCast (float radius, btVector3& from, btVector3& to)
|
||||
{
|
||||
OurClosestConvexResultCallback callback(from, to);
|
||||
callback.m_collisionFilterGroup = 0xff;
|
||||
callback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap;
|
||||
|
||||
btSphereShape shape(radius);
|
||||
const btQuaternion btrot(0.0f, 0.0f, 0.0f);
|
||||
|
||||
btTransform from_ (btrot, from);
|
||||
btTransform to_ (btrot, to);
|
||||
|
||||
mDynamicsWorld->convexSweepTest(&shape, from_, to_, callback);
|
||||
|
||||
if (callback.hasHit())
|
||||
return std::make_pair(true, callback.m_closestHitFraction);
|
||||
else
|
||||
return std::make_pair(false, 1.0f);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,320 +0,0 @@
|
|||
#ifndef OENGINE_BULLET_PHYSIC_H
|
||||
#define OENGINE_BULLET_PHYSIC_H
|
||||
|
||||
#include <BulletDynamics/Dynamics/btRigidBody.h>
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "BulletShapeLoader.h"
|
||||
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class btRigidBody;
|
||||
class btBroadphaseInterface;
|
||||
class btDefaultCollisionConfiguration;
|
||||
class btSequentialImpulseConstraintSolver;
|
||||
class btCollisionDispatcher;
|
||||
class btDiscreteDynamicsWorld;
|
||||
class btHeightfieldTerrainShape;
|
||||
|
||||
namespace BtOgre
|
||||
{
|
||||
class DebugDrawer;
|
||||
}
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class SceneManager;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class World;
|
||||
}
|
||||
|
||||
|
||||
namespace OEngine {
|
||||
namespace Physic
|
||||
{
|
||||
struct PhysicEvent;
|
||||
class PhysicEngine;
|
||||
class RigidBody;
|
||||
|
||||
enum CollisionType {
|
||||
CollisionType_Nothing = 0, //<Collide with nothing
|
||||
CollisionType_World = 1<<0, //<Collide with world objects
|
||||
CollisionType_Actor = 1<<1, //<Collide sith actors
|
||||
CollisionType_HeightMap = 1<<2, //<collide with heightmap
|
||||
CollisionType_Projectile = 1<<3,
|
||||
CollisionType_Water = 1<<4
|
||||
};
|
||||
|
||||
/**
|
||||
*This class is just an extension of normal btRigidBody in order to add extra info.
|
||||
*When bullet give back a btRigidBody, you can just do a static_cast to RigidBody,
|
||||
*so one never should use btRigidBody directly!
|
||||
*/
|
||||
class RigidBody: public btRigidBody
|
||||
{
|
||||
public:
|
||||
RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name);
|
||||
virtual ~RigidBody();
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
class PhysicActor
|
||||
{
|
||||
public:
|
||||
PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale);
|
||||
|
||||
~PhysicActor();
|
||||
|
||||
void setPosition(const Ogre::Vector3 &pos);
|
||||
|
||||
/**
|
||||
* Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry.
|
||||
*/
|
||||
void enableCollisionMode(bool collision);
|
||||
|
||||
/**
|
||||
* Enables or disables the *external* collision body. If disabled, other actors will not collide with this actor.
|
||||
*/
|
||||
void enableCollisionBody(bool collision);
|
||||
|
||||
bool getCollisionMode() const
|
||||
{
|
||||
return mInternalCollisionMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scale of the PhysicActor
|
||||
*/
|
||||
void setScale(float scale);
|
||||
|
||||
void setRotation (const Ogre::Quaternion& rotation);
|
||||
|
||||
const Ogre::Vector3& getPosition() const;
|
||||
|
||||
/**
|
||||
* Returns the (scaled) half extents
|
||||
*/
|
||||
Ogre::Vector3 getHalfExtents() const;
|
||||
|
||||
/**
|
||||
* Sets the current amount of inertial force (incl. gravity) affecting this physic actor
|
||||
*/
|
||||
void setInertialForce(const Ogre::Vector3 &force);
|
||||
|
||||
/**
|
||||
* Gets the current amount of inertial force (incl. gravity) affecting this physic actor
|
||||
*/
|
||||
const Ogre::Vector3 &getInertialForce() const
|
||||
{
|
||||
return mForce;
|
||||
}
|
||||
|
||||
void setOnGround(bool grounded);
|
||||
|
||||
bool getOnGround() const
|
||||
{
|
||||
return mInternalCollisionMode && mOnGround;
|
||||
}
|
||||
|
||||
btCollisionObject *getCollisionBody() const
|
||||
{
|
||||
return mBody;
|
||||
}
|
||||
|
||||
|
||||
/// Sets whether this actor should be able to collide with the water surface
|
||||
void setCanWaterWalk(bool waterWalk);
|
||||
|
||||
/// Sets whether this actor has been walking on the water surface in the last frame
|
||||
void setWalkingOnWater(bool walkingOnWater);
|
||||
bool isWalkingOnWater() const;
|
||||
|
||||
private:
|
||||
/// Removes then re-adds the collision body to the dynamics world
|
||||
void updateCollisionMask();
|
||||
|
||||
bool mCanWaterWalk;
|
||||
bool mWalkingOnWater;
|
||||
|
||||
boost::shared_ptr<btCollisionShape> mShape;
|
||||
|
||||
OEngine::Physic::RigidBody* mBody;
|
||||
|
||||
Ogre::Quaternion mMeshOrientation;
|
||||
Ogre::Vector3 mMeshTranslation;
|
||||
Ogre::Vector3 mHalfExtents;
|
||||
|
||||
float mScale;
|
||||
Ogre::Vector3 mPosition;
|
||||
|
||||
Ogre::Vector3 mForce;
|
||||
bool mOnGround;
|
||||
bool mInternalCollisionMode;
|
||||
bool mExternalCollisionMode;
|
||||
|
||||
std::string mMesh;
|
||||
std::string mName;
|
||||
PhysicEngine *mEngine;
|
||||
|
||||
PhysicActor(const PhysicActor&);
|
||||
PhysicActor& operator=(const PhysicActor&);
|
||||
};
|
||||
|
||||
|
||||
struct HeightField
|
||||
{
|
||||
btHeightfieldTerrainShape* mShape;
|
||||
RigidBody* mBody;
|
||||
};
|
||||
|
||||
struct AnimatedShapeInstance
|
||||
{
|
||||
btCollisionShape* mCompound;
|
||||
|
||||
// Maps node record index to child index in the compound shape
|
||||
std::map<int, int> mAnimatedShapes;
|
||||
};
|
||||
|
||||
/**
|
||||
* The PhysicEngine class contain everything which is needed for Physic.
|
||||
* It's needed that Ogre Resources are set up before the PhysicEngine is created.
|
||||
* Note:deleting it WILL NOT delete the RigidBody!
|
||||
* TODO:unload unused resources?
|
||||
*/
|
||||
class PhysicEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Note that the shapeLoader IS destroyed by the phyic Engine!!
|
||||
*/
|
||||
PhysicEngine();
|
||||
|
||||
/**
|
||||
* It DOES destroy the shape loader!
|
||||
*/
|
||||
~PhysicEngine();
|
||||
|
||||
/**
|
||||
* Creates a RigidBody. It does not add it to the simulation.
|
||||
* After created, the body is set to the correct rotation, position, and scale
|
||||
*/
|
||||
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 placeable=false);
|
||||
|
||||
/**
|
||||
* Adjusts a rigid body to the right position and rotation
|
||||
*/
|
||||
|
||||
void adjustRigidBody(RigidBody* body, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
|
||||
const Ogre::Vector3 &scaledBoxTranslation = Ogre::Vector3::ZERO,
|
||||
const Ogre::Quaternion &boxRotation = Ogre::Quaternion::IDENTITY);
|
||||
/**
|
||||
Mainly used to (but not limited to) adjust rigid bodies based on box shapes to the right position and rotation.
|
||||
*/
|
||||
void boxAdjustExternal(const std::string &mesh, RigidBody* body, float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation);
|
||||
/**
|
||||
* Add a HeightField to the simulation
|
||||
*/
|
||||
void addHeightField(float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts);
|
||||
|
||||
/**
|
||||
* Remove a HeightField from the simulation
|
||||
*/
|
||||
void removeHeightField(int x, int y);
|
||||
|
||||
/**
|
||||
* Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap.
|
||||
*/
|
||||
void removeRigidBody(const std::string &name);
|
||||
|
||||
/**
|
||||
* Delete a RigidBody, and remove it from RigidBodyMap.
|
||||
*/
|
||||
void deleteRigidBody(const std::string &name);
|
||||
|
||||
/**
|
||||
* Return a pointer to a given rigid body.
|
||||
*/
|
||||
RigidBody* getRigidBody(const std::string &name);
|
||||
|
||||
/**
|
||||
* Create and add a character to the scene, and add it to the ActorMap.
|
||||
*/
|
||||
void addCharacter(const std::string &name, const std::string &mesh,
|
||||
const Ogre::Vector3 &position, float scale, const Ogre::Quaternion &rotation);
|
||||
|
||||
/**
|
||||
* Remove a character from the scene.
|
||||
*/
|
||||
void removeCharacter(const std::string &name);
|
||||
|
||||
/**
|
||||
* Return a pointer to a character
|
||||
*/
|
||||
PhysicActor* getCharacter(const std::string &name);
|
||||
|
||||
/**
|
||||
* This step the simulation of a given time.
|
||||
*/
|
||||
void stepSimulation(double deltaT);
|
||||
|
||||
/**
|
||||
* Return the closest object hit by a ray. If there are no objects, it will return ("",-1).
|
||||
* If \a normal is non-NULL, the hit normal will be written there (if there is a hit)
|
||||
*/
|
||||
std::pair<std::string,float> rayTest(const btVector3& from,const btVector3& to,
|
||||
bool ignoreHeightMap = false, Ogre::Vector3* normal = NULL);
|
||||
|
||||
std::pair<bool, float> sphereCast (float radius, btVector3& from, btVector3& to);
|
||||
///< @return (hit, relative distance)
|
||||
|
||||
std::vector<std::string> getCollisions(const std::string& name, int collisionGroup, int collisionMask);
|
||||
|
||||
// Get the nearest object that's inside the given object, filtering out objects of the
|
||||
// provided name
|
||||
std::pair<const RigidBody*,btVector3> getFilteredContact(const std::string &filter,
|
||||
const btVector3 &origin,
|
||||
btCollisionObject *object);
|
||||
|
||||
//Bullet Stuff
|
||||
btBroadphaseInterface* mBroadphase;
|
||||
btDefaultCollisionConfiguration* mCollisionConfiguration;
|
||||
btSequentialImpulseConstraintSolver* mSolver;
|
||||
btCollisionDispatcher* mDispatcher;
|
||||
btDiscreteDynamicsWorld* mDynamicsWorld;
|
||||
|
||||
typedef std::map<std::string, HeightField> HeightFieldContainer;
|
||||
HeightFieldContainer mHeightFieldMap;
|
||||
|
||||
typedef std::map<std::string,RigidBody*> RigidBodyContainer;
|
||||
RigidBodyContainer mCollisionObjectMap;
|
||||
|
||||
// Compound shapes that must be animated each frame based on bone positions
|
||||
// the index refers to an element in mCollisionObjectMap
|
||||
std::map<RigidBody*, AnimatedShapeInstance > mAnimatedShapes;
|
||||
|
||||
typedef std::map<std::string, PhysicActor*> PhysicActorContainer;
|
||||
PhysicActorContainer mActorMap;
|
||||
|
||||
private:
|
||||
PhysicEngine(const PhysicEngine&);
|
||||
PhysicEngine& operator=(const PhysicEngine&);
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
|
@ -1,133 +0,0 @@
|
|||
|
||||
#include "trace.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <btBulletCollisionCommon.h>
|
||||
|
||||
#include "physic.hpp"
|
||||
|
||||
|
||||
namespace OEngine
|
||||
{
|
||||
namespace Physic
|
||||
{
|
||||
|
||||
class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
|
||||
{
|
||||
public:
|
||||
ClosestNotMeConvexResultCallback(btCollisionObject *me, const btVector3 &up, btScalar minSlopeDot)
|
||||
: btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)),
|
||||
mMe(me), mUp(up), mMinSlopeDot(minSlopeDot)
|
||||
{
|
||||
}
|
||||
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
|
||||
{
|
||||
if(convexResult.m_hitCollisionObject == mMe)
|
||||
return btScalar( 1 );
|
||||
|
||||
btVector3 hitNormalWorld;
|
||||
if(normalInWorldSpace)
|
||||
hitNormalWorld = convexResult.m_hitNormalLocal;
|
||||
else
|
||||
{
|
||||
///need to transform normal into worldspace
|
||||
hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
|
||||
}
|
||||
|
||||
// NOTE : m_hitNormalLocal is not always vertical on the ground with a capsule or a box...
|
||||
|
||||
btScalar dotUp = mUp.dot(hitNormalWorld);
|
||||
if(dotUp < mMinSlopeDot)
|
||||
return btScalar(1);
|
||||
|
||||
return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
|
||||
}
|
||||
|
||||
protected:
|
||||
btCollisionObject *mMe;
|
||||
const btVector3 mUp;
|
||||
const btScalar mMinSlopeDot;
|
||||
};
|
||||
|
||||
|
||||
void ActorTracer::doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, const PhysicEngine *enginePass)
|
||||
{
|
||||
const btVector3 btstart(start.x, start.y, start.z);
|
||||
const btVector3 btend(end.x, end.y, end.z);
|
||||
|
||||
const btTransform &trans = actor->getWorldTransform();
|
||||
btTransform from(trans);
|
||||
btTransform to(trans);
|
||||
from.setOrigin(btstart);
|
||||
to.setOrigin(btend);
|
||||
|
||||
ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0));
|
||||
// Inherit the actor's collision group and mask
|
||||
newTraceCallback.m_collisionFilterGroup = actor->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
newTraceCallback.m_collisionFilterMask = actor->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
btCollisionShape *shape = actor->getCollisionShape();
|
||||
assert(shape->isConvex());
|
||||
enginePass->mDynamicsWorld->convexSweepTest(static_cast<btConvexShape*>(shape),
|
||||
from, to, newTraceCallback);
|
||||
|
||||
// Copy the hit data over to our trace results struct:
|
||||
if(newTraceCallback.hasHit())
|
||||
{
|
||||
const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld;
|
||||
mFraction = newTraceCallback.m_closestHitFraction;
|
||||
mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z());
|
||||
mEndPos = (end-start)*mFraction + start;
|
||||
mHitObject = newTraceCallback.m_hitCollisionObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEndPos = end;
|
||||
mPlaneNormal = Ogre::Vector3(0.0f, 0.0f, 1.0f);
|
||||
mFraction = 1.0f;
|
||||
mHitObject = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 btend(end.x, end.y, end.z+1.0f);
|
||||
|
||||
const btTransform &trans = actor->getCollisionBody()->getWorldTransform();
|
||||
btTransform from(trans.getBasis(), btstart);
|
||||
btTransform to(trans.getBasis(), btend);
|
||||
|
||||
ClosestNotMeConvexResultCallback newTraceCallback(actor->getCollisionBody(), btstart-btend, btScalar(0.0));
|
||||
// Inherit the actor's collision group and mask
|
||||
newTraceCallback.m_collisionFilterGroup = actor->getCollisionBody()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
newTraceCallback.m_collisionFilterMask = actor->getCollisionBody()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
newTraceCallback.m_collisionFilterMask &= ~CollisionType_Actor;
|
||||
|
||||
btVector3 halfExtents(actor->getHalfExtents().x, actor->getHalfExtents().y, actor->getHalfExtents().z);
|
||||
|
||||
halfExtents[2] = 1.0f;
|
||||
btCylinderShapeZ base(halfExtents);
|
||||
|
||||
enginePass->mDynamicsWorld->convexSweepTest(&base, from, to, newTraceCallback);
|
||||
if(newTraceCallback.hasHit())
|
||||
{
|
||||
const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld;
|
||||
mFraction = newTraceCallback.m_closestHitFraction;
|
||||
mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z());
|
||||
mEndPos = (end-start)*mFraction + start;
|
||||
mEndPos[2] += 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEndPos = end;
|
||||
mPlaneNormal = Ogre::Vector3(0.0f, 0.0f, 1.0f);
|
||||
mFraction = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#ifndef OENGINE_BULLET_TRACE_H
|
||||
#define OENGINE_BULLET_TRACE_H
|
||||
|
||||
#include <OgreVector3.h>
|
||||
|
||||
|
||||
class btCollisionObject;
|
||||
|
||||
|
||||
namespace OEngine
|
||||
{
|
||||
namespace Physic
|
||||
{
|
||||
class PhysicEngine;
|
||||
class PhysicActor;
|
||||
|
||||
struct ActorTracer
|
||||
{
|
||||
Ogre::Vector3 mEndPos;
|
||||
Ogre::Vector3 mPlaneNormal;
|
||||
const btCollisionObject* mHitObject;
|
||||
|
||||
float mFraction;
|
||||
|
||||
void doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end,
|
||||
const PhysicEngine *enginePass);
|
||||
void findGround(const OEngine::Physic::PhysicActor* actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end,
|
||||
const PhysicEngine *enginePass);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue