2012-07-03 10:30:50 +00:00
# include "physicssystem.hpp"
2011-10-29 07:50:11 +00:00
# include <stdexcept>
2012-07-03 10:30:50 +00:00
# include <OgreRoot.h>
# include <OgreRenderWindow.h>
# include <OgreSceneManager.h>
# include <OgreViewport.h>
# include <OgreCamera.h>
# include <OgreTextureManager.h>
2011-08-01 13:55:36 +00:00
2012-07-03 10:30:50 +00:00
# include <components/nifbullet/bullet_nif_loader.hpp>
2011-08-01 13:55:36 +00:00
2012-08-13 22:36:18 +00:00
//#include "../mwbase/world.hpp" // FIXME
2011-08-01 13:55:36 +00:00
2012-07-03 10:30:50 +00:00
# include "ptr.hpp"
2012-07-24 14:52:08 +00:00
# include "class.hpp"
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-06-06 18:29:30 +00:00
delete playerphysics ;
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
2012-08-17 06:10:37 +00:00
std : : pair < std : : string , float > PhysicsSystem : : getFacedHandle ( MWWorld : : World & world )
{
2012-08-17 11:07:12 +00:00
btVector3 dir ( 0 , 1 , 0 ) ;
dir = dir . rotate ( btVector3 ( 1 , 0 , 0 ) , mPlayerData . pitch ) ;
dir = dir . rotate ( btVector3 ( 0 , 0 , 1 ) , mPlayerData . yaw ) ;
dir . setX ( - dir . x ( ) ) ;
btVector3 origin (
mPlayerData . eyepos . x ,
mPlayerData . eyepos . y ,
mPlayerData . eyepos . z ) ;
origin + = dir * 5 ;
btVector3 dest = origin + dir * 500 ;
return mEngine - > rayTest ( origin , dest ) ;
2011-10-20 22:15:30 +00:00
}
2012-03-25 18:52:56 +00:00
std : : vector < std : : pair < float , std : : string > > PhysicsSystem : : getFacedObjects ( )
{
2012-08-17 11:07:12 +00:00
btVector3 dir ( 0 , 1 , 0 ) ;
dir = dir . rotate ( btVector3 ( 1 , 0 , 0 ) , mPlayerData . pitch ) ;
dir = dir . rotate ( btVector3 ( 0 , 0 , 1 ) , mPlayerData . yaw ) ;
dir . setX ( - dir . x ( ) ) ;
btVector3 origin (
mPlayerData . eyepos . x ,
mPlayerData . eyepos . y ,
mPlayerData . eyepos . z ) ;
origin + = dir * 5 ;
btVector3 dest = origin + dir * 500 ;
return mEngine - > rayTest2 ( origin , dest ) ;
2012-03-25 18:52:56 +00:00
}
2012-06-02 10:25:24 +00:00
std : : vector < std : : pair < float , std : : string > > PhysicsSystem : : getFacedObjects ( float mouseX , float mouseY )
{
Ray ray = mRender . getCamera ( ) - > getCameraToViewportRay ( mouseX , mouseY ) ;
Ogre : : Vector3 from = ray . getOrigin ( ) ;
Ogre : : Vector3 to = ray . getPoint ( 500 ) ; /// \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 ) ;
return mEngine - > rayTest2 ( _from , _to ) ;
}
void PhysicsSystem : : setCurrentWater ( bool hasWater , int waterHeight )
{
2012-04-18 04:13:38 +00:00
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-06-02 10:25:24 +00:00
btVector3 PhysicsSystem : : getRayPoint ( float extent , float mouseX , float mouseY )
{
//get a ray pointing to the center of the viewport
Ray centerRay = mRender . getCamera ( ) - > getCameraToViewportRay ( mouseX , mouseY ) ;
btVector3 result ( centerRay . getPoint ( 500 * extent ) . x , - centerRay . getPoint ( 500 * extent ) . z , centerRay . getPoint ( 500 * extent ) . y ) ; /// \todo make this distance (ray length) configurable
return result ;
}
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-07-25 16:25:53 +00:00
std : : pair < bool , Ogre : : Vector3 >
PhysicsSystem : : castRay ( const Ogre : : Vector3 & orig , const Ogre : : Vector3 & dir , float len )
{
Ogre : : Ray ray = Ogre : : Ray ( orig , dir ) ;
Ogre : : Vector3 to = ray . getPoint ( len ) ;
btVector3 btFrom = btVector3 ( orig . x , orig . y , orig . z ) ;
btVector3 btTo = btVector3 ( to . x , to . y , to . z ) ;
std : : pair < std : : string , float > test = mEngine - > rayTest ( btFrom , btTo ) ;
if ( test . first = = " " ) {
return std : : make_pair ( false , Ogre : : Vector3 ( ) ) ;
}
return std : : make_pair ( true , ray . getPoint ( len * test . second ) ) ;
}
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-09-01 21:28:12 +00:00
2012-08-13 22:36:18 +00:00
playerMove : : playercmd & pm_ref = playerphysics - > cmd ;
2012-04-17 22:12:05 +00:00
2012-09-01 21:28:12 +00:00
2012-04-17 22:12:05 +00:00
pm_ref . rightmove = 0 ;
pm_ref . forwardmove = 0 ;
pm_ref . upmove = 0 ;
2012-08-04 19:43:33 +00:00
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 )
{
//dirty stuff to get the camera orientation. Must be changed!
2012-08-13 22:36:18 +00:00
if ( iter - > first = = " player " ) {
2012-08-17 06:10:37 +00:00
playerphysics - > ps . viewangles . x =
Ogre : : Radian ( mPlayerData . pitch ) . valueDegrees ( ) ;
2011-08-01 13:55:36 +00:00
2012-04-30 21:55:22 +00:00
2012-07-10 11:23:41 +00:00
2012-08-17 06:10:37 +00:00
playerphysics - > ps . viewangles . y =
Ogre : : Radian ( mPlayerData . yaw ) . valueDegrees ( ) + 90 ;
2012-04-30 21:55:22 +00:00
2012-09-05 21:44:11 +00:00
pm_ref . rightmove = iter - > second . x ;
2012-08-13 22:36:18 +00:00
pm_ref . forwardmove = - iter - > second . y ;
pm_ref . upmove = iter - > second . z ;
}
2012-07-20 15:08:15 +00:00
}
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-09-05 21:44:11 +00:00
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 + + )
{
2012-04-30 21:55:22 +00:00
2012-09-12 22:30:32 +00:00
Ogre : : Vector3 coord = it - > second - > getPosition ( ) ;
2012-04-30 21:55:22 +00:00
if ( it - > first = = " player " ) {
2012-08-04 19:43:33 +00:00
coord = playerphysics - > ps . origin ;
2012-09-05 21:44:11 +00:00
2012-04-30 21:55:22 +00:00
}
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-06-18 00:56:10 +00:00
handleToMesh [ handle ] = mesh ;
2012-08-12 04:36:49 +00:00
OEngine : : Physic : : RigidBody * body = mEngine - > createAndAdjustRigidBody ( mesh , handle , scale , position , rotation ) ;
2011-08-01 13:55:36 +00:00
mEngine - > addRigidBody ( body ) ;
}
void PhysicsSystem : : addActor ( const std : : string & handle , const std : : string & mesh ,
2012-09-04 00:32:20 +00:00
const Ogre : : Vector3 & position , float scale , const Ogre : : Quaternion & rotation )
2011-08-01 13:55:36 +00:00
{
//TODO:optimize this. Searching the std::map isn't very efficient i think.
2012-09-04 00:32:20 +00:00
mEngine - > addCharacter ( handle , mesh , position , scale , rotation ) ;
2011-08-01 13:55:36 +00:00
}
void PhysicsSystem : : removeObject ( const std : : string & handle )
{
//TODO:check if actor???
mEngine - > removeCharacter ( handle ) ;
mEngine - > removeRigidBody ( handle ) ;
mEngine - > deleteRigidBody ( handle ) ;
}
2012-08-14 22:04:58 +00:00
void PhysicsSystem : : moveObject ( const std : : string & handle , Ogre : : SceneNode * node )
2011-08-01 13:55:36 +00:00
{
2012-09-04 00:32:20 +00:00
Ogre : : Vector3 position = node - > getPosition ( ) ;
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
2012-09-04 00:32:20 +00:00
2012-08-15 00:29:48 +00:00
if ( dynamic_cast < btBoxShape * > ( body - > getCollisionShape ( ) ) = = NULL ) {
btTransform tr = body - > getWorldTransform ( ) ;
tr . setOrigin ( btVector3 ( position . x , position . y , position . z ) ) ;
body - > setWorldTransform ( tr ) ;
}
else
mEngine - > boxAdjustExternal ( handleToMesh [ handle ] , body , node - > getScale ( ) . x , position , node - > getOrientation ( ) ) ;
2011-09-04 07:48:50 +00:00
}
if ( OEngine : : Physic : : PhysicActor * act = mEngine - > getCharacter ( handle ) )
{
2012-09-04 00:32:20 +00:00
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
2011-09-04 07:48:50 +00:00
// 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 ) ) ;
2012-09-04 00:32:20 +00:00
}
2011-08-01 13:55:36 +00:00
}
}
2012-08-14 22:04:58 +00:00
void PhysicsSystem : : rotateObject ( const std : : string & handle , Ogre : : SceneNode * node )
2011-08-01 13:55:36 +00:00
{
2012-09-04 00:32:20 +00:00
Ogre : : Quaternion rotation = node - > getOrientation ( ) ;
if ( OEngine : : Physic : : PhysicActor * act = mEngine - > getCharacter ( handle ) )
2012-01-05 00:47:06 +00:00
{
2012-09-04 00:32:20 +00:00
//Needs to be changed
2012-09-15 17:23:49 +00:00
act - > setRotation ( rotation ) ;
2012-09-04 00:32:20 +00:00
}
2012-07-10 10:10:50 +00:00
if ( OEngine : : Physic : : RigidBody * body = mEngine - > getRigidBody ( handle ) )
{
2012-08-15 00:29:48 +00:00
if ( dynamic_cast < btBoxShape * > ( body - > getCollisionShape ( ) ) = = NULL )
body - > getWorldTransform ( ) . setRotation ( btQuaternion ( rotation . x , rotation . y , rotation . z , rotation . w ) ) ;
else
mEngine - > boxAdjustExternal ( handleToMesh [ handle ] , body , node - > getScale ( ) . x , node - > getPosition ( ) , rotation ) ;
2012-07-10 10:10:50 +00:00
}
2011-08-01 13:55:36 +00:00
}
2012-08-14 22:04:58 +00:00
void PhysicsSystem : : scaleObject ( const std : : string & handle , Ogre : : SceneNode * node )
2011-08-01 13:55:36 +00:00
{
2012-06-18 17:03:00 +00:00
if ( handleToMesh . find ( handle ) ! = handleToMesh . end ( ) )
{
removeObject ( handle ) ;
2012-07-10 11:23:41 +00:00
2012-08-14 22:04:58 +00:00
float scale = node - > getScale ( ) . x ;
Ogre : : Quaternion quat = node - > getOrientation ( ) ;
Ogre : : Vector3 vec = node - > getPosition ( ) ;
2012-06-18 17:03:00 +00:00
addObject ( handle , handleToMesh [ handle ] , quat , scale , vec ) ;
2012-06-20 17:14:27 +00:00
}
2012-09-12 22:30:32 +00:00
if ( OEngine : : Physic : : PhysicActor * act = mEngine - > getCharacter ( handle ) )
{
float scale = node - > getScale ( ) . x ;
act - > setScale ( scale ) ;
}
2011-08-01 13:55:36 +00:00
}
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
}
2012-07-24 18:08:23 +00:00
void PhysicsSystem : : insertObjectPhysics ( const MWWorld : : Ptr & ptr , const std : : string model ) {
2012-04-30 21:55:22 +00:00
2012-07-24 18:08:23 +00:00
Ogre : : SceneNode * node = ptr . getRefData ( ) . getBaseNode ( ) ;
2012-04-30 16:46:51 +00:00
2012-07-24 18:08:23 +00:00
addObject (
node - > getName ( ) ,
model ,
node - > getOrientation ( ) ,
node - > getScale ( ) . x ,
node - > getPosition ( ) ) ;
}
2012-03-25 02:03:08 +00:00
2012-07-24 18:08:23 +00:00
void PhysicsSystem : : insertActorPhysics ( const MWWorld : : Ptr & ptr , const std : : string model ) {
Ogre : : SceneNode * node = ptr . getRefData ( ) . getBaseNode ( ) ;
2012-09-04 00:32:20 +00:00
addActor ( node - > getName ( ) , model , node - > getPosition ( ) , node - > getScale ( ) . x , node - > getOrientation ( ) ) ;
2012-07-24 18:08:23 +00:00
}
2011-11-09 23:06:55 +00:00
2012-07-26 12:14:11 +00:00
bool PhysicsSystem : : getObjectAABB ( const MWWorld : : Ptr & ptr , Ogre : : Vector3 & min , Ogre : : Vector3 & max )
2012-07-24 18:08:23 +00:00
{
2012-07-24 16:22:11 +00:00
std : : string model = MWWorld : : Class : : get ( ptr ) . getModel ( ptr ) ;
2012-07-24 14:52:08 +00:00
if ( model . empty ( ) ) {
2012-07-25 14:58:55 +00:00
return false ;
2012-07-24 14:52:08 +00:00
}
2012-07-26 12:14:11 +00:00
btVector3 btMin , btMax ;
float scale = ptr . getCellRef ( ) . scale ;
mEngine - > getObjectAABB ( model , scale , btMin , btMax ) ;
2011-11-09 23:06:55 +00:00
2012-07-26 12:14:11 +00:00
min . x = btMin . x ( ) ;
min . y = btMin . y ( ) ;
min . z = btMin . z ( ) ;
max . x = btMax . x ( ) ;
max . y = btMax . y ( ) ;
max . z = btMax . z ( ) ;
2012-07-25 14:58:55 +00:00
return true ;
2012-07-24 18:08:23 +00:00
}
2012-08-17 06:10:37 +00:00
void PhysicsSystem : : updatePlayerData ( Ogre : : Vector3 & eyepos , float pitch , float yaw )
{
mPlayerData . eyepos = eyepos ;
mPlayerData . pitch = pitch ;
mPlayerData . yaw = yaw ;
}
2011-08-01 13:55:36 +00:00
}