diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index ae190608..ec82c57c 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -22,7 +22,7 @@ namespace Float4 worldPointOfContact; if( proto->Intersects(*deuter, worldPointOfContact) ) { - switch( proto->CallSubscription(proto, deuter) ) + switch( proto->CallSubscription_Collision(deuter) ) { case ICustomBody::SubscriptMessage_ignore_collision_response: break; @@ -163,7 +163,7 @@ void API_Impl::Update() for( ; proto != updateList.end(); ++proto ) { // Step 1: Apply Gravity - (*proto)->GetState( state ); + Float4 gravityImpulse = Float4::null; for( ::std::vector::size_type i = 0; i < this->gravity.size(); ++i ) { switch( this->gravity[i].gravityType ) @@ -175,12 +175,12 @@ void API_Impl::Update() 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 ); + gravityImpulse += (this->updateFrameLength * force / ::std::sqrt(rSquared)) * d; } break; } case Gravity::GravityType_Directed: - state.ApplyLinearImpulse( Float4(this->gravity[i].directed.impulse, 0.0f) ); + gravityImpulse += Float4( this->gravity[i].directed.impulse, 0.0f ); break; // case Gravity::GravityType_DirectedField: // //this->gravity[i].directedField. @@ -189,7 +189,14 @@ void API_Impl::Update() default: break; } } - (*proto)->SetState( state ); + + if( gravityImpulse != Float4::null ) + { + (*proto)->GetState( state ); + state.ApplyLinearImpulse( gravityImpulse ); + (*proto)->SetGravityNormal( gravityImpulse.GetNormalized().xyz ); + (*proto)->SetState( state ); + } // Step 2: Apply Collision Response this->worldScene.Visit( *proto, OnPossibleCollision ); @@ -202,6 +209,7 @@ void API_Impl::Update() { case UpdateState_altered: this->worldScene.SetAsAltered( this->worldScene.GetTemporaryReferenceOf(*proto) ); + (*proto)->CallSubscription_Move(); case UpdateState_resting: default: break; } @@ -367,5 +375,8 @@ namespace Oyster { namespace Physics { /* Do nothing except returning business as usual. */ return ::Oyster::Physics::ICustomBody::SubscriptMessage_none; } + + void EventAction_Move( const ::Oyster::Physics::ICustomBody *object ) + { /* Do nothing. */ } } } } \ No newline at end of file diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 314e0657..8b38004c 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -32,8 +32,8 @@ 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 AddGravity( const API::Gravity &g ); + void RemoveGravity( const API::Gravity &g ); //void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF ); @@ -52,7 +52,7 @@ namespace Oyster private: ::Oyster::Math::Float gravityConstant, updateFrameLength; EventAction_Destruction destructionAction; - ::std::vector gravity; + ::std::vector gravity; Octree worldScene; }; @@ -60,6 +60,7 @@ namespace Oyster { void EventAction_Destruction( ::Utility::DynamicMemory::UniquePointer<::Oyster::Physics::ICustomBody> proto ); ::Oyster::Physics::ICustomBody::SubscriptMessage EventAction_Collision( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter ); + void EventAction_Move( const ::Oyster::Physics::ICustomBody *object ); } } } diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index 49fa292f..b506f032 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -46,7 +46,8 @@ SimpleRigidBody::SimpleRigidBody() this->rigid = RigidBody(); this->rigid.SetMass_KeepMomentum( 16.0f ); this->gravityNormal = Float3::null; - this->collisionAction = Default::EventAction_Collision; + this->onCollision = Default::EventAction_Collision; + this->onMovement = Default::EventAction_Move; this->ignoreGravity = this->isForwarded = false; this->scene = nullptr; } @@ -63,13 +64,22 @@ SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) this->gravityNormal = Float3::null; - if( desc.subscription ) + if( desc.subscription_onCollision ) { - this->collisionAction = desc.subscription; + this->onCollision = desc.subscription_onCollision; } else { - this->collisionAction = Default::EventAction_Collision; + this->onCollision = Default::EventAction_Collision; + } + + if( desc.subscription_onMovement ) + { + this->onMovement= desc.subscription_onMovement; + } + else + { + this->onMovement = Default::EventAction_Move; } this->ignoreGravity = desc.ignoreGravity; @@ -138,9 +148,14 @@ void SimpleRigidBody::SetState( const SimpleRigidBody::State &state ) } } -ICustomBody::SubscriptMessage SimpleRigidBody::CallSubscription( const ICustomBody *proto, const ICustomBody *deuter ) +ICustomBody::SubscriptMessage SimpleRigidBody::CallSubscription_Collision( const ICustomBody *deuter ) { - return this->collisionAction( proto, deuter ); + return this->onCollision( this, deuter ); +} + +void SimpleRigidBody::CallSubscription_Move() +{ + this->onMovement( this ); } bool SimpleRigidBody::IsAffectedByGravity() const @@ -282,11 +297,23 @@ void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_Collision functi { if( functionPointer ) { - this->collisionAction = functionPointer; + this->onCollision = functionPointer; } else { - this->collisionAction = Default::EventAction_Collision; + this->onCollision = Default::EventAction_Collision; + } +} + +void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_Move functionPointer ) +{ + if( functionPointer ) + { + this->onMovement = functionPointer; + } + else + { + this->onMovement = Default::EventAction_Move; } } diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index 618e0235..7f1c50e6 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -21,7 +21,9 @@ namespace Oyster { namespace Physics void SetState( const State &state ); //::Oyster::Math::Float3 GetRigidLinearVelocity() const; - SubscriptMessage CallSubscription( const ICustomBody *proto, const ICustomBody *deuter ); + SubscriptMessage CallSubscription_Collision( const ICustomBody *deuter ); + void CallSubscription_Move(); + bool IsAffectedByGravity() const; bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const; bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; @@ -39,7 +41,10 @@ namespace Oyster { namespace Physics void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime ); void SetScene( void *scene ); + void SetSubscription( EventAction_Collision functionPointer ); + void SetSubscription( EventAction_Move functionPointer ); + void SetGravity( bool ignore); void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ); //void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ); @@ -56,7 +61,8 @@ namespace Oyster { namespace Physics ::Oyster::Physics3D::RigidBody rigid; ::Oyster::Math::Float4 deltaPos, deltaAxis; ::Oyster::Math::Float3 gravityNormal; - EventAction_Collision collisionAction; + EventAction_Collision onCollision; + EventAction_Move onMovement; Octree *scene; bool ignoreGravity, isForwarded; }; diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index 2d96412c..3ce1a6ce 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -13,7 +13,8 @@ SphericalRigidBody::SphericalRigidBody() this->rigid = RigidBody(); this->rigid.SetMass_KeepMomentum( 10.0f ); this->gravityNormal = Float3::null; - this->collisionAction = Default::EventAction_Collision; + this->onCollision = Default::EventAction_Collision; + this->onMovement = Default::EventAction_Move; this->ignoreGravity = this->isForwarded = false; this->scene = nullptr; this->body = Sphere( Float3::null, 0.5f ); @@ -32,13 +33,22 @@ SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &des this->gravityNormal = Float3::null; - if( desc.subscription ) + if( desc.subscription_onCollision ) { - this->collisionAction = desc.subscription; + this->onCollision = desc.subscription_onCollision; } else { - this->collisionAction = Default::EventAction_Collision; + this->onCollision = Default::EventAction_Collision; + } + + if( desc.subscription_onMovement ) + { + this->onMovement= desc.subscription_onMovement; + } + else + { + this->onMovement = Default::EventAction_Move; } this->ignoreGravity = desc.ignoreGravity; @@ -108,9 +118,14 @@ void SphericalRigidBody::SetState( const SphericalRigidBody::State &state ) } } -ICustomBody::SubscriptMessage SphericalRigidBody::CallSubscription( const ICustomBody *proto, const ICustomBody *deuter ) +ICustomBody::SubscriptMessage SphericalRigidBody::CallSubscription_Collision( const ICustomBody *deuter ) { - return this->collisionAction( proto, deuter ); + return this->onCollision( this, deuter ); +} + +void SphericalRigidBody::CallSubscription_Move() +{ + this->onMovement( this ); } bool SphericalRigidBody::IsAffectedByGravity() const @@ -207,11 +222,23 @@ void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_Collision fun { if( functionPointer ) { - this->collisionAction = functionPointer; + this->onCollision = functionPointer; } else { - this->collisionAction = Default::EventAction_Collision; + this->onCollision = Default::EventAction_Collision; + } +} + +void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_Move functionPointer ) +{ + if( functionPointer ) + { + this->onMovement = functionPointer; + } + else + { + this->onMovement = Default::EventAction_Move; } } diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.h b/Code/GamePhysics/Implementation/SphericalRigidBody.h index 51d1b998..74b74535 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.h +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.h @@ -22,7 +22,9 @@ namespace Oyster { namespace Physics void SetState( const State &state ); //::Oyster::Math::Float3 GetRigidLinearVelocity() const; - SubscriptMessage CallSubscription( const ICustomBody *proto, const ICustomBody *deuter ); + SubscriptMessage CallSubscription_Collision( const ICustomBody *deuter ); + void CallSubscription_Move(); + bool IsAffectedByGravity() const; bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const; bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; @@ -40,7 +42,10 @@ namespace Oyster { namespace Physics void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime ); void SetScene( void *scene ); + void SetSubscription( EventAction_Collision functionPointer ); + void SetSubscription( EventAction_Move functionPointer ); + void SetGravity( bool ignore); void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ); //void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ); @@ -57,7 +62,8 @@ namespace Oyster { namespace Physics ::Oyster::Physics3D::RigidBody rigid; ::Oyster::Math::Float4 deltaPos, deltaAxis; ::Oyster::Math::Float3 gravityNormal; - EventAction_Collision collisionAction; + EventAction_Collision onCollision; + EventAction_Move onMovement; bool ignoreGravity, isForwarded; Octree *scene; ::Oyster::Collision3D::Sphere body; diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 019a4af7..82a139c3 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -129,12 +129,12 @@ namespace Oyster /******************************************************** * TODO: @todo doc ********************************************************/ - virtual void AddGravity( const Gravity &g ) = 0; + virtual void AddGravity( const API::Gravity &g ) = 0; /******************************************************** * TODO: @todo doc ********************************************************/ - virtual void RemoveGravity( const Gravity &g ) = 0; + virtual void RemoveGravity( const API::Gravity &g ) = 0; ///******************************************************** // * Apply force on an object. @@ -235,6 +235,7 @@ namespace Oyster }; typedef SubscriptMessage (*EventAction_Collision)( const ICustomBody *proto, const ICustomBody *deuter ); + typedef void (*EventAction_Move)( const ICustomBody *object ); typedef Struct::SimpleBodyDescription SimpleBodyDescription; typedef Struct::SphericalBodyDescription SphericalBodyDescription; typedef Struct::CustomBodyState State; @@ -250,7 +251,12 @@ namespace Oyster /******************************************************** * @todo TODO: need doc ********************************************************/ - virtual SubscriptMessage CallSubscription( const ICustomBody *proto, const ICustomBody *deuter ) = 0; + virtual SubscriptMessage CallSubscription_Collision( const ICustomBody *deuter ) = 0; + + /******************************************************** + * @todo TODO: need doc + ********************************************************/ + virtual void CallSubscription_Move() = 0; /******************************************************** * @todo TODO: need doc @@ -371,6 +377,13 @@ namespace Oyster ********************************************************/ virtual void SetSubscription( EventAction_Collision functionPointer ) = 0; + /******************************************************** + * Sets the function that will be called by the engine + * whenever an object have moved. + * @param functionPointer: If NULL, an empty default function will be set. + ********************************************************/ + virtual void SetSubscription( EventAction_Move functionPointer ) = 0; + /******************************************************** * @param ignore: True if Engine should not apply Gravity. ********************************************************/ diff --git a/Code/GamePhysics/PhysicsStructs-Impl.h b/Code/GamePhysics/PhysicsStructs-Impl.h index 17c18ba2..2f218095 100644 --- a/Code/GamePhysics/PhysicsStructs-Impl.h +++ b/Code/GamePhysics/PhysicsStructs-Impl.h @@ -17,7 +17,8 @@ namespace Oyster this->size = ::Oyster::Math::Float4( 1.0f ); this->mass = 12.0f; this->inertiaTensor = ::Oyster::Math::Float4x4::identity; - this->subscription = NULL; + this->subscription_onCollision = NULL; + this->subscription_onMovement = NULL; this->ignoreGravity = false; } @@ -27,7 +28,8 @@ namespace Oyster this->centerPosition = ::Oyster::Math::Float4::standard_unit_w; this->radius = 0.5f; this->mass = 10.0f; - this->subscription = NULL; + this->subscription_onCollision = NULL; + this->subscription_onMovement = NULL; this->ignoreGravity = false; } diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index 7ed37c59..1d3d58dd 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -15,7 +15,8 @@ namespace Oyster { namespace Physics ::Oyster::Math::Float4 size; ::Oyster::Math::Float mass; ::Oyster::Math::Float4x4 inertiaTensor; - ::Oyster::Physics::ICustomBody::EventAction_Collision subscription; + ::Oyster::Physics::ICustomBody::EventAction_Collision subscription_onCollision; + ::Oyster::Physics::ICustomBody::EventAction_Move subscription_onMovement; bool ignoreGravity; SimpleBodyDescription(); @@ -27,7 +28,8 @@ namespace Oyster { namespace Physics ::Oyster::Math::Float4 centerPosition; ::Oyster::Math::Float radius; ::Oyster::Math::Float mass; - ::Oyster::Physics::ICustomBody::EventAction_Collision subscription; + ::Oyster::Physics::ICustomBody::EventAction_Collision subscription_onCollision; + ::Oyster::Physics::ICustomBody::EventAction_Move subscription_onMovement; bool ignoreGravity; SphericalBodyDescription();