Merge branch 'Physics' of https://github.com/dean11/Danbias into GameLogic

This commit is contained in:
lindaandersson 2014-02-03 15:52:15 +01:00
commit c08c3d2b53
37 changed files with 604 additions and 111 deletions

View File

@ -40,6 +40,7 @@ void Octree::AddObject(UniquePointer< ICustomBody > customBodyRef)
data.next = NULL; data.next = NULL;
data.prev = NULL; data.prev = NULL;
data.customBodyRef = customBodyRef; data.customBodyRef = customBodyRef;
data.limbo = false;
this->mapReferences.insert(std::pair <ICustomBody*, unsigned int> (data.customBodyRef, this->leafData.size())); this->mapReferences.insert(std::pair <ICustomBody*, unsigned int> (data.customBodyRef, this->leafData.size()));
this->leafData.push_back(data); this->leafData.push_back(data);
@ -64,6 +65,33 @@ void Octree::MoveToUpdateQueue(UniquePointer< ICustomBody > customBodyRef)
this->updateQueue.push_back(&this->leafData[this->mapReferences[customBodyRef]]);*/ this->updateQueue.push_back(&this->leafData[this->mapReferences[customBodyRef]]);*/
} }
void Octree::MoveToLimbo(const ICustomBody* customBodyRef)
{
auto object = this->mapReferences.find(customBodyRef);
unsigned int tempRef = object->second;
this->leafData[tempRef].limbo = true;
}
bool Octree::IsInLimbo(const ICustomBody* customBodyRef)
{
auto object = this->mapReferences.find(customBodyRef);
unsigned int tempRef = object->second;
return this->leafData[tempRef].limbo;
}
void Octree::ReleaseFromLimbo(const ICustomBody* customBodyRef)
{
auto object = this->mapReferences.find(customBodyRef);
unsigned int tempRef = object->second;
this->leafData[tempRef].limbo = false;
}
void Octree::DestroyObject(UniquePointer< ICustomBody > customBodyRef) void Octree::DestroyObject(UniquePointer< ICustomBody > customBodyRef)
{ {
std::map<const ICustomBody*, unsigned int>::iterator it = this->mapReferences.find(customBodyRef); std::map<const ICustomBody*, unsigned int>::iterator it = this->mapReferences.find(customBodyRef);
@ -86,7 +114,7 @@ std::vector<ICustomBody*>& Octree::Sample(ICustomBody* customBodyRef, std::vecto
for(unsigned int i = 0; i<this->leafData.size(); i++) for(unsigned int i = 0; i<this->leafData.size(); i++)
{ {
if(tempRef != i) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container)) if(tempRef != i && !this->leafData[i].limbo) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container))
{ {
updateList.push_back(this->leafData[i].customBodyRef); updateList.push_back(this->leafData[i].customBodyRef);
} }
@ -99,7 +127,7 @@ std::vector<ICustomBody*>& Octree::Sample(const Oyster::Collision3D::ICollideabl
{ {
for(unsigned int i = 0; i<this->leafData.size(); i++) for(unsigned int i = 0; i<this->leafData.size(); i++)
{ {
if(this->leafData[i].container.Intersects(collideable)) if(!this->leafData[i].limbo && this->leafData[i].container.Intersects(collideable))
{ {
updateList.push_back(this->leafData[i].customBodyRef); updateList.push_back(this->leafData[i].customBodyRef);
} }
@ -121,7 +149,7 @@ void Octree::Visit(ICustomBody* customBodyRef, VisitorAction hitAction )
for(unsigned int i = 0; i<this->leafData.size(); i++) for(unsigned int i = 0; i<this->leafData.size(); i++)
{ {
if(tempRef != i) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container)) if(tempRef != i && !this->leafData[i].limbo) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container))
{ {
hitAction(*this, tempRef, i); hitAction(*this, tempRef, i);
} }
@ -132,7 +160,7 @@ void Octree::Visit(const Oyster::Collision3D::ICollideable& collideable, void* a
{ {
for(unsigned int i = 0; i<this->leafData.size(); i++) for(unsigned int i = 0; i<this->leafData.size(); i++)
{ {
if(collideable.Intersects(this->leafData[i].container)) if(!this->leafData[i].limbo && collideable.Intersects(this->leafData[i].container))
{ {
hitAction( this->GetCustomBody(i), args ); hitAction( this->GetCustomBody(i), args );
} }

View File

@ -29,6 +29,8 @@ namespace Oyster
::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef; ::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef;
bool limbo;
unsigned int queueRef; unsigned int queueRef;
}; };
@ -48,6 +50,10 @@ namespace Oyster
void MoveToUpdateQueue(::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef); void MoveToUpdateQueue(::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef);
void MoveToLimbo(const ICustomBody* customBodyRef);
bool IsInLimbo(const ICustomBody* customBodyRef);
void ReleaseFromLimbo(const ICustomBody* customBodyRef);
void DestroyObject(::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef); void DestroyObject(::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef);
std::vector<ICustomBody*>& Sample(ICustomBody* customBodyRef, std::vector<ICustomBody*>& updateList); std::vector<ICustomBody*>& Sample(ICustomBody* customBodyRef, std::vector<ICustomBody*>& updateList);
@ -66,6 +72,7 @@ namespace Oyster
private: private:
std::vector < Data > leafData; std::vector < Data > leafData;
std::vector < Data* > updateQueue; std::vector < Data* > updateQueue;
std::vector < Data* > limbo;
std::map< const ICustomBody*, unsigned int > mapReferences; std::map< const ICustomBody*, unsigned int > mapReferences;

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(),
@ -78,10 +80,14 @@ namespace
deuterState.GetMass(), deuterG_Magnitude ); deuterState.GetMass(), deuterG_Magnitude );
Float4 bounce = Average( bounceD, bounceP ); Float4 bounce = Average( bounceD, bounceP );
Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal,
Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(),
Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass());
Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() ); Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() );
protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz ); protoState.ApplyImpulse( bounce.xyz - friction.xyz, worldPointOfContact.xyz, normal.xyz );
proto->SetState( protoState ); proto->SetState( protoState );
Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() ); Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() );
@ -233,17 +239,16 @@ void API_Impl::Update()
bool API_Impl::IsInLimbo( const ICustomBody* objRef ) bool API_Impl::IsInLimbo( const ICustomBody* objRef )
{ {
//! @todo TODO: implement stub return this->worldScene.IsInLimbo( objRef );
return true;
} }
void API_Impl::MoveToLimbo( const ICustomBody* objRef ) void API_Impl::MoveToLimbo( const ICustomBody* objRef )
{ {
/** @todo TODO: Fix this function.*/ this->worldScene.MoveToLimbo( objRef );
} }
void API_Impl::ReleaseFromLimbo( const ICustomBody* objRef ) void API_Impl::ReleaseFromLimbo( const ICustomBody* objRef )
{ {
/** @todo TODO: Fix this function.*/ this->worldScene.ReleaseFromLimbo( objRef );
} }
void API_Impl::AddObject( ::Utility::DynamicMemory::UniquePointer<ICustomBody> handle ) void API_Impl::AddObject( ::Utility::DynamicMemory::UniquePointer<ICustomBody> handle )

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

@ -49,13 +49,13 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength )
{ // by Dan Andersson: Euler leap frog update when Runga Kutta is not needed { // by Dan Andersson: Euler leap frog update when Runga Kutta is not needed
// updating the linear // updating the linear
//Decrease momentum with 1% as "fall-off"
//! 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 // 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
@ -181,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;
}; };
} } } }