forked from mirror/openmw-tes3mp
Merge branch 'raycasting' of https://github.com/scrawl/openmw
This commit is contained in:
commit
919cc3d5ad
13 changed files with 238 additions and 444 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue