1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 21:23:52 +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/BulletShapeLoader.cpp
${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)
, mUseSound (true)
, mCompileAll (false)
, mFocusTDiff (0)
, mScriptContext (0)
, mFSStrict (false)
, mCfgMgr(configurationManager)
@ -263,7 +262,6 @@ void OMW::Engine::setNewGame(bool newGame)
void OMW::Engine::go()
{
mFocusTDiff = 0;
assert (!mCellName.empty());
assert (!mMaster.empty());
assert (!mOgre);

View file

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

View file

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

View file

@ -60,6 +60,7 @@ namespace MWInput
A_CycleWeaponRight,
A_ToggleSneak, //Toggles Sneak, add Push-Sneak later
A_ToggleWalk, //Toggle Walking/Running
A_Crouch,
A_QuickSave,
A_QuickLoad,
@ -310,6 +311,9 @@ namespace MWInput
poller.bind(A_MoveRight, KC_D);
poller.bind(A_MoveForward, KC_W);
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
@ -356,6 +360,13 @@ namespace MWInput
}
else
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

View file

@ -8,8 +8,9 @@ namespace MWMechanics
{
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 mUpDown;
Movement() : mLeftRight (0), mForwardBackward (0) {}
Movement() : mLeftRight (0), mForwardBackward (0), mUpDown(0) {}
};
}

View file

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

View file

@ -21,23 +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 = "";
@ -65,6 +66,13 @@ namespace MWWorld
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)
{
@ -75,35 +83,35 @@ 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++)
{
OEngine::Physic::PhysicActor* act = it->second;
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;
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
iter!=actors.end(); ++iter)
@ -118,21 +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 both = yawQuat * pitchQuat;
//playerphysics->ps.viewangles.z = both.getPitch().valueDegrees();
Ogre::Quaternion pitchQuat = pitchNode->getOrientation();
// 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";
@ -140,31 +151,65 @@ 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);
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
}
response.push_back(std::pair<std::string, Ogre::Vector3>(it->first, coord));
}
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)
{
@ -207,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));
}
}
}
@ -228,6 +280,11 @@ namespace MWWorld
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++)
{
if (it->first=="player")
@ -258,7 +315,12 @@ namespace MWWorld
}
void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){
Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
// unused
//Ogre::Vector3 objPos = node->getPosition();
addObject (node->getName(), model, node->getOrientation(),
node->getScale().x, node->getPosition());
}

View file

@ -5,6 +5,7 @@
#include <openengine/ogre/renderer.hpp>
#include <openengine/bullet/physic.hpp>
#include "ptr.hpp"
#include <openengine/bullet/pmove.h>
namespace MWWorld
{
@ -15,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);
@ -24,6 +28,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);
@ -49,11 +59,13 @@ namespace MWWorld
OEngine::Physic::PhysicEngine* getEngine();
void setCurrentWater(bool hasWater, int waterHeight);
private:
OEngine::Render::OgreRenderer &mRender;
OEngine::Physic::PhysicEngine* mEngine;
bool mFreeFly;
playerMove* playerphysics;
PhysicsSystem (const PhysicsSystem&);
PhysicsSystem& operator= (const PhysicsSystem&);

View file

@ -85,6 +85,14 @@ namespace MWWorld
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()
{
@ -100,4 +108,5 @@ namespace MWWorld
MWWorld::Ptr ptr = getPlayer();
return MWWorld::Class::get(ptr).getNpcStats(ptr).mDrawState;
}
}

View file

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

View file

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

View file

@ -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,50 @@ 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)
{
if (it->first=="player")
// 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();
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()
@ -789,7 +815,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);
}

View file

@ -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:

View file

@ -1,6 +1,7 @@
#include "physic.hpp"
#include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h>
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
#include <components/nifbullet/bullet_nif_loader.hpp>
//#include <apps\openmw\mwworld\world.hpp>
#include "CMotionState.h"
@ -10,6 +11,8 @@
#include "BtOgreGP.h"
#include "BtOgreExtras.h"
#include <boost/lexical_cast.hpp>
#define BIT(x) (1<<(x))
namespace OEngine {
@ -161,10 +164,12 @@ namespace Physic
// The actual physics solver
solver = new btSequentialImpulseConstraintSolver;
//btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache();
pairCache = new btSortedOverlappingPairCache();
//pairCache->setInternalGhostPairCallback( new btGhostPairCallback() );
broadphase = new btDbvtBroadphase(pairCache);
broadphase = new btDbvtBroadphase();
// The world.
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
@ -253,6 +258,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<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)
{
//get the shape from the .nif
@ -334,7 +393,7 @@ namespace Physic
void PhysicEngine::stepSimulation(double deltaT)
{
dynamicsWorld->stepSimulation(deltaT,1,1/50.);
dynamicsWorld->stepSimulation(deltaT,10, 1/60.0);
if(isDebugCreated)
{
mDebugDrawer->step();

View file

@ -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
*/

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
};
enum collaborativePhysicsType : unsigned
enum collaborativePhysicsType
{
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)
@ -53,10 +53,10 @@ struct traceResults
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);
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<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);
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);
#endif
#endif