Merge remote-tracking branch 'origin/Physics' into GameLogic

This commit is contained in:
Erik Persson 2014-01-16 11:40:58 +01:00
commit df7801336a
7 changed files with 196 additions and 20 deletions

View File

@ -3,6 +3,7 @@
#include "SimpleRigidBody.h"
#include "SphericalRigidBody.h"
using namespace ::Oyster;
using namespace ::Oyster::Physics;
using namespace ::Oyster::Math;
using namespace ::Oyster::Collision3D;
@ -113,6 +114,7 @@ API_Impl::API_Impl()
this->gravityConstant = Constant::gravity_constant;
this->updateFrameLength = 1.0f / 120.0f;
this->destructionAction = Default::EventAction_Destruction;
this->gravity = ::std::vector<Gravity>();
this->worldScene = Octree();
}
@ -121,6 +123,8 @@ API_Impl::~API_Impl() {}
void API_Impl::Init( unsigned int numObjects, unsigned int numGravityWells , const Float3 &worldSize )
{
unsigned char numLayers = 4; //!< @todo TODO: calc numLayers from worldSize
this->gravity.resize( 0 );
this->gravity.reserve( numGravityWells );
this->worldScene = Octree( numObjects, numLayers, worldSize );
}
@ -153,14 +157,39 @@ float API_Impl::GetFrameTimeLength() const
void API_Impl::Update()
{ /** @todo TODO: Update is a temporary solution .*/
::std::vector<ICustomBody*> updateList;
ICustomBody::State state;
auto proto = this->worldScene.Sample( Universe(), updateList ).begin();
for( ; proto != updateList.end(); ++proto )
{
// Step 1: @todo TODO: Apply Gravity
// Step 1: Apply Gravity
(*proto)->GetState( state );
for( ::std::vector<Gravity>::size_type i = 0; i < this->gravity.size(); ++i )
{
switch( this->gravity[i].gravityType )
{
case Gravity::GravityType_Well:
{
Float4 d = state.GetCenterPosition() - Float4( this->gravity[i].well.position, 1.0f );
Float rSquared = d.Dot( d );
if( rSquared != 0.0 )
{
Float force = Physics3D::Formula::ForceField( this->gravityConstant, state.GetMass(), this->gravity[i].well.mass, rSquared );
state.ApplyLinearImpulse( (this->updateFrameLength * force / ::std::sqrt(rSquared)) * d );
}
break;
}
case Gravity::GravityType_Directed:
state.ApplyLinearImpulse( Float4(this->gravity[i].directed.impulse, 0.0f) );
break;
// case Gravity::GravityType_DirectedField:
// //this->gravity[i].directedField.
// //! TODO: @todo rethink
// break;
default: break;
}
}
(*proto)->SetState( state );
// Step 2: Apply Collision Response
this->worldScene.Visit( *proto, OnPossibleCollision );
@ -213,6 +242,24 @@ void API_Impl::DestroyObject( const ICustomBody* objRef )
}
}
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 );
}
}
}
//void API_Impl::ApplyForceAt( const ICustomBody* objRef, const Float3 &worldPos, const Float3 &worldF )
//{
// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );

View File

@ -32,6 +32,9 @@ namespace Oyster
::Utility::DynamicMemory::UniquePointer<ICustomBody> ExtractObject( const ICustomBody* objRef );
void DestroyObject( const ICustomBody* objRef );
void AddGravity( const Gravity &g );
void RemoveGravity( const Gravity &g );
//void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF );
//void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI );
@ -49,6 +52,7 @@ namespace Oyster
private:
::Oyster::Math::Float gravityConstant, updateFrameLength;
EventAction_Destruction destructionAction;
::std::vector<Gravity> gravity;
Octree worldScene;
};

View File

@ -22,6 +22,7 @@ namespace Oyster
struct SimpleBodyDescription;
struct SphericalBodyDescription;
struct CustomBodyState;
struct Gravity;
}
enum UpdateState
@ -40,6 +41,7 @@ namespace Oyster
public:
typedef Struct::SimpleBodyDescription SimpleBodyDescription;
typedef Struct::SphericalBodyDescription SphericalBodyDescription;
typedef Struct::Gravity Gravity;
typedef void (*EventAction_Destruction)( ::Utility::DynamicMemory::UniquePointer<ICustomBody> proto );
@ -124,6 +126,16 @@ namespace Oyster
********************************************************/
virtual void DestroyObject( const ICustomBody* objRef ) = 0;
/********************************************************
* TODO: @todo doc
********************************************************/
virtual void AddGravity( const Gravity &g ) = 0;
/********************************************************
* TODO: @todo doc
********************************************************/
virtual void RemoveGravity( const Gravity &g ) = 0;
///********************************************************
// * Apply force on an object.
// * @param objRef: A pointer to the ICustomBody representing a physical object.

View File

@ -353,6 +353,26 @@ namespace Oyster
return *this;
}
inline bool GravityWell::operator == ( const GravityWell &gravity ) const
{
if( this->position == gravity.position )
if( this->mass == gravity.mass )
{
return true;
}
return false;
}
inline bool GravityWell::operator != ( const GravityWell &gravity ) const
{
if( this->position == gravity.position )
if( this->mass == gravity.mass )
{
return false;
}
return true;
}
inline GravityDirected::GravityDirected( )
{
this->impulse = ::Oyster::Math::Float3::null;
@ -370,6 +390,16 @@ namespace Oyster
return *this;
}
inline bool GravityDirected::operator == ( const GravityDirected &gravity ) const
{
return this->impulse == gravity.impulse;
}
inline bool GravityDirected::operator != ( const GravityDirected &gravity ) const
{
return this->impulse != gravity.impulse;
}
inline GravityDirectedField::GravityDirectedField( )
{
this->normalizedDirection = ::Oyster::Math::Float3::null;
@ -393,6 +423,28 @@ namespace Oyster
return *this;
}
inline bool GravityDirectedField::operator == ( const GravityDirectedField &gravity ) const
{
if( this->normalizedDirection == gravity.normalizedDirection )
if( this->mass == gravity.mass )
if( this->magnitude == gravity.magnitude )
{
return true;
}
return false;
}
inline bool GravityDirectedField::operator != ( const GravityDirectedField &gravity ) const
{
if( this->normalizedDirection == gravity.normalizedDirection )
if( this->mass == gravity.mass )
if( this->magnitude == gravity.magnitude )
{
return false;
}
return true;
}
inline Gravity::Gravity()
{
this->gravityType = GravityType_Undefined;
@ -437,6 +489,36 @@ namespace Oyster
return *this;
}
inline bool Gravity::operator == ( const Gravity &gravity ) const
{
if( this->gravityType == gravity.gravityType )
{
switch( this->gravityType )
{
case GravityType_Well: return this->well == gravity.well;
case GravityType_Directed: return this->directed == gravity.directed;
case GravityType_DirectedField: return this->directedField == gravity.directedField;
default: return true;
}
}
return false;
}
inline bool Gravity::operator != ( const Gravity &gravity ) const
{
if( this->gravityType == gravity.gravityType )
{
switch( this->gravityType )
{
case GravityType_Well: return this->well != gravity.well;
case GravityType_Directed: return this->directed != gravity.directed;
case GravityType_DirectedField: return this->directedField != gravity.directedField;
default: return false;
}
}
return true;
}
}
}
}

View File

@ -123,7 +123,10 @@ namespace Oyster { namespace Physics
GravityWell( );
GravityWell( const GravityWell &gravityWell );
GravityWell& operator=( const GravityWell &gravityWell );
GravityWell & operator = ( const GravityWell &gravityWell );
bool operator == ( const GravityWell &gravity ) const;
bool operator != ( const GravityWell &gravity ) const;
};
struct GravityDirected
@ -133,6 +136,9 @@ namespace Oyster { namespace Physics
GravityDirected( );
GravityDirected( const GravityDirected &gravityDirected );
GravityDirected & operator = ( const GravityDirected &gravityDirected );
bool operator == ( const GravityDirected &gravity ) const;
bool operator != ( const GravityDirected &gravity ) const;
};
struct GravityDirectedField
@ -143,7 +149,10 @@ namespace Oyster { namespace Physics
GravityDirectedField( );
GravityDirectedField( const GravityDirectedField &gravityDirectedField );
GravityDirectedField & operator=( const GravityDirectedField &gravityDirectedField );
GravityDirectedField & operator = ( const GravityDirectedField &gravityDirectedField );
bool operator == ( const GravityDirectedField &gravity ) const;
bool operator != ( const GravityDirectedField &gravity ) const;
};
struct Gravity
@ -177,6 +186,9 @@ namespace Oyster { namespace Physics
Gravity( );
Gravity( const Gravity &gravity );
Gravity & operator = ( const Gravity &gravity );
bool operator == ( const Gravity &gravity ) const;
bool operator != ( const Gravity &gravity ) const;
};
}
} }

View File

@ -204,7 +204,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
bool SeperatingAxisTest_AxisAlignedVsTransformedBox( const Float4 &boundingOffsetA, const Float4 &boundingOffsetB, const Float4x4 &rotationB, const Float4 &worldOffset, Float4 &worldPointOfContact )
bool SeperatingAxisTest_AxisAlignedVsTransformedBox( const Float4 &boundingOffsetA, const Float4 &boundingOffsetB, const Float4x4 &rotationB, const Float4 &worldOffset, Float4 &localPointOfContact )
{ // by Dan Andersson
/*****************************************************************
@ -241,7 +241,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
{ // no intersection
return false;
}
worldPointOfContact = s * ( centerSeperation * eA / edgeSeperation );
localPointOfContact = s * ( centerSeperation * eA / edgeSeperation );
s = Float4::standard_unit_y;
centerSeperation = t.Dot(s);
@ -251,7 +251,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
{ // no intersection
return false;
}
worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
localPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
s = Float4::standard_unit_z;
centerSeperation = t.Dot(s);
@ -261,7 +261,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
{ // no intersection
return false;
}
worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
localPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
s = rotationB.v[0];
centerSeperation = t.Dot(s);
@ -271,7 +271,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
{ // no intersection
return false;
}
worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
localPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
s = rotationB.v[1];
centerSeperation = t.Dot(s);
@ -281,7 +281,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
{ // no intersection
return false;
}
worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
localPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
s = rotationB.v[2];
centerSeperation = t.Dot(s);
@ -291,7 +291,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
{ // no intersection
return false;
}
worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation ); // enough point of contact data gathered for approximative result.
localPointOfContact += s * ( centerSeperation * eA / edgeSeperation ); // enough point of contact data gathered for approximative result.
s = Float4( Float3::standard_unit_x.Cross(rotationB.v[0].xyz), 0.0f );
centerSeperation = t.Dot(s);
@ -374,7 +374,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
return false;
}
worldPointOfContact *= 0.5f;
localPointOfContact *= 0.5f;
return true;
}
}
@ -821,10 +821,11 @@ namespace Oyster { namespace Collision3D { namespace Utility
Float4 alignedOffsetBoundaries = (boxB.maxVertex - boxB.minVertex) * 0.5f,
offset = boxA.center - Average( boxB.maxVertex, boxB.minVertex );
Float4 pointOfContact;
if( Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( alignedOffsetBoundaries, boxA.boundingOffset, boxA.rotation, offset, pointOfContact ) )
Float4 localPointOfContact;
if( Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( alignedOffsetBoundaries, boxA.boundingOffset, boxA.rotation, offset, localPointOfContact ) )
{
worldPointOfContact = pointOfContact.xyz;
worldPointOfContact = localPointOfContact + boxA.center;
worldPointOfContact.w = 1.0f;
return true;
}
else return false;
@ -843,10 +844,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
Float4x4 rotationB = TransformMatrix( InverseRotationMatrix(boxA.rotation), boxB.rotation );
Float4 posB = boxB.center - boxA.center;
Float4 pointOfContact;
if( Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( boxA.boundingOffset, boxB.boundingOffset, rotationB, posB, pointOfContact ) )
Float4 localPointOfContact;
if( Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( boxA.boundingOffset, boxB.boundingOffset, rotationB, posB, localPointOfContact ) )
{
worldPointOfContact = TransformVector( boxA.rotation, pointOfContact, pointOfContact ).xyz;
worldPointOfContact = TransformVector( boxA.rotation, localPointOfContact, localPointOfContact );
worldPointOfContact += boxA.center;
worldPointOfContact.w = 1.0f;
return true;
}
else return false;

View File

@ -273,6 +273,22 @@ namespace Oyster { namespace Physics3D
return momentOfInertia * angularImpulseAcceleration;
}
/******************************************************************
* @todo TODO: doc
******************************************************************/
inline ::Oyster::Math::Float ForceField( ::Oyster::Math::Float g, ::Oyster::Math::Float massA, ::Oyster::Math::Float massB, ::Oyster::Math::Float radiusSquared )
{
return g * massA * massB / radiusSquared;
}
/******************************************************************
* @todo TODO: doc
******************************************************************/
inline ::Oyster::Math::Float ForceField( ::Oyster::Math::Float g, ::Oyster::Math::Float massA, ::Oyster::Math::Float massB, const ::Oyster::Math::Float4 &deltaPos )
{
return g * massA * massB / deltaPos.Dot( deltaPos );
}
namespace MomentOfInertia
{ /// Library of Formulas to calculate moment of inerta for simple shapes
/** @todo TODO: add MomentOfInertia tensor formulas */