mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 19:19:56 +00:00
Merge remote-tracking branch 'scrawl/raycasting'
This commit is contained in:
commit
2cc20c67cb
14 changed files with 241 additions and 439 deletions
|
@ -442,8 +442,6 @@ void OMW::Engine::go()
|
|||
if (!mStartupScript.empty())
|
||||
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
|
||||
|
||||
std::cout << "\nPress Q/ESC or close window to exit.\n";
|
||||
|
||||
// Start the main rendering loop
|
||||
mOgre->start();
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace MWGui
|
|||
, mBalanceChangePause(0.0)
|
||||
{
|
||||
// items the NPC is wearing should not be for trade
|
||||
mDisplayEquippedItems = true;
|
||||
mDisplayEquippedItems = false;
|
||||
|
||||
MyGUI::ScrollView* itemView;
|
||||
MyGUI::Widget* containerWidget;
|
||||
|
|
|
@ -13,9 +13,9 @@ using namespace MWRender;
|
|||
using namespace Ogre;
|
||||
|
||||
OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) :
|
||||
mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mSingleObjectQuery(0), mActiveQuery(0),
|
||||
mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false),
|
||||
mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false),
|
||||
mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mActiveQuery(0),
|
||||
mDoQuery(0), mSunVisibility(0),
|
||||
mWasVisible(false),
|
||||
mBBNode(0), mActive(false)
|
||||
{
|
||||
mRendering = renderer;
|
||||
|
@ -26,9 +26,8 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
|
||||
mSunTotalAreaQuery = renderSystem->createHardwareOcclusionQuery();
|
||||
mSunVisibleAreaQuery = renderSystem->createHardwareOcclusionQuery();
|
||||
mSingleObjectQuery = renderSystem->createHardwareOcclusionQuery();
|
||||
|
||||
mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0) && (mSingleObjectQuery != 0);
|
||||
mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0);
|
||||
}
|
||||
catch (Ogre::Exception e)
|
||||
{
|
||||
|
@ -56,7 +55,6 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
if (sunNode)
|
||||
mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode();
|
||||
|
||||
mObjectNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
||||
mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
||||
|
||||
mBBQueryTotal = mRendering->getScene()->createBillboardSet(1);
|
||||
|
@ -77,16 +75,6 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
mBBQueryVisible->setVisibilityFlags(RV_OcclusionQuery);
|
||||
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()->addRenderQueueListener(this);
|
||||
mDoQuery = true;
|
||||
|
@ -98,9 +86,10 @@ OcclusionQuery::~OcclusionQuery()
|
|||
mRendering->getScene()->removeRenderQueueListener(this);
|
||||
|
||||
RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
|
||||
if (mSunTotalAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunTotalAreaQuery);
|
||||
if (mSunVisibleAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunVisibleAreaQuery);
|
||||
if (mSingleObjectQuery) renderSystem->destroyHardwareOcclusionQuery(mSingleObjectQuery);
|
||||
if (mSunTotalAreaQuery)
|
||||
renderSystem->destroyHardwareOcclusionQuery(mSunTotalAreaQuery);
|
||||
if (mSunVisibleAreaQuery)
|
||||
renderSystem->destroyHardwareOcclusionQuery(mSunVisibleAreaQuery);
|
||||
}
|
||||
|
||||
bool OcclusionQuery::supported()
|
||||
|
@ -137,13 +126,6 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass
|
|||
mActiveQuery = mSunVisibleAreaQuery;
|
||||
}
|
||||
}
|
||||
if (mDoQuery == true && rend == mBBQuerySingleObject)
|
||||
{
|
||||
mQuerySingleObjectStarted = true;
|
||||
mQuerySingleObjectRequested = false;
|
||||
mActiveQuery = mSingleObjectQuery;
|
||||
mObjectWasVisible = true;
|
||||
}
|
||||
|
||||
if (mActiveQuery != NULL)
|
||||
mActiveQuery->beginOcclusionQuery();
|
||||
|
@ -173,13 +155,6 @@ void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocati
|
|||
mSunVisibleAreaQuery->beginOcclusionQuery();
|
||||
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;
|
||||
|
||||
mWasVisible = false;
|
||||
mObjectWasVisible = false;
|
||||
|
||||
// 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
|
||||
|
@ -209,8 +183,7 @@ void OcclusionQuery::update(float duration)
|
|||
mDoQuery = false;
|
||||
|
||||
if (!mSunTotalAreaQuery->isStillOutstanding()
|
||||
&& !mSunVisibleAreaQuery->isStillOutstanding()
|
||||
&& !mSingleObjectQuery->isStillOutstanding())
|
||||
&& !mSunVisibleAreaQuery->isStillOutstanding())
|
||||
{
|
||||
unsigned int totalPixels;
|
||||
unsigned int visiblePixels;
|
||||
|
@ -229,88 +202,13 @@ void OcclusionQuery::update(float duration)
|
|||
if (mSunVisibility > 1) mSunVisibility = 1;
|
||||
}
|
||||
|
||||
unsigned int result;
|
||||
|
||||
mSingleObjectQuery->pullOcclusionQuery(&result);
|
||||
|
||||
mTestResult = (result != 0);
|
||||
|
||||
mQuerySingleObjectStarted = false;
|
||||
mQuerySingleObjectRequested = false;
|
||||
|
||||
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)
|
||||
{
|
||||
mSunNode = node;
|
||||
if (!mBBNode)
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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;};
|
||||
|
||||
void setSunNode(Ogre::SceneNode* node);
|
||||
|
@ -72,33 +47,23 @@ namespace MWRender
|
|||
private:
|
||||
Ogre::HardwareOcclusionQuery* mSunTotalAreaQuery;
|
||||
Ogre::HardwareOcclusionQuery* mSunVisibleAreaQuery;
|
||||
Ogre::HardwareOcclusionQuery* mSingleObjectQuery;
|
||||
Ogre::HardwareOcclusionQuery* mActiveQuery;
|
||||
|
||||
Ogre::BillboardSet* mBBQueryVisible;
|
||||
Ogre::BillboardSet* mBBQueryTotal;
|
||||
Ogre::BillboardSet* mBBQuerySingleObject;
|
||||
|
||||
Ogre::SceneNode* mSunNode;
|
||||
Ogre::SceneNode* mBBNode;
|
||||
Ogre::SceneNode* mBBNodeReal;
|
||||
float mSunVisibility;
|
||||
|
||||
Ogre::SceneNode* mObjectNode;
|
||||
|
||||
bool mWasVisible;
|
||||
bool mObjectWasVisible;
|
||||
|
||||
bool mTestResult;
|
||||
|
||||
bool mActive;
|
||||
|
||||
bool mSupported;
|
||||
bool mDoQuery;
|
||||
|
||||
bool mQuerySingleObjectRequested;
|
||||
bool mQuerySingleObjectStarted;
|
||||
|
||||
OEngine::Render::OgreRenderer* mRendering;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -370,7 +370,9 @@ namespace MWWorld
|
|||
Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
|
||||
handleToMesh[node->getName()] = mesh;
|
||||
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)
|
||||
|
@ -395,9 +397,14 @@ namespace MWWorld
|
|||
Ogre::SceneNode *node = ptr.getRefData().getBaseNode();
|
||||
const std::string &handle = node->getName();
|
||||
const Ogre::Vector3 &position = node->getPosition();
|
||||
|
||||
if(OEngine::Physic::RigidBody *body = mEngine->getRigidBody(handle))
|
||||
body->getWorldTransform().setOrigin(btVector3(position.x,position.y,position.z));
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -418,6 +425,13 @@ namespace MWWorld
|
|||
else
|
||||
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)
|
||||
|
|
|
@ -1018,42 +1018,10 @@ namespace MWWorld
|
|||
mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun));
|
||||
}
|
||||
|
||||
// update faced handle (object the player is looking at)
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
updateFacedHandle ();
|
||||
}
|
||||
|
||||
void World::processFacedQueryResults (MWRender::OcclusionQuery* query)
|
||||
{
|
||||
// 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)
|
||||
void World::updateFacedHandle ()
|
||||
{
|
||||
// send new query
|
||||
// figure out which object we want to test against
|
||||
|
@ -1084,95 +1052,16 @@ namespace MWWorld
|
|||
|
||||
if (results.size() == 0)
|
||||
{
|
||||
mNumFacing = 0;
|
||||
}
|
||||
else if (results.size() == 1)
|
||||
{
|
||||
beginSingleFacedQueryProcess (query, results);
|
||||
mFacedHandle = "";
|
||||
mFacedDistance = FLT_MAX;
|
||||
}
|
||||
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
|
||||
{
|
||||
Ptr::CellStore *currentCell = mWorldScene->getCurrentCell();
|
||||
|
@ -1299,6 +1188,9 @@ namespace MWWorld
|
|||
pos.pos[0] = result.second[0];
|
||||
pos.pos[1] = result.second[1];
|
||||
pos.pos[2] = result.second[2];
|
||||
// We want only the Z part of the player's rotation
|
||||
pos.rot[0] = 0;
|
||||
pos.rot[1] = 0;
|
||||
|
||||
Ptr dropped = copyObjectToCell(object, *cell, pos);
|
||||
PCDropped(dropped);
|
||||
|
@ -1353,6 +1245,9 @@ namespace MWWorld
|
|||
|
||||
ESM::Position pos =
|
||||
actor.getRefData().getPosition();
|
||||
// We want only the Z part of the actor's rotation
|
||||
pos.rot[0] = 0;
|
||||
pos.rot[1] = 0;
|
||||
|
||||
Ogre::Vector3 orig =
|
||||
Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||
|
|
|
@ -97,10 +97,7 @@ namespace MWWorld
|
|||
|
||||
void updateWindowManager ();
|
||||
void performUpdateSceneQueries ();
|
||||
void processFacedQueryResults (MWRender::OcclusionQuery* query);
|
||||
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);
|
||||
void updateFacedHandle ();
|
||||
|
||||
float getMaxActivationDistance ();
|
||||
float getNpcActivationDistance ();
|
||||
|
|
|
@ -22,9 +22,12 @@ http://www.gnu.org/licenses/ .
|
|||
*/
|
||||
|
||||
#include "bulletnifloader.hpp"
|
||||
#include <Ogre.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "../nif/niffile.hpp"
|
||||
#include "../nif/node.hpp"
|
||||
#include "../nif/data.hpp"
|
||||
|
@ -46,6 +49,20 @@ typedef unsigned char ubyte;
|
|||
namespace NifBullet
|
||||
{
|
||||
|
||||
struct TriangleMeshShape : public btBvhTriangleMeshShape
|
||||
{
|
||||
TriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression)
|
||||
: btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~TriangleMeshShape()
|
||||
{
|
||||
delete getTriangleInfoMap();
|
||||
delete m_meshInterface;
|
||||
}
|
||||
};
|
||||
|
||||
ManualBulletShapeLoader::~ManualBulletShapeLoader()
|
||||
{
|
||||
}
|
||||
|
@ -62,10 +79,11 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
|
|||
resourceName = cShape->getName();
|
||||
cShape->mCollide = false;
|
||||
mBoundingBox = NULL;
|
||||
cShape->boxTranslation = Ogre::Vector3(0,0,0);
|
||||
cShape->boxRotation = Ogre::Quaternion::IDENTITY;
|
||||
cShape->mBoxTranslation = Ogre::Vector3(0,0,0);
|
||||
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
|
||||
// of the early stages of development. Right now we WANT to catch
|
||||
|
@ -94,35 +112,43 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
|
|||
bool hasCollisionNode = hasRootCollisionNode(node);
|
||||
|
||||
//do a first pass
|
||||
handleNode(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;
|
||||
}
|
||||
};
|
||||
handleNode(mesh1, node,0,hasCollisionNode,false,false);
|
||||
|
||||
if(mBoundingBox != NULL)
|
||||
cShape->Shape = mBoundingBox;
|
||||
else
|
||||
{
|
||||
currentShape = new TriangleMeshShape(mTriMesh,true);
|
||||
cShape->Shape = currentShape;
|
||||
cShape->mCollisionShape = mBoundingBox;
|
||||
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)
|
||||
|
@ -147,22 +173,26 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node)
|
|||
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 raycastingOnly)
|
||||
bool raycasting)
|
||||
{
|
||||
// Accumulate the flags from all the child nodes. This works for all
|
||||
// the flags we currently use, at least.
|
||||
flags |= node->flags;
|
||||
|
||||
isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode);
|
||||
if (!raycasting)
|
||||
isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode);
|
||||
else
|
||||
isCollisionNode = isCollisionNode && (node->recType != Nif::RC_RootCollisionNode);
|
||||
|
||||
// Marker objects: no collision
|
||||
/// \todo don't do this in the editor
|
||||
if (node->name.find("marker") != std::string::npos)
|
||||
std::string nodename = node->name;
|
||||
Misc::StringUtils::toLower(nodename);
|
||||
if (nodename.find("marker") != std::string::npos)
|
||||
{
|
||||
flags |= 0x800;
|
||||
cShape->mIgnore = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for extra data
|
||||
|
@ -185,7 +215,7 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
|
|||
// No collision. Use an internal flag setting to mark this.
|
||||
flags |= 0x800;
|
||||
}
|
||||
else if (sd->string == "MRK" && !raycastingOnly)
|
||||
else if (sd->string == "MRK")
|
||||
// Marker objects. These are only visible in the
|
||||
// editor. Until and unless we add an editor component to
|
||||
// the engine, just skip this entire node.
|
||||
|
@ -193,19 +223,18 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
|
|||
}
|
||||
}
|
||||
|
||||
if(!hasCollisionNode || isCollisionNode)
|
||||
if (isCollisionNode || (!hasCollisionNode && !raycasting))
|
||||
{
|
||||
if(node->hasBounds)
|
||||
{
|
||||
cShape->boxTranslation = node->boundPos;
|
||||
cShape->boxRotation = node->boundRot;
|
||||
cShape->mBoxTranslation = node->boundPos;
|
||||
cShape->mBoxRotation = node->boundRot;
|
||||
mBoundingBox = new btBoxShape(getbtVector(node->boundXYZ));
|
||||
}
|
||||
|
||||
if(node->recType == Nif::RC_NiTriShape)
|
||||
else if(node->recType == Nif::RC_NiTriShape)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,13 +246,13 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
|
|||
for(size_t i = 0;i < list.length();i++)
|
||||
{
|
||||
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,
|
||||
bool raycastingOnly)
|
||||
void ManualBulletShapeLoader::handleNiTriShape(btTriangleMesh* mesh, const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform,
|
||||
bool raycasting)
|
||||
{
|
||||
assert(shape != NULL);
|
||||
|
||||
|
@ -234,18 +263,19 @@ void ManualBulletShapeLoader::handleNiTriShape(const Nif::NiTriShape *shape, int
|
|||
|
||||
// If the object was marked "NCO" earlier, it shouldn't collide with
|
||||
// anything. So don't do anything.
|
||||
if (flags & 0x800 && !raycastingOnly)
|
||||
if ((flags & 0x800) && !raycasting)
|
||||
{
|
||||
collide = false;
|
||||
bbcollide = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!collide && !bbcollide && hidden && !raycastingOnly)
|
||||
if (!collide && !bbcollide && hidden && !raycasting)
|
||||
// This mesh apparently isn't being used for anything, so don't
|
||||
// bother setting it up.
|
||||
return;
|
||||
|
||||
mHasShape = true;
|
||||
|
||||
const Nif::NiTriShapeData *data = shape->data.getPtr();
|
||||
const std::vector<Ogre::Vector3> &vertices = data->vertices;
|
||||
|
@ -255,7 +285,7 @@ void ManualBulletShapeLoader::handleNiTriShape(const Nif::NiTriShape *shape, int
|
|||
Ogre::Vector3 b1 = transform*vertices[triangles[i+0]];
|
||||
Ogre::Vector3 b2 = transform*vertices[triangles[i+1]];
|
||||
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
|
||||
#define OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP
|
||||
|
||||
#include <OgreMesh.h>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include "openengine/bullet/BulletShapeLoader.h"
|
||||
#include <openengine/bullet/BulletShapeLoader.h>
|
||||
|
||||
// For warning messages
|
||||
#include <iostream>
|
||||
|
@ -83,7 +82,7 @@ private:
|
|||
/**
|
||||
*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
|
||||
|
@ -93,15 +92,15 @@ private:
|
|||
/**
|
||||
*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 resourceGroup;
|
||||
|
||||
OEngine::Physic::BulletShape* cShape;//current shape
|
||||
btTriangleMesh *mTriMesh;
|
||||
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
|
||||
we have none as such. Full details can be set through scripts.
|
||||
*/
|
||||
Shape = NULL;
|
||||
mCollisionShape = NULL;
|
||||
mRaycastingShape = NULL;
|
||||
mCollide = true;
|
||||
mIgnore = false;
|
||||
createParamDictionary("BulletShape");
|
||||
|
@ -25,7 +26,8 @@ Ogre::Resource(creator, name, handle, group, isManual, loader)
|
|||
|
||||
BulletShape::~BulletShape()
|
||||
{
|
||||
deleteShape(Shape);
|
||||
deleteShape(mCollisionShape);
|
||||
deleteShape(mRaycastingShape);
|
||||
}
|
||||
|
||||
// farm out to BulletShapeLoader
|
||||
|
@ -34,27 +36,28 @@ void BulletShape::loadImpl()
|
|||
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();
|
||||
for(int i=0; i <a;i++)
|
||||
{
|
||||
deleteShape(ms->getChildShape(i));
|
||||
}
|
||||
}
|
||||
delete mShape;
|
||||
delete shape;
|
||||
}
|
||||
mShape = NULL;
|
||||
shape = NULL;
|
||||
}
|
||||
|
||||
void BulletShape::unloadImpl()
|
||||
{
|
||||
deleteShape(Shape);
|
||||
deleteShape(mCollisionShape);
|
||||
deleteShape(mRaycastingShape);
|
||||
}
|
||||
|
||||
//TODO:change this?
|
||||
|
|
|
@ -22,7 +22,7 @@ protected:
|
|||
void unloadImpl();
|
||||
size_t calculateSize() const;
|
||||
|
||||
void deleteShape(btCollisionShape* mShape);
|
||||
void deleteShape(btCollisionShape* shape);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -32,9 +32,11 @@ public:
|
|||
|
||||
virtual ~BulletShape();
|
||||
|
||||
btCollisionShape* Shape;
|
||||
Ogre::Vector3 boxTranslation;
|
||||
Ogre::Quaternion boxRotation;
|
||||
btCollisionShape* mCollisionShape;
|
||||
btCollisionShape* mRaycastingShape;
|
||||
|
||||
Ogre::Vector3 mBoxTranslation;
|
||||
Ogre::Quaternion mBoxRotation;
|
||||
//this flag indicate if the shape is used for collision or if it's for raycasting only.
|
||||
bool mCollide;
|
||||
|
||||
|
|
|
@ -25,11 +25,10 @@ namespace Physic
|
|||
if(name == "player")
|
||||
collisionMode = false;
|
||||
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();
|
||||
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
|
||||
//mBody->setCollisionFlags(COL_NOTHING);
|
||||
//mBody->setMas
|
||||
mEngine->addRigidBody(mBody, false, mRaycastingBody); //Add rigid body to dynamics world, but do not add to object map
|
||||
}
|
||||
|
||||
PhysicActor::~PhysicActor()
|
||||
|
@ -39,6 +38,11 @@ namespace Physic
|
|||
mEngine->dynamicsWorld->removeRigidBody(mBody);
|
||||
delete mBody;
|
||||
}
|
||||
if(mRaycastingBody)
|
||||
{
|
||||
mEngine->dynamicsWorld->removeRigidBody(mRaycastingBody);
|
||||
delete mRaycastingBody;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicActor::enableCollisions(bool collision)
|
||||
|
@ -52,13 +56,18 @@ namespace Physic
|
|||
void PhysicActor::setPosition(const Ogre::Vector3 &pos)
|
||||
{
|
||||
if(pos != getPosition())
|
||||
{
|
||||
mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
|
||||
mEngine->adjustRigidBody(mRaycastingBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicActor::setRotation(const Ogre::Quaternion &quat)
|
||||
{
|
||||
if(!quat.equals(getRotation(), Ogre::Radian(0))){
|
||||
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)
|
||||
: btRigidBody(CI)
|
||||
, mName(name)
|
||||
, mIgnore(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -226,8 +234,19 @@ namespace Physic
|
|||
delete hf_it->second.mBody;
|
||||
}
|
||||
|
||||
RigidBodyContainer::iterator rb_it = ObjectMap.begin();
|
||||
for (; rb_it != ObjectMap.end(); ++rb_it)
|
||||
RigidBodyContainer::iterator rb_it = mCollisionObjectMap.begin();
|
||||
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)
|
||||
{
|
||||
|
@ -243,8 +262,6 @@ namespace Physic
|
|||
{
|
||||
if (pa_it->second != NULL)
|
||||
{
|
||||
|
||||
|
||||
delete pa_it->second;
|
||||
pa_it->second = NULL;
|
||||
}
|
||||
|
@ -296,7 +313,6 @@ namespace Physic
|
|||
|
||||
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape);
|
||||
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));
|
||||
|
||||
HeightField hf;
|
||||
|
@ -347,12 +363,12 @@ namespace Physic
|
|||
BulletShapeManager::getSingletonPtr()->load(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,
|
||||
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 outputstring = mesh + sid;
|
||||
|
@ -361,72 +377,77 @@ namespace Physic
|
|||
mShapeLoader->load(outputstring,"General");
|
||||
BulletShapeManager::getSingletonPtr()->load(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
|
||||
CMotionState* newMotionState = new CMotionState(this,name);
|
||||
|
||||
//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);
|
||||
body->mCollide = shape->mCollide;
|
||||
body->mIgnore = shape->mIgnore;
|
||||
|
||||
if(scaledBoxTranslation != 0)
|
||||
*scaledBoxTranslation = shape->boxTranslation * scale;
|
||||
*scaledBoxTranslation = shape->mBoxTranslation * scale;
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap)
|
||||
void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody)
|
||||
{
|
||||
if(body)
|
||||
{
|
||||
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;
|
||||
}
|
||||
if(!body && !raycastingBody)
|
||||
return; // nothing to do
|
||||
|
||||
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)
|
||||
{
|
||||
RigidBodyContainer::iterator it = ObjectMap.find(name);
|
||||
if (it != ObjectMap.end() )
|
||||
RigidBodyContainer::iterator it = mCollisionObjectMap.find(name);
|
||||
if (it != mCollisionObjectMap.end() )
|
||||
{
|
||||
RigidBody* body = it->second;
|
||||
if(body != NULL)
|
||||
{
|
||||
dynamicsWorld->removeRigidBody(body);
|
||||
}
|
||||
}
|
||||
it = mRaycastingObjectMap.find(name);
|
||||
if (it != mRaycastingObjectMap.end() )
|
||||
{
|
||||
RigidBody* body = it->second;
|
||||
if(body != NULL)
|
||||
{
|
||||
// broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher);
|
||||
/*PhysicActorContainer::iterator it2 = PhysicActorMap.begin();
|
||||
for(;it2!=PhysicActorMap.end();it++)
|
||||
{
|
||||
it2->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher);
|
||||
it2->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher);
|
||||
}*/
|
||||
dynamicsWorld->removeRigidBody(body);
|
||||
}
|
||||
}
|
||||
|
@ -434,35 +455,42 @@ namespace Physic
|
|||
|
||||
void PhysicEngine::deleteRigidBody(const std::string &name)
|
||||
{
|
||||
RigidBodyContainer::iterator it = ObjectMap.find(name);
|
||||
if (it != ObjectMap.end() )
|
||||
RigidBodyContainer::iterator it = mCollisionObjectMap.find(name);
|
||||
if (it != mCollisionObjectMap.end() )
|
||||
{
|
||||
RigidBody* body = it->second;
|
||||
//btScaledBvhTriangleMeshShape* scaled = dynamic_cast<btScaledBvhTriangleMeshShape*> (body->getCollisionShape());
|
||||
|
||||
if(body != NULL)
|
||||
{
|
||||
delete body;
|
||||
}
|
||||
/*if(scaled != NULL)
|
||||
mCollisionObjectMap.erase(it);
|
||||
}
|
||||
it = mRaycastingObjectMap.find(name);
|
||||
if (it != mRaycastingObjectMap.end() )
|
||||
{
|
||||
RigidBody* body = it->second;
|
||||
|
||||
if(body != NULL)
|
||||
{
|
||||
delete scaled;
|
||||
}*/
|
||||
ObjectMap.erase(it);
|
||||
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);
|
||||
if (it != ObjectMap.end() )
|
||||
RigidBodyContainer* map = raycasting ? &mRaycastingObjectMap : &mCollisionObjectMap;
|
||||
RigidBodyContainer::iterator it = map->find(name);
|
||||
if (it != map->end() )
|
||||
{
|
||||
RigidBody* body = ObjectMap[name];
|
||||
RigidBody* body = (*map)[name];
|
||||
return body;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,7 +558,7 @@ namespace Physic
|
|||
|
||||
float d1 = 10000.;
|
||||
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
||||
resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_Raycasting;
|
||||
resultCallback1.m_collisionFilterMask = CollisionType_Raycasting;
|
||||
dynamicsWorld->rayTest(from, to, resultCallback1);
|
||||
if (resultCallback1.hasHit())
|
||||
{
|
||||
|
@ -539,35 +567,16 @@ namespace Physic
|
|||
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);
|
||||
}
|
||||
|
||||
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
|
||||
{
|
||||
MyRayResultCallback resultCallback1;
|
||||
resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_Raycasting;
|
||||
resultCallback1.m_collisionFilterMask = CollisionType_Raycasting;
|
||||
dynamicsWorld->rayTest(from, to, resultCallback1);
|
||||
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;
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return results2;
|
||||
|
@ -600,6 +603,6 @@ namespace Physic
|
|||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
|
||||
shape->Shape->getAabb(trans, min, max);
|
||||
shape->mCollisionShape->getAabb(trans, min, max);
|
||||
}
|
||||
}}
|
||||
|
|
|
@ -141,6 +141,7 @@ namespace Physic
|
|||
private:
|
||||
|
||||
OEngine::Physic::RigidBody* mBody;
|
||||
OEngine::Physic::RigidBody* mRaycastingBody;
|
||||
Ogre::Vector3 mBoxScaledTranslation;
|
||||
btQuaternion mBoxRotationInverse;
|
||||
Ogre::Quaternion mBoxRotation;
|
||||
|
@ -163,10 +164,6 @@ namespace Physic
|
|||
RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name);
|
||||
virtual ~RigidBody();
|
||||
std::string mName;
|
||||
|
||||
//is this body used for raycasting only?
|
||||
bool mCollide;
|
||||
bool mIgnore;
|
||||
};
|
||||
|
||||
struct HeightField
|
||||
|
@ -200,7 +197,7 @@ namespace Physic
|
|||
*/
|
||||
RigidBody* createAndAdjustRigidBody(const std::string &mesh, const std::string &name,
|
||||
float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
|
||||
Ogre::Vector3* scaledBoxTranslation = 0, Ogre::Quaternion* boxRotation = 0);
|
||||
Ogre::Vector3* scaledBoxTranslation = 0, Ogre::Quaternion* boxRotation = 0, bool raycasting=false);
|
||||
|
||||
/**
|
||||
* Adjusts a rigid body to the right position and rotation
|
||||
|
@ -228,7 +225,7 @@ namespace Physic
|
|||
/**
|
||||
* 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.
|
||||
|
@ -242,9 +239,8 @@ namespace Physic
|
|||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -322,7 +318,9 @@ namespace Physic
|
|||
HeightFieldContainer mHeightFieldMap;
|
||||
|
||||
typedef std::map<std::string,RigidBody*> RigidBodyContainer;
|
||||
RigidBodyContainer ObjectMap;
|
||||
RigidBodyContainer mCollisionObjectMap;
|
||||
|
||||
RigidBodyContainer mRaycastingObjectMap;
|
||||
|
||||
typedef std::map<std::string, PhysicActor*> PhysicActorContainer;
|
||||
PhysicActorContainer PhysicActorMap;
|
||||
|
|
|
@ -27,7 +27,7 @@ void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vec
|
|||
const btTransform to(btrot, 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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue