mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 13:19:40 +00:00
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)
|
include(CPack)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
# Libs
|
|
||||||
include_directories(libs)
|
|
||||||
add_subdirectory(libs/openengine)
|
|
||||||
|
|
||||||
# Extern
|
# Extern
|
||||||
add_subdirectory (extern/osg-ffmpeg-videoplayer)
|
add_subdirectory (extern/osg-ffmpeg-videoplayer)
|
||||||
add_subdirectory (extern/oics)
|
add_subdirectory (extern/oics)
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/translation/translation.hpp>
|
#include <components/translation/translation.hpp>
|
||||||
|
|
||||||
#include <components/nifbullet/bulletnifloader.hpp>
|
|
||||||
|
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
#include "mwinput/inputmanagerimp.hpp"
|
#include "mwinput/inputmanagerimp.hpp"
|
||||||
|
|
|
@ -2,20 +2,8 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#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 <osg/Group>
|
||||||
|
|
||||||
#include <openengine/bullet/trace.h>
|
|
||||||
#include <openengine/bullet/physic.hpp>
|
|
||||||
//#include <openengine/bullet/BulletShapeLoader.h>
|
|
||||||
|
|
||||||
#include <components/nifbullet/bulletnifloader.hpp>
|
#include <components/nifbullet/bulletnifloader.hpp>
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
|
||||||
|
@ -33,20 +21,18 @@
|
||||||
#include "../mwrender/bulletdebugdraw.hpp"
|
#include "../mwrender/bulletdebugdraw.hpp"
|
||||||
|
|
||||||
//#include "../apps/openmw/mwrender/animation.hpp"
|
//#include "../apps/openmw/mwrender/animation.hpp"
|
||||||
#include "../apps/openmw/mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../apps/openmw/mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
#include "ptr.hpp"
|
#include "ptr.hpp"
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
|
|
||||||
using namespace Ogre;
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>& map, btDynamicsWorld* dynamicsWorld)
|
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();
|
for (std::map<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>::iterator it = map.begin();
|
||||||
it != map.end(); ++it)
|
it != map.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -87,41 +73,11 @@ void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Phys
|
||||||
// needed because we used btDynamicsWorld::setForceUpdateAllAabbs(false)
|
// needed because we used btDynamicsWorld::setForceUpdateAllAabbs(false)
|
||||||
dynamicsWorld->updateSingleAabb(it->first);
|
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
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -188,6 +144,8 @@ namespace MWWorld
|
||||||
* +--+ +--------
|
* +--+ +--------
|
||||||
* ==============================================
|
* ==============================================
|
||||||
*/
|
*/
|
||||||
|
return false;
|
||||||
|
#if 0
|
||||||
OEngine::Physic::ActorTracer tracer, stepper;
|
OEngine::Physic::ActorTracer tracer, stepper;
|
||||||
|
|
||||||
stepper.doTrace(colobj, position, position+Ogre::Vector3(0.0f,0.0f,sStepSizeUp), engine);
|
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,
|
// moved between 0 and just under sStepSize distance but slope was too great,
|
||||||
// or moved full sStepSize distance (FIXME: is this a bug?)
|
// or moved full sStepSize distance (FIXME: is this a bug?)
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,6 +225,8 @@ namespace MWWorld
|
||||||
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
||||||
Ogre::Vector3 position(refpos.pos);
|
Ogre::Vector3 position(refpos.pos);
|
||||||
|
|
||||||
|
return position;
|
||||||
|
#if 0
|
||||||
OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle());
|
OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle());
|
||||||
if (!physicActor)
|
if (!physicActor)
|
||||||
return position;
|
return position;
|
||||||
|
@ -302,6 +263,7 @@ namespace MWWorld
|
||||||
|
|
||||||
return tracer.mEndPos;
|
return tracer.mEndPos;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
|
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();
|
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
||||||
Ogre::Vector3 position(refpos.pos);
|
Ogre::Vector3 position(refpos.pos);
|
||||||
|
return position;
|
||||||
|
#if 0
|
||||||
// Early-out for totally static creatures
|
// Early-out for totally static creatures
|
||||||
// (Not sure if gravity should still apply?)
|
// (Not sure if gravity should still apply?)
|
||||||
if (!ptr.getClass().isMobile(ptr))
|
if (!ptr.getClass().isMobile(ptr))
|
||||||
|
@ -526,21 +489,20 @@ namespace MWWorld
|
||||||
|
|
||||||
newPosition.z -= halfExtents.z; // remove what was added at the beginning
|
newPosition.z -= halfExtents.z; // remove what was added at the beginning
|
||||||
return newPosition;
|
return newPosition;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PhysicsSystem::PhysicsSystem(osg::ref_ptr<osg::Group> parentNode) :
|
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()
|
PhysicsSystem::~PhysicsSystem()
|
||||||
{
|
{
|
||||||
if (mWaterCollisionObject.get())
|
//if (mWaterCollisionObject.get())
|
||||||
mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
// mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||||
delete mEngine;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsSystem::toggleDebugRendering()
|
bool PhysicsSystem::toggleDebugRendering()
|
||||||
|
@ -549,25 +511,22 @@ namespace MWWorld
|
||||||
|
|
||||||
if (mDebugDrawEnabled && !mDebugDrawer.get())
|
if (mDebugDrawEnabled && !mDebugDrawer.get())
|
||||||
{
|
{
|
||||||
mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mEngine->mDynamicsWorld));
|
//mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mEngine->mDynamicsWorld));
|
||||||
mEngine->mDynamicsWorld->setDebugDrawer(mDebugDrawer.get());
|
//mEngine->mDynamicsWorld->setDebugDrawer(mDebugDrawer.get());
|
||||||
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
//mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||||
}
|
}
|
||||||
else if (mDebugDrawer.get())
|
else if (mDebugDrawer.get())
|
||||||
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||||
return mDebugDrawEnabled;
|
return mDebugDrawEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine()
|
|
||||||
{
|
|
||||||
return mEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<std::string,Ogre::Vector3> PhysicsSystem::getHitContact(const std::string &name,
|
std::pair<std::string,Ogre::Vector3> PhysicsSystem::getHitContact(const std::string &name,
|
||||||
const Ogre::Vector3 &origin,
|
const Ogre::Vector3 &origin,
|
||||||
const Ogre::Quaternion &orient,
|
const Ogre::Quaternion &orient,
|
||||||
float queryDistance)
|
float queryDistance)
|
||||||
{
|
{
|
||||||
|
return std::make_pair(std::string(), Ogre::Vector3());
|
||||||
|
/*
|
||||||
const MWWorld::Store<ESM::GameSetting> &store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
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(),
|
btConeShape shape(Ogre::Degree(store.find("fCombatAngleXY")->getFloat()/2.0f).valueRadians(),
|
||||||
|
@ -589,22 +548,28 @@ namespace MWWorld
|
||||||
if(!result.first)
|
if(!result.first)
|
||||||
return std::make_pair(std::string(), Ogre::Vector3(&result.second[0]));
|
return std::make_pair(std::string(), Ogre::Vector3(&result.second[0]));
|
||||||
return std::make_pair(result.first->mName, 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;
|
btVector3 _from, _to;
|
||||||
_from = btVector3(from.x, from.y, from.z);
|
_from = btVector3(from.x, from.y, from.z);
|
||||||
_to = btVector3(to.x, to.y, to.z);
|
_to = btVector3(to.x, to.y, to.z);
|
||||||
|
|
||||||
std::pair<std::string, float> result = mEngine->rayTest(_from, _to,ignoreHeightMap);
|
std::pair<std::string, float> result = mEngine->rayTest(_from, _to,ignoreHeightMap);
|
||||||
return !(result.first == "");
|
return !(result.first == "");
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool, Ogre::Vector3>
|
std::pair<bool, Ogre::Vector3>
|
||||||
PhysicsSystem::castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len)
|
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::Ray ray = Ogre::Ray(orig, dir);
|
||||||
Ogre::Vector3 to = ray.getPoint(len);
|
Ogre::Vector3 to = ray.getPoint(len);
|
||||||
|
|
||||||
|
@ -616,125 +581,42 @@ namespace MWWorld
|
||||||
return std::make_pair(false, Ogre::Vector3());
|
return std::make_pair(false, Ogre::Vector3());
|
||||||
}
|
}
|
||||||
return std::make_pair(true, ray.getPoint(len * test.second));
|
return std::make_pair(true, ray.getPoint(len * test.second));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> PhysicsSystem::getCollisions(const Ptr &ptr, int collisionGroup, int collisionMask)
|
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)
|
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,
|
void PhysicsSystem::addHeightField (float* heights,
|
||||||
int x, int y, float yoffset,
|
int x, int y, float yoffset,
|
||||||
float triSize, float sqrtVerts)
|
float triSize, float sqrtVerts)
|
||||||
{
|
{
|
||||||
mEngine->addHeightField(heights, x, y, yoffset, triSize, sqrtVerts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::removeHeightField (int x, int y)
|
void PhysicsSystem::removeHeightField (int x, int y)
|
||||||
{
|
{
|
||||||
mEngine->removeHeightField(x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::addObject (const Ptr& ptr, const std::string& mesh, bool placeable)
|
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)
|
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()
|
bool PhysicsSystem::toggleCollisionMode()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->mActorMap.begin(); it != mEngine->mActorMap.end();++it)
|
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->mActorMap.begin(); it != mEngine->mActorMap.end();++it)
|
||||||
{
|
{
|
||||||
if (it->first=="player")
|
if (it->first=="player")
|
||||||
|
@ -756,6 +638,8 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::logic_error ("can't find player");
|
throw std::logic_error ("can't find player");
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::queueObjectMovement(const Ptr &ptr, const Ogre::Vector3 &movement)
|
void PhysicsSystem::queueObjectMovement(const Ptr &ptr, const Ogre::Vector3 &movement)
|
||||||
|
@ -791,6 +675,8 @@ namespace MWWorld
|
||||||
mCollisions.clear();
|
mCollisions.clear();
|
||||||
mStandingCollisions.clear();
|
mStandingCollisions.clear();
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
PtrVelocityList::iterator iter = mMovementQueue.begin();
|
PtrVelocityList::iterator iter = mMovementQueue.begin();
|
||||||
for(;iter != mMovementQueue.end();++iter)
|
for(;iter != mMovementQueue.end();++iter)
|
||||||
|
@ -831,6 +717,8 @@ namespace MWWorld
|
||||||
mMovementResults.push_back(std::make_pair(iter->first, newpos));
|
mMovementResults.push_back(std::make_pair(iter->first, newpos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
mTimeAccum = 0.0f;
|
mTimeAccum = 0.0f;
|
||||||
}
|
}
|
||||||
mMovementQueue.clear();
|
mMovementQueue.clear();
|
||||||
|
@ -840,9 +728,9 @@ namespace MWWorld
|
||||||
|
|
||||||
void PhysicsSystem::stepSimulation(float dt)
|
void PhysicsSystem::stepSimulation(float dt)
|
||||||
{
|
{
|
||||||
animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld);
|
//animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld);
|
||||||
|
|
||||||
mEngine->stepSimulation(dt);
|
//mEngine->stepSimulation(dt);
|
||||||
|
|
||||||
if (mDebugDrawer.get())
|
if (mDebugDrawer.get())
|
||||||
mDebugDrawer->step();
|
mDebugDrawer->step();
|
||||||
|
@ -932,7 +820,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
if (mWaterCollisionObject.get())
|
if (mWaterCollisionObject.get())
|
||||||
{
|
{
|
||||||
mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
//mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mWaterEnabled)
|
if (!mWaterEnabled)
|
||||||
|
@ -941,7 +829,7 @@ namespace MWWorld
|
||||||
mWaterCollisionObject.reset(new btCollisionObject());
|
mWaterCollisionObject.reset(new btCollisionObject());
|
||||||
mWaterCollisionShape.reset(new btStaticPlaneShape(btVector3(0,0,1), mWaterHeight));
|
mWaterCollisionShape.reset(new btStaticPlaneShape(btVector3(0,0,1), mWaterHeight));
|
||||||
mWaterCollisionObject->setCollisionShape(mWaterCollisionShape.get());
|
mWaterCollisionObject->setCollisionShape(mWaterCollisionShape.get());
|
||||||
mEngine->mDynamicsWorld->addCollisionObject(mWaterCollisionObject.get(), OEngine::Physic::CollisionType_Water,
|
//mEngine->mDynamicsWorld->addCollisionObject(mWaterCollisionObject.get(), OEngine::Physic::CollisionType_Water,
|
||||||
OEngine::Physic::CollisionType_Actor);
|
// OEngine::Physic::CollisionType_Actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,15 +55,6 @@ namespace MWWorld
|
||||||
|
|
||||||
void removeHeightField (int x, int y);
|
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();
|
bool toggleCollisionMode();
|
||||||
|
|
||||||
void stepSimulation(float dt);
|
void stepSimulation(float dt);
|
||||||
|
@ -82,8 +73,6 @@ namespace MWWorld
|
||||||
std::pair<bool, Ogre::Vector3>
|
std::pair<bool, Ogre::Vector3>
|
||||||
castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len);
|
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
|
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
|
||||||
/// be overwritten. Valid until the next call to applyQueuedMovement.
|
/// be overwritten. Valid until the next call to applyQueuedMovement.
|
||||||
void queueObjectMovement(const Ptr &ptr, const Ogre::Vector3 &velocity);
|
void queueObjectMovement(const Ptr &ptr, const Ogre::Vector3 &velocity);
|
||||||
|
@ -117,7 +106,6 @@ namespace MWWorld
|
||||||
|
|
||||||
bool mDebugDrawEnabled;
|
bool mDebugDrawEnabled;
|
||||||
|
|
||||||
OEngine::Physic::PhysicEngine* mEngine;
|
|
||||||
std::map<std::string, std::string> handleToMesh;
|
std::map<std::string, std::string> handleToMesh;
|
||||||
|
|
||||||
// Tracks all movement collisions happening during a single frame. <actor handle, collided handle>
|
// Tracks all movement collisions happening during a single frame. <actor handle, collided handle>
|
||||||
|
|
|
@ -13,9 +13,6 @@
|
||||||
|
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
|
||||||
#include <libs/openengine/bullet/trace.h>
|
|
||||||
#include <libs/openengine/bullet/physic.hpp>
|
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include <components/files/collections.hpp>
|
#include <components/files/collections.hpp>
|
||||||
|
@ -59,8 +56,6 @@
|
||||||
#include "contentloader.hpp"
|
#include "contentloader.hpp"
|
||||||
#include "esmloader.hpp"
|
#include "esmloader.hpp"
|
||||||
|
|
||||||
using namespace Ogre;
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1402,7 +1397,7 @@ namespace MWWorld
|
||||||
cellY = static_cast<int>(std::floor(y / cellSize));
|
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);
|
//mPhysics->queueObjectMovement(ptr, velocity);
|
||||||
}
|
}
|
||||||
|
@ -1630,7 +1625,9 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::updateSoundListener()
|
void World::updateSoundListener()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
Ogre::Vector3 playerPos = mPlayer->getPlayer().getRefData().getBaseNodeOld()->getPosition();
|
Ogre::Vector3 playerPos = mPlayer->getPlayer().getRefData().getBaseNodeOld()->getPosition();
|
||||||
|
|
||||||
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(getPlayerPtr().getRefData().getHandle());
|
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(getPlayerPtr().getRefData().getHandle());
|
||||||
if(actor) playerPos.z += 1.85f * actor->getHalfExtents().z;
|
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) *
|
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);
|
Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y);
|
||||||
MWBase::Environment::get().getSoundManager()->setListenerPosDir(playerPos, playerOrient.yAxis(),
|
MWBase::Environment::get().getSoundManager()->setListenerPosDir(playerPos, playerOrient.yAxis(),
|
||||||
playerOrient.zAxis());
|
playerOrient.zAxis());
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::updateWindowManager ()
|
void World::updateWindowManager ()
|
||||||
|
@ -1654,7 +1652,7 @@ namespace MWWorld
|
||||||
Ogre::AxisAlignedBox bounds = node->_getWorldAABB();
|
Ogre::AxisAlignedBox bounds = node->_getWorldAABB();
|
||||||
if (bounds.isFinite())
|
if (bounds.isFinite())
|
||||||
{
|
{
|
||||||
Vector4 screenCoords;// = mRendering->boundingBoxToScreen(bounds);
|
Ogre::Vector4 screenCoords;// = mRendering->boundingBoxToScreen(bounds);
|
||||||
MWBase::Environment::get().getWindowManager()->setFocusObjectScreenCoords(
|
MWBase::Environment::get().getWindowManager()->setFocusObjectScreenCoords(
|
||||||
screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]);
|
screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]);
|
||||||
}
|
}
|
||||||
|
@ -1746,11 +1744,11 @@ namespace MWWorld
|
||||||
MWWorld::CellRefList<ESM::Static>& statics = cell->get<ESM::Static>();
|
MWWorld::CellRefList<ESM::Static>& statics = cell->get<ESM::Static>();
|
||||||
MWWorld::LiveCellRef<ESM::Static>* ref = statics.find("northmarker");
|
MWWorld::LiveCellRef<ESM::Static>* ref = statics.find("northmarker");
|
||||||
if (!ref)
|
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);
|
Ogre::Quaternion orient (Ogre::Radian(-ref->mData.getPosition().rot[2]), Ogre::Vector3::UNIT_Z);
|
||||||
Vector3 dir = orient * Ogre::Vector3(0,1,0);
|
Ogre::Vector3 dir = orient * Ogre::Vector3(0,1,0);
|
||||||
Vector2 d = Vector2(dir.x, dir.y);
|
Ogre::Vector2 d = Ogre::Vector2(dir.x, dir.y);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2002,9 +2000,9 @@ namespace MWWorld
|
||||||
&& isLevitationEnabled())
|
&& isLevitationEnabled())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const OEngine::Physic::PhysicActor *actor = 0;//mPhysEngine->getCharacter(ptr.getRefData().getHandle());
|
//const OEngine::Physic::PhysicActor *actor = 0;//mPhysEngine->getCharacter(ptr.getRefData().getHandle());
|
||||||
if(!actor || !actor->getCollisionMode())
|
//if(!actor || !actor->getCollisionMode())
|
||||||
return true;
|
// return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2042,10 +2040,10 @@ namespace MWWorld
|
||||||
const float *fpos = object.getRefData().getPosition().pos;
|
const float *fpos = object.getRefData().getPosition().pos;
|
||||||
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
|
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
|
||||||
|
|
||||||
const OEngine::Physic::PhysicActor *actor = 0;//mPhysEngine->getCharacter(object.getRefData().getHandle());
|
//const OEngine::Physic::PhysicActor *actor = 0;//mPhysEngine->getCharacter(object.getRefData().getHandle());
|
||||||
if (actor)
|
//if (actor)
|
||||||
{
|
{
|
||||||
pos.z += heightRatio*2*actor->getHalfExtents().z;
|
// pos.z += heightRatio*2*actor->getHalfExtents().z;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isUnderwater(object.getCell(), pos);
|
return isUnderwater(object.getCell(), pos);
|
||||||
|
@ -2071,6 +2069,8 @@ namespace MWWorld
|
||||||
// TODO: There might be better places to update PhysicActor::mOnGround.
|
// TODO: There might be better places to update PhysicActor::mOnGround.
|
||||||
bool World::isOnGround(const MWWorld::Ptr &ptr) const
|
bool World::isOnGround(const MWWorld::Ptr &ptr) const
|
||||||
{
|
{
|
||||||
|
return true;
|
||||||
|
/*
|
||||||
//RefData &refdata = ptr.getRefData();
|
//RefData &refdata = ptr.getRefData();
|
||||||
OEngine::Physic::PhysicActor *physactor = 0;//mPhysEngine->getCharacter(refdata.getHandle());
|
OEngine::Physic::PhysicActor *physactor = 0;//mPhysEngine->getCharacter(refdata.getHandle());
|
||||||
|
|
||||||
|
@ -2096,6 +2096,7 @@ namespace MWWorld
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::vanityRotateCamera(float * rot)
|
bool World::vanityRotateCamera(float * rot)
|
||||||
|
@ -2371,6 +2372,7 @@ namespace MWWorld
|
||||||
if (!targetActor.getRefData().getBaseNodeOld() || !targetActor.getRefData().getBaseNodeOld())
|
if (!targetActor.getRefData().getBaseNodeOld() || !targetActor.getRefData().getBaseNodeOld())
|
||||||
return false; // not in active cell
|
return false; // not in active cell
|
||||||
|
|
||||||
|
/*
|
||||||
OEngine::Physic::PhysicActor* actor1 = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
OEngine::Physic::PhysicActor* actor1 = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
||||||
OEngine::Physic::PhysicActor* actor2 = mPhysEngine->getCharacter(targetActor.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);
|
std::pair<std::string, float> result = mPhysEngine->rayTest(from, to,false);
|
||||||
if(result.first == "") return true;
|
if(result.first == "") return true;
|
||||||
|
*/
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float World::getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist)
|
float World::getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
|
/*
|
||||||
btVector3 btFrom(from.x, from.y, from.z);
|
btVector3 btFrom(from.x, from.y, from.z);
|
||||||
btVector3 btTo = btVector3(dir.x, dir.y, dir.z);
|
btVector3 btTo = btVector3(dir.x, dir.y, dir.z);
|
||||||
btTo.normalize();
|
btTo.normalize();
|
||||||
|
@ -2402,13 +2407,16 @@ namespace MWWorld
|
||||||
|
|
||||||
if(result.second == -1) return maxDist;
|
if(result.second == -1) return maxDist;
|
||||||
else return result.second*(btTo-btFrom).length();
|
else return result.second*(btTo-btFrom).length();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::enableActorCollision(const MWWorld::Ptr& actor, bool enable)
|
void World::enableActorCollision(const MWWorld::Ptr& actor, bool enable)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
OEngine::Physic::PhysicActor *physicActor = 0;//mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
OEngine::Physic::PhysicActor *physicActor = 0;//mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
||||||
if (physicActor)
|
if (physicActor)
|
||||||
physicActor->enableCollisionBody(enable);
|
physicActor->enableCollisionBody(enable);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::findInteriorPosition(const std::string &name, ESM::Position &pos)
|
bool World::findInteriorPosition(const std::string &name, ESM::Position &pos)
|
||||||
|
@ -3235,7 +3243,7 @@ namespace MWWorld
|
||||||
mRendering->spawnEffect(model, textureOverride, worldPos);
|
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)
|
const std::string& id, const std::string& sourceName)
|
||||||
{
|
{
|
||||||
std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply;
|
std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply;
|
||||||
|
@ -3350,9 +3358,12 @@ namespace MWWorld
|
||||||
|
|
||||||
bool World::isWalkingOnWater(const Ptr &actor)
|
bool World::isWalkingOnWater(const Ptr &actor)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
|
/*
|
||||||
OEngine::Physic::PhysicActor* physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
OEngine::Physic::PhysicActor* physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
||||||
if (physicActor && physicActor->isWalkingOnWater())
|
if (physicActor && physicActor->isWalkingOnWater())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,9 +52,9 @@ add_component_dir (nifosg
|
||||||
nifloader controller particle userdata
|
nifloader controller particle userdata
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (nifbullet
|
#add_component_dir (nifbullet
|
||||||
bulletnifloader
|
# bulletnifloader
|
||||||
)
|
# )
|
||||||
|
|
||||||
add_component_dir (to_utf8
|
add_component_dir (to_utf8
|
||||||
to_utf8
|
to_utf8
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef OPENENGINE_MYGUI_LOGLISTENER_H
|
#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_LOGLISTENER_H
|
||||||
#define OPENENGINE_MYGUI_LOGLISTENER_H
|
#define OPENMW_COMPONENTS_MYGUIPLATFORM_LOGLISTENER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
|
@ -26,11 +26,11 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <set>
|
||||||
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
|
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
|
||||||
#include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h>
|
#include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h>
|
||||||
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
||||||
#include <btBulletDynamicsCommon.h>
|
#include <btBulletDynamicsCommon.h>
|
||||||
#include <openengine/bullet/BulletShapeLoader.h>
|
|
||||||
|
|
||||||
#include <osg/Matrixf>
|
#include <osg/Matrixf>
|
||||||
|
|
||||||
|
@ -70,8 +70,7 @@ class ManualBulletShapeLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ManualBulletShapeLoader(bool showMarkers=false)
|
ManualBulletShapeLoader(bool showMarkers=false)
|
||||||
: mShape(NULL)
|
: mCompoundShape(NULL)
|
||||||
, mCompoundShape(NULL)
|
|
||||||
, mStaticMesh(NULL)
|
, mStaticMesh(NULL)
|
||||||
, mBoundingBox(NULL)
|
, mBoundingBox(NULL)
|
||||||
, mShowMarkers(showMarkers)
|
, mShowMarkers(showMarkers)
|
||||||
|
@ -91,11 +90,6 @@ public:
|
||||||
abort();
|
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:
|
private:
|
||||||
btVector3 getbtVector(Ogre::Vector3 const &v);
|
btVector3 getbtVector(Ogre::Vector3 const &v);
|
||||||
|
|
||||||
|
@ -116,7 +110,7 @@ private:
|
||||||
|
|
||||||
std::string mResourceName;
|
std::string mResourceName;
|
||||||
|
|
||||||
OEngine::Physic::BulletShape* mShape;//current shape
|
//OEngine::Physic::BulletShape* mShape;//current shape
|
||||||
|
|
||||||
btCompoundShape* mCompoundShape;
|
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