1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-20 07:23:51 +00:00

Merge remote branch 'scrawl/physicsaedra2'

This commit is contained in:
Marc Zinnschlag 2012-05-03 14:59:36 +02:00
commit 1149e282b8
20 changed files with 2789 additions and 81 deletions

View file

@ -122,6 +122,10 @@ set(OENGINE_BULLET
${LIBDIR}/openengine/bullet/physic.hpp ${LIBDIR}/openengine/bullet/physic.hpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp ${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.h ${LIBDIR}/openengine/bullet/BulletShapeLoader.h
${LIBDIR}/openengine/bullet/pmove.cpp
${LIBDIR}/openengine/bullet/pmove.h
${LIBDIR}/openengine/bullet/trace.cpp
${LIBDIR}/openengine/bullet/trace.h
) )

View file

@ -148,7 +148,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
, mNewGame (false) , mNewGame (false)
, mUseSound (true) , mUseSound (true)
, mCompileAll (false) , mCompileAll (false)
, mFocusTDiff (0)
, mScriptContext (0) , mScriptContext (0)
, mFSStrict (false) , mFSStrict (false)
, mCfgMgr(configurationManager) , mCfgMgr(configurationManager)
@ -263,7 +262,6 @@ void OMW::Engine::setNewGame(bool newGame)
void OMW::Engine::go() void OMW::Engine::go()
{ {
mFocusTDiff = 0;
assert (!mCellName.empty()); assert (!mCellName.empty());
assert (!mMaster.empty()); assert (!mMaster.empty());
assert (!mOgre); assert (!mOgre);

View file

@ -74,7 +74,6 @@ namespace OMW
bool mNewGame; bool mNewGame;
bool mUseSound; bool mUseSound;
bool mCompileAll; bool mCompileAll;
float mFocusTDiff;
std::string mFocusName; std::string mFocusName;
std::map<std::string,std::string> mFallbackMap; std::map<std::string,std::string> mFallbackMap;

View file

@ -287,11 +287,12 @@ namespace MWClass
{ {
Ogre::Vector3 vector (0, 0, 0); Ogre::Vector3 vector (0, 0, 0);
vector.x = - getMovementSettings (ptr).mLeftRight * 200; vector.x = - getMovementSettings (ptr).mLeftRight * 127;
vector.y = getMovementSettings (ptr).mForwardBackward * 200; vector.y = getMovementSettings (ptr).mForwardBackward * 127;
vector.z = getMovementSettings(ptr).mUpDown * 127;
if (getStance (ptr, Run, false)) //if (getStance (ptr, Run, false))
vector *= 2; // vector *= 2;
return vector; return vector;
} }

View file

@ -60,6 +60,7 @@ namespace MWInput
A_CycleWeaponRight, A_CycleWeaponRight,
A_ToggleSneak, //Toggles Sneak, add Push-Sneak later A_ToggleSneak, //Toggles Sneak, add Push-Sneak later
A_ToggleWalk, //Toggle Walking/Running A_ToggleWalk, //Toggle Walking/Running
A_Crouch,
A_QuickSave, A_QuickSave,
A_QuickLoad, A_QuickLoad,
@ -310,6 +311,9 @@ namespace MWInput
poller.bind(A_MoveRight, KC_D); poller.bind(A_MoveRight, KC_D);
poller.bind(A_MoveForward, KC_W); poller.bind(A_MoveForward, KC_W);
poller.bind(A_MoveBackward, KC_S); poller.bind(A_MoveBackward, KC_S);
poller.bind(A_Jump, KC_E);
poller.bind(A_Crouch, KC_LCONTROL);
} }
//NOTE: Used to check for movement keys //NOTE: Used to check for movement keys
@ -356,6 +360,13 @@ namespace MWInput
} }
else else
player.setForwardBackward (0); player.setForwardBackward (0);
if (poller.isDown(A_Jump))
player.setUpDown (1);
else if (poller.isDown(A_Crouch))
player.setUpDown (-1);
else
player.setUpDown (0);
} }
// Switch between gui modes. Besides controlling the Gui windows // Switch between gui modes. Besides controlling the Gui windows

View file

@ -8,8 +8,9 @@ namespace MWMechanics
{ {
signed char mLeftRight; // 1: wants to move left, -1: wants to move right signed char mLeftRight; // 1: wants to move left, -1: wants to move right
signed char mForwardBackward; // 1:wants to move forward, -1: wants to move backward signed char mForwardBackward; // 1:wants to move forward, -1: wants to move backward
signed char mUpDown;
Movement() : mLeftRight (0), mForwardBackward (0) {} Movement() : mLeftRight (0), mForwardBackward (0), mUpDown(0) {}
}; };
} }

View file

@ -53,9 +53,11 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_)
Ogre::SceneNode* insert = cellnode->createChildSceneNode(); Ogre::SceneNode* insert = cellnode->createChildSceneNode();
const float *f = ptr.getRefData().getPosition().pos; const float *f = ptr.getRefData().getPosition().pos;
insert->setPosition(f[0], f[1], f[2]); insert->setPosition(f[0], f[1], f[2]);
insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale); insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale);
// Convert MW rotation to a quaternion: // Convert MW rotation to a quaternion:
f = ptr.getCellRef().pos.rot; f = ptr.getCellRef().pos.rot;

View file

@ -22,10 +22,11 @@ namespace MWWorld
mRender(_rend), mEngine(0), mFreeFly (true) mRender(_rend), mEngine(0), mFreeFly (true)
{ {
playerphysics = new playerMove;
// Create physics. shapeLoader is deleted by the physic engine // Create physics. shapeLoader is deleted by the physic engine
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader();
mEngine = new OEngine::Physic::PhysicEngine(shapeLoader); mEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
playerphysics->mEngine = mEngine;
} }
PhysicsSystem::~PhysicsSystem() PhysicsSystem::~PhysicsSystem()
@ -65,6 +66,13 @@ namespace MWWorld
return mEngine->rayTest2(from,to); return mEngine->rayTest2(from,to);
} }
void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight){
playerphysics->hasWater = hasWater;
if(hasWater){
playerphysics->waterHeight = waterHeight;
}
}
btVector3 PhysicsSystem::getRayPoint(float extent) btVector3 PhysicsSystem::getRayPoint(float extent)
{ {
@ -87,22 +95,22 @@ namespace MWWorld
return !(result.first == ""); return !(result.first == "");
} }
void PhysicsSystem::doPhysics(float dt, const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration,
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
{ {
//set the DebugRenderingMode. To disable it,set it to 0 //set the DebugRenderingMode. To disable it,set it to 0
//eng->setDebugRenderingMode(1); //eng->setDebugRenderingMode(1);
//set the walkdirection to 0 (no movement) for every actor) //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++) for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
{ {
OEngine::Physic::PhysicActor* act = it->second; OEngine::Physic::PhysicActor* act = it->second;
act->setWalkDirection(btVector3(0,0,0)); act->setWalkDirection(btVector3(0,0,0));
} }
playerMove::playercmd& pm_ref = playerphysics->cmd;
pm_ref.rightmove = 0;
pm_ref.forwardmove = 0;
pm_ref.upmove = 0;
//playerphysics->ps.move_type = PM_NOCLIP; //playerphysics->ps.move_type = PM_NOCLIP;
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin()); for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
@ -119,18 +127,21 @@ namespace MWWorld
Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); Ogre::Node* pitchNode = yawNode->getChildIterator().getNext();
Ogre::Quaternion yawQuat = yawNode->getOrientation(); Ogre::Quaternion yawQuat = yawNode->getOrientation();
Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); Ogre::Quaternion pitchQuat = pitchNode->getOrientation();
Ogre::Quaternion both = yawQuat * pitchQuat;
// unused
//Ogre::Quaternion both = yawQuat * pitchQuat;
//playerphysics->ps.viewangles.z = both.getPitch().valueDegrees(); playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
playerphysics->ps.viewangles.z = 0;
playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90;
if(mFreeFly) if(mFreeFly)
{ {
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); 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"; //std::cout << "Current angle" << yawQuat.getYaw().valueDegrees() - 90<< "\n";
@ -140,9 +151,15 @@ namespace MWWorld
} }
else else
{ {
Ogre::Quaternion quat = yawNode->getOrientation(); Ogre::Quaternion quat = yawNode->getOrientation();
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); 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); dir = 0.025*(quat*dir1);
} }
@ -151,7 +168,13 @@ namespace MWWorld
//set the walk direction //set the walk direction
act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y)); act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y));
} }
mEngine->stepSimulation(duration); 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; 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++) for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
@ -159,12 +182,34 @@ namespace MWWorld
btVector3 newPos = it->second->getPosition(); btVector3 newPos = it->second->getPosition();
Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z()); 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)); response.push_back(std::pair<std::string, Ogre::Vector3>(it->first, coord));
} }
return response; 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, void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh,
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position)
{ {
@ -207,9 +252,16 @@ namespace MWWorld
{ {
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
// start positions others than 0, 0, 0 // start positions others than 0, 0, 0
if (handle == "player")
{
playerphysics->ps.origin = position;
}
else
{
act->setPosition(btVector3(position.x,position.y,position.z)); act->setPosition(btVector3(position.x,position.y,position.z));
} }
} }
}
void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation) void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation)
{ {
@ -228,6 +280,11 @@ namespace MWWorld
bool PhysicsSystem::toggleCollisionMode() bool PhysicsSystem::toggleCollisionMode()
{ {
if(playerphysics->ps.move_type==PM_NOCLIP)
playerphysics->ps.move_type=PM_NORMAL;
else
playerphysics->ps.move_type=PM_NOCLIP;
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
{ {
if (it->first=="player") if (it->first=="player")
@ -258,7 +315,12 @@ namespace MWWorld
} }
void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){ void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){
Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
// unused
//Ogre::Vector3 objPos = node->getPosition();
addObject (node->getName(), model, node->getOrientation(), addObject (node->getName(), model, node->getOrientation(),
node->getScale().x, node->getPosition()); node->getScale().x, node->getPosition());
} }

View file

@ -5,6 +5,7 @@
#include <openengine/ogre/renderer.hpp> #include <openengine/ogre/renderer.hpp>
#include <openengine/bullet/physic.hpp> #include <openengine/bullet/physic.hpp>
#include "ptr.hpp" #include "ptr.hpp"
#include <openengine/bullet/pmove.h>
namespace MWWorld namespace MWWorld
{ {
@ -15,8 +16,11 @@ namespace MWWorld
PhysicsSystem (OEngine::Render::OgreRenderer &_rend); PhysicsSystem (OEngine::Render::OgreRenderer &_rend);
~PhysicsSystem (); ~PhysicsSystem ();
std::vector< std::pair<std::string, Ogre::Vector3> > doPhysics (float duration, void doPhysics(float duration, const std::vector<std::pair<std::string, Ogre::Vector3> >& actors);
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, void addObject (const std::string& handle, const std::string& mesh,
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position); const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position);
@ -24,6 +28,12 @@ namespace MWWorld
void addActor (const std::string& handle, const std::string& mesh, void addActor (const std::string& handle, const std::string& mesh,
const Ogre::Vector3& position); 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 removeObject (const std::string& handle);
void moveObject (const std::string& handle, const Ogre::Vector3& position); void moveObject (const std::string& handle, const Ogre::Vector3& position);
@ -49,11 +59,13 @@ namespace MWWorld
OEngine::Physic::PhysicEngine* getEngine(); OEngine::Physic::PhysicEngine* getEngine();
void setCurrentWater(bool hasWater, int waterHeight);
private: private:
OEngine::Render::OgreRenderer &mRender; OEngine::Render::OgreRenderer &mRender;
OEngine::Physic::PhysicEngine* mEngine; OEngine::Physic::PhysicEngine* mEngine;
bool mFreeFly; bool mFreeFly;
playerMove* playerphysics;
PhysicsSystem (const PhysicsSystem&); PhysicsSystem (const PhysicsSystem&);
PhysicsSystem& operator= (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&);

View file

@ -85,6 +85,14 @@ namespace MWWorld
MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value; MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value;
} }
void Player::setUpDown(int value)
{
MWWorld::Ptr ptr = getPlayer();
MWWorld::Class::get (ptr).getMovementSettings (ptr).mUpDown = value;
}
void Player::toggleRunning() void Player::toggleRunning()
{ {
@ -100,4 +108,5 @@ namespace MWWorld
MWWorld::Ptr ptr = getPlayer(); MWWorld::Ptr ptr = getPlayer();
return MWWorld::Class::get(ptr).getNpcStats(ptr).mDrawState; return MWWorld::Class::get(ptr).getNpcStats(ptr).mDrawState;
} }
} }

View file

@ -116,6 +116,7 @@ namespace MWWorld
void setLeftRight (int value); void setLeftRight (int value);
void setForwardBackward (int value); void setForwardBackward (int value);
void setUpDown(int value);
void toggleRunning(); void toggleRunning();
}; };

View file

@ -75,11 +75,14 @@ namespace MWWorld
// silence annoying g++ warning // silence annoying g++ warning
for (std::vector<Ogre::SceneNode*>::const_iterator iter (functor.mHandles.begin()); for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin());
iter!=functor.mHandles.end(); ++iter){ iter2!=functor.mHandles.end(); ++iter2){
Ogre::SceneNode* node = *iter; Ogre::SceneNode* node = *iter2;
mPhysics->removeObject (node->getName()); 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); mRendering.removeCell(*iter);
@ -103,20 +106,36 @@ namespace MWWorld
std::pair<CellStoreCollection::iterator, bool> result = std::pair<CellStoreCollection::iterator, bool> result =
mActiveCells.insert(cell); mActiveCells.insert(cell);
if(result.second){
if(result.second)
{
insertCell(*cell); insertCell(*cell);
mRendering.cellAdded (cell); 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.configureAmbient(*cell);
mRendering.requestMap(cell); mRendering.requestMap(cell);
mRendering.configureAmbient(*cell); mRendering.configureAmbient(*cell);
}
}
} }
void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
bool adjustPlayerPos) bool adjustPlayerPos)
{ {
bool hasWater = cell->cell->data.flags & cell->cell->HasWater;
mPhysics->setCurrentWater(hasWater, cell->cell->water);
if (adjustPlayerPos) if (adjustPlayerPos)
mWorld->getPlayer().setPos (position.pos[0], position.pos[1], position.pos[2]); mWorld->getPlayer().setPos (position.pos[0], position.pos[1], position.pos[2]);

View file

@ -215,6 +215,7 @@ namespace MWWorld
setFallbackValues(fallbackMap); 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[0] = x;
ptr.getRefData().getPosition().pos[1] = y; ptr.getRefData().getPosition().pos[1] = y;
ptr.getRefData().getPosition().pos[2] = z; ptr.getRefData().getPosition().pos[2] = z;
@ -582,6 +584,7 @@ namespace MWWorld
if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY) if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY)
{ {
mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getRefData().getPosition(), false); mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getRefData().getPosition(), false);
ret = true;
} }
} }
@ -591,6 +594,8 @@ namespace MWWorld
/// \todo cell change for non-player ref /// \todo cell change for non-player ref
mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z)); mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z));
return ret;
} }
void World::moveObject (Ptr ptr, float x, float y, float z) void World::moveObject (Ptr ptr, float x, float y, float z)
@ -632,7 +637,24 @@ namespace MWWorld
void World::doPhysics (const std::vector<std::pair<std::string, Ogre::Vector3> >& actors, void World::doPhysics (const std::vector<std::pair<std::string, Ogre::Vector3> >& actors,
float duration) float duration)
{ {
std::vector< std::pair<std::string, Ogre::Vector3> > vectors = mPhysics->doPhysics (duration, actors); mPhysics->doPhysics(duration, actors);
const int tick = 16; // 16 ms ^= 60 Hz
// 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)
{
// throw away wall clock time if necessary to keep the framerate above the minimum of 10 fps
lastTick += (dt - 100);
dt = 100;
}
while (dt >= tick)
{
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(); std::vector< std::pair<std::string, Ogre::Vector3> >::iterator player = vectors.end();
@ -653,8 +675,12 @@ namespace MWWorld
// Make sure player is moved last (otherwise the cell might change in the middle of an update // Make sure player is moved last (otherwise the cell might change in the middle of an update
// loop) // loop)
if (player!=vectors.end()) if (player!=vectors.end())
moveObjectImp (getPtrViaHandle (player->first), {
player->second.x, player->second.y, player->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
}
}
} }
bool World::toggleCollisionMode() bool World::toggleCollisionMode()
@ -789,7 +815,8 @@ namespace MWWorld
std::vector < std::pair < float, std::string > >::iterator it = results.begin(); std::vector < std::pair < float, std::string > >::iterator it = results.begin();
while (it != results.end()) 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); it = results.erase(it);
} }

View file

@ -22,6 +22,8 @@
#include <openengine/bullet/physic.hpp> #include <openengine/bullet/physic.hpp>
#include <openengine/ogre/fader.hpp> #include <openengine/ogre/fader.hpp>
#include <OgreTimer.h>
namespace Ogre namespace Ogre
{ {
class Vector3; class Vector3;
@ -100,9 +102,13 @@ namespace MWWorld
int mNumFacing; int mNumFacing;
std::map<std::string,std::string> mFallback; std::map<std::string,std::string> mFallback;
unsigned long lastTick;
Ogre::Timer mTimer;
int getDaysPerMonth (int month) const; 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: public:

View file

@ -1,6 +1,7 @@
#include "physic.hpp" #include "physic.hpp"
#include <btBulletDynamicsCommon.h> #include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h> #include <btBulletCollisionCommon.h>
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
#include <components/nifbullet/bullet_nif_loader.hpp> #include <components/nifbullet/bullet_nif_loader.hpp>
//#include <apps\openmw\mwworld\world.hpp> //#include <apps\openmw\mwworld\world.hpp>
#include "CMotionState.h" #include "CMotionState.h"
@ -10,6 +11,8 @@
#include "BtOgreGP.h" #include "BtOgreGP.h"
#include "BtOgreExtras.h" #include "BtOgreExtras.h"
#include <boost/lexical_cast.hpp>
#define BIT(x) (1<<(x)) #define BIT(x) (1<<(x))
namespace OEngine { namespace OEngine {
@ -161,10 +164,12 @@ namespace Physic
// The actual physics solver // The actual physics solver
solver = new btSequentialImpulseConstraintSolver; solver = new btSequentialImpulseConstraintSolver;
//btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache();
pairCache = new btSortedOverlappingPairCache(); pairCache = new btSortedOverlappingPairCache();
//pairCache->setInternalGhostPairCallback( new btGhostPairCallback() ); //pairCache->setInternalGhostPairCallback( new btGhostPairCallback() );
broadphase = new btDbvtBroadphase(pairCache); broadphase = new btDbvtBroadphase();
// The world. // The world.
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
@ -253,6 +258,60 @@ namespace Physic
delete mShapeLoader; 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<std::string>(x) + "_"
+ boost::lexical_cast<std::string>(y);
// find the minimum and maximum heights (needed for bullet)
float minh;
float maxh;
for (int i=0; i<sqrtVerts*sqrtVerts; ++i)
{
float h = heights[i];
if (i==0)
{
minh = h;
maxh = h;
}
if (h>maxh) maxh = h;
if (h<minh) minh = h;
}
btHeightfieldTerrainShape* hfShape = new btHeightfieldTerrainShape(
sqrtVerts, sqrtVerts, heights, 1,
minh, maxh, 2,
PHY_FLOAT,true);
hfShape->setUseDiamondSubdivision(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<std::string>(x) + "_"
+ boost::lexical_cast<std::string>(y);
removeRigidBody(name);
deleteRigidBody(name);
}
RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale)
{ {
//get the shape from the .nif //get the shape from the .nif
@ -334,7 +393,7 @@ namespace Physic
void PhysicEngine::stepSimulation(double deltaT) void PhysicEngine::stepSimulation(double deltaT)
{ {
dynamicsWorld->stepSimulation(deltaT,1,1/50.); dynamicsWorld->stepSimulation(deltaT,10, 1/60.0);
if(isDebugCreated) if(isDebugCreated)
{ {
mDebugDrawer->step(); mDebugDrawer->step();

View file

@ -140,6 +140,18 @@ namespace Physic
*/ */
RigidBody* createRigidBody(std::string mesh,std::string name,float scale); 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 * Add a RigidBody to the simulation
*/ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,200 @@
#ifndef OENGINE_BULLET_PMOVE_H
#define OENGINE_BULLET_PMOVE_H
/*
This source file is a *modified* version of various header files from the Quake 3 Arena source code,
which was released under the GNU GPL (v2) in 2005.
Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc.
*/
#include <Ogre.h>
#include <OgreMath.h>
#include <float.h>
#include "trace.h"
#include "physic.hpp"
//#include "GameMath.h"
//#include "GameTime.h"
// Forwards-declare it!
/*#ifndef COMPILING_PMOVE
#include "Scene.h"
extern SceneInstance* global_lastscene;
#endif*/
static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2);
#define MAX_CLIP_PLANES 5
#define OVERCLIP 1.001f
//#define STEPSIZE 18 // 18 is way too much
#define STEPSIZE (18 / 2)
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
#define YAW 0
#define PITCH /*1*/2
#define ROLL /*2*/1
#define SHORT2ANGLE(x) ( (x) * (360.0f / 65536.0f) )
#define ANGLE2SHORT(x) ( (const short)( (x) / (360.0f / 65536.0f) ) )
#define GENTITYNUM_BITS 10 // don't need to send any more
#define MAX_GENTITIES (1 << GENTITYNUM_BITS)
#define ENTITYNUM_NONE (MAX_GENTITIES - 1)
#define ENTITYNUM_WORLD (MAX_GENTITIES - 2)
#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes
#define JUMP_VELOCITY (270)
#define PS_PMOVEFRAMECOUNTBITS 6
#define MINS_Z -24
#define DEFAULT_VIEWHEIGHT 26
#define CROUCH_VIEWHEIGHT 12
#define DEAD_VIEWHEIGHT (-16)
#define CONTENTS_SOLID 1 // an eye is never valid in a solid
#define CONTENTS_LAVA 8
#define CONTENTS_SLIME 16
#define CONTENTS_WATER 32
#define CONTENTS_FOG 64
static const float pm_accelerate = 10.0f;
static const float pm_stopspeed = 100.0f;
static const float pm_friction = 12.0f;
static const float pm_flightfriction = 3.0f;
static const float pm_waterfriction = 1.0f;
static const float pm_airaccelerate = 1.0f;
static const float pm_swimScale = 0.50f;
static const float pm_duckScale = 0.25f;
static const float pm_flyaccelerate = 8.0f;
static const float pm_wateraccelerate = 4.0f;
enum pmtype_t
{
PM_NORMAL, // can accelerate and turn
PM_NOCLIP, // noclip movement
PM_SPECTATOR, // still run into walls
PM_DEAD, // no acceleration or turning, but free falling
PM_FREEZE, // stuck in place with no control
PM_INTERMISSION, // no movement or status bar
PM_SPINTERMISSION // no movement or status bar
};
enum waterlevel_t
{
WL_DRYLAND = 0,
WL_ANKLE,
WL_WAIST,
WL_UNDERWATER
};
//#include "bprintf.h"
struct playerMove
{
struct playerStruct
{
playerStruct() : gravity(800.0f), speed(480.0f), pmove_framecount(20), groundEntityNum(ENTITYNUM_NONE), commandTime(40), move_type(PM_NOCLIP), pm_time(0), snappingImplemented(true), bSnap(false), counter(-1)
{
origin = Ogre::Vector3(733.164f,900.0f, 839.432f);
velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f);
viewangles = Ogre::Vector3(0.0f, 0.0f, 0.0f);
delta_angles[0] = delta_angles[1] = delta_angles[2] = 0;
lastframe_origin.x = lastframe_origin.y = lastframe_origin.z = 0;
lerp_multiplier.x = lerp_multiplier.y = lerp_multiplier.z = 0;
}
inline void SpeedUp(void)
{
//printf("speed up to: %f\n", speed);
speed *= 1.25f;
}
inline void SpeedDown(void)
{
//printf("speed down to %f\n", speed);
speed /= 1.25f;
}
Ogre::Vector3 velocity;
Ogre::Vector3 origin;
bool bSnap;
bool snappingImplemented;
int counter;
float gravity; // default = 800
float speed; // default = 320
int commandTime; // the time at which this command was issued (in milliseconds)
int pm_time;
Ogre::Vector3 viewangles;
int groundEntityNum;
int pmove_framecount;
int watertype;
waterlevel_t waterlevel;
signed short delta_angles[3];
pmtype_t move_type;
float last_compute_time;
Ogre::Vector3 lastframe_origin;
Ogre::Vector3 lerp_multiplier;
} ps;
struct playercmd
{
enum CMDstateChange
{
NO_CHANGE,
KEYDOWN,
KEYUP
};
playercmd() : forwardmove(0), rightmove(0), upmove(0), serverTime(50), ducking(false),
activating(false), lastActivatingState(false), procActivating(NO_CHANGE),
dropping(false), lastDroppingState(false), procDropping(NO_CHANGE)
{
angles[0] = angles[1] = angles[2] = 0;
}
int serverTime;
short angles[3];
signed char forwardmove;
signed char rightmove;
signed char upmove;
bool ducking;
bool activating; // if the user is holding down the activate button
bool dropping; // if the user is dropping an item
bool lastActivatingState;
bool lastDroppingState;
CMDstateChange procActivating;
CMDstateChange procDropping;
} cmd;
playerMove() : msec(50), pmove_fixed(false), pmove_msec(50), waterHeight(0), isInterior(true), hasWater(false)
{
}
int msec;
int pmove_msec;
bool pmove_fixed;
int waterHeight;
bool hasWater;
bool isInterior;
//Object* traceObj;
OEngine::Physic::PhysicEngine* mEngine;
};
void Pmove (playerMove* const pmove);
void Ext_UpdateViewAngles(playerMove* const pm);
void AngleVectors( const Ogre::Vector3& angles, Ogre::Vector3* const forward, Ogre::Vector3* const right, Ogre::Vector3* const up) ;
#endif

View file

@ -0,0 +1,190 @@
#include "trace.h"
#include <map>
void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass) //Traceobj was a Aedra Object
{
//if (!traceobj)
// return;
//if (!traceobj->incellptr)
// return;
const Ogre::Vector3 rayDir = end - start;
// Nudge starting point backwards
//const Position3D nudgestart = start + (rayDir * -0.1f); // by 10% (isn't that too much?)
//const Position3D nudgestart = start;
NewPhysTraceResults out;
//std::cout << "Starting trace\n";
//Ogre::Vector3 startReplace = Ogre::Vector3(650,950, 45);
//Ogre::Vector3 endReplace = startReplace;
//endReplace.z -= .25;
const bool hasHit = NewPhysicsTrace<collisionWorldTrace>(&out, start, end, BBHalfExtents, Ogre::Vector3(0.0f, 0.0, rotation), isInterior, enginePass);
if (out.fraction < 0.001f)
results->startsolid = true;
else
results->startsolid = false;
//results->allsolid = out.startSolid;
// If outside and underground, we're solid
/*if (isInterior)
{
const Ogre::Vector3 height = GetGroundPosition(start, CellCoords(traceCell->data->gridX, traceCell->data->gridY) );
if (start.yPos - height.yPos < (-2.0f * BBHalfExtents.yPos) )
{
results->allsolid = true;
}
else
results->allsolid = false;
}*/
// If inside and out of the tree, we're solid
//else
//{
results->allsolid = out.startSolid;
//std::cout << "allsolid" << results->allsolid << "\n";
//}
if (!hasHit)
{
results->endpos = end;
results->planenormal = Ogre::Vector3(0.0f, 0.0f, 1.0f);
results->entityNum = ENTITYNUM_NONE;
results->fraction = 1.0f;
}
else
{
results->fraction = out.fraction;
results->planenormal = out.hitNormal;
results->endpos = rayDir * results->fraction + start;
results->entityNum = ENTITYNUM_WORLD;
/*bprintf("Start: (%f, %f, %f) End: (%f, %f, %f) TraceDir: (%f, %f, %f) HitNormal: (%f, %f, %f) Fraction: %f Hitpos: (%f, %f, %f) CompensatedHitpos: (%f, %f, %f)\n",
start.xPos, start.yPos, start.zPos,
end.xPos, end.yPos, end.zPos,
rayDir.xPos, rayDir.yPos, rayDir.zPos,
results->planenormal.xPos, results->planenormal.yPos, results->planenormal.zPos, results->fraction,
out.endPos.xPos, out.endPos.yPos, out.endPos.zPos,
results->endpos.xPos, results->endpos.yPos, results->endpos.zPos);*/
}
}
template <const traceWorldType traceType>
const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end,
const Ogre::Vector3& BBHalfExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass)
{
//if (!traceobj->incellptr)
// return false;
//if(enginePass->dynamicsWorld->getCollisionObjectArray().at(60)->getCollisionShape()->isConvex())
// std::cout << "It's convex\n";
const btVector3 btstart(start.x, start.y, start.z);
const btVector3 btend(end.x, end.y, end.z);
const btQuaternion btrot(rotation.y, rotation.x, rotation.z); //y, x, z
const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z));
const btTransform from(btrot, btstart);
const btTransform to(btrot, btend);
// warning: unused variable ...
/*
float x = from.getOrigin().getX();
float y = from.getOrigin().getY();
float z = from.getOrigin().getZ();
float x2 = to.getOrigin().getX();
float y2 = to.getOrigin().getY();
float z2 = to.getOrigin().getZ();
*/
//std::cout << "BtFrom: " << x << "," << y << "," << z << "\n";
//std::cout << "BtTo: " << x2 << "," << y2 << "," << z2 << "\n";
//std::cout << "BtTo: " << to.getOrigin().getX() << "," << to.getOrigin().getY() << "," << to.getOrigin().getZ() << "\n";
btCollisionWorld::ClosestConvexResultCallback
newTraceCallback(btstart, btend);
newTraceCallback.m_collisionFilterMask = (traceType == collisionWorldTrace) ? Only_Collision : Only_Pickup;
enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback);
//newTraceCallback.
//std::cout << "NUM: " << enginePass->dynamicsWorld->getNumCollisionObjects() << "\n";
// Copy the hit data over to our trace results struct:
out->fraction = newTraceCallback.m_closestHitFraction;
Ogre::Vector3& outhitnormal = out->hitNormal;
const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld;
outhitnormal.x = tracehitnormal.x();
outhitnormal.y = tracehitnormal.y();
outhitnormal.z = tracehitnormal.z();
Ogre::Vector3& outhitpos = out->endPos;
const btVector3& tracehitpos = newTraceCallback.m_hitPointWorld;
outhitpos.x = tracehitpos.x();
outhitpos.y = tracehitpos.y();
outhitpos.z= tracehitpos.z();
// StartSolid test:
{
out->startSolid = false;
//btCollisionObject collision;
//collision.setCollisionShape(const_cast<btBoxShape* const>(&newshape) );
//CustomContactCallback crb;
//world.world->contactTest(&collision, crb);
//out->startSolid = crb.hit;
// If outside and underground, we're solid
if (!isInterior) //Check if we are interior
{
}
// If inside and out of the tree, we're solid
else
{
btVector3 aabbMin, aabbMax;
enginePass->broadphase->getBroadphaseAabb(aabbMin, aabbMax);
//std::cout << "AABBMIN" << aabbMin.getX() <<"," <<aabbMin.getY() << "," << aabbMin.getZ() << "\n";
//std::cout << "AABBMAX" << aabbMax.getX() <<"," <<aabbMax.getY() << "," << aabbMax.getZ() << "\n";
//std::cout << "AABBMAX" << aabbMax << "\n";
if (!TestPointAgainstAabb2(aabbMin, aabbMax, *(const btVector3* const)&(start) ) )
{
//We're solid
out->startSolid = true;
}
}
}
const bool hasHit = newTraceCallback.hasHit();
return hasHit;
}

View file

@ -18,7 +18,7 @@ enum traceWorldType
bothWorldTrace = collisionWorldTrace | pickWorldTrace bothWorldTrace = collisionWorldTrace | pickWorldTrace
}; };
enum collaborativePhysicsType : unsigned enum collaborativePhysicsType
{ {
No_Physics = 0, // Both are empty (example: statics you can walk through, like tall grass) No_Physics = 0, // Both are empty (example: statics you can walk through, like tall grass)
Only_Collision = 1, // This object only has collision physics but no pickup physics (example: statics) Only_Collision = 1, // This object only has collision physics but no pickup physics (example: statics)
@ -53,8 +53,8 @@ struct traceResults
template <const traceWorldType traceType> template <const traceWorldType traceType>
const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
template const bool NewPhysicsTrace<collisionWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); //template const bool NewPhysicsTrace<collisionWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
template const bool NewPhysicsTrace<pickWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); //template const bool NewPhysicsTrace<pickWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);