pMove in a seperate loop with fixed timestep to prevent frame-dependent movement

actorid
scrawl 13 years ago
parent 4655ec94f0
commit 86b6184f43

@ -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;
// 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<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
}
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…
Cancel
Save