diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 9880526d..614014e2 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -60,6 +60,8 @@ namespace return; } + // calculate and store time interpolation value, for later rebound. + proto->SetTimeOfContact( worldPointOfContact ); // bounce Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(), diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index a2871229..d1be7d61 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -49,14 +49,21 @@ SimpleRigidBody::SimpleRigidBody() this->onCollision = Default::EventAction_BeforeCollisionResponse; this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; this->onMovement = Default::EventAction_Move; + + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + this->scene = nullptr; this->customTag = nullptr; this->ignoreGravity = this->isForwarded = false; } SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) -{ - //this->rigid.SetRotation( desc.rotation ); +{ + this->rigid = RigidBody(); + this->rigid.SetRotation( desc.rotation ); this->rigid.centerPos = desc.centerPosition; this->rigid.SetSize( desc.size ); this->rigid.SetMass_KeepMomentum( desc.mass ); @@ -66,6 +73,11 @@ SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) this->gravityNormal = Float3::null; + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + if( desc.subscription_onCollision ) { this->onCollision = desc.subscription_onCollision; @@ -198,6 +210,26 @@ bool SimpleRigidBody::Intersects( const ICustomBody &object, Float4 &worldPointO return object.Intersects( Box(this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize()), worldPointOfContact ); } +void SimpleRigidBody::SetTimeOfContact( Float4 &worldPointOfContact ) +{ + Point pointOfContact = Point( worldPointOfContact ); + Box start = Box(); + { + start.rotation = RotationMatrix( this->collisionRebound.previousSpatial.axis ); + start.center = this->collisionRebound.previousSpatial.center; + start.boundingOffset = this->collisionRebound.previousSpatial.reach; + } + Box end = Box(); + { + end.rotation = RotationMatrix( this->rigid.axis ); + end.center = this->rigid.centerPos; + end.boundingOffset = this->rigid.boundingReach; + } + Float timeOfContact = ::Oyster::Collision3D::Utility::TimeOfContact( start, end, pointOfContact ); + + this->collisionRebound.timeOfContact = Min( this->collisionRebound.timeOfContact, timeOfContact ); +} + Sphere & SimpleRigidBody::GetBoundingSphere( Sphere &targetMem ) const { return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.GetMagnitude() ); @@ -293,18 +325,52 @@ void * SimpleRigidBody::GetCustomTag() const UpdateState SimpleRigidBody::Update( Float timeStepLength ) { - if( this->isForwarded ) - { - this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz ); - this->deltaPos = Float4::null; - this->deltaAxis = Float4::null; - this->isForwarded = false; - } + //if( this->isForwarded ) + //{ + // this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz ); + // this->deltaPos = Float4::null; + // this->deltaAxis = Float4::null; + // this->isForwarded = false; + //} this->rigid.Update_LeapFrog( timeStepLength ); - //! @todo TODO: compare previous and new state and return result - //return this->current == this->previous ? UpdateState_resting : UpdateState_altered; + { // Rebound if needed + if( this->collisionRebound.timeOfContact < 1.0f ) + { + this->rigid.centerPos = Lerp( this->collisionRebound.previousSpatial.center, this->rigid.centerPos, this->collisionRebound.timeOfContact ); + this->rigid.SetRotation( Lerp(this->collisionRebound.previousSpatial.axis, this->rigid.axis, this->collisionRebound.timeOfContact) ); + this->rigid.boundingReach = Lerp( this->collisionRebound.previousSpatial.reach, this->rigid.boundingReach, this->collisionRebound.timeOfContact ); + } + + // Update rebound data + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + } + + { // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too) + Float3 n; + ::std::modf( this->rigid.axis * (0.5f / pi), n ); + this->rigid.axis -= (2.0f * pi) * n; + } + + { // Check if this is close enough to be set resting + unsigned char resting = 0; + if( this->rigid.momentum_Linear.Dot(this->rigid.momentum_Linear) <= (Constant::epsilon * Constant::epsilon) ) + { + this->rigid.momentum_Linear = Float3::null; + resting = 1; + } + if( this->rigid.momentum_Angular.Dot(this->rigid.momentum_Angular) <= (Constant::epsilon * Constant::epsilon) ) + { + this->rigid.momentum_Angular = Float3::null; + ++resting; + } + if( resting == 2 ) return UpdateState_resting; + } + return UpdateState_altered; } diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index 9e61cee3..1811c911 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -30,6 +30,8 @@ namespace Oyster { namespace Physics bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const; + void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ); + ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const; ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const; ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; @@ -65,9 +67,17 @@ namespace Oyster { namespace Physics ::Oyster::Physics3D::RigidBody rigid; ::Oyster::Math::Float4 deltaPos, deltaAxis; ::Oyster::Math::Float3 gravityNormal; + + struct + { + struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial; + ::Oyster::Math::Float timeOfContact; + } collisionRebound; + EventAction_BeforeCollisionResponse onCollision; EventAction_AfterCollisionResponse onCollisionResponse; EventAction_Move onMovement; + Octree *scene; void *customTag; bool ignoreGravity, isForwarded; diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index f6f89c64..49aed408 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -11,11 +11,17 @@ using namespace ::Utility::Value; SphericalRigidBody::SphericalRigidBody() { this->rigid = RigidBody(); - this->rigid.SetMass_KeepMomentum( 10.0f ); + this->rigid.SetMass_KeepMomentum( 16.0f ); this->gravityNormal = Float3::null; this->onCollision = Default::EventAction_BeforeCollisionResponse; this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; this->onMovement = Default::EventAction_Move; + + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + this->scene = nullptr; this->customTag = nullptr; this->ignoreGravity = this->isForwarded = false; @@ -24,7 +30,7 @@ SphericalRigidBody::SphericalRigidBody() SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &desc ) { this->rigid = RigidBody(); - //this->rigid.SetRotation( desc.rotation ); + this->rigid.SetRotation( desc.rotation ); this->rigid.centerPos = desc.centerPosition; this->rigid.boundingReach = Float4( desc.radius, desc.radius, desc.radius, 0.0f ); this->rigid.SetMass_KeepMomentum( desc.mass ); @@ -34,6 +40,11 @@ SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &des this->gravityNormal = Float3::null; + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + if( desc.subscription_onCollision ) { this->onCollision = desc.subscription_onCollision; @@ -64,6 +75,11 @@ SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &des this->scene = nullptr; this->customTag = nullptr; this->ignoreGravity = desc.ignoreGravity; + + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; } SphericalRigidBody::~SphericalRigidBody() {} @@ -165,6 +181,17 @@ bool SphericalRigidBody::Intersects( const ICustomBody &object, Float4 &worldPoi return object.Intersects( Sphere(this->rigid.centerPos, this->rigid.boundingReach.x), worldPointOfContact ); } +void SphericalRigidBody::SetTimeOfContact( Float4 &worldPointOfContact ) +{ + Point pointOfContact = Point( worldPointOfContact ); + Sphere start = Sphere( this->collisionRebound.previousSpatial.center, this->collisionRebound.previousSpatial.reach.x ); + Sphere end = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ); + + Float timeOfContact = ::Oyster::Collision3D::Utility::TimeOfContact( start, end, pointOfContact ); + + this->collisionRebound.timeOfContact = Min( this->collisionRebound.timeOfContact, timeOfContact ); +} + Sphere & SphericalRigidBody::GetBoundingSphere( Sphere &targetMem ) const { return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ); @@ -219,18 +246,52 @@ void * SphericalRigidBody::GetCustomTag() const UpdateState SphericalRigidBody::Update( Float timeStepLength ) { - if( this->isForwarded ) - { - this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz ); - this->deltaPos = Float4::null; - this->deltaAxis = Float4::null; - this->isForwarded = false; - } + //if( this->isForwarded ) + //{ + // this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz ); + // this->deltaPos = Float4::null; + // this->deltaAxis = Float4::null; + // this->isForwarded = false; + //} this->rigid.Update_LeapFrog( timeStepLength ); - // compare previous and new state and return result - //return this->current == this->previous ? UpdateState_resting : UpdateState_altered; + { // Rebound if needed + if( this->collisionRebound.timeOfContact < 1.0f ) + { + this->rigid.centerPos = Lerp( this->collisionRebound.previousSpatial.center, this->rigid.centerPos, this->collisionRebound.timeOfContact ); + this->rigid.SetRotation( Lerp(this->collisionRebound.previousSpatial.axis, this->rigid.axis, this->collisionRebound.timeOfContact) ); + this->rigid.boundingReach = Lerp( this->collisionRebound.previousSpatial.reach, this->rigid.boundingReach, this->collisionRebound.timeOfContact ); + } + + // Update rebound data + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + } + + { // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too) + Float3 n; + ::std::modf( this->rigid.axis * (0.5f / pi), n ); + this->rigid.axis -= (2.0f * pi) * n; + } + + { // Check if this is close enough to be set resting + unsigned char resting = 0; + if( this->rigid.momentum_Linear.Dot(this->rigid.momentum_Linear) <= (Constant::epsilon * Constant::epsilon) ) + { + this->rigid.momentum_Linear = Float3::null; + resting = 1; + } + if( this->rigid.momentum_Angular.Dot(this->rigid.momentum_Angular) <= (Constant::epsilon * Constant::epsilon) ) + { + this->rigid.momentum_Angular = Float3::null; + ++resting; + } + if( resting == 2 ) return UpdateState_resting; + } + return UpdateState_altered; } diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.h b/Code/GamePhysics/Implementation/SphericalRigidBody.h index 390b7171..c2dc8131 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.h +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.h @@ -31,6 +31,8 @@ namespace Oyster { namespace Physics bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const; + void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ); + ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const; ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const; ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; @@ -66,6 +68,13 @@ namespace Oyster { namespace Physics ::Oyster::Physics3D::RigidBody rigid; ::Oyster::Math::Float4 deltaPos, deltaAxis; ::Oyster::Math::Float3 gravityNormal; + + struct + { + struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial; + ::Oyster::Math::Float timeOfContact; + } collisionRebound; + EventAction_BeforeCollisionResponse onCollision; EventAction_AfterCollisionResponse onCollisionResponse; EventAction_Move onMovement; diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 080b8d30..f636bb73 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -322,6 +322,11 @@ namespace Oyster ********************************************************/ virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0; + /******************************************************** + * Sets how far back it needs to be interpolated to not be overlapping worldPointOfContact. + ********************************************************/ + virtual void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ) = 0; + /******************************************************** * Required by Engine's Collision Search. * @param targetMem: Provided memory that written into and then returned. diff --git a/Code/GamePhysics/PhysicsStructs-Impl.h b/Code/GamePhysics/PhysicsStructs-Impl.h index af2fb91c..311b81f8 100644 --- a/Code/GamePhysics/PhysicsStructs-Impl.h +++ b/Code/GamePhysics/PhysicsStructs-Impl.h @@ -12,7 +12,7 @@ namespace Oyster { inline SimpleBodyDescription::SimpleBodyDescription() { - this->rotation = ::Oyster::Math::Float4x4::identity; + this->rotation = ::Oyster::Math::Float3::null; this->centerPosition = ::Oyster::Math::Float3::null; this->size = ::Oyster::Math::Float3( 1.0f ); this->mass = 6.0f; @@ -28,7 +28,7 @@ namespace Oyster inline SphericalBodyDescription::SphericalBodyDescription() { - this->rotation = ::Oyster::Math::Float4x4::identity; + this->rotation = ::Oyster::Math::Float3::null; this->centerPosition = ::Oyster::Math::Float3::null; this->radius = 0.5f; this->mass = 10.0f; diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index aef157a8..61a0569f 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -11,7 +11,7 @@ namespace Oyster { namespace Physics { struct SimpleBodyDescription { - ::Oyster::Math::Float4x4 rotation; + ::Oyster::Math::Float3 rotation; ::Oyster::Math::Float3 centerPosition; ::Oyster::Math::Float3 size; ::Oyster::Math::Float mass; @@ -29,7 +29,7 @@ namespace Oyster { namespace Physics struct SphericalBodyDescription { - ::Oyster::Math::Float4x4 rotation; + ::Oyster::Math::Float3 rotation; ::Oyster::Math::Float3 centerPosition; ::Oyster::Math::Float radius; ::Oyster::Math::Float mass; diff --git a/Code/Misc/Utilities.h b/Code/Misc/Utilities.h index 9c71a515..9b3abac0 100644 --- a/Code/Misc/Utilities.h +++ b/Code/Misc/Utilities.h @@ -315,6 +315,14 @@ namespace Utility { using ::std::numeric_limits; + template + inline bool Within( const ValueType &value, const ValueType &lower, const ValueType &upper ) + { + if( value < lower ) return false; + if( value > upper ) return false; + return true; + } + template inline ValueType Abs( const ValueType &value ) { return value < 0 ? value * -1 : value; } diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h index dce7a026..ebb1e375 100644 --- a/Code/OysterMath/LinearMath.h +++ b/Code/OysterMath/LinearMath.h @@ -11,27 +11,6 @@ #include "Quaternion.h" #include -namespace std -{ - template - inline ::LinearAlgebra::Vector2 asin( const ::LinearAlgebra::Vector2 &vec ) - { - return ::LinearAlgebra::Vector2( asin(vec.x), asin(vec.y) ); - } - - template - inline ::LinearAlgebra::Vector3 asin( const ::LinearAlgebra::Vector3 &vec ) - { - return ::LinearAlgebra::Vector3( asin(vec.x), asin(vec.y), asin(vec.z) ); - } - - template - inline ::LinearAlgebra::Vector4 asin( const ::LinearAlgebra::Vector4 &vec ) - { - return ::LinearAlgebra::Vector4( asin(vec.x), asin(vec.y), asin(vec.z), asin(vec.w) ); - } -} - // x2 template @@ -112,6 +91,69 @@ inline ::LinearAlgebra::Vector4 operator * ( const ::LinearAlgebra:: (vector.x * matrix.m14) + (vector.y * matrix.m24) + (vector.z * matrix.m34) + (vector.w * matrix.m44) ); } +namespace std +{ + template + inline ::LinearAlgebra::Vector2 asin( const ::LinearAlgebra::Vector2 &vec ) + { + return ::LinearAlgebra::Vector2( asin(vec.x), asin(vec.y) ); + } + + template + inline ::LinearAlgebra::Vector3 asin( const ::LinearAlgebra::Vector3 &vec ) + { + return ::LinearAlgebra::Vector3( asin(vec.x), asin(vec.y), asin(vec.z) ); + } + + template + inline ::LinearAlgebra::Vector4 asin( const ::LinearAlgebra::Vector4 &vec ) + { + return ::LinearAlgebra::Vector4( asin(vec.x), asin(vec.y), asin(vec.z), asin(vec.w) ); + } + + /******************************************************************* + * @param numerator of the vector vec + * @return the denomiator of the vector vec. + *******************************************************************/ + template + inline ::LinearAlgebra::Vector2 modf( const ::LinearAlgebra::Vector2 &vec, ::LinearAlgebra::Vector2 &numerator ) + { + ::LinearAlgebra::Vector2 denominator; + denominator.x = (ScalarType)modf( vec.x, &numerator.x ); + denominator.y = (ScalarType)modf( vec.y, &numerator.y ); + return denominator; + } + + /******************************************************************* + * @param numerator of the vector vec + * @return the denomiator of the vector vec. + *******************************************************************/ + template + inline ::LinearAlgebra::Vector3 modf( const ::LinearAlgebra::Vector3 &vec, ::LinearAlgebra::Vector3 &numerator ) + { + ::LinearAlgebra::Vector3 denominator; + denominator.x = (ScalarType)modf( vec.x, &numerator.x ); + denominator.y = (ScalarType)modf( vec.y, &numerator.y ); + denominator.z = (ScalarType)modf( vec.z, &numerator.z ); + return denominator; + } + + /******************************************************************* + * @param numerator of the vector vec + * @return the denomiator of the vector vec. + *******************************************************************/ + template + inline ::LinearAlgebra::Vector4 modf( const ::LinearAlgebra::Vector4 &vec, ::LinearAlgebra::Vector4 &numerator ) + { + ::LinearAlgebra::Vector4 denominator; + denominator.x = (ScalarType)modf( vec.x, &numerator.x ); + denominator.y = (ScalarType)modf( vec.y, &numerator.y ); + denominator.z = (ScalarType)modf( vec.z, &numerator.z ); + denominator.w = (ScalarType)modf( vec.w, &numerator.w ); + return denominator; + } +} + namespace LinearAlgebra { // Creates a solution matrix for 'outī= 'targetMem' * 'in'. @@ -795,11 +837,42 @@ namespace LinearAlgebra3D } template - ::LinearAlgebra::Matrix4x4 & InterpolateOrientation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) + inline ::LinearAlgebra::Matrix4x4 & InterpolateRotation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) { targetMem.v[0] = ::LinearAlgebra::Nlerp( start.v[0], end.v[0], t ); targetMem.v[1] = ::LinearAlgebra::Nlerp( start.v[1], end.v[1], t ); targetMem.v[2] = ::LinearAlgebra::Nlerp( start.v[2], end.v[2], t ); + return targetMem; + } + + template + inline ::LinearAlgebra::Matrix4x4 & InterpolateOrientation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) + { + InterpolateRotation_UsingNonRigidNlerp( start, end, t, targetMem ); + targetMem.v[3] = ::LinearAlgebra::Lerp( start.v[3], end.v[3], t ); + return targetMem; + } + + template + ::LinearAlgebra::Matrix4x4 & InterpolateRotation_UsingRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) + { + // Nlerp y axis + targetMem.v[1] = ::LinearAlgebra::Nlerp( start.v[1], end.v[1], t ); + + // Lerp z axis and orthogonolize against y axis + targetMem.v[2] = ::LinearAlgebra::Lerp( start.v[2], end.v[2], t ); + targetMem.v[2] -= targetMem.v[2].Dot(targetMem.v[1]) * targetMem.v[1]; + targetMem.v[2].Normalize(); + + // Cross product x axis from y and z + targetMem.v[0].xyz = targetMem.v[1].xyz.Cross(targetMem.v[2].xyz); + return targetMem; + } + + template + inline ::LinearAlgebra::Matrix4x4 & InterpolateOrientation_UsingRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) + { + InterpolateRotation_UsingRigidNlerp( start, end, t, targetMem ); targetMem.v[3] = ::LinearAlgebra::Lerp( start.v[3], end.v[3], t ); return targetMem; } diff --git a/Code/OysterMath/OysterMath.h b/Code/OysterMath/OysterMath.h index 7e123183..23ee06db 100644 --- a/Code/OysterMath/OysterMath.h +++ b/Code/OysterMath/OysterMath.h @@ -322,7 +322,10 @@ namespace Oyster { namespace Math3D //! Oyster's native math library specialized using ::LinearAlgebra3D::SnapAxisYToNormal_UsingNlerp; using ::LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp; + using ::LinearAlgebra3D::InterpolateRotation_UsingNonRigidNlerp; + using ::LinearAlgebra3D::InterpolateRotation_UsingRigidNlerp; using ::LinearAlgebra3D::InterpolateOrientation_UsingNonRigidNlerp; + using ::LinearAlgebra3D::InterpolateOrientation_UsingRigidNlerp; using ::LinearAlgebra3D::InterpolateOrientation_UsingSlerp; using ::LinearAlgebra3D::SnapAngularAxis; } } diff --git a/Code/OysterPhysics3D/Box.cpp b/Code/OysterPhysics3D/Box.cpp index f55415b7..56950e24 100644 --- a/Code/OysterPhysics3D/Box.cpp +++ b/Code/OysterPhysics3D/Box.cpp @@ -92,4 +92,27 @@ bool Box::Contains( const ICollideable &target ) const //case Type_frustrum: return false; // TODO: default: return false; } -} \ No newline at end of file +} + +Float Box::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } +} + +namespace Oyster { namespace Math +{ + Box & Nlerp( const Box &start, const Box &end, Float t, Box &targetMem ) + { + InterpolateRotation_UsingRigidNlerp( start.rotation, end.rotation, t, targetMem.rotation ); + targetMem.center = Lerp( start.center, end.center, t ); + targetMem.boundingOffset = Lerp( start.boundingOffset, end.boundingOffset, t ); + return targetMem; + } +} } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Box.h b/Code/OysterPhysics3D/Box.h index f98ae362..553037be 100644 --- a/Code/OysterPhysics3D/Box.h +++ b/Code/OysterPhysics3D/Box.h @@ -9,35 +9,48 @@ #include "OysterMath.h" #include "ICollideable.h" -namespace Oyster { namespace Collision3D +namespace Oyster { - class Box : public ICollideable + namespace Collision3D { - public: - union + class Box : public ICollideable { - struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; }; - struct + public: + union { - ::Oyster::Math::Float4 xAxis; - ::Oyster::Math::Float4 yAxis; - ::Oyster::Math::Float4 zAxis; + struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; }; + struct + { + ::Oyster::Math::Float4 xAxis; + ::Oyster::Math::Float4 yAxis; + ::Oyster::Math::Float4 zAxis; + }; + char byte[sizeof(::Oyster::Math::Float4x4) + 2*sizeof(::Oyster::Math::Float4)]; }; - char byte[sizeof(::Oyster::Math::Float4x4) + 2*sizeof(::Oyster::Math::Float4)]; + + Box( ); + Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &size ); + Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float4 &worldPos, const ::Oyster::Math::Float4 &size ); + virtual ~Box( ); + + Box & operator = ( const Box &box ); + + virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const; + bool Intersects( const ICollideable &target ) const; + bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; + bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; + } - Box( ); - Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &size ); - Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float4 &worldPos, const ::Oyster::Math::Float4 &size ); - virtual ~Box( ); - - Box & operator = ( const Box &box ); - - virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const; - bool Intersects( const ICollideable &target ) const; - bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; - bool Contains( const ICollideable &target ) const; - }; -} } + namespace Math + { + /******************************************************************** + * Normalized Linear Interpolation + ********************************************************************/ + ::Oyster::Collision3D::Box & Nlerp( const ::Oyster::Collision3D::Box &start, const ::Oyster::Collision3D::Box &end, ::Oyster::Math::Float t, ::Oyster::Collision3D::Box &targetMem = ::Oyster::Collision3D::Box() ); + } +} #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/BoxAxisAligned.cpp b/Code/OysterPhysics3D/BoxAxisAligned.cpp index bd10016f..8c934617 100644 --- a/Code/OysterPhysics3D/BoxAxisAligned.cpp +++ b/Code/OysterPhysics3D/BoxAxisAligned.cpp @@ -76,4 +76,16 @@ bool BoxAxisAligned::Contains( const ICollideable &target ) const //default: return false; //} return false; +} + +Float BoxAxisAligned::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/BoxAxisAligned.h b/Code/OysterPhysics3D/BoxAxisAligned.h index 2ff39463..9ad55165 100644 --- a/Code/OysterPhysics3D/BoxAxisAligned.h +++ b/Code/OysterPhysics3D/BoxAxisAligned.h @@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/Frustrum.cpp b/Code/OysterPhysics3D/Frustrum.cpp index ce2c5256..32e6357b 100644 --- a/Code/OysterPhysics3D/Frustrum.cpp +++ b/Code/OysterPhysics3D/Frustrum.cpp @@ -243,6 +243,18 @@ bool Frustrum::Contains( const ICollideable &target ) const } } +Float Frustrum::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } +} + ::Oyster::Math::Float3 Frustrum::ExtractForwad() { return this->bottomPlane.normal.xyz; diff --git a/Code/OysterPhysics3D/Frustrum.h b/Code/OysterPhysics3D/Frustrum.h index ae0f086c..0c4cc04f 100644 --- a/Code/OysterPhysics3D/Frustrum.h +++ b/Code/OysterPhysics3D/Frustrum.h @@ -42,6 +42,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target, Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; + ::Oyster::Math::Float3 ExtractForwad(); }; diff --git a/Code/OysterPhysics3D/ICollideable.h b/Code/OysterPhysics3D/ICollideable.h index b3f61671..3e63200e 100644 --- a/Code/OysterPhysics3D/ICollideable.h +++ b/Code/OysterPhysics3D/ICollideable.h @@ -38,6 +38,8 @@ namespace Oyster { namespace Collision3D //! Contains a collection of 3D shapes virtual bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0; virtual bool Intersects( const ICollideable &target ) const = 0; virtual bool Contains( const ICollideable &target ) const = 0; + + virtual ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const = 0; }; } } #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/Line.cpp b/Code/OysterPhysics3D/Line.cpp index cebceaff..fc81791d 100644 --- a/Code/OysterPhysics3D/Line.cpp +++ b/Code/OysterPhysics3D/Line.cpp @@ -76,3 +76,15 @@ bool Line::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) bool Line::Contains( const ICollideable &target ) const { /* TODO: : */ return false; } + +Float Line::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } +} \ No newline at end of file diff --git a/Code/OysterPhysics3D/Line.h b/Code/OysterPhysics3D/Line.h index 2e6d2d55..a305622f 100644 --- a/Code/OysterPhysics3D/Line.h +++ b/Code/OysterPhysics3D/Line.h @@ -32,6 +32,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/OysterCollision3D.cpp b/Code/OysterPhysics3D/OysterCollision3D.cpp index 89b3af8a..cc68d536 100644 --- a/Code/OysterPhysics3D/OysterCollision3D.cpp +++ b/Code/OysterPhysics3D/OysterCollision3D.cpp @@ -1061,4 +1061,43 @@ namespace Oyster { namespace Collision3D { namespace Utility return container.normal == -plane.normal; return false; } + + Float TimeOfContact( const Sphere &protoStart, const Sphere &protoEnd, const Point &deuter ) + { // Bisection with 5 levels of detail + Float t = 0.5f; + Sphere s; + for( int i = 0; i < 5; ++i ) + { + Nlerp( protoStart, protoEnd, t, s ); + if( Intersect(s, deuter) ) + { + t *= 0.5f; + } + else + { + t *= 1.5f; + } + } + return t; + } + + Float TimeOfContact( const Box &protoStart, const Box &protoEnd, const Point &deuter ) + { // Bisection with 5 levels of detail + Float t = 0.5f; + Box b; + for( int i = 0; i < 5; ++i ) + { + Nlerp( protoStart, protoEnd, t, b ); + if( Intersect(b, deuter) ) + { + t *= 0.5f; + } + else + { + t *= 1.5f; + } + } + return t; + } + } } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/OysterCollision3D.h b/Code/OysterPhysics3D/OysterCollision3D.h index 20a55a18..83a6239e 100644 --- a/Code/OysterPhysics3D/OysterCollision3D.h +++ b/Code/OysterPhysics3D/OysterCollision3D.h @@ -121,6 +121,9 @@ namespace Oyster { namespace Collision3D { namespace Utility // bool Contains( const Frustrum &container, const BoxAxisAligned &box ); // bool Contains( const Frustrum &container, const Box &box ); // bool Contains( const Frustrum &container, const Frustrum &frustrum ); + + ::Oyster::Math::Float TimeOfContact( const Sphere &protoStart, const Sphere &protoEnd, const Point &deuter ); + ::Oyster::Math::Float TimeOfContact( const Box &protoStart, const Box &protoEnd, const Point &deuter ); } } } #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters b/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters index da336ce5..f6b6d934 100644 --- a/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters +++ b/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters @@ -27,9 +27,6 @@ - - Header Files\Collision - Header Files\Collision @@ -81,6 +78,9 @@ Header Files\Physics + + Header Files\Collision + diff --git a/Code/OysterPhysics3D/Plane.cpp b/Code/OysterPhysics3D/Plane.cpp index 59ffbc47..2923a802 100644 --- a/Code/OysterPhysics3D/Plane.cpp +++ b/Code/OysterPhysics3D/Plane.cpp @@ -83,4 +83,16 @@ bool Plane::Contains( const ICollideable &target ) const //case Type_triangle: return false; // TODO: default: return false; } +} + +Float Plane::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Plane.h b/Code/OysterPhysics3D/Plane.h index f148ed8e..a66e7f3b 100644 --- a/Code/OysterPhysics3D/Plane.h +++ b/Code/OysterPhysics3D/Plane.h @@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/Point.cpp b/Code/OysterPhysics3D/Point.cpp index 788ab32d..dd879e27 100644 --- a/Code/OysterPhysics3D/Point.cpp +++ b/Code/OysterPhysics3D/Point.cpp @@ -81,4 +81,18 @@ bool Point::Contains( const ICollideable &target ) const case Type_point: return Utility::Intersect( *this, (const Point&)target ); default: return false; } +} + +Float Point::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_sphere: return Utility::TimeOfContact( (const Sphere&)deuterStart, (const Sphere&)deuterEnd, *this ); + case Type_box: return Utility::TimeOfContact( (const Box&)deuterStart, (const Box&)deuterEnd, *this ); + case Type_universe: return 0.0f; + default: return 1.0f; + } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Point.h b/Code/OysterPhysics3D/Point.h index 60486373..15abc488 100644 --- a/Code/OysterPhysics3D/Point.h +++ b/Code/OysterPhysics3D/Point.h @@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/Ray.cpp b/Code/OysterPhysics3D/Ray.cpp index e7f21de8..5e58d14b 100644 --- a/Code/OysterPhysics3D/Ray.cpp +++ b/Code/OysterPhysics3D/Ray.cpp @@ -92,4 +92,16 @@ bool Ray::Contains( const ICollideable &target ) const case Type_ray: return Utility::Contains( *this, (const Ray&)target ); default: return false; } +} + +Float Ray::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Ray.h b/Code/OysterPhysics3D/Ray.h index a85580b3..cd797539 100644 --- a/Code/OysterPhysics3D/Ray.h +++ b/Code/OysterPhysics3D/Ray.h @@ -39,6 +39,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index 70ded863..68f435e9 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -53,13 +53,9 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) //! HACK: @todo Add real solution with fluid drag this->momentum_Linear = this->momentum_Linear*0.99f; this->momentum_Angular = this->momentum_Angular*0.99f; + // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G - Float3 deltaPos = ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); - if( deltaPos.GetLength() < 0.001f ) - { - deltaPos = Float3::null; - } - this->centerPos += deltaPos; + this->centerPos += ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); // updating the angular // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H @@ -185,6 +181,12 @@ void RigidBody::SetMass_KeepMomentum( const Float &m ) } } +void RigidBody::SetRotation( const Float3 &axis ) +{ // by Dan Andersson + this->axis = axis; + this->rotation = Rotation( this->axis ); +} + void RigidBody::SetMomentum_Linear( const Float3 &worldG, const Float3 &atWorldPos ) { // by Dan Andersson Float3 worldOffset = atWorldPos - this->centerPos; diff --git a/Code/OysterPhysics3D/RigidBody.h b/Code/OysterPhysics3D/RigidBody.h index c666662a..f7aebd22 100644 --- a/Code/OysterPhysics3D/RigidBody.h +++ b/Code/OysterPhysics3D/RigidBody.h @@ -64,7 +64,7 @@ namespace Oyster { namespace Physics3D void SetMass_KeepMomentum( const ::Oyster::Math::Float &m ); //void SetOrientation( const ::Oyster::Math::Float4x4 &o ); - //void SetRotation( const ::Oyster::Math::Float4x4 &r ); + void SetRotation( const ::Oyster::Math::Float3 &axis ); void SetSize( const ::Oyster::Math::Float3 &widthHeight ); void SetMomentum_Linear( const ::Oyster::Math::Float3 &worldG, const ::Oyster::Math::Float3 &atWorldPos ); diff --git a/Code/OysterPhysics3D/Sphere.cpp b/Code/OysterPhysics3D/Sphere.cpp index c402b2ef..86230508 100644 --- a/Code/OysterPhysics3D/Sphere.cpp +++ b/Code/OysterPhysics3D/Sphere.cpp @@ -86,4 +86,30 @@ bool Sphere::Contains( const ICollideable &target ) const //case Type_frustrum: return false; // TODO: default: return false; } -} \ No newline at end of file +} + +Float Sphere::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { + //case Type_point: // not implemented + //case Type_sphere: // not implemented + //case Type_box: // not implemented + case Type_universe: return 0.0f; + default: return 1.0f; + } +} + +namespace Oyster { namespace Math +{ + Sphere & Nlerp( const Sphere &start, const Sphere &end, Float t, Sphere &targetMem ) + { + Float4 i = Lerp( Float4(start.center.xyz, start.radius), Float4(end.center.xyz, end.radius), t ); + targetMem.center.xyz = i.xyz; + targetMem.radius = i.w; + return targetMem; + } +} } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Sphere.h b/Code/OysterPhysics3D/Sphere.h index 2f483ecd..c3cc32a3 100644 --- a/Code/OysterPhysics3D/Sphere.h +++ b/Code/OysterPhysics3D/Sphere.h @@ -9,29 +9,42 @@ #include "OysterMath.h" #include "ICollideable.h" -namespace Oyster { namespace Collision3D +namespace Oyster { - class Sphere : public ICollideable + namespace Collision3D { - public: - union + class Sphere : public ICollideable { - struct{ ::Oyster::Math::Float4 center; ::Oyster::Math::Float radius; }; - char byte[sizeof(::Oyster::Math::Float4) + sizeof(::Oyster::Math::Float)]; + public: + union + { + struct{ ::Oyster::Math::Float4 center; ::Oyster::Math::Float radius; }; + char byte[sizeof(::Oyster::Math::Float4) + sizeof(::Oyster::Math::Float)]; + }; + + Sphere( ); + Sphere( const ::Oyster::Math::Float3 ¢er, const ::Oyster::Math::Float &radius ); + Sphere( const ::Oyster::Math::Float4 ¢er, const ::Oyster::Math::Float &radius ); + virtual ~Sphere( ); + + Sphere & operator = ( const Sphere &sphere ); + + virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const; + bool Intersects( const ICollideable &target ) const; + bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; + bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; + } - Sphere( ); - Sphere( const ::Oyster::Math::Float3 ¢er, const ::Oyster::Math::Float &radius ); - Sphere( const ::Oyster::Math::Float4 ¢er, const ::Oyster::Math::Float &radius ); - virtual ~Sphere( ); - - Sphere & operator = ( const Sphere &sphere ); - - virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const; - bool Intersects( const ICollideable &target ) const; - bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; - bool Contains( const ICollideable &target ) const; - }; -} } + namespace Math + { + /******************************************************************** + * Normalized Linear Interpolation + ********************************************************************/ + ::Oyster::Collision3D::Sphere & Nlerp( const ::Oyster::Collision3D::Sphere &start, const ::Oyster::Collision3D::Sphere &end, ::Oyster::Math::Float t, ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ); + } +} #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/Universe.cpp b/Code/OysterPhysics3D/Universe.cpp index 7eb788ae..a3548ad9 100644 --- a/Code/OysterPhysics3D/Universe.cpp +++ b/Code/OysterPhysics3D/Universe.cpp @@ -78,4 +78,9 @@ bool Universe::Intersects( const ICollideable &target, Float4 &worldPointOfConta bool Universe::Contains( const ICollideable &target ) const { // universe contains everything return true; +} + +Float Universe::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + return 0.0f; } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Universe.h b/Code/OysterPhysics3D/Universe.h index 5f009e0b..7b5fb969 100644 --- a/Code/OysterPhysics3D/Universe.h +++ b/Code/OysterPhysics3D/Universe.h @@ -23,6 +23,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } }