
I connect two bodies but there is no connection. When I drag one of the bodies around and there is no slightest change to another body. And i keep getting crashes.

Moderators: Sascha Willems, walaber
Slider::Slider( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos, const Ogre::Vector3& pin ) : Joint()
{
m_world = world;
if (parent)
{
m_joint = NewtonConstraintCreateSlider( world->getNewtonWorld(), &pos.x, &pin.x,
child->getNewtonBody(), parent->getNewtonBody() );
}
else
{
m_joint = NewtonConstraintCreateSlider( world->getNewtonWorld(), &pos.x, &pin.x,
child->getNewtonBody(), NULL );
}
NewtonJointSetUserData( m_joint, this );
NewtonJointSetDestructor( m_joint, destructor );
NewtonSliderSetUserCallback( m_joint, newtonCallback );
m_callback = NULL;
}
Slider::~Slider()
{
}
Ogre::Vector3 Slider::getJointForce() const
{
Ogre::Vector3 ret;
NewtonSliderGetJointForce( m_joint, &ret.x );
return ret;
}
unsigned _CDECL Slider::newtonCallback( const NewtonJoint* slider, NewtonHingeSliderUpdateDesc* desc )
{
Slider* me = (Slider*)NewtonJointGetUserData( slider );
me->m_desc = desc;
me->m_retval = 0;
if (me->m_callback)
(*me->m_callback)( me );
me->m_desc = NULL;
return me->m_retval;
}
/////// CALLBACK FUNCTIONS ///////
void Slider::setCallbackAccel( Ogre::Real accel )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_accel = (float)accel;
}
}
void Slider::setCallbackFrictionMin( Ogre::Real min )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_minFriction = (float)min;
}
}
void Slider::setCallbackFrictionMax( Ogre::Real max )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_maxFriction = (float)max;
}
}
Ogre::Real Slider::getCallbackTimestep() const
{
if (m_desc)
return (Ogre::Real)m_desc->m_timestep;
else
return 0.0;
}
Ogre::Real Slider::calculateStopAccel( Ogre::Real dist ) const
{
if (m_desc)
return (Ogre::Real)NewtonSliderCalculateStopAccel( m_joint, m_desc, (float)dist );
else
return 0.0;
}
class _OgreNewtExport Slider : public Joint
{
public:
//! custom slider callback function.
/*!
use the setCallback() function to assign your custom function to the joint.
*/
typedef void(*SliderCallback)( Slider* me );
//! constructor
/*!
\param world pointer to the OgreNewt::World
\param child pointer to the child rigid body.
\param parent pointer to the parent rigid body. pass NULL to make the world itself the parent (aka a rigid joint)
\param pin direction of the joint pin in global space
*/
Slider( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos, const Ogre::Vector3& pin );
//! destructor.
~Slider();
//! get position of child along the pin
Ogre::Real getJointPosit() const { return (Ogre::Real)NewtonSliderGetJointPosit( m_joint ); }
//! get rotational velocity along the pin
Ogre::Real getJointVeloc() const { return (Ogre::Real)NewtonSliderGetJointVeloc( m_joint ); }
//! get force on the joint.
Ogre::Vector3 getJointForce() const;
//! set a custom callback for controlling this joint.
/*!
Joint callbacks allow you to make complex joint behavior such as limits or motors. just make a custom static function that
accepts a pointer to a OgreNewt::BasicJoints::Slider as the single parameter. this function will be called automatically every
time you upate the World.
*/
void setCallback( SliderCallback callback ) { m_callback = callback; }
////////// CALLBACK COMMANDS ///////////
// the following commands are only valid from inside a hinge callback function
//! set the acceleration along the pin.
/*!
This command is only valid when used inside a custom Slider callback.
*/
void setCallbackAccel( Ogre::Real accel );
//! set minimum friction for the joint
/*!
This command is only valid when used inside a custom Slider callback.
*/
void setCallbackFrictionMin( Ogre::Real min );
//! set maximum friction for the joint.
/*!
This command is only valid when used inside a custom Slider callback.
*/
void setCallbackFrictionMax( Ogre::Real max );
//! get current physics timestep.
/*!
This command is only valid when used inside a custom Slider callback.
*/
Ogre::Real getCallbackTimestep() const;
//! calculate the acceleration neccesary to stop the joint at the specified distance.
/*!
For implementing joint limits.
This command is only valid when used inside a custom Slider callback.
*/
Ogre::Real calculateStopAccel( Ogre::Real dist ) const;
protected:
//! newton callback. used internally.
static unsigned _CDECL newtonCallback( const NewtonJoint* slider, NewtonHingeSliderUpdateDesc* desc );
SliderCallback m_callback;
NewtonHingeSliderUpdateDesc* m_desc;
unsigned m_retval;
};
std::vector<SceneNodeClass::TSN> tmplt;
SceneNodeClass::TSN t = {"cali/cali_box_1m.mesh", Ogre::Vector3(0,0,0), Ogre::Quaternion::IDENTITY, Ogre::Vector3(1,1,1)};
tmplt.push_back(t);
//my system for creating objects...works with no problems
SceneNodeManager::getSingleton().CreateMesh("box1",tmplt,Ogre::Vector3(0,10,0),Ogre::Quaternion::IDENTITY,Ogre::Vector3(1,1,1));
PhysicObject* po1 = ObjectManager::getSingleton().createBody("box1",false,Ogre::Vector3::ZERO,800,false);
SceneNodeManager::getSingleton().CreateMesh("box2",tmplt,Ogre::Vector3(0,10,2),Ogre::Quaternion::IDENTITY,Ogre::Vector3(1,1,1));
PhysicObject* po2 = ObjectManager::getSingleton().createBody("box2",false,Ogre::Vector3::ZERO,800,false);
//creation of slider...
OgreNewt::BasicJoints::Slider* sl = new OgreNewt::BasicJoints::Slider(m_World,po1->getOgreNewtBody(),po2->getOgreNewtBody(),Ogre::Vector3(0,10,1),Ogre::Vector3::UNIT_Y);
//Ogre::Vector3::UNIT_Y should be Vector3(0.0,1.0,0.0)
/*
OgreNewt Library
Ogre implementation of Newton Game Dynamics SDK
OgreNewt basically has no license, you may use any or all of the library however you desire... I hope it can help you in any way.
by Walaber
some changes by melven
*/
#ifndef _INCLUDE_OGRENEWT_JOINT
#define _INCLUDE_OGRENEWT_JOINT
#include "OgreNewt_Prerequisites.h"
// OgreNewt namespace. all functions and classes use this namespace.
namespace OgreNewt
{
//! base class for all joints.
/*!
this class is inherited by all other specific joint types.
*/
class _OgreNewtExport Joint
{
public:
//! constructor
Joint();
//! destructor
virtual ~Joint();
//! returns collision state
/*!
The collision state determines whether collision should be calculated between the parent and child bodies of the joint.
\return integer value. 1 = collision on, 0 = collision off.
*/
int getCollisionState() const { return NewtonJointGetCollisionState( m_joint ); }
//! sets the collision state
/*!
The collision state determines whether collision should be calculated between the parent and child bodies of the joint.
\param state integer value. 1 = collision on, 0 = collision off.
*/
void setCollisionState( int state ) const { NewtonJointSetCollisionState( m_joint, state ); }
//! get joint stiffness
/*!
Joint stiffness adjusts how much "play" the joint can have. high stiffness = very small play, but more likely to become unstable.
\return float representing joint stiffness in range [0,1]
*/
Ogre::Real getStiffness() const { return (Ogre::Real)NewtonJointGetStiffness( m_joint ); }
//! set joint stiffness
/*!
Joint stiffness adjusts how much "play" the joint can have. high stiffness = very small play, but more likely to become unstable.
\param stiffness float representing joint stiffness in range [0,1]
*/
void setStiffness( Ogre::Real stiffness ) const { NewtonJointSetStiffness( m_joint, stiffness ); }
const OgreNewt::World* getWorld(void) const {return m_world;}
//! set user data for this joint
/*!
user data can be used to connect this class to other user classes through the use of this general pointer.
*/
#ifndef OGRENEWT_NO_OGRE_ANY
void setUserData( const Ogre::Any& data ) { m_userdata = data; }
#else
void setUserData( void* data ) { m_userdata = data; }
#endif
//! get user data for this joint
/*!
user data can be used to connect this class to other user classes through the use of this general pointer.
*/
#ifndef OGRENEWT_NO_OGRE_ANY
const Ogre::Any& getUserData() const { return m_userdata; }
#else
void* getUserData() const { return m_userdata; }
#endif
protected:
NewtonJoint* m_joint;
const OgreNewt::World* m_world;
#ifndef OGRENEWT_NO_OGRE_ANY
Ogre::Any m_userdata;
#else
void* m_userdata;
#endif
static void _CDECL destructor( const NewtonJoint* me );
};
//! CustomJoint
/*!
this class represents a basic class for creating user-defined joints. this class must be inherited to create discreet joints.
*/
class _OgreNewtExport CustomJoint : public Joint
{
public:
//! constructor
CustomJoint( unsigned int maxDOF, const Body* body0, const Body* body1 );
//! destructor
virtual ~CustomJoint();
//! must be over-written for a functioning joint.
virtual void submitConstraint( Ogre::Real timeStep, int threadIndex ) = 0;
//! can be overwritten, empty as default
virtual void feedbackCollector( Ogre::Real timeSte, int threadIndex ) {}
//! find the local orientation and position of the joint with regards to the 2 bodies in the joint.
void pinAndDirToLocal( const Ogre::Vector3& pinpt, const Ogre::Vector3& pindir, Ogre::Quaternion& localOrient0, Ogre::Vector3& localPos0, Ogre::Quaternion& localOrient1, Ogre::Vector3& localPos1 ) const;
//! find the global orientation and position of the joint with regards to the a body in the joint.
void localToGlobal( const Ogre::Quaternion& localOrient, const Ogre::Vector3& localPos, Ogre::Quaternion& globalOrient, Ogre::Vector3& globalPos, int bodyIndex = 0 ) const;
//! find the local orientation and position of the joint with regards to the a body in the joint.
void globalToLocal( const Ogre::Quaternion& localOrient, const Ogre::Vector3& localPos, Ogre::Quaternion& globalOrient, Ogre::Vector3& globalPos, int bodyIndex = 0 ) const;
//! add a linear row to the constraint.
void addLinearRow( const Ogre::Vector3& pt0, const Ogre::Vector3& pt1, const Ogre::Vector3& dir ) const;
//! add an angular row to the constraint.
void addAngularRow( Ogre::Radian relativeAngleError, const Ogre::Vector3& dir ) const;
//! set the general jacobian rows directly.
void addGeneralRow( const Ogre::Vector3& linear0, const Ogre::Vector3& angular0, const Ogre::Vector3& linear1, const Ogre::Vector3& angular1 ) const;
//! set row minimum friction
void setRowMinimumFriction( Ogre::Real friction ) const;
//! set row maximum friction
void setRowMaximumFriction( Ogre::Real friction ) const;
//! set row acceleration
void setRowAcceleration( Ogre::Real accel ) const;
//! set row stiffness
void setRowStiffness( Ogre::Real stiffness ) const;
//! apply a spring to this row, allowing for joints with spring behaviour in 1 or more DoF's
/*!
\param springK float spring constant.
\param springD float natural rest state distance of the spring.
*/
void setRowSpringDamper( Ogre::Real springK, Ogre::Real springD ) const;
//! retrieve the force acting on the current row.
Ogre::Real getRowForce( int row ) const { return NewtonUserJointGetRowForce( m_joint, row ); }
//! pin vector to arbitrary quaternion utility function.
Ogre::Quaternion grammSchmidt( const Ogre::Vector3& pin ) const;
protected:
unsigned int m_maxDOF;
const OgreNewt::Body* m_body0;
const OgreNewt::Body* m_body1;
private:
//! newton callback. used internally.
static void _CDECL newtonSubmitConstraint( const NewtonJoint* me, float timeStep, int threadIndex );
static void _CDECL newtonGetInfo( const NewtonJoint* me, NewtonJointRecord* info );
static void _CDECL newtonFeedbackCollector( const NewtonJoint* me, float timeStep, int threadIndex );
};
} // end NAMESPACE OgreNewt
#endif
// _INCLUDE_OGRENEWT_JOINT
#include "OgreNewt_Joint.h"
#include "OgreNewt_Body.h"
#include "OgreNewt_World.h"
namespace OgreNewt
{
Joint::Joint()
{
// nothing here
}
Joint::~Joint()
{
if(m_joint)
{
if (NewtonJointGetUserData(m_joint))
{
NewtonJointSetDestructor( m_joint, NULL );
NewtonDestroyJoint( m_world->getNewtonWorld(), m_joint );
}
}
}
void _CDECL Joint::destructor( const NewtonJoint* me )
{
Joint* jnt;
jnt = (Joint*)NewtonJointGetUserData( me );
NewtonJointSetDestructor( me, NULL );
NewtonJointSetUserData( me, NULL );
delete jnt;
}
CustomJoint::CustomJoint( unsigned int maxDOF, const Body* body0, const Body* body1 ) : Joint()
{
m_maxDOF = maxDOF;
m_body0 = body0;
m_body1 = body1;
m_world = m_body0->getWorld();
if (body1)
m_joint = NewtonConstraintCreateUserJoint( m_world->getNewtonWorld(), m_maxDOF,
CustomJoint::newtonSubmitConstraint, CustomJoint::newtonGetInfo,
m_body0->getNewtonBody(), m_body1->getNewtonBody() );
else
m_joint = NewtonConstraintCreateUserJoint( m_world->getNewtonWorld(), m_maxDOF,
CustomJoint::newtonSubmitConstraint, CustomJoint::newtonGetInfo,
m_body0->getNewtonBody(), NULL );
NewtonJointSetUserData (m_joint, this);
NewtonJointSetDestructor (m_joint, destructor);
NewtonUserJointSetFeedbackCollectorCallback( m_joint, CustomJoint::newtonFeedbackCollector );
}
CustomJoint::~CustomJoint()
{
}
void CustomJoint::pinAndDirToLocal( const Ogre::Vector3& pinpt, const Ogre::Vector3& pindir,
Ogre::Quaternion& localOrient0, Ogre::Vector3& localPos0, Ogre::Quaternion& localOrient1, Ogre::Vector3& localPos1 ) const
{
localOrient0 = localOrient1 = Ogre::Quaternion::IDENTITY;
localPos0 = localPos1 = Ogre::Vector3::ZERO;
Ogre::Quaternion bodyOrient0 = Ogre::Quaternion::IDENTITY;
Ogre::Quaternion bodyOrient1 = Ogre::Quaternion::IDENTITY;
Ogre::Vector3 bodyPos0 = Ogre::Vector3::ZERO;
Ogre::Vector3 bodyPos1 = Ogre::Vector3::ZERO;
Ogre::Quaternion pinOrient = grammSchmidt(pindir);
m_body0->getPositionOrientation( bodyPos0, bodyOrient0 );
if (m_body1)
m_body1->getPositionOrientation( bodyPos1, bodyOrient1 );
localPos0 = bodyOrient0.Inverse() * (pinpt - bodyPos0);
localOrient0 = pinOrient * bodyOrient0.Inverse();
localPos1 = bodyOrient1.Inverse() * (pinpt - bodyPos1);
localOrient1 = pinOrient * bodyOrient1.Inverse();
}
void CustomJoint::localToGlobal( const Ogre::Quaternion& localOrient, const Ogre::Vector3& localPos, Ogre::Quaternion& globalOrient, Ogre::Vector3& globalPos, int bodyIndex ) const
{
globalOrient = Ogre::Quaternion::IDENTITY;
globalPos= Ogre::Vector3::ZERO;
const Body* bdy = NULL;
if (bodyIndex == 0)
bdy = m_body0;
else if (m_body1)
bdy = m_body1;
Ogre::Quaternion bodyOrient = Ogre::Quaternion::IDENTITY;
Ogre::Vector3 bodyPos = Ogre::Vector3::ZERO;
if (bdy)
bdy->getPositionOrientation( bodyPos, bodyOrient );
globalPos = (bodyOrient * localPos) + bodyPos;
globalOrient = bodyOrient * localOrient;
}
void CustomJoint::globalToLocal( const Ogre::Quaternion& globalOrient, const Ogre::Vector3& globalPos, Ogre::Quaternion& localOrient, Ogre::Vector3& localPos, int bodyIndex ) const
{
localOrient = Ogre::Quaternion::IDENTITY;
localPos= Ogre::Vector3::ZERO;
const Body* bdy = NULL;
if (bodyIndex == 0)
bdy = m_body0;
else if (m_body1)
bdy = m_body1;
Ogre::Quaternion bodyOrient = Ogre::Quaternion::IDENTITY;
Ogre::Vector3 bodyPos = Ogre::Vector3::ZERO;
if (bdy)
bdy->getPositionOrientation( bodyPos, bodyOrient );
Ogre::Quaternion bodyOrientInv = bodyOrient.Inverse();
localOrient = bodyOrientInv * globalOrient;
localPos = bodyOrientInv * (globalPos - bodyPos);
}
void CustomJoint::addLinearRow( const Ogre::Vector3& pt0, const Ogre::Vector3& pt1, const Ogre::Vector3& dir ) const
{
NewtonUserJointAddLinearRow( m_joint, &pt0.x, &pt1.x, &dir.x );
}
void CustomJoint::addAngularRow( Ogre::Radian relativeAngleError, const Ogre::Vector3& dir ) const
{
NewtonUserJointAddAngularRow( m_joint, relativeAngleError.valueRadians(), &dir.x );
}
void CustomJoint::addGeneralRow(const Ogre::Vector3& linear0, const Ogre::Vector3& angular0, const Ogre::Vector3& linear1, const Ogre::Vector3& angular1) const
{
float jacobian0[6], jacobian1[6];
jacobian0[0] = linear0.x;
jacobian0[1] = linear0.y;
jacobian0[2] = linear0.z;
jacobian0[3] = angular0.x;
jacobian0[4] = angular0.y;
jacobian0[5] = angular0.z;
jacobian1[0] = linear1.x;
jacobian1[1] = linear1.y;
jacobian1[2] = linear1.z;
jacobian1[3] = angular1.x;
jacobian1[4] = angular1.y;
jacobian1[5] = angular1.z;
NewtonUserJointAddGeneralRow( m_joint, jacobian0, jacobian1 );
}
void CustomJoint::setRowMinimumFriction( Ogre::Real friction ) const
{
NewtonUserJointSetRowMinimumFriction( m_joint, friction );
}
void CustomJoint::setRowMaximumFriction( Ogre::Real friction ) const
{
NewtonUserJointSetRowMaximumFriction( m_joint, friction );
}
void CustomJoint::setRowAcceleration( Ogre::Real accel ) const
{
NewtonUserJointSetRowAcceleration( m_joint, accel );
}
void CustomJoint::setRowStiffness( Ogre::Real stiffness ) const
{
NewtonUserJointSetRowStiffness( m_joint, stiffness );
}
void CustomJoint::setRowSpringDamper(Ogre::Real springK, Ogre::Real springD) const
{
NewtonUserJointSetRowSpringDamperAcceleration( m_joint, springK, springD );
}
void _CDECL CustomJoint::newtonSubmitConstraint( const NewtonJoint* me, float timeStep, int threadIndex )
{
CustomJoint* j = (CustomJoint*)NewtonJointGetUserData( me );
j->submitConstraint( (Ogre::Real)timeStep, threadIndex );
}
void _CDECL CustomJoint::newtonFeedbackCollector( const NewtonJoint* me, float timeStep, int threadIndex )
{
CustomJoint* j = (CustomJoint*)NewtonJointGetUserData( me );
j->feedbackCollector( (Ogre::Real)timeStep, threadIndex );
}
void _CDECL CustomJoint::newtonGetInfo(const NewtonJoint *me, NewtonJointRecord *info)
{
CustomJoint* j = (CustomJoint*)NewtonJointGetUserData( me );
}
Ogre::Quaternion CustomJoint::grammSchmidt( const Ogre::Vector3& pin ) const
{
Ogre::Vector3 front, up, right;
front = pin;
front.normalise();
if (Ogre::Math::Abs( front.z ) > 0.577f)
right = front.crossProduct( Ogre::Vector3(-front.y, front.z, 0.0f) );
else
right = front.crossProduct( Ogre::Vector3(-front.y, front.x, 0.0f) );
right.normalise();
up = right.crossProduct( front );
Ogre::Matrix3 ret;
ret.FromAxes( front, up, right );
Ogre::Quaternion quat;
quat.FromRotationMatrix( ret );
return quat;
}
} // end NAMESPACE OgreNewt
/*
OgreNewt Library
Ogre implementation of Newton Game Dynamics SDK
OgreNewt basically has no license, you may use any or all of the library however you desire... I hope it can help you in any way.
by Walaber
some changes by melven
*/
#ifndef _INCLUDE_OGRENEWT_BASICJOINTS
#define _INCLUDE_OGRENEWT_BASICJOINTS
#include "OgreNewt_Prerequisites.h"
#include "OgreNewt_Joint.h"
// OgreNewt namespace. all functions and classes use this namespace.
namespace OgreNewt
{
//! Namespace for ready-made joints
namespace BasicJoints
{
//! Ball and Socket joint.
/*!
simple ball and socket joint, with limits.
*/
class _OgreNewtExport BallAndSocket : public Joint
{
public:
//! custom ballandsocket callback function.
/*!
use the setCallback() function to assign your custom function to the joint.
*/
typedef void(*BallAndSocketCallback)( BallAndSocket* me, Ogre::Real timestep );
//! constructor
/*!
\param world pointer to the OgreNewt::World
\param child pointer to the child rigid body.
\param parent pointer to the parent rigid body. pass NULL to make the world itself the parent (aka a rigid joint)
\param pos position of the joint in global space
*/
BallAndSocket( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos );
//! destructor.
~BallAndSocket();
//! retrieve the current joint angle
Ogre::Vector3 getJointAngle() const;
//! retrieve the current joint omega
Ogre::Vector3 getJointOmega() const;
//! retrieve the current joint force.
/*!
This can be used to find the "stress" on the joint. you can do special effects like break the joint if the force exceedes some value, etc.
*/
Ogre::Vector3 getJointForce() const;
//! set limits for the joints rotation
/*!
\param pin pin direction in global space
\param maxCone max angle for "swing" (in radians)
\param maxTwist max angle for "twist" (in radians)
*/
void setLimits( const Ogre::Vector3& pin, Ogre::Radian maxCone, Ogre::Radian maxTwist ) const { NewtonBallSetConeLimits( m_joint, &pin.x, (float)maxCone.valueRadians(), (float)maxTwist.valueRadians() ); }
//! set callback function
void setCallback(BallAndSocketCallback *callback) {m_callback = callback;}
protected:
BallAndSocketCallback *m_callback;
private:
static void _CDECL newtonBallCallback(const NewtonJoint* ball, float timestep);
};
//! hinge joint.
/*!
simple hinge joint. implement motors/limits through a callback.
*/
class _OgreNewtExport Hinge : public Joint
{
public:
//! custom hinge callback function.
/*!
use the setCallback() function to assign your custom function to the joint.
*/
typedef void(*HingeCallback)( Hinge* me );
//! constructor
/*!
\param world pointer to the OgreNewt::World
\param child pointer to the child rigid body.
\param parent pointer to the parent rigid body. pass NULL to make the world itself the parent (aka a rigid joint)
\param pin direction of the joint pin in global space
*/
Hinge( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos, const Ogre::Vector3& pin );
//! destructor
~Hinge();
//! retrieve the angle around the pin.
Ogre::Radian getJointAngle() const { return Ogre::Radian(NewtonHingeGetJointAngle( m_joint )); }
//! retrieve the rotational velocity around the pin.
Ogre::Real getJointOmega() const { return (Ogre::Real)NewtonHingeGetJointOmega( m_joint ); }
//! get the force on the joint.
Ogre::Vector3 getJointForce() const;
//! set a custom callback for controlling this joint.
/*!
Joint callbacks allow you to make complex joint behavior such as limits or motors. just make a custom static function that
accepts a pointer to a OgreNewt::BasicJoints::Hinge as the single parameter. this function will be called automatically every
time you upate the World.
*/
void setCallback( HingeCallback callback ) { m_callback = callback; }
////////// CALLBACK COMMANDS ///////////
// the following commands are only valid from inside a hinge callback function
//! set acceleration around the joint pin
/*!
This command is only valid when used inside a custom Hinge callback.
*/
void setCallbackAccel( Ogre::Real accel );
//! set minimum joint friction.
/*!
This command is only valid when used inside a custom Hinge callback.
*/
void setCallbackFrictionMin( Ogre::Real min );
//! set maximum joint friction
/*!
This command is only valid when used inside a custom Hinge callback.
*/
void setCallbackFrictionMax( Ogre::Real max );
//! get the current physics timestep.
/*!
This command is only valid when used inside a custom Hinge callback.
*/
Ogre::Real getCallbackTimestep() const;
//! calculate the acceleration neccesary to stop the joint at the specified angle.
/*!
For implementing joint limits.
This command is only valid when used inside a custom Hinge callback.
*/
Ogre::Real calculateStopAlpha( Ogre::Radian angle ) const;
protected:
//! newton callback, used internally.
static unsigned _CDECL newtonCallback( const NewtonJoint* hinge, NewtonHingeSliderUpdateDesc* desc );
HingeCallback m_callback;
NewtonHingeSliderUpdateDesc* m_desc;
unsigned m_retval;
};
//! slider joint.
/*!
simple slider joint. implement motors/limits through a callback.
*/
class _OgreNewtExport Slider : public Joint
{
public:
//! custom slider callback function.
/*!
use the setCallback() function to assign your custom function to the joint.
*/
typedef void(*SliderCallback)( Slider* me );
//! constructor
/*!
\param world pointer to the OgreNewt::World
\param child pointer to the child rigid body.
\param parent pointer to the parent rigid body. pass NULL to make the world itself the parent (aka a rigid joint)
\param pin direction of the joint pin in global space
*/
Slider( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos, const Ogre::Vector3& pin );
//! destructor.
~Slider();
//! get position of child along the pin
Ogre::Real getJointPosit() const { return (Ogre::Real)NewtonSliderGetJointPosit( m_joint ); }
//! get rotational velocity along the pin
Ogre::Real getJointVeloc() const { return (Ogre::Real)NewtonSliderGetJointVeloc( m_joint ); }
//! get force on the joint.
Ogre::Vector3 getJointForce() const;
//! set a custom callback for controlling this joint.
/*!
Joint callbacks allow you to make complex joint behavior such as limits or motors. just make a custom static function that
accepts a pointer to a OgreNewt::BasicJoints::Slider as the single parameter. this function will be called automatically every
time you upate the World.
*/
void setCallback( SliderCallback callback ) { m_callback = callback; }
////////// CALLBACK COMMANDS ///////////
// the following commands are only valid from inside a hinge callback function
//! set the acceleration along the pin.
/*!
This command is only valid when used inside a custom Slider callback.
*/
void setCallbackAccel( Ogre::Real accel );
//! set minimum friction for the joint
/*!
This command is only valid when used inside a custom Slider callback.
*/
void setCallbackFrictionMin( Ogre::Real min );
//! set maximum friction for the joint.
/*!
This command is only valid when used inside a custom Slider callback.
*/
void setCallbackFrictionMax( Ogre::Real max );
//! get current physics timestep.
/*!
This command is only valid when used inside a custom Slider callback.
*/
Ogre::Real getCallbackTimestep() const;
//! calculate the acceleration neccesary to stop the joint at the specified distance.
/*!
For implementing joint limits.
This command is only valid when used inside a custom Slider callback.
*/
Ogre::Real calculateStopAccel( Ogre::Real dist ) const;
protected:
//! newton callback. used internally.
static unsigned _CDECL newtonCallback( const NewtonJoint* slider, NewtonHingeSliderUpdateDesc* desc );
SliderCallback m_callback;
NewtonHingeSliderUpdateDesc* m_desc;
unsigned m_retval;
};
//! this class represents a Universal joint.
/*!
simple universal joint. implement motors/limits through a callback.
*/
class _OgreNewtExport Universal : public Joint
{
public:
//! custom universal callback function.
/*!
use the setCallback() function to assign your custom function to the joint.
*/
typedef void(*UniversalCallback)( Universal* me );
//! constructor
/*!
\param world pointer to the OgreNewt::World
\param child pointer to the child rigid body.
\param parent pointer to the parent rigid body. pass NULL to make the world itself the parent (aka a rigid joint)
\param pos position of the joint in global space
\param pin0 direction of the first axis of rotation in global space
\param pin1 direction of the second axis of rotation in global space
*/
Universal( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos, const Ogre::Vector3& pin0, const Ogre::Vector3& pin1 );
//! destructor
~Universal();
//! get the angle around pin0.
Ogre::Radian getJointAngle0() const { return Ogre::Radian(NewtonUniversalGetJointAngle0( m_joint )); }
//! get the angle around pin1.
Ogre::Radian getJointAngle1() const { return Ogre::Radian(NewtonUniversalGetJointAngle1( m_joint )); }
//! get the rotational velocity around pin0.
Ogre::Real getJointOmega0() const { return (Ogre::Real)NewtonUniversalGetJointOmega0( m_joint ); }
//! get the rotational velocity around pin1.
Ogre::Real getJointOmega1() const { return (Ogre::Real)NewtonUniversalGetJointOmega1( m_joint ); }
//! get the force on the joint.
Ogre::Vector3 getJointForce() const;
//! set a custom callback for controlling this joint.
/*!
Joint callbacks allow you to make complex joint behavior such as limits or motors. just make a custom static function that
accepts a pointer to a OgreNewt::BasicJoints::Universal as the single parameter. this function will be called automatically every
time you upate the World.
*/
void setCallback( UniversalCallback callback ) { m_callback = callback; }
////////// CALLBACK COMMANDS ///////////
// the following commands are only valid from inside a hinge callback function
//! set the acceleration around a particular pin.
/*
this function can only be called from within a custom callback.
\param accel desired acceleration
\param axis which pin to use (0 or 1)
*/
void setCallbackAccel( Ogre::Real accel, unsigned axis );
//! set the minimum friction around a particular pin
/*
this function can only be called from within a custom callback.
\param min minimum friction
\param axis which pin to use (0 or 1)
*/
void setCallbackFrictionMin( Ogre::Real min, unsigned axis );
//! set the maximum friction around a particular pin.
/*
this function can only be called from within a custom callback.
\param max maximum friction
\param axis which pin to use (0 or 1)
*/
void setCallbackFrictionMax( Ogre::Real max, unsigned axis );
//! get the current phsics timestep.
/*
this function can only be called from within a custom callback.
*/
Ogre::Real getCallbackTimestep() const;
//! calculate the acceleration neccesary to stop the joint at the specified angle on pin 0.
/*!
For implementing joint limits.
This command is only valid when used inside a custom callback.
*/
Ogre::Real calculateStopAlpha0( Ogre::Real angle ) const;
//! calculate the acceleration neccesary to stop the joint at the specified angle on pin 1.
/*!
For implementing joint limits.
This command is only valid when used inside a custom callback.
*/
Ogre::Real calculateStopAlpha1( Ogre::Real angle ) const;
protected:
//! newton callback. used internally.
static unsigned _CDECL newtonCallback( const NewtonJoint* universal, NewtonHingeSliderUpdateDesc* desc );
UniversalCallback m_callback;
NewtonHingeSliderUpdateDesc* m_desc;
unsigned m_retval;
};
//! UpVector joint.
/*!
simple upvector joint. upvectors remove all rotation except for a single pin. useful for character controllers, etc.
*/
class _OgreNewtExport UpVector : public Joint
{
public:
//! constructor
/*
\param world pointer to the OgreNewt::World.
\param body pointer to the body to apply the upvector to.
\param pin direction of the upvector in global space.
*/
UpVector( const World* world, const Body* body, const Ogre::Vector3& pin );
//! destructor
~UpVector();
//! set the pin direction.
/*
by calling this function in realtime, you can effectively "animate" the pin.
*/
void setPin( const Ogre::Vector3& pin ) const { NewtonUpVectorSetPin( m_joint, &pin.x ); }
//! get the current pin direction.
Ogre::Vector3 getPin() const;
};
} // end NAMESPACE BasicJoints
//! namespace for pre-built custom joints
namespace PrebuiltCustomJoints
{
//! Custom2DJoint class
/*!
This class represents a joint that limits movement to a plane, and rotation only around the normal of that
plane. This can be used to create simple 2D simulations. it also supports limits and acceleration for spinning.
This joint has been used in a few projects, but is not 100% fully-tested.
*/
class _OgreNewtExport Custom2DJoint : public OgreNewt::CustomJoint
{
public:
//! constructor
Custom2DJoint( const OgreNewt::Body* body, const Ogre::Vector3& pin );
//! destructor
~Custom2DJoint() {}
//! overloaded function that applies the actual constraint.
void submitConstraint( Ogre::Real timeStep, int threadIndex );
//! get the current angle of the joint.
Ogre::Radian getAngle() const { return mAngle; }
//! set rotational limits for the joint.
void setLimits( Ogre::Degree min, Ogre::Degree max ) { mMin = min, mMax = max; }
//! sets whether to enable limits or not for the joint.
void setLimitsOn( bool onoff ) { mLimitsOn = onoff; }
//! returns whether limits are turned on or off for the joint.
bool getLimitsOn() const { return mLimitsOn; }
//! adds rotational acceleration to the joint (like a motor)
void addAccel( Ogre::Real accel ) { mAccel = accel; }
//! resets the joint angle to 0. this simply sets the internal variable to zero.
//! you might want to call this for example after resetting a body.
void resetAngle() { mAngle = Ogre::Radian(0.0f); }
//! get the pin.
Ogre::Vector3 getPin() { return mPin; }
private:
Ogre::Vector3 mPin;
Ogre::Quaternion mLocalOrient0, mLocalOrient1;
Ogre::Vector3 mLocalPos0, mLocalPos1;
Ogre::Radian mAngle;
Ogre::Radian mMin;
Ogre::Radian mMax;
bool mLimitsOn;
Ogre::Real mAccel;
};
//! CustomFixedJoint
/*!
This joint implements a fully fixed joint, which removes all DOF, creating a completely fixed connection between bodies.
This is probably the most expensive kind of joint, and should only be used when really needed.
*/
class _OgreNewtExport CustomRigidJoint : public OgreNewt::CustomJoint
{
public:
CustomRigidJoint( OgreNewt::Body* child, OgreNewt::Body* parent, Ogre::Vector3 dir, Ogre::Vector3 pos);
~CustomRigidJoint();
void submitConstraint( Ogre::Real timeStep, int threadIndex );
private:
Ogre::Vector3 mLocalPos0;
Ogre::Vector3 mLocalPos1;
Ogre::Quaternion mLocalOrient0;
Ogre::Quaternion mLocalOrient1;
};
//! CustomDryRollingFriction
/*!
* This joint is usefully to simulate the rolling friction of a rolling ball over a flat surface.
* Normally this is not important for non spherical objects, but for games like poll, pinball, bolling, golf
* or any other where the movement of balls is the main objective the rolling friction is a real big problem.
*/
/* // not tested yet
class _OgreNewtExport CustomDryRollingFriction : public OgreNewt::CustomJoint
{
public:
CustomDryRollingFriction( OgreNewt::Body* child, Ogre::Real radius, Ogre::Real rollingFrictionCoefficient );
~CustomDryRollingFriction();
void submitConstraint( Ogre::Real timestep, int threadIndex );
private:
Ogre::Real mFrictionCoefficient;
Ogre::Real mFrictionTorque;
OgreNewt::Body* mChild;
};
*/
} // end NAMESPACE PrebuiltCustomJoints
} // end NAMESPACE OgreNewt
#endif
// _INCLUDE_OGRENEWT_BASICJOINTS
#include "OgreNewt_BasicJoints.h"
#include "OgreNewt_World.h"
#include "OgreNewt_Body.h"
#ifdef __APPLE__
# include <Ogre/OgreLogManager.h>
# include <Ogre/OgreStringConverter.h>
#else
# include <OgreLogManager.h>
# include <OgreStringConverter.h>
#endif
namespace OgreNewt
{
namespace BasicJoints
{
BallAndSocket::BallAndSocket( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos ) : Joint()
{
m_world = world;
if (parent)
m_joint = NewtonConstraintCreateBall( world->getNewtonWorld(), &pos.x, child->getNewtonBody(), parent->getNewtonBody() );
else
m_joint = NewtonConstraintCreateBall( world->getNewtonWorld(), &pos.x, child->getNewtonBody(), NULL );
// all constructors inherited from Joint MUST call these 2 functions to make the joint function properly.
NewtonJointSetUserData( m_joint, this );
NewtonJointSetDestructor( m_joint, destructor );
m_callback = NULL;
}
BallAndSocket::~BallAndSocket()
{
// nothing, the ~Joint() function will take care of us.
}
Ogre::Vector3 BallAndSocket::getJointAngle() const
{
Ogre::Vector3 ret;
NewtonBallGetJointAngle( m_joint, &ret.x );
return ret;
}
Ogre::Vector3 BallAndSocket::getJointOmega() const
{
Ogre::Vector3 ret;
NewtonBallGetJointOmega( m_joint, &ret.x );
return ret;
}
Ogre::Vector3 BallAndSocket::getJointForce() const
{
Ogre::Vector3 ret;
NewtonBallGetJointForce( m_joint, &ret.x );
return ret;
}
void _CDECL BallAndSocket::newtonBallCallback(const NewtonJoint* ball, float timestep)
{
BallAndSocket* me = (BallAndSocket*)NewtonJointGetUserData(ball);
if( me->m_callback != NULL )
( *me->m_callback )(me, timestep);
}
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
Hinge::Hinge( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos, const Ogre::Vector3& pin ) : Joint()
{
m_world = world;
if (parent)
{
m_joint = NewtonConstraintCreateHinge( world->getNewtonWorld(), &pos.x, &pin.x,
child->getNewtonBody(), parent->getNewtonBody() );
}
else
{
m_joint = NewtonConstraintCreateHinge( world->getNewtonWorld(), &pos.x, &pin.x,
child->getNewtonBody(), NULL );
}
NewtonJointSetUserData( m_joint, this );
NewtonJointSetDestructor( m_joint, destructor );
NewtonHingeSetUserCallback( m_joint, newtonCallback );
m_callback = NULL;
}
Hinge::~Hinge()
{
}
Ogre::Vector3 Hinge::getJointForce() const
{
Ogre::Vector3 ret;
NewtonHingeGetJointForce( m_joint, &ret.x );
return ret;
}
unsigned _CDECL Hinge::newtonCallback( const NewtonJoint* hinge, NewtonHingeSliderUpdateDesc* desc )
{
Hinge* me = (Hinge*)NewtonJointGetUserData( hinge );
me->m_desc = desc;
me->m_retval = 0;
if (me->m_callback)
(*me->m_callback)( me );
me->m_desc = NULL;
return me->m_retval;
}
/////// CALLBACK FUNCTIONS ///////
void Hinge::setCallbackAccel( Ogre::Real accel )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_accel = (float)accel;
}
}
void Hinge::setCallbackFrictionMin( Ogre::Real min )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_minFriction = (float)min;
}
}
void Hinge::setCallbackFrictionMax( Ogre::Real max )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_maxFriction = (float)max;
}
}
Ogre::Real Hinge::getCallbackTimestep() const
{
if (m_desc)
return (Ogre::Real)m_desc->m_timestep;
else
return 0.0;
}
Ogre::Real Hinge::calculateStopAlpha( Ogre::Radian angle ) const
{
if (m_desc)
return (Ogre::Real)NewtonHingeCalculateStopAlpha( m_joint, m_desc, (float)angle.valueRadians() );
else
return 0.0;
}
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
Slider::Slider( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos, const Ogre::Vector3& pin ) : Joint()
{
m_world = world;
//std::cout << "EJ WTF pos" << pos << " pin" << pin << "\n";
float pi[3];float po[3];
pi[0] = pin.x;
pi[1] = pin.y;
pi[2] = pin.z;
po[0] = pos.x;
po[1] = pos.y;
po[2] = pos.z;
if (parent)
{
m_joint = NewtonConstraintCreateSlider( world->getNewtonWorld(), po, pi,
child->getNewtonBody(), parent->getNewtonBody() );
}
else
{
m_joint = NewtonConstraintCreateSlider( world->getNewtonWorld(), po, pi,
child->getNewtonBody(), NULL );
}
NewtonJointSetUserData( m_joint, this );
NewtonJointSetDestructor( m_joint, destructor );
NewtonSliderSetUserCallback( m_joint, newtonCallback );
m_callback = NULL;
}
Slider::~Slider()
{
}
Ogre::Vector3 Slider::getJointForce() const
{
Ogre::Vector3 ret;
NewtonSliderGetJointForce( m_joint, &ret.x );
return ret;
}
unsigned _CDECL Slider::newtonCallback( const NewtonJoint* slider, NewtonHingeSliderUpdateDesc* desc )
{
Slider* me = (Slider*)NewtonJointGetUserData( slider );
me->m_desc = desc;
me->m_retval = 0;
if (me->m_callback)
(*me->m_callback)( me );
me->m_desc = NULL;
return me->m_retval;
}
/////// CALLBACK FUNCTIONS ///////
void Slider::setCallbackAccel( Ogre::Real accel )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_accel = (float)accel;
}
}
void Slider::setCallbackFrictionMin( Ogre::Real min )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_minFriction = (float)min;
}
}
void Slider::setCallbackFrictionMax( Ogre::Real max )
{
if (m_desc)
{
m_retval = 1;
m_desc->m_maxFriction = (float)max;
}
}
Ogre::Real Slider::getCallbackTimestep() const
{
if (m_desc)
return (Ogre::Real)m_desc->m_timestep;
else
return 0.0;
}
Ogre::Real Slider::calculateStopAccel( Ogre::Real dist ) const
{
if (m_desc)
return (Ogre::Real)NewtonSliderCalculateStopAccel( m_joint, m_desc, (float)dist );
else
return 0.0;
}
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
Universal::Universal( const World* world, const OgreNewt::Body* child, const OgreNewt::Body* parent, const Ogre::Vector3& pos, const Ogre::Vector3& pin0, const Ogre::Vector3& pin1 ) : Joint()
{
m_world = world;
if (parent)
{
m_joint = NewtonConstraintCreateUniversal( world->getNewtonWorld(), &pos.x, &pin0.x, &pin1.x,
child->getNewtonBody(), parent->getNewtonBody() );
}
else
{
m_joint = NewtonConstraintCreateUniversal( world->getNewtonWorld(), &pos.x, &pin0.x, &pin1.x,
child->getNewtonBody(), NULL );
}
NewtonJointSetUserData( m_joint, this );
NewtonJointSetDestructor( m_joint, destructor );
NewtonUniversalSetUserCallback( m_joint, newtonCallback );
m_callback = NULL;
}
Universal::~Universal()
{
}
Ogre::Vector3 Universal::getJointForce() const
{
Ogre::Vector3 ret;
NewtonUniversalGetJointForce( m_joint, &ret.x );
return ret;
}
unsigned _CDECL Universal::newtonCallback( const NewtonJoint* universal, NewtonHingeSliderUpdateDesc* desc )
{
Universal* me = (Universal*)NewtonJointGetUserData( universal );
me->m_desc = desc;
me->m_retval = 0;
if (me->m_callback)
(*me->m_callback)( me );
me->m_desc = NULL;
return me->m_retval;
}
/////// CALLBACK FUNCTIONS ///////
void Universal::setCallbackAccel( Ogre::Real accel, unsigned int axis )
{
if (axis > 1) { return; }
if (m_desc)
{
m_retval |= axis;
m_desc[axis].m_accel = (float)accel;
}
}
void Universal::setCallbackFrictionMax( Ogre::Real max, unsigned int axis )
{
if (axis > 1) { return; }
if (m_desc)
{
m_retval |= axis;
m_desc[axis].m_maxFriction = (float)max;
}
}
void Universal::setCallbackFrictionMin( Ogre::Real min, unsigned int axis )
{
if (axis > 1) { return; }
if (m_desc)
{
m_retval |= axis;
m_desc[axis].m_minFriction = (float)min;
}
}
Ogre::Real Universal::getCallbackTimestep() const
{
if (m_desc)
return (Ogre::Real)m_desc->m_timestep;
else
return 0.0;
}
Ogre::Real Universal::calculateStopAlpha0( Ogre::Real angle ) const
{
if (m_desc)
return (Ogre::Real)NewtonUniversalCalculateStopAlpha0( m_joint, m_desc, (float)angle );
else
return 0.0;
}
Ogre::Real Universal::calculateStopAlpha1( Ogre::Real angle ) const
{
if (m_desc)
return (Ogre::Real)NewtonUniversalCalculateStopAlpha1( m_joint, m_desc, (float)angle );
else
return 0.0;
}
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
UpVector::UpVector( const World* world, const Body* body, const Ogre::Vector3& pin )
{
m_world = world;
m_joint = NewtonConstraintCreateUpVector( world->getNewtonWorld(), &pin.x, body->getNewtonBody() );
NewtonJointSetUserData( m_joint, this );
NewtonJointSetDestructor( m_joint, destructor );
}
UpVector::~UpVector()
{
}
Ogre::Vector3 UpVector::getPin() const
{
Ogre::Vector3 ret;
NewtonUpVectorGetPin( m_joint, &ret.x );
return ret;
}
} // end NAMESPACE BasicJoints
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
namespace PrebuiltCustomJoints
{
Custom2DJoint::Custom2DJoint(const OgreNewt::Body* body, const Ogre::Vector3& pin ) : CustomJoint( 4, body, NULL )
{
mPin = pin;
Ogre::Quaternion bodyorient;
Ogre::Vector3 bodypos;
body->getPositionOrientation( bodypos, bodyorient );
pinAndDirToLocal( bodypos, pin, mLocalOrient0, mLocalPos0, mLocalOrient1, mLocalPos1 );
// initialize variables
mMin = mMax = Ogre::Degree(0);
mLimitsOn = false;
mAccel = 0.0f;
}
void Custom2DJoint::submitConstraint( Ogre::Real timeStep, int threadIndex )
{
// get the global orientations.
Ogre::Quaternion globalOrient0, globalOrient1;
Ogre::Vector3 globalPos0, globalPos1;
localToGlobal( mLocalOrient0, mLocalPos0, globalOrient0, globalPos0, 0 );
localToGlobal( mLocalOrient1, mLocalPos1, globalOrient1, globalPos1, 1 );
// calculate all main 6 vectors.
Ogre::Vector3 bod0X = globalOrient0 * Ogre::Vector3( Ogre::Vector3::UNIT_X );
Ogre::Vector3 bod0Y = globalOrient0 * Ogre::Vector3( Ogre::Vector3::UNIT_Y );
Ogre::Vector3 bod0Z = globalOrient0 * Ogre::Vector3( Ogre::Vector3::UNIT_Z );
Ogre::Vector3 bod1X = globalOrient1 * Ogre::Vector3( Ogre::Vector3::UNIT_X );
Ogre::Vector3 bod1Y = globalOrient1 * Ogre::Vector3( Ogre::Vector3::UNIT_Y );
Ogre::Vector3 bod1Z = globalOrient1 * Ogre::Vector3( Ogre::Vector3::UNIT_Z );
#ifdef _DEBUG
Ogre::LogManager::getSingletonPtr()->logMessage(" Submit Constraint bod0X:"+Ogre::StringConverter::toString( bod0X )+
" bod1X:"+Ogre::StringConverter::toString( bod1X ) );
#endif
// ---------------------------------------------------------------
// first add a linear row to keep the body on the plane.
addLinearRow( globalPos0, globalPos1, bod0X );
// have we strayed from the plane along the normal?
Ogre::Plane thePlane( bod0X, globalPos0 );
Ogre::Real stray = thePlane.getDistance( globalPos1 );
if (stray > 0.0001f)
{
// we have strayed, apply acceleration to move back to 0 in one timestep.
Ogre::Real accel = (stray / timeStep);
if (thePlane.getSide( globalPos1 ) == Ogre::Plane::NEGATIVE_SIDE) { accel = -accel; }
setRowAcceleration( accel );
}
// see if the main axis (pin) has wandered off.
Ogre::Vector3 latDir = bod0X.crossProduct( bod1X );
Ogre::Real latMag = latDir.squaredLength();
if (latMag > 1.0e-6f)
{
// has wandered a bit, we need to correct. first find the angle off.
latMag = Ogre::Math::Sqrt( latMag );
latDir.normalise();
Ogre::Radian angle = Ogre::Math::ASin( latMag );
// ---------------------------------------------------------------
addAngularRow( angle, latDir );
// ---------------------------------------------------------------
// secondary correction for stability.
Ogre::Vector3 latDir2 = latDir.crossProduct( bod1X );
addAngularRow( Ogre::Radian(0.0f), latDir2 );
}
else
{
// ---------------------------------------------------------------
// no major change, just add 2 simple constraints.
addAngularRow( Ogre::Radian(0.0f), bod1Y );
addAngularRow( Ogre::Radian(0.0f), bod1Z );
}
// calculate the current angle.
Ogre::Real cos = bod0Y.dotProduct( bod1Y );
Ogre::Real sin = (bod0Y.crossProduct( bod1Y )).dotProduct( bod0X );
mAngle = Ogre::Math::ATan2( sin, cos );
if (mLimitsOn)
{
if (mAngle > mMax)
{
Ogre::Radian diff = mAngle - mMax;
addAngularRow( diff, bod0X );
setRowStiffness( 1.0f );
}
else if (mAngle < mMin)
{
Ogre::Radian diff = mAngle - mMin;
addAngularRow( diff, bod0X );
setRowStiffness( 1.0f );
}
}
else
{
if (mAccel != 0.0f)
{
addAngularRow( Ogre::Radian(0.0f), bod0X );
setRowAcceleration( mAccel );
mAccel = 0.0f;
}
}
}
CustomRigidJoint::CustomRigidJoint(OgreNewt::Body *child, OgreNewt::Body *parent, Ogre::Vector3 dir, Ogre::Vector3 pos) : OgreNewt::CustomJoint(6,child,parent)
{
// calculate local offsets.
pinAndDirToLocal( pos, dir, mLocalOrient0, mLocalPos0, mLocalOrient1, mLocalPos1 );
}
CustomRigidJoint::~CustomRigidJoint()
{
}
void CustomRigidJoint::submitConstraint( Ogre::Real timeStep, int threadIndex )
{
// get globals.
Ogre::Vector3 globalPos0, globalPos1;
Ogre::Quaternion globalOrient0, globalOrient1;
localToGlobal( mLocalOrient0, mLocalPos0, globalOrient0, globalPos0, 0 );
localToGlobal( mLocalOrient1, mLocalPos1, globalOrient1, globalPos1, 1 );
// apply the constraints!
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_X );
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_Y );
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_Z );
// now find a point off 10 units away.
globalPos0 = globalPos0 + (globalOrient0 * (Ogre::Vector3::UNIT_X * 10.0f));
globalPos1 = globalPos1 + (globalOrient1 * (Ogre::Vector3::UNIT_X * 10.0f));
// apply the constraints!
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_Y );
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_Z );
Ogre::Vector3 xdir0 = globalOrient0 * Ogre::Vector3::UNIT_X;
Ogre::Vector3 xdir1 = globalOrient1 * Ogre::Vector3::UNIT_X;
Ogre::Radian angle = Ogre::Math::ACos( xdir0.dotProduct( xdir1 ) );
addAngularRow( angle, globalOrient0 * Ogre::Vector3::UNIT_X );
}
/*
CustomDryRollingFriction::CustomDryRollingFriction( OgreNewt::Body* child, Ogre::Real radius, Ogre::Real rollingFrictionCoefficient ) :
OgreNewt::CustomJoint(1, child, NULL),
mChild(child)
{
Ogre::Real mass;
Ogre::Vector3 inertia;
child->getMassMatrix( mass, inertia );
mFrictionCoefficient = rollingFrictionCoefficient;
mFrictionTorque = inertia.x * radius;
}
CustomDryRollingFriction::~CustomDryRollingFriction()
{
}
// copied from CustomDryRollingFriction joint in newton
void CustomDryRollingFriction::submitConstraint( Ogre::Real timestep, int threadIndex )
{
Ogre::Vector3 omega;
Ogre::Real omegaMag;
Ogre::Real torqueFriction;
omega = mChild->getOmega();
omegaMag = omega.length();
if( omegaMag > 0.1f )
{
addAngularRow(Ogre::Radian(0), omega.normalisedCopy());
setRowAcceleration( -omegaMag/timestep );
torqueFriction = mFrictionTorque*mFrictionCoefficient;
setRowMinimumFriction(-torqueFriction);
setRowMaximumFriction(torqueFriction);
}
else
{
mChild->setOmega(omega*0.2f);
}
}
*/
} // end NAMESPACE PrebuiltCustomJoints
} // end NAMESPACE OgreNewt
Users browsing this forum: No registered users and 1 guest