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;
}
// calculate and store time interpolation value, for later rebound.
proto->SetTimeOfContact( worldPointOfContact );
// bounce
Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(),

View File

@ -49,6 +49,12 @@ 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;
@ -56,7 +62,8 @@ SimpleRigidBody::SimpleRigidBody()
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;
}

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 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;

View File

@ -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;
}

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 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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

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

View File

@ -11,27 +11,6 @@
#include "Quaternion.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
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) );
}
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
{
// Creates a solution matrix for 'out´= 'targetMem' * 'in'.
@ -795,11 +837,42 @@ namespace LinearAlgebra3D
}
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[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<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 );
return targetMem;
}

View File

@ -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;
} }

View File

@ -93,3 +93,26 @@ bool Box::Contains( const ICollideable &target ) const
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,8 +9,10 @@
#include "OysterMath.h"
#include "ICollideable.h"
namespace Oyster { namespace Collision3D
namespace Oyster
{
namespace Collision3D
{
class Box : public ICollideable
{
public:
@ -37,7 +39,18 @@ 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;
};
} }
}
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

View File

@ -77,3 +77,15 @@ bool BoxAxisAligned::Contains( const ICollideable &target ) const
//}
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, ::Oyster::Math::Float4 &worldPointOfContact ) 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()
{
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 Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
::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 ) const = 0;
virtual bool Contains( const ICollideable &target ) const = 0;
virtual ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const = 0;
};
} }
#endif

View File

@ -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;
}
}

View File

@ -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;
};
} }

View File

@ -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;
}
} } }

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 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

View File

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

View File

@ -84,3 +84,15 @@ bool Plane::Contains( const ICollideable &target ) const
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, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
};
} }

View File

@ -82,3 +82,17 @@ bool Point::Contains( const ICollideable &target ) const
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, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const;
};
} }

View File

@ -93,3 +93,15 @@ bool Ray::Contains( const ICollideable &target ) const
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, ::Oyster::Math::Float4 &worldPointOfContact ) 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
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;

View File

@ -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 );

View File

@ -87,3 +87,29 @@ bool Sphere::Contains( const ICollideable &target ) const
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,8 +9,10 @@
#include "OysterMath.h"
#include "ICollideable.h"
namespace Oyster { namespace Collision3D
namespace Oyster
{
namespace Collision3D
{
class Sphere : public ICollideable
{
public:
@ -31,7 +33,18 @@ 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;
};
} }
}
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

View File

@ -79,3 +79,8 @@ 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;
}

View File

@ -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;
};
} }