mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:23:53 +00:00
pMove in a seperate loop with fixed timestep to prevent frame-dependent movement
This commit is contained in:
parent
4655ec94f0
commit
86b6184f43
5 changed files with 102 additions and 74 deletions
|
@ -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<std::string, float> 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<std::string, float> result = mEngine->rayTest(_from, _to);
|
||||
|
||||
|
||||
return !(result.first == "");
|
||||
}
|
||||
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration,
|
||||
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
|
||||
void PhysicsSystem::doPhysics(float dt, const std::vector<std::pair<std::string, Ogre::Vector3> >& 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<std::string,OEngine::Physic::PhysicActor*>::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<std::pair<std::string, Ogre::Vector3> >::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;
|
||||
|
||||
playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
|
||||
playerphysics->ps.viewangles.z = 0;
|
||||
// unused
|
||||
//Ogre::Quaternion both = yawQuat * pitchQuat;
|
||||
|
||||
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<std::string, Ogre::Vector3> > PhysicsSystem::doPhysicsFixed (
|
||||
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
|
||||
{
|
||||
Pmove(playerphysics);
|
||||
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > response;
|
||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::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
|
||||
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
response.push_back(std::pair<std::string, Ogre::Vector3>(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
|
||||
|
|
|
@ -16,8 +16,11 @@ namespace MWWorld
|
|||
PhysicsSystem (OEngine::Render::OgreRenderer &_rend);
|
||||
~PhysicsSystem ();
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > doPhysics (float duration,
|
||||
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors);
|
||||
void doPhysics(float duration, const std::vector<std::pair<std::string, Ogre::Vector3> >& 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<std::string, Ogre::Vector3> > doPhysicsFixed (const std::vector<std::pair<std::string, Ogre::Vector3> >& 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&);
|
||||
};
|
||||
|
|
|
@ -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<std::pair<std::string, Ogre::Vector3> >& actors,
|
||||
float duration)
|
||||
{
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > vectors = mPhysics->doPhysics (duration, actors);
|
||||
mPhysics->doPhysics(duration, actors);
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> >::iterator player = vectors.end();
|
||||
const int tick = 16; // 16 ms ^= 60 Hz
|
||||
|
||||
for (std::vector< std::pair<std::string, Ogre::Vector3> >::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<std::string, Ogre::Vector3> > vectors = mPhysics->doPhysicsFixed (actors);
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> >::iterator player = vectors.end();
|
||||
|
||||
for (std::vector< std::pair<std::string, Ogre::Vector3> >::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()
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <openengine/bullet/physic.hpp>
|
||||
#include <openengine/ogre/fader.hpp>
|
||||
|
||||
#include <OgreTimer.h>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Vector3;
|
||||
|
@ -100,9 +102,13 @@ namespace MWWorld
|
|||
int mNumFacing;
|
||||
std::map<std::string,std::string> 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:
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue