2011-10-29 07:50:11 +00:00
# include <stdexcept>
2011-08-01 13:55:36 +00:00
# include "physicssystem.hpp"
# include "../mwworld/ptr.hpp"
# include "../mwworld/world.hpp" // FIXME
2012-01-29 15:31:18 +00:00
# include <components/nifbullet/bullet_nif_loader.hpp>
2011-08-01 13:55:36 +00:00
# include "OgreRoot.h"
# include "OgreRenderWindow.h"
# include "OgreSceneManager.h"
# include "OgreViewport.h"
# include "OgreCamera.h"
# include "OgreTextureManager.h"
2012-03-20 00:03:48 +00:00
2011-10-20 22:15:30 +00:00
using namespace Ogre ;
2011-08-01 13:55:36 +00:00
namespace MWWorld
{
2012-01-29 15:31:18 +00:00
PhysicsSystem : : PhysicsSystem ( OEngine : : Render : : OgreRenderer & _rend ) :
mRender ( _rend ) , mEngine ( 0 ) , mFreeFly ( true )
2011-08-01 13:55:36 +00:00
{
2012-04-30 21:55:22 +00:00
2012-04-17 22:12:05 +00:00
playerphysics = new playerMove ;
2012-01-29 15:31:18 +00:00
// Create physics. shapeLoader is deleted by the physic engine
NifBullet : : ManualBulletShapeLoader * shapeLoader = new NifBullet : : ManualBulletShapeLoader ( ) ;
mEngine = new OEngine : : Physic : : PhysicEngine ( shapeLoader ) ;
2012-04-17 22:12:05 +00:00
playerphysics - > mEngine = mEngine ;
2011-08-01 13:55:36 +00:00
}
2011-08-22 19:34:51 +00:00
2011-08-01 13:55:36 +00:00
PhysicsSystem : : ~ PhysicsSystem ( )
{
2012-01-29 15:31:18 +00:00
delete mEngine ;
2012-04-30 21:55:22 +00:00
2012-01-29 15:31:18 +00:00
}
OEngine : : Physic : : PhysicEngine * PhysicsSystem : : getEngine ( )
{
return mEngine ;
2011-08-01 13:55:36 +00:00
}
2012-04-30 21:55:22 +00:00
2011-10-20 22:15:30 +00:00
std : : pair < std : : string , float > PhysicsSystem : : getFacedHandle ( MWWorld : : World & world )
{
std : : string handle = " " ;
//get a ray pointing to the center of the viewport
Ray centerRay = mRender . getCamera ( ) - > getCameraToViewportRay (
mRender . getViewport ( ) - > getWidth ( ) / 2 ,
mRender . getViewport ( ) - > getHeight ( ) / 2 ) ;
//let's avoid the capsule shape of the player.
centerRay . setOrigin ( centerRay . getOrigin ( ) + 20 * centerRay . getDirection ( ) ) ;
btVector3 from ( centerRay . getOrigin ( ) . x , - centerRay . getOrigin ( ) . z , centerRay . getOrigin ( ) . y ) ;
btVector3 to ( centerRay . getPoint ( 500 ) . x , - centerRay . getPoint ( 500 ) . z , centerRay . getPoint ( 500 ) . y ) ;
return mEngine - > rayTest ( from , to ) ;
}
2012-03-25 18:52:56 +00:00
std : : vector < std : : pair < float , std : : string > > PhysicsSystem : : getFacedObjects ( )
{
//get a ray pointing to the center of the viewport
Ray centerRay = mRender . getCamera ( ) - > getCameraToViewportRay (
mRender . getViewport ( ) - > getWidth ( ) / 2 ,
mRender . getViewport ( ) - > getHeight ( ) / 2 ) ;
btVector3 from ( centerRay . getOrigin ( ) . x , - centerRay . getOrigin ( ) . z , centerRay . getOrigin ( ) . y ) ;
btVector3 to ( centerRay . getPoint ( 500 ) . x , - centerRay . getPoint ( 500 ) . z , centerRay . getPoint ( 500 ) . y ) ;
return mEngine - > rayTest2 ( from , to ) ;
}
2012-04-18 04:13:38 +00:00
void PhysicsSystem : : setCurrentWater ( bool hasWater , int waterHeight ) {
playerphysics - > hasWater = hasWater ;
if ( hasWater ) {
playerphysics - > waterHeight = waterHeight ;
}
2012-04-30 21:55:22 +00:00
2012-04-18 04:13:38 +00:00
}
2012-03-25 18:52:56 +00:00
btVector3 PhysicsSystem : : getRayPoint ( float extent )
{
//get a ray pointing to the center of the viewport
Ray centerRay = mRender . getCamera ( ) - > getCameraToViewportRay (
mRender . getViewport ( ) - > getWidth ( ) / 2 ,
mRender . getViewport ( ) - > getHeight ( ) / 2 ) ;
2012-05-15 14:47:23 +00:00
btVector3 result ( centerRay . getPoint ( 500 * extent ) . x , - centerRay . getPoint ( 500 * extent ) . z , centerRay . getPoint ( 500 * extent ) . y ) ; /// \todo make this distance (ray length) configurable
2012-03-27 20:36:02 +00:00
return result ;
2012-03-25 18:52:56 +00:00
}
2012-04-30 21:55:22 +00:00
2012-02-24 15:12:43 +00:00
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 ) ;
2012-04-30 21:55:22 +00:00
2012-02-24 15:12:43 +00:00
std : : pair < std : : string , float > result = mEngine - > rayTest ( _from , _to ) ;
2012-04-30 21:55:22 +00:00
2012-02-24 15:12:43 +00:00
return ! ( result . first = = " " ) ;
}
2011-10-20 22:15:30 +00:00
2012-05-15 14:47:23 +00:00
std : : pair < bool , Ogre : : Vector3 > PhysicsSystem : : castRay ( float mouseX , float mouseY )
{
Ogre : : Ray ray = mRender . getCamera ( ) - > getCameraToViewportRay (
mouseX ,
mouseY ) ;
Ogre : : Vector3 from = ray . getOrigin ( ) ;
Ogre : : Vector3 to = ray . getPoint ( 200 ) ; /// \todo make this distance (ray length) configurable
btVector3 _from , _to ;
// OGRE to MW coordinates
_from = btVector3 ( from . x , - from . z , from . y ) ;
_to = btVector3 ( to . x , - to . z , to . y ) ;
std : : pair < std : : string , float > result = mEngine - > rayTest ( _from , _to ) ;
if ( result . first = = " " )
return std : : make_pair ( false , Ogre : : Vector3 ( ) ) ;
else
{
return std : : make_pair ( true , ray . getPoint ( 200 * result . second ) ) ; /// \todo make this distance (ray length) configurable
}
}
2012-04-30 21:55:22 +00:00
void PhysicsSystem : : doPhysics ( float dt , const std : : vector < std : : pair < std : : string , Ogre : : Vector3 > > & actors )
2011-08-01 13:55:36 +00:00
{
//set the DebugRenderingMode. To disable it,set it to 0
//eng->setDebugRenderingMode(1);
2012-04-30 21:55:22 +00:00
2011-08-01 13:55:36 +00:00
//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 ) ) ;
}
2012-03-20 00:03:48 +00:00
playerMove : : playercmd & pm_ref = playerphysics - > cmd ;
2012-04-17 22:12:05 +00:00
pm_ref . rightmove = 0 ;
pm_ref . forwardmove = 0 ;
pm_ref . upmove = 0 ;
2012-04-30 21:55:22 +00:00
2012-03-20 00:03:48 +00:00
//playerphysics->ps.move_type = PM_NOCLIP;
2011-08-01 13:55:36 +00:00
for ( std : : vector < std : : pair < std : : string , Ogre : : Vector3 > > : : const_iterator iter ( actors . begin ( ) ) ;
iter ! = actors . end ( ) ; + + iter )
{
OEngine : : Physic : : PhysicActor * act = mEngine - > getCharacter ( iter - > first ) ;
2012-03-20 00:03:48 +00:00
//if(iter->first == "player")
// std::cout << "This is player\n";
2011-08-01 13:55:36 +00:00
//dirty stuff to get the camera orientation. Must be changed!
Ogre : : SceneNode * sceneNode = mRender . getScene ( ) - > getSceneNode ( iter - > first ) ;
Ogre : : Vector3 dir ;
Ogre : : Node * yawNode = sceneNode - > getChildIterator ( ) . getNext ( ) ;
Ogre : : Node * pitchNode = yawNode - > getChildIterator ( ) . getNext ( ) ;
2012-03-20 00:03:48 +00:00
Ogre : : Quaternion yawQuat = yawNode - > getOrientation ( ) ;
2012-04-30 21:55:22 +00:00
Ogre : : Quaternion pitchQuat = pitchNode - > getOrientation ( ) ;
// unused
//Ogre::Quaternion both = yawQuat * pitchQuat;
2012-04-30 16:46:51 +00:00
2012-04-30 21:55:22 +00:00
playerphysics - > ps . viewangles . x = pitchQuat . getPitch ( ) . valueDegrees ( ) ;
playerphysics - > ps . viewangles . z = 0 ;
2012-04-18 00:31:36 +00:00
playerphysics - > ps . viewangles . y = yawQuat . getYaw ( ) . valueDegrees ( ) * - 1 + 90 ;
2012-04-17 22:12:05 +00:00
2011-08-01 13:55:36 +00:00
if ( mFreeFly )
{
Ogre : : Vector3 dir1 ( iter - > second . x , iter - > second . z , - iter - > second . y ) ;
2012-04-17 22:12:05 +00:00
2012-03-20 00:03:48 +00:00
pm_ref . rightmove = - dir1 . x ;
pm_ref . forwardmove = dir1 . z ;
2012-03-25 02:03:08 +00:00
pm_ref . upmove = dir1 . y ;
2012-04-17 22:12:05 +00:00
2012-04-30 21:55:22 +00:00
2012-03-20 00:03:48 +00:00
//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";
2011-08-01 13:55:36 +00:00
dir = 0.07 * ( yawQuat * pitchQuat * dir1 ) ;
}
else
{
2012-04-30 21:55:22 +00:00
2011-08-01 13:55:36 +00:00
Ogre : : Quaternion quat = yawNode - > getOrientation ( ) ;
Ogre : : Vector3 dir1 ( iter - > second . x , iter - > second . z , - iter - > second . y ) ;
2012-04-30 21:55:22 +00:00
2012-03-20 00:03:48 +00:00
pm_ref . rightmove = - dir1 . x ;
pm_ref . forwardmove = dir1 . z ;
2012-03-28 00:17:54 +00:00
pm_ref . upmove = dir1 . y ;
2012-04-30 21:55:22 +00:00
2011-08-01 13:55:36 +00:00
dir = 0.025 * ( quat * dir1 ) ;
}
2012-04-30 21:55:22 +00:00
2011-08-01 13:55:36 +00:00
//set the walk direction
act - > setWalkDirection ( btVector3 ( dir . x , - dir . z , dir . y ) ) ;
}
2012-04-30 21:55:22 +00:00
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 ) ;
2012-04-17 22:12:05 +00:00
2011-08-02 16:44:10 +00:00
std : : vector < std : : pair < std : : string , Ogre : : Vector3 > > response ;
2011-08-01 13:55:36 +00:00
for ( std : : map < std : : string , OEngine : : Physic : : PhysicActor * > : : iterator it = mEngine - > PhysicActorMap . begin ( ) ; it ! = mEngine - > PhysicActorMap . end ( ) ; it + + )
{
2011-08-02 16:16:39 +00:00
btVector3 newPos = it - > second - > getPosition ( ) ;
2012-04-30 21:55:22 +00:00
2011-08-02 16:16:39 +00:00
Ogre : : Vector3 coord ( newPos . x ( ) , newPos . y ( ) , newPos . z ( ) ) ;
2012-04-30 21:55:22 +00:00
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
}
2011-08-02 16:44:10 +00:00
response . push_back ( std : : pair < std : : string , Ogre : : Vector3 > ( it - > first , coord ) ) ;
2011-08-01 13:55:36 +00:00
}
2012-04-30 21:55:22 +00:00
2011-08-02 16:16:39 +00:00
return response ;
2011-08-01 13:55:36 +00:00
}
2012-03-13 16:09:50 +00:00
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 ) ;
}
2011-08-01 13:55:36 +00:00
void PhysicsSystem : : addObject ( const std : : string & handle , const std : : string & mesh ,
const Ogre : : Quaternion & rotation , float scale , const Ogre : : Vector3 & position )
{
2012-03-02 15:47:39 +00:00
OEngine : : Physic : : RigidBody * body = mEngine - > createRigidBody ( mesh , handle , scale ) ;
2011-08-01 13:55:36 +00:00
mEngine - > addRigidBody ( body ) ;
btTransform tr ;
tr . setOrigin ( btVector3 ( position . x , position . y , position . z ) ) ;
tr . setRotation ( btQuaternion ( rotation . x , rotation . y , rotation . z , rotation . w ) ) ;
body - > setWorldTransform ( tr ) ;
}
void PhysicsSystem : : addActor ( const std : : string & handle , const std : : string & mesh ,
const Ogre : : Vector3 & position )
{
//TODO:optimize this. Searching the std::map isn't very efficient i think.
mEngine - > addCharacter ( handle ) ;
OEngine : : Physic : : PhysicActor * act = mEngine - > getCharacter ( handle ) ;
act - > setPosition ( btVector3 ( position . x , position . y , position . z ) ) ;
}
void PhysicsSystem : : removeObject ( const std : : string & handle )
{
//TODO:check if actor???
mEngine - > removeCharacter ( handle ) ;
mEngine - > removeRigidBody ( handle ) ;
mEngine - > deleteRigidBody ( handle ) ;
}
2011-09-04 07:48:50 +00:00
void PhysicsSystem : : moveObject ( const std : : string & handle , const Ogre : : Vector3 & position )
2011-08-01 13:55:36 +00:00
{
2011-09-04 07:48:50 +00:00
if ( OEngine : : Physic : : RigidBody * body = mEngine - > getRigidBody ( handle ) )
2011-08-01 13:55:36 +00:00
{
2011-09-04 07:48:50 +00:00
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
// start positions others than 0, 0, 0
btTransform tr = body - > getWorldTransform ( ) ;
tr . setOrigin ( btVector3 ( position . x , position . y , position . z ) ) ;
body - > setWorldTransform ( tr ) ;
}
if ( OEngine : : Physic : : PhysicActor * act = mEngine - > getCharacter ( handle ) )
{
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
// start positions others than 0, 0, 0
2012-04-30 21:55:22 +00:00
if ( handle = = " player " )
{
playerphysics - > ps . origin = position ;
}
else
{
act - > setPosition ( btVector3 ( position . x , position . y , position . z ) ) ;
}
2011-08-01 13:55:36 +00:00
}
}
void PhysicsSystem : : rotateObject ( const std : : string & handle , const Ogre : : Quaternion & rotation )
{
2012-01-05 00:47:06 +00:00
if ( OEngine : : Physic : : PhysicActor * act = mEngine - > getCharacter ( handle ) )
{
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
// start positions others than 0, 0, 0
act - > setRotation ( btQuaternion ( rotation . x , rotation . y , rotation . z , rotation . w ) ) ;
}
2011-08-01 13:55:36 +00:00
}
void PhysicsSystem : : scaleObject ( const std : : string & handle , float scale )
{
}
bool PhysicsSystem : : toggleCollisionMode ( )
{
2012-03-25 02:03:08 +00:00
if ( playerphysics - > ps . move_type = = PM_NOCLIP )
playerphysics - > ps . move_type = PM_NORMAL ;
2012-04-18 00:31:36 +00:00
2012-03-25 02:03:08 +00:00
else
playerphysics - > ps . move_type = PM_NOCLIP ;
2011-08-01 13:55:36 +00:00
for ( std : : map < std : : string , OEngine : : Physic : : PhysicActor * > : : iterator it = mEngine - > PhysicActorMap . begin ( ) ; it ! = mEngine - > PhysicActorMap . end ( ) ; it + + )
{
2011-10-29 07:50:11 +00:00
if ( it - > first = = " player " )
2011-08-01 13:55:36 +00:00
{
2011-10-29 07:50:11 +00:00
OEngine : : Physic : : PhysicActor * act = it - > second ;
bool cmode = act - > getCollisionMode ( ) ;
if ( cmode )
{
act - > enableCollisions ( false ) ;
act - > setGravity ( 0. ) ;
act - > setVerticalVelocity ( 0 ) ;
mFreeFly = true ;
return false ;
}
else
{
mFreeFly = false ;
act - > enableCollisions ( true ) ;
act - > setGravity ( 4. ) ;
act - > setVerticalVelocity ( 0 ) ;
return true ;
}
2011-08-01 13:55:36 +00:00
}
}
2011-10-29 07:50:11 +00:00
throw std : : logic_error ( " can't find player " ) ;
2011-08-01 13:55:36 +00:00
}
2011-11-18 00:38:52 +00:00
void PhysicsSystem : : insertObjectPhysics ( const MWWorld : : Ptr & ptr , const std : : string model ) {
2012-04-30 21:55:22 +00:00
2011-11-11 05:20:53 +00:00
Ogre : : SceneNode * node = ptr . getRefData ( ) . getBaseNode ( ) ;
2012-04-30 16:46:51 +00:00
// unused
//Ogre::Vector3 objPos = node->getPosition();
2012-03-25 02:03:08 +00:00
2011-11-18 00:38:52 +00:00
addObject ( node - > getName ( ) , model , node - > getOrientation ( ) ,
2011-11-09 23:06:55 +00:00
node - > getScale ( ) . x , node - > getPosition ( ) ) ;
}
2011-11-18 00:38:52 +00:00
void PhysicsSystem : : insertActorPhysics ( const MWWorld : : Ptr & ptr , const std : : string model ) {
2011-11-11 05:20:53 +00:00
Ogre : : SceneNode * node = ptr . getRefData ( ) . getBaseNode ( ) ;
2011-12-25 06:52:57 +00:00
// std::cout << "Adding node with name" << node->getName();
2011-11-18 00:38:52 +00:00
addActor ( node - > getName ( ) , model , node - > getPosition ( ) ) ;
2011-11-09 23:06:55 +00:00
}
2011-08-01 13:55:36 +00:00
}