diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp new file mode 100644 index 00000000..20d806c9 --- /dev/null +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -0,0 +1,157 @@ +#include "SphericalRigidBody.h" +#include "PhysicsAPI_Impl.h" + +using namespace ::Oyster::Physics; +using namespace ::Oyster::Math3D; +using namespace ::Oyster::Collision3D; +using namespace ::Utility::DynamicMemory; +using namespace ::Utility::Value; + +SphericalRigidBody::SphericalRigidBody() + : previous(), current( Box(Float4x4::identity, Float3::null, Float3(1.0f)) ), + gravityNormal( 0.0f ), + subscribeCollision( true ), + ignoreGravity( false ), + body( Float3::null, 0.5f ) {} + +SphericalRigidBody::~SphericalRigidBody() {} + +UniquePointer SphericalRigidBody::Clone() const +{ + return new SphericalRigidBody( *this ); +} + +bool SphericalRigidBody::IsSubscribingCollisions() const +{ // Assumption + return this->subscribeCollision; +} + +bool SphericalRigidBody::IsAffectedByGravity() const +{ + return !this->ignoreGravity; +} + +bool SphericalRigidBody::Intersects( const ICustomBody &object, Float timeStepLength, Float &deltaWhen, Float3 &worldPointOfContact ) const +{ + if( object.Intersects(this->body) ) + { //! @todo TODO: better implementation needed + deltaWhen = timeStepLength; + worldPointOfContact = Average( this->body.center, object.GetCenter() ); + return true; + } + else + { + return false; + } +} + +bool SphericalRigidBody::Intersects( const ICollideable &shape ) const +{ + return this->current.box.Intersects( shape ); +} + +Sphere & SphericalRigidBody::GetBoundingSphere( Sphere &targetMem ) const +{ + return targetMem = this->body; +} + +Float3 & SphericalRigidBody::GetNormalAt( const Float3 &worldPos, Float3 &targetMem ) const +{ + //! @todo TODO: better implementation needed + return targetMem = (worldPos - this->current.box.center).GetNormalized(); +} + +Float3 & SphericalRigidBody::GetGravityNormal( Float3 &targetMem ) const +{ + return targetMem = this->gravityNormal; +} + +Float3 & SphericalRigidBody::GetCenter( Float3 &targetMem ) const +{ + return targetMem = this->current.box.center; +} + +Float4x4 & SphericalRigidBody::GetRotation( Float4x4 &targetMem ) const +{ + return targetMem = this->current.box.rotation; +} + +Float4x4 & SphericalRigidBody::GetOrientation( Float4x4 &targetMem ) const +{ + return targetMem = this->current.GetOrientation(); +} + +Float4x4 & SphericalRigidBody::GetView( Float4x4 &targetMem ) const +{ + return targetMem = this->current.GetView(); +} + +UpdateState SphericalRigidBody::Update( Float timeStepLength ) +{ + this->previous = this->current; // memorizing the old state + + this->current.Update_LeapFrog( timeStepLength ); + this->body.center = this->current.GetCenter(); + + // compare previous and new state and return result + return this->current == this->previous ? resting : altered; +} + +void SphericalRigidBody::SetGravity( bool ignore) +{ + this->ignoreGravity = ignore; + this->gravityNormal = Float3::null; +} + +void SphericalRigidBody::SetGravityNormal( const Float3 &normalizedVector ) +{ + this->gravityNormal = normalizedVector; +} + +void SphericalRigidBody::SetSubscription( bool subscribeCollision ) +{ + this->subscribeCollision = subscribeCollision; +} + +void SphericalRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI ) +{ + this->current.SetMomentOfInertia_KeepVelocity( localI ); +} + +void SphericalRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI ) +{ + this->current.SetMomentOfInertia_KeepMomentum( localI ); +} + +void SphericalRigidBody::SetMass_KeepVelocity( Float m ) +{ + this->current.SetMass_KeepVelocity( m ); +} + +void SphericalRigidBody::SetMass_KeepMomentum( Float m ) +{ + this->current.SetMass_KeepMomentum( m ); +} + +void SphericalRigidBody::SetCenter( const Float3 &worldPos ) +{ + this->current.SetCenter( worldPos ); + this->body.center = worldPos; +} + +void SphericalRigidBody::SetRotation( const Float4x4 &rotation ) +{ + this->current.SetRotation( rotation ); +} + +void SphericalRigidBody::SetOrientation( const Float4x4 &orientation ) +{ + this->current.SetOrientation( orientation ); + this->body.center = orientation.v[3].xyz; +} + +void SphericalRigidBody::SetSize( const Float3 &size ) +{ + this->current.SetSize( size ); + this->body.radius = 0.5f * Min( Min( size.x, size.y ), size.z ); // inline Min( FloatN )? +} \ No newline at end of file diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.h b/Code/GamePhysics/Implementation/SphericalRigidBody.h new file mode 100644 index 00000000..7a727ee8 --- /dev/null +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.h @@ -0,0 +1,53 @@ +#ifndef OYSTER_PHYSICS_SPHERICAL_RIGIDBODY_H +#define OYSTER_PHYSICS_SPHERICAL_RIGIDBODY_H + +#include "..\PhysicsAPI.h" +#include "RigidBody.h" +#include "Sphere.h" + +namespace Oyster { namespace Physics +{ + class SphericalRigidBody : public ICustomBody + { + public: + SphericalRigidBody(); + virtual ~SphericalRigidBody(); + + ::Utility::DynamicMemory::UniquePointer Clone() const; + + bool IsSubscribingCollisions() const; + bool IsAffectedByGravity() 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; + ::Oyster::Math::Float3 & GetNormalAt( const ::Oyster::Math::Float3 &worldPos, ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; + ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; + ::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; + ::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; + ::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; + ::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; + + UpdateState Update( ::Oyster::Math::Float timeStepLength ); + + void SetGravity( bool ignore); + void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ); + void SetSubscription( bool subscribeCollision ); + void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ); + void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI ); + void SetMass_KeepVelocity( ::Oyster::Math::Float m ); + void SetMass_KeepMomentum( ::Oyster::Math::Float m ); + void SetCenter( const ::Oyster::Math::Float3 &worldPos ); + void SetRotation( const ::Oyster::Math::Float4x4 &rotation ); + void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ); + void SetSize( const ::Oyster::Math::Float3 &size ); + + private: + ::Oyster::Physics3D::RigidBody previous, current; + ::Oyster::Math::Float3 gravityNormal; + bool subscribeCollision, ignoreGravity; + ::Oyster::Collision3D::Sphere body; + }; +} } + +#endif \ No newline at end of file