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.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 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
} }
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
} } }
|
} } }
|
|
@ -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
|
|
@ -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">
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
} }
|
|
@ -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 ¢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( );
|
namespace Math
|
||||||
Sphere( const ::Oyster::Math::Float3 ¢er, const ::Oyster::Math::Float &radius );
|
{
|
||||||
Sphere( const ::Oyster::Math::Float4 ¢er, 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
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue