diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index b3abf32c..ae190608 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -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(); 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 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::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::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 ); diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 0c08bf11..314e0657 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -32,6 +32,9 @@ namespace Oyster ::Utility::DynamicMemory::UniquePointer 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; Octree worldScene; }; diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 0904551d..019a4af7 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -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 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. diff --git a/Code/OysterPhysics3D/OysterPhysics3D.h b/Code/OysterPhysics3D/OysterPhysics3D.h index 970d739e..f814ff46 100644 --- a/Code/OysterPhysics3D/OysterPhysics3D.h +++ b/Code/OysterPhysics3D/OysterPhysics3D.h @@ -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 */