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
|
2014-02-03 11:10:04 +01:00
|
|
|
//Decrease momentum with 1% as "fall-off"
|
|
|
|
//! HACK: @todo Add real solution with fluid drag
|
2014-02-04 10:29:02 +01:00
|
|
|
this->momentum_Linear = this->momentum_Linear*0.9999f;
|
|
|
|
this->momentum_Angular = this->momentum_Angular*0.9999f;
|
2014-02-03 15:48:42 +01:00
|
|
|
|
2013-11-21 11:39:11 +01:00
|
|
|
// ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G
|
2014-02-03 15:48:42 +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-29 14:57:39 +01:00
|
|
|
// dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H
|
|
|
|
this->axis += updateFrameLength * this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) );
|
2014-01-23 19:13:02 +01:00
|
|
|
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
|
|
|
|
2014-01-29 14:57:39 +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
|
2014-02-04 16:56:31 +01:00
|
|
|
Float3 offset = atWorldPos - this->centerPos;
|
|
|
|
if( offset.Dot(offset) > 0.0f )
|
|
|
|
{
|
|
|
|
return this->momentum_Linear + Formula::TangentialLinearMomentum( this->momentum_Angular, offset );
|
|
|
|
}
|
|
|
|
return this->momentum_Linear;
|
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-02-03 15:48:42 +01:00
|
|
|
void RigidBody::SetRotation( const Float3 &axis )
|
|
|
|
{ // by Dan Andersson
|
|
|
|
this->axis = axis;
|
|
|
|
this->rotation = Rotation( this->axis );
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|