diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 13184ce5..2c745500 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -1,6 +1,7 @@ #include "PhysicsAPI_Impl.h" -#include "SimpleRigidBody.h" #include "OysterPhysics3D.h" +#include "SimpleRigidBody.h" +#include "SphericalRigidBody.h" using namespace ::Oyster::Physics; using namespace ::Oyster::Physics3D; @@ -161,9 +162,14 @@ void API_Impl::SetSize( const ICustomBody* objRef, const Float3 &size ) //! @todo TODO: implement stub } -UniquePointer API_Impl::CreateSimpleRigidBody() const +UniquePointer API_Impl::CreateRigidBody( const API::SimpleBodyDescription &desc ) const { - return new SimpleRigidBody(); + return new SimpleRigidBody( desc ); +} + +UniquePointer API_Impl::CreateRigidBody( const API::SphericalBodyDescription &desc ) const +{ + return new SphericalRigidBody(); } namespace Oyster { namespace Physics { namespace Default diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 28858da0..7d6858f0 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -41,7 +41,9 @@ namespace Oyster void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation ); void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size ); - ::Utility::DynamicMemory::UniquePointer CreateSimpleRigidBody() const; + ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SimpleBodyDescription &desc ) const; + ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SphericalBodyDescription &desc ) const; + private: ::Oyster::Math::Float gravityConstant, updateFrameLength; EventAction_Destruction destructionAction; diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index 95256915..d83aa399 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -2,16 +2,38 @@ #include "PhysicsAPI_Impl.h" using namespace ::Oyster::Physics; +using namespace ::Oyster::Physics3D; using namespace ::Oyster::Math3D; using namespace ::Oyster::Collision3D; using namespace ::Utility::DynamicMemory; using namespace ::Utility::Value; SimpleRigidBody::SimpleRigidBody() - : previous(), current(), - gravityNormal(0.0f), - collisionAction(Default::EventAction_Collision), - ignoreGravity(false) {} +{ + this->rigid = RigidBody(); + this->gravityNormal = Float3::null; + this->collisionAction = Default::EventAction_Collision; + this->ignoreGravity = false; +} + +SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) +{ + this->rigid = RigidBody( Box( desc.rotation, desc.centerPosition, desc.size ), + desc.mass, + desc.inertiaTensor ); + this->gravityNormal = Float3::null; + + if( desc.subscription ) + { + this->collisionAction = desc.subscription; + } + else + { + this->collisionAction = Default::EventAction_Collision; + } + + this->ignoreGravity = desc.ignoreGravity; +} SimpleRigidBody::~SimpleRigidBody() {} @@ -27,10 +49,10 @@ bool SimpleRigidBody::IsAffectedByGravity() const bool SimpleRigidBody::Intersects( const ICustomBody &object, Float timeStepLength, Float &deltaWhen, Float3 &worldPointOfContact ) const { - if( object.Intersects(this->current.box) ) + if( object.Intersects(this->rigid.box) ) { //! @todo TODO: better implementation needed deltaWhen = timeStepLength; - worldPointOfContact = Average( this->current.box.center, object.GetCenter() ); + worldPointOfContact = Average( this->rigid.box.center, object.GetCenter() ); return true; } else @@ -41,18 +63,18 @@ bool SimpleRigidBody::Intersects( const ICustomBody &object, Float timeStepLengt bool SimpleRigidBody::Intersects( const ICollideable &shape ) const { - return this->current.box.Intersects( shape ); + return this->rigid.box.Intersects( shape ); } Sphere & SimpleRigidBody::GetBoundingSphere( Sphere &targetMem ) const { - return targetMem = Sphere( this->current.box.center, this->current.box.boundingOffset.GetMagnitude() ); + return targetMem = Sphere( this->rigid.box.center, this->rigid.box.boundingOffset.GetMagnitude() ); } Float3 & SimpleRigidBody::GetNormalAt( const Float3 &worldPos, Float3 &targetMem ) const { //! @todo TODO: better implementation needed - return targetMem = (worldPos - this->current.box.center).GetNormalized(); + return targetMem = (worldPos - this->rigid.box.center).GetNormalized(); } Float3 & SimpleRigidBody::GetGravityNormal( Float3 &targetMem ) const @@ -62,32 +84,31 @@ Float3 & SimpleRigidBody::GetGravityNormal( Float3 &targetMem ) const Float3 & SimpleRigidBody::GetCenter( Float3 &targetMem ) const { - return targetMem = this->current.box.center; + return targetMem = this->rigid.box.center; } Float4x4 & SimpleRigidBody::GetRotation( Float4x4 &targetMem ) const { - return targetMem = this->current.box.rotation; + return targetMem = this->rigid.box.rotation; } Float4x4 & SimpleRigidBody::GetOrientation( Float4x4 &targetMem ) const { - return targetMem = this->current.GetOrientation(); + return targetMem = this->rigid.GetOrientation(); } Float4x4 & SimpleRigidBody::GetView( Float4x4 &targetMem ) const { - return targetMem = this->current.GetView(); + return targetMem = this->rigid.GetView(); } UpdateState SimpleRigidBody::Update( Float timeStepLength ) { - this->previous = this->current; // memorizing the old state - - this->current.Update_LeapFrog( timeStepLength ); + this->rigid.Update_LeapFrog( timeStepLength ); // compare previous and new state and return result - return this->current == this->previous ? UpdateState_resting : UpdateState_altered; + //return this->current == this->previous ? UpdateState_resting : UpdateState_altered; + return UpdateState_altered; } void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_Collision functionPointer ) @@ -115,40 +136,40 @@ void SimpleRigidBody::SetGravityNormal( const Float3 &normalizedVector ) void SimpleRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI ) { - this->current.SetMomentOfInertia_KeepVelocity( localI ); + this->rigid.SetMomentOfInertia_KeepVelocity( localI ); } void SimpleRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI ) { - this->current.SetMomentOfInertia_KeepMomentum( localI ); + this->rigid.SetMomentOfInertia_KeepMomentum( localI ); } void SimpleRigidBody::SetMass_KeepVelocity( Float m ) { - this->current.SetMass_KeepVelocity( m ); + this->rigid.SetMass_KeepVelocity( m ); } void SimpleRigidBody::SetMass_KeepMomentum( Float m ) { - this->current.SetMass_KeepMomentum( m ); + this->rigid.SetMass_KeepMomentum( m ); } void SimpleRigidBody::SetCenter( const Float3 &worldPos ) { - this->current.SetCenter( worldPos ); + this->rigid.SetCenter( worldPos ); } void SimpleRigidBody::SetRotation( const Float4x4 &rotation ) { - this->current.SetRotation( rotation ); + this->rigid.SetRotation( rotation ); } void SimpleRigidBody::SetOrientation( const Float4x4 &orientation ) { - this->current.SetOrientation( orientation ); + this->rigid.SetOrientation( orientation ); } void SimpleRigidBody::SetSize( const Float3 &size ) { - this->current.SetSize( size ); + this->rigid.SetSize( size ); } \ No newline at end of file diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index c19a1ddb..c76f6a51 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -10,6 +10,7 @@ namespace Oyster { namespace Physics { public: SimpleRigidBody(); + SimpleRigidBody( const API::SimpleBodyDescription &desc ); virtual ~SimpleRigidBody(); ::Utility::DynamicMemory::UniquePointer Clone() const; @@ -41,7 +42,7 @@ namespace Oyster { namespace Physics void SetSize( const ::Oyster::Math::Float3 &size ); private: - ::Oyster::Physics3D::RigidBody previous, current; + ::Oyster::Physics3D::RigidBody rigid; ::Oyster::Math::Float3 gravityNormal; EventAction_Collision collisionAction; bool ignoreGravity; diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index 6d50b386..1c9b7b52 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -2,6 +2,7 @@ #include "PhysicsAPI_Impl.h" using namespace ::Oyster::Physics; +using namespace ::Oyster::Physics3D; using namespace ::Oyster::Math3D; using namespace ::Oyster::Collision3D; using namespace ::Utility::DynamicMemory; diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 71bebc1f..dd36a9ee 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -45,6 +45,9 @@ namespace Oyster class PHYSICS_DLL_USAGE API { public: + struct SimpleBodyDescription; + struct SphericalBodyDescription; + typedef void (*EventAction_Destruction)( ::Utility::DynamicMemory::UniquePointer proto ); /** Gets the Physics instance. */ @@ -207,10 +210,18 @@ namespace Oyster /******************************************************** * Creates a new dynamically allocated object that can be used as a component for more complex ICustomBodies. + * @param desc: @see API::SimpleBodyDescription * @return A pointer along with the responsibility to delete. ********************************************************/ - virtual ::Utility::DynamicMemory::UniquePointer CreateSimpleRigidBody() const = 0; - + virtual ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SimpleBodyDescription &desc ) const = 0; + + /******************************************************** + * Creates a new dynamically allocated object that can be used as a component for more complex ICustomBodies. + * @param desc: @see API::SphericalBodyDescription + * @return A pointer along with the responsibility to delete. + ********************************************************/ + virtual ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SphericalBodyDescription &desc ) const = 0; + protected: virtual ~API() {} }; @@ -375,6 +386,50 @@ namespace Oyster ********************************************************/ virtual void SetSize( const ::Oyster::Math::Float3 &size ) = 0; }; + + struct API::SimpleBodyDescription + { + ::Oyster::Math::Float4x4 rotation; + ::Oyster::Math::Float3 centerPosition; + ::Oyster::Math::Float3 size; + ::Oyster::Math::Float mass; + ::Oyster::Math::Float4x4 inertiaTensor; + ICustomBody::EventAction_Collision subscription; + bool ignoreGravity; + + SimpleBodyDescription() + { + this->rotation = ::Oyster::Math::Float4x4::identity; + this->centerPosition = ::Oyster::Math::Float3::null; + this->size = ::Oyster::Math::Float3( 1.0f ); + this->mass = 12.0f; + this->inertiaTensor = ::Oyster::Math::Float4x4::identity; + this->subscription = NULL; + this->ignoreGravity = false; + } + }; + + struct API::SphericalBodyDescription + { + ::Oyster::Math::Float4x4 rotation; + ::Oyster::Math::Float3 centerPosition; + ::Oyster::Math::Float radius; + ::Oyster::Math::Float mass; + ::Oyster::Math::Float4x4 inertiaTensor; + ICustomBody::EventAction_Collision subscription; + bool ignoreGravity; + + SphericalBodyDescription() + { + this->rotation = ::Oyster::Math::Float4x4::identity; + this->centerPosition = ::Oyster::Math::Float3::null; + this->radius = 0.5f; + this->mass = 10.0f; + this->inertiaTensor = ::Oyster::Math::Float4x4::identity; + this->subscription = NULL; + this->ignoreGravity = false; + } + }; } } #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index 24648999..182a5a17 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -9,9 +9,14 @@ using namespace ::Oyster::Collision3D; using namespace ::Oyster::Physics3D; using namespace ::Oyster::Math3D; -RigidBody::RigidBody( const Box &b, Float m ) - : box(b), angularMomentum(0.0f), linearMomentum(0.0f), impulseTorqueSum(0.0f), impulseForceSum(0.0f) +RigidBody::RigidBody( const Box &b, Float m, const Float4x4 &inertiaTensor ) { // by Dan Andersson + this->box = b; + this->angularMomentum = Float3::null; + this->linearMomentum = Float3::null; + this->impulseTorqueSum = Float3::null; + this->impulseForceSum = Float3::null; + if( m != 0.0f ) { this->mass = m; @@ -21,7 +26,14 @@ RigidBody::RigidBody( const Box &b, Float m ) this->mass = ::Utility::Value::numeric_limits::epsilon(); } - this->momentOfInertiaTensor = Float4x4::identity; + if( inertiaTensor.GetDeterminant() != 0.0f ) + { + this->momentOfInertiaTensor = inertiaTensor; + } + else + { + this->momentOfInertiaTensor = Float4x4::identity; + } } RigidBody & RigidBody::operator = ( const RigidBody &body ) diff --git a/Code/OysterPhysics3D/RigidBody.h b/Code/OysterPhysics3D/RigidBody.h index bff6acde..81c92ae0 100644 --- a/Code/OysterPhysics3D/RigidBody.h +++ b/Code/OysterPhysics3D/RigidBody.h @@ -20,7 +20,9 @@ namespace Oyster { namespace Physics3D impulseTorqueSum, /** The impulse torque T (Nm) that will be consumed each update. (worldValue) */ impulseForceSum; /** The impulse force F (N) that will be consumed each update. (worldValue) */ - RigidBody( const ::Oyster::Collision3D::Box &box = ::Oyster::Collision3D::Box(), ::Oyster::Math::Float mass = 1.0f ); + RigidBody( const ::Oyster::Collision3D::Box &box = ::Oyster::Collision3D::Box(), + ::Oyster::Math::Float mass = 12.0f, + const ::Oyster::Math::Float4x4 &inertiaTensor = ::Oyster::Math::Float4x4::identity ); RigidBody & operator = ( const RigidBody &body );