diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 7fe83eeab..fb13e37c6 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -21,27 +21,24 @@ namespace MWWorld PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) : mRender(_rend), mEngine(0), mFreeFly (true) { - + playerphysics = new playerMove; // Create physics. shapeLoader is deleted by the physic engine NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); mEngine = new OEngine::Physic::PhysicEngine(shapeLoader); playerphysics->mEngine = mEngine; - - - } PhysicsSystem::~PhysicsSystem() { delete mEngine; - + } OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine() { return mEngine; } - + std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world) { std::string handle = ""; @@ -74,7 +71,7 @@ namespace MWWorld if(hasWater){ playerphysics->waterHeight = waterHeight; } - + } btVector3 PhysicsSystem::getRayPoint(float extent) @@ -86,26 +83,23 @@ namespace MWWorld btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); return result; } - + bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) { btVector3 _from, _to; _from = btVector3(from.x, from.y, from.z); _to = btVector3(to.x, to.y, to.z); - + std::pair result = mEngine->rayTest(_from, _to); - + return !(result.first == ""); } - - std::vector< std::pair > PhysicsSystem::doPhysics (float duration, - const std::vector >& actors) + void PhysicsSystem::doPhysics(float dt, const std::vector >& actors) { //set the DebugRenderingMode. To disable it,set it to 0 //eng->setDebugRenderingMode(1); - - + //set the walkdirection to 0 (no movement) for every actor) for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) { @@ -117,8 +111,7 @@ namespace MWWorld pm_ref.rightmove = 0; pm_ref.forwardmove = 0; pm_ref.upmove = 0; - - + //playerphysics->ps.move_type = PM_NOCLIP; for (std::vector >::const_iterator iter (actors.begin()); iter!=actors.end(); ++iter) @@ -133,29 +126,24 @@ namespace MWWorld Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); Ogre::Quaternion yawQuat = yawNode->getOrientation(); - Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); + Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); + + // unused + //Ogre::Quaternion both = yawQuat * pitchQuat; - // unused - //Ogre::Quaternion both = yawQuat * pitchQuat; - - playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); - playerphysics->ps.viewangles.z = 0; + playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); + playerphysics->ps.viewangles.z = 0; playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90; - - - if(mFreeFly) { - Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); pm_ref.rightmove = -dir1.x; pm_ref.forwardmove = dir1.z; pm_ref.upmove = dir1.y; - - + //std::cout << "Current angle" << yawQuat.getYaw().valueDegrees() - 90<< "\n"; //playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); //std::cout << "Pitch: " << yawQuat.getPitch() << "Yaw:" << yawQuat.getYaw() << "Roll: " << yawQuat.getRoll() << "\n"; @@ -163,46 +151,50 @@ namespace MWWorld } else { - + Ogre::Quaternion quat = yawNode->getOrientation(); Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); - + pm_ref.rightmove = -dir1.x; pm_ref.forwardmove = dir1.z; pm_ref.upmove = dir1.y; - - - + + + dir = 0.025*(quat*dir1); } - + //set the walk direction act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y)); } - mEngine->stepSimulation(duration); - Pmove(playerphysics); + mEngine->stepSimulation(dt); + } + + std::vector< std::pair > PhysicsSystem::doPhysicsFixed ( + const std::vector >& actors) + { + Pmove(playerphysics); - std::vector< std::pair > response; for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) { btVector3 newPos = it->second->getPosition(); - + Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z()); - if(it->first == "player"){ - - coord = playerphysics->ps.origin; - //std::cout << "ZCoord: " << coord.z << "\n"; - //std::cout << "Coord" << coord << "\n"; - //coord = Ogre::Vector3(coord.x, coord.z, coord.y); //x, z, -y - - } - - + if(it->first == "player"){ + + coord = playerphysics->ps.origin; + //std::cout << "ZCoord: " << coord.z << "\n"; + //std::cout << "Coord" << coord << "\n"; + //coord = Ogre::Vector3(coord.x, coord.z, coord.y); //x, z, -y + + } + + response.push_back(std::pair(it->first, coord)); } - + return response; } @@ -260,7 +252,14 @@ namespace MWWorld { // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow // start positions others than 0, 0, 0 - act->setPosition(btVector3(position.x,position.y,position.z)); + if (handle == "player") + { + playerphysics->ps.origin = position; + } + else + { + act->setPosition(btVector3(position.x,position.y,position.z)); + } } } @@ -316,7 +315,7 @@ namespace MWWorld } void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){ - + Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); // unused diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index cb559f000..1af6bcca2 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -16,8 +16,11 @@ namespace MWWorld PhysicsSystem (OEngine::Render::OgreRenderer &_rend); ~PhysicsSystem (); - std::vector< std::pair > doPhysics (float duration, - const std::vector >& actors); + void doPhysics(float duration, const std::vector >& actors); + ///< do physics with dt - Usage: first call doPhysics with frame dt, then call doPhysicsFixed as often as time steps have passed + + std::vector< std::pair > doPhysicsFixed (const std::vector >& actors); + ///< do physics with fixed timestep - Usage: first call doPhysics with frame dt, then call doPhysicsFixed as often as time steps have passed void addObject (const std::string& handle, const std::string& mesh, const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position); @@ -55,7 +58,7 @@ namespace MWWorld void insertActorPhysics(const MWWorld::Ptr&, std::string model); OEngine::Physic::PhysicEngine* getEngine(); - + void setCurrentWater(bool hasWater, int waterHeight); private: @@ -64,7 +67,6 @@ namespace MWWorld bool mFreeFly; playerMove* playerphysics; - PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); }; diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 04bc999a0..adbdaece6 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -215,6 +215,7 @@ namespace MWWorld setFallbackValues(fallbackMap); + lastTick = mTimer.getMilliseconds(); } @@ -559,8 +560,9 @@ namespace MWWorld } } - void World::moveObjectImp (Ptr ptr, float x, float y, float z) + bool World::moveObjectImp (Ptr ptr, float x, float y, float z) { + bool ret = false; ptr.getRefData().getPosition().pos[0] = x; ptr.getRefData().getPosition().pos[1] = y; ptr.getRefData().getPosition().pos[2] = z; @@ -582,6 +584,7 @@ namespace MWWorld if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY) { mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getRefData().getPosition(), false); + ret = true; } } @@ -591,6 +594,8 @@ namespace MWWorld /// \todo cell change for non-player ref mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z)); + + return ret; } void World::moveObject (Ptr ptr, float x, float y, float z) @@ -632,29 +637,45 @@ namespace MWWorld void World::doPhysics (const std::vector >& actors, float duration) { - std::vector< std::pair > vectors = mPhysics->doPhysics (duration, actors); + mPhysics->doPhysics(duration, actors); - std::vector< std::pair >::iterator player = vectors.end(); + const int tick = 16; // 16 ms ^= 60 Hz - for (std::vector< std::pair >::iterator it = vectors.begin(); - it!= vectors.end(); ++it) + // Game clock part of the loop, contains everything that has to be executed in a fixed timestep + long long dt = mTimer.getMilliseconds() - lastTick; + if (dt >= 100) dt = 100; // throw away wall clock time if necessary to keep the framerate above the minimum of 10 fps + while (dt >= tick) { - if (it->first=="player") + dt -= tick; + lastTick += tick; + + std::vector< std::pair > vectors = mPhysics->doPhysicsFixed (actors); + + std::vector< std::pair >::iterator player = vectors.end(); + + for (std::vector< std::pair >::iterator it = vectors.begin(); + it!= vectors.end(); ++it) { - player = it; + if (it->first=="player") + { + player = it; + } + else + { + MWWorld::Ptr ptr = getPtrViaHandle (it->first); + moveObjectImp (ptr, it->second.x, it->second.y, it->second.z); + } } - else + + // Make sure player is moved last (otherwise the cell might change in the middle of an update + // loop) + if (player!=vectors.end()) { - MWWorld::Ptr ptr = getPtrViaHandle (it->first); - moveObjectImp (ptr, it->second.x, it->second.y, it->second.z); + if (moveObjectImp (getPtrViaHandle (player->first), + player->second.x, player->second.y, player->second.z) == true) + return; // abort the current loop if the cell has changed } } - - // Make sure player is moved last (otherwise the cell might change in the middle of an update - // loop) - if (player!=vectors.end()) - moveObjectImp (getPtrViaHandle (player->first), - player->second.x, player->second.y, player->second.z); } bool World::toggleCollisionMode() diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 77e5bcef6..7359f8b90 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -22,6 +22,8 @@ #include #include +#include + namespace Ogre { class Vector3; @@ -100,9 +102,13 @@ namespace MWWorld int mNumFacing; std::map mFallback; + unsigned long lastTick; + Ogre::Timer mTimer; + int getDaysPerMonth (int month) const; - void moveObjectImp (Ptr ptr, float x, float y, float z); + bool moveObjectImp (Ptr ptr, float x, float y, float z); + ///< @return true if the active cell (cell player is in) changed public: diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 3d507d4ee..42853d8cf 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -393,7 +393,7 @@ namespace Physic void PhysicEngine::stepSimulation(double deltaT) { - dynamicsWorld->stepSimulation(deltaT,10); + dynamicsWorld->stepSimulation(deltaT,10, 1/60.0); if(isDebugCreated) { mDebugDrawer->step();