diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index d33e4e0500..16d19f65f2 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -183,6 +183,19 @@ namespace MWWorld return response; } + + void PhysicsSystem::addHeightField (float* heights, + int x, int y, float yoffset, + float triSize, float sqrtVerts) + { + mEngine->addHeightField(heights, x, y, yoffset, triSize, sqrtVerts); + } + + void PhysicsSystem::removeHeightField (int x, int y) + { + mEngine->removeHeightField(x, y); + } + void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh, const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) { diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index a2dea24925..d8e7e125aa 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -25,6 +25,12 @@ namespace MWWorld void addActor (const std::string& handle, const std::string& mesh, const Ogre::Vector3& position); + void addHeightField (float* heights, + int x, int y, float yoffset, + float triSize, float sqrtVerts); + + void removeHeightField (int x, int y); + void removeObject (const std::string& handle); void moveObject (const std::string& handle, const Ogre::Vector3& position); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index df7d20bb60..377e60b398 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -75,11 +75,14 @@ namespace MWWorld // silence annoying g++ warning - for (std::vector::const_iterator iter (functor.mHandles.begin()); - iter!=functor.mHandles.end(); ++iter){ - Ogre::SceneNode* node = *iter; + for (std::vector::const_iterator iter2 (functor.mHandles.begin()); + iter2!=functor.mHandles.end(); ++iter2){ + Ogre::SceneNode* node = *iter2; mPhysics->removeObject (node->getName()); } + + if (!((*iter)->cell->data.flags & ESM::Cell::Interior)) + mPhysics->removeHeightField( (*iter)->cell->data.gridX, (*iter)->cell->data.gridY ); } mRendering.removeCell(*iter); @@ -103,14 +106,28 @@ namespace MWWorld std::pair result = mActiveCells.insert(cell); - if(result.second){ - insertCell(*cell, mEnvironment); - mRendering.cellAdded(cell); - mRendering.configureAmbient(*cell); - mRendering.requestMap(cell); - mRendering.configureAmbient(*cell); - } + if(result.second) + { + insertCell(*cell, mEnvironment); + mRendering.cellAdded (cell); + + float verts = ESM::Land::LAND_SIZE; + float worldsize = ESM::Land::REAL_SIZE; + + if (!(cell->cell->data.flags & ESM::Cell::Interior)) + { + ESM::Land* land = mWorld->getStore().lands.search(cell->cell->data.gridX,cell->cell->data.gridY); + mPhysics->addHeightField (land->landData->heights, + cell->cell->data.gridX, cell->cell->data.gridY, + 0, ( worldsize/(verts-1) ), verts); + } + + mRendering.configureAmbient(*cell); + mRendering.requestMap(cell); + mRendering.configureAmbient(*cell); + + } } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 1c64039d4c..f8b8de89a5 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -776,7 +776,8 @@ namespace MWWorld std::vector < std::pair < float, std::string > >::iterator it = results.begin(); while (it != results.end()) { - if ( getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) + if ( (*it).second.find("HeightField") != std::string::npos // not interested in terrain + || getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) // not interested in player (unless you want to talk to yourself) { it = results.erase(it); } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index bca97c5585..2968a2f8ca 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -1,6 +1,7 @@ #include "physic.hpp" #include #include +#include #include //#include #include "CMotionState.h" @@ -10,6 +11,8 @@ #include "BtOgreGP.h" #include "BtOgreExtras.h" +#include + #define BIT(x) (1<<(x)) namespace OEngine { @@ -254,6 +257,60 @@ namespace Physic delete mShapeLoader; } + void PhysicEngine::addHeightField(float* heights, + int x, int y, float yoffset, + float triSize, float sqrtVerts) + { + const std::string name = "HeightField_" + + boost::lexical_cast(x) + "_" + + boost::lexical_cast(y); + + // find the minimum and maximum heights (needed for bullet) + float minh; + float maxh; + for (int i=0; imaxh) maxh = h; + if (hsetUseDiamondSubdivision(true); + + btVector3 scl(triSize, triSize, 1); + hfShape->setLocalScaling(scl); + + CMotionState* newMotionState = new CMotionState(this,name); + + btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape); + RigidBody* body = new RigidBody(CI,name); + body->collide = true; + body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f)); + + addRigidBody(body); + } + + void PhysicEngine::removeHeightField(int x, int y) + { + const std::string name = "HeightField_" + + boost::lexical_cast(x) + "_" + + boost::lexical_cast(y); + + removeRigidBody(name); + deleteRigidBody(name); + } + RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) { //get the shape from the .nif diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 8d177efda8..ba241b2b77 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -140,6 +140,18 @@ namespace Physic */ RigidBody* createRigidBody(std::string mesh,std::string name,float scale); + /** + * Add a HeightField to the simulation + */ + void addHeightField(float* heights, + int x, int y, float yoffset, + float triSize, float sqrtVerts); + + /** + * Remove a HeightField from the simulation + */ + void removeHeightField(int x, int y); + /** * Add a RigidBody to the simulation */