Big patch! New feature :)

Objects will now rebound back when colliding.
This commit is contained in:
Dander7BD 2014-02-03 15:48:42 +01:00
parent f527d329a2
commit 8b0e1b2426
35 changed files with 553 additions and 102 deletions

View File

@ -60,6 +60,8 @@ namespace
return; return;
} }
// calculate and store time interpolation value, for later rebound.
proto->SetTimeOfContact( worldPointOfContact );
// bounce // bounce
Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(), Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(),

View File

@ -49,14 +49,21 @@ SimpleRigidBody::SimpleRigidBody()
this->onCollision = Default::EventAction_BeforeCollisionResponse; this->onCollision = Default::EventAction_BeforeCollisionResponse;
this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; this->onCollisionResponse = Default::EventAction_AfterCollisionResponse;
this->onMovement = Default::EventAction_Move; 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->scene = nullptr;
this->customTag = nullptr; this->customTag = nullptr;
this->ignoreGravity = this->isForwarded = false; this->ignoreGravity = this->isForwarded = false;
} }
SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) 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.centerPos = desc.centerPosition;
this->rigid.SetSize( desc.size ); this->rigid.SetSize( desc.size );
this->rigid.SetMass_KeepMomentum( desc.mass ); this->rigid.SetMass_KeepMomentum( desc.mass );
@ -66,6 +73,11 @@ SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc )
this->gravityNormal = Float3::null; 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 ) if( desc.subscription_onCollision )
{ {
this->onCollision = 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 ); 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 Sphere & SimpleRigidBody::GetBoundingSphere( Sphere &targetMem ) const
{ {
return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.GetMagnitude() ); return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.GetMagnitude() );
@ -293,18 +325,52 @@ void * SimpleRigidBody::GetCustomTag() const
UpdateState SimpleRigidBody::Update( Float timeStepLength ) UpdateState SimpleRigidBody::Update( Float timeStepLength )
{ {
if( this->isForwarded ) //if( this->isForwarded )
{ //{
this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz ); // this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz );
this->deltaPos = Float4::null; // this->deltaPos = Float4::null;
this->deltaAxis = Float4::null; // this->deltaAxis = Float4::null;
this->isForwarded = false; // this->isForwarded = false;
} //}
this->rigid.Update_LeapFrog( timeStepLength ); this->rigid.Update_LeapFrog( timeStepLength );
//! @todo TODO: compare previous and new state and return result { // Rebound if needed
//return this->current == this->previous ? UpdateState_resting : UpdateState_altered; 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; return UpdateState_altered;
} }

View File

@ -30,6 +30,8 @@ namespace Oyster { namespace Physics
bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Intersects( const ICustomBody &object, ::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::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::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; ::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::Physics3D::RigidBody rigid;
::Oyster::Math::Float4 deltaPos, deltaAxis; ::Oyster::Math::Float4 deltaPos, deltaAxis;
::Oyster::Math::Float3 gravityNormal; ::Oyster::Math::Float3 gravityNormal;
struct
{
struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial;
::Oyster::Math::Float timeOfContact;
} collisionRebound;
EventAction_BeforeCollisionResponse onCollision; EventAction_BeforeCollisionResponse onCollision;
EventAction_AfterCollisionResponse onCollisionResponse; EventAction_AfterCollisionResponse onCollisionResponse;
EventAction_Move onMovement; EventAction_Move onMovement;
Octree *scene; Octree *scene;
void *customTag; void *customTag;
bool ignoreGravity, isForwarded; bool ignoreGravity, isForwarded;

View File

@ -11,11 +11,17 @@ using namespace ::Utility::Value;
SphericalRigidBody::SphericalRigidBody() SphericalRigidBody::SphericalRigidBody()
{ {
this->rigid = RigidBody(); this->rigid = RigidBody();
this->rigid.SetMass_KeepMomentum( 10.0f ); this->rigid.SetMass_KeepMomentum( 16.0f );
this->gravityNormal = Float3::null; this->gravityNormal = Float3::null;
this->onCollision = Default::EventAction_BeforeCollisionResponse; this->onCollision = Default::EventAction_BeforeCollisionResponse;
this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; this->onCollisionResponse = Default::EventAction_AfterCollisionResponse;
this->onMovement = Default::EventAction_Move; 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->scene = nullptr;
this->customTag = nullptr; this->customTag = nullptr;
this->ignoreGravity = this->isForwarded = false; this->ignoreGravity = this->isForwarded = false;
@ -24,7 +30,7 @@ SphericalRigidBody::SphericalRigidBody()
SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &desc ) SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &desc )
{ {
this->rigid = RigidBody(); this->rigid = RigidBody();
//this->rigid.SetRotation( desc.rotation ); this->rigid.SetRotation( desc.rotation );
this->rigid.centerPos = desc.centerPosition; this->rigid.centerPos = desc.centerPosition;
this->rigid.boundingReach = Float4( desc.radius, desc.radius, desc.radius, 0.0f ); this->rigid.boundingReach = Float4( desc.radius, desc.radius, desc.radius, 0.0f );
this->rigid.SetMass_KeepMomentum( desc.mass ); this->rigid.SetMass_KeepMomentum( desc.mass );
@ -34,6 +40,11 @@ SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &des
this->gravityNormal = Float3::null; 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 ) if( desc.subscription_onCollision )
{ {
this->onCollision = desc.subscription_onCollision; this->onCollision = desc.subscription_onCollision;
@ -64,6 +75,11 @@ SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &des
this->scene = nullptr; this->scene = nullptr;
this->customTag = nullptr; this->customTag = nullptr;
this->ignoreGravity = desc.ignoreGravity; 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() {} 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 ); 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 Sphere & SphericalRigidBody::GetBoundingSphere( Sphere &targetMem ) const
{ {
return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ); return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x );
@ -219,18 +246,52 @@ void * SphericalRigidBody::GetCustomTag() const
UpdateState SphericalRigidBody::Update( Float timeStepLength ) UpdateState SphericalRigidBody::Update( Float timeStepLength )
{ {
if( this->isForwarded ) //if( this->isForwarded )
{ //{
this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz ); // this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz );
this->deltaPos = Float4::null; // this->deltaPos = Float4::null;
this->deltaAxis = Float4::null; // this->deltaAxis = Float4::null;
this->isForwarded = false; // this->isForwarded = false;
} //}
this->rigid.Update_LeapFrog( timeStepLength ); this->rigid.Update_LeapFrog( timeStepLength );
// compare previous and new state and return result { // Rebound if needed
//return this->current == this->previous ? UpdateState_resting : UpdateState_altered; 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; return UpdateState_altered;
} }

View File

@ -31,6 +31,8 @@ namespace Oyster { namespace Physics
bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Intersects( const ICustomBody &object, ::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::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::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; ::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::Physics3D::RigidBody rigid;
::Oyster::Math::Float4 deltaPos, deltaAxis; ::Oyster::Math::Float4 deltaPos, deltaAxis;
::Oyster::Math::Float3 gravityNormal; ::Oyster::Math::Float3 gravityNormal;
struct
{
struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial;
::Oyster::Math::Float timeOfContact;
} collisionRebound;
EventAction_BeforeCollisionResponse onCollision; EventAction_BeforeCollisionResponse onCollision;
EventAction_AfterCollisionResponse onCollisionResponse; EventAction_AfterCollisionResponse onCollisionResponse;
EventAction_Move onMovement; EventAction_Move onMovement;

View File

@ -322,6 +322,11 @@ namespace Oyster
********************************************************/ ********************************************************/
virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0; 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. * Required by Engine's Collision Search.
* @param targetMem: Provided memory that written into and then returned. * @param targetMem: Provided memory that written into and then returned.

View File

@ -12,7 +12,7 @@ namespace Oyster
{ {
inline SimpleBodyDescription::SimpleBodyDescription() inline SimpleBodyDescription::SimpleBodyDescription()
{ {
this->rotation = ::Oyster::Math::Float4x4::identity; this->rotation = ::Oyster::Math::Float3::null;
this->centerPosition = ::Oyster::Math::Float3::null; this->centerPosition = ::Oyster::Math::Float3::null;
this->size = ::Oyster::Math::Float3( 1.0f ); this->size = ::Oyster::Math::Float3( 1.0f );
this->mass = 6.0f; this->mass = 6.0f;
@ -28,7 +28,7 @@ namespace Oyster
inline SphericalBodyDescription::SphericalBodyDescription() inline SphericalBodyDescription::SphericalBodyDescription()
{ {
this->rotation = ::Oyster::Math::Float4x4::identity; this->rotation = ::Oyster::Math::Float3::null;
this->centerPosition = ::Oyster::Math::Float3::null; this->centerPosition = ::Oyster::Math::Float3::null;
this->radius = 0.5f; this->radius = 0.5f;
this->mass = 10.0f; this->mass = 10.0f;

View File

@ -11,7 +11,7 @@ namespace Oyster { namespace Physics
{ {
struct SimpleBodyDescription struct SimpleBodyDescription
{ {
::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float3 rotation;
::Oyster::Math::Float3 centerPosition; ::Oyster::Math::Float3 centerPosition;
::Oyster::Math::Float3 size; ::Oyster::Math::Float3 size;
::Oyster::Math::Float mass; ::Oyster::Math::Float mass;
@ -29,7 +29,7 @@ namespace Oyster { namespace Physics
struct SphericalBodyDescription struct SphericalBodyDescription
{ {
::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float3 rotation;
::Oyster::Math::Float3 centerPosition; ::Oyster::Math::Float3 centerPosition;
::Oyster::Math::Float radius; ::Oyster::Math::Float radius;
::Oyster::Math::Float mass; ::Oyster::Math::Float mass;

View File

@ -315,6 +315,14 @@ namespace Utility
{ {
using ::std::numeric_limits; using ::std::numeric_limits;
template<typename ValueType>
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<typename ValueType> template<typename ValueType>
inline ValueType Abs( const ValueType &value ) inline ValueType Abs( const ValueType &value )
{ return value < 0 ? value * -1 : value; } { return value < 0 ? value * -1 : value; }

View File

@ -11,27 +11,6 @@
#include "Quaternion.h" #include "Quaternion.h"
#include <math.h> #include <math.h>
namespace std
{
template<typename ScalarType>
inline ::LinearAlgebra::Vector2<ScalarType> asin( const ::LinearAlgebra::Vector2<ScalarType> &vec )
{
return ::LinearAlgebra::Vector2<ScalarType>( asin(vec.x), asin(vec.y) );
}
template<typename ScalarType>
inline ::LinearAlgebra::Vector3<ScalarType> asin( const ::LinearAlgebra::Vector3<ScalarType> &vec )
{
return ::LinearAlgebra::Vector3<ScalarType>( asin(vec.x), asin(vec.y), asin(vec.z) );
}
template<typename ScalarType>
inline ::LinearAlgebra::Vector4<ScalarType> asin( const ::LinearAlgebra::Vector4<ScalarType> &vec )
{
return ::LinearAlgebra::Vector4<ScalarType>( asin(vec.x), asin(vec.y), asin(vec.z), asin(vec.w) );
}
}
// x2 // x2
template<typename ScalarType> template<typename ScalarType>
@ -112,6 +91,69 @@ inline ::LinearAlgebra::Vector4<ScalarType> operator * ( const ::LinearAlgebra::
(vector.x * matrix.m14) + (vector.y * matrix.m24) + (vector.z * matrix.m34) + (vector.w * matrix.m44) ); (vector.x * matrix.m14) + (vector.y * matrix.m24) + (vector.z * matrix.m34) + (vector.w * matrix.m44) );
} }
namespace std
{
template<typename ScalarType>
inline ::LinearAlgebra::Vector2<ScalarType> asin( const ::LinearAlgebra::Vector2<ScalarType> &vec )
{
return ::LinearAlgebra::Vector2<ScalarType>( asin(vec.x), asin(vec.y) );
}
template<typename ScalarType>
inline ::LinearAlgebra::Vector3<ScalarType> asin( const ::LinearAlgebra::Vector3<ScalarType> &vec )
{
return ::LinearAlgebra::Vector3<ScalarType>( asin(vec.x), asin(vec.y), asin(vec.z) );
}
template<typename ScalarType>
inline ::LinearAlgebra::Vector4<ScalarType> asin( const ::LinearAlgebra::Vector4<ScalarType> &vec )
{
return ::LinearAlgebra::Vector4<ScalarType>( 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<typename ScalarType>
inline ::LinearAlgebra::Vector2<ScalarType> modf( const ::LinearAlgebra::Vector2<ScalarType> &vec, ::LinearAlgebra::Vector2<ScalarType> &numerator )
{
::LinearAlgebra::Vector2<ScalarType> 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<typename ScalarType>
inline ::LinearAlgebra::Vector3<ScalarType> modf( const ::LinearAlgebra::Vector3<ScalarType> &vec, ::LinearAlgebra::Vector3<ScalarType> &numerator )
{
::LinearAlgebra::Vector3<ScalarType> 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<typename ScalarType>
inline ::LinearAlgebra::Vector4<ScalarType> modf( const ::LinearAlgebra::Vector4<ScalarType> &vec, ::LinearAlgebra::Vector4<ScalarType> &numerator )
{
::LinearAlgebra::Vector4<ScalarType> 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 namespace LinearAlgebra
{ {
// Creates a solution matrix for 'out´= 'targetMem' * 'in'. // Creates a solution matrix for 'out´= 'targetMem' * 'in'.
@ -795,11 +837,42 @@ namespace LinearAlgebra3D
} }
template<typename ScalarType> template<typename ScalarType>
::LinearAlgebra::Matrix4x4<ScalarType> & InterpolateOrientation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4<ScalarType> &start, const ::LinearAlgebra::Matrix4x4<ScalarType> &end, ScalarType t, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem ) inline ::LinearAlgebra::Matrix4x4<ScalarType> & InterpolateRotation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4<ScalarType> &start, const ::LinearAlgebra::Matrix4x4<ScalarType> &end, ScalarType t, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem )
{ {
targetMem.v[0] = ::LinearAlgebra::Nlerp( start.v[0], end.v[0], t ); 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[1] = ::LinearAlgebra::Nlerp( start.v[1], end.v[1], t );
targetMem.v[2] = ::LinearAlgebra::Nlerp( start.v[2], end.v[2], t ); targetMem.v[2] = ::LinearAlgebra::Nlerp( start.v[2], end.v[2], t );
return targetMem;
}
template<typename ScalarType>
inline ::LinearAlgebra::Matrix4x4<ScalarType> & InterpolateOrientation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4<ScalarType> &start, const ::LinearAlgebra::Matrix4x4<ScalarType> &end, ScalarType t, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem )
{
InterpolateRotation_UsingNonRigidNlerp( start, end, t, targetMem );
targetMem.v[3] = ::LinearAlgebra::Lerp( start.v[3], end.v[3], t );
return targetMem;
}
template<typename ScalarType>
::LinearAlgebra::Matrix4x4<ScalarType> & InterpolateRotation_UsingRigidNlerp( const ::LinearAlgebra::Matrix4x4<ScalarType> &start, const ::LinearAlgebra::Matrix4x4<ScalarType> &end, ScalarType t, ::LinearAlgebra::Matrix4x4<ScalarType> &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<typename ScalarType>
inline ::LinearAlgebra::Matrix4x4<ScalarType> & InterpolateOrientation_UsingRigidNlerp( const ::LinearAlgebra::Matrix4x4<ScalarType> &start, const ::LinearAlgebra::Matrix4x4<ScalarType> &end, ScalarType t, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem )
{
InterpolateRotation_UsingRigidNlerp( start, end, t, targetMem );
targetMem.v[3] = ::LinearAlgebra::Lerp( start.v[3], end.v[3], t ); targetMem.v[3] = ::LinearAlgebra::Lerp( start.v[3], end.v[3], t );
return targetMem; return targetMem;
} }

View File

@ -322,7 +322,10 @@ namespace Oyster { namespace Math3D //! Oyster's native math library specialized
using ::LinearAlgebra3D::SnapAxisYToNormal_UsingNlerp; using ::LinearAlgebra3D::SnapAxisYToNormal_UsingNlerp;
using ::LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp; using ::LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp;
using ::LinearAlgebra3D::InterpolateRotation_UsingNonRigidNlerp;
using ::LinearAlgebra3D::InterpolateRotation_UsingRigidNlerp;
using ::LinearAlgebra3D::InterpolateOrientation_UsingNonRigidNlerp; using ::LinearAlgebra3D::InterpolateOrientation_UsingNonRigidNlerp;
using ::LinearAlgebra3D::InterpolateOrientation_UsingRigidNlerp;
using ::LinearAlgebra3D::InterpolateOrientation_UsingSlerp; using ::LinearAlgebra3D::InterpolateOrientation_UsingSlerp;
using ::LinearAlgebra3D::SnapAngularAxis; using ::LinearAlgebra3D::SnapAngularAxis;
} } } }

View File

@ -92,4 +92,27 @@ bool Box::Contains( const ICollideable &target ) const
//case Type_frustrum: return false; // TODO: //case Type_frustrum: return false; // TODO:
default: return false; default: return false;
} }
} }
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;
}
} }

View File

@ -9,35 +9,48 @@
#include "OysterMath.h" #include "OysterMath.h"
#include "ICollideable.h" #include "ICollideable.h"
namespace Oyster { namespace Collision3D namespace Oyster
{ {
class Box : public ICollideable namespace Collision3D
{ {
public: class Box : public ICollideable
union
{ {
struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; }; public:
struct union
{ {
::Oyster::Math::Float4 xAxis; struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; };
::Oyster::Math::Float4 yAxis; struct
::Oyster::Math::Float4 zAxis; {
::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<ICollideable> 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( ); namespace Math
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( ); * Normalized Linear Interpolation
********************************************************************/
Box & operator = ( const Box &box ); ::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() );
}
virtual ::Utility::DynamicMemory::UniquePointer<ICollideable> Clone( ) const; }
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
#endif #endif

View File

@ -76,4 +76,16 @@ bool BoxAxisAligned::Contains( const ICollideable &target ) const
//default: return false; //default: return false;
//} //}
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;
}
} }

View File

@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D
bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const; bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
}; };
} } } }

View File

@ -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() ::Oyster::Math::Float3 Frustrum::ExtractForwad()
{ {
return this->bottomPlane.normal.xyz; return this->bottomPlane.normal.xyz;

View File

@ -42,6 +42,8 @@ namespace Oyster { namespace Collision3D
bool Intersects( const ICollideable &target, Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICollideable &target, Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const; bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
::Oyster::Math::Float3 ExtractForwad(); ::Oyster::Math::Float3 ExtractForwad();
}; };

View File

@ -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, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0;
virtual bool Intersects( const ICollideable &target ) const = 0; virtual bool Intersects( const ICollideable &target ) const = 0;
virtual bool Contains( 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 #endif

View File

@ -76,3 +76,15 @@ bool Line::Intersects( const ICollideable &target, Float4 &worldPointOfContact )
bool Line::Contains( const ICollideable &target ) const bool Line::Contains( const ICollideable &target ) const
{ /* TODO: : */ return false; } { /* 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;
}
}

View File

@ -32,6 +32,8 @@ namespace Oyster { namespace Collision3D
bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const; bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
}; };
} } } }

View File

@ -1061,4 +1061,43 @@ namespace Oyster { namespace Collision3D { namespace Utility
return container.normal == -plane.normal; return container.normal == -plane.normal;
return false; 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;
}
} } } } } }

View File

@ -121,6 +121,9 @@ namespace Oyster { namespace Collision3D { namespace Utility
// bool Contains( const Frustrum &container, const BoxAxisAligned &box ); // bool Contains( const Frustrum &container, const BoxAxisAligned &box );
// bool Contains( const Frustrum &container, const Box &box ); // bool Contains( const Frustrum &container, const Box &box );
// bool Contains( const Frustrum &container, const Frustrum &frustrum ); // 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 #endif

View File

@ -27,9 +27,6 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Universe.h">
<Filter>Header Files\Collision</Filter>
</ClInclude>
<ClInclude Include="Box.h"> <ClInclude Include="Box.h">
<Filter>Header Files\Collision</Filter> <Filter>Header Files\Collision</Filter>
</ClInclude> </ClInclude>
@ -81,6 +78,9 @@
<ClInclude Include="Inertia.h"> <ClInclude Include="Inertia.h">
<Filter>Header Files\Physics</Filter> <Filter>Header Files\Physics</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Universe.h">
<Filter>Header Files\Collision</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Box.cpp"> <ClCompile Include="Box.cpp">

View File

@ -83,4 +83,16 @@ bool Plane::Contains( const ICollideable &target ) const
//case Type_triangle: return false; // TODO: //case Type_triangle: return false; // TODO:
default: return false; 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;
}
} }

View File

@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D
bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const; bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
}; };
} } } }

View File

@ -81,4 +81,18 @@ bool Point::Contains( const ICollideable &target ) const
case Type_point: return Utility::Intersect( *this, (const Point&)target ); case Type_point: return Utility::Intersect( *this, (const Point&)target );
default: return false; 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;
}
} }

View File

@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D
bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const; bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
}; };
} } } }

View File

@ -92,4 +92,16 @@ bool Ray::Contains( const ICollideable &target ) const
case Type_ray: return Utility::Contains( *this, (const Ray&)target ); case Type_ray: return Utility::Contains( *this, (const Ray&)target );
default: return false; 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;
}
} }

View File

@ -39,6 +39,8 @@ namespace Oyster { namespace Collision3D
bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const; bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
}; };
} } } }

View File

@ -53,13 +53,9 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength )
//! HACK: @todo Add real solution with fluid drag //! HACK: @todo Add real solution with fluid drag
this->momentum_Linear = this->momentum_Linear*0.99f; this->momentum_Linear = this->momentum_Linear*0.99f;
this->momentum_Angular = this->momentum_Angular*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 // 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 ); this->centerPos += ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear );
if( deltaPos.GetLength() < 0.001f )
{
deltaPos = Float3::null;
}
this->centerPos += deltaPos;
// updating the angular // updating the angular
// dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H // 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 ) void RigidBody::SetMomentum_Linear( const Float3 &worldG, const Float3 &atWorldPos )
{ // by Dan Andersson { // by Dan Andersson
Float3 worldOffset = atWorldPos - this->centerPos; Float3 worldOffset = atWorldPos - this->centerPos;

View File

@ -64,7 +64,7 @@ namespace Oyster { namespace Physics3D
void SetMass_KeepMomentum( const ::Oyster::Math::Float &m ); void SetMass_KeepMomentum( const ::Oyster::Math::Float &m );
//void SetOrientation( const ::Oyster::Math::Float4x4 &o ); //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 SetSize( const ::Oyster::Math::Float3 &widthHeight );
void SetMomentum_Linear( const ::Oyster::Math::Float3 &worldG, const ::Oyster::Math::Float3 &atWorldPos ); void SetMomentum_Linear( const ::Oyster::Math::Float3 &worldG, const ::Oyster::Math::Float3 &atWorldPos );

View File

@ -86,4 +86,30 @@ bool Sphere::Contains( const ICollideable &target ) const
//case Type_frustrum: return false; // TODO: //case Type_frustrum: return false; // TODO:
default: return false; default: return false;
} }
} }
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;
}
} }

View File

@ -9,29 +9,42 @@
#include "OysterMath.h" #include "OysterMath.h"
#include "ICollideable.h" #include "ICollideable.h"
namespace Oyster { namespace Collision3D namespace Oyster
{ {
class Sphere : public ICollideable namespace Collision3D
{ {
public: class Sphere : public ICollideable
union
{ {
struct{ ::Oyster::Math::Float4 center; ::Oyster::Math::Float radius; }; public:
char byte[sizeof(::Oyster::Math::Float4) + sizeof(::Oyster::Math::Float)]; 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 &center, const ::Oyster::Math::Float &radius );
Sphere( const ::Oyster::Math::Float4 &center, const ::Oyster::Math::Float &radius );
virtual ~Sphere( );
Sphere & operator = ( const Sphere &sphere );
virtual ::Utility::DynamicMemory::UniquePointer<ICollideable> 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( ); namespace Math
Sphere( const ::Oyster::Math::Float3 &center, const ::Oyster::Math::Float &radius ); {
Sphere( const ::Oyster::Math::Float4 &center, const ::Oyster::Math::Float &radius ); /********************************************************************
virtual ~Sphere( ); * Normalized Linear Interpolation
********************************************************************/
Sphere & operator = ( const Sphere &sphere ); ::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() );
}
virtual ::Utility::DynamicMemory::UniquePointer<ICollideable> Clone( ) const; }
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
#endif #endif

View File

@ -78,4 +78,9 @@ bool Universe::Intersects( const ICollideable &target, Float4 &worldPointOfConta
bool Universe::Contains( const ICollideable &target ) const bool Universe::Contains( const ICollideable &target ) const
{ // universe contains everything { // universe contains everything
return true; return true;
}
Float Universe::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const
{
return 0.0f;
} }

View File

@ -23,6 +23,8 @@ namespace Oyster { namespace Collision3D
bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const; bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
}; };
} } } }