Merge branch 'Physics' of https://github.com/dean11/Danbias into GameLogic
This commit is contained in:
commit
c08c3d2b53
|
@ -40,6 +40,7 @@ void Octree::AddObject(UniquePointer< ICustomBody > customBodyRef)
|
|||
data.next = NULL;
|
||||
data.prev = NULL;
|
||||
data.customBodyRef = customBodyRef;
|
||||
data.limbo = false;
|
||||
this->mapReferences.insert(std::pair <ICustomBody*, unsigned int> (data.customBodyRef, this->leafData.size()));
|
||||
this->leafData.push_back(data);
|
||||
|
||||
|
@ -64,6 +65,33 @@ void Octree::MoveToUpdateQueue(UniquePointer< ICustomBody > 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)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -99,7 +127,7 @@ std::vector<ICustomBody*>& Octree::Sample(const Oyster::Collision3D::ICollideabl
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
@ -121,7 +149,7 @@ void Octree::Visit(ICustomBody* customBodyRef, VisitorAction hitAction )
|
|||
|
||||
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);
|
||||
}
|
||||
|
@ -132,7 +160,7 @@ void Octree::Visit(const Oyster::Collision3D::ICollideable& collideable, void* a
|
|||
{
|
||||
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 );
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace Oyster
|
|||
|
||||
::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef;
|
||||
|
||||
bool limbo;
|
||||
|
||||
unsigned int queueRef;
|
||||
};
|
||||
|
||||
|
@ -48,6 +50,10 @@ namespace Oyster
|
|||
|
||||
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);
|
||||
|
||||
std::vector<ICustomBody*>& Sample(ICustomBody* customBodyRef, std::vector<ICustomBody*>& updateList);
|
||||
|
@ -66,6 +72,7 @@ namespace Oyster
|
|||
private:
|
||||
std::vector < Data > leafData;
|
||||
std::vector < Data* > updateQueue;
|
||||
std::vector < Data* > limbo;
|
||||
|
||||
std::map< const ICustomBody*, unsigned int > mapReferences;
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
@ -79,9 +81,13 @@ namespace
|
|||
|
||||
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() );
|
||||
|
||||
protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz );
|
||||
protoState.ApplyImpulse( bounce.xyz - friction.xyz, worldPointOfContact.xyz, normal.xyz );
|
||||
proto->SetState( protoState );
|
||||
|
||||
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 )
|
||||
{
|
||||
//! @todo TODO: implement stub
|
||||
return true;
|
||||
return this->worldScene.IsInLimbo( objRef );
|
||||
}
|
||||
|
||||
void API_Impl::MoveToLimbo( const ICustomBody* objRef )
|
||||
{
|
||||
/** @todo TODO: Fix this function.*/
|
||||
this->worldScene.MoveToLimbo( 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 )
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
} }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
} }
|
|
@ -9,35 +9,48 @@
|
|||
#include "OysterMath.h"
|
||||
#include "ICollideable.h"
|
||||
|
||||
namespace Oyster { namespace Collision3D
|
||||
namespace Oyster
|
||||
{
|
||||
class Box : public ICollideable
|
||||
namespace Collision3D
|
||||
{
|
||||
public:
|
||||
union
|
||||
class Box : public ICollideable
|
||||
{
|
||||
struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; };
|
||||
struct
|
||||
public:
|
||||
union
|
||||
{
|
||||
::Oyster::Math::Float4 xAxis;
|
||||
::Oyster::Math::Float4 yAxis;
|
||||
::Oyster::Math::Float4 zAxis;
|
||||
struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; };
|
||||
struct
|
||||
{
|
||||
::Oyster::Math::Float4 xAxis;
|
||||
::Oyster::Math::Float4 yAxis;
|
||||
::Oyster::Math::Float4 zAxis;
|
||||
};
|
||||
char byte[sizeof(::Oyster::Math::Float4x4) + 2*sizeof(::Oyster::Math::Float4)];
|
||||
};
|
||||
char byte[sizeof(::Oyster::Math::Float4x4) + 2*sizeof(::Oyster::Math::Float4)];
|
||||
|
||||
Box( );
|
||||
Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &size );
|
||||
Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float4 &worldPos, const ::Oyster::Math::Float4 &size );
|
||||
virtual ~Box( );
|
||||
|
||||
Box & operator = ( const Box &box );
|
||||
|
||||
virtual ::Utility::DynamicMemory::UniquePointer<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( );
|
||||
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;
|
||||
};
|
||||
} }
|
||||
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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
} }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
} }
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
} } }
|
|
@ -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
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
} }
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
} }
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
} }
|
||||
|
||||
|
|
|
@ -49,13 +49,13 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength )
|
|||
{ // by Dan Andersson: Euler leap frog update when Runga Kutta is not needed
|
||||
|
||||
// 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
|
||||
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
|
||||
|
@ -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 )
|
||||
{ // by Dan Andersson
|
||||
Float3 worldOffset = atWorldPos - this->centerPos;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
} }
|
|
@ -9,29 +9,42 @@
|
|||
#include "OysterMath.h"
|
||||
#include "ICollideable.h"
|
||||
|
||||
namespace Oyster { namespace Collision3D
|
||||
namespace Oyster
|
||||
{
|
||||
class Sphere : public ICollideable
|
||||
namespace Collision3D
|
||||
{
|
||||
public:
|
||||
union
|
||||
class Sphere : public ICollideable
|
||||
{
|
||||
struct{ ::Oyster::Math::Float4 center; ::Oyster::Math::Float radius; };
|
||||
char byte[sizeof(::Oyster::Math::Float4) + sizeof(::Oyster::Math::Float)];
|
||||
public:
|
||||
union
|
||||
{
|
||||
struct{ ::Oyster::Math::Float4 center; ::Oyster::Math::Float radius; };
|
||||
char byte[sizeof(::Oyster::Math::Float4) + sizeof(::Oyster::Math::Float)];
|
||||
};
|
||||
|
||||
Sphere( );
|
||||
Sphere( const ::Oyster::Math::Float3 ¢er, const ::Oyster::Math::Float &radius );
|
||||
Sphere( const ::Oyster::Math::Float4 ¢er, const ::Oyster::Math::Float &radius );
|
||||
virtual ~Sphere( );
|
||||
|
||||
Sphere & operator = ( const Sphere &sphere );
|
||||
|
||||
virtual ::Utility::DynamicMemory::UniquePointer<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( );
|
||||
Sphere( const ::Oyster::Math::Float3 ¢er, const ::Oyster::Math::Float &radius );
|
||||
Sphere( const ::Oyster::Math::Float4 ¢er, const ::Oyster::Math::Float &radius );
|
||||
virtual ~Sphere( );
|
||||
|
||||
Sphere & operator = ( const Sphere &sphere );
|
||||
|
||||
virtual ::Utility::DynamicMemory::UniquePointer<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;
|
||||
};
|
||||
} }
|
||||
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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
} }
|
||||
|
||||
|
|
Loading…
Reference in New Issue