diff --git a/Code/GameLogic/Camera.cpp b/Code/GameLogic/Camera.cpp new file mode 100644 index 00000000..bad0bdf9 --- /dev/null +++ b/Code/GameLogic/Camera.cpp @@ -0,0 +1,182 @@ +#include "Camera.h" + +Camera::Camera() +{ + this->m_position = Oyster::Math::Float3(0, 50, 0); + this->mRight = Oyster::Math::Float3(1, 0, 0); + this->mUp = Oyster::Math::Float3(0, 1, 0); + this->mLook = Oyster::Math::Float3(0, 0, 1); +} + +Camera::~Camera() +{ +} + +void Camera::SetPosition(const Oyster::Math::Float3& v) +{ + this->m_position = v; +} + +Oyster::Math::Float3 Camera::GetPosition()const +{ + return this->m_position; +} + +Oyster::Math::Float3 Camera::GetRight()const +{ + return this->mRight; +} + +Oyster::Math::Float3 Camera::GetUp()const +{ + return this->mUp; +} + +Oyster::Math::Float3 Camera::GetLook()const +{ + return this->mLook; +} + +float Camera::GetNearZ()const +{ + return this->mNearZ; +} + +float Camera::GetFarZ()const +{ + return this->mFarZ; +} + +float Camera::GetAspect()const +{ + return this->mAspect; +} + +Oyster::Math::Float3 Camera::CrossMatrix(const Oyster::Math::Float3& vector, const Oyster::Math::Float4x4& matrix) +{ + Oyster::Math::Float3 vec; + vec.x = matrix.m11*vector.x + matrix.m12*vector.y + matrix.m13*vector.z; + vec.y = matrix.m21*vector.x + matrix.m22*vector.y + matrix.m23*vector.z; + vec.z = matrix.m31*vector.x + matrix.m32*vector.y + matrix.m33*vector.z; + return vec; +} + +void Camera::SetLens(float fovY, float aspect, float zn, float zf) +{ + this->mFovY = fovY; + this->mAspect = aspect; + this->mNearZ = zn; + this->mFarZ = zf; + + float yScale = tan((Oyster::Math::pi*0.5f) - (mFovY*0.5f)); + float xScale = yScale/this->mAspect; + + mProj = Oyster::Math::Float4x4(xScale, 0, 0, 0, + 0, yScale, 0, 0, + 0, 0, zf/(zf-zn), 1, + 0, 0, -zn*zf/(zf-zn), 0); +} + +void Camera::LookAt(Oyster::Math::Float3 pos, Oyster::Math::Float3 target, Oyster::Math::Float3 worldUp) +{ + Oyster::Math::Float3 L; + + D3DXVec3Subtract(&L, &target, &pos); + L = target - pos; + D3DXVec3Normalize(&L, &L); + Oyster::Math::Float3 R; + D3DXVec3Cross(&R, &worldUp, &L); + D3DXVec3Normalize(&R, &R); + Oyster::Math::Float3 U; + D3DXVec3Cross(&U, &L, &R); + + this->m_position = pos; + this->mLook = L; + this->mRight = R; + this->mUp = U; +} + +Oyster::Math::Float4x4 Camera::View()const +{ + return this->mView; +} + +Oyster::Math::Float4x4 Camera::Proj()const +{ + return this->mProj; +} + +Oyster::Math::Float4x4 Camera::ViewsProj()const +{ + Oyster::Math::Float4x4 M; + D3DXMatrixMultiply(&M, &this->mView, &this->mProj); + return M; +} + +void Camera::Walk(float dist) +{ + this->m_position += dist*Oyster::Math::Float3(1,0,0); +} + +void Camera::Strafe(float dist) +{ + this->m_position += dist*this->mRight; +} + +void Camera::Pitch(float angle) +{ + float radians = angle * 0.0174532925f; + + Oyster::Math::Float4x4 R; + + D3DXMatrixRotationAxis(&R, &-mRight, radians); + this->mUp = CrossMatrix(this->mUp, R); + this->mLook = CrossMatrix(this->mLook, R); +} + +void Camera::Yaw(float angle) +{ + float radians = angle * 0.0174532925f; + + Oyster::Math::Float4x4 R; + + Oyster::Math::Float3 up(0,1,0); + D3DXMatrixRotationAxis(&R, &-up, radians); + + this->mRight = CrossMatrix(this->mRight, R); + this->mUp = CrossMatrix(mUp, R); + this->mLook = CrossMatrix(this->mLook, R); +} + +void Camera::UpdateViewMatrix() +{ + D3DXVec3Normalize(&this->mLook, &this->mLook); + D3DXVec3Cross(&this->mUp, &this->mLook, &this->mRight); + D3DXVec3Normalize(&this->mUp, &this->mUp); + D3DXVec3Cross(&this->mRight, &this->mUp, &this->mLook); + + + float x = -D3DXVec3Dot(&this->m_position, &mRight); + float y = -D3DXVec3Dot(&this->m_position, &mUp); + float z = -D3DXVec3Dot(&this->m_position, &mLook); + + this->mView(0, 0) = this->mRight.x; + this->mView(1, 0) = this->mRight.y; + this->mView(2, 0) = this->mRight.z; + this->mView(3, 0) = x; + + this->mView(0, 1) = this->mUp.x; + this->mView(1, 1) = this->mUp.y; + this->mView(2, 1) = this->mUp.z; + this->mView(3, 1) = y; + + this->mView(0, 2) = this->mLook.x; + this->mView(1, 2) = this->mLook.y; + this->mView(2, 2) = this->mLook.z; + this->mView(3, 2) = z; + + this->mView(0, 3) = 0.0f; + this->mView(1, 3) = 0.0f; + this->mView(2, 3) = 0.0f; + this->mView(3, 3) = 1.0f; +} \ No newline at end of file diff --git a/Code/GameLogic/Camera.h b/Code/GameLogic/Camera.h new file mode 100644 index 00000000..deb9df62 --- /dev/null +++ b/Code/GameLogic/Camera.h @@ -0,0 +1,63 @@ +#ifndef CAMERA__H +#define CAMERA__H + +#include "OysterMath.h" + +class Camera +{ +private: + + Oyster::Math::Float3 m_position; + Oyster::Math::Float3 mRight; + Oyster::Math::Float3 mUp; + Oyster::Math::Float3 mLook; + + + + float mNearZ; + float mFarZ; + float mAspect; + float mFovY; + + Oyster::Math::Float4x4 mView; + Oyster::Math::Float4x4 mProj; + +public: + Camera(); + virtual ~Camera(); + + void SetPosition(const Oyster::Math::Float3& v); + + Oyster::Math::Float3 GetPosition()const; + + Oyster::Math::Float3 GetRight()const; + Oyster::Math::Float3 GetUp()const; + Oyster::Math::Float3 GetLook()const; + + float GetNearZ()const; + float GetFarZ()const; + float GetAspect()const; + + Oyster::Math::Float3 CrossMatrix(const Oyster::Math::Float3& v, const Oyster::Math::Float4x4& m); + + void SetLens(float fovY, float aspect, float zn, float zf); + + void LookAt(Oyster::Math::Float3 pos, Oyster::Math::Float3 target, Oyster::Math::Float3 worldUp); + + void setLook(Oyster::Math::Float3 look) { mLook = look; } + void setUp(Oyster::Math::Float3 up) { mUp = up; } + void setRight(Oyster::Math::Float3 right) { mRight = right; } + + Oyster::Math::Float4x4 View()const; + Oyster::Math::Float4x4 Proj()const; + Oyster::Math::Float4x4 ViewsProj()const; + + void Walk(float dist); + void Strafe(float dist); + + void Pitch(float angle); + void Yaw(float angle); + + void UpdateViewMatrix(); +}; +#endif \ No newline at end of file diff --git a/Code/GameLogic/Object.cpp b/Code/GameLogic/Object.cpp index d93dba63..4d01332b 100644 --- a/Code/GameLogic/Object.cpp +++ b/Code/GameLogic/Object.cpp @@ -18,14 +18,7 @@ Object::Object(void) model = new Model(); model = Oyster::Graphics::API::CreateModel(L"bth.obj"); - ICustomBody* temp = rigidBody = API::Instance().CreateSimpleRigidBody().Release(); - - rigidBody->SetCenter(Float3(50,0,0)); - rigidBody->SetMass_KeepMomentum(30); - rigidBody->SetSize(Float3(2,2,2)); - rigidBody->SetSubscription(true); - rigidBody->SetMomentOfInertiaTensor_KeepMomentum(Float4x4(MomentOfInertia::CreateCuboidMatrix(30, 2, 2, 2))); - + ICustomBody* temp = rigidBody = API::Instance().CreateRigidBody().Release(); GameLogic::RefManager::getInstance()->AddMapping(*rigidBody, *this); diff --git a/Code/GamePhysics/GamePhysics.vcxproj.filters b/Code/GamePhysics/GamePhysics.vcxproj.filters index 4c0fd5f3..cc9a84c8 100644 --- a/Code/GamePhysics/GamePhysics.vcxproj.filters +++ b/Code/GamePhysics/GamePhysics.vcxproj.filters @@ -33,6 +33,9 @@ Header Files\Implementation + + Header Files\Implementation + diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 6c3e4a27..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; @@ -10,14 +11,6 @@ using namespace ::Utility::DynamicMemory; API_Impl API_instance; -// default API::EventAction_Collision -void defaultCollisionAction( const ICustomBody *proto, const ICustomBody *deuter ) -{ /* do nothing */ } - -// default API::EventAction_Destruction -void defaultDestructionAction( UniquePointer proto ) -{ /* do nothing besides proto auto deleting itself. */ } - Float4x4 & MomentOfInertia::CreateSphereMatrix( const Float mass, const Float radius) { return Formula::MomentOfInertia::Sphere(mass, radius); @@ -51,8 +44,7 @@ API & API::Instance() API_Impl::API_Impl() : gravityConstant( Constant::gravity_constant ), updateFrameLength( 1.0f / 120.0f ), - collisionAction( defaultCollisionAction ), - destructionAction( defaultDestructionAction ) + destructionAction( Default::EventAction_Destruction ) {} API_Impl::~API_Impl() {} @@ -66,17 +58,22 @@ void API_Impl::SetDeltaTime( float deltaTime ) { updateFrameLength = deltaTime; } + void API_Impl::SetGravityConstant( float g ) { this->gravityConstant = g; } -void API_Impl::SetAction( API::EventAction_Collision functionPointer ) + +void API_Impl::SetSubscription( API::EventAction_Destruction functionPointer ) { - this->collisionAction = functionPointer; -} -void API_Impl::SetAction( API::EventAction_Destruction functionPointer ) -{ - this->destructionAction = functionPointer; + if( functionPointer ) + { + this->destructionAction = functionPointer; + } + else + { + this->destructionAction = Default::EventAction_Destruction; + } } void API_Impl::Update() @@ -165,7 +162,25 @@ 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(); -} \ No newline at end of file + return new SimpleRigidBody( desc ); +} + +UniquePointer API_Impl::CreateRigidBody( const API::SphericalBodyDescription &desc ) const +{ + return new SphericalRigidBody(); +} + +namespace Oyster { namespace Physics { namespace Default +{ + + void EventAction_Destruction( ::Utility::DynamicMemory::UniquePointer<::Oyster::Physics::ICustomBody> proto ) + { /* Do nothing except allowing the proto uniquePointer destroy itself. */ } + + ::Oyster::Physics::ICustomBody::SubscriptMessage EventAction_Collision( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter ) + { /* Do nothing except returning business as usual. */ + return ::Oyster::Physics::ICustomBody::SubscriptMessage_none; + } + +} } } \ No newline at end of file diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 5a2e3ef6..7d6858f0 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -17,8 +17,7 @@ namespace Oyster void SetDeltaTime( float deltaTime ); void SetGravityConstant( float g ); - void SetAction( EventAction_Collision functionPointer ); - void SetAction( EventAction_Destruction functionPointer ); + void SetSubscription( EventAction_Destruction functionPointer ); void Update(); @@ -42,14 +41,20 @@ 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_Collision collisionAction; EventAction_Destruction destructionAction; }; - } + namespace Default + { + 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 ); + } + } } #endif \ No newline at end of file diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index cc1f847b..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), - subscribeCollision(true), - 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() {} @@ -20,11 +42,6 @@ UniquePointer SimpleRigidBody::Clone() const return new SimpleRigidBody( *this ); } -bool SimpleRigidBody::IsSubscribingCollisions() const -{ // Assumption - return this->subscribeCollision; -} - bool SimpleRigidBody::IsAffectedByGravity() const { return !this->ignoreGravity; @@ -32,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 @@ -46,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 @@ -67,32 +84,43 @@ 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 ? resting : altered; + //return this->current == this->previous ? UpdateState_resting : UpdateState_altered; + return UpdateState_altered; +} + +void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_Collision functionPointer ) +{ + if( functionPointer ) + { + this->collisionAction = functionPointer; + } + else + { + this->collisionAction = Default::EventAction_Collision; + } } void SimpleRigidBody::SetGravity( bool ignore) @@ -106,47 +134,42 @@ void SimpleRigidBody::SetGravityNormal( const Float3 &normalizedVector ) this->gravityNormal = normalizedVector; } -void SimpleRigidBody::SetSubscription( bool subscribeCollision ) -{ - this->subscribeCollision = subscribeCollision; -} - 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 41be919b..c76f6a51 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -10,11 +10,11 @@ namespace Oyster { namespace Physics { public: SimpleRigidBody(); + SimpleRigidBody( const API::SimpleBodyDescription &desc ); virtual ~SimpleRigidBody(); ::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; @@ -29,9 +29,9 @@ namespace Oyster { namespace Physics UpdateState Update( ::Oyster::Math::Float timeStepLength ); + void SetSubscription( EventAction_Collision functionPointer ); 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 ); @@ -42,9 +42,10 @@ 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; - bool subscribeCollision, ignoreGravity; + EventAction_Collision collisionAction; + bool ignoreGravity; }; } } diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index 20d806c9..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; @@ -10,7 +11,7 @@ using namespace ::Utility::Value; SphericalRigidBody::SphericalRigidBody() : previous(), current( Box(Float4x4::identity, Float3::null, Float3(1.0f)) ), gravityNormal( 0.0f ), - subscribeCollision( true ), + collisionAction(Default::EventAction_Collision), ignoreGravity( false ), body( Float3::null, 0.5f ) {} @@ -21,11 +22,6 @@ UniquePointer SphericalRigidBody::Clone() const return new SphericalRigidBody( *this ); } -bool SphericalRigidBody::IsSubscribingCollisions() const -{ // Assumption - return this->subscribeCollision; -} - bool SphericalRigidBody::IsAffectedByGravity() const { return !this->ignoreGravity; @@ -94,7 +90,19 @@ UpdateState SphericalRigidBody::Update( Float timeStepLength ) this->body.center = this->current.GetCenter(); // compare previous and new state and return result - return this->current == this->previous ? resting : altered; + return this->current == this->previous ? UpdateState_resting : UpdateState_altered; +} + +void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_Collision functionPointer ) +{ + if( functionPointer ) + { + this->collisionAction = functionPointer; + } + else + { + this->collisionAction = Default::EventAction_Collision; + } } void SphericalRigidBody::SetGravity( bool ignore) @@ -108,11 +116,6 @@ 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 ); diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.h b/Code/GamePhysics/Implementation/SphericalRigidBody.h index 7a727ee8..1540f7a1 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.h +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.h @@ -30,9 +30,9 @@ namespace Oyster { namespace Physics UpdateState Update( ::Oyster::Math::Float timeStepLength ); + void SetSubscription( EventAction_Collision functionPointer ); 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 ); @@ -45,7 +45,8 @@ namespace Oyster { namespace Physics private: ::Oyster::Physics3D::RigidBody previous, current; ::Oyster::Math::Float3 gravityNormal; - bool subscribeCollision, ignoreGravity; + EventAction_Collision collisionAction; + bool ignoreGravity; ::Oyster::Collision3D::Sphere body; }; } } diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index bf80e6fa..dd36a9ee 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -19,8 +19,8 @@ namespace Oyster enum UpdateState { - resting, - altered + UpdateState_resting, + UpdateState_altered }; namespace Constant @@ -45,7 +45,9 @@ namespace Oyster class PHYSICS_DLL_USAGE API { public: - typedef void (*EventAction_Collision)( const ICustomBody *proto, const ICustomBody *deuter ); + struct SimpleBodyDescription; + struct SphericalBodyDescription; + typedef void (*EventAction_Destruction)( ::Utility::DynamicMemory::UniquePointer proto ); /** Gets the Physics instance. */ @@ -70,20 +72,15 @@ namespace Oyster * @param g: Default is the real world Constant::gravity_constant [N(m/kg)^2] ********************************************************/ virtual void SetGravityConstant( float g ) = 0; - - /******************************************************** - * Sets the function that will be called by the engine - * whenever a subscribed collision occurs. - ********************************************************/ - virtual void SetAction( EventAction_Collision functionPointer ) = 0; /******************************************************** * Sets the function that will be called by the engine * whenever an object is being destroyed for some reason. * - Because DestroyObject(...) were called. * - Out of memory forced engine to destroy an object. + * @param functionPointer: If NULL, an empty default function will be set. ********************************************************/ - virtual void SetAction( EventAction_Destruction functionPointer ) = 0; + virtual void SetSubscription( EventAction_Destruction functionPointer ) = 0; /******************************************************** * Triggers the engine to run next update frame. @@ -213,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() {} }; @@ -225,6 +230,14 @@ namespace Oyster class PHYSICS_DLL_USAGE ICustomBody { public: + enum SubscriptMessage + { + SubscriptMessage_none, + SubscriptMessage_ignore_collision_response + }; + + typedef SubscriptMessage (*EventAction_Collision)( const ICustomBody *proto, const ICustomBody *deuter ); + virtual ~ICustomBody() {}; /******************************************************** @@ -232,11 +245,6 @@ namespace Oyster * @return An ICustomBody pointer along with the responsibility to delete. ********************************************************/ virtual ::Utility::DynamicMemory::UniquePointer Clone() const = 0; - - /******************************************************** - * @return true if Engine should call the EventAction_Collision function. - ********************************************************/ - virtual bool IsSubscribingCollisions() const = 0; /******************************************************** * @return true if Engine should apply gravity on this object. @@ -312,6 +320,13 @@ namespace Oyster ********************************************************/ virtual UpdateState Update( ::Oyster::Math::Float timeStepLength ) = 0; + /******************************************************** + * Sets the function that will be called by the engine + * whenever a collision occurs. + * @param functionPointer: If NULL, an empty default function will be set. + ********************************************************/ + virtual void SetSubscription( EventAction_Collision functionPointer ) = 0; + /******************************************************** * @param ignore: True if Engine should not apply Gravity. ********************************************************/ @@ -323,11 +338,6 @@ namespace Oyster ********************************************************/ virtual void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ) = 0; - /******************************************************** - * @param subscribeCollision: If is true, engine will call EventAction_Collision when this collides. - ********************************************************/ - virtual void SetSubscription( bool subscribeCollision ) = 0; - /******************************************************** * To not be called if is in Engine * Use API::SetMomentOfInertiaTensor_KeepVelocity(...) instead @@ -376,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/Misc/Utilities-InlineImpl.h b/Code/Misc/Utilities-InlineImpl.h index c2bbd2a9..6cc99aab 100644 --- a/Code/Misc/Utilities-InlineImpl.h +++ b/Code/Misc/Utilities-InlineImpl.h @@ -98,6 +98,18 @@ namespace Utility return this->ownedInstance != NULL; } + template + bool UniquePointer::operator == ( Type *stray ) const + { + return this->ownedInstance == stray; + } + + template + bool UniquePointer::operator != ( Type *stray ) const + { + return this->ownedInstance != stray; + } + template Type* UniquePointer::Release() { @@ -165,6 +177,18 @@ namespace Utility return this->ownedArray != NULL; } + template + bool UniqueArray::operator == ( Type *stray ) const + { + return this->ownedArray == stray; + } + + template + bool UniqueArray::operator != ( Type *stray ) const + { + return this->ownedArray != stray; + } + template Type* UniqueArray::Release() { diff --git a/Code/Misc/Utilities.h b/Code/Misc/Utilities.h index 66164e19..59d5042d 100644 --- a/Code/Misc/Utilities.h +++ b/Code/Misc/Utilities.h @@ -60,6 +60,12 @@ namespace Utility //! If true, this UniquePointer have a current ownership/responsibility of a dynamic instance. operator bool () const; + //! @return true if this ownedInstance matches with stray + bool operator == ( Type *stray ) const; + + //! @return false if this ownedInstance matches with stray + bool operator != ( Type *stray ) const; + //! This UniquePointer drops all claims of ownership/responsibility and returns the dynamic instance. Now it is your responsibility to delete. Type* Release(); @@ -104,6 +110,12 @@ namespace Utility //! If true, this UniqueArray have a current ownership/responsibility of a dynamic instance. operator bool () const; + //! @return true if this ownedInstance matches with stray + bool operator == ( Type *stray ) const; + + //! @return false if this ownedInstance matches with stray + bool operator != ( Type *stray ) const; + //! This UniqueArray drops all claims of ownership/responsibility and returns the dynamic array. Now it is your responsibility to delete. Type* Release(); 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 );