2013-11-12 12:33:52 +01:00
/////////////////////////////////////////////////////////////////////
// Created by Dan Andersson & Robin Engman 2013
/////////////////////////////////////////////////////////////////////
# include "RigidBody.h"
# include "Utilities.h"
using namespace : : Oyster : : Collision3D ;
using namespace : : Oyster : : Physics3D ;
using namespace : : Oyster : : Math3D ;
2013-12-20 10:55:04 +01:00
using namespace : : Utility : : Value ;
2013-11-12 12:33:52 +01:00
2013-12-19 21:39:20 +01:00
RigidBody : : RigidBody ( )
{ // by Dan Andersson
this - > centerPos = Float4 : : standard_unit_w ;
this - > axis = Float4 : : null ;
this - > boundingReach = Float4 ( 0.5f , 0.5f , 0.5f , 0.0f ) ;
this - > momentum_Linear = Float4 : : null ;
this - > momentum_Angular = Float4 : : null ;
this - > impulse_Linear = Float4 : : null ;
this - > impulse_Angular = Float4 : : null ;
2013-12-18 14:16:13 +01:00
this - > restitutionCoeff = 1.0f ;
2013-12-19 21:39:20 +01:00
this - > frictionCoeff_Static = 0.5f ;
2013-12-19 10:03:56 +01:00
this - > frictionCoeff_Kinetic = 1.0f ;
2013-12-19 21:39:20 +01:00
this - > mass = 10 ;
2014-01-23 19:13:02 +01:00
this - > momentOfInertiaTensor = MomentOfInertia ( ) ;
2013-12-19 21:39:20 +01:00
this - > rotation = Quaternion : : identity ;
2013-11-12 12:33:52 +01:00
}
RigidBody & RigidBody : : operator = ( const RigidBody & body )
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
this - > centerPos = body . centerPos ;
this - > axis = body . axis ;
this - > boundingReach = body . boundingReach ;
this - > momentum_Linear = body . momentum_Linear ;
this - > momentum_Angular = body . momentum_Angular ;
this - > impulse_Linear = body . impulse_Linear ;
this - > impulse_Angular = body . impulse_Angular ;
2013-12-18 14:16:13 +01:00
this - > restitutionCoeff = body . restitutionCoeff ;
2013-12-19 10:03:56 +01:00
this - > frictionCoeff_Static = body . frictionCoeff_Static ;
this - > frictionCoeff_Kinetic = body . frictionCoeff_Kinetic ;
2013-11-12 12:33:52 +01:00
this - > mass = body . mass ;
this - > momentOfInertiaTensor = body . momentOfInertiaTensor ;
2013-12-19 21:39:20 +01:00
this - > rotation = body . rotation ;
2013-11-12 12:33:52 +01:00
return * this ;
}
2013-12-19 21:39:20 +01:00
void RigidBody : : Update_LeapFrog ( Float updateFrameLength )
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson: Euler leap frog update when Runga Kutta is not needed
// updating the linear
2013-11-21 11:39:11 +01:00
// ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G
2013-12-20 10:55:04 +01:00
this - > centerPos + = ( updateFrameLength / this - > mass ) * AverageWithDelta ( this - > momentum_Linear , this - > impulse_Linear ) ;
2014-01-23 19:13:02 +01:00
2013-11-12 12:33:52 +01:00
// updating the angular
2014-01-23 19:13:02 +01:00
//Float4x4 rotationMatrix; ::Oyster::Math3D::RotationMatrix( this->rotation, rotationMatrix );
2013-12-19 21:39:20 +01:00
// Important! The member data is all world data except the Inertia tensor. Thus a new InertiaTensor needs to be created to be compatible with the rest of the world data.
2014-01-23 19:13:02 +01:00
//Float4x4 wMomentOfInertiaTensor = TransformMatrix( rotationMatrix, this->momentOfInertiaTensor ); // RI
2013-11-12 12:33:52 +01:00
2013-12-19 21:39:20 +01:00
// dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H
2014-01-20 15:31:19 +01:00
//! HACK: @todo Rotation temporary disabled
//this->axis += Radian( Formula::AngularVelocity(wMomentOfInertiaTensor.GetInverse(), AverageWithDelta(this->momentum_Angular, this->impulse_Angular)) );
2014-01-23 19:13:02 +01:00
this - > axis + = this - > momentOfInertiaTensor . CalculateAngularVelocity ( this - > rotation , AverageWithDelta ( this - > momentum_Angular , this - > impulse_Angular ) ) ;
this - > rotation = Rotation ( this - > axis ) ;
2013-11-12 12:33:52 +01:00
2013-12-19 21:39:20 +01:00
// update momentums and clear impulse_Linear and impulse_Angular
this - > momentum_Linear + = this - > impulse_Linear ;
this - > impulse_Linear = Float4 : : null ;
2014-01-20 15:31:19 +01:00
//this->momentum_Angular += this->impulse_Angular; //! HACK: @todo Rotation temporary disabled
2013-12-19 21:39:20 +01:00
this - > impulse_Angular = Float4 : : null ;
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
void RigidBody : : Predict_LeapFrog ( Float3 & outDeltaPos , Float3 & outDeltaAxis , const Float3 & actingLinearImpulse , const Float3 & actingAngularImpulse , Float deltaTime )
2013-12-20 10:55:04 +01:00
{
// updating the linear
// ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G
outDeltaPos = ( deltaTime / this - > mass ) * AverageWithDelta ( this - > momentum_Linear , actingLinearImpulse ) ;
// updating the angular
2014-01-23 19:13:02 +01:00
//Float4x4 rotationMatrix; ::Oyster::Math3D::RotationMatrix( this->rotation, rotationMatrix );
//Float4x4 wMomentOfInertiaTensor = TransformMatrix( rotationMatrix, this->momentOfInertiaTensor ); // RI
2013-12-20 10:55:04 +01:00
// dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H
2014-01-23 19:13:02 +01:00
//outDeltaAxis = Formula::AngularVelocity( wMomentOfInertiaTensor.GetInverse(), AverageWithDelta(this->momentum_Angular, actingAngularImpulse) );
outDeltaAxis = this - > momentOfInertiaTensor . CalculateAngularVelocity ( this - > rotation , AverageWithDelta ( this - > momentum_Angular , this - > impulse_Angular ) ) ;
2013-12-20 10:55:04 +01:00
}
2014-01-28 09:23:58 +01:00
void RigidBody : : Move ( const Float3 & deltaPos , const Float3 & deltaAxis )
2013-12-20 11:19:07 +01:00
{
this - > centerPos + = deltaPos ;
this - > axis + = deltaAxis ;
this - > rotation = Rotation ( this - > axis ) ;
}
2014-01-28 09:23:58 +01:00
void RigidBody : : ApplyImpulse ( const Float3 & worldJ , const Float3 & atWorldPos )
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
2014-01-28 09:23:58 +01:00
Float3 worldOffset = atWorldPos - this - > centerPos ;
if ( worldOffset ! = Float3 : : null )
2013-11-12 12:33:52 +01:00
{
2013-12-19 21:39:20 +01:00
this - > impulse_Linear + = VectorProjection ( worldJ , atWorldPos ) ;
this - > impulse_Angular + = Formula : : ImpulseTorque ( worldJ , atWorldPos ) ;
2013-11-12 12:33:52 +01:00
}
else
{
2013-12-19 21:39:20 +01:00
this - > impulse_Linear + = worldJ ;
2013-11-12 12:33:52 +01:00
}
}
2014-01-23 19:13:02 +01:00
const MomentOfInertia & RigidBody : : GetMomentOfInertia ( ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
return this - > momentOfInertiaTensor ;
}
2013-12-19 21:39:20 +01:00
Float RigidBody : : GetMass ( ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
return this - > mass ;
}
2014-01-28 09:23:58 +01:00
const Quaternion & RigidBody : : GetRotationQuaternion ( ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
return this - > rotation ;
2013-11-12 12:33:52 +01:00
}
2013-12-19 21:39:20 +01:00
Float4x4 RigidBody : : GetRotationMatrix ( ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
return RotationMatrix ( this - > rotation ) ;
2013-11-12 12:33:52 +01:00
}
2013-12-19 21:39:20 +01:00
Float4x4 RigidBody : : GetOrientation ( ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
return : : Oyster : : Math3D : : OrientationMatrix ( this - > rotation , this - > centerPos ) ;
2013-11-12 12:33:52 +01:00
}
2013-12-19 21:39:20 +01:00
Float4x4 RigidBody : : GetView ( ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
return ViewMatrix ( this - > rotation , this - > centerPos ) ;
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
Float3 RigidBody : : GetVelocity_Linear ( ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
return Formula : : LinearVelocity ( this - > mass , this - > momentum_Linear ) ;
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
Float3 RigidBody : : GetVelocity_Angular ( ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
2014-01-23 19:13:02 +01:00
return this - > momentOfInertiaTensor . CalculateAngularVelocity ( this - > rotation , this - > momentum_Angular ) ;
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
Float3 RigidBody : : GetLinearMomentum ( const Float3 & atWorldPos ) const
2013-11-12 12:33:52 +01:00
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
return this - > momentum_Linear + Formula : : TangentialLinearMomentum ( this - > momentum_Angular , atWorldPos - this - > centerPos ) ;
2013-11-12 12:33:52 +01:00
}
2014-01-23 19:13:02 +01:00
void RigidBody : : SetMomentOfInertia_KeepVelocity ( const MomentOfInertia & localTensorI )
2013-11-21 17:22:13 +01:00
{ // by Dan Andersson
2014-01-28 09:23:58 +01:00
Float3 w = this - > momentOfInertiaTensor . CalculateAngularVelocity ( this - > rotation , this - > momentum_Angular ) ;
2014-01-23 19:13:02 +01:00
this - > momentOfInertiaTensor = localTensorI ;
this - > momentum_Angular = this - > momentOfInertiaTensor . CalculateAngularVelocity ( this - > rotation , w ) ;
2013-11-21 17:22:13 +01:00
}
2014-01-23 19:13:02 +01:00
void RigidBody : : SetMomentOfInertia_KeepMomentum ( const MomentOfInertia & localTensorI )
2013-11-18 14:01:23 +01:00
{ // by Dan Andersson
2014-01-23 19:13:02 +01:00
this - > momentOfInertiaTensor = localTensorI ;
2013-11-12 12:33:52 +01:00
}
void RigidBody : : SetMass_KeepVelocity ( const Float & m )
2013-11-18 14:01:23 +01:00
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
if ( m ! = 0.0f )
{ // insanity check! Mass must be invertable
2014-01-28 09:23:58 +01:00
Float3 v = Formula : : LinearVelocity ( this - > mass , this - > momentum_Linear ) ;
2013-11-18 14:01:23 +01:00
this - > mass = m ;
2013-12-19 21:39:20 +01:00
this - > momentum_Linear = Formula : : LinearMomentum ( this - > mass , v ) ;
2013-11-18 14:01:23 +01:00
}
2013-11-12 12:33:52 +01:00
}
void RigidBody : : SetMass_KeepMomentum ( const Float & m )
2013-11-18 14:01:23 +01:00
{ // by Dan Anderson
2013-12-19 21:39:20 +01:00
if ( m ! = 0.0f )
{ // insanity check! Mass must be invertable
2013-11-18 14:01:23 +01:00
this - > mass = m ;
}
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
//void RigidBody::SetOrientation( const Float4x4 &o )
//{ // by Dan Andersson
// this->axis = ExtractAngularAxis( o );
// this->rotation = Rotation( this->axis );
// this->centerPos = o.v[3].xyz;
//}
//
//void RigidBody::SetRotation( const Float4x4 &r )
//{ // by Dan Andersson
// this->axis = ExtractAngularAxis( r );
// this->rotation = Rotation( this->axis );
//}
2013-11-12 12:33:52 +01:00
2014-01-28 09:23:58 +01:00
void RigidBody : : SetMomentum_Linear ( const Float3 & worldG , const Float3 & atWorldPos )
2013-11-18 14:01:23 +01:00
{ // by Dan Andersson
2014-01-28 09:23:58 +01:00
Float3 worldOffset = atWorldPos - this - > centerPos ;
2013-12-19 21:39:20 +01:00
this - > momentum_Linear = VectorProjection ( worldG , worldOffset ) ;
this - > momentum_Angular = Formula : : AngularMomentum ( worldG , worldOffset ) ;
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
void RigidBody : : SetVelocity_Linear ( const Float3 & worldV )
2013-11-18 14:01:23 +01:00
{ // by Dan Andersson
2013-12-19 21:39:20 +01:00
this - > momentum_Linear = Formula : : LinearMomentum ( this - > mass , worldV ) ;
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
void RigidBody : : SetVelocity_Linear ( const Float3 & worldV , const Float3 & atWorldPos )
2013-11-18 14:01:23 +01:00
{ // by Dan Andersson
2014-01-28 09:23:58 +01:00
Float3 worldOffset = atWorldPos - this - > centerPos ;
2014-01-23 19:13:02 +01:00
this - > momentum_Linear = Formula : : LinearMomentum ( this - > mass , VectorProjection ( worldV , worldOffset ) ) ;
this - > momentum_Angular = this - > momentOfInertiaTensor . CalculateAngularMomentum ( this - > rotation , Formula : : AngularVelocity ( worldV , worldOffset ) ) ;
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
void RigidBody : : SetVelocity_Angular ( const Float3 & worldW )
2013-11-21 11:39:11 +01:00
{ // by Dan Andersson
2014-01-23 19:13:02 +01:00
this - > momentum_Angular = this - > momentOfInertiaTensor . CalculateAngularMomentum ( this - > rotation , worldW ) ;
2013-11-12 12:33:52 +01:00
}
2014-01-28 09:23:58 +01:00
void RigidBody : : SetImpulse_Linear ( const Float3 & worldJ , const Float3 & atWorldPos )
2013-11-21 11:39:11 +01:00
{ // by Dan Andersson
2014-01-28 09:23:58 +01:00
Float3 worldOffset = atWorldPos - this - > centerPos ;
2013-12-19 21:39:20 +01:00
this - > impulse_Linear = VectorProjection ( worldJ , worldOffset ) ;
this - > impulse_Angular = Formula : : ImpulseTorque ( worldJ , worldOffset ) ;
2013-11-12 12:33:52 +01:00
}