This commit is contained in:
vorenon 2013-03-09 02:21:54 +01:00
commit 919cc3d5ad
13 changed files with 238 additions and 444 deletions

View file

@ -32,7 +32,7 @@ namespace MWGui
, mBalanceChangePause(0.0) , mBalanceChangePause(0.0)
{ {
// items the NPC is wearing should not be for trade // items the NPC is wearing should not be for trade
mDisplayEquippedItems = true; mDisplayEquippedItems = false;
MyGUI::ScrollView* itemView; MyGUI::ScrollView* itemView;
MyGUI::Widget* containerWidget; MyGUI::Widget* containerWidget;

View file

@ -13,9 +13,9 @@ using namespace MWRender;
using namespace Ogre; using namespace Ogre;
OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) : OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) :
mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mSingleObjectQuery(0), mActiveQuery(0), mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mActiveQuery(0),
mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false), mDoQuery(0), mSunVisibility(0),
mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mWasVisible(false),
mBBNode(0), mActive(false) mBBNode(0), mActive(false)
{ {
mRendering = renderer; mRendering = renderer;
@ -26,9 +26,8 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
mSunTotalAreaQuery = renderSystem->createHardwareOcclusionQuery(); mSunTotalAreaQuery = renderSystem->createHardwareOcclusionQuery();
mSunVisibleAreaQuery = renderSystem->createHardwareOcclusionQuery(); mSunVisibleAreaQuery = renderSystem->createHardwareOcclusionQuery();
mSingleObjectQuery = renderSystem->createHardwareOcclusionQuery();
mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0) && (mSingleObjectQuery != 0); mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0);
} }
catch (Ogre::Exception e) catch (Ogre::Exception e)
{ {
@ -56,7 +55,6 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
if (sunNode) if (sunNode)
mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode(); mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode();
mObjectNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode(); mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
mBBQueryTotal = mRendering->getScene()->createBillboardSet(1); mBBQueryTotal = mRendering->getScene()->createBillboardSet(1);
@ -77,16 +75,6 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
mBBQueryVisible->setVisibilityFlags(RV_OcclusionQuery); mBBQueryVisible->setVisibilityFlags(RV_OcclusionQuery);
mBBNodeReal->attachObject(mBBQueryVisible); mBBNodeReal->attachObject(mBBQueryVisible);
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
/// \todo ideally this should occupy exactly 1 pixel on the screen
mBBQuerySingleObject->setCastShadows(false);
mBBQuerySingleObject->setDefaultDimensions(0.003, 0.003);
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
mBBQuerySingleObject->setRenderQueueGroup(RQG_OcclusionQuery);
mBBQuerySingleObject->setVisibilityFlags(RV_OcclusionQuery);
mObjectNode->attachObject(mBBQuerySingleObject);
mRendering->getScene()->addRenderObjectListener(this); mRendering->getScene()->addRenderObjectListener(this);
mRendering->getScene()->addRenderQueueListener(this); mRendering->getScene()->addRenderQueueListener(this);
mDoQuery = true; mDoQuery = true;
@ -98,9 +86,10 @@ OcclusionQuery::~OcclusionQuery()
mRendering->getScene()->removeRenderQueueListener(this); mRendering->getScene()->removeRenderQueueListener(this);
RenderSystem* renderSystem = Root::getSingleton().getRenderSystem(); RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
if (mSunTotalAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunTotalAreaQuery); if (mSunTotalAreaQuery)
if (mSunVisibleAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunVisibleAreaQuery); renderSystem->destroyHardwareOcclusionQuery(mSunTotalAreaQuery);
if (mSingleObjectQuery) renderSystem->destroyHardwareOcclusionQuery(mSingleObjectQuery); if (mSunVisibleAreaQuery)
renderSystem->destroyHardwareOcclusionQuery(mSunVisibleAreaQuery);
} }
bool OcclusionQuery::supported() bool OcclusionQuery::supported()
@ -137,13 +126,6 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass
mActiveQuery = mSunVisibleAreaQuery; mActiveQuery = mSunVisibleAreaQuery;
} }
} }
if (mDoQuery == true && rend == mBBQuerySingleObject)
{
mQuerySingleObjectStarted = true;
mQuerySingleObjectRequested = false;
mActiveQuery = mSingleObjectQuery;
mObjectWasVisible = true;
}
if (mActiveQuery != NULL) if (mActiveQuery != NULL)
mActiveQuery->beginOcclusionQuery(); mActiveQuery->beginOcclusionQuery();
@ -173,13 +155,6 @@ void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocati
mSunVisibleAreaQuery->beginOcclusionQuery(); mSunVisibleAreaQuery->beginOcclusionQuery();
mSunVisibleAreaQuery->endOcclusionQuery(); mSunVisibleAreaQuery->endOcclusionQuery();
} }
if (mObjectWasVisible == false && mDoQuery)
{
mSingleObjectQuery->beginOcclusionQuery();
mSingleObjectQuery->endOcclusionQuery();
mQuerySingleObjectStarted = true;
mQuerySingleObjectRequested = false;
}
} }
} }
@ -188,7 +163,6 @@ void OcclusionQuery::update(float duration)
if (!mSupported) return; if (!mSupported) return;
mWasVisible = false; mWasVisible = false;
mObjectWasVisible = false;
// Adjust the position of the sun billboards according to camera viewing distance // Adjust the position of the sun billboards according to camera viewing distance
// we need to do this to make sure that _everything_ can occlude the sun // we need to do this to make sure that _everything_ can occlude the sun
@ -209,8 +183,7 @@ void OcclusionQuery::update(float duration)
mDoQuery = false; mDoQuery = false;
if (!mSunTotalAreaQuery->isStillOutstanding() if (!mSunTotalAreaQuery->isStillOutstanding()
&& !mSunVisibleAreaQuery->isStillOutstanding() && !mSunVisibleAreaQuery->isStillOutstanding())
&& !mSingleObjectQuery->isStillOutstanding())
{ {
unsigned int totalPixels; unsigned int totalPixels;
unsigned int visiblePixels; unsigned int visiblePixels;
@ -229,88 +202,13 @@ void OcclusionQuery::update(float duration)
if (mSunVisibility > 1) mSunVisibility = 1; if (mSunVisibility > 1) mSunVisibility = 1;
} }
unsigned int result;
mSingleObjectQuery->pullOcclusionQuery(&result);
mTestResult = (result != 0);
mQuerySingleObjectStarted = false;
mQuerySingleObjectRequested = false;
mDoQuery = true; mDoQuery = true;
} }
} }
void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::SceneNode* object)
{
assert( !occlusionTestPending()
&& "Occlusion test still pending");
mBBQuerySingleObject->setVisible(true);
mObjectNode->setPosition(position);
// scale proportional to camera distance, in order to always give the billboard the same size in screen-space
mObjectNode->setScale( Vector3(1,1,1)*(position - mRendering->getCamera()->getRealPosition()).length() );
mQuerySingleObjectRequested = true;
mDoQuery = true;
}
bool OcclusionQuery::occlusionTestPending()
{
return (mQuerySingleObjectRequested || mQuerySingleObjectStarted);
}
void OcclusionQuery::setSunNode(Ogre::SceneNode* node) void OcclusionQuery::setSunNode(Ogre::SceneNode* node)
{ {
mSunNode = node; mSunNode = node;
if (!mBBNode) if (!mBBNode)
mBBNode = node->getParentSceneNode()->createChildSceneNode(); mBBNode = node->getParentSceneNode()->createChildSceneNode();
} }
bool OcclusionQuery::getTestResult()
{
assert( !occlusionTestPending()
&& "Occlusion test still pending");
return mTestResult;
}
bool OcclusionQuery::isPotentialOccluder(Ogre::SceneNode* node)
{
bool result = false;
for (unsigned int i=0; i < node->numAttachedObjects(); ++i)
{
MovableObject* ob = node->getAttachedObject(i);
std::string type = ob->getMovableType();
if (type == "Entity")
{
Entity* ent = static_cast<Entity*>(ob);
for (unsigned int j=0; j < ent->getNumSubEntities(); ++j)
{
// if any sub entity has a material with depth write off,
// consider the object as not an occluder
MaterialPtr mat = ent->getSubEntity(j)->getMaterial();
Material::TechniqueIterator techIt = mat->getTechniqueIterator();
while (techIt.hasMoreElements())
{
Technique* tech = techIt.getNext();
Technique::PassIterator passIt = tech->getPassIterator();
while (passIt.hasMoreElements())
{
Pass* pass = passIt.getNext();
if (pass->getDepthWriteEnabled() == false)
return false;
else
result = true;
}
}
}
}
}
return result;
}

View file

@ -40,31 +40,6 @@ namespace MWRender
*/ */
void update(float duration); void update(float duration);
/**
* request occlusion test for a billboard at the given position, omitting an entity
* @param position of the billboard in ogre coordinates
* @param object to exclude from the occluders
*/
void occlusionTest(const Ogre::Vector3& position, Ogre::SceneNode* object);
/**
* @return true if a request is still outstanding
*/
bool occlusionTestPending();
/**
* Checks if the objects held by this scenenode
* can be considered as potential occluders
* (which might not be the case when transparency is involved)
* @param Scene node
*/
bool isPotentialOccluder(Ogre::SceneNode* node);
/**
* @return true if the object tested in the last request was occluded
*/
bool getTestResult();
float getSunVisibility() const {return mSunVisibility;}; float getSunVisibility() const {return mSunVisibility;};
void setSunNode(Ogre::SceneNode* node); void setSunNode(Ogre::SceneNode* node);
@ -72,33 +47,23 @@ namespace MWRender
private: private:
Ogre::HardwareOcclusionQuery* mSunTotalAreaQuery; Ogre::HardwareOcclusionQuery* mSunTotalAreaQuery;
Ogre::HardwareOcclusionQuery* mSunVisibleAreaQuery; Ogre::HardwareOcclusionQuery* mSunVisibleAreaQuery;
Ogre::HardwareOcclusionQuery* mSingleObjectQuery;
Ogre::HardwareOcclusionQuery* mActiveQuery; Ogre::HardwareOcclusionQuery* mActiveQuery;
Ogre::BillboardSet* mBBQueryVisible; Ogre::BillboardSet* mBBQueryVisible;
Ogre::BillboardSet* mBBQueryTotal; Ogre::BillboardSet* mBBQueryTotal;
Ogre::BillboardSet* mBBQuerySingleObject;
Ogre::SceneNode* mSunNode; Ogre::SceneNode* mSunNode;
Ogre::SceneNode* mBBNode; Ogre::SceneNode* mBBNode;
Ogre::SceneNode* mBBNodeReal; Ogre::SceneNode* mBBNodeReal;
float mSunVisibility; float mSunVisibility;
Ogre::SceneNode* mObjectNode;
bool mWasVisible; bool mWasVisible;
bool mObjectWasVisible;
bool mTestResult;
bool mActive; bool mActive;
bool mSupported; bool mSupported;
bool mDoQuery; bool mDoQuery;
bool mQuerySingleObjectRequested;
bool mQuerySingleObjectStarted;
OEngine::Render::OgreRenderer* mRendering; OEngine::Render::OgreRenderer* mRendering;
protected: protected:

View file

@ -370,7 +370,9 @@ namespace MWWorld
Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
handleToMesh[node->getName()] = mesh; handleToMesh[node->getName()] = mesh;
OEngine::Physic::RigidBody* body = mEngine->createAndAdjustRigidBody(mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation()); OEngine::Physic::RigidBody* body = mEngine->createAndAdjustRigidBody(mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation());
mEngine->addRigidBody(body); OEngine::Physic::RigidBody* raycastingBody = mEngine->createAndAdjustRigidBody
(mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, true);
mEngine->addRigidBody(body, true, raycastingBody);
} }
void PhysicsSystem::addActor (const Ptr& ptr) void PhysicsSystem::addActor (const Ptr& ptr)
@ -395,9 +397,14 @@ namespace MWWorld
Ogre::SceneNode *node = ptr.getRefData().getBaseNode(); Ogre::SceneNode *node = ptr.getRefData().getBaseNode();
const std::string &handle = node->getName(); const std::string &handle = node->getName();
const Ogre::Vector3 &position = node->getPosition(); const Ogre::Vector3 &position = node->getPosition();
if(OEngine::Physic::RigidBody *body = mEngine->getRigidBody(handle)) if(OEngine::Physic::RigidBody *body = mEngine->getRigidBody(handle))
body->getWorldTransform().setOrigin(btVector3(position.x,position.y,position.z)); body->getWorldTransform().setOrigin(btVector3(position.x,position.y,position.z));
else if(OEngine::Physic::PhysicActor *physact = mEngine->getCharacter(handle))
if(OEngine::Physic::RigidBody *body = mEngine->getRigidBody(handle, true))
body->getWorldTransform().setOrigin(btVector3(position.x,position.y,position.z));
if(OEngine::Physic::PhysicActor *physact = mEngine->getCharacter(handle))
physact->setPosition(position); physact->setPosition(position);
} }
@ -418,6 +425,13 @@ namespace MWWorld
else else
mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, node->getPosition(), rotation); mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, node->getPosition(), rotation);
} }
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle, true))
{
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);
}
} }
void PhysicsSystem::scaleObject (const Ptr& ptr) void PhysicsSystem::scaleObject (const Ptr& ptr)

View file

@ -1018,42 +1018,10 @@ namespace MWWorld
mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun)); mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun));
} }
// update faced handle (object the player is looking at) updateFacedHandle ();
// this uses a mixture of raycasts and occlusion queries.
else // if (mRendering->occlusionQuerySupported())
{
MWRender::OcclusionQuery* query = mRendering->getOcclusionQuery();
if (!query->occlusionTestPending())
{
processFacedQueryResults (query);
beginFacedQueryProcess (query);
}
}
} }
void World::processFacedQueryResults (MWRender::OcclusionQuery* query) void World::updateFacedHandle ()
{
// get result of last query
if (mNumFacing == 0)
{
mFacedHandle = "";
mFacedDistance = FLT_MAX;
}
else if (mNumFacing == 1)
{
bool result = query->getTestResult();
mFacedHandle = result ? mFaced1Name : "";
mFacedDistance = result ? mFaced1Distance : FLT_MAX;
}
else if (mNumFacing == 2)
{
bool result = query->getTestResult();
mFacedHandle = result ? mFaced2Name : mFaced1Name;
mFacedDistance = result ? mFaced1Distance : mFaced1Distance;
}
}
void World::beginFacedQueryProcess (MWRender::OcclusionQuery* query)
{ {
// send new query // send new query
// figure out which object we want to test against // figure out which object we want to test against
@ -1084,95 +1052,16 @@ namespace MWWorld
if (results.size() == 0) if (results.size() == 0)
{ {
mNumFacing = 0; mFacedHandle = "";
} mFacedDistance = FLT_MAX;
else if (results.size() == 1)
{
beginSingleFacedQueryProcess (query, results);
} }
else else
{ {
beginDoubleFacedQueryProcess (query, results); mFacedHandle = results.front().second;
mFacedDistance = results.front().first;
} }
} }
void World::beginSingleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results)
{
mFaced1 = getPtrViaHandle(results.front().second);
mFaced1Name = results.front().second;
mFaced1Distance = results.front().first;
mNumFacing = 1;
btVector3 p;
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
float x, y;
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
p = mPhysics->getRayPoint(results.front().first, x, y);
}
else
p = mPhysics->getRayPoint(results.front().first);
Ogre::Vector3 pos(p.x(), p.y(), p.z());
Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode();
//std::cout << "Num facing 1 : " << mFaced1Name << std::endl;
//std::cout << "Type 1 " << mFaced1.getTypeName() << std::endl;
query->occlusionTest(pos, node);
}
void World::beginDoubleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results)
{
mFaced1Name = results.at (0).second;
mFaced2Name = results.at (1).second;
mFaced1Distance = results.at (0).first;
mFaced2Distance = results.at (1).first;
mFaced1 = getPtrViaHandle(results.at (0).second);
mFaced2 = getPtrViaHandle(results.at (1).second);
mNumFacing = 2;
btVector3 p;
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
float x, y;
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
p = mPhysics->getRayPoint(results.at (1).first, x, y);
}
else
p = mPhysics->getRayPoint(results.at (1).first);
Ogre::Vector3 pos(p.x(), p.y(), p.z());
Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode();
Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode();
// no need to test if the first node is not occluder
if (!query->isPotentialOccluder(node1) && (mFaced1.getTypeName().find("Static") == std::string::npos))
{
mFacedHandle = mFaced1Name;
mFacedDistance = mFaced1Distance;
//std::cout << "node1 Not an occluder" << std::endl;
return;
}
// no need to test if the second object is static (thus cannot be activated)
if (mFaced2.getTypeName().find("Static") != std::string::npos)
{
mFacedHandle = mFaced1Name;
mFacedDistance = mFaced1Distance;
return;
}
// work around door problems
if (mFaced1.getTypeName().find("Static") != std::string::npos
&& mFaced2.getTypeName().find("Door") != std::string::npos)
{
mFacedHandle = mFaced2Name;
mFacedDistance = mFaced2Distance;
return;
}
query->occlusionTest(pos, node2);
}
bool World::isCellExterior() const bool World::isCellExterior() const
{ {
Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); Ptr::CellStore *currentCell = mWorldScene->getCurrentCell();

View file

@ -97,10 +97,7 @@ namespace MWWorld
void updateWindowManager (); void updateWindowManager ();
void performUpdateSceneQueries (); void performUpdateSceneQueries ();
void processFacedQueryResults (MWRender::OcclusionQuery* query); void updateFacedHandle ();
void beginFacedQueryProcess (MWRender::OcclusionQuery* query);
void beginSingleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results);
void beginDoubleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results);
float getMaxActivationDistance (); float getMaxActivationDistance ();
float getNpcActivationDistance (); float getNpcActivationDistance ();

View file

@ -22,9 +22,11 @@ http://www.gnu.org/licenses/ .
*/ */
#include "bulletnifloader.hpp" #include "bulletnifloader.hpp"
#include <Ogre.h>
#include <cstdio> #include <cstdio>
#include <boost/algorithm/string.hpp>
#include "../nif/niffile.hpp" #include "../nif/niffile.hpp"
#include "../nif/node.hpp" #include "../nif/node.hpp"
#include "../nif/data.hpp" #include "../nif/data.hpp"
@ -46,6 +48,20 @@ typedef unsigned char ubyte;
namespace NifBullet namespace NifBullet
{ {
struct TriangleMeshShape : public btBvhTriangleMeshShape
{
TriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression)
: btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression)
{
}
virtual ~TriangleMeshShape()
{
delete getTriangleInfoMap();
delete m_meshInterface;
}
};
ManualBulletShapeLoader::~ManualBulletShapeLoader() ManualBulletShapeLoader::~ManualBulletShapeLoader()
{ {
} }
@ -62,10 +78,11 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
resourceName = cShape->getName(); resourceName = cShape->getName();
cShape->mCollide = false; cShape->mCollide = false;
mBoundingBox = NULL; mBoundingBox = NULL;
cShape->boxTranslation = Ogre::Vector3(0,0,0); cShape->mBoxTranslation = Ogre::Vector3(0,0,0);
cShape->boxRotation = Ogre::Quaternion::IDENTITY; cShape->mBoxRotation = Ogre::Quaternion::IDENTITY;
mHasShape = false;
mTriMesh = new btTriangleMesh(); btTriangleMesh* mesh1 = new btTriangleMesh();
// Load the NIF. TODO: Wrap this in a try-catch block once we're out // Load the NIF. TODO: Wrap this in a try-catch block once we're out
// of the early stages of development. Right now we WANT to catch // of the early stages of development. Right now we WANT to catch
@ -94,35 +111,43 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
bool hasCollisionNode = hasRootCollisionNode(node); bool hasCollisionNode = hasRootCollisionNode(node);
//do a first pass //do a first pass
handleNode(node,0,hasCollisionNode,false,false); handleNode(mesh1, node,0,hasCollisionNode,false,false);
//if collide = false, then it does a second pass which create a shape for raycasting.
if(cShape->mCollide == false)
handleNode(node,0,hasCollisionNode,false,true);
//cShape->collide = hasCollisionNode&&cShape->collide;
struct TriangleMeshShape : public btBvhTriangleMeshShape
{
TriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression)
: btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression)
{
}
virtual ~TriangleMeshShape()
{
delete getTriangleInfoMap();
delete m_meshInterface;
}
};
if(mBoundingBox != NULL) if(mBoundingBox != NULL)
cShape->Shape = mBoundingBox;
else
{ {
currentShape = new TriangleMeshShape(mTriMesh,true); cShape->mCollisionShape = mBoundingBox;
cShape->Shape = currentShape; delete mesh1;
} }
else if (mHasShape && !cShape->mIgnore && cShape->mCollide)
{
cShape->mCollisionShape = new TriangleMeshShape(mesh1,true);
}
else
delete mesh1;
//second pass which create a shape for raycasting.
resourceName = cShape->getName();
cShape->mCollide = false;
mBoundingBox = NULL;
cShape->mBoxTranslation = Ogre::Vector3(0,0,0);
cShape->mBoxRotation = Ogre::Quaternion::IDENTITY;
mHasShape = false;
btTriangleMesh* mesh2 = new btTriangleMesh();
handleNode(mesh2, node,0,hasCollisionNode,true,true);
if(mBoundingBox != NULL)
{
cShape->mRaycastingShape = mBoundingBox;
delete mesh2;
}
else if (mHasShape && !cShape->mIgnore)
{
cShape->mRaycastingShape = new TriangleMeshShape(mesh2,true);
}
else
delete mesh2;
} }
bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node) bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node)
@ -147,22 +172,26 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node)
return false; return false;
} }
void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags, void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node *node, int flags,
bool hasCollisionNode, bool isCollisionNode, bool hasCollisionNode, bool isCollisionNode,
bool raycastingOnly) bool raycasting)
{ {
// Accumulate the flags from all the child nodes. This works for all // Accumulate the flags from all the child nodes. This works for all
// the flags we currently use, at least. // the flags we currently use, at least.
flags |= node->flags; flags |= node->flags;
if (!raycasting)
isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode); isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode);
else
isCollisionNode = isCollisionNode && (node->recType != Nif::RC_RootCollisionNode);
// Marker objects: no collision // Marker objects: no collision
/// \todo don't do this in the editor /// \todo don't do this in the editor
if (node->name.find("marker") != std::string::npos) std::string nodename = node->name;
boost::algorithm::to_lower(nodename);
if (nodename.find("marker") != std::string::npos)
{ {
flags |= 0x800; return;
cShape->mIgnore = true;
} }
// Check for extra data // Check for extra data
@ -185,7 +214,7 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
// No collision. Use an internal flag setting to mark this. // No collision. Use an internal flag setting to mark this.
flags |= 0x800; flags |= 0x800;
} }
else if (sd->string == "MRK" && !raycastingOnly) else if (sd->string == "MRK")
// Marker objects. These are only visible in the // Marker objects. These are only visible in the
// editor. Until and unless we add an editor component to // editor. Until and unless we add an editor component to
// the engine, just skip this entire node. // the engine, just skip this entire node.
@ -193,20 +222,16 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
} }
} }
if(!hasCollisionNode || isCollisionNode)
{
if(node->hasBounds) if(node->hasBounds)
{ {
cShape->boxTranslation = node->boundPos; cShape->mBoxTranslation = node->boundPos;
cShape->boxRotation = node->boundRot; cShape->mBoxRotation = node->boundRot;
mBoundingBox = new btBoxShape(getbtVector(node->boundXYZ)); mBoundingBox = new btBoxShape(getbtVector(node->boundXYZ));
} }
else if( (isCollisionNode || (!hasCollisionNode && !raycasting)) && node->recType == Nif::RC_NiTriShape)
if(node->recType == Nif::RC_NiTriShape)
{ {
cShape->mCollide = !(flags&0x800); cShape->mCollide = !(flags&0x800);
handleNiTriShape(static_cast<const Nif::NiTriShape*>(node), flags, node->getWorldTransform(), raycastingOnly); handleNiTriShape(mesh, static_cast<const Nif::NiTriShape*>(node), flags, node->getWorldTransform(), raycasting);
}
} }
// For NiNodes, loop through children // For NiNodes, loop through children
@ -217,13 +242,13 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
for(size_t i = 0;i < list.length();i++) for(size_t i = 0;i < list.length();i++)
{ {
if(!list[i].empty()) if(!list[i].empty())
handleNode(list[i].getPtr(), flags, hasCollisionNode, isCollisionNode, raycastingOnly); handleNode(mesh, list[i].getPtr(), flags, hasCollisionNode, isCollisionNode, raycasting);
} }
} }
} }
void ManualBulletShapeLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform, void ManualBulletShapeLoader::handleNiTriShape(btTriangleMesh* mesh, const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform,
bool raycastingOnly) bool raycasting)
{ {
assert(shape != NULL); assert(shape != NULL);
@ -234,18 +259,19 @@ void ManualBulletShapeLoader::handleNiTriShape(const Nif::NiTriShape *shape, int
// If the object was marked "NCO" earlier, it shouldn't collide with // If the object was marked "NCO" earlier, it shouldn't collide with
// anything. So don't do anything. // anything. So don't do anything.
if (flags & 0x800 && !raycastingOnly) if ((flags & 0x800) && !raycasting)
{ {
collide = false; collide = false;
bbcollide = false; bbcollide = false;
return; return;
} }
if (!collide && !bbcollide && hidden && !raycastingOnly) if (!collide && !bbcollide && hidden && !raycasting)
// This mesh apparently isn't being used for anything, so don't // This mesh apparently isn't being used for anything, so don't
// bother setting it up. // bother setting it up.
return; return;
mHasShape = true;
const Nif::NiTriShapeData *data = shape->data.getPtr(); const Nif::NiTriShapeData *data = shape->data.getPtr();
const std::vector<Ogre::Vector3> &vertices = data->vertices; const std::vector<Ogre::Vector3> &vertices = data->vertices;
@ -255,7 +281,7 @@ void ManualBulletShapeLoader::handleNiTriShape(const Nif::NiTriShape *shape, int
Ogre::Vector3 b1 = transform*vertices[triangles[i+0]]; Ogre::Vector3 b1 = transform*vertices[triangles[i+0]];
Ogre::Vector3 b2 = transform*vertices[triangles[i+1]]; Ogre::Vector3 b2 = transform*vertices[triangles[i+1]];
Ogre::Vector3 b3 = transform*vertices[triangles[i+2]]; Ogre::Vector3 b3 = transform*vertices[triangles[i+2]];
mTriMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z)); mesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z));
} }
} }

View file

@ -24,13 +24,12 @@
#ifndef OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP #ifndef OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP
#define OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP #define OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP
#include <OgreMesh.h>
#include <cassert> #include <cassert>
#include <string> #include <string>
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h> #include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
#include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h> #include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h>
#include <btBulletDynamicsCommon.h> #include <btBulletDynamicsCommon.h>
#include "openengine/bullet/BulletShapeLoader.h" #include <openengine/bullet/BulletShapeLoader.h>
// For warning messages // For warning messages
#include <iostream> #include <iostream>
@ -83,7 +82,7 @@ private:
/** /**
*Parse a node. *Parse a node.
*/ */
void handleNode(Nif::Node const *node, int flags, bool hasCollisionNode, bool isCollisionNode, bool raycastingOnly); void handleNode(btTriangleMesh* mesh, Nif::Node const *node, int flags, bool hasCollisionNode, bool isCollisionNode, bool raycasting);
/** /**
*Helper function *Helper function
@ -93,15 +92,15 @@ private:
/** /**
*convert a NiTriShape to a bullet trishape. *convert a NiTriShape to a bullet trishape.
*/ */
void handleNiTriShape(const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform, bool raycastingOnly); void handleNiTriShape(btTriangleMesh* mesh, const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform, bool raycasting);
std::string resourceName; std::string resourceName;
std::string resourceGroup; std::string resourceGroup;
OEngine::Physic::BulletShape* cShape;//current shape OEngine::Physic::BulletShape* cShape;//current shape
btTriangleMesh *mTriMesh;
btBoxShape *mBoundingBox; btBoxShape *mBoundingBox;
btBvhTriangleMeshShape* currentShape;//the shape curently under construction
bool mHasShape;
}; };
} }

View file

@ -17,7 +17,8 @@ Ogre::Resource(creator, name, handle, group, isManual, loader)
list all the options that need to be set before loading, of which 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. we have none as such. Full details can be set through scripts.
*/ */
Shape = NULL; mCollisionShape = NULL;
mRaycastingShape = NULL;
mCollide = true; mCollide = true;
mIgnore = false; mIgnore = false;
createParamDictionary("BulletShape"); createParamDictionary("BulletShape");
@ -25,7 +26,8 @@ Ogre::Resource(creator, name, handle, group, isManual, loader)
BulletShape::~BulletShape() BulletShape::~BulletShape()
{ {
deleteShape(Shape); deleteShape(mCollisionShape);
deleteShape(mRaycastingShape);
} }
// farm out to BulletShapeLoader // farm out to BulletShapeLoader
@ -34,27 +36,28 @@ void BulletShape::loadImpl()
mLoader->loadResource(this); mLoader->loadResource(this);
} }
void BulletShape::deleteShape(btCollisionShape* mShape) void BulletShape::deleteShape(btCollisionShape* shape)
{ {
if(mShape!=NULL) if(shape!=NULL)
{ {
if(mShape->isCompound()) if(shape->isCompound())
{ {
btCompoundShape* ms = static_cast<btCompoundShape*>(Shape); btCompoundShape* ms = static_cast<btCompoundShape*>(mCollisionShape);
int a = ms->getNumChildShapes(); int a = ms->getNumChildShapes();
for(int i=0; i <a;i++) for(int i=0; i <a;i++)
{ {
deleteShape(ms->getChildShape(i)); deleteShape(ms->getChildShape(i));
} }
} }
delete mShape; delete shape;
} }
mShape = NULL; shape = NULL;
} }
void BulletShape::unloadImpl() void BulletShape::unloadImpl()
{ {
deleteShape(Shape); deleteShape(mCollisionShape);
deleteShape(mRaycastingShape);
} }
//TODO:change this? //TODO:change this?

View file

@ -22,7 +22,7 @@ protected:
void unloadImpl(); void unloadImpl();
size_t calculateSize() const; size_t calculateSize() const;
void deleteShape(btCollisionShape* mShape); void deleteShape(btCollisionShape* shape);
public: public:
@ -32,9 +32,11 @@ public:
virtual ~BulletShape(); virtual ~BulletShape();
btCollisionShape* Shape; btCollisionShape* mCollisionShape;
Ogre::Vector3 boxTranslation; btCollisionShape* mRaycastingShape;
Ogre::Quaternion boxRotation;
Ogre::Vector3 mBoxTranslation;
Ogre::Quaternion mBoxRotation;
//this flag indicate if the shape is used for collision or if it's for raycasting only. //this flag indicate if the shape is used for collision or if it's for raycasting only.
bool mCollide; bool mCollide;

View file

@ -25,11 +25,10 @@ namespace Physic
if(name == "player") if(name == "player")
collisionMode = false; collisionMode = false;
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation); mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation);
mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation, true);
Ogre::Quaternion inverse = mBoxRotation.Inverse(); Ogre::Quaternion inverse = mBoxRotation.Inverse();
mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w); mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w);
mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map mEngine->addRigidBody(mBody, false, mRaycastingBody); //Add rigid body to dynamics world, but do not add to object map
//mBody->setCollisionFlags(COL_NOTHING);
//mBody->setMas
} }
PhysicActor::~PhysicActor() PhysicActor::~PhysicActor()
@ -39,6 +38,11 @@ namespace Physic
mEngine->dynamicsWorld->removeRigidBody(mBody); mEngine->dynamicsWorld->removeRigidBody(mBody);
delete mBody; delete mBody;
} }
if(mRaycastingBody)
{
mEngine->dynamicsWorld->removeRigidBody(mRaycastingBody);
delete mRaycastingBody;
}
} }
void PhysicActor::enableCollisions(bool collision) void PhysicActor::enableCollisions(bool collision)
@ -52,13 +56,18 @@ namespace Physic
void PhysicActor::setPosition(const Ogre::Vector3 &pos) void PhysicActor::setPosition(const Ogre::Vector3 &pos)
{ {
if(pos != getPosition()) if(pos != getPosition())
{
mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation); mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
mEngine->adjustRigidBody(mRaycastingBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
}
} }
void PhysicActor::setRotation(const Ogre::Quaternion &quat) void PhysicActor::setRotation(const Ogre::Quaternion &quat)
{ {
if(!quat.equals(getRotation(), Ogre::Radian(0))){ if(!quat.equals(getRotation(), Ogre::Radian(0))){
mEngine->adjustRigidBody(mBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation); mEngine->adjustRigidBody(mBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation);
mEngine->adjustRigidBody(mRaycastingBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation);
} }
} }
@ -135,7 +144,6 @@ namespace Physic
RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name) RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name)
: btRigidBody(CI) : btRigidBody(CI)
, mName(name) , mName(name)
, mIgnore(false)
{ {
} }
@ -226,8 +234,19 @@ namespace Physic
delete hf_it->second.mBody; delete hf_it->second.mBody;
} }
RigidBodyContainer::iterator rb_it = ObjectMap.begin(); RigidBodyContainer::iterator rb_it = mCollisionObjectMap.begin();
for (; rb_it != ObjectMap.end(); ++rb_it) for (; rb_it != mCollisionObjectMap.end(); ++rb_it)
{
if (rb_it->second != NULL)
{
dynamicsWorld->removeRigidBody(rb_it->second);
delete rb_it->second;
rb_it->second = NULL;
}
}
rb_it = mRaycastingObjectMap.begin();
for (; rb_it != mRaycastingObjectMap.end(); ++rb_it)
{ {
if (rb_it->second != NULL) if (rb_it->second != NULL)
{ {
@ -243,8 +262,6 @@ namespace Physic
{ {
if (pa_it->second != NULL) if (pa_it->second != NULL)
{ {
delete pa_it->second; delete pa_it->second;
pa_it->second = NULL; pa_it->second = NULL;
} }
@ -296,7 +313,6 @@ namespace Physic
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape); btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape);
RigidBody* body = new RigidBody(CI,name); RigidBody* body = new RigidBody(CI,name);
body->mCollide = true;
body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f)); body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f));
HeightField hf; HeightField hf;
@ -347,12 +363,12 @@ namespace Physic
BulletShapeManager::getSingletonPtr()->load(outputstring,"General"); BulletShapeManager::getSingletonPtr()->load(outputstring,"General");
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General"); BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General");
adjustRigidBody(body, position, rotation, shape->boxTranslation * scale, shape->boxRotation); adjustRigidBody(body, position, rotation, shape->mBoxTranslation * scale, shape->mBoxRotation);
} }
RigidBody* PhysicEngine::createAndAdjustRigidBody(const std::string &mesh, const std::string &name, RigidBody* PhysicEngine::createAndAdjustRigidBody(const std::string &mesh, const std::string &name,
float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
Ogre::Vector3* scaledBoxTranslation, Ogre::Quaternion* boxRotation) Ogre::Vector3* scaledBoxTranslation, Ogre::Quaternion* boxRotation, bool raycasting)
{ {
std::string sid = (boost::format("%07.3f") % scale).str(); std::string sid = (boost::format("%07.3f") % scale).str();
std::string outputstring = mesh + sid; std::string outputstring = mesh + sid;
@ -361,72 +377,77 @@ namespace Physic
mShapeLoader->load(outputstring,"General"); mShapeLoader->load(outputstring,"General");
BulletShapeManager::getSingletonPtr()->load(outputstring,"General"); BulletShapeManager::getSingletonPtr()->load(outputstring,"General");
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General"); BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General");
shape->Shape->setLocalScaling( btVector3(scale,scale,scale));
if (!shape->mCollisionShape && !raycasting)
return NULL;
if (!shape->mRaycastingShape && raycasting)
return NULL;
if (!raycasting)
shape->mCollisionShape->setLocalScaling( btVector3(scale,scale,scale));
else
shape->mRaycastingShape->setLocalScaling( btVector3(scale,scale,scale));
//create the motionState //create the motionState
CMotionState* newMotionState = new CMotionState(this,name); CMotionState* newMotionState = new CMotionState(this,name);
//create the real body //create the real body
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape); btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo
(0,newMotionState, raycasting ? shape->mRaycastingShape : shape->mCollisionShape);
RigidBody* body = new RigidBody(CI,name); RigidBody* body = new RigidBody(CI,name);
body->mCollide = shape->mCollide;
body->mIgnore = shape->mIgnore;
if(scaledBoxTranslation != 0) if(scaledBoxTranslation != 0)
*scaledBoxTranslation = shape->boxTranslation * scale; *scaledBoxTranslation = shape->mBoxTranslation * scale;
if(boxRotation != 0) if(boxRotation != 0)
*boxRotation = shape->boxRotation; *boxRotation = shape->mBoxRotation;
adjustRigidBody(body, position, rotation, shape->boxTranslation * scale, shape->boxRotation); adjustRigidBody(body, position, rotation, shape->mBoxTranslation * scale, shape->mBoxRotation);
return body; return body;
} }
void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap) void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody)
{ {
if(body) if(!body && !raycastingBody)
{ return; // nothing to do
if (body->mIgnore)
return;
if(body->mCollide)
{
dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal);
}
else
{
dynamicsWorld->addRigidBody(body,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_World);
}
body->setActivationState(DISABLE_DEACTIVATION);
if(addToMap){
RigidBody* oldBody = ObjectMap[body->mName];
if (oldBody != NULL)
{
dynamicsWorld->removeRigidBody(oldBody);
delete oldBody;
}
ObjectMap[body->mName] = body; const std::string& name = (body ? body->mName : raycastingBody->mName);
}
if (body)
dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal);
if (raycastingBody)
dynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_World);
if(addToMap){
removeRigidBody(name);
deleteRigidBody(name);
if (body)
mCollisionObjectMap[name] = body;
if (raycastingBody)
mRaycastingObjectMap[name] = raycastingBody;
} }
} }
void PhysicEngine::removeRigidBody(const std::string &name) void PhysicEngine::removeRigidBody(const std::string &name)
{ {
RigidBodyContainer::iterator it = ObjectMap.find(name); RigidBodyContainer::iterator it = mCollisionObjectMap.find(name);
if (it != ObjectMap.end() ) if (it != mCollisionObjectMap.end() )
{ {
RigidBody* body = it->second; RigidBody* body = it->second;
if(body != NULL) if(body != NULL)
{ {
// broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); dynamicsWorld->removeRigidBody(body);
/*PhysicActorContainer::iterator it2 = PhysicActorMap.begin(); }
for(;it2!=PhysicActorMap.end();it++) }
it = mRaycastingObjectMap.find(name);
if (it != mRaycastingObjectMap.end() )
{
RigidBody* body = it->second;
if(body != NULL)
{ {
it2->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher);
it2->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher);
}*/
dynamicsWorld->removeRigidBody(body); dynamicsWorld->removeRigidBody(body);
} }
} }
@ -434,35 +455,42 @@ namespace Physic
void PhysicEngine::deleteRigidBody(const std::string &name) void PhysicEngine::deleteRigidBody(const std::string &name)
{ {
RigidBodyContainer::iterator it = ObjectMap.find(name); RigidBodyContainer::iterator it = mCollisionObjectMap.find(name);
if (it != ObjectMap.end() ) if (it != mCollisionObjectMap.end() )
{ {
RigidBody* body = it->second; RigidBody* body = it->second;
//btScaledBvhTriangleMeshShape* scaled = dynamic_cast<btScaledBvhTriangleMeshShape*> (body->getCollisionShape());
if(body != NULL) if(body != NULL)
{ {
delete body; delete body;
} }
/*if(scaled != NULL) mCollisionObjectMap.erase(it);
}
it = mRaycastingObjectMap.find(name);
if (it != mRaycastingObjectMap.end() )
{ {
delete scaled; RigidBody* body = it->second;
}*/
ObjectMap.erase(it); if(body != NULL)
{
delete body;
}
mRaycastingObjectMap.erase(it);
} }
} }
RigidBody* PhysicEngine::getRigidBody(const std::string &name) RigidBody* PhysicEngine::getRigidBody(const std::string &name, bool raycasting)
{ {
RigidBodyContainer::iterator it = ObjectMap.find(name); RigidBodyContainer* map = raycasting ? &mRaycastingObjectMap : &mCollisionObjectMap;
if (it != ObjectMap.end() ) RigidBodyContainer::iterator it = map->find(name);
if (it != map->end() )
{ {
RigidBody* body = ObjectMap[name]; RigidBody* body = (*map)[name];
return body; return body;
} }
else else
{ {
return 0; return NULL;
} }
} }
@ -530,7 +558,7 @@ namespace Physic
float d1 = 10000.; float d1 = 10000.;
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_Raycasting; resultCallback1.m_collisionFilterMask = CollisionType_Raycasting;
dynamicsWorld->rayTest(from, to, resultCallback1); dynamicsWorld->rayTest(from, to, resultCallback1);
if (resultCallback1.hasHit()) if (resultCallback1.hasHit())
{ {
@ -539,35 +567,16 @@ namespace Physic
d = d1; d = d1;
} }
btCollisionWorld::ClosestRayResultCallback resultCallback2(from, to);
resultCallback2.m_collisionFilterMask = CollisionType_ActorInternal|CollisionType_ActorExternal;
dynamicsWorld->rayTest(from, to, resultCallback2);
float d2 = 10000.;
if (resultCallback2.hasHit())
{
d2 = resultCallback1.m_closestHitFraction;
if(d2<=d1)
{
name = static_cast<const PairCachingGhostObject&>(*resultCallback2.m_collisionObject).mName;
d = d2;
}
}
return std::pair<std::string,float>(name,d); return std::pair<std::string,float>(name,d);
} }
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to) std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
{ {
MyRayResultCallback resultCallback1; MyRayResultCallback resultCallback1;
resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_Raycasting; resultCallback1.m_collisionFilterMask = CollisionType_Raycasting;
dynamicsWorld->rayTest(from, to, resultCallback1); dynamicsWorld->rayTest(from, to, resultCallback1);
std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results; std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results;
MyRayResultCallback resultCallback2;
resultCallback2.m_collisionFilterMask = CollisionType_ActorInternal|CollisionType_ActorExternal;
dynamicsWorld->rayTest(from, to, resultCallback2);
std::vector< std::pair<float, const btCollisionObject*> > actorResults = resultCallback2.results;
std::vector< std::pair<float, std::string> > results2; std::vector< std::pair<float, std::string> > results2;
for (std::vector< std::pair<float, const btCollisionObject*> >::iterator it=results.begin(); for (std::vector< std::pair<float, const btCollisionObject*> >::iterator it=results.begin();
@ -576,12 +585,6 @@ namespace Physic
results2.push_back( std::make_pair( (*it).first, static_cast<const RigidBody&>(*(*it).second).mName ) ); results2.push_back( std::make_pair( (*it).first, static_cast<const RigidBody&>(*(*it).second).mName ) );
} }
for (std::vector< std::pair<float, const btCollisionObject*> >::iterator it=actorResults.begin();
it != actorResults.end(); ++it)
{
results2.push_back( std::make_pair( (*it).first, static_cast<const PairCachingGhostObject&>(*(*it).second).mName ) );
}
std::sort(results2.begin(), results2.end(), MyRayResultCallback::cmp); std::sort(results2.begin(), results2.end(), MyRayResultCallback::cmp);
return results2; return results2;
@ -600,6 +603,6 @@ namespace Physic
btTransform trans; btTransform trans;
trans.setIdentity(); trans.setIdentity();
shape->Shape->getAabb(trans, min, max); shape->mCollisionShape->getAabb(trans, min, max);
} }
}} }}

View file

@ -141,6 +141,7 @@ namespace Physic
private: private:
OEngine::Physic::RigidBody* mBody; OEngine::Physic::RigidBody* mBody;
OEngine::Physic::RigidBody* mRaycastingBody;
Ogre::Vector3 mBoxScaledTranslation; Ogre::Vector3 mBoxScaledTranslation;
btQuaternion mBoxRotationInverse; btQuaternion mBoxRotationInverse;
Ogre::Quaternion mBoxRotation; Ogre::Quaternion mBoxRotation;
@ -163,10 +164,6 @@ namespace Physic
RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name);
virtual ~RigidBody(); virtual ~RigidBody();
std::string mName; std::string mName;
//is this body used for raycasting only?
bool mCollide;
bool mIgnore;
}; };
struct HeightField struct HeightField
@ -200,7 +197,7 @@ namespace Physic
*/ */
RigidBody* createAndAdjustRigidBody(const std::string &mesh, const std::string &name, RigidBody* createAndAdjustRigidBody(const std::string &mesh, const std::string &name,
float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
Ogre::Vector3* scaledBoxTranslation = 0, Ogre::Quaternion* boxRotation = 0); Ogre::Vector3* scaledBoxTranslation = 0, Ogre::Quaternion* boxRotation = 0, bool raycasting=false);
/** /**
* Adjusts a rigid body to the right position and rotation * Adjusts a rigid body to the right position and rotation
@ -228,7 +225,7 @@ namespace Physic
/** /**
* Add a RigidBody to the simulation * Add a RigidBody to the simulation
*/ */
void addRigidBody(RigidBody* body, bool addToMap = true); void addRigidBody(RigidBody* body, bool addToMap = true, RigidBody* raycastingBody = NULL);
/** /**
* Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap. * Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap.
@ -242,9 +239,8 @@ namespace Physic
/** /**
* Return a pointer to a given rigid body. * Return a pointer to a given rigid body.
* TODO:check if exist
*/ */
RigidBody* getRigidBody(const std::string &name); RigidBody* getRigidBody(const std::string &name, bool raycasting=false);
/** /**
* Create and add a character to the scene, and add it to the ActorMap. * Create and add a character to the scene, and add it to the ActorMap.
@ -322,7 +318,9 @@ namespace Physic
HeightFieldContainer mHeightFieldMap; HeightFieldContainer mHeightFieldMap;
typedef std::map<std::string,RigidBody*> RigidBodyContainer; typedef std::map<std::string,RigidBody*> RigidBodyContainer;
RigidBodyContainer ObjectMap; RigidBodyContainer mCollisionObjectMap;
RigidBodyContainer mRaycastingObjectMap;
typedef std::map<std::string, PhysicActor*> PhysicActorContainer; typedef std::map<std::string, PhysicActor*> PhysicActorContainer;
PhysicActorContainer PhysicActorMap; PhysicActorContainer PhysicActorMap;

View file

@ -27,7 +27,7 @@ void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vec
const btTransform to(btrot, btend); const btTransform to(btrot, btend);
btCollisionWorld::ClosestConvexResultCallback newTraceCallback(btstart, btend); btCollisionWorld::ClosestConvexResultCallback newTraceCallback(btstart, btend);
newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_Raycasting; newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World;
enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback); enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback);