2013-11-20 11:09:27 +01:00
|
|
|
#include "PhysicsAPI_Impl.h"
|
2013-11-22 11:52:45 +01:00
|
|
|
#include "OysterPhysics3D.h"
|
2013-11-28 11:58:46 +01:00
|
|
|
#include "SimpleRigidBody.h"
|
|
|
|
#include "SphericalRigidBody.h"
|
2013-11-20 11:09:27 +01:00
|
|
|
|
2014-01-15 10:44:31 +01:00
|
|
|
using namespace ::Oyster;
|
2013-11-21 17:22:13 +01:00
|
|
|
using namespace ::Oyster::Physics;
|
|
|
|
using namespace ::Oyster::Math;
|
|
|
|
using namespace ::Oyster::Collision3D;
|
|
|
|
using namespace ::Utility::DynamicMemory;
|
2013-12-19 10:15:32 +01:00
|
|
|
using namespace ::Utility::Value;
|
2013-11-20 11:09:27 +01:00
|
|
|
|
2013-11-25 16:35:56 +01:00
|
|
|
API_Impl API_instance;
|
2013-11-20 11:09:27 +01:00
|
|
|
|
2013-11-29 09:21:44 +01:00
|
|
|
namespace
|
|
|
|
{
|
2014-02-06 21:15:28 +01:00
|
|
|
/*void OnPossibleCollision( Octree& worldScene, unsigned int protoTempRef, unsigned int deuterTempRef )
|
2014-02-04 15:43:17 +01:00
|
|
|
{
|
2013-11-29 09:21:44 +01:00
|
|
|
auto proto = worldScene.GetCustomBody( protoTempRef );
|
|
|
|
auto deuter = worldScene.GetCustomBody( deuterTempRef );
|
|
|
|
|
2013-12-18 08:57:27 +01:00
|
|
|
Float4 worldPointOfContact;
|
|
|
|
if( proto->Intersects(*deuter, worldPointOfContact) )
|
2013-11-29 09:21:44 +01:00
|
|
|
{
|
2014-01-29 11:22:04 +01:00
|
|
|
// Apply CollisionResponse in pure gather pattern
|
|
|
|
ICustomBody::State protoState; proto->GetState( protoState );
|
|
|
|
ICustomBody::State deuterState; deuter->GetState( deuterState );
|
2014-01-14 09:12:37 +01:00
|
|
|
|
2014-02-04 16:10:18 +01:00
|
|
|
// calc from perspective of deuter.
|
2014-02-06 21:15:28 +01:00
|
|
|
Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )); // Init value is only borrowed
|
|
|
|
//if( normal.Dot(normal) > 0.0f )
|
2014-02-04 16:10:18 +01:00
|
|
|
{
|
|
|
|
deuter->GetNormalAt( worldPointOfContact, normal );
|
|
|
|
}
|
2014-02-06 21:15:28 +01:00
|
|
|
//else
|
|
|
|
//{ // special case: deuter is completly contained within proto or they have overlapping centers.
|
|
|
|
|
|
|
|
// normal = Float4( protoState.GetCenterPosition() - deuterState.GetCenterPosition(), 0.0f );
|
|
|
|
// if( normal.Dot(normal) == 0.0f )
|
|
|
|
// { // they have overlapping centers. Rebound at least
|
|
|
|
// // calculate and store time interpolation value, for later rebound.
|
|
|
|
// proto->SetTimeOfContact( worldPointOfContact );
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // borrowing the negated normal of proto.
|
|
|
|
// proto->GetNormalAt( worldPointOfContact, normal );
|
|
|
|
// normal = -normal;
|
|
|
|
//}
|
2014-02-05 11:46:04 +01:00
|
|
|
normal.Normalize();
|
2014-02-04 15:43:17 +01:00
|
|
|
|
2014-02-05 11:46:04 +01:00
|
|
|
Float4 protoG = Float4(protoState.GetLinearMomentum( worldPointOfContact.xyz ), 0),
|
|
|
|
deuterG = Float4(deuterState.GetLinearMomentum( worldPointOfContact.xyz ), 0);
|
2014-02-04 15:43:17 +01:00
|
|
|
|
2014-02-04 16:38:42 +01:00
|
|
|
if( normal != normal ) // debug: trap
|
|
|
|
const char *breakpoint = "This should never happen";
|
|
|
|
|
|
|
|
if( protoG != protoG ) // debug: trap
|
|
|
|
const char *breakpoint = "This should never happen";
|
|
|
|
|
|
|
|
if( deuterG != deuterG ) // debug: trap
|
|
|
|
const char *breakpoint = "This should never happen";
|
|
|
|
|
2014-01-29 11:22:04 +01:00
|
|
|
Float protoG_Magnitude = protoG.Dot( normal ),
|
2014-02-04 15:43:17 +01:00
|
|
|
deuterG_Magnitude = deuterG.Dot( normal );
|
2014-01-29 11:22:04 +01:00
|
|
|
|
|
|
|
// if they are not relatively moving towards eachother, there is no collision
|
|
|
|
Float deltaPos = normal.Dot( Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1) );
|
|
|
|
if( deltaPos < 0.0f )
|
|
|
|
{
|
|
|
|
if( protoG_Magnitude >= deuterG_Magnitude )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( deltaPos > 0.0f )
|
|
|
|
{
|
|
|
|
if( protoG_Magnitude <= deuterG_Magnitude )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_ignore_collision_response )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-05 11:46:04 +01:00
|
|
|
// PLayerHAck
|
2014-02-05 11:53:38 +01:00
|
|
|
if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_player_collision_response )
|
2014-02-05 11:46:04 +01:00
|
|
|
{
|
2014-02-06 21:15:28 +01:00
|
|
|
//Float3 linearMomentum = protoState.GetLinearMomentum();
|
|
|
|
//Float3 up = -protoState.GetGravityNormal();
|
|
|
|
//Float3 upForce = (linearMomentum.Dot(up) * up);
|
2014-02-05 11:46:04 +01:00
|
|
|
|
2014-02-06 21:15:28 +01:00
|
|
|
//Float3 noBounceForce = linearMomentum - upForce;
|
|
|
|
//protoState.SetLinearMomentum(noBounceForce);
|
|
|
|
//proto->SetState(protoState);
|
2014-02-05 11:46:04 +01:00
|
|
|
return;
|
2014-02-05 11:53:38 +01:00
|
|
|
}
|
2014-02-03 15:48:42 +01:00
|
|
|
// calculate and store time interpolation value, for later rebound.
|
|
|
|
proto->SetTimeOfContact( worldPointOfContact );
|
2014-01-29 11:22:04 +01:00
|
|
|
|
|
|
|
// bounce
|
|
|
|
Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(),
|
2014-02-04 15:43:17 +01:00
|
|
|
deuterState.GetMass(), deuterG_Magnitude,
|
|
|
|
protoState.GetMass(), protoG_Magnitude );
|
2013-12-18 08:57:27 +01:00
|
|
|
|
2014-01-29 11:22:04 +01:00
|
|
|
|
|
|
|
// calc from perspective of proto
|
2014-02-04 16:10:18 +01:00
|
|
|
|
2014-02-06 21:15:28 +01:00
|
|
|
normal = (worldPointOfContact - Float4(protoState.GetCenterPosition(), 1.0f )).GetNormalized();
|
|
|
|
//if( normal.Dot(normal) > 0.0f )
|
|
|
|
{
|
|
|
|
proto->GetNormalAt( worldPointOfContact, normal );
|
|
|
|
protoG_Magnitude = protoG.Dot( normal );
|
|
|
|
deuterG_Magnitude = deuterG.Dot( normal );
|
|
|
|
normal.Normalize();
|
|
|
|
}
|
|
|
|
//else
|
|
|
|
//{ // special case: proto is completly contained within deuter.
|
|
|
|
// // borrowing the negated normal of deuter.
|
|
|
|
// deuter->GetNormalAt( worldPointOfContact, normal );
|
|
|
|
// normal = -normal;
|
|
|
|
// protoG_Magnitude = -protoG_Magnitude;
|
|
|
|
// deuterG_Magnitude = -deuterG_Magnitude;
|
|
|
|
//}
|
|
|
|
|
|
|
|
if( normal != normal ) // debug: trap
|
|
|
|
const char *breakpoint = "This should never happen";
|
|
|
|
|
|
|
|
// bounce
|
|
|
|
Float4 bounceP = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(),
|
|
|
|
protoState.GetMass(), protoG_Magnitude,
|
|
|
|
deuterState.GetMass(), deuterG_Magnitude );
|
|
|
|
|
|
|
|
Float4 bounce = Average( bounceD, bounceP );
|
|
|
|
|
|
|
|
Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal,
|
|
|
|
Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(),
|
|
|
|
Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass());
|
|
|
|
|
|
|
|
if(protoState.GetMass() == 70)
|
|
|
|
{
|
|
|
|
const char* breakPoint = "here";
|
|
|
|
}
|
|
|
|
|
|
|
|
Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() );
|
|
|
|
|
|
|
|
protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz );
|
|
|
|
proto->SetState( protoState );
|
|
|
|
|
|
|
|
Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() );
|
|
|
|
|
|
|
|
proto->CallSubscription_AfterCollisionResponse( deuter, kineticEnergyPBefore - kineticEnergyPAFter );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}*/
|
|
|
|
void OnPossibleCollision( Octree& worldScene, unsigned int protoTempRef, unsigned int deuterTempRef )
|
|
|
|
{
|
|
|
|
auto proto = worldScene.GetCustomBody( protoTempRef );
|
|
|
|
auto deuter = worldScene.GetCustomBody( deuterTempRef );
|
|
|
|
|
|
|
|
Float4 worldPointOfContact;
|
|
|
|
if( proto->Intersects(*deuter, worldPointOfContact) )
|
|
|
|
{
|
|
|
|
// Apply CollisionResponse in pure gather pattern
|
|
|
|
ICustomBody::State protoState; proto->GetState( protoState );
|
|
|
|
ICustomBody::State deuterState; deuter->GetState( deuterState );
|
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
|
2014-02-06 21:15:28 +01:00
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
Float4 normal = deuter->GetNormalAt(worldPointOfContact);
|
|
|
|
if(normal == Float4::null)
|
|
|
|
{
|
|
|
|
normal = Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1);
|
2014-02-06 21:15:28 +01:00
|
|
|
}
|
|
|
|
normal.Normalize();
|
|
|
|
|
|
|
|
Float4 protoG = Float4(protoState.GetLinearMomentum( worldPointOfContact.xyz ), 0),
|
|
|
|
deuterG = Float4(deuterState.GetLinearMomentum( worldPointOfContact.xyz ), 0);
|
|
|
|
|
|
|
|
Float protoG_Magnitude = protoG.Dot( normal ),
|
|
|
|
deuterG_Magnitude = deuterG.Dot( normal );
|
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// If true the object is inside the world
|
|
|
|
if(worldPointOfContact.GetLength() < 600 && protoState.GetCenterPosition().GetLength() != 0)
|
2014-02-06 21:15:28 +01:00
|
|
|
{
|
2014-02-07 15:38:53 +01:00
|
|
|
Float overlap = 600 - worldPointOfContact.GetLength();
|
|
|
|
Float3 newPos = overlap*worldPointOfContact.GetNormalized();
|
|
|
|
protoState.SetCenterPosition(protoState.GetCenterPosition() + newPos);
|
|
|
|
protoState.SetLinearMomentum(Float3(0, 0, 0));
|
2014-02-06 21:15:28 +01:00
|
|
|
}
|
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// If they are not relatively moving towards eachother, there is no collision
|
2014-02-06 21:15:28 +01:00
|
|
|
Float deltaPos = normal.Dot( Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1) );
|
|
|
|
if( deltaPos < 0.0f )
|
|
|
|
{
|
|
|
|
if( protoG_Magnitude >= deuterG_Magnitude )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( deltaPos > 0.0f )
|
|
|
|
{
|
|
|
|
if( protoG_Magnitude <= deuterG_Magnitude )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// Proto
|
|
|
|
normal = -proto->GetNormalAt(worldPointOfContact);
|
|
|
|
if(normal == Float4::null)
|
2014-02-04 16:10:18 +01:00
|
|
|
{
|
2014-02-07 15:38:53 +01:00
|
|
|
normal = Float4(protoState.GetCenterPosition(), 1) - Float4(deuterState.GetCenterPosition(), 1);
|
2014-02-04 16:10:18 +01:00
|
|
|
}
|
2014-02-06 21:15:28 +01:00
|
|
|
normal.Normalize();
|
2014-02-04 16:38:42 +01:00
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// Calculate and apply friction to rigid body
|
2014-02-06 21:15:28 +01:00
|
|
|
Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal,
|
|
|
|
Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(),
|
|
|
|
Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass());
|
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
//protoState.ApplyFriction( -friction.xyz );
|
2014-02-07 11:43:18 +01:00
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// If no other collision response is wanted then this will stop the bounce
|
2014-02-06 21:15:28 +01:00
|
|
|
if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_ignore_collision_response )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
|
2014-02-07 11:43:18 +01:00
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// Calaculate bounce
|
|
|
|
Float4 bounce = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(),
|
2014-02-04 15:43:17 +01:00
|
|
|
protoState.GetMass(), protoG_Magnitude,
|
|
|
|
deuterState.GetMass(), deuterG_Magnitude );
|
2014-02-07 15:38:53 +01:00
|
|
|
// If bounce is not big enough to matter, set to 0
|
2014-02-06 21:15:28 +01:00
|
|
|
if( abs(bounce.x) < 0.001 )
|
|
|
|
{
|
|
|
|
bounce.x = 0;
|
|
|
|
}
|
|
|
|
if( abs(bounce.y) < 0.001 )
|
|
|
|
{
|
|
|
|
bounce.y = 0;
|
|
|
|
}
|
|
|
|
if( abs(bounce.z) < 0.001 )
|
|
|
|
{
|
|
|
|
bounce.z = 0;
|
|
|
|
}
|
2014-02-03 10:45:25 +01:00
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
if( bounce != bounce)
|
|
|
|
{
|
|
|
|
const char* breakpoint = "STOP";
|
|
|
|
}
|
2014-01-22 13:50:54 +01:00
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// Calculate kinetic energy before impulse is applied
|
|
|
|
Float kineticEnergyBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() );
|
|
|
|
|
|
|
|
// Apply the bounce as impulse
|
2014-02-06 21:15:28 +01:00
|
|
|
protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz );
|
2014-01-29 11:22:04 +01:00
|
|
|
proto->SetState( protoState );
|
2014-01-22 15:29:50 +01:00
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// Calculate kinetic energy after impulse is applied
|
|
|
|
Float kineticEnergyAfter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() );
|
2014-01-29 11:22:04 +01:00
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// Call a collision function with kinetic energy loss
|
|
|
|
proto->CallSubscription_AfterCollisionResponse( deuter, kineticEnergyBefore - kineticEnergyAfter );
|
2013-11-29 09:21:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-25 12:21:44 +01:00
|
|
|
API & API::Instance()
|
2013-11-20 11:09:27 +01:00
|
|
|
{
|
2013-11-25 16:35:56 +01:00
|
|
|
return API_instance;
|
2013-11-20 11:09:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
API_Impl::API_Impl()
|
2013-11-28 17:59:12 +01:00
|
|
|
{
|
|
|
|
this->gravityConstant = Constant::gravity_constant;
|
2014-01-29 12:22:18 +01:00
|
|
|
this->epsilon = Constant::epsilon;
|
2013-11-28 17:59:12 +01:00
|
|
|
this->updateFrameLength = 1.0f / 120.0f;
|
|
|
|
this->destructionAction = Default::EventAction_Destruction;
|
2014-01-15 10:44:31 +01:00
|
|
|
this->gravity = ::std::vector<Gravity>();
|
2013-11-28 17:59:12 +01:00
|
|
|
this->worldScene = Octree();
|
|
|
|
}
|
2013-11-20 11:09:27 +01:00
|
|
|
|
2013-11-25 16:57:38 +01:00
|
|
|
API_Impl::~API_Impl() {}
|
2013-11-20 11:09:27 +01:00
|
|
|
|
2013-11-26 13:27:34 +01:00
|
|
|
void API_Impl::Init( unsigned int numObjects, unsigned int numGravityWells , const Float3 &worldSize )
|
|
|
|
{
|
2013-11-28 17:59:12 +01:00
|
|
|
unsigned char numLayers = 4; //!< @todo TODO: calc numLayers from worldSize
|
2014-01-15 10:44:31 +01:00
|
|
|
this->gravity.resize( 0 );
|
|
|
|
this->gravity.reserve( numGravityWells );
|
2013-11-28 17:59:12 +01:00
|
|
|
this->worldScene = Octree( numObjects, numLayers, worldSize );
|
2013-11-26 13:27:34 +01:00
|
|
|
}
|
|
|
|
|
2013-11-28 17:59:12 +01:00
|
|
|
void API_Impl::SetFrameTimeLength( float deltaTime )
|
2013-11-20 11:09:27 +01:00
|
|
|
{
|
2013-11-28 17:59:12 +01:00
|
|
|
this->updateFrameLength = deltaTime;
|
2013-11-20 11:09:27 +01:00
|
|
|
}
|
2013-11-28 10:26:29 +01:00
|
|
|
|
2013-11-20 11:09:27 +01:00
|
|
|
void API_Impl::SetGravityConstant( float g )
|
|
|
|
{
|
2013-11-25 16:57:38 +01:00
|
|
|
this->gravityConstant = g;
|
2013-11-20 11:09:27 +01:00
|
|
|
}
|
2013-11-28 10:26:29 +01:00
|
|
|
|
2014-01-29 12:22:18 +01:00
|
|
|
void API_Impl::SetEpsilon( float e )
|
|
|
|
{
|
|
|
|
this->epsilon = e;
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:26:29 +01:00
|
|
|
void API_Impl::SetSubscription( API::EventAction_Destruction functionPointer )
|
2013-11-20 11:09:27 +01:00
|
|
|
{
|
2013-11-28 10:26:29 +01:00
|
|
|
if( functionPointer )
|
|
|
|
{
|
|
|
|
this->destructionAction = functionPointer;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->destructionAction = Default::EventAction_Destruction;
|
|
|
|
}
|
2013-11-20 11:09:27 +01:00
|
|
|
}
|
|
|
|
|
2013-12-20 11:43:12 +01:00
|
|
|
float API_Impl::GetFrameTimeLength() const
|
|
|
|
{
|
|
|
|
return this->updateFrameLength;
|
|
|
|
}
|
|
|
|
|
2013-11-20 11:09:27 +01:00
|
|
|
void API_Impl::Update()
|
2014-02-07 15:38:53 +01:00
|
|
|
{
|
|
|
|
ICustomBody::State state;
|
2013-11-29 09:21:44 +01:00
|
|
|
::std::vector<ICustomBody*> updateList;
|
2014-02-07 15:38:53 +01:00
|
|
|
|
|
|
|
// Fetch objects in universe
|
2014-02-07 13:09:44 +01:00
|
|
|
this->worldScene.Sample( Universe(), updateList );
|
2014-02-07 15:38:53 +01:00
|
|
|
|
|
|
|
// Change momentum for all rigid bodies
|
2014-02-08 14:26:18 +01:00
|
|
|
for( unsigned int i = 0; i < updateList.size(); i++ )
|
2013-11-29 09:21:44 +01:00
|
|
|
{
|
2014-02-07 15:38:53 +01:00
|
|
|
ICustomBody* proto = updateList[i];
|
|
|
|
// Step 1: Apply gravity to rigid body
|
2014-01-17 13:30:07 +01:00
|
|
|
Float4 gravityImpulse = Float4::null;
|
2014-02-07 13:09:44 +01:00
|
|
|
proto->GetState( state );
|
2014-02-07 15:38:53 +01:00
|
|
|
|
|
|
|
Float4 deltaPosGrav = Float4( this->gravity[0].well.position, 1.0f ) - Float4( state.GetCenterPosition(), 1.0f );
|
|
|
|
Float rSquared = deltaPosGrav.Dot( deltaPosGrav );
|
|
|
|
if( rSquared != 0.0 )
|
2014-01-15 10:44:31 +01:00
|
|
|
{
|
2014-02-08 14:26:18 +01:00
|
|
|
Float force = 9.82f*10.0f;
|
2014-02-07 15:38:53 +01:00
|
|
|
gravityImpulse += (this->updateFrameLength*force)*deltaPosGrav.GetNormalized();
|
2014-01-15 10:44:31 +01:00
|
|
|
}
|
2014-01-17 13:30:07 +01:00
|
|
|
|
2014-02-06 21:15:28 +01:00
|
|
|
Float posLength = state.GetCenterPosition().GetLength();
|
2014-02-07 16:01:43 +01:00
|
|
|
if( gravityImpulse != Float4::null && posLength - 600 > state.GetReach().GetLength() )
|
2014-01-17 13:30:07 +01:00
|
|
|
{
|
2014-01-28 09:52:58 +01:00
|
|
|
state.ApplyLinearImpulse( gravityImpulse.xyz );
|
2014-01-31 15:15:08 +01:00
|
|
|
state.SetGravityNormal( gravityImpulse.GetNormalized().xyz );
|
2014-02-07 13:09:44 +01:00
|
|
|
proto->SetState( state );
|
2014-01-17 13:30:07 +01:00
|
|
|
}
|
2014-02-07 15:38:53 +01:00
|
|
|
|
|
|
|
// Step 2: Step through octree and apply collision responses to rigid body
|
2014-02-07 13:09:44 +01:00
|
|
|
this->worldScene.Visit( proto, OnPossibleCollision );
|
2013-11-29 09:21:44 +01:00
|
|
|
}
|
|
|
|
|
2014-02-07 15:38:53 +01:00
|
|
|
// Go through all rigid bodies and move them according to their momentums
|
2014-02-08 14:26:18 +01:00
|
|
|
for( unsigned int i = 0; i < updateList.size(); i++ )
|
2013-11-29 09:21:44 +01:00
|
|
|
{
|
2014-02-07 13:09:44 +01:00
|
|
|
auto proto = updateList[i];
|
2014-01-31 13:41:06 +01:00
|
|
|
|
2014-02-07 13:09:44 +01:00
|
|
|
switch( proto->Update(this->updateFrameLength) )
|
2013-11-29 09:21:44 +01:00
|
|
|
{
|
|
|
|
case UpdateState_altered:
|
2014-02-07 15:38:53 +01:00
|
|
|
// Moves the container in the octree to the new rigid body position
|
2014-02-07 13:09:44 +01:00
|
|
|
this->worldScene.SetAsAltered( this->worldScene.GetTemporaryReferenceOf(proto) );
|
|
|
|
proto->CallSubscription_Move();
|
2014-01-29 12:22:18 +01:00
|
|
|
case UpdateState_resting:
|
|
|
|
default:
|
2013-11-29 09:21:44 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-11-20 11:09:27 +01:00
|
|
|
}
|
|
|
|
|
2013-11-25 10:54:27 +01:00
|
|
|
bool API_Impl::IsInLimbo( const ICustomBody* objRef )
|
2013-11-21 17:22:13 +01:00
|
|
|
{
|
2014-02-03 15:15:47 +01:00
|
|
|
return this->worldScene.IsInLimbo( objRef );
|
2013-11-21 17:22:13 +01:00
|
|
|
}
|
|
|
|
|
2013-11-25 10:54:27 +01:00
|
|
|
void API_Impl::MoveToLimbo( const ICustomBody* objRef )
|
2013-11-20 11:09:27 +01:00
|
|
|
{
|
2014-02-03 15:15:47 +01:00
|
|
|
this->worldScene.MoveToLimbo( objRef );
|
2013-11-20 11:09:27 +01:00
|
|
|
}
|
2013-11-25 10:54:27 +01:00
|
|
|
void API_Impl::ReleaseFromLimbo( const ICustomBody* objRef )
|
2013-11-20 11:09:27 +01:00
|
|
|
{
|
2014-02-03 15:15:47 +01:00
|
|
|
this->worldScene.ReleaseFromLimbo( objRef );
|
2013-11-20 11:09:27 +01:00
|
|
|
}
|
|
|
|
|
2013-11-25 10:54:27 +01:00
|
|
|
void API_Impl::AddObject( ::Utility::DynamicMemory::UniquePointer<ICustomBody> handle )
|
2013-11-20 11:09:27 +01:00
|
|
|
{
|
2013-11-28 17:59:12 +01:00
|
|
|
this->worldScene.AddObject( handle );
|
2013-11-20 11:09:27 +01:00
|
|
|
}
|
2013-11-21 17:22:13 +01:00
|
|
|
|
2013-11-28 17:59:12 +01:00
|
|
|
UniquePointer<ICustomBody> API_Impl::ExtractObject( const ICustomBody* objRef )
|
2013-11-21 17:22:13 +01:00
|
|
|
{
|
2013-11-28 17:59:12 +01:00
|
|
|
return this->worldScene.Extract( objRef );
|
2013-11-21 17:22:13 +01:00
|
|
|
}
|
|
|
|
|
2013-11-25 10:54:27 +01:00
|
|
|
void API_Impl::DestroyObject( const ICustomBody* objRef )
|
2013-11-20 11:09:27 +01:00
|
|
|
{
|
2013-11-28 17:59:12 +01:00
|
|
|
UniquePointer<ICustomBody> object = this->worldScene.Extract( objRef );
|
2013-11-28 18:05:19 +01:00
|
|
|
if( object )
|
2013-11-28 17:59:12 +01:00
|
|
|
{
|
|
|
|
this->destructionAction( object );
|
|
|
|
}
|
2013-11-21 17:22:13 +01:00
|
|
|
}
|
|
|
|
|
2014-01-15 10:44:31 +01:00
|
|
|
void API_Impl::AddGravity( const API::Gravity &g )
|
|
|
|
{
|
|
|
|
this->gravity.push_back( g );
|
|
|
|
}
|
|
|
|
|
|
|
|
void API_Impl::RemoveGravity( const API::Gravity &g )
|
|
|
|
{
|
|
|
|
for( ::std::vector<Gravity>::size_type i = this->gravity.size() - 1; i >= 0; --i )
|
|
|
|
{
|
|
|
|
if( g == this->gravity[i] )
|
|
|
|
{
|
|
|
|
int end = this->gravity.size() - 1;
|
|
|
|
this->gravity[i] = this->gravity[end];
|
|
|
|
this->gravity.resize( end );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-28 10:18:26 +01:00
|
|
|
void API_Impl::ApplyEffect( const Oyster::Collision3D::ICollideable& collideable, void* args, void(hitAction)(ICustomBody*, void*) )
|
2014-01-21 14:10:31 +01:00
|
|
|
{
|
2014-01-28 10:18:26 +01:00
|
|
|
this->worldScene.Visit(collideable, args, hitAction);
|
2014-01-21 14:10:31 +01:00
|
|
|
}
|
|
|
|
|
2013-12-18 14:16:13 +01:00
|
|
|
//void API_Impl::ApplyForceAt( const ICustomBody* objRef, const Float3 &worldPos, const Float3 &worldF )
|
|
|
|
//{
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// //this->worldScene.GetCustomBody( tempRef )->Apply //!< @todo TODO: need function
|
|
|
|
// this->worldScene.SetAsAltered( tempRef );
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void API_Impl::SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const Float4x4 &localI )
|
|
|
|
//{ // deprecated
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepVelocity( localI );
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void API_Impl::SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const Float4x4 &localI )
|
|
|
|
//{ // deprecated
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepMomentum( localI );
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void API_Impl::SetMass_KeepVelocity( const ICustomBody* objRef, Float m )
|
|
|
|
//{ // deprecated
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// this->worldScene.GetCustomBody( tempRef )->SetMass_KeepVelocity( m );
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void API_Impl::SetMass_KeepMomentum( const ICustomBody* objRef, Float m )
|
|
|
|
//{ // deprecated
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// this->worldScene.GetCustomBody( tempRef )->SetMass_KeepMomentum( m );
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void API_Impl::SetCenter( const ICustomBody* objRef, const Float3 &worldPos )
|
|
|
|
//{
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// //this->worldScene.GetCustomBody( tempRef )->Set //!< @todo TODO: need function
|
|
|
|
// this->worldScene.EvaluatePosition( tempRef );
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void API_Impl::SetRotation( const ICustomBody* objRef, const Float4x4 &rotation )
|
|
|
|
//{
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// this->worldScene.GetCustomBody( tempRef )->SetRotation( rotation );
|
|
|
|
// this->worldScene.EvaluatePosition( tempRef );
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void API_Impl::SetOrientation( const ICustomBody* objRef, const Float4x4 &orientation )
|
|
|
|
//{
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// this->worldScene.GetCustomBody( tempRef )->SetOrientation( orientation );
|
|
|
|
// this->worldScene.EvaluatePosition( tempRef );
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void API_Impl::SetSize( const ICustomBody* objRef, const Float3 &size )
|
|
|
|
//{
|
|
|
|
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
|
|
|
|
// if( tempRef != this->worldScene.invalid_ref )
|
|
|
|
// {
|
|
|
|
// this->worldScene.GetCustomBody( tempRef )->SetSize( size );
|
|
|
|
// this->worldScene.EvaluatePosition( tempRef );
|
|
|
|
// }
|
|
|
|
//}
|
2013-11-26 13:27:34 +01:00
|
|
|
|
2013-11-28 11:58:46 +01:00
|
|
|
UniquePointer<ICustomBody> API_Impl::CreateRigidBody( const API::SimpleBodyDescription &desc ) const
|
|
|
|
{
|
|
|
|
return new SimpleRigidBody( desc );
|
|
|
|
}
|
|
|
|
|
|
|
|
UniquePointer<ICustomBody> API_Impl::CreateRigidBody( const API::SphericalBodyDescription &desc ) const
|
2013-11-21 17:22:13 +01:00
|
|
|
{
|
2013-11-28 12:13:14 +01:00
|
|
|
return new SphericalRigidBody( desc );
|
2013-11-28 10:26:29 +01:00
|
|
|
}
|
|
|
|
|
2013-11-28 17:59:12 +01:00
|
|
|
namespace Oyster { namespace Physics
|
2013-11-28 10:26:29 +01:00
|
|
|
{
|
2013-11-28 17:59:12 +01:00
|
|
|
namespace Default
|
|
|
|
{
|
|
|
|
void EventAction_Destruction( ::Utility::DynamicMemory::UniquePointer<::Oyster::Physics::ICustomBody> proto )
|
|
|
|
{ /* Do nothing except allowing the proto uniquePointer destroy itself. */ }
|
2013-11-28 10:26:29 +01:00
|
|
|
|
2014-01-29 11:22:04 +01:00
|
|
|
::Oyster::Physics::ICustomBody::SubscriptMessage EventAction_BeforeCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter )
|
2013-11-28 17:59:12 +01:00
|
|
|
{ /* Do nothing except returning business as usual. */
|
|
|
|
return ::Oyster::Physics::ICustomBody::SubscriptMessage_none;
|
|
|
|
}
|
2014-01-17 16:07:25 +01:00
|
|
|
|
2014-01-29 11:22:04 +01:00
|
|
|
void EventAction_AfterCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss )
|
2014-01-22 13:50:54 +01:00
|
|
|
{ /* Do nothing except returning business as usual. */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-01-17 16:07:25 +01:00
|
|
|
void EventAction_Move( const ::Oyster::Physics::ICustomBody *object )
|
|
|
|
{ /* Do nothing. */ }
|
2013-11-28 10:26:29 +01:00
|
|
|
}
|
2013-11-28 17:59:12 +01:00
|
|
|
} }
|