From a869771ffa51a95c05b2b42c6c89516f5c187c7b Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Mon, 25 Nov 2013 16:35:56 +0100 Subject: [PATCH] Simple Rigid Body implementation Second Iteration [iteration 1]: stubs [iteration 2]: implementations with shortcuts [iteration final]: implementations with real solutions --- .../Implementation/PhysicsAPI_Impl.cpp | 7 +- .../Implementation/PhysicsAPI_Impl.h | 1 - .../Implementation/SimpleRigidBody.cpp | 77 ++++++++++--------- .../Implementation/SimpleRigidBody.h | 4 +- Code/GamePhysics/PhysicsAPI.h | 5 +- Code/OysterPhysics3D/RigidBody.cpp | 50 ++++++++++++ Code/OysterPhysics3D/RigidBody.h | 4 + 7 files changed, 103 insertions(+), 45 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 52339f37..53c06dfb 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -7,7 +7,8 @@ using namespace ::Oyster::Math; using namespace ::Oyster::Collision3D; using namespace ::Utility::DynamicMemory; -API_Impl instance; +API_Impl API_instance; +Float updateFrameLength = 1.0f / 120.0f; ::Oyster::Math::Float4x4 & MomentOfInertia::CreateSphereMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float radius) { @@ -36,7 +37,7 @@ API_Impl instance; API & API::Instance() { - return instance; + return API_instance; } API_Impl::API_Impl() @@ -51,7 +52,7 @@ API_Impl::~API_Impl() void API_Impl::SetDeltaTime( float deltaTime ) { - /** @todo TODO: Fix this function.*/ + updateFrameLength = deltaTime; } void API_Impl::SetGravityConstant( float g ) { diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 2cec91a9..ac78c2dc 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -41,7 +41,6 @@ namespace Oyster ::Utility::DynamicMemory::UniquePointer CreateSimpleRigidBody() const; }; - } } diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index 00f456aa..7fd15e40 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -1,19 +1,15 @@ #include "SimpleRigidBody.h" +#include "PhysicsAPI_Impl.h" using namespace ::Oyster::Physics; -using namespace ::Oyster::Math; +using namespace ::Oyster::Math3D; using namespace ::Oyster::Collision3D; using namespace ::Utility::DynamicMemory; +using namespace ::Utility::Value; -SimpleRigidBody::SimpleRigidBody() -{ - //! @todo TODO: implement stub -} +SimpleRigidBody::SimpleRigidBody() : previous(), current() {} -SimpleRigidBody::~SimpleRigidBody() -{ - //! @todo TODO: implement stub -} +SimpleRigidBody::~SimpleRigidBody() {} UniquePointer SimpleRigidBody::Clone() const { @@ -21,96 +17,101 @@ UniquePointer SimpleRigidBody::Clone() const } bool SimpleRigidBody::IsSubscribingCollisions() const -{ - //! @todo TODO: implement stub - return false; +{ // Assumption + return true; } -bool SimpleRigidBody::Intersects( const ICustomBody &object, Float &deltaWhen, Float3 &worldPointOfContact ) const +bool SimpleRigidBody::Intersects( const ICustomBody &object, Float timeStepLength, Float &deltaWhen, Float3 &worldPointOfContact ) const { - //! @todo TODO: implement stub - return false; + if( object.Intersects(this->current.box) ) + { //! @todo TODO: better implementation needed + deltaWhen = timeStepLength; + worldPointOfContact = Average( this->current.box.center, object.GetCenter() ); + return true; + } + else + { + return false; + } } bool SimpleRigidBody::Intersects( const ICollideable &shape ) const { - //! @todo TODO: implement stub - return false; + return this->current.box.Intersects( shape ); } Sphere & SimpleRigidBody::GetBoundingSphere( Sphere &targetMem ) const { - //! @todo TODO: implement stub - return targetMem = Sphere( Float3::null, 0.0f ); + return targetMem = Sphere( this->current.box.center, this->current.box.boundingOffset.GetMagnitude() ); } Float3 & SimpleRigidBody::GetNormalAt( const Float3 &worldPos, Float3 &targetMem ) const { - //! @todo TODO: implement stub - return targetMem = Float3::standard_unit_z; + //! @todo TODO: better implementation needed + return targetMem = (worldPos - this->current.box.center).GetNormalized(); } Float3 & SimpleRigidBody::GetCenter( Float3 &targetMem ) const { - //! @todo TODO: implement stub - return targetMem = Float3::null; + return targetMem = this->current.box.center; } Float4x4 & SimpleRigidBody::GetRotation( Float4x4 &targetMem ) const { - //! @todo TODO: implement stub - return targetMem = Float4x4::identity; + return targetMem = this->current.box.rotation; } Float4x4 & SimpleRigidBody::GetOrientation( Float4x4 &targetMem ) const { - //! @todo TODO: implement stub - return targetMem = Float4x4::identity; + return targetMem = this->current.GetOrientation(); } Float4x4 & SimpleRigidBody::GetView( Float4x4 &targetMem ) const { - //! @todo TODO: implement stub - return targetMem = Float4x4::identity; + return targetMem = this->current.GetView(); } UpdateState SimpleRigidBody::Update( Float timeStepLength ) { - //! @todo TODO: implement stub - return resting; + this->previous = this->current; // memorizing the old state + + this->current.Update_LeapFrog( timeStepLength ); + + // compare previous and new state and return result + return this->current == this->previous ? resting : altered; } void SimpleRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI ) { - //! @todo TODO: implement stub + this->current.SetMomentOfInertia_KeepVelocity( localI ); } void SimpleRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI ) { - //! @todo TODO: implement stub + this->current.SetMomentOfInertia_KeepMomentum( localI ); } void SimpleRigidBody::SetMass_KeepVelocity( Float m ) { - //! @todo TODO: implement stub + this->current.SetMass_KeepVelocity( m ); } void SimpleRigidBody::SetMass_KeepMomentum( Float m ) { - //! @todo TODO: implement stub + this->current.SetMass_KeepMomentum( m ); } void SimpleRigidBody::SetCenter( const Float3 &worldPos ) { - //! @todo TODO: implement stub + this->current.SetCenter( worldPos ); } void SimpleRigidBody::SetRotation( const Float4x4 &rotation ) { - //! @todo TODO: implement stub + this->current.SetRotation( rotation ); } void SimpleRigidBody::SetOrientation( const Float4x4 &orientation ) { - //! @todo TODO: implement stub + this->current.SetOrientation( orientation ); } \ No newline at end of file diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index ebedcb6a..99295e44 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -2,6 +2,7 @@ #define OYSTER_PHYSICS_SIMPLE_RIGIDBODY_H #include "..\PhysicsAPI.h" +#include "RigidBody.h" namespace Oyster { namespace Physics { @@ -14,7 +15,7 @@ namespace Oyster { namespace Physics ::Utility::DynamicMemory::UniquePointer Clone() const; bool IsSubscribingCollisions() const; - bool Intersects( const ICustomBody &object, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact ) const; + bool Intersects( const ICustomBody &object, ::Oyster::Math::Float timeStepLength, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact ) const; bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const; ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const; @@ -35,6 +36,7 @@ namespace Oyster { namespace Physics void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ); private: + ::Oyster::Physics3D::RigidBody previous, current; }; } } diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index a59a5e16..091f1edc 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -226,11 +226,12 @@ namespace Oyster /******************************************************** * Performs a detailed Intersect test and returns if, when and where. * @param object: What this is intersect testing against. - * @param deltaWhen: Time in seconds since last update frame til timeOfContact. 0.0f <= deltaWhen <= deltaTime + * @param timeStepLength: The value set by API::SetDeltaTime(...) + * @param deltaWhen: Time in seconds since last update frame til timeOfContact. 0.0f <= deltaWhen <= timeStepLength * @param worldPointOfContact: Where at timeOfContact, this and object touches eachother. * @return true if this truly intersects with object. ********************************************************/ - virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact ) const = 0; + virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float timeStepLength, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact ) const = 0; /******************************************************** * param shape: Any defined sample shape. diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index 748d2272..24648999 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -36,6 +36,51 @@ RigidBody & RigidBody::operator = ( const RigidBody &body ) return *this; } +bool RigidBody::operator == ( const RigidBody &body ) +{ + if( this->box.center != body.box.center ) + { + return false; + } + + if( this->box.rotation != body.box.rotation ) + { + return false; + } + + if( this->box.boundingOffset != body.box.boundingOffset ) + { + return false; + } + + if( this->angularMomentum != body.angularMomentum ) + { + return false; + } + + if( this->linearMomentum != body.linearMomentum ) + { + return false; + } + + if( this->impulseTorqueSum != body.impulseTorqueSum ) + { + return false; + } + + if( this->impulseForceSum != body.impulseForceSum ) + { + return false; + } + + return true; +} + +bool RigidBody::operator != ( const RigidBody &body ) +{ + return !this->operator==( body ); +} + void RigidBody::Update_LeapFrog( Float deltaTime ) { // by Dan Andersson: Euler leap frog update when Runga Kutta is not needed @@ -287,6 +332,11 @@ void RigidBody::SetCenter( const Float3 &worldPos ) this->box.center = worldPos; } +void RigidBody::SetRotation( const Float4x4 &r ) +{ // by Dan Andersson + this->box.rotation = r; +} + void RigidBody::SetImpulseTorque( const Float3 &worldT ) { // by Dan Andersson this->impulseTorqueSum = worldT; diff --git a/Code/OysterPhysics3D/RigidBody.h b/Code/OysterPhysics3D/RigidBody.h index b343ff07..bff6acde 100644 --- a/Code/OysterPhysics3D/RigidBody.h +++ b/Code/OysterPhysics3D/RigidBody.h @@ -24,6 +24,9 @@ namespace Oyster { namespace Physics3D RigidBody & operator = ( const RigidBody &body ); + bool operator == ( const RigidBody &body ); + bool operator != ( const RigidBody &body ); + void Update_LeapFrog( ::Oyster::Math::Float deltaTime ); void ApplyImpulseForce( const ::Oyster::Math::Float3 &worldF ); void ApplyImpulseForceAt( const ::Oyster::Math::Float3 &worldF, const ::Oyster::Math::Float3 &worldPos ); @@ -76,6 +79,7 @@ namespace Oyster { namespace Physics3D void SetOrientation( const ::Oyster::Math::Float4x4 &o ); void SetSize( const ::Oyster::Math::Float3 &widthHeight ); void SetCenter( const ::Oyster::Math::Float3 &worldPos ); + void SetRotation( const ::Oyster::Math::Float4x4 &r ); void SetImpulseTorque( const ::Oyster::Math::Float3 &worldT ); void SetAngularMomentum( const ::Oyster::Math::Float3 &worldH );