diff --git a/Code/GamePhysics/GamePhysics.vcxproj b/Code/GamePhysics/GamePhysics.vcxproj
index 06e64fd1..1abcc6f8 100644
--- a/Code/GamePhysics/GamePhysics.vcxproj
+++ b/Code/GamePhysics/GamePhysics.vcxproj
@@ -166,6 +166,8 @@
+
+
diff --git a/Code/GamePhysics/GamePhysics.vcxproj.filters b/Code/GamePhysics/GamePhysics.vcxproj.filters
index 15221691..aa3cbd73 100644
--- a/Code/GamePhysics/GamePhysics.vcxproj.filters
+++ b/Code/GamePhysics/GamePhysics.vcxproj.filters
@@ -42,6 +42,12 @@
Header Files\Include
+
+ Header Files\Include
+
+
+ Header Files\Include
+
diff --git a/Code/GamePhysics/Implementation/Octree.cpp b/Code/GamePhysics/Implementation/Octree.cpp
index b841b49d..a1ccdbd8 100644
--- a/Code/GamePhysics/Implementation/Octree.cpp
+++ b/Code/GamePhysics/Implementation/Octree.cpp
@@ -31,6 +31,7 @@ Octree& Octree::operator=(const Octree& orig)
void Octree::AddObject(UniquePointer< ICustomBody > customBodyRef)
{
+ customBodyRef->SetScene( this );
Data data;
//Data* tempPtr = this->worldNode.dataPtr;
diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp
index 46b3369c..f917407b 100644
--- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp
+++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp
@@ -4,10 +4,10 @@
#include "SphericalRigidBody.h"
using namespace ::Oyster::Physics;
-using namespace ::Oyster::Physics3D;
using namespace ::Oyster::Math;
using namespace ::Oyster::Collision3D;
using namespace ::Utility::DynamicMemory;
+using namespace ::Utility::Value;
API_Impl API_instance;
@@ -18,40 +18,70 @@ namespace
auto proto = worldScene.GetCustomBody( protoTempRef );
auto deuter = worldScene.GetCustomBody( deuterTempRef );
- float deltaWhen;
- Float3 worldWhere;
- if( proto->Intersects(*deuter, 1.0f, deltaWhen, worldWhere) )
+ Float4 worldPointOfContact;
+ if( proto->Intersects(*deuter, worldPointOfContact) )
{
- proto->CallSubscription( proto, deuter );
+ switch( proto->CallSubscription(proto, deuter) )
+ {
+ case ICustomBody::SubscriptMessage_ignore_collision_response:
+ break;
+ default:
+ { // Apply CollisionResponse in pure gather pattern
+ ICustomBody::State protoState; proto->GetState( protoState );
+ ICustomBody::State deuterState; deuter->GetState( deuterState );
+
+ Float4 protoG = protoState.GetLinearMomentum( worldPointOfContact ),
+ deuterG = deuterState.GetLinearMomentum( worldPointOfContact );
+
+ // calc from perspective of deuter
+ Float4 normal; deuter->GetNormalAt( worldPointOfContact, normal );
+ Float protoG_Magnitude = protoG.Dot( normal ),
+ deuterG_Magnitude = deuterG.Dot( normal );
+
+ // bounce
+ Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(),
+ deuterState.GetMass(), deuterG_Magnitude,
+ protoState.GetMass(), protoG_Magnitude );
+
+ //sumJ -= Formula::CollisionResponse::Friction( impulse, normal,
+ // protoState.GetLinearMomentum(), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(),
+ // deuterState.GetLinearMomentum(), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass());
+
+ // calc from perspective of proto
+ proto->GetNormalAt( worldPointOfContact, normal );
+ protoG_Magnitude = protoG.Dot( normal ),
+ deuterG_Magnitude = deuterG.Dot( normal );
+
+ // bounce
+ Float4 bounceP = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(),
+ protoState.GetMass(), protoG_Magnitude,
+ deuterState.GetMass(), deuterG_Magnitude );
+
+ Float4 bounce = Average( bounceD, bounceP );
+ //Float4 bounce = bounceD + bounceP;
+
+ // FRICTION
+ // Apply
+ //sumJ += ( 1 / deuterState.GetMass() )*frictionImpulse;
+ // FRICTION END
+
+ Float4 forwardedDeltaPos, forwardedDeltaAxis;
+ { // @todo TODO: is this right?
+ Float4 bounceAngularImpulse = ::Oyster::Math::Float4( (worldPointOfContact - protoState.GetCenterPosition()).xyz.Cross(bounce.xyz), 0.0f ),
+ bounceLinearImpulse = bounce - bounceAngularImpulse;
+ proto->Predict( forwardedDeltaPos, forwardedDeltaAxis, bounceLinearImpulse, bounceAngularImpulse, API_instance.GetFrameTimeLength() );
+ }
+
+ protoState.ApplyForwarding( forwardedDeltaPos, forwardedDeltaAxis );
+ protoState.ApplyImpulse( bounce, worldPointOfContact, normal );
+ proto->SetState( protoState );
+ }
+ break;
+ }
}
}
}
-Float4x4 & MomentOfInertia::CreateSphereMatrix( const Float mass, const Float radius, ::Oyster::Math::Float4x4 &targetMem )
-{
- return targetMem = Formula::MomentOfInertia::Sphere(mass, radius);
-}
-
-Float4x4 & MomentOfInertia::CreateHollowSphereMatrix( const Float mass, const Float radius, ::Oyster::Math::Float4x4 &targetMem )
-{
- return targetMem = Formula::MomentOfInertia::HollowSphere(mass, radius);
-}
-
-Float4x4 & MomentOfInertia::CreateCuboidMatrix( const Float mass, const Float height, const Float width, const Float depth, ::Oyster::Math::Float4x4 &targetMem )
-{
- return targetMem = Formula::MomentOfInertia::Cuboid(mass, height, width, depth);
-}
-
-Float4x4 & MomentOfInertia::CreateCylinderMatrix( const Float mass, const Float height, const Float radius, ::Oyster::Math::Float4x4 &targetMem )
-{
- return targetMem = Formula::MomentOfInertia::Cylinder(mass, height, radius);
-}
-
-Float4x4 & MomentOfInertia::CreateRodMatrix( const Float mass, const Float length, ::Oyster::Math::Float4x4 &targetMem )
-{
- return targetMem = Formula::MomentOfInertia::RodCenter(mass, length);
-}
-
API & API::Instance()
{
return API_instance;
@@ -95,12 +125,23 @@ void API_Impl::SetSubscription( API::EventAction_Destruction functionPointer )
}
}
+float API_Impl::GetFrameTimeLength() const
+{
+ return this->updateFrameLength;
+}
+
void API_Impl::Update()
{ /** @todo TODO: Update is a temporary solution .*/
+
+
+
::std::vector updateList;
auto proto = this->worldScene.Sample( Universe(), updateList ).begin();
for( ; proto != updateList.end(); ++proto )
{
+ // Step 1: @todo TODO: Apply Gravity
+
+ // Step 2: Apply Collision Response
this->worldScene.Visit( *proto, OnPossibleCollision );
}
@@ -151,101 +192,91 @@ void API_Impl::DestroyObject( const ICustomBody* objRef )
}
}
-void API_Impl::ApplyForceAt( const ICustomBody* objRef, const Float3 &worldPos, const Float3 &worldF )
-{
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- //this->worldScene.GetCustomBody( tempRef )->Apply //!< @todo TODO: need function
- this->worldScene.SetAsAltered( tempRef );
- }
-}
-
-void API_Impl::ApplyCollisionResponse( const ICustomBody* objRefA, const ICustomBody* objRefB, Float &deltaWhen, Float3 &worldPointOfContact )
-{
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRefA );
- if( tempRef != this->worldScene.invalid_ref )
- {
- //! @todo TODO: implement stub
- this->worldScene.SetAsAltered( tempRef );
- }
-}
-
-void API_Impl::SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const Float4x4 &localI )
-{ // deprecated
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepVelocity( localI );
- }
-}
-
-void API_Impl::SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const Float4x4 &localI )
-{ // deprecated
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepMomentum( localI );
- }
-}
-
-void API_Impl::SetMass_KeepVelocity( const ICustomBody* objRef, Float m )
-{ // deprecated
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- this->worldScene.GetCustomBody( tempRef )->SetMass_KeepVelocity( m );
- }
-}
-
-void API_Impl::SetMass_KeepMomentum( const ICustomBody* objRef, Float m )
-{ // deprecated
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- this->worldScene.GetCustomBody( tempRef )->SetMass_KeepMomentum( m );
- }
-}
-
-void API_Impl::SetCenter( const ICustomBody* objRef, const Float3 &worldPos )
-{
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- //this->worldScene.GetCustomBody( tempRef )->Set //!< @todo TODO: need function
- this->worldScene.EvaluatePosition( tempRef );
- }
-}
-
-void API_Impl::SetRotation( const ICustomBody* objRef, const Float4x4 &rotation )
-{
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- this->worldScene.GetCustomBody( tempRef )->SetRotation( rotation );
- this->worldScene.EvaluatePosition( tempRef );
- }
-}
-
-void API_Impl::SetOrientation( const ICustomBody* objRef, const Float4x4 &orientation )
-{
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- this->worldScene.GetCustomBody( tempRef )->SetOrientation( orientation );
- this->worldScene.EvaluatePosition( tempRef );
- }
-}
-
-void API_Impl::SetSize( const ICustomBody* objRef, const Float3 &size )
-{
- unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
- if( tempRef != this->worldScene.invalid_ref )
- {
- this->worldScene.GetCustomBody( tempRef )->SetSize( size );
- this->worldScene.EvaluatePosition( tempRef );
- }
-}
+//void API_Impl::ApplyForceAt( const ICustomBody* objRef, const Float3 &worldPos, const Float3 &worldF )
+//{
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// //this->worldScene.GetCustomBody( tempRef )->Apply //!< @todo TODO: need function
+// this->worldScene.SetAsAltered( tempRef );
+// }
+//}
+//
+//void API_Impl::SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const Float4x4 &localI )
+//{ // deprecated
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepVelocity( localI );
+// }
+//}
+//
+//void API_Impl::SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const Float4x4 &localI )
+//{ // deprecated
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepMomentum( localI );
+// }
+//}
+//
+//void API_Impl::SetMass_KeepVelocity( const ICustomBody* objRef, Float m )
+//{ // deprecated
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// this->worldScene.GetCustomBody( tempRef )->SetMass_KeepVelocity( m );
+// }
+//}
+//
+//void API_Impl::SetMass_KeepMomentum( const ICustomBody* objRef, Float m )
+//{ // deprecated
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// this->worldScene.GetCustomBody( tempRef )->SetMass_KeepMomentum( m );
+// }
+//}
+//
+//void API_Impl::SetCenter( const ICustomBody* objRef, const Float3 &worldPos )
+//{
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// //this->worldScene.GetCustomBody( tempRef )->Set //!< @todo TODO: need function
+// this->worldScene.EvaluatePosition( tempRef );
+// }
+//}
+//
+//void API_Impl::SetRotation( const ICustomBody* objRef, const Float4x4 &rotation )
+//{
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// this->worldScene.GetCustomBody( tempRef )->SetRotation( rotation );
+// this->worldScene.EvaluatePosition( tempRef );
+// }
+//}
+//
+//void API_Impl::SetOrientation( const ICustomBody* objRef, const Float4x4 &orientation )
+//{
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// this->worldScene.GetCustomBody( tempRef )->SetOrientation( orientation );
+// this->worldScene.EvaluatePosition( tempRef );
+// }
+//}
+//
+//void API_Impl::SetSize( const ICustomBody* objRef, const Float3 &size )
+//{
+// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
+// if( tempRef != this->worldScene.invalid_ref )
+// {
+// this->worldScene.GetCustomBody( tempRef )->SetSize( size );
+// this->worldScene.EvaluatePosition( tempRef );
+// }
+//}
UniquePointer API_Impl::CreateRigidBody( const API::SimpleBodyDescription &desc ) const
{
diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h
index 5de9c05a..0c08bf11 100644
--- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h
+++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h
@@ -20,6 +20,8 @@ namespace Oyster
void SetGravityConstant( float g );
void SetSubscription( EventAction_Destruction functionPointer );
+ float GetFrameTimeLength() const;
+
void Update();
bool IsInLimbo( const ICustomBody* objRef );
@@ -30,17 +32,16 @@ namespace Oyster
::Utility::DynamicMemory::UniquePointer ExtractObject( const ICustomBody* objRef );
void DestroyObject( const ICustomBody* objRef );
- void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF );
- void ApplyCollisionResponse( const ICustomBody* objRefA, const ICustomBody* objRefB, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact );
+ //void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF );
- void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI );
- void SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI );
- void SetMass_KeepVelocity( const ICustomBody* objRef, ::Oyster::Math::Float m );
- void SetMass_KeepMomentum( const ICustomBody* objRef, ::Oyster::Math::Float m );
- void SetCenter( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos );
- void SetRotation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &rotation );
- void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation );
- void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size );
+ //void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI );
+ //void SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI );
+ //void SetMass_KeepVelocity( const ICustomBody* objRef, ::Oyster::Math::Float m );
+ //void SetMass_KeepMomentum( const ICustomBody* objRef, ::Oyster::Math::Float m );
+ //void SetCenter( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos );
+ //void SetRotation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &rotation );
+ //void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation );
+ //void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size );
::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SimpleBodyDescription &desc ) const;
::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SphericalBodyDescription &desc ) const;
diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp
index 80e352ea..09855984 100644
--- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp
+++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp
@@ -8,19 +8,59 @@ using namespace ::Oyster::Collision3D;
using namespace ::Utility::DynamicMemory;
using namespace ::Utility::Value;
+namespace Private
+{
+ const Float epsilon = (const Float)1e-20;
+
+ // Float calculations can suffer roundingerrors. Which is where epsilon = 1e-20 comes into the picture
+ inline bool EqualsZero( const Float &value )
+ { // by Dan Andersson
+ return Abs( value ) < epsilon;
+ }
+
+ inline bool Contains( const Plane &container, const Float4 &pos )
+ { // by Dan Andersson
+ return EqualsZero( container.normal.Dot( pos ) + container.phasing );
+ }
+
+ // revision of Ray Vs Plane intersect test, there ray is more of an axis
+ bool Intersects( const Ray &axis, const Plane &plane, Float &connectDistance )
+ { // by Dan Andersson
+ Float c = plane.normal.Dot(axis.direction);
+ if( EqualsZero(c) )
+ { // axis is parallell with the plane. (axis direction orthogonal with the planar normal)
+ connectDistance = 0.0f;
+ return Contains( plane, axis.origin );
+ }
+
+ connectDistance = -plane.phasing;
+ connectDistance -= plane.normal.Dot( axis.origin );
+ connectDistance /= c;
+
+ return true;
+ }
+}
+
SimpleRigidBody::SimpleRigidBody()
{
- this->rigid = RigidBody( Box(Float4x4::identity, Float3::null, Float3(1.0f)), 16.0f, Float4x4::identity );
+ this->rigid = RigidBody();
+ this->rigid.SetMass_KeepMomentum( 16.0f );
this->gravityNormal = Float3::null;
this->collisionAction = Default::EventAction_Collision;
- this->ignoreGravity = false;
+ this->ignoreGravity = this->isForwarded = false;
+ this->scene = nullptr;
}
SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc )
{
- this->rigid = RigidBody( Box( desc.rotation, desc.centerPosition, desc.size ),
- desc.mass,
- desc.inertiaTensor );
+ this->rigid.SetRotation( desc.rotation );
+ this->rigid.centerPos = desc.centerPosition;
+ this->rigid.SetSize( desc.size );
+ this->rigid.SetMass_KeepMomentum( desc.mass );
+ this->rigid.SetMomentOfInertia_KeepMomentum( desc.inertiaTensor );
+ this->deltaPos = Float4::null;
+ this->deltaAxis = Float4::null;
+
this->gravityNormal = Float3::null;
if( desc.subscription )
@@ -33,6 +73,7 @@ SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc )
}
this->ignoreGravity = desc.ignoreGravity;
+ this->scene = nullptr;
}
SimpleRigidBody::~SimpleRigidBody() {}
@@ -44,24 +85,60 @@ UniquePointer SimpleRigidBody::Clone() const
SimpleRigidBody::State SimpleRigidBody::GetState() const
{
- return State( this->rigid.box.boundingOffset, this->rigid.box.center, AngularAxis(this->rigid.box.rotation).xyz );
+ return State( this->rigid.GetMass(), this->rigid.restitutionCoeff,
+ this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic,
+ this->rigid.GetMomentOfInertia(), this->rigid.boundingReach,
+ this->rigid.centerPos, this->rigid.axis,
+ this->rigid.momentum_Linear, this->rigid.momentum_Angular );
}
SimpleRigidBody::State & SimpleRigidBody::GetState( SimpleRigidBody::State &targetMem ) const
{
- return targetMem = State( this->rigid.box.boundingOffset, this->rigid.box.center, AngularAxis(this->rigid.box.rotation).xyz );
+ return targetMem = State( this->rigid.GetMass(), this->rigid.restitutionCoeff,
+ this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic,
+ this->rigid.GetMomentOfInertia(), this->rigid.boundingReach,
+ this->rigid.centerPos, this->rigid.axis,
+ this->rigid.momentum_Linear, this->rigid.momentum_Angular );
}
void SimpleRigidBody::SetState( const SimpleRigidBody::State &state )
-{ /** @todo TODO: temporary solution! Need to know it's occtree */
- this->rigid.box.boundingOffset = state.GetReach();
- this->rigid.box.center = state.GetCenterPosition();
- this->rigid.box.rotation = state.GetRotation();
+{
+ this->rigid.centerPos = state.GetCenterPosition();
+ this->rigid.SetRotation( state.GetRotation() );
+ this->rigid.boundingReach = state.GetReach();
+ this->rigid.momentum_Linear = state.GetLinearMomentum();
+ this->rigid.momentum_Angular = state.GetAngularMomentum();
+ this->rigid.impulse_Linear += state.GetLinearImpulse();
+ this->rigid.impulse_Angular += state.GetAngularImpulse();
+ this->rigid.restitutionCoeff = state.GetRestitutionCoeff();
+ this->rigid.frictionCoeff_Static = state.GetFrictionCoeff_Static();
+ this->rigid.frictionCoeff_Kinetic = state.GetFrictionCoeff_Kinetic();
+
+ if( state.IsForwarded() )
+ {
+ this->deltaPos += state.GetForward_DeltaPos();
+ this->deltaAxis += state.GetForward_DeltaAxis();
+ this->isForwarded;
+ }
+
+ if( this->scene )
+ {
+ if( state.IsSpatiallyAltered() )
+ {
+ unsigned int tempRef = this->scene->GetTemporaryReferenceOf( this );
+ this->scene->SetAsAltered( tempRef );
+ this->scene->EvaluatePosition( tempRef );
+ }
+ else if( state.IsDisturbed() )
+ {
+ this->scene->SetAsAltered( this->scene->GetTemporaryReferenceOf(this) );
+ }
+ }
}
-void SimpleRigidBody::CallSubscription( const ICustomBody *proto, const ICustomBody *deuter )
+ICustomBody::SubscriptMessage SimpleRigidBody::CallSubscription( const ICustomBody *proto, const ICustomBody *deuter )
{
- this->collisionAction( proto, deuter );
+ return this->collisionAction( proto, deuter );
}
bool SimpleRigidBody::IsAffectedByGravity() const
@@ -69,34 +146,76 @@ bool SimpleRigidBody::IsAffectedByGravity() const
return !this->ignoreGravity;
}
-bool SimpleRigidBody::Intersects( const ICustomBody &object, Float timeStepLength, Float &deltaWhen, Float3 &worldPointOfContact ) const
-{
- if( object.Intersects(this->rigid.box) )
- { //! @todo TODO: better implementation needed
- deltaWhen = timeStepLength;
- worldPointOfContact = Average( this->rigid.box.center, object.GetCenter() );
- return true;
- }
- else
- {
- return false;
- }
-}
-
bool SimpleRigidBody::Intersects( const ICollideable &shape ) const
{
- return this->rigid.box.Intersects( shape );
+ return Box( this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize() ).Intersects( shape );
+}
+
+bool SimpleRigidBody::Intersects( const ICollideable &shape, Float4 &worldPointOfContact ) const
+{
+ return Box( this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize() ).Intersects( shape, worldPointOfContact );
+}
+
+bool SimpleRigidBody::Intersects( const ICustomBody &object, Float4 &worldPointOfContact ) const
+{
+ return object.Intersects( Box(this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize()), worldPointOfContact );
}
Sphere & SimpleRigidBody::GetBoundingSphere( Sphere &targetMem ) const
{
- return targetMem = Sphere( this->rigid.box.center, this->rigid.box.boundingOffset.GetMagnitude() );
+ return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.GetMagnitude() );
}
-Float3 & SimpleRigidBody::GetNormalAt( const Float3 &worldPos, Float3 &targetMem ) const
+Float4 & SimpleRigidBody::GetNormalAt( const Float4 &worldPos, Float4 &targetMem ) const
{
- //! @todo TODO: better implementation needed
- return targetMem = (worldPos - this->rigid.box.center).GetNormalized();
+ Float4 offset = worldPos - this->rigid.centerPos;
+ Float distance = offset.Dot( offset );
+ Float3 normal = Float3::null;
+
+ if( distance != 0.0f )
+ { // sanity check
+ Ray axis( Float4::standard_unit_w, offset / (Float)::std::sqrt(distance) );
+ Float minDistance = numeric_limits::max();
+ Float4x4 rotationMatrix = this->rigid.GetRotationMatrix();
+
+ if( Private::Intersects(axis, Plane(rotationMatrix.v[0], -this->rigid.boundingReach.x), axis.collisionDistance) )
+ { // check along x-axis
+ if( axis.collisionDistance < 0.0f )
+ normal = -rotationMatrix.v[0].xyz;
+ else
+ normal = rotationMatrix.v[0].xyz;
+
+ minDistance = Abs( axis.collisionDistance );
+ }
+
+ if( Private::Intersects(axis, Plane(rotationMatrix.v[1], -this->rigid.boundingReach.y), axis.collisionDistance) )
+ { // check along y-axis
+ distance = Abs( axis.collisionDistance ); // recycling memory
+ if( minDistance > distance )
+ {
+ if( axis.collisionDistance < 0.0f )
+ normal = -rotationMatrix.v[1].xyz;
+ else
+ normal = rotationMatrix.v[1].xyz;
+
+ minDistance = distance;
+ }
+ }
+
+ if( Private::Intersects(axis, Plane(rotationMatrix.v[2], -this->rigid.boundingReach.z), axis.collisionDistance) )
+ { // check along z-axis
+ if( minDistance > Abs( axis.collisionDistance ) )
+ {
+ if( axis.collisionDistance < 0.0f )
+ normal = -rotationMatrix.v[2].xyz;
+ else
+ normal = rotationMatrix.v[2].xyz;
+ }
+ }
+ }
+ targetMem.xyz = normal;
+ targetMem.w = 0.0f;
+ return targetMem;
}
Float3 & SimpleRigidBody::GetGravityNormal( Float3 &targetMem ) const
@@ -104,41 +223,59 @@ Float3 & SimpleRigidBody::GetGravityNormal( Float3 &targetMem ) const
return targetMem = this->gravityNormal;
}
-Float3 & SimpleRigidBody::GetCenter( Float3 &targetMem ) const
-{
- return targetMem = this->rigid.box.center;
-}
+//Float3 & SimpleRigidBody::GetCenter( Float3 &targetMem ) const
+//{
+// return targetMem = this->rigid.centerPos;
+//}
+//
+//Float4x4 & SimpleRigidBody::GetRotation( Float4x4 &targetMem ) const
+//{
+// return targetMem = this->rigid.box.rotation;
+//}
+//
+//Float4x4 & SimpleRigidBody::GetOrientation( Float4x4 &targetMem ) const
+//{
+// return targetMem = this->rigid.GetOrientation();
+//}
+//
+//Float4x4 & SimpleRigidBody::GetView( Float4x4 &targetMem ) const
+//{
+// return targetMem = this->rigid.GetView();
+//}
-Float4x4 & SimpleRigidBody::GetRotation( Float4x4 &targetMem ) const
-{
- return targetMem = this->rigid.box.rotation;
-}
-
-Float4x4 & SimpleRigidBody::GetOrientation( Float4x4 &targetMem ) const
-{
- return targetMem = this->rigid.GetOrientation();
-}
-
-Float4x4 & SimpleRigidBody::GetView( Float4x4 &targetMem ) const
-{
- return targetMem = this->rigid.GetView();
-}
-
-Float3 SimpleRigidBody::GetRigidLinearVelocity() const
-{
- return this->rigid.GetLinearVelocity();
-}
+//Float3 SimpleRigidBody::GetRigidLinearVelocity() const
+//{
+// return this->rigid.GetLinearVelocity();
+//}
UpdateState SimpleRigidBody::Update( Float timeStepLength )
{
+ if( this->isForwarded )
+ {
+ this->rigid.Move( this->deltaPos, this->deltaAxis );
+ this->deltaPos = Float4::null;
+ this->deltaAxis = Float4::null;
+ this->isForwarded = false;
+ }
+
this->rigid.Update_LeapFrog( timeStepLength );
- // compare previous and new state and return result
+ //! @todo TODO: compare previous and new state and return result
//return this->current == this->previous ? UpdateState_resting : UpdateState_altered;
return UpdateState_altered;
}
+void SimpleRigidBody::Predict( Float4 &outDeltaPos, Float4 &outDeltaAxis, const Float4 &actingLinearImpulse, const Float4 &actingAngularImpulse, Float deltaTime )
+{
+ this->rigid.Predict_LeapFrog( outDeltaPos, outDeltaAxis, actingLinearImpulse, actingAngularImpulse, deltaTime );
+}
+
+void SimpleRigidBody::SetScene( void *scene )
+{
+ this->scene = (Octree*)scene;
+}
+
void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_Collision functionPointer )
{
if( functionPointer )
@@ -162,47 +299,47 @@ void SimpleRigidBody::SetGravityNormal( const Float3 &normalizedVector )
this->gravityNormal = normalizedVector;
}
-void SimpleRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI )
-{
- this->rigid.SetMomentOfInertia_KeepVelocity( localI );
-}
-
-void SimpleRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI )
-{
- this->rigid.SetMomentOfInertia_KeepMomentum( localI );
-}
-
-void SimpleRigidBody::SetMass_KeepVelocity( Float m )
-{
- this->rigid.SetMass_KeepVelocity( m );
-}
-
-void SimpleRigidBody::SetMass_KeepMomentum( Float m )
-{
- this->rigid.SetMass_KeepMomentum( m );
-}
-
-void SimpleRigidBody::SetCenter( const Float3 &worldPos )
-{
- this->rigid.SetCenter( worldPos );
-}
-
-void SimpleRigidBody::SetRotation( const Float4x4 &rotation )
-{
- this->rigid.SetRotation( rotation );
-}
-
-void SimpleRigidBody::SetOrientation( const Float4x4 &orientation )
-{
- this->rigid.SetOrientation( orientation );
-}
-
-void SimpleRigidBody::SetSize( const Float3 &size )
-{
- this->rigid.SetSize( size );
-}
-
-void SimpleRigidBody::SetMomentum( const Float3 &worldG )
-{
- this->rigid.SetLinearMomentum( worldG );
-}
\ No newline at end of file
+//void SimpleRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI )
+//{
+// this->rigid.SetMomentOfInertia_KeepVelocity( localI );
+//}
+//
+//void SimpleRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI )
+//{
+// this->rigid.SetMomentOfInertia_KeepMomentum( localI );
+//}
+//
+//void SimpleRigidBody::SetMass_KeepVelocity( Float m )
+//{
+// this->rigid.SetMass_KeepVelocity( m );
+//}
+//
+//void SimpleRigidBody::SetMass_KeepMomentum( Float m )
+//{
+// this->rigid.SetMass_KeepMomentum( m );
+//}
+//
+//void SimpleRigidBody::SetCenter( const Float3 &worldPos )
+//{
+// this->rigid.SetCenter( worldPos );
+//}
+//
+//void SimpleRigidBody::SetRotation( const Float4x4 &rotation )
+//{
+// this->rigid.SetRotation( rotation );
+//}
+//
+//void SimpleRigidBody::SetOrientation( const Float4x4 &orientation )
+//{
+// this->rigid.SetOrientation( orientation );
+//}
+//
+//void SimpleRigidBody::SetSize( const Float3 &size )
+//{
+// this->rigid.SetSize( size );
+//}
+//
+//void SimpleRigidBody::SetMomentum( const Float3 &worldG )
+//{
+// this->rigid.SetLinearMomentum( worldG );
+//}
diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h
index 9eefeb48..618e0235 100644
--- a/Code/GamePhysics/Implementation/SimpleRigidBody.h
+++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h
@@ -3,6 +3,7 @@
#include "..\PhysicsAPI.h"
#include "RigidBody.h"
+#include "Octree.h"
namespace Oyster { namespace Physics
{
@@ -18,41 +19,46 @@ namespace Oyster { namespace Physics
State GetState() const;
State & GetState( State &targetMem ) const;
void SetState( const State &state );
- ::Oyster::Math::Float3 GetRigidLinearVelocity() const;
+ //::Oyster::Math::Float3 GetRigidLinearVelocity() const;
- void CallSubscription( const ICustomBody *proto, const ICustomBody *deuter );
+ SubscriptMessage CallSubscription( const ICustomBody *proto, const ICustomBody *deuter );
bool IsAffectedByGravity() const;
- bool Intersects( const ICustomBody &object, ::Oyster::Math::Float timeStepLength, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact ) const;
bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const;
+ bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const;
+ bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const;
::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const;
- ::Oyster::Math::Float3 & GetNormalAt( const ::Oyster::Math::Float3 &worldPos, ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) 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 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const;
- ::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
- ::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
- ::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
+ //::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const;
+ //::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
+ //::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
+ //::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
UpdateState Update( ::Oyster::Math::Float timeStepLength );
+ void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime );
+ void SetScene( void *scene );
void SetSubscription( EventAction_Collision functionPointer );
void SetGravity( bool ignore);
void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector );
- void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI );
- void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI );
- void SetMass_KeepVelocity( ::Oyster::Math::Float m );
- void SetMass_KeepMomentum( ::Oyster::Math::Float m );
- void SetCenter( const ::Oyster::Math::Float3 &worldPos );
- void SetRotation( const ::Oyster::Math::Float4x4 &rotation );
- void SetOrientation( const ::Oyster::Math::Float4x4 &orientation );
- void SetSize( const ::Oyster::Math::Float3 &size );
- void SetMomentum( const ::Oyster::Math::Float3 &worldG );
+ //void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI );
+ //void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI );
+ //void SetMass_KeepVelocity( ::Oyster::Math::Float m );
+ //void SetMass_KeepMomentum( ::Oyster::Math::Float m );
+ //void SetCenter( const ::Oyster::Math::Float3 &worldPos );
+ //void SetRotation( const ::Oyster::Math::Float4x4 &rotation );
+ //void SetOrientation( const ::Oyster::Math::Float4x4 &orientation );
+ //void SetSize( const ::Oyster::Math::Float3 &size );
+ //void SetMomentum( const ::Oyster::Math::Float3 &worldG );
private:
::Oyster::Physics3D::RigidBody rigid;
+ ::Oyster::Math::Float4 deltaPos, deltaAxis;
::Oyster::Math::Float3 gravityNormal;
EventAction_Collision collisionAction;
- bool ignoreGravity;
+ Octree *scene;
+ bool ignoreGravity, isForwarded;
};
} }
diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp
index 364d7454..95901763 100644
--- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp
+++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp
@@ -10,18 +10,26 @@ using namespace ::Utility::Value;
SphericalRigidBody::SphericalRigidBody()
{
- this->rigid = RigidBody( Box(Float4x4::identity, Float3::null, Float3(1.0f)), 10.0f, Float4x4::identity );
+ this->rigid = RigidBody();
+ this->rigid.SetMass_KeepMomentum( 10.0f );
this->gravityNormal = Float3::null;
this->collisionAction = Default::EventAction_Collision;
- this->ignoreGravity = false;
+ this->ignoreGravity = this->isForwarded = false;
+ this->scene = nullptr;
this->body = Sphere( Float3::null, 0.5f );
}
SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &desc )
{
- this->rigid = RigidBody( Box( desc.rotation, desc.centerPosition, Float3(2.0f * desc.radius) ),
- desc.mass,
- MomentOfInertia::CreateSphereMatrix( desc.mass, desc.radius ) );
+ this->rigid = RigidBody();
+ 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 );
+ this->rigid.SetMomentOfInertia_KeepMomentum( Formula::MomentOfInertia::CreateSphereMatrix( desc.mass, desc.radius ) );
+ this->deltaPos = Float4::null;
+ this->deltaAxis = Float4::null;
+
this->gravityNormal = Float3::null;
if( desc.subscription )
@@ -34,6 +42,7 @@ SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &des
}
this->ignoreGravity = desc.ignoreGravity;
+ this->scene = nullptr;
this->body = Sphere( desc.centerPosition, desc.radius );
}
@@ -46,24 +55,60 @@ UniquePointer SphericalRigidBody::Clone() const
SphericalRigidBody::State SphericalRigidBody::GetState() const
{
- return State( this->rigid.box.boundingOffset, this->rigid.box.center, AngularAxis(this->rigid.box.rotation).xyz );
+ return State( this->rigid.GetMass(), this->rigid.restitutionCoeff,
+ this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic,
+ this->rigid.GetMomentOfInertia(), this->rigid.boundingReach,
+ this->rigid.centerPos, this->rigid.axis,
+ this->rigid.momentum_Linear, this->rigid.momentum_Angular );
}
SphericalRigidBody::State & SphericalRigidBody::GetState( SphericalRigidBody::State &targetMem ) const
{
- return targetMem = State( this->rigid.box.boundingOffset, this->rigid.box.center, AngularAxis(this->rigid.box.rotation).xyz );
+ return targetMem = State( this->rigid.GetMass(), this->rigid.restitutionCoeff,
+ this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic,
+ this->rigid.GetMomentOfInertia(), this->rigid.boundingReach,
+ this->rigid.centerPos, this->rigid.axis,
+ this->rigid.momentum_Linear, this->rigid.momentum_Angular );
}
void SphericalRigidBody::SetState( const SphericalRigidBody::State &state )
-{ /** @todo TODO: temporary solution! Need to know it's occtree */
- this->rigid.box.boundingOffset = state.GetReach();
- this->rigid.box.center = state.GetCenterPosition();
- this->rigid.box.rotation = state.GetRotation();
+{
+ this->rigid.centerPos = state.GetCenterPosition();
+ this->rigid.SetRotation( state.GetRotation() );
+ this->rigid.boundingReach = state.GetReach();
+ this->rigid.momentum_Linear = state.GetLinearMomentum();
+ this->rigid.momentum_Angular = state.GetAngularMomentum();
+ this->rigid.impulse_Linear += state.GetLinearImpulse();
+ this->rigid.impulse_Angular += state.GetAngularImpulse();
+ this->rigid.restitutionCoeff = state.GetRestitutionCoeff();
+ this->rigid.frictionCoeff_Static = state.GetFrictionCoeff_Static();
+ this->rigid.frictionCoeff_Kinetic = state.GetFrictionCoeff_Kinetic();
+
+ if( state.IsForwarded() )
+ {
+ this->deltaPos += state.GetForward_DeltaPos();
+ this->deltaAxis += state.GetForward_DeltaAxis();
+ this->isForwarded = false;
+ }
+
+ if( this->scene )
+ {
+ if( state.IsSpatiallyAltered() )
+ {
+ unsigned int tempRef = this->scene->GetTemporaryReferenceOf( this );
+ this->scene->SetAsAltered( tempRef );
+ this->scene->EvaluatePosition( tempRef );
+ }
+ else if( state.IsDisturbed() )
+ {
+ this->scene->SetAsAltered( this->scene->GetTemporaryReferenceOf(this) );
+ }
+ }
}
-void SphericalRigidBody::CallSubscription( const ICustomBody *proto, const ICustomBody *deuter )
+ICustomBody::SubscriptMessage SphericalRigidBody::CallSubscription( const ICustomBody *proto, const ICustomBody *deuter )
{
- this->collisionAction( proto, deuter );
+ return this->collisionAction( proto, deuter );
}
bool SphericalRigidBody::IsAffectedByGravity() const
@@ -71,23 +116,19 @@ bool SphericalRigidBody::IsAffectedByGravity() const
return !this->ignoreGravity;
}
-bool SphericalRigidBody::Intersects( const ICustomBody &object, Float timeStepLength, Float &deltaWhen, Float3 &worldPointOfContact ) const
-{
- if( object.Intersects(this->body) )
- { //! @todo TODO: better implementation needed
- deltaWhen = timeStepLength;
- worldPointOfContact = Average( this->body.center, object.GetCenter() );
- return true;
- }
- else
- {
- return false;
- }
-}
-
bool SphericalRigidBody::Intersects( const ICollideable &shape ) const
{
- return this->rigid.box.Intersects( shape );
+ return Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ).Intersects( shape );
+}
+
+bool SphericalRigidBody::Intersects( const ICollideable &shape, Float4 &worldPointOfContact ) const
+{
+ return Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ).Intersects( shape, worldPointOfContact );
+}
+
+bool SphericalRigidBody::Intersects( const ICustomBody &object, Float4 &worldPointOfContact ) const
+{
+ return object.Intersects( Sphere(this->rigid.centerPos, this->rigid.boundingReach.x), worldPointOfContact );
}
Sphere & SphericalRigidBody::GetBoundingSphere( Sphere &targetMem ) const
@@ -95,10 +136,16 @@ Sphere & SphericalRigidBody::GetBoundingSphere( Sphere &targetMem ) const
return targetMem = this->body;
}
-Float3 & SphericalRigidBody::GetNormalAt( const Float3 &worldPos, Float3 &targetMem ) const
+Float4 & SphericalRigidBody::GetNormalAt( const Float4 &worldPos, Float4 &targetMem ) const
{
- //! @todo TODO: better implementation needed
- return targetMem = (worldPos - this->rigid.box.center).GetNormalized();
+ targetMem = worldPos - this->rigid.centerPos;
+ Float magnitude = targetMem.GetMagnitude();
+ if( magnitude != 0.0f )
+ { // sanity check
+ targetMem.Normalize();
+ }
+
+ return targetMem;
}
Float3 & SphericalRigidBody::GetGravityNormal( Float3 &targetMem ) const
@@ -106,41 +153,54 @@ Float3 & SphericalRigidBody::GetGravityNormal( Float3 &targetMem ) const
return targetMem = this->gravityNormal;
}
-Float3 & SphericalRigidBody::GetCenter( Float3 &targetMem ) const
-{
- return targetMem = this->rigid.box.center;
-}
+//Float3 & SphericalRigidBody::GetCenter( Float3 &targetMem ) const
+//{
+// return targetMem = this->rigid.centerPos;
+//}
+//
+//Float4x4 & SphericalRigidBody::GetRotation( Float4x4 &targetMem ) const
+//{
+// return targetMem = this->rigid.box.rotation;
+//}
+//
+//Float4x4 & SphericalRigidBody::GetOrientation( Float4x4 &targetMem ) const
+//{
+// return targetMem = this->rigid.GetOrientation();
+//}
+//
+//Float4x4 & SphericalRigidBody::GetView( Float4x4 &targetMem ) const
+//{
+// return targetMem = this->rigid.GetView();
+//}
-Float4x4 & SphericalRigidBody::GetRotation( Float4x4 &targetMem ) const
-{
- return targetMem = this->rigid.box.rotation;
-}
-
-Float4x4 & SphericalRigidBody::GetOrientation( Float4x4 &targetMem ) const
-{
- return targetMem = this->rigid.GetOrientation();
-}
-
-Float4x4 & SphericalRigidBody::GetView( Float4x4 &targetMem ) const
-{
- return targetMem = this->rigid.GetView();
-}
-
-Float3 SphericalRigidBody::GetRigidLinearVelocity() const
-{
- return this->rigid.GetLinearVelocity();
-}
+//Float3 SphericalRigidBody::GetRigidLinearVelocity() const
+//{
+// return this->rigid.GetLinearVelocity();
+//}
UpdateState SphericalRigidBody::Update( Float timeStepLength )
{
+ if( this->isForwarded )
+ {
+ this->rigid.Move( this->deltaPos, this->deltaAxis );
+ this->deltaPos = Float4::null;
+ this->deltaAxis = Float4::null;
+ this->isForwarded = false;
+ }
+
this->rigid.Update_LeapFrog( timeStepLength );
- this->body.center = this->rigid.GetCenter();
+ this->body.center = this->rigid.centerPos;
// compare previous and new state and return result
//return this->current == this->previous ? UpdateState_resting : UpdateState_altered;
return UpdateState_altered;
}
+void SphericalRigidBody::Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime )
+{
+ this->rigid.Predict_LeapFrog( outDeltaPos, outDeltaAxis, actingLinearImpulse, actingAngularImpulse, deltaTime );
+}
+
void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_Collision functionPointer )
{
if( functionPointer )
@@ -153,7 +213,12 @@ void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_Collision fun
}
}
-void SphericalRigidBody::SetGravity( bool ignore)
+void SphericalRigidBody::SetScene( void *scene )
+{
+ this->scene = (Octree*)scene;
+}
+
+void SphericalRigidBody::SetGravity( bool ignore )
{
this->ignoreGravity = ignore;
this->gravityNormal = Float3::null;
@@ -164,50 +229,50 @@ void SphericalRigidBody::SetGravityNormal( const Float3 &normalizedVector )
this->gravityNormal = normalizedVector;
}
-void SphericalRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI )
-{
- this->rigid.SetMomentOfInertia_KeepVelocity( localI );
-}
-
-void SphericalRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI )
-{
- this->rigid.SetMomentOfInertia_KeepMomentum( localI );
-}
-
-void SphericalRigidBody::SetMass_KeepVelocity( Float m )
-{
- this->rigid.SetMass_KeepVelocity( m );
-}
-
-void SphericalRigidBody::SetMass_KeepMomentum( Float m )
-{
- this->rigid.SetMass_KeepMomentum( m );
-}
-
-void SphericalRigidBody::SetCenter( const Float3 &worldPos )
-{
- this->rigid.SetCenter( worldPos );
- this->body.center = worldPos;
-}
-
-void SphericalRigidBody::SetRotation( const Float4x4 &rotation )
-{
- this->rigid.SetRotation( rotation );
-}
-
-void SphericalRigidBody::SetOrientation( const Float4x4 &orientation )
-{
- this->rigid.SetOrientation( orientation );
- this->body.center = orientation.v[3].xyz;
-}
-
-void SphericalRigidBody::SetSize( const Float3 &size )
-{
- this->rigid.SetSize( size );
- this->body.radius = 0.5f * Min( Min( size.x, size.y ), size.z ); // inline Min( FloatN )?
-}
-
-void SphericalRigidBody::SetMomentum( const Float3 &worldG )
-{
- this->rigid.SetLinearMomentum( worldG );
-}
\ No newline at end of file
+//void SphericalRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI )
+//{
+// this->rigid.SetMomentOfInertia_KeepVelocity( localI );
+//}
+//
+//void SphericalRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI )
+//{
+// this->rigid.SetMomentOfInertia_KeepMomentum( localI );
+//}
+//
+//void SphericalRigidBody::SetMass_KeepVelocity( Float m )
+//{
+// this->rigid.SetMass_KeepVelocity( m );
+//}
+//
+//void SphericalRigidBody::SetMass_KeepMomentum( Float m )
+//{
+// this->rigid.SetMass_KeepMomentum( m );
+//}
+//
+//void SphericalRigidBody::SetCenter( const Float3 &worldPos )
+//{
+// this->rigid.SetCenter( worldPos );
+// this->body.center = worldPos;
+//}
+//
+//void SphericalRigidBody::SetRotation( const Float4x4 &rotation )
+//{
+// this->rigid.SetRotation( rotation );
+//}
+//
+//void SphericalRigidBody::SetOrientation( const Float4x4 &orientation )
+//{
+// this->rigid.SetOrientation( orientation );
+// this->body.center = orientation.v[3].xyz;
+//}
+//
+//void SphericalRigidBody::SetSize( const Float3 &size )
+//{
+// this->rigid.SetSize( size );
+// this->body.radius = 0.5f * Min( Min( size.x, size.y ), size.z ); // inline Min( FloatN )?
+//}
+//
+//void SphericalRigidBody::SetMomentum( const Float3 &worldG )
+//{
+// this->rigid.SetLinearMomentum( worldG );
+//}
diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.h b/Code/GamePhysics/Implementation/SphericalRigidBody.h
index 4d003f99..51d1b998 100644
--- a/Code/GamePhysics/Implementation/SphericalRigidBody.h
+++ b/Code/GamePhysics/Implementation/SphericalRigidBody.h
@@ -4,6 +4,7 @@
#include "..\PhysicsAPI.h"
#include "RigidBody.h"
#include "Sphere.h"
+#include "Octree.h"
namespace Oyster { namespace Physics
{
@@ -19,41 +20,46 @@ namespace Oyster { namespace Physics
State GetState() const;
State & GetState( State &targetMem = State() ) const;
void SetState( const State &state );
- ::Oyster::Math::Float3 GetRigidLinearVelocity() const;
+ //::Oyster::Math::Float3 GetRigidLinearVelocity() const;
- void CallSubscription( const ICustomBody *proto, const ICustomBody *deuter );
+ SubscriptMessage CallSubscription( const ICustomBody *proto, const ICustomBody *deuter );
bool IsAffectedByGravity() const;
- bool Intersects( const ICustomBody &object, ::Oyster::Math::Float timeStepLength, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact ) const;
bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const;
+ bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const;
+ bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const;
::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const;
- ::Oyster::Math::Float3 & GetNormalAt( const ::Oyster::Math::Float3 &worldPos, ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) 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 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const;
- ::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
- ::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
- ::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
+ //::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const;
+ //::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
+ //::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
+ //::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
UpdateState Update( ::Oyster::Math::Float timeStepLength );
+ void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime );
+ void SetScene( void *scene );
void SetSubscription( EventAction_Collision functionPointer );
void SetGravity( bool ignore);
void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector );
- void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI );
- void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI );
- void SetMass_KeepVelocity( ::Oyster::Math::Float m );
- void SetMass_KeepMomentum( ::Oyster::Math::Float m );
- void SetCenter( const ::Oyster::Math::Float3 &worldPos );
- void SetRotation( const ::Oyster::Math::Float4x4 &rotation );
- void SetOrientation( const ::Oyster::Math::Float4x4 &orientation );
- void SetSize( const ::Oyster::Math::Float3 &size );
- void SetMomentum( const ::Oyster::Math::Float3 &worldG );
+ //void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI );
+ //void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI );
+ //void SetMass_KeepVelocity( ::Oyster::Math::Float m );
+ //void SetMass_KeepMomentum( ::Oyster::Math::Float m );
+ //void SetCenter( const ::Oyster::Math::Float3 &worldPos );
+ //void SetRotation( const ::Oyster::Math::Float4x4 &rotation );
+ //void SetOrientation( const ::Oyster::Math::Float4x4 &orientation );
+ //void SetSize( const ::Oyster::Math::Float3 &size );
+ //void SetMomentum( const ::Oyster::Math::Float3 &worldG );
private:
::Oyster::Physics3D::RigidBody rigid;
+ ::Oyster::Math::Float4 deltaPos, deltaAxis;
::Oyster::Math::Float3 gravityNormal;
EventAction_Collision collisionAction;
- bool ignoreGravity;
+ bool ignoreGravity, isForwarded;
+ Octree *scene;
::Oyster::Collision3D::Sphere body;
};
} }
diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h
index 04d0d3f1..0904551d 100644
--- a/Code/GamePhysics/PhysicsAPI.h
+++ b/Code/GamePhysics/PhysicsAPI.h
@@ -35,20 +35,6 @@ namespace Oyster
const float gravity_constant = (const float)6.67284e-11; //!< The _big_G_! ( N(m/kg)^2 ) Used in real gravityforcefields.
}
- class PHYSICS_DLL_USAGE MomentOfInertia
- {
- public:
- static ::Oyster::Math::Float4x4 & CreateSphereMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float radius, ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() );
-
- static ::Oyster::Math::Float4x4 & CreateHollowSphereMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float radius, ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() );
-
- static ::Oyster::Math::Float4x4 & CreateCuboidMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float height, const ::Oyster::Math::Float width, const ::Oyster::Math::Float depth, ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() );
-
- static ::Oyster::Math::Float4x4 & CreateCylinderMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float height, const ::Oyster::Math::Float radius, ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() );
-
- static ::Oyster::Math::Float4x4 & CreateRodMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float length, ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() );
- };
-
class PHYSICS_DLL_USAGE API
{
public:
@@ -138,82 +124,73 @@ namespace Oyster
********************************************************/
virtual void DestroyObject( const ICustomBody* objRef ) = 0;
- /********************************************************
- * Apply force on an object.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param worldPos: Relative to the world origo. (Not relative to object) [m]
- * @param worldF: Vector with the direction and magnitude of the force. [N]
- ********************************************************/
- virtual void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF ) = 0;
+ ///********************************************************
+ // * Apply force on an object.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param worldPos: Relative to the world origo. (Not relative to object) [m]
+ // * @param worldF: Vector with the direction and magnitude of the force. [N]
+ // ********************************************************/
+ //virtual void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF ) = 0;
- /********************************************************
- * Apply force on an object.
- * @param objRefA: A pointer to the ICustomBody representing a physical object.
- * @param objRefB: A pointer to the ICustomBody representing a physical object.
- * @param deltaWhen: The elapsed simulation time since last update frame. [s]
- * @param worldPointOfContact: Point of Collision, relative to the world origo. (Not relative to the objects) [m]
- ********************************************************/
- virtual void ApplyCollisionResponse( const ICustomBody* objRefA, const ICustomBody* objRefB, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact ) = 0;
-
- /********************************************************
- * Sets the MomentOfInertia tensor matrix of an object without changing it's angular velocity.
- * Noticeable effect: The angular momentum will change. Changing the amount of kinetic energy.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param localI: The tensor matrix relative to the axises of the object. @see MomentOfInertia namespace.
- ********************************************************/
- virtual void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ) = 0;
-
- /********************************************************
- * Sets the MomentOfInertia tensor matrix of an object without changing it's angular momentum.
- * Noticeable effect: The angular velocity will change. Can be used to create slow effects.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param localI: The tensor matrix relative to the axises of the object. @see MomentOfInertia namespace.
- ********************************************************/
- virtual void SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ) = 0;
-
- /********************************************************
- * Sets the mass of an object without changing it's linear velocity.
- * Noticeable effect: The linear momentum will change. Changing the amount of kinetic energy.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param m: [kg]
- ********************************************************/
- virtual void SetMass_KeepVelocity( const ICustomBody* objRef, ::Oyster::Math::Float m ) = 0;
-
- /********************************************************
- * Sets the mass of an object without changing it's linear velocity.
- * Noticeable effect: The linear velocity will change. Can be used to create slow effects.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param m: [kg]
- ********************************************************/
- virtual void SetMass_KeepMomentum( const ICustomBody* objRef, ::Oyster::Math::Float m ) = 0;
-
- /********************************************************
- * Instantly moves an object.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param worldPos: Relative to the world origo. (Not relative to object) [m]
- ********************************************************/
- virtual void SetCenter( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos ) = 0;
-
- /********************************************************
- * Instantly redirects object.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param rotation: New rotation.
- ********************************************************/
- virtual void SetRotation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &rotation ) = 0;
-
- /********************************************************
- * Instantly moves and redirects object.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param orientation: New orientation.
- ********************************************************/
- virtual void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation ) = 0;
-
- /********************************************************
- * Resizes the boundingBox.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @param size: New size of this [m]
- ********************************************************/
- virtual void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size ) = 0;
+ ///********************************************************
+ // * Sets the MomentOfInertia tensor matrix of an object without changing it's angular velocity.
+ // * Noticeable effect: The angular momentum will change. Changing the amount of kinetic energy.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param localI: The tensor matrix relative to the axises of the object. @see MomentOfInertia namespace.
+ // ********************************************************/
+ //virtual void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ) = 0;
+ //
+ ///********************************************************
+ // * Sets the MomentOfInertia tensor matrix of an object without changing it's angular momentum.
+ // * Noticeable effect: The angular velocity will change. Can be used to create slow effects.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param localI: The tensor matrix relative to the axises of the object. @see MomentOfInertia namespace.
+ // ********************************************************/
+ //virtual void SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ) = 0;
+ //
+ ///********************************************************
+ // * Sets the mass of an object without changing it's linear velocity.
+ // * Noticeable effect: The linear momentum will change. Changing the amount of kinetic energy.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param m: [kg]
+ // ********************************************************/
+ //virtual void SetMass_KeepVelocity( const ICustomBody* objRef, ::Oyster::Math::Float m ) = 0;
+ //
+ ///********************************************************
+ // * Sets the mass of an object without changing it's linear velocity.
+ // * Noticeable effect: The linear velocity will change. Can be used to create slow effects.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param m: [kg]
+ // ********************************************************/
+ //virtual void SetMass_KeepMomentum( const ICustomBody* objRef, ::Oyster::Math::Float m ) = 0;
+ //
+ ///********************************************************
+ // * Instantly moves an object.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param worldPos: Relative to the world origo. (Not relative to object) [m]
+ // ********************************************************/
+ //virtual void SetCenter( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos ) = 0;
+ //
+ ///********************************************************
+ // * Instantly redirects object.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param rotation: New rotation.
+ // ********************************************************/
+ //virtual void SetRotation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &rotation ) = 0;
+ //
+ ///********************************************************
+ // * Instantly moves and redirects object.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param orientation: New orientation.
+ // ********************************************************/
+ //virtual void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation ) = 0;
+ //
+ ///********************************************************
+ // * Resizes the boundingBox.
+ // * @param objRef: A pointer to the ICustomBody representing a physical object.
+ // * @param size: New size of this [m]
+ // ********************************************************/
+ //virtual void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size ) = 0;
/********************************************************
* Creates a new dynamically allocated object that can be used as a component for more complex ICustomBodies.
@@ -245,11 +222,6 @@ namespace Oyster
SubscriptMessage_ignore_collision_response
};
- /********************************************************
- * @param gameObjectRef: a pointer to the object in the game owning the rigid body.
- ********************************************************/
- void* gameObjectRef;
-
typedef SubscriptMessage (*EventAction_Collision)( const ICustomBody *proto, const ICustomBody *deuter );
typedef Struct::SimpleBodyDescription SimpleBodyDescription;
typedef Struct::SphericalBodyDescription SphericalBodyDescription;
@@ -266,7 +238,7 @@ namespace Oyster
/********************************************************
* @todo TODO: need doc
********************************************************/
- virtual void CallSubscription( const ICustomBody *proto, const ICustomBody *deuter ) = 0;
+ virtual SubscriptMessage CallSubscription( const ICustomBody *proto, const ICustomBody *deuter ) = 0;
/********************************************************
* @todo TODO: need doc
@@ -281,7 +253,7 @@ namespace Oyster
/********************************************************
* @return the linear velocity of the rigid body in a vector.
********************************************************/
- virtual Math::Float3 GetRigidLinearVelocity() const = 0;
+ //virtual Math::Float3 GetRigidLinearVelocity() const = 0;
/********************************************************
* @todo TODO: need doc
@@ -293,22 +265,28 @@ namespace Oyster
********************************************************/
virtual bool IsAffectedByGravity() const = 0;
- /********************************************************
- * Performs a detailed Intersect test and returns if, when and where.
- * @param object: What this is intersect testing against.
- * @param timeStepLength: The value set by API::SetDeltaTime(...)
- * @param deltaWhen: Time in seconds since last update frame til timeOfContact. 0.0f <= deltaWhen <= timeStepLength
- * @param worldPointOfContact: Where at timeOfContact, this and object touches eachother.
- * @return true if this truly intersects with object.
- ********************************************************/
- virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float timeStepLength, ::Oyster::Math::Float &deltaWhen, ::Oyster::Math::Float3 &worldPointOfContact ) const = 0;
-
/********************************************************
* param shape: Any defined sample shape.
* @return true if this truly intersects with shape.
********************************************************/
virtual bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const = 0;
+ /********************************************************
+ * Performs a detailed Intersect test and returns if, when and where.
+ * @param shape: Any defined sample shape.
+ * @param worldPointOfContact: Where at timeOfContact, this and object touches eachother.
+ * @return true if this truly intersects with object.
+ ********************************************************/
+ virtual bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0;
+
+ /********************************************************
+ * Performs a detailed Intersect test and returns if, when and where.
+ * @param object: What this is intersect testing against.
+ * @param worldPointOfContact: Where at timeOfContact, this and object touches eachother.
+ * @return true if this truly intersects with object.
+ ********************************************************/
+ virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0;
+
/********************************************************
* Required by Engine's Collision Search.
* @param targetMem: Provided memory that written into and then returned.
@@ -322,7 +300,7 @@ namespace Oyster
* @param targetMem: Provided memory that written into and then returned.
* @return a surface normal in worldSpace.
********************************************************/
- virtual ::Oyster::Math::Float3 & GetNormalAt( const ::Oyster::Math::Float3 &worldPos, ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const = 0;
+ virtual ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const = 0;
/********************************************************
* The gravity normal will have same direction as the total gravity force pulling on this and have the magnitude of 1.0f.
@@ -331,37 +309,49 @@ namespace Oyster
********************************************************/
virtual ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const = 0;
- /********************************************************
- * The world position of this center of gravity.
- * @param targetMem: Provided memory that written into and then returned.
- * @return a position in worldSpace.
- ********************************************************/
- virtual ::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const = 0;
-
- /********************************************************
- * @param targetMem: Provided memory that written into and then returned.
- * @return a copy of this's rotation matrix.
- ********************************************************/
- virtual ::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
-
- /********************************************************
- * @param targetMem: Provided memory that written into and then returned.
- * @return a copy of this's orientation matrix.
- ********************************************************/
- virtual ::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
-
- /********************************************************
- * @param targetMem: Provided memory that written into and then returned.
- * @return a copy of this's view matrix.
- ********************************************************/
- virtual ::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
+ ///********************************************************
+ // * The world position of this center of gravity.
+ // * @param targetMem: Provided memory that written into and then returned.
+ // * @return a position in worldSpace.
+ // ********************************************************/
+ //virtual ::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const = 0;
+ //
+ ///********************************************************
+ // * @param targetMem: Provided memory that written into and then returned.
+ // * @return a copy of this's rotation matrix.
+ // ********************************************************/
+ //virtual ::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
+ //
+ ///********************************************************
+ // * @param targetMem: Provided memory that written into and then returned.
+ // * @return a copy of this's orientation matrix.
+ // ********************************************************/
+ //virtual ::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
+ //
+ ///********************************************************
+ // * @param targetMem: Provided memory that written into and then returned.
+ // * @return a copy of this's view matrix.
+ // ********************************************************/
+ //virtual ::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
/********************************************************
* To not be called if is in Engine
* Is called during API::Update
********************************************************/
virtual UpdateState Update( ::Oyster::Math::Float timeStepLength ) = 0;
+
+ /********************************************************
+ * @todo TODO: add doc
+ ********************************************************/
+ virtual void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime ) = 0;
+ /********************************************************
+ * Sets which scene this ICustomBody is within.
+ * Reserved to only be used by the scene.
+ * @todo TODO: create an IScene interface
+ ********************************************************/
+ virtual void SetScene( void *scene ) = 0;
+
/********************************************************
* Sets the function that will be called by the engine
* whenever a collision occurs.
@@ -380,63 +370,64 @@ namespace Oyster
********************************************************/
virtual void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ) = 0;
- /********************************************************
- * To not be called if is in Engine
- * Use API::SetMomentOfInertiaTensor_KeepVelocity(...) instead
- ********************************************************/
- virtual void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ) = 0;
-
- /********************************************************
- * To not be called if is in Engine
- * Use API::SetMomentOfInertiaTensor_KeepMomentum(...)
- ********************************************************/
- virtual void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI ) = 0;
-
- /********************************************************
- * To not be called if is in Engine
- * Use API::SetMass_KeepVelocity(...)
- ********************************************************/
- virtual void SetMass_KeepVelocity( ::Oyster::Math::Float m ) = 0;
-
- /********************************************************
- * To not be called if is in Engine
- * Use API::SetMass_KeepMomentum(...)
- ********************************************************/
- virtual void SetMass_KeepMomentum( ::Oyster::Math::Float m ) = 0;
-
- /********************************************************
- * To not be called if is in Engine
- * Use API::SetCenter(...)
- ********************************************************/
- virtual void SetCenter( const ::Oyster::Math::Float3 &worldPos ) = 0;
-
- /********************************************************
- * To not be called if is in Engine
- * Use API::SetRotation(...)
- ********************************************************/
- virtual void SetRotation( const ::Oyster::Math::Float4x4 &rotation ) = 0;
-
- /********************************************************
- * To not be called if is in Engine
- * Use API::SetOrientation(...)
- ********************************************************/
- virtual void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ) = 0;
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::SetMomentOfInertiaTensor_KeepVelocity(...) instead
+ // ********************************************************/
+ //virtual void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ) = 0;
+ //
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::SetMomentOfInertiaTensor_KeepMomentum(...)
+ // ********************************************************/
+ //virtual void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI ) = 0;
+ //
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::SetMass_KeepVelocity(...)
+ // ********************************************************/
+ //virtual void SetMass_KeepVelocity( ::Oyster::Math::Float m ) = 0;
+ //
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::SetMass_KeepMomentum(...)
+ // ********************************************************/
+ //virtual void SetMass_KeepMomentum( ::Oyster::Math::Float m ) = 0;
+ //
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::SetCenter(...)
+ // ********************************************************/
+ //virtual void SetCenter( const ::Oyster::Math::Float3 &worldPos ) = 0;
+ //
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::SetRotation(...)
+ // ********************************************************/
+ //virtual void SetRotation( const ::Oyster::Math::Float4x4 &rotation ) = 0;
+ //
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::SetOrientation(...)
+ // ********************************************************/
+ //virtual void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ) = 0;
- /********************************************************
- * To not be called if is in Engine
- * Use API::SetSize(...)
- ********************************************************/
- virtual void SetSize( const ::Oyster::Math::Float3 &size ) = 0;
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::SetSize(...)
+ // ********************************************************/
+ //virtual void SetSize( const ::Oyster::Math::Float3 &size ) = 0;
- /********************************************************
- * To not be called if is in Engine
- * Use API::?? @todo TODO:
- ********************************************************/
- virtual void SetMomentum( const ::Oyster::Math::Float3 &worldG ) = 0;
+ ///********************************************************
+ // * To not be called if is in Engine
+ // * Use API::?? @todo TODO:
+ // ********************************************************/
+ //virtual void SetMomentum( const ::Oyster::Math::Float3 &worldG ) = 0;
};
}
}
#include "PhysicsStructs.h"
+#include "PhysicsFormula.h"
#endif
\ No newline at end of file
diff --git a/Code/GamePhysics/PhysicsFormula-Impl.h b/Code/GamePhysics/PhysicsFormula-Impl.h
new file mode 100644
index 00000000..323fd732
--- /dev/null
+++ b/Code/GamePhysics/PhysicsFormula-Impl.h
@@ -0,0 +1,76 @@
+#ifndef PHYSICS_FORMULA_IMPL_H
+#define PHYSICS_FORMULA_IMPL_H
+
+#include "PhysicsFormula.h"
+#include "OysterPhysics3D.h"
+
+namespace Oyster { namespace Physics { namespace Formula
+{
+ namespace MomentOfInertia
+ {
+ inline ::Oyster::Math::Float4x4 CreateSphereMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float radius )
+ {
+ return ::Oyster::Physics3D::Formula::MomentOfInertia::Sphere(mass, radius);
+ }
+
+ inline ::Oyster::Math::Float4x4 CreateHollowSphereMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float radius )
+ {
+ return ::Oyster::Physics3D::Formula::MomentOfInertia::HollowSphere(mass, radius);
+ }
+
+ inline ::Oyster::Math::Float4x4 CreateCuboidMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float height, const ::Oyster::Math::Float width, const ::Oyster::Math::Float depth )
+ {
+ return ::Oyster::Physics3D::Formula::MomentOfInertia::Cuboid(mass, height, width, depth);
+ }
+
+ inline ::Oyster::Math::Float4x4 CreateCylinderMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float height, const ::Oyster::Math::Float radius )
+ {
+ return ::Oyster::Physics3D::Formula::MomentOfInertia::Cylinder(mass, height, radius);
+ }
+
+ inline ::Oyster::Math::Float4x4 CreateRodMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float length )
+ {
+ return ::Oyster::Physics3D::Formula::MomentOfInertia::RodCenter(mass, length);
+ }
+ }
+
+ namespace CollisionResponse
+ {
+ inline ::Oyster::Math::Float Bounce( ::Oyster::Math::Float e, ::Oyster::Math::Float mA, ::Oyster::Math::Float gA, ::Oyster::Math::Float mB, ::Oyster::Math::Float gB )
+ {
+ //return (e + 1) * (mB*gA - mA*gB) / (mA + mB);
+ return (e + 1) * (mA*gB - mB*gA) / (mA + mB);
+ }
+
+ inline ::Oyster::Math::Float4 Friction( ::Oyster::Math::Float i, ::Oyster::Math::Float4 iN, ::Oyster::Math::Float4 momA, ::Oyster::Math::Float sFA, ::Oyster::Math::Float dFA, ::Oyster::Math::Float mA, ::Oyster::Math::Float4 momB, ::Oyster::Math::Float sFB, ::Oyster::Math::Float dFB, ::Oyster::Math::Float mB )
+ {
+ // FRICTION
+ // Relative momentum after normal impulse
+ ::Oyster::Math::Float4 relativeMomentum = momB - momA;
+
+ ::Oyster::Math::Float4 tanFriction = relativeMomentum - relativeMomentum.Dot( iN )*iN;
+ tanFriction.Normalize();
+
+ ::Oyster::Math::Float magnitudeFriction = -relativeMomentum.Dot( tanFriction );
+ magnitudeFriction = magnitudeFriction*mA*mB/( mA + mB );
+
+ ::Oyster::Math::Float mu = 0.5f*( sFA + sFB );
+
+ ::Oyster::Math::Float4 frictionImpulse;
+ if( abs(magnitudeFriction) < i*mu )
+ {
+ frictionImpulse = magnitudeFriction*tanFriction;
+ }
+ else
+ {
+ ::Oyster::Math::Float dynamicFriction = 0.5f*( dFA + dFB );
+ frictionImpulse = -i*tanFriction*dynamicFriction;
+ }
+
+ return ( 1 / mA )*frictionImpulse;
+ }
+ }
+
+} } }
+
+#endif
\ No newline at end of file
diff --git a/Code/GamePhysics/PhysicsFormula.h b/Code/GamePhysics/PhysicsFormula.h
new file mode 100644
index 00000000..fe91ae3a
--- /dev/null
+++ b/Code/GamePhysics/PhysicsFormula.h
@@ -0,0 +1,35 @@
+#ifndef PHYSICS_FORMULA_H
+#define PHYSICS_FORMULA_H
+
+#include "OysterMath.h"
+#include "OysterPhysics3D.h"
+
+namespace Oyster { namespace Physics { namespace Formula
+{
+ namespace MomentOfInertia
+ {
+ ::Oyster::Math::Float4x4 CreateSphereMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float radius );
+ ::Oyster::Math::Float4x4 CreateHollowSphereMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float radius );
+ ::Oyster::Math::Float4x4 CreateCuboidMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float height, const ::Oyster::Math::Float width, const ::Oyster::Math::Float depth );
+ ::Oyster::Math::Float4x4 CreateCylinderMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float height, const ::Oyster::Math::Float radius );
+ ::Oyster::Math::Float4x4 CreateRodMatrix( const ::Oyster::Math::Float mass, const ::Oyster::Math::Float length );
+ }
+
+ namespace CollisionResponse
+ {
+ ::Oyster::Math::Float Bounce( ::Oyster::Math::Float coeffOfRestitution,
+ ::Oyster::Math::Float massA, ::Oyster::Math::Float momentumA,
+ ::Oyster::Math::Float massB, ::Oyster::Math::Float momentumB );
+
+ ::Oyster::Math::Float4 Friction( ::Oyster::Math::Float impulse, ::Oyster::Math::Float4 impulseNormal,
+ ::Oyster::Math::Float4 momentumA, ::Oyster::Math::Float staticFrictionA,
+ ::Oyster::Math::Float dynamicFrictionA, ::Oyster::Math::Float massA,
+ ::Oyster::Math::Float4 momentumB, ::Oyster::Math::Float staticFrictionB,
+ ::Oyster::Math::Float dynamicFrictionB, ::Oyster::Math::Float massB );
+
+ }
+} } }
+
+#include "PhysicsFormula-Impl.h"
+
+#endif
\ No newline at end of file
diff --git a/Code/GamePhysics/PhysicsStructs-Impl.h b/Code/GamePhysics/PhysicsStructs-Impl.h
index 3de46ee2..e7704460 100644
--- a/Code/GamePhysics/PhysicsStructs-Impl.h
+++ b/Code/GamePhysics/PhysicsStructs-Impl.h
@@ -10,8 +10,8 @@ namespace Oyster { namespace Physics
inline SimpleBodyDescription::SimpleBodyDescription()
{
this->rotation = ::Oyster::Math::Float4x4::identity;
- this->centerPosition = ::Oyster::Math::Float3::null;
- this->size = ::Oyster::Math::Float3( 1.0f );
+ this->centerPosition = ::Oyster::Math::Float4::null;
+ this->size = ::Oyster::Math::Float4( 1.0f );
this->mass = 12.0f;
this->inertiaTensor = ::Oyster::Math::Float4x4::identity;
this->subscription = NULL;
@@ -21,33 +21,77 @@ namespace Oyster { namespace Physics
inline SphericalBodyDescription::SphericalBodyDescription()
{
this->rotation = ::Oyster::Math::Float4x4::identity;
- this->centerPosition = ::Oyster::Math::Float3::null;
+ this->centerPosition = ::Oyster::Math::Float4::null;
this->radius = 0.5f;
this->mass = 10.0f;
this->subscription = NULL;
this->ignoreGravity = false;
}
-
- inline CustomBodyState::CustomBodyState( const ::Oyster::Math::Float3 &reach, const ::Oyster::Math::Float3 ¢erPos, const ::Oyster::Math::Float3 &rotation )
+ inline CustomBodyState::CustomBodyState( ::Oyster::Math::Float mass, ::Oyster::Math::Float restitutionCoeff, ::Oyster::Math::Float staticFrictionCoeff, ::Oyster::Math::Float kineticFrictionCoeff, const ::Oyster::Math::Float4x4 &inertiaTensor, const ::Oyster::Math::Float4 &reach, const ::Oyster::Math::Float4 ¢erPos, const ::Oyster::Math::Float4 &rotation, const ::Oyster::Math::Float4 &linearMomentum, const ::Oyster::Math::Float4 &angularMomentum )
{
- this->reach = ::Oyster::Math::Float4( reach, 0.0f );
- this->centerPos = ::Oyster::Math::Float4( centerPos, 1.0f );
- this->angularAxis = ::Oyster::Math::Float4( rotation, 0.0f );
- this->isSpatiallyAltered = this->isDisturbed = false;
+ this->mass = mass;
+ this->restitutionCoeff = restitutionCoeff;
+ this->staticFrictionCoeff = staticFrictionCoeff;
+ this->kineticFrictionCoeff = kineticFrictionCoeff;
+ this->inertiaTensor = inertiaTensor;
+ this->reach = reach;
+ this->centerPos = centerPos;
+ this->angularAxis = rotation;
+ this->linearMomentum = linearMomentum;
+ this->angularMomentum = angularMomentum;
+ this->linearImpulse = this->angularImpulse = ::Oyster::Math::Float4::null;
+ this->deltaPos = this->deltaAxis = ::Oyster::Math::Float4::null;
+ this->isSpatiallyAltered = this->isDisturbed = this->isForwarded = false;
}
inline CustomBodyState & CustomBodyState::operator = ( const CustomBodyState &state )
{
+ this->mass = state.mass;
+ this->restitutionCoeff = state.restitutionCoeff;
+ this->staticFrictionCoeff = state.staticFrictionCoeff;
+ this->kineticFrictionCoeff = state.kineticFrictionCoeff;
+ this->inertiaTensor = state.inertiaTensor;
this->reach = state.reach;
this->centerPos = state.centerPos;
this->angularAxis = state.angularAxis;
-
+ this->linearMomentum = state.linearMomentum;
+ this->angularMomentum = state.angularMomentum;
+ this->linearImpulse = state.linearImpulse;
+ this->angularImpulse = state.angularImpulse;
+ this->deltaPos = state.deltaPos;
+ this->deltaAxis = state.deltaAxis;
this->isSpatiallyAltered = state.isSpatiallyAltered;
this->isDisturbed = state.isDisturbed;
+ this->isForwarded = state.isForwarded;
return *this;
}
+ inline const ::Oyster::Math::Float CustomBodyState::GetMass() const
+ {
+ return this->mass;
+ }
+
+ inline const ::Oyster::Math::Float CustomBodyState::GetRestitutionCoeff() const
+ {
+ return this->restitutionCoeff;
+ }
+
+ inline const ::Oyster::Math::Float CustomBodyState::GetFrictionCoeff_Static() const
+ {
+ return this->staticFrictionCoeff;
+ }
+
+ inline const ::Oyster::Math::Float CustomBodyState::GetFrictionCoeff_Kinetic() const
+ {
+ return this->kineticFrictionCoeff;
+ }
+
+ inline const ::Oyster::Math::Float4x4 & CustomBodyState::GetMomentOfInertia() const
+ {
+ return this->inertiaTensor;
+ }
+
inline const ::Oyster::Math::Float4 & CustomBodyState::GetReach() const
{
return this->reach;
@@ -73,25 +117,116 @@ namespace Oyster { namespace Physics
return ::Oyster::Math3D::RotationMatrix( this->GetAngularAxis().xyz );
}
- inline void CustomBodyState::SetSize( const ::Oyster::Math::Float3 &size )
+ inline ::Oyster::Math::Float4x4 CustomBodyState::GetOrientation() const
+ {
+ return ::Oyster::Math3D::OrientationMatrix( this->angularAxis.xyz, this->centerPos.xyz );
+ }
+
+ inline ::Oyster::Math::Float4x4 CustomBodyState::GetView() const
+ {
+ return ::Oyster::Math3D::ViewMatrix( this->angularAxis.xyz, this->centerPos.xyz );
+ }
+
+ inline const ::Oyster::Math::Float4 & CustomBodyState::GetLinearMomentum() const
+ {
+ return this->linearMomentum;
+ }
+
+ inline ::Oyster::Math::Float4 CustomBodyState::GetLinearMomentum( const ::Oyster::Math::Float4 &at ) const
+ {
+ //return this->linearMomentum + ::Oyster::Physics3D::Formula::TangentialLinearMomentum( this->angularMomentum, at - this->centerPos ); // C3083 error?
+ return this->linearMomentum + ::Oyster::Math::Float4( this->angularMomentum.xyz.Cross((at - this->centerPos).xyz), 0.0f );
+ }
+
+ inline const ::Oyster::Math::Float4 & CustomBodyState::GetAngularMomentum() const
+ {
+ return this->angularMomentum;
+ }
+
+ inline const ::Oyster::Math::Float4 & CustomBodyState::GetLinearImpulse() const
+ {
+ return this->linearImpulse;
+ }
+
+ inline const ::Oyster::Math::Float4 & CustomBodyState::GetAngularImpulse() const
+ {
+ return this->angularImpulse;
+ }
+
+ inline const ::Oyster::Math::Float4 & CustomBodyState::GetForward_DeltaPos() const
+ {
+ return this->deltaPos;
+ }
+
+ inline const ::Oyster::Math::Float4 & CustomBodyState::GetForward_DeltaAxis() const
+ {
+ return this->deltaAxis;
+ }
+
+ inline void CustomBodyState::SetMass_KeepMomentum( ::Oyster::Math::Float m )
+ {
+ this->mass = m;
+ }
+
+ inline void CustomBodyState::SetMass_KeepVelocity( ::Oyster::Math::Float m )
+ {
+ if( m != 0.0f )
+ { // sanity block!
+ // Formula::LinearMomentum( m, Formula::LinearVelocity(this->mass, this->linearMomentum) )
+ // is the same as (this->linearMomentum / this->mass) * m = (m / this->mass) * this->linearMomentum
+ this->linearMomentum *= (m / this->mass);
+ this->mass = m;
+ }
+ }
+
+ inline void CustomBodyState::SetRestitutionCoeff( ::Oyster::Math::Float e )
+ {
+ this->restitutionCoeff = e;
+ }
+
+ inline void CustomBodyState::SetFrictionCoeff( ::Oyster::Math::Float staticU, ::Oyster::Math::Float kineticU )
+ {
+ this->staticFrictionCoeff = staticU;
+ this->kineticFrictionCoeff = kineticU;
+ }
+
+ inline void CustomBodyState::SetMomentOfInertia_KeepMomentum( const ::Oyster::Math::Float4x4 &tensor )
+ {
+ this->inertiaTensor = tensor;
+ }
+
+ inline void CustomBodyState::SetMomentOfInertia_KeepVelocity( const ::Oyster::Math::Float4x4 &tensor )
+ {
+ if( tensor.GetDeterminant() != 0.0f )
+ { // sanity block!
+ ::Oyster::Math::Float4x4 rotation = ::Oyster::Math3D::RotationMatrix(this->angularAxis.xyz);
+ //::Oyster::Math::Float4 w = ::Oyster::Physics3D::Formula::AngularVelocity( (rotation * this->inertiaTensor).GetInverse(), this->angularMomentum ); // C3083 error?
+ ::Oyster::Math::Float4 w = (rotation * this->inertiaTensor).GetInverse() * this->angularMomentum;
+ this->inertiaTensor = tensor;
+ //this->angularMomentum = ::Oyster::Physics3D::Formula::AngularMomentum( rotation * tensor, w ); // C3083 error?
+ this->angularMomentum = rotation * tensor * w;
+ }
+ }
+
+ inline void CustomBodyState::SetSize( const ::Oyster::Math::Float4 &size )
{
this->SetReach( 0.5f * size );
}
- inline void CustomBodyState::SetReach( const ::Oyster::Math::Float3 &halfSize )
+ inline void CustomBodyState::SetReach( const ::Oyster::Math::Float4 &halfSize )
{
this->reach.xyz = halfSize;
this->reach = ::Utility::Value::Max( this->reach, ::Oyster::Math::Float4::null );
this->isSpatiallyAltered = this->isDisturbed = true;
}
- inline void CustomBodyState::SetCenterPosition( const ::Oyster::Math::Float3 ¢erPos )
+ inline void CustomBodyState::SetCenterPosition( const ::Oyster::Math::Float4 ¢erPos )
{
this->centerPos.xyz = centerPos;
this->isSpatiallyAltered = this->isDisturbed = true;
}
- inline void CustomBodyState::SetRotation( const ::Oyster::Math::Float3 &angularAxis )
+ inline void CustomBodyState::SetRotation( const ::Oyster::Math::Float4 &angularAxis )
{
this->angularAxis.xyz = angularAxis;
this->isSpatiallyAltered = this->isDisturbed = true;
@@ -99,7 +234,78 @@ namespace Oyster { namespace Physics
inline void CustomBodyState::SetRotation( const ::Oyster::Math::Float4x4 &rotation )
{
- this->SetRotation( ::Oyster::Math3D::AngularAxis(rotation).xyz );
+ this->SetRotation( ::Oyster::Math3D::AngularAxis(rotation) );
+ }
+
+ inline void CustomBodyState::SetOrientation( const ::Oyster::Math::Float4x4 &orientation )
+ {
+ this->SetRotation( ::Oyster::Math3D::ExtractAngularAxis(orientation) );
+ this->SetCenterPosition( orientation.v[3] );
+ }
+
+ inline void CustomBodyState::SetLinearMomentum( const ::Oyster::Math::Float4 &g )
+ {
+ this->linearMomentum.xyz = g;
+ this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::SetAngularMomentum( const ::Oyster::Math::Float4 &h )
+ {
+ this->angularMomentum.xyz = h;
+ this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::SetLinearImpulse( const ::Oyster::Math::Float4 &j )
+ {
+ this->linearImpulse.xyz = j;
+ this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::SetAngularImpulse( const ::Oyster::Math::Float4 &j )
+ {
+ this->angularImpulse.xyz = j;
+ this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::AddRotation( const ::Oyster::Math::Float4 &angularAxis )
+ {
+ this->angularAxis += angularAxis;
+ this->isSpatiallyAltered = this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::AddTranslation( const ::Oyster::Math::Float4 &deltaPos )
+ {
+ this->centerPos += deltaPos;
+ this->isSpatiallyAltered = this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::ApplyLinearImpulse( const ::Oyster::Math::Float4 &j )
+ {
+ this->linearImpulse += j;
+ this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::ApplyAngularImpulse( const ::Oyster::Math::Float4 &j )
+ {
+ this->angularImpulse += j;
+ this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::ApplyImpulse( const ::Oyster::Math::Float4 &j, const ::Oyster::Math::Float4 &at, const ::Oyster::Math::Float4 &normal )
+ {
+ //::Oyster::Math::Float4 tangentialImpulse = ::Oyster::Physics3D::Formula::AngularMomentum( j, at - this->centerPos ); // C3083 error?
+ ::Oyster::Math::Float4 tangentialImpulse = ::Oyster::Math::Float4( (at - this->centerPos).xyz.Cross(j.xyz), 0.0f );
+ this->linearImpulse += j - tangentialImpulse;
+ this->angularImpulse += tangentialImpulse;
+
+ this->isDisturbed = true;
+ }
+
+ inline void CustomBodyState::ApplyForwarding( const ::Oyster::Math::Float4 &deltaPos, const ::Oyster::Math::Float4 &deltaAxis )
+ {
+ this->deltaPos += deltaPos;
+ this->deltaAxis += deltaAxis;
+ this->isDisturbed = this->isForwarded = true;
}
inline bool CustomBodyState::IsSpatiallyAltered() const
@@ -111,6 +317,11 @@ namespace Oyster { namespace Physics
{
return this->isDisturbed;
}
+
+ inline bool CustomBodyState::IsForwarded() const
+ {
+ return this->isForwarded;
+ }
}
} }
diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h
index c1f74640..3c17ae6d 100644
--- a/Code/GamePhysics/PhysicsStructs.h
+++ b/Code/GamePhysics/PhysicsStructs.h
@@ -11,8 +11,8 @@ namespace Oyster { namespace Physics
struct SimpleBodyDescription
{
::Oyster::Math::Float4x4 rotation;
- ::Oyster::Math::Float3 centerPosition;
- ::Oyster::Math::Float3 size;
+ ::Oyster::Math::Float4 centerPosition;
+ ::Oyster::Math::Float4 size;
::Oyster::Math::Float mass;
::Oyster::Math::Float4x4 inertiaTensor;
::Oyster::Physics::ICustomBody::EventAction_Collision subscription;
@@ -24,7 +24,7 @@ namespace Oyster { namespace Physics
struct SphericalBodyDescription
{
::Oyster::Math::Float4x4 rotation;
- ::Oyster::Math::Float3 centerPosition;
+ ::Oyster::Math::Float4 centerPosition;
::Oyster::Math::Float radius;
::Oyster::Math::Float mass;
::Oyster::Physics::ICustomBody::EventAction_Collision subscription;
@@ -36,31 +36,77 @@ namespace Oyster { namespace Physics
struct CustomBodyState
{
public:
- CustomBodyState( const ::Oyster::Math::Float3 &reach = ::Oyster::Math::Float3::null,
- const ::Oyster::Math::Float3 ¢erPos = ::Oyster::Math::Float3::null,
- const ::Oyster::Math::Float3 &rotation = ::Oyster::Math::Float3::null );
+ CustomBodyState( ::Oyster::Math::Float mass = 1.0f,
+ ::Oyster::Math::Float restitutionCoeff = 1.0f,
+ ::Oyster::Math::Float staticFrictionCoeff = 1.0f,
+ ::Oyster::Math::Float kineticFrictionCoeff = 1.0f,
+ const ::Oyster::Math::Float4x4 &inertiaTensor = ::Oyster::Math::Float4x4::identity,
+ const ::Oyster::Math::Float4 &reach = ::Oyster::Math::Float4::null,
+ const ::Oyster::Math::Float4 ¢erPos = ::Oyster::Math::Float4::standard_unit_w,
+ const ::Oyster::Math::Float4 &rotation = ::Oyster::Math::Float4::null,
+ const ::Oyster::Math::Float4 &linearMomentum = ::Oyster::Math::Float4::null,
+ const ::Oyster::Math::Float4 &angularMomentum = ::Oyster::Math::Float4::null );
CustomBodyState & operator = ( const CustomBodyState &state );
- const ::Oyster::Math::Float4 & GetReach() const;
- ::Oyster::Math::Float4 GetSize() const;
- const ::Oyster::Math::Float4 & GetCenterPosition() const;
- const ::Oyster::Math::Float4 & GetAngularAxis() const;
- ::Oyster::Math::Float4x4 GetRotation() const;
-
- void SetSize( const ::Oyster::Math::Float3 &size );
- void SetReach( const ::Oyster::Math::Float3 &halfSize );
- void SetCenterPosition( const ::Oyster::Math::Float3 ¢erPos );
- void SetRotation( const ::Oyster::Math::Float3 &angularAxis );
+ const ::Oyster::Math::Float GetMass() const;
+ const ::Oyster::Math::Float GetRestitutionCoeff() const;
+ const ::Oyster::Math::Float GetFrictionCoeff_Static() const;
+ const ::Oyster::Math::Float GetFrictionCoeff_Kinetic() const;
+ const ::Oyster::Math::Float4x4 & GetMomentOfInertia() const;
+ const ::Oyster::Math::Float4 & GetReach() const;
+ ::Oyster::Math::Float4 GetSize() const;
+ const ::Oyster::Math::Float4 & GetCenterPosition() const;
+ const ::Oyster::Math::Float4 & GetAngularAxis() const;
+ ::Oyster::Math::Float4x4 GetRotation() const;
+ ::Oyster::Math::Float4x4 GetOrientation() const;
+ ::Oyster::Math::Float4x4 GetView() const;
+ const ::Oyster::Math::Float4 & GetLinearMomentum() const;
+ ::Oyster::Math::Float4 GetLinearMomentum( const ::Oyster::Math::Float4 &at ) const;
+ const ::Oyster::Math::Float4 & GetAngularMomentum() const;
+ const ::Oyster::Math::Float4 & GetLinearImpulse() const;
+ const ::Oyster::Math::Float4 & GetAngularImpulse() const;
+ const ::Oyster::Math::Float4 & GetForward_DeltaPos() const;
+ const ::Oyster::Math::Float4 & GetForward_DeltaAxis() const;
+
+ void SetMass_KeepMomentum( ::Oyster::Math::Float m );
+ void SetMass_KeepVelocity( ::Oyster::Math::Float m );
+ void SetRestitutionCoeff( ::Oyster::Math::Float e );
+ void SetFrictionCoeff( ::Oyster::Math::Float staticU, ::Oyster::Math::Float kineticU );
+ void SetMomentOfInertia_KeepMomentum( const ::Oyster::Math::Float4x4 &tensor );
+ void SetMomentOfInertia_KeepVelocity( const ::Oyster::Math::Float4x4 &tensor );
+ void SetSize( const ::Oyster::Math::Float4 &size );
+ void SetReach( const ::Oyster::Math::Float4 &halfSize );
+ void SetCenterPosition( const ::Oyster::Math::Float4 ¢erPos );
+ void SetRotation( const ::Oyster::Math::Float4 &angularAxis );
void SetRotation( const ::Oyster::Math::Float4x4 &rotation );
+ void SetOrientation( const ::Oyster::Math::Float4x4 &orientation );
+ void SetLinearMomentum( const ::Oyster::Math::Float4 &g );
+ void SetAngularMomentum( const ::Oyster::Math::Float4 &h );
+ void SetLinearImpulse( const ::Oyster::Math::Float4 &j );
+ void SetAngularImpulse( const ::Oyster::Math::Float4 &j );
+
+ void AddRotation( const ::Oyster::Math::Float4 &angularAxis );
+ void AddTranslation( const ::Oyster::Math::Float4 &deltaPos );
+
+ void ApplyLinearImpulse( const ::Oyster::Math::Float4 &j );
+ void ApplyAngularImpulse( const ::Oyster::Math::Float4 &j );
+ void ApplyImpulse( const ::Oyster::Math::Float4 &j, const ::Oyster::Math::Float4 &at, const ::Oyster::Math::Float4 &normal );
+ void ApplyForwarding( const ::Oyster::Math::Float4 &deltaPos, const ::Oyster::Math::Float4 &deltaAxis );
bool IsSpatiallyAltered() const;
bool IsDisturbed() const;
+ bool IsForwarded() const;
private:
+ ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, kineticFrictionCoeff;
+ ::Oyster::Math::Float4x4 inertiaTensor;
::Oyster::Math::Float4 reach, centerPos, angularAxis;
+ ::Oyster::Math::Float4 linearMomentum, angularMomentum;
+ ::Oyster::Math::Float4 linearImpulse, angularImpulse;
+ ::Oyster::Math::Float4 deltaPos, deltaAxis; // Forwarding data sum
- bool isSpatiallyAltered, isDisturbed;
+ bool isSpatiallyAltered, isDisturbed, isForwarded;
};
}
} }
diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h
index 8bca1c19..b5eab471 100644
--- a/Code/OysterMath/LinearMath.h
+++ b/Code/OysterMath/LinearMath.h
@@ -266,6 +266,12 @@ namespace LinearAlgebra3D
return ::std::asin( ::LinearAlgebra::Vector4(rotationMatrix.v[1].z, rotationMatrix.v[2].x, rotationMatrix.v[0].y, 1) );
}
+ template
+ inline ::LinearAlgebra::Vector4 ExtractAngularAxis( const ::LinearAlgebra::Matrix4x4 &orientationMatrix )
+ {
+ return ::std::asin( ::LinearAlgebra::Vector4(orientationMatrix.v[1].z, orientationMatrix.v[2].x, orientationMatrix.v[0].y, 0) );
+ }
+
template
inline ::LinearAlgebra::Matrix4x4 & TranslationMatrix( const ::LinearAlgebra::Vector3 &position, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
{
@@ -275,6 +281,106 @@ namespace LinearAlgebra3D
0, 0, 0, 1 );
}
+ template
+ inline ::LinearAlgebra::Quaternion Rotation( const ScalarType &radian, const ::LinearAlgebra::Vector3 &normalizedAxis )
+ {
+ ScalarType r = radian * 0.5f,
+ s = std::sin( r ),
+ c = std::cos( r );
+
+ return ::LinearAlgebra::Quaternion( normalizedAxis * s, c );
+ }
+
+ template
+ inline ::LinearAlgebra::Quaternion Rotation( const ScalarType &radian, const ::LinearAlgebra::Vector4 &normalizedAxis )
+ {
+ ScalarType r = radian * 0.5f,
+ s = std::sin( r ),
+ c = std::cos( r );
+
+ return ::LinearAlgebra::Quaternion( (normalizedAxis * s).xyz, c );
+ }
+
+ template
+ inline ::LinearAlgebra::Quaternion Rotation( const ::LinearAlgebra::Vector3 &angularAxis )
+ {
+ ScalarType radius = angularAxis.Dot( angularAxis );
+ if( radius != 0 )
+ {
+ radius = (ScalarType)::std::sqrt( radius );
+ return Rotation( radius, angularAxis / radius );
+ }
+ else
+ {
+ return ::LinearAlgebra::Quaternion::identity;
+ }
+ }
+
+ template
+ inline ::LinearAlgebra::Quaternion Rotation( const ::LinearAlgebra::Vector4 &angularAxis )
+ {
+ ScalarType radius = angularAxis.Dot( angularAxis );
+ if( radius != 0 )
+ {
+ radius = (ScalarType)::std::sqrt( radius );
+ return Rotation( radius, angularAxis / radius );
+ }
+ else
+ {
+ return ::LinearAlgebra::Quaternion::identity;
+ }
+ }
+
+ template
+ inline ::LinearAlgebra::Matrix4x4 & RotationMatrix( const ::LinearAlgebra::Quaternion &rotationQuaternion, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
+ {
+ ::LinearAlgebra::Quaternion conjugate = rotationQuaternion.GetConjugate();
+
+ targetMem.v[0] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(1,0,0)*conjugate).imaginary, 0 );
+ targetMem.v[1] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(0,1,0)*conjugate).imaginary, 0 );
+ targetMem.v[2] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(0,0,1)*conjugate).imaginary, 0 );
+ targetMem.v[3] = ::LinearAlgebra::Vector4::standard_unit_w;
+ return targetMem;
+ }
+
+ template
+ inline ::LinearAlgebra::Matrix4x4 & OrientationMatrix( const ::LinearAlgebra::Quaternion &rotationQuaternion, const ::LinearAlgebra::Vector3 &translation, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
+ {
+ ::LinearAlgebra::Quaternion conjugate = rotationQuaternion.GetConjugate();
+
+ targetMem.v[0] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(1,0,0)*conjugate).imaginary, 0 );
+ targetMem.v[1] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(0,1,0)*conjugate).imaginary, 0 );
+ targetMem.v[2] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(0,0,1)*conjugate).imaginary, 0 );
+ targetMem.v[3] = ::LinearAlgebra::Vector4( translation, 1 );
+ return targetMem;
+ }
+
+ template
+ inline ::LinearAlgebra::Matrix4x4 & OrientationMatrix( const ::LinearAlgebra::Quaternion &rotationQuaternion, const ::LinearAlgebra::Vector4 &translation, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
+ {
+ ::LinearAlgebra::Quaternion conjugate = rotationQuaternion.GetConjugate();
+
+ targetMem.v[0] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(1,0,0)*conjugate).imaginary, 0 );
+ targetMem.v[1] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(0,1,0)*conjugate).imaginary, 0 );
+ targetMem.v[2] = ::LinearAlgebra::Vector4( (rotationQuaternion*::LinearAlgebra::Vector3(0,0,1)*conjugate).imaginary, 0 );
+ targetMem.v[3] = translation;
+ return targetMem;
+ }
+
+ template
+ inline ::LinearAlgebra::Matrix4x4 & ViewMatrix( const ::LinearAlgebra::Quaternion &rotationQuaternion, const ::LinearAlgebra::Vector3 &translation, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
+ {
+ OrientationMatrix( rotationQuaternion, translation, targetMem );
+ return InverseOrientationMatrix( targetMem, targetMem );
+ }
+
+ template
+ inline ::LinearAlgebra::Matrix4x4 & ViewMatrix( const ::LinearAlgebra::Quaternion &rotationQuaternion, const ::LinearAlgebra::Vector4 &translation, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
+ {
+ OrientationMatrix( rotationQuaternion, translation, targetMem );
+ return InverseOrientationMatrix( targetMem, targetMem );
+ }
+
template
inline ::LinearAlgebra::Matrix3x3 & RotationMatrix_AxisX( const ScalarType &radian, ::LinearAlgebra::Matrix3x3 &targetMem = ::LinearAlgebra::Matrix3x3() )
{
@@ -400,18 +506,35 @@ namespace LinearAlgebra3D
}
template
- ::LinearAlgebra::Matrix4x4 & OrientationMatrix( const ::LinearAlgebra::Vector3 &sumDeltaAngularAxis, const ::LinearAlgebra::Vector3 &sumTranslation, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
- { /** @todo TODO: not tested */
- ScalarType radian = sumDeltaAngularAxis.Dot( sumDeltaAngularAxis );
+ ::LinearAlgebra::Matrix4x4 & OrientationMatrix( const ::LinearAlgebra::Vector3 &angularAxis, const ::LinearAlgebra::Vector3 &translation, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
+ {
+ ScalarType radian = angularAxis.Dot( angularAxis );
if( radian > 0 )
{
radian = ::std::sqrt( radian );
- return OrientationMatrix( sumDeltaAngularAxis / radian, radian, sumTranslation, targetMem );
+ return OrientationMatrix( angularAxis / radian, radian, translation, targetMem );
}
else
{
targetMem = ::LinearAlgebra::Matrix4x4::identity;
- targetMem.v[3].xyz = sumTranslation;
+ targetMem.v[3].xyz = translation;
+ return targetMem;
+ }
+ }
+
+ template
+ ::LinearAlgebra::Matrix4x4 & ViewMatrix( const ::LinearAlgebra::Vector3 &angularAxis, const ::LinearAlgebra::Vector3 &translation, ::LinearAlgebra::Matrix4x4 &targetMem = ::LinearAlgebra::Matrix4x4() )
+ {
+ ScalarType radian = angularAxis.Dot( angularAxis );
+ if( radian > 0 )
+ {
+ radian = ::std::sqrt( radian );
+ return InverseOrientationMatrix( OrientationMatrix(angularAxis / radian, radian, translation, targetMem) );
+ }
+ else
+ {
+ targetMem = ::LinearAlgebra::Matrix4x4::identity;
+ targetMem.v[3].xyz = -translation;
return targetMem;
}
}
@@ -534,9 +657,17 @@ namespace LinearAlgebra3D
inline ::LinearAlgebra::Vector3 VectorProjection( const ::LinearAlgebra::Vector3 &vector, const ::LinearAlgebra::Vector3 &axis )
{ return axis * ( vector.Dot(axis) / axis.Dot(axis) ); }
+ template
+ inline ::LinearAlgebra::Vector4 VectorProjection( const ::LinearAlgebra::Vector4 &vector, const ::LinearAlgebra::Vector4 &axis )
+ { return axis * ( vector.Dot(axis) / axis.Dot(axis) ); }
+
template
inline ::LinearAlgebra::Vector3 NormalProjection( const ::LinearAlgebra::Vector3 &vector, const ::LinearAlgebra::Vector3 &normalizedAxis )
{ return normalizedAxis * ( vector.Dot(normalizedAxis) ); }
+
+ template
+ inline ::LinearAlgebra::Vector4 NormalProjection( const ::LinearAlgebra::Vector4 &vector, const ::LinearAlgebra::Vector4 &normalizedAxis )
+ { return normalizedAxis * ( vector.Dot(normalizedAxis) ); }
}
#include "Utilities.h"
diff --git a/Code/OysterMath/OysterMath.cpp b/Code/OysterMath/OysterMath.cpp
index cf9fa8ae..f44de9fd 100644
--- a/Code/OysterMath/OysterMath.cpp
+++ b/Code/OysterMath/OysterMath.cpp
@@ -91,11 +91,61 @@ namespace Oyster { namespace Math3D
return ::LinearAlgebra3D::AngularAxis( rotationMatrix );
}
+ Float4 ExtractAngularAxis( const Float4x4 &orientationMatrix )
+ {
+ return ::LinearAlgebra3D::ExtractAngularAxis( orientationMatrix );
+ }
+
Float4x4 & TranslationMatrix( const Float3 &position, Float4x4 &targetMem )
{
return ::LinearAlgebra3D::TranslationMatrix( position, targetMem );
}
+ Quaternion Rotation( Float radian, const Float3 &normalizedAxis )
+ {
+ return ::LinearAlgebra3D::Rotation( radian, normalizedAxis );
+ }
+
+ Quaternion Rotation( Float radian, const Float4 &normalizedAxis )
+ {
+ return ::LinearAlgebra3D::Rotation( radian, normalizedAxis );
+ }
+
+ Quaternion Rotation( const Float3 &angularAxis )
+ {
+ return ::LinearAlgebra3D::Rotation( angularAxis );
+ }
+
+ Quaternion Rotation( const Float4 &angularAxis )
+ {
+ return ::LinearAlgebra3D::Rotation( angularAxis );
+ }
+
+ Float4x4 & RotationMatrix( const Quaternion &rotationQuaternion, Float4x4 &targetMem )
+ {
+ return ::LinearAlgebra3D::RotationMatrix( rotationQuaternion, targetMem );
+ }
+
+ Float4x4 & OrientationMatrix( const Quaternion &rotationQuaternion, const Float3 &translation, Float4x4 &targetMem )
+ {
+ return ::LinearAlgebra3D::OrientationMatrix( rotationQuaternion, translation, targetMem );
+ }
+
+ Float4x4 & OrientationMatrix( const Quaternion &rotationQuaternion, const Float4 &translation, Float4x4 &targetMem )
+ {
+ return ::LinearAlgebra3D::OrientationMatrix( rotationQuaternion, translation, targetMem );
+ }
+
+ Float4x4 & ViewMatrix( const Quaternion &rotationQuaternion, const Float3 &translation, Float4x4 &targetMem )
+ {
+ return ::LinearAlgebra3D::ViewMatrix( rotationQuaternion, translation, targetMem );
+ }
+
+ Float4x4 & ViewMatrix( const Quaternion &rotationQuaternion, const Float4 &translation, Float4x4 &targetMem )
+ {
+ return ::LinearAlgebra3D::ViewMatrix( rotationQuaternion, translation, targetMem );
+ }
+
Float4x4 & RotationMatrix_AxisX( const Float &radian, Float4x4 &targetMem )
{
return ::LinearAlgebra3D::RotationMatrix_AxisX( radian, targetMem );
@@ -147,9 +197,14 @@ namespace Oyster { namespace Math3D
return ::LinearAlgebra3D::OrientationMatrix( normalizedAxis, deltaRadian, sumTranslation, targetMem );
}
- Float4x4 & OrientationMatrix( const Float3 &sumDeltaAngularAxis, const Float3 &sumTranslation, Float4x4 &targetMem )
+ Float4x4 & OrientationMatrix( const Float3 &angularAxis, const Float3 &translation, Float4x4 &targetMem )
{
- return ::LinearAlgebra3D::OrientationMatrix( sumDeltaAngularAxis, sumTranslation, targetMem );
+ return ::LinearAlgebra3D::OrientationMatrix( angularAxis, translation, targetMem );
+ }
+
+ Float4x4 & ViewMatrix( const Float3 &angularAxis, const Float3 &translation, Float4x4 &targetMem )
+ {
+ return ::LinearAlgebra3D::ViewMatrix( angularAxis, translation, targetMem );
}
Float4x4 & OrientationMatrix( const Float3 &sumDeltaAngularAxis, const Float3 &sumTranslation, const Float3 ¢erOfMass, Float4x4 &targetMem )
@@ -207,8 +262,18 @@ namespace Oyster { namespace Math3D
return ::LinearAlgebra3D::VectorProjection( vector, axis );
}
+ Float4 VectorProjection( const Float4 &vector, const Float4 &axis )
+ {
+ return ::LinearAlgebra3D::VectorProjection( vector, axis );
+ }
+
Float3 NormalProjection( const Float3 &vector, const Float3 &normalizedAxis )
{
return ::LinearAlgebra3D::NormalProjection( vector, normalizedAxis );
}
+
+ Float4 NormalProjection( const Float4 &vector, const Float4 &normalizedAxis )
+ {
+ return ::LinearAlgebra3D::NormalProjection( vector, normalizedAxis );
+ }
} }
\ No newline at end of file
diff --git a/Code/OysterMath/OysterMath.h b/Code/OysterMath/OysterMath.h
index 72fe7478..2fe57718 100644
--- a/Code/OysterMath/OysterMath.h
+++ b/Code/OysterMath/OysterMath.h
@@ -9,17 +9,19 @@
#include "LinearMath.h"
#include
-namespace Oyster { namespace Math /// Oyster's native math library
+namespace Oyster { namespace Math //! Oyster's native math library
{
- typedef float Float; /// Oyster's native scalar is float
+ typedef float Float; //!< Oyster's native scalar is float
- typedef ::LinearAlgebra::Vector2 Float2; /// 2D Linear Vector for Oyster
- typedef ::LinearAlgebra::Vector3 Float3; /// 3D Linear Vector for Oyster
- typedef ::LinearAlgebra::Vector4 Float4; /// 4D Linear Vector for Oyster
+ typedef ::LinearAlgebra::Vector2 Float2; //!< 2D Linear Vector for Oyster
+ typedef ::LinearAlgebra::Vector3 Float3; //!< 3D Linear Vector for Oyster
+ typedef ::LinearAlgebra::Vector4 Float4; //!< 4D Linear Vector for Oyster
- typedef ::LinearAlgebra::Matrix2x2 Float2x2; /// 2x2 Linear Matrix for Oyster
- typedef ::LinearAlgebra::Matrix3x3 Float3x3; /// 3x3 Linear Matrix for Oyster
- typedef ::LinearAlgebra::Matrix4x4 Float4x4; /// 4x4 Linear Matrix for Oyster
+ typedef ::LinearAlgebra::Matrix2x2 Float2x2; //!< 2x2 Linear Matrix for Oyster
+ typedef ::LinearAlgebra::Matrix3x3 Float3x3; //!< 3x3 Linear Matrix for Oyster
+ typedef ::LinearAlgebra::Matrix4x4 Float4x4; //!< 4x4 Linear Matrix for Oyster
+
+ typedef ::LinearAlgebra::Quaternion Quaternion; //!< Quaternion for Oyster
typedef Float4x4 Matrix; // by popular demand
typedef Float2 Vector2; // by popular demand
@@ -28,20 +30,20 @@ namespace Oyster { namespace Math /// Oyster's native math library
const Float pi = 3.1415926535897932384626433832795f;
- /// Function Highly recommended to check at start, just in case current version is using a feature that might be available.
- /// @todo TODO: create a template UniquePointer to use here
+ //! Function Highly recommended to check at start, just in case current version is using a feature that might be available.
+ //! @todo TODO: create a template UniquePointer to use here
bool IsSupported();
- /// Creates a solution matrix for 'out´= 'targetMem' * 'in'.
- /// Returns false if there is no explicit solution.
+ //! Creates a solution matrix for 'out´= 'targetMem' * 'in'.
+ //! Returns false if there is no explicit solution.
bool SuperpositionMatrix( const Float2x2 &in, const Float2x2 &out, Float2x2 &targetMem );
- /// Creates a solution matrix for 'out´= 'targetMem' * 'in'.
- /// Returns false if there is no explicit solution.
+ //! Creates a solution matrix for 'out´= 'targetMem' * 'in'.
+ //! Returns false if there is no explicit solution.
bool SuperpositionMatrix( const Float3x3 &in, const Float3x3 &out, Float3x3 &targetMem );
- /// Creates a solution matrix for 'out´= 'targetMem' * 'in'.
- /// Returns false if there is no explicit solution.
+ //! Creates a solution matrix for 'out´= 'targetMem' * 'in'.
+ //! Returns false if there is no explicit solution.
bool SuperpositionMatrix( const Float4x4 &in, const Float4x4 &out, Float4x4 &targetMem );
} }
@@ -96,54 +98,54 @@ inline ::Oyster::Math::Float3x3 operator * ( const ::Oyster::Math::Float &left,
inline ::Oyster::Math::Float4x4 operator * ( const ::Oyster::Math::Float &left, const ::Oyster::Math::Float4x4 &right )
{ return ::Oyster::Math::Float4x4(right) *= left; }
-namespace Oyster { namespace Math2D /// Oyster's native math library specialized for 2D
+namespace Oyster { namespace Math2D //! Oyster's native math library specialized for 2D
{
using namespace ::Oyster::Math; // deliberate inheritance from ::Oyster::Math namespace
- /// If there is an Y-axis on a 2D plane, then there is an explicit X-axis on and that is what is returned.
- /// Recommended too make sure that yAxis is normalized.
+ //! If there is an Y-axis on a 2D plane, then there is an explicit X-axis on and that is what is returned.
+ //! Recommended too make sure that yAxis is normalized.
Float2 X_AxisTo( const Float2 &yAxis );
- /// If there is an X-axis on a 2D plane, then there is an explicit Y-axis and that is what is returned.
- /// Recommended too make sure that yAxis is normalized.
+ //! If there is an X-axis on a 2D plane, then there is an explicit Y-axis and that is what is returned.
+ //! Recommended too make sure that yAxis is normalized.
Float2 Y_AxisTo( const Float2 &xAxis );
- /// Sets and returns targetMem to a translationMatrix with position as translation.
+ //! Sets and returns targetMem to a translationMatrix with position as translation.
Float3x3 & TranslationMatrix( const Float2 &position, Float3x3 &targetMem = Float3x3() );
- /// Sets and returns targetMem as a counterclockwise rotationMatrix
+ //! Sets and returns targetMem as a counterclockwise rotationMatrix
Float3x3 & RotationMatrix( const Float &radian, Float3x3 &targetMem = Float3x3() );
- /// If rotation is assumed to be by all definitions a rotation matrix. Then this is a much faster inverse method.
+ //! If rotation is assumed to be by all definitions a rotation matrix. Then this is a much faster inverse method.
Float2x2 & InverseRotationMatrix( const Float2x2 &rotation, Float2x2 &targetMem = Float2x2() );
- /// If rotation is assumed to be by all definitions a rotation matrix. Then this is a much faster inverse method.
+ //! If rotation is assumed to be by all definitions a rotation matrix. Then this is a much faster inverse method.
Float3x3 & InverseRotationMatrix( const Float3x3 &rotation, Float3x3 &targetMem = Float3x3() );
- /// Sets and returns targetMem as an orientation Matrix composed by the rotation matrix and translation vector
+ //! Sets and returns targetMem as an orientation Matrix composed by the rotation matrix and translation vector
Float3x3 & OrientationMatrix( const Float2x2 &rotation, const Float2 &translation, Float3x3 &targetMem = Float3x3() );
- /// Sets and returns targetMem as an orientation Matrix composed by the rotation matrix and translation vector
+ //! Sets and returns targetMem as an orientation Matrix composed by the rotation matrix and translation vector
Float3x3 & OrientationMatrix( const Float3x3 &rotation, const Float2 &translation, Float3x3 &targetMem = Float3x3() );
- /// Sets and returns targetMem as an orientation Matrix with position as translation and radian rotation
+ //! Sets and returns targetMem as an orientation Matrix with position as translation and radian rotation
Float3x3 & OrientationMatrix( const Float2 &position, const Float &radian, Float3x3 &targetMem = Float3x3() );
- /// Sets and returns targetMem as an orientation Matrix with position as translation and local y-axis directed at lookAt
+ //! Sets and returns targetMem as an orientation Matrix with position as translation and local y-axis directed at lookAt
Float3x3 & OrientationMatrix( const Float2 &position, const Float2 &lookAt, Float3x3 &targetMem = Float3x3() );
- /// Sets and returns targetMem as an orientation Matrix that is rotated around localCenterOfRotation and then translated with position.
- /// TODO: not tested
+ //! Sets and returns targetMem as an orientation Matrix that is rotated around localCenterOfRotation and then translated with position.
+ //! TODO: not tested
Float3x3 & OrientationMatrix( const Float2 &position, Float radian, const Float2 &localCenterOfRotation, Float3x3 &targetMem = Float3x3() );
- /// If orientationMatrix is assumed to be by all definitions a rigid orientation matrix aka rigid body matrix. Then this is a much faster inverse method.
+ //! If orientationMatrix is assumed to be by all definitions a rigid orientation matrix aka rigid body matrix. Then this is a much faster inverse method.
Float3x3 & InverseOrientationMatrix( const Float3x3 &orientationMatrix, Float3x3 &targetMem = Float3x3() );
- /// Returns targetmem after writing the rotation data from orientation, into it.
+ //! Returns targetmem after writing the rotation data from orientation, into it.
Float3x3 & ExtractRotationMatrix( const Float3x3 &orientation, Float3x3 &targetMem = Float3x3() );
} }
-namespace Oyster { namespace Math3D /// Oyster's native math library specialized for 3D
+namespace Oyster { namespace Math3D //! Oyster's native math library specialized for 3D
{
using namespace ::Oyster::Math; // deliberate inheritance from ::Oyster::Math namespace
@@ -153,35 +155,65 @@ namespace Oyster { namespace Math3D /// Oyster's native math library specialized
//! Extracts the angularAxis from rotationMatrix
Float4 AngularAxis( const Float4x4 &rotationMatrix );
- /// Sets and returns targetMem to a translationMatrix with position as translation.
+ //! Extracts the angularAxis from orientationMatrix
+ Float4 ExtractAngularAxis( const Float4x4 &orientationMatrix );
+
+ //! Sets and returns targetMem to a translationMatrix with position as translation.
Float4x4 & TranslationMatrix( const Float3 &position, Float4x4 &targetMem = Float4x4() );
- /// Sets and returns targetMem as an counterclockwise rotation matrix around the global X-axis
+ /** @todo TODO: add doc */
+ Quaternion Rotation( Float radian, const Float3 &normalizedAxis );
+
+ /** @todo TODO: add doc */
+ Quaternion Rotation( Float radian, const Float3 &normalizedAxis );
+
+ /** @todo TODO: add doc */
+ Quaternion Rotation( const Float3 &angularAxis );
+
+ /** @todo TODO: add doc */
+ Quaternion Rotation( const Float4 &angularAxis );
+
+ /** @todo TODO: add doc */
+ Float4x4 & RotationMatrix( const Quaternion &rotationQuaternion, Float4x4 &targetMem = Float4x4() );
+
+ /** @todo TODO: add doc */
+ Float4x4 & OrientationMatrix( const Quaternion &rotationQuaternion, const Float3 &translation, Float4x4 &targetMem = Float4x4() );
+
+ /** @todo TODO: add doc */
+ Float4x4 & OrientationMatrix( const Quaternion &rotationQuaternion, const Float4 &translation, Float4x4 &targetMem = Float4x4() );
+
+ /** @todo TODO: add doc */
+ Float4x4 & ViewMatrix( const Quaternion &rotationQuaternion, const Float3 &translation, Float4x4 &targetMem = Float4x4() );
+
+ /** @todo TODO: add doc */
+ Float4x4 & ViewMatrix( const Quaternion &rotationQuaternion, const Float4 &translation, Float4x4 &targetMem = Float4x4() );
+
+ //! Sets and returns targetMem as an counterclockwise rotation matrix around the global X-axis
Float4x4 & RotationMatrix_AxisX( const Float &radian, Float4x4 &targetMem = Float4x4() );
- /// Sets and returns targetMem as an counterclockwise rotation matrix around the global Y-axis
+ //! Sets and returns targetMem as an counterclockwise rotation matrix around the global Y-axis
Float4x4 & RotationMatrix_AxisY( const Float &radian, Float4x4 &targetMem = Float4x4() );
- /// Sets and returns targetMem as an counterclockwise rotation matrix around the global Z-axis
+ //! Sets and returns targetMem as an counterclockwise rotation matrix around the global Z-axis
Float4x4 & RotationMatrix_AxisZ( const Float &radian, Float4x4 &targetMem = Float4x4() );
- /// Sets and returns targetMem as an counterclockwise rotation matrix around the angularAxis.
+ //! Sets and returns targetMem as an counterclockwise rotation matrix around the angularAxis.
Float4x4 & RotationMatrix( const Float3 &angularAxis, Float4x4 &targetMem = Float4x4() );
- /// Sets and returns targetMem as an counterclockwise rotation matrix around the normalizedAxis.
- /// Please make sure normalizedAxis is normalized.
+ //! Sets and returns targetMem as an counterclockwise rotation matrix around the normalizedAxis.
+ //! Please make sure normalizedAxis is normalized.
Float4x4 & RotationMatrix( const Float &radian, const Float3 &normalizedAxis, Float4x4 &targetMem = Float4x4() );
- /// If rotation is assumed to be by all definitions a rotation matrix. Then this is a much faster inverse method.
+ //! If rotation is assumed to be by all definitions a rotation matrix. Then this is a much faster inverse method.
Float3x3 & InverseRotationMatrix( const Float3x3 &rotation, Float3x3 &targetMem = Float3x3() );
- /// If rotation is assumed to be by all definitions a rotation matrix. Then this is a much faster inverse method.
+ //! If rotation is assumed to be by all definitions a rotation matrix. Then this is a much faster inverse method.
Float4x4 & InverseRotationMatrix( const Float4x4 &rotation, Float4x4 &targetMem = Float4x4() );
- /// Sets and returns targetMem as an orientation Matrix composed by the rotation matrix and translation vector
+ //! Sets and returns targetMem as an orientation Matrix composed by the rotation matrix and translation vector
Float4x4 & OrientationMatrix( const Float3x3 &rotation, const Float3 &translation, Float4x4 &targetMem = Float4x4() );
- /// Sets and returns targetMem as an orientation Matrix composed by the rotation matrix and translation vector
+ //! Sets and returns targetMem as an orientation Matrix composed by the rotation matrix and translation vector
Float4x4 & OrientationMatrix( const Float4x4 &rotation, const Float3 &translation, Float4x4 &targetMem = Float4x4() );
/*******************************************************************
@@ -191,19 +223,26 @@ namespace Oyster { namespace Math3D /// Oyster's native math library specialized
* @param sumTranslation: sum of all the translation vectors.
* @param targetMem: is set to a rigibody matrix that rotate counterclockwise and then translates.
* @return targetMem
- * @todo TODO: not tested
*******************************************************************/
Float4x4 & OrientationMatrix( const Float3 &normalizedAxis, const Float & deltaRadian, const Float3 &sumTranslation, Float4x4 &targetMem = Float4x4() );
/*******************************************************************
* Sets and returns targetMem as an orientation Matrix
- * @param sumDeltaAngularAxis: sum of all ( (1/I) * ( L x D ) )-vectorproducts. There I is known as "moment of inertia", L as "angular momentum vector" and D the "lever vector".
- * @param sumTranslation: sum of all the translation vectors.
+ * @param angularAxis: sum of all ( (1/I) * ( L x D ) )-vectorproducts. There I is known as "moment of inertia", L as "angular momentum vector" and D the "lever vector".
+ * @param translation: sum of all the translation vectors.
* @param targetMem: is set to a rigibody matrix that rotate counterclockwise and then translates.
* @return targetMem
- * @todo TODO: not tested
*******************************************************************/
- Float4x4 & OrientationMatrix( const Float3 &sumDeltaAngularAxis, const Float3 &sumTranslation, Float4x4 &targetMem = Float4x4() );
+ Float4x4 & OrientationMatrix( const Float3 &angularAxis, const Float3 &translation, Float4x4 &targetMem = Float4x4() );
+
+ /*******************************************************************
+ * Sets and returns targetMem as a view Matrix
+ * @param angularAxis: sum of all ( (1/I) * ( L x D ) )-vectorproducts. There I is known as "moment of inertia", L as "angular momentum vector" and D the "lever vector".
+ * @param translation: sum of all the translation vectors.
+ * @param targetMem: is set to a rigibody matrix that rotate counterclockwise and then translates.
+ * @return targetMem
+ *******************************************************************/
+ Float4x4 & ViewMatrix( const Float3 &angularAxis, const Float3 &translation, Float4x4 &targetMem = Float4x4() );
/*******************************************************************
* Sets and returns targetMem as an orientation Matrix
@@ -228,14 +267,14 @@ namespace Oyster { namespace Math3D /// Oyster's native math library specialized
//! @todo TODO: Add documentation and not tested
Float4x4 & ViewMatrix_LookAtPos( const Float3 &worldLookAt, const Float3 &normalizedUpVector, const Float3 &worldPos, Float4x4 &targetMem = Float4x4() );
- /// If orientationMatrix is assumed to be by all definitions a rigid orientation matrix aka rigid body matrix. Then this is a much faster inverse method.
+ //! If orientationMatrix is assumed to be by all definitions a rigid orientation matrix aka rigid body matrix. Then this is a much faster inverse method.
Float4x4 & InverseOrientationMatrix( const Float4x4 &orientationMatrix, Float4x4 &targetMem = Float4x4() );
// O0 = T0 * R0
// O1 = T1 * T0 * R1 * R0
Float4x4 & UpdateOrientationMatrix( const Float3 &deltaPosition, const Float4x4 &deltaRotationMatrix, Float4x4 &orientationMatrix );
- /// Returns targetmem after writing the rotation data from orientation, into it.
+ //! Returns targetmem after writing the rotation data from orientation, into it.
Float4x4 & ExtractRotationMatrix( const Float4x4 &orientation, Float4x4 &targetMem = Float4x4() );
/*******************************************************************
@@ -262,13 +301,19 @@ namespace Oyster { namespace Math3D /// Oyster's native math library specialized
*******************************************************************/
Float4x4 & ProjectionMatrix_Perspective( const Float &verticalFoV, const Float &aspectRatio, const Float &nearClip = ::std::numeric_limits::epsilon(), const Float &farClip = ::std::numeric_limits::max(), Float4x4 &targetMem = Float4x4() );
- /// returns the component vector of vector that is parallell with axis
+ //! returns the component vector of vector that is parallell with axis
Float3 VectorProjection( const Float3 &vector, const Float3 &axis );
- /// returns the component vector of vector that is parallell with axis. Faster than VectorProjection.
+ //! returns the component vector of vector that is parallell with axis
+ Float4 VectorProjection( const Float4 &vector, const Float4 &axis );
+
+ //! returns the component vector of vector that is parallell with axis. Faster than VectorProjection.
Float3 NormalProjection( const Float3 &vector, const Float3 &normalizedAxis );
- /// Helper inline function that sets and then returns targetMem = projection * view
+ //! returns the component vector of vector that is parallell with axis. Faster than VectorProjection.
+ Float4 NormalProjection( const Float4 &vector, const Float4 &normalizedAxis );
+
+ //! Helper inline function that sets and then returns targetMem = projection * view
inline Float4x4 & ViewProjectionMatrix( const Float4x4 &view, const Float4x4 &projection, Float4x4 &targetMem = Float4x4() )
{ return targetMem = projection * view; }
@@ -280,7 +325,7 @@ namespace Oyster { namespace Math3D /// Oyster's native math library specialized
inline Float4x4 TransformMatrix( const Float4x4 &transformer, const Float4x4 &transformee )
{ return transformer * transformee; }
- /// Helper inline function that sets and then returns targetMem = transformer * transformee
+ //! Helper inline function that sets and then returns targetMem = transformer * transformee
inline Float4 & TransformVector( const Float4x4 &transformer, const Float4 &transformee, Float4 &targetMem = Float4() )
{ return targetMem = transformer * transformee; }
} }
diff --git a/Code/OysterMath/Quaternion.h b/Code/OysterMath/Quaternion.h
index fd19100f..da790f75 100644
--- a/Code/OysterMath/Quaternion.h
+++ b/Code/OysterMath/Quaternion.h
@@ -22,8 +22,10 @@ namespace LinearAlgebra
char byte[sizeof(ScalarType[2])];
};
+ static const Quaternion null;
+ static const Quaternion identity;
+
Quaternion( );
- Quaternion( const Quaternion &quaternion );
Quaternion( const Vector3 &imaginary, const ScalarType &real );
operator ScalarType* ( );
@@ -53,40 +55,54 @@ namespace LinearAlgebra
// Body
///////////////////////////////////////////////////////////////////////////////////
+ template const Quaternion Quaternion::null = Quaternion( Vector3((ScalarType)0), (ScalarType)0 );
+ template const Quaternion Quaternion::identity = Quaternion( Vector3((ScalarType)0), (ScalarType)1 );
+
template
Quaternion::Quaternion( ) : imaginary(), real() {}
template
- Quaternion::Quaternion( const Quaternion &quaternion )
- { this->imaginary = quaternion.imaginary; this->real = quaternion.real; }
-
- template
- Quaternion::Quaternion( const Vector3 &_imaginary, const ScalarType &_real )
- { this->imaginary = _imaginary; this->real = _real; }
+ Quaternion::Quaternion( const Vector3 &imaginary, const ScalarType &real )
+ {
+ this->imaginary = imaginary;
+ this->real = real;
+ }
template
inline Quaternion::operator ScalarType* ( )
- { return this->element; }
+ {
+ return this->element;
+ }
template
inline Quaternion::operator const ScalarType* ( ) const
- { return this->element; }
+ {
+ return this->element;
+ }
template
inline Quaternion::operator char* ( )
- { return this->byte; }
+ {
+ return this->byte;
+ }
template
inline Quaternion::operator const char* ( ) const
- { return this->byte; }
+ {
+ return this->byte;
+ }
template
inline ScalarType & Quaternion::operator [] ( int i )
- { return this->element[i]; }
+ {
+ return this->element[i];
+ }
template
inline const ScalarType & Quaternion::operator [] ( int i ) const
- { return this->element[i]; }
+ {
+ return this->element[i];
+ }
template
Quaternion & Quaternion::operator = ( const Quaternion &quaternion )
@@ -154,27 +170,39 @@ namespace LinearAlgebra
template
inline Quaternion Quaternion::operator * ( const ScalarType &scalar ) const
- { return Quaternion(*this) *= scalar; }
+ {
+ return Quaternion(*this) *= scalar;
+ }
template
inline Quaternion Quaternion::operator / ( const ScalarType &scalar ) const
- { return Quaternion(*this) /= scalar; }
+ {
+ return Quaternion(*this) /= scalar;
+ }
template
inline Quaternion Quaternion::operator + ( const Quaternion &quaternion ) const
- { return Quaternion(*this) += quaternion; }
+ {
+ return Quaternion(*this) += quaternion;
+ }
template
inline Quaternion Quaternion::operator - ( const Quaternion &quaternion ) const
- { return Quaternion(*this) -= quaternion; }
+ {
+ return Quaternion(*this) -= quaternion;
+ }
template
inline Quaternion Quaternion::operator - ( ) const
- { return Quaternion(-this->imaginary, -this->real); }
+ {
+ return Quaternion(-this->imaginary, -this->real);
+ }
template
inline Quaternion Quaternion::GetConjugate( ) const
- { return Quaternion(-this->imaginary, this->real ); }
+ {
+ return Quaternion(-this->imaginary, this->real );
+ }
}
#endif
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Box.cpp b/Code/OysterPhysics3D/Box.cpp
index 382c6732..f55415b7 100644
--- a/Code/OysterPhysics3D/Box.cpp
+++ b/Code/OysterPhysics3D/Box.cpp
@@ -16,10 +16,17 @@ Box::Box( ) : ICollideable(Type_box)
}
Box::Box( const Float4x4 &r, const Float3 &p, const Float3 &s ) : ICollideable(Type_box)
+{
+ this->rotation = r;
+ this->center = Float4( p, 1.0f );
+ this->boundingOffset = Float4( s * 0.5f , 0.0f);
+}
+
+Box::Box( const Float4x4 &r, const Float4 &p, const Float4 &s ) : ICollideable(Type_box)
{
this->rotation = r;
this->center = p;
- this->boundingOffset = Float3(s*0.5);
+ this->boundingOffset = s * 0.5f;
}
Box::~Box( ) {}
@@ -41,16 +48,35 @@ bool Box::Intersects( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_universe: return true;
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- case Type_ray: return Utility::Intersect( *this, *(Ray*)&target, ((Ray*)&target)->collisionDistance );
- case Type_sphere: return Utility::Intersect( *this, *(Sphere*)&target );
- case Type_plane: return Utility::Intersect( *this, *(Plane*)&target );
- // case Type_triangle: return false; // TODO: :
- case Type_box_axis_aligned: return Utility::Intersect( *this, *(BoxAxisAligned*)&target );
- case Type_box: return Utility::Intersect( *this, *(Box*)&target );
- // case Type_frustrum: return false; // TODO: :
- default: return false;
+ case Type_universe: return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, ((const Ray&)target).collisionDistance );
+ case Type_sphere: return Utility::Intersect( *this, (const Sphere&)target );
+ case Type_plane: return Utility::Intersect( *this, (const Plane&)target );
+ // case Type_triangle: return false; // TODO: :
+ case Type_box_axis_aligned: return Utility::Intersect( *this, (const BoxAxisAligned&)target );
+ case Type_box: return Utility::Intersect( *this, (const Box&)target );
+ // case Type_frustrum: return false; // TODO: :
+ default: return false;
+ }
+}
+
+bool Box::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{
+ switch( target.type )
+ {
+ case Type_universe:
+ worldPointOfContact = this->center;
+ return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target, worldPointOfContact );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, ((const Ray&)target).collisionDistance, worldPointOfContact );
+ case Type_sphere: return Utility::Intersect( *this, (const Sphere&)target, worldPointOfContact );
+ case Type_plane: return Utility::Intersect( *this, (const Plane&)target, worldPointOfContact );
+ // case Type_triangle: return false; // TODO: :
+ case Type_box_axis_aligned: return Utility::Intersect( *this, (const BoxAxisAligned&)target, worldPointOfContact );
+ case Type_box: return Utility::Intersect( *this, (const Box&)target, worldPointOfContact );
+ // case Type_frustrum: return false; // TODO: :
+ default: return false;
}
}
@@ -58,12 +84,12 @@ bool Box::Contains( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- // case Type_sphere: return false; // TODO:
- // case Type_triangle: return false; // TODO:
- // case Type_box_axis_aligned: return false; // TODO:
- // case Type_box: return false; // TODO:
- // case Type_frustrum: return false; // TODO:
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ //case Type_sphere: return false; // TODO:
+ //case Type_triangle: return false; // TODO:
+ //case Type_box_axis_aligned: return false; // TODO:
+ //case Type_box: return false; // TODO:
+ //case Type_frustrum: return false; // TODO:
default: return false;
}
}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Box.h b/Code/OysterPhysics3D/Box.h
index d40c9f30..f98ae362 100644
--- a/Code/OysterPhysics3D/Box.h
+++ b/Code/OysterPhysics3D/Box.h
@@ -16,24 +16,26 @@ namespace Oyster { namespace Collision3D
public:
union
{
- struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float3 center, boundingOffset; };
+ struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; };
struct
{
- ::Oyster::Math::Float3 xAxis; ::Oyster::Math::Float paddingA;
- ::Oyster::Math::Float3 yAxis; ::Oyster::Math::Float paddingB;
- ::Oyster::Math::Float3 zAxis; ::Oyster::Math::Float paddingC;
+ ::Oyster::Math::Float4 xAxis;
+ ::Oyster::Math::Float4 yAxis;
+ ::Oyster::Math::Float4 zAxis;
};
- char byte[sizeof(::Oyster::Math::Float4x4) + 2*sizeof(::Oyster::Math::Float3)];
+ 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 Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
diff --git a/Code/OysterPhysics3D/BoxAxisAligned.cpp b/Code/OysterPhysics3D/BoxAxisAligned.cpp
index f50f4b6d..bd10016f 100644
--- a/Code/OysterPhysics3D/BoxAxisAligned.cpp
+++ b/Code/OysterPhysics3D/BoxAxisAligned.cpp
@@ -14,16 +14,16 @@ BoxAxisAligned::BoxAxisAligned( ) : ICollideable(Type_box_axis_aligned)
this->maxVertex = Float3( 0.5f, 0.5f, 0.5f );
}
-BoxAxisAligned::BoxAxisAligned( const Float3 &_minVertex, const Float3 &_maxVertex ) : ICollideable(Type_box_axis_aligned)
+BoxAxisAligned::BoxAxisAligned( const Float3 &minVertex, const Float3 &maxVertex ) : ICollideable(Type_box_axis_aligned)
{
- this->minVertex = _minVertex;
- this->maxVertex = _maxVertex;
+ this->minVertex = Float4( minVertex, 1.0f );
+ this->maxVertex = Float4( maxVertex, 1.0f );
}
BoxAxisAligned::BoxAxisAligned( const Float &leftClip, const Float &rightClip, const Float &topClip, const Float &bottomClip, const Float &nearClip, const Float &farClip ) : ICollideable(Type_box_axis_aligned)
{
- this->minVertex = Float3( leftClip, bottomClip, nearClip );
- this->maxVertex = Float3( rightClip, topClip, farClip );
+ this->minVertex = Float4( leftClip, bottomClip, nearClip, 1.0f );
+ this->maxVertex = Float4( rightClip, topClip, farClip, 1.0f );
}
BoxAxisAligned::~BoxAxisAligned( ) {}
@@ -44,29 +44,36 @@ bool BoxAxisAligned::Intersects( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_universe: return true;
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- case Type_ray: return Utility::Intersect( *this, *(Ray*)&target, ((Ray*)&target)->collisionDistance );
- case Type_sphere: return Utility::Intersect( *this, *(Sphere*)&target );
- case Type_plane: return Utility::Intersect( *this, *(Plane*)&target );
- // case Type_triangle: return false; // TODO:
- case Type_box_axis_aligned: return Utility::Intersect( *this, *(BoxAxisAligned*)&target );
- // case Type_box: return false; // TODO:
- // case Type_frustrum: return false; // TODO:
- default: return false;
+ case Type_universe: return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, ((const Ray&)target).collisionDistance );
+ case Type_sphere: return Utility::Intersect( *this, (const Sphere&)target );
+ case Type_plane: return Utility::Intersect( *this, (const Plane&)target );
+ // case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( *this, (const BoxAxisAligned&)target );
+ // case Type_box: return false; // TODO:
+ // case Type_frustrum: return false; // TODO:
+ default: return false;
}
}
+bool BoxAxisAligned::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{
+ //! @todo TODO: implement stub properly
+ return this->Intersects( target );
+}
+
bool BoxAxisAligned::Contains( const ICollideable &target ) const
{
- switch( target.type )
- {
- // case Type_point: return false; // TODO:
- // case Type_sphere: return false; // TODO:
- // case Type_triangle: return false; // TODO:
- // case Type_box_axis_aligned: return false; // TODO:
- // case Type_box: return false; // TODO:
- // case Type_frustrum: return false; // TODO:
- default: return false;
- }
+ //switch( target.type )
+ //{
+ ////case Type_point: return false; // TODO:
+ ////case Type_sphere: return false; // TODO:
+ ////case Type_triangle: return false; // TODO:
+ ////case Type_box_axis_aligned: return false; // TODO:
+ ////case Type_box: return false; // TODO:
+ ////case Type_frustrum: return false; // TODO:
+ //default: return false;
+ //}
+ return false;
}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/BoxAxisAligned.h b/Code/OysterPhysics3D/BoxAxisAligned.h
index a0e109b2..2ff39463 100644
--- a/Code/OysterPhysics3D/BoxAxisAligned.h
+++ b/Code/OysterPhysics3D/BoxAxisAligned.h
@@ -16,8 +16,8 @@ namespace Oyster { namespace Collision3D
public:
union
{
- struct{ ::Oyster::Math::Float3 minVertex, maxVertex; };
- char byte[2*sizeof(::Oyster::Math::Float3)];
+ struct{ ::Oyster::Math::Float4 minVertex, maxVertex; };
+ char byte[2*sizeof(::Oyster::Math::Float4)];
};
BoxAxisAligned( );
@@ -29,6 +29,7 @@ namespace Oyster { namespace Collision3D
virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
diff --git a/Code/OysterPhysics3D/Frustrum.cpp b/Code/OysterPhysics3D/Frustrum.cpp
index 7099c2ce..54e6a67f 100644
--- a/Code/OysterPhysics3D/Frustrum.cpp
+++ b/Code/OysterPhysics3D/Frustrum.cpp
@@ -5,8 +5,8 @@
#include "Frustrum.h"
#include "OysterCollision3D.h"
-using namespace Oyster::Math;
-using namespace Oyster::Collision3D;
+using namespace ::Oyster::Math;
+using namespace ::Oyster::Collision3D;
namespace PrivateStatic
{
@@ -76,12 +76,12 @@ namespace PrivateStatic
Frustrum::Frustrum() : ICollideable(Type_frustrum)
{
- this->leftPlane = Plane( Float3::standard_unit_x, -0.5f );
- this->rightPlane = Plane(-Float3::standard_unit_x, 0.5f ),
- this->bottomPlane = Plane( Float3::standard_unit_y, -0.5f );
- this->topPlane = Plane(-Float3::standard_unit_y, 0.5f );
- this->nearPlane = Plane( Float3::standard_unit_z, -0.5f );
- this->farPlane = Plane(-Float3::standard_unit_z, 0.5f );
+ this->leftPlane = Plane( Float4::standard_unit_x, -0.5f );
+ this->rightPlane = Plane(-Float4::standard_unit_x, 0.5f ),
+ this->bottomPlane = Plane( Float4::standard_unit_y, -0.5f );
+ this->topPlane = Plane(-Float4::standard_unit_y, 0.5f );
+ this->nearPlane = Plane( Float4::standard_unit_z, -0.5f );
+ this->farPlane = Plane(-Float4::standard_unit_z, 0.5f );
}
Frustrum::Frustrum( const Float4x4 &vp ) : ICollideable(Type_frustrum)
@@ -198,39 +198,47 @@ void Frustrum::WriteToByte( unsigned int &nextIndex, unsigned char targetMem[] )
}
::Utility::DynamicMemory::UniquePointer Frustrum::Clone( ) const
-{ return ::Utility::DynamicMemory::UniquePointer( new Frustrum(*this) ); }
+{
+ return ::Utility::DynamicMemory::UniquePointer( new Frustrum(*this) );
+}
bool Frustrum::Intersects( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_universe: return true;
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- case Type_ray: return Utility::Intersect( *this, *(Ray*)&target, ((Ray*)&target)->collisionDistance );
- case Type_sphere: return Utility::Intersect( *this, *(Sphere*)&target );
- case Type_plane: return Utility::Intersect( *this, *(Plane*)&target );
- // case Type_triangle: return false; // TODO:
- case Type_box_axis_aligned: return Utility::Intersect( *this, *(BoxAxisAligned*)&target );
- case Type_box: return Utility::Intersect( *this, *(Box*)&target );
- case Type_frustrum: return Utility::Intersect( *this, *(Frustrum*)&target );
- // case Type_line: return false; // TODO:
- default: return false;
+ case Type_universe: return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, ((const Ray&)target).collisionDistance );
+ case Type_sphere: return Utility::Intersect( *this, (const Sphere&)target );
+ case Type_plane: return Utility::Intersect( *this, (const Plane&)target );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( *this, (const BoxAxisAligned&)target );
+ case Type_box: return Utility::Intersect( *this, (const Box&)target );
+ case Type_frustrum: return Utility::Intersect( *this, (const Frustrum&)target );
+ //case Type_line: return false; // TODO:
+ default: return false;
}
}
+bool Frustrum::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{
+ //! @todo TODO: implement stub properly
+ return this->Intersects( target );
+}
+
bool Frustrum::Contains( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- // case Type_ray: return false; // TODO:
- // case Type_sphere: return false; // TODO:
- // case Type_plane: return false; // TODO:
- // case Type_triangle: return false; // TODO:
- // case Type_box_axis_aligned: return false; // TODO:
- // case Type_box: return false; // TODO:
- // case Type_frustrum: return false; // TODO:
- // case Type_line: return false; // TODO:
- default: return false;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ //case Type_ray: return false; // TODO:
+ //case Type_sphere: return false; // TODO:
+ //case Type_plane: return false; // TODO:
+ //case Type_triangle: return false; // TODO:
+ //case Type_box_axis_aligned: return false; // TODO:
+ //case Type_box: return false; // TODO:
+ //case Type_frustrum: return false; // TODO:
+ //case Type_line: return false; // TODO:
+ default: return false;
}
}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Frustrum.h b/Code/OysterPhysics3D/Frustrum.h
index afd8d8bd..ba5656c5 100644
--- a/Code/OysterPhysics3D/Frustrum.h
+++ b/Code/OysterPhysics3D/Frustrum.h
@@ -39,6 +39,7 @@ namespace Oyster { namespace Collision3D
virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
diff --git a/Code/OysterPhysics3D/ICollideable.h b/Code/OysterPhysics3D/ICollideable.h
index 34a86f7b..b3f61671 100644
--- a/Code/OysterPhysics3D/ICollideable.h
+++ b/Code/OysterPhysics3D/ICollideable.h
@@ -6,6 +6,7 @@
#ifndef OYSTER_COLLISION_3D_ICOLLIDEABLE_H
#define OYSTER_COLLISION_3D_ICOLLIDEABLE_H
+#include "OysterMath.h"
#include "Utilities.h"
namespace Oyster { namespace Collision3D //! Contains a collection of 3D shapes and intercollission algorithms.
@@ -34,6 +35,7 @@ namespace Oyster { namespace Collision3D //! Contains a collection of 3D shapes
virtual ~ICollideable();
virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const = 0;
+ 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;
};
diff --git a/Code/OysterPhysics3D/Line.cpp b/Code/OysterPhysics3D/Line.cpp
index 17fe55f7..cebceaff 100644
--- a/Code/OysterPhysics3D/Line.cpp
+++ b/Code/OysterPhysics3D/Line.cpp
@@ -46,8 +46,29 @@ bool Line::Intersects( const ICollideable &target ) const
return true;
}
- if( this->ray.Intersects( target ) ) if( this->ray.collisionDistance >= 0.0f ) if( this->ray.collisionDistance <= this->length )
+ if( this->ray.Intersects(target) ) if( this->ray.collisionDistance >= 0.0f ) if( this->ray.collisionDistance <= this->length )
+ {
return true;
+ }
+
+ this->ray.collisionDistance = 0.0f;
+ return false;
+}
+
+bool Line::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{
+ if( target.type == Type_universe )
+ {
+ this->ray.collisionDistance = 0.0f;
+ worldPointOfContact = this->ray.origin;
+ return true;
+ }
+
+ if( this->ray.Intersects(target) ) if( this->ray.collisionDistance >= 0.0f ) if( this->ray.collisionDistance <= this->length )
+ {
+ worldPointOfContact = this->ray.origin + this->ray.direction * this->ray.collisionDistance;
+ return true;
+ }
this->ray.collisionDistance = 0.0f;
return false;
diff --git a/Code/OysterPhysics3D/Line.h b/Code/OysterPhysics3D/Line.h
index f062c0dc..2e6d2d55 100644
--- a/Code/OysterPhysics3D/Line.h
+++ b/Code/OysterPhysics3D/Line.h
@@ -30,6 +30,7 @@ namespace Oyster { namespace Collision3D
virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
diff --git a/Code/OysterPhysics3D/OysterCollision3D.cpp b/Code/OysterPhysics3D/OysterCollision3D.cpp
index 5df9761c..3ef44974 100644
--- a/Code/OysterPhysics3D/OysterCollision3D.cpp
+++ b/Code/OysterPhysics3D/OysterCollision3D.cpp
@@ -30,10 +30,10 @@ namespace Oyster { namespace Collision3D { namespace Utility
}
// returns true if miss/reject
- bool BoxVsRayPerSlabCheck( const Float3 &axis, const Float &boundingOffset, const Float3 &deltaPos, const Float3 rayDirection, Float &tMin, Float &tMax )
+ bool BoxVsRayPerSlabCheck( const Float4 &axis, const Float &boundingOffset, const Float4 &deltaPos, const Float4 rayDirection, Float &tMin, Float &tMax )
{ // by Dan Andersson
Float e = axis.Dot( deltaPos ),
- f = axis.Dot( rayDirection );
+ f = axis.Dot( rayDirection );
if( EqualsZero(f) ) // if axis is not parallell with ray
{
Float t1 = e + boundingOffset,
@@ -51,12 +51,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return false;
}
- inline bool Contains( const Plane &container, const Float3 &pos )
+ inline bool Contains( const Plane &container, const Float4 &pos )
{ // by Dan Andersson
return EqualsZero( container.normal.Dot( pos ) + container.phasing );
}
- inline void Compare( Float &connectOffset, const Plane &plane, const Float3 &pos )
+ inline void Compare( Float &connectOffset, const Plane &plane, const Float4 &pos )
{ // by Dan Andersson
connectOffset = plane.normal.Dot(pos);
connectOffset += plane.phasing;
@@ -64,7 +64,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
void Compare( Float &boxExtend, Float ¢erDistance, const Plane &plane, const BoxAxisAligned &box )
{ // by Dan Andersson
- Float3 c = (box.maxVertex + box.minVertex) * 0.5f, // box.Center
+ Float4 c = (box.maxVertex + box.minVertex) * 0.5f, // box.Center
h = (box.maxVertex - box.minVertex) * 0.5f; // box.halfSize
boxExtend = h.x * Abs(plane.normal.x); // Box max extending towards plane
boxExtend += h.y * Abs(plane.normal.y);
@@ -81,7 +81,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
centerDistance = box.center.Dot(plane.normal) + plane.phasing; // distance between box center and plane
}
- bool SeperatingAxisTest_AxisAlignedVsTransformedBox( const Float3 &boundingOffsetA, const Float3 &boundingOffsetB, const Float4x4 &rotationB, const Float3 &worldOffset )
+ bool SeperatingAxisTest_AxisAlignedVsTransformedBox( const Float4 &boundingOffsetA, const Float4 &boundingOffsetB, const Float4x4 &rotationB, const Float4 &worldOffset )
{ // by Dan Andersson
/*****************************************************************
@@ -103,37 +103,37 @@ namespace Oyster { namespace Collision3D { namespace Utility
Float3 absWorldOffset = Abs(worldOffset); // |t|: [absWorldOffset]
// s = { 1, 0, 0 } [ RA.v[0] ]
- if( absWorldOffset.x > boundingOffsetA.x + boundingOffsetB.Dot(Float3(absRotationB.v[0].x, absRotationB.v[1].x, absRotationB.v[2].x)) )
+ if( absWorldOffset.x > boundingOffsetA.x + boundingOffsetB.Dot(Float4(absRotationB.v[0].x, absRotationB.v[1].x, absRotationB.v[2].x, 0.0f)) )
{ // |t dot s| > hA dot |s| + hB dot |s * RB| -->> t.x > hA.x + hB dot |{RB.v[0].x, RB.v[1].x, RB.v[2].x}|
return false;
}
// s = { 0, 1, 0 } [ RA.v[1] ]
- if( absWorldOffset.y > boundingOffsetA.y + boundingOffsetB.Dot(Float3(absRotationB.v[0].y, absRotationB.v[1].y, absRotationB.v[2].y)) )
+ if( absWorldOffset.y > boundingOffsetA.y + boundingOffsetB.Dot(Float4(absRotationB.v[0].y, absRotationB.v[1].y, absRotationB.v[2].y, 0.0f)) )
{ // t.y > hA.y + hB dot |{RB.v[0].y, RB.v[1].y, RB.v[2].y}|
return false;
}
// s = { 0, 0, 1 } [ RA.v[2] ]
- if( absWorldOffset.z > boundingOffsetA.z + boundingOffsetB.Dot(Float3(absRotationB.v[0].z, absRotationB.v[1].z, absRotationB.v[2].z)) )
+ if( absWorldOffset.z > boundingOffsetA.z + boundingOffsetB.Dot(Float4(absRotationB.v[0].z, absRotationB.v[1].z, absRotationB.v[2].z, 0.0f)) )
{ // t.z > hA.z + hB dot |{RB.v[0].z, RB.v[1].z, RB.v[2].z}|
return false;
}
// s = RB.v[0].xyz
- if( Abs(worldOffset.Dot(rotationB.v[0].xyz)) > boundingOffsetA.Dot(absRotationB.v[0].xyz) + boundingOffsetB.x )
+ if( Abs(worldOffset.Dot(rotationB.v[0])) > boundingOffsetA.Dot(absRotationB.v[0]) + boundingOffsetB.x )
{ // |t dot s| > hA dot |s| + hB dot |s * RB| -->> |t dot s| > hA dot |s| + hB dot |{1, 0, 0}| -->> |t dot s| > hA dot |s| + hB.x
return false;
}
// s = RB.v[1].xyz
- if( Abs(worldOffset.Dot(rotationB.v[1].xyz)) > boundingOffsetA.Dot(absRotationB.v[1].xyz) + boundingOffsetB.y )
+ if( Abs(worldOffset.Dot(rotationB.v[1])) > boundingOffsetA.Dot(absRotationB.v[1]) + boundingOffsetB.y )
{ // |t dot s| > hA dot |s| + hB.y
return false;
}
// s = RB.v[2].xyz
- if( Abs(worldOffset.Dot(rotationB.v[2].xyz)) > boundingOffsetA.Dot(absRotationB.v[2].xyz) + boundingOffsetB.z )
+ if( Abs(worldOffset.Dot(rotationB.v[2])) > boundingOffsetA.Dot(absRotationB.v[2]) + boundingOffsetB.z )
{ // |t dot s| > hA dot |s| + hB.z
return false;
}
@@ -203,13 +203,187 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
+
+ bool SeperatingAxisTest_AxisAlignedVsTransformedBox( const Float4 &boundingOffsetA, const Float4 &boundingOffsetB, const Float4x4 &rotationB, const Float4 &worldOffset, Float4 &worldPointOfContact )
+ { // by Dan Andersson
+
+ /*****************************************************************
+ * Uses the Seperating Axis Theorem
+ * if( |t dot s| > hA dot |s * RA| + hB dot |s * RB| ) then not intersecting
+ * |t dot s| > hA dot |s| + hB dot |s * RB| .. as RA = I
+ *
+ * t: objectB's offset from objectA [worldOffset]
+ * s: current comparison axis
+ * hA: boundingReach vector of objectA. Only absolute values is assumed. [boundingOffsetA]
+ * hB: boundingReach vector of objectB. Only absolute values is assumed. [boundingOffsetB]
+ * RA: rotation matrix of objectA. Is identity matrix here, thus omitted.
+ * RB: rotation matrix of objectB. Is transformed into objectA's view at this point. [rotationB]
+ *
+ * Note: s * RB = (RB^T * s)^T = (RB^-1 * s)^T .... vector == vector^T
+ *****************************************************************/
+
+ /*****************************************************************
+ * Distance Alghorithm based on .. something Dan came up with
+ * pi = si * ( (t dot si) * (hA dot |si|) / (hA dot |si| + hB dot |si * RB|) )
+ * p = estimated point of contact
+ * = ( p1 + p2 + ... + p5 + p6 ) / 2
+ *****************************************************************/
+
+ const Float4 &t = worldOffset,
+ &hA = boundingOffsetA,
+ &hB = boundingOffsetB;
+ Float4 s = Float4::standard_unit_x;
+
+ Float centerSeperation = t.Dot(s),
+ eA = hA.Dot( Abs(s) ),
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+ worldPointOfContact = s * ( centerSeperation * eA / edgeSeperation );
+
+ s = Float4::standard_unit_y;
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+ worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
+
+ s = Float4::standard_unit_z;
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+ worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
+
+ s = rotationB.v[0];
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+ worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
+
+ s = rotationB.v[1];
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+ worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation );
+
+ s = rotationB.v[2];
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+ worldPointOfContact += s * ( centerSeperation * eA / edgeSeperation ); // enough point of contact data gathered for approximative result.
+
+ s = Float4( Float3::standard_unit_x.Cross(rotationB.v[0].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ s = Float4( Float3::standard_unit_x.Cross(rotationB.v[1].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ s = Float4( Float3::standard_unit_x.Cross(rotationB.v[2].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ s = Float4( Float3::standard_unit_y.Cross(rotationB.v[0].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ s = Float4( Float3::standard_unit_y.Cross(rotationB.v[1].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ s = Float4( Float3::standard_unit_y.Cross(rotationB.v[2].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ s = Float4( Float3::standard_unit_z.Cross(rotationB.v[0].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ s = Float4( Float3::standard_unit_z.Cross(rotationB.v[1].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ s = Float4( Float3::standard_unit_z.Cross(rotationB.v[2].xyz), 0.0f );
+ centerSeperation = t.Dot(s);
+ eA = hA.Dot( Abs(s) );
+ edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
+ if( Abs(centerSeperation) > edgeSeperation )
+ { // no intersection
+ return false;
+ }
+
+ worldPointOfContact *= 0.5f;
+ return true;
+ }
}
// PUBLIC BODY //////////////////////////////////////////////////////
void Compare( Float &connectDistance, Float &connectOffsetSquared, const Ray &ray, const Point &point )
{ // by Dan Andersson
- Float3 dP = point.center - ray.origin;
+ Float4 dP = point.center - ray.origin;
connectDistance = dP.Dot( ray.direction );
connectDistance /= ray.direction.Dot( ray.direction );
@@ -220,7 +394,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
void Compare( Float &connectDistanceA, Float &connectDistanceB, Float &connectOffsetSquared, const Ray &rayA, const Ray &rayB )
{ // by Dan Andersson
- Float3 dP = rayB.origin - rayA.origin;
+ Float4 dP = rayB.origin - rayA.origin;
connectDistanceA = rayA.direction.Dot( dP );
connectDistanceA /= rayA.direction.Dot( rayA.direction );
@@ -249,6 +423,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true; // Passed all tests, is in same position
}
+ bool Intersect( const Point &pointA, const Point &pointB, ::Oyster::Math::Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const Ray &ray, const Point &point, Float &connectDistance )
{ // by Dan Andersson
Float connectOffsetSquared;
@@ -264,6 +444,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return false;
}
+ bool Intersect( const Ray &ray, const Point &point, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const Ray &rayA, const Ray &rayB, Float &connectDistanceA, Float &connectDistanceB )
{ // by Dan Andersson
Float connectOffsetSquared;
@@ -279,6 +465,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return false;
}
+ bool Intersect( const Ray &rayA, const Ray &rayB, ::Oyster::Math::Float &connectDistanceA, ::Oyster::Math::Float &connectDistanceB, ::Oyster::Math::Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const Sphere &sphere, const Point &point )
{ // by Dan Andersson
Float3 dP = point.center - sphere.center;
@@ -287,9 +479,15 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
+ bool Intersect( const Sphere &sphere, const Point &point, ::Oyster::Math::Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const Sphere &sphere, const Ray &ray, Float &connectDistance )
{// by Dan Andersson
- Float3 dP = sphere.center - ray.origin;
+ Float4 dP = sphere.center - ray.origin;
Float s = dP.Dot( ray.direction ),
dSquared = dP.Dot( dP ),
rSquared = sphere.radius * sphere.radius;
@@ -307,9 +505,15 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
+ bool Intersect( const Sphere &sphere, const Ray &ray, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const Sphere &sphereA, const Sphere &sphereB )
{ // by Fredrick Johansson
- Float3 C = sphereA.center;
+ Float4 C = sphereA.center;
C -= sphereB.center;
Float r = (sphereA.radius + sphereB.radius);
@@ -320,6 +524,27 @@ namespace Oyster { namespace Collision3D { namespace Utility
return false;
}
+
+ bool Intersect( const Sphere &sphereA, const Sphere &sphereB, ::Oyster::Math::Float4 &worldPointOfContact )
+ { // by Robin Engman
+ Float4 C = sphereA.center;
+ C -= sphereB.center;
+ Float r = sphereA.radius + sphereB.radius;
+
+ if ( r*r >= C.Dot(C) )
+ {
+ Float distance;
+ Ray ray(sphereB.center, C.Normalize());
+
+ Intersect( sphereA, ray, distance );
+
+ worldPointOfContact = ray.origin + ray.direction*distance;
+
+ return true;
+ }
+
+ return false;
+ }
bool Intersect( const Plane &plane, const Point &point )
{ // by Dan Andersson
@@ -328,6 +553,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return Private::EqualsZero(connectOffset);
}
+ bool Intersect( const Plane &plane, const Point &point, Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const Plane &plane, const Ray &ray, Float &connectDistance )
{ // by Dan Andersson
Float c = plane.normal.Dot(ray.direction);
@@ -348,6 +579,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return false;
}
+ bool Intersect( const Plane &plane, const Ray &ray, Float &connectDistance, Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const Plane &plane, const Sphere &sphere )
{ // by Dan Andersson
Float connectOffset;
@@ -355,6 +592,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return (connectOffset <= sphere.radius);
}
+ bool Intersect( const Plane &plane, const Sphere &sphere, Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const Plane &planeA, const Plane &planeB )
{ // by Dan Andersson
if( planeA.normal == planeB.normal ) // they are parallell
@@ -364,6 +607,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true; // none parallell planes ALWAYS intersects somewhere
}
+ bool Intersect( const Plane &planeA, const Plane &planeB, Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement Stub
+ return false;
+ }
+
bool Intersect( const BoxAxisAligned &box, const Point &point )
{ // by Dan Andersson
if( point.center.x < box.minVertex.x ) return false;
@@ -375,31 +624,66 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
+ bool Intersect( const BoxAxisAligned &box, const Point &point, Float4 &worldPointOfContact )
+ { // by Dan Andersson
+ if( Intersect(box, point) )
+ {
+ worldPointOfContact = point.center;
+ return true;
+ }
+ return false;
+ }
+
bool Intersect( const BoxAxisAligned &box, const Ray &ray, Float &connectDistance )
{ // by Dan Andersson
Float tMin = ::std::numeric_limits::max(),
tMax = -tMin; // initiating to extremevalues
- Float3 boundingOffset = ((box.maxVertex - box.minVertex) * 0.5f),
+ Float4 boundingOffset = ((box.maxVertex - box.minVertex) * 0.5f),
dP = ((box.maxVertex + box.minVertex) * 0.5f) - ray.origin;
- if( Private::BoxVsRayPerSlabCheck( Float3::standard_unit_x, boundingOffset.x, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
- if( Private::BoxVsRayPerSlabCheck( Float3::standard_unit_y, boundingOffset.y, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
- if( Private::BoxVsRayPerSlabCheck( Float3::standard_unit_z, boundingOffset.z, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
+ if( Private::BoxVsRayPerSlabCheck( Float4::standard_unit_x, boundingOffset.x, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
+ if( Private::BoxVsRayPerSlabCheck( Float4::standard_unit_y, boundingOffset.y, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
+ if( Private::BoxVsRayPerSlabCheck( Float4::standard_unit_z, boundingOffset.z, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
if( tMin > 0.0f ) connectDistance = tMin;
else connectDistance = tMax;
return true;
}
+ bool Intersect( const BoxAxisAligned &box, const Ray &ray, Float &connectDistance, Float4 &worldPointOfContact )
+ { // by Dan Andersson
+ if( Intersect(box, ray, connectDistance) )
+ {
+ worldPointOfContact = ray.origin + ray.direction * connectDistance;
+ return true;
+ }
+ return false;
+ }
+
bool Intersect( const BoxAxisAligned &box, const Sphere &sphere )
{ // by Dan Andersson
- Float4 e = Max( Float4(box.minVertex - sphere.center, 0.0f), Float4::null );
- e += Max( Float4(sphere.center - box.maxVertex, 0.0f), Float4::null );
+ Float4 e = Max( box.minVertex - sphere.center, Float4::null );
+ e += Max( sphere.center - box.maxVertex, Float4::null );
if( e.Dot(e) > (sphere.radius * sphere.radius) ) return false;
return true;
}
+ bool Intersect( const BoxAxisAligned &box, const Sphere &sphere, Float4 &worldPointOfContact )
+ { // by Robin Engman
+ if( Intersect(box, sphere) )
+ {
+ Float distance;
+ Float4 boxMiddle = (box.maxVertex - box.minVertex) * 0.5f;
+ Ray ray( boxMiddle, (sphere.center - boxMiddle).Normalize() );
+ Intersect( sphere, ray, distance );
+ worldPointOfContact = ray.origin + ray.direction * distance;
+ return true;
+ }
+
+ return false;
+ }
+
bool Intersect( const BoxAxisAligned &box, const Plane &plane )
{ // by Dan Andersson
Float e, d;
@@ -409,6 +693,12 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
+ bool Intersect( const BoxAxisAligned &box, const Plane &plane, Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement stub
+ return Intersect( box, plane );
+ }
+
// bool Intersect( const BoxAxisAligned &box, const Triangle &triangle )
// { return false; /* TODO: */ }
@@ -425,7 +715,7 @@ namespace Oyster { namespace Collision3D { namespace Utility
bool Intersect( const Box &box, const Point &point )
{ // by Dan Andersson
- Float3 dPos = point.center - box.center;
+ Float4 dPos = point.center - box.center;
Float coordinate = dPos.Dot( box.xAxis );
if( coordinate > box.boundingOffset.x ) return false;
@@ -442,12 +732,22 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
+ bool Intersect( const Box &box, const Point &point, Float4 &worldPointOfContact )
+ { // by Dan Andersson
+ if( Intersect(box, point) )
+ {
+ worldPointOfContact = point.center;
+ return true;
+ }
+ return false;
+ }
+
bool Intersect( const Box &box, const Ray &ray, Float &connectDistance )
{ // by Dan Andersson
Float tMin = ::std::numeric_limits::max(),
tMax = -tMin; // initiating to extremevalues
- Float3 dP = box.center - ray.origin;
+ Float4 dP = box.center - ray.origin;
if( Private::BoxVsRayPerSlabCheck( box.xAxis, box.boundingOffset.x, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
if( Private::BoxVsRayPerSlabCheck( box.yAxis, box.boundingOffset.y, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
if( Private::BoxVsRayPerSlabCheck( box.zAxis, box.boundingOffset.z, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
@@ -457,18 +757,43 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
+ bool Intersect( const Box &box, const Ray &ray, Float &connectDistance, Float4 &worldPointOfContact )
+ { // by Dan Andersson
+ if( Intersect(box, ray, connectDistance) )
+ {
+ worldPointOfContact = ray.origin + ray.direction * connectDistance;
+ return true;
+ }
+ return false;
+ }
+
bool Intersect( const Box &box, const Sphere &sphere )
{ // by Dan Andersson
// center: sphere's center in the box's view space
- Float4 center = TransformVector( InverseRotationMatrix(box.rotation), Float4(sphere.center - box.center, 0.0f) );
+ Float4 center = TransformVector( InverseRotationMatrix(box.rotation), sphere.center - box.center );
- Float4 e = Max( Float4(-box.boundingOffset, 0.0f) - center, Float4::null );
- e += Max( center - Float4(box.boundingOffset, 0.0f), Float4::null );
+ Float4 e = Max( -box.boundingOffset - center, Float4::null );
+ e += Max( center - box.boundingOffset, Float4::null );
if( e.Dot(e) > (sphere.radius * sphere.radius) ) return false;
return true;
}
+ bool Intersect( const Box &box, const Sphere &sphere, Float4 &worldPointOfContact )
+ { // by Robin Engman
+ if( Intersect(box, sphere) )
+ {
+ Float distance;
+ Ray ray( box.center, sphere.center - box.center );
+
+ Intersect( sphere, ray, distance );
+ worldPointOfContact = ray.origin + ray.direction*distance;
+ return true;
+ }
+
+ return false;
+ }
+
bool Intersect( const Box &box, const Plane &plane )
{// by Dan Andersson
Float e, d;
@@ -478,22 +803,53 @@ namespace Oyster { namespace Collision3D { namespace Utility
return true;
}
+ bool Intersect( const Box &box, const Plane &plane, Float4 &worldPointOfContact )
+ {
+ //! @todo TODO: implement stub
+ return Intersect( box, plane );
+ }
+
bool Intersect( const Box &boxA, const BoxAxisAligned &boxB )
{ // by Dan Andersson
- Float3 alignedOffsetBoundaries = (boxB.maxVertex - boxB.minVertex) * 0.5f,
- offset = boxA.center - Average( boxB.minVertex, boxB.maxVertex );
+ Float4 alignedOffsetBoundaries = (boxB.maxVertex - boxB.minVertex) * 0.5f,
+ offset = boxA.center- Average( boxB.maxVertex, boxB.minVertex );
return Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( alignedOffsetBoundaries, boxA.boundingOffset, boxA.rotation, offset );
}
+ bool Intersect( const Box &boxA, const BoxAxisAligned &boxB, ::Oyster::Math::Float4 &worldPointOfContact )
+ { // by Dan Andersson
+ Float4 alignedOffsetBoundaries = (boxB.maxVertex - boxB.minVertex) * 0.5f,
+ offset = boxA.center - Average( boxB.maxVertex, boxB.minVertex );
+
+ Float4 pointOfContact;
+ if( Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( alignedOffsetBoundaries, boxA.boundingOffset, boxA.rotation, offset, pointOfContact ) )
+ {
+ worldPointOfContact = pointOfContact.xyz;
+ return true;
+ }
+ else return false;
+ }
+
bool Intersect( const Box &boxA, const Box &boxB )
{ // by Dan Andersson
- Float4x4 orientationA = OrientationMatrix(boxA.rotation, boxA.center),
- orientationB = OrientationMatrix(boxB.rotation, boxB.center),
- invOrientationA = InverseOrientationMatrix( orientationA );
+ Float4x4 rotationB = TransformMatrix( InverseRotationMatrix(boxA.rotation), boxB.rotation );
+ Float4 posB = boxB.center - boxA.center;
- orientationB = TransformMatrix( invOrientationA, orientationB );
+ return Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( boxA.boundingOffset, boxB.boundingOffset, rotationB, posB );
+ }
- return Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( boxA.boundingOffset, boxB.boundingOffset, ExtractRotationMatrix(orientationB), orientationB.v[3].xyz );
+ bool Intersect( const Box &boxA, const Box &boxB, Float4 &worldPointOfContact )
+ {
+ Float4x4 rotationB = TransformMatrix( InverseRotationMatrix(boxA.rotation), boxB.rotation );
+ Float4 posB = boxB.center - boxA.center;
+
+ Float4 pointOfContact;
+ if( Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( boxA.boundingOffset, boxB.boundingOffset, rotationB, posB, pointOfContact ) )
+ {
+ worldPointOfContact = TransformVector( boxA.rotation, pointOfContact, pointOfContact ).xyz;
+ return true;
+ }
+ else return false;
}
bool Intersect( const Frustrum &frustrum, const Point &point )
diff --git a/Code/OysterPhysics3D/OysterCollision3D.h b/Code/OysterPhysics3D/OysterCollision3D.h
index 24d6a568..20a55a18 100644
--- a/Code/OysterPhysics3D/OysterCollision3D.h
+++ b/Code/OysterPhysics3D/OysterCollision3D.h
@@ -25,18 +25,28 @@ namespace Oyster { namespace Collision3D { namespace Utility
void Compare( ::Oyster::Math::Float &connectOffset, const Plane &plane, const Point &point );
bool Intersect( const Point &pointA, const Point &pointB );
+ bool Intersect( const Point &pointA, const Point &pointB, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Ray &ray, const Point &point, ::Oyster::Math::Float &connectDistance );
+ bool Intersect( const Ray &ray, const Point &point, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Ray &rayA, const Ray &rayB, ::Oyster::Math::Float &connectDistanceA, ::Oyster::Math::Float &connectDistanceB );
+ bool Intersect( const Ray &rayA, const Ray &rayB, ::Oyster::Math::Float &connectDistanceA, ::Oyster::Math::Float &connectDistanceB, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Sphere &sphere, const Point &point );
+ bool Intersect( const Sphere &sphere, const Point &point, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Sphere &sphere, const Ray &ray, ::Oyster::Math::Float &connectDistance );
+ bool Intersect( const Sphere &sphere, const Ray &ray, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Sphere &sphereA, const Sphere &sphereB );
+ bool Intersect( const Sphere &sphereA, const Sphere &sphereB, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Plane &plane, const Point &point );
+ bool Intersect( const Plane &plane, const Point &point, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Plane &plane, const Ray &ray, ::Oyster::Math::Float &connectDistance );
+ bool Intersect( const Plane &plane, const Ray &ray, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Plane &plane, const Sphere &sphere );
+ bool Intersect( const Plane &plane, const Sphere &sphere, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Plane &planeA, const Plane &planeB );
+ bool Intersect( const Plane &planeA, const Plane &planeB, ::Oyster::Math::Float4 &worldPointOfContact );
// bool Intersect( const Triangle &triangle, const Point &point, ? );
// bool Intersect( const Triangle &triangle, const Ray &ray, ? );
@@ -45,19 +55,29 @@ namespace Oyster { namespace Collision3D { namespace Utility
// bool Intersect( const Triangle &triangleA, const Triangle &triangleB, ? );
bool Intersect( const BoxAxisAligned &box, const Point &point );
+ bool Intersect( const BoxAxisAligned &box, const Point &point, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const BoxAxisAligned &box, const Ray &ray, ::Oyster::Math::Float &connectDistance );
+ bool Intersect( const BoxAxisAligned &box, const Ray &ray, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const BoxAxisAligned &box, const Sphere &sphere );
+ bool Intersect( const BoxAxisAligned &box, const Sphere &sphere, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const BoxAxisAligned &box, const Plane &plane );
+ bool Intersect( const BoxAxisAligned &box, const Plane &plane, ::Oyster::Math::Float4 &worldPointOfContact );
// bool Intersect( const BoxAxisAligned &box, const Triangle &triangle );
bool Intersect( const BoxAxisAligned &boxA, const BoxAxisAligned &boxB );
bool Intersect( const Box &box, const Point &point );
+ bool Intersect( const Box &box, const Point &point, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Box &box, const Ray &ray, ::Oyster::Math::Float &connectDistance );
+ bool Intersect( const Box &box, const Ray &ray, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Box &box, const Sphere &sphere );
+ bool Intersect( const Box &box, const Sphere &sphere, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Box &box, const Plane &plane );
+ bool Intersect( const Box &box, const Plane &plane, ::Oyster::Math::Float4 &worldPointOfContact );
// bool Intersect( const Box &box, const Triangle &triangle, ? );
bool Intersect( const Box &boxA, const BoxAxisAligned &boxB );
+ bool Intersect( const Box &boxA, const BoxAxisAligned &boxB, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Box &boxA, const Box &boxB );
+ bool Intersect( const Box &boxA, const Box &boxB, ::Oyster::Math::Float4 &worldPointOfContact );
bool Intersect( const Frustrum &frustrum, const Point &point );
bool Intersect( const Frustrum &frustrum, const Ray &ray, ::Oyster::Math::Float &connectDistance );
diff --git a/Code/OysterPhysics3D/OysterPhysics3D.h b/Code/OysterPhysics3D/OysterPhysics3D.h
index 614a4a29..f70d228f 100644
--- a/Code/OysterPhysics3D/OysterPhysics3D.h
+++ b/Code/OysterPhysics3D/OysterPhysics3D.h
@@ -12,6 +12,60 @@ namespace Oyster { namespace Physics3D
namespace Formula
{ /// Library of 3D physics related formulas
+ /******************************************************************
+ * Returns the linear momentum of a mass in motion.
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 LinearMomentum( const ::Oyster::Math::Float &mass, const ::Oyster::Math::Float4 &linearVelocity )
+ {
+ return linearVelocity * mass;
+ }
+
+ /******************************************************************
+ * Returns the linear momentum of a mass in motion.
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 LinearVelocity( const ::Oyster::Math::Float &mass, const ::Oyster::Math::Float4 &linearMomentum )
+ {
+ return linearMomentum / mass;
+ }
+
+ /******************************************************************
+ * Returns the world angular momentum of a mass in rotation.
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 AngularMomentum( const ::Oyster::Math::Float4 linearMomentum, const ::Oyster::Math::Float4 &worldOffset )
+ {
+ return ::Oyster::Math::Float4( worldOffset.xyz.Cross(linearMomentum.xyz), 0.0f );
+ }
+
+ /******************************************************************
+ * Returns the world angular momentum of a mass in rotation.
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 AngularMomentum( const ::Oyster::Math::Float4x4 &worldMomentOfInertia, const ::Oyster::Math::Float4 &angularVelocity )
+ {
+ return worldMomentOfInertia * angularVelocity;
+ }
+
+ /******************************************************************
+ * Returns the world angular velocity of a mass in rotation.
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 AngularVelocity( const ::Oyster::Math::Float4x4 &worldMomentOfInertiaInversed, const ::Oyster::Math::Float4 &angularMomentum )
+ {
+ return worldMomentOfInertiaInversed * angularMomentum;
+ }
+
+ /******************************************************************
+ * Returns the world tangential momentum at worldPos, of a mass in rotation.
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 TangentialLinearMomentum( const ::Oyster::Math::Float4 &angularMomentum, const ::Oyster::Math::Float4 &worldOffset )
+ {
+ return ::Oyster::Math::Float4( angularMomentum.xyz.Cross(worldOffset.xyz), 0.0f );
+ }
+
/******************************************************************
* Returns the linear kinetic energy of a mass in motion.
* @todo TODO: improve doc
@@ -138,6 +192,15 @@ namespace Oyster { namespace Physics3D
return worldOffset.Cross( linearVelocity );
}
+ /******************************************************************
+ * Returns the world angular velocity of a mass in rotation.
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 AngularVelocity( const ::Oyster::Math::Float4 &linearVelocity, const ::Oyster::Math::Float4 &worldOffset )
+ {
+ return ::Oyster::Math::Float4( worldOffset.xyz.Cross( linearVelocity.xyz ), 0.0f );
+ }
+
/******************************************************************
* Returns the world tangential velocity at worldPos, of a mass in rotation.
* @todo TODO: improve doc
@@ -183,6 +246,15 @@ namespace Oyster { namespace Physics3D
return worldOffset.Cross( impulseForce );
}
+ /******************************************************************
+ *
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 ImpulseTorque( const ::Oyster::Math::Float4 & impulseForce, const ::Oyster::Math::Float4 &worldOffset )
+ {
+ return ::Oyster::Math::Float4( worldOffset.xyz.Cross(impulseForce.xyz), 0.0f );
+ }
+
/******************************************************************
* T = I*a
* @todo TODO: improve doc
@@ -192,10 +264,13 @@ namespace Oyster { namespace Physics3D
return ( momentOfInertia * ::Oyster::Math::Float4(angularImpulseAcceleration, 0.0f) ).xyz;
}
- inline ::Oyster::Math::Float3 Impulse( )
+ /******************************************************************
+ * T = I*a
+ * @todo TODO: improve doc
+ ******************************************************************/
+ inline ::Oyster::Math::Float4 ImpulseTorque( const ::Oyster::Math::Float4x4 & momentOfInertia, const ::Oyster::Math::Float4 &angularImpulseAcceleration )
{
- //! @todo TODO: implement calculation for impulse. Hijack Mattias Eriksson
- return ::Oyster::Math::Float3::null;
+ return momentOfInertia * angularImpulseAcceleration;
}
namespace MomentOfInertia
diff --git a/Code/OysterPhysics3D/OysterPhysics3D.vcxproj b/Code/OysterPhysics3D/OysterPhysics3D.vcxproj
index f24f23e4..186ea535 100644
--- a/Code/OysterPhysics3D/OysterPhysics3D.vcxproj
+++ b/Code/OysterPhysics3D/OysterPhysics3D.vcxproj
@@ -163,6 +163,7 @@
+
diff --git a/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters b/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters
index e3a8a70d..02919d28 100644
--- a/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters
+++ b/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters
@@ -75,6 +75,9 @@
Header Files\Physics
+
+ Header Files\Physics
+
diff --git a/Code/OysterPhysics3D/Particle.cpp b/Code/OysterPhysics3D/Particle.cpp
index 830e13b5..c84b1e31 100644
--- a/Code/OysterPhysics3D/Particle.cpp
+++ b/Code/OysterPhysics3D/Particle.cpp
@@ -34,7 +34,7 @@ Particle & Particle::operator = ( const Particle &particle )
void Particle::Update_LeapFrog( Float deltaTime )
{ // Euler leap frog update when Runga Kutta is not needed
this->impulseForceSum *= (deltaTime / this->mass); // is now deltaLinearVelocity ( dt * a = dt * F / m )
- this->sphere.center += deltaTime * ::Utility::Value::AverageWithDelta( Formula::LinearVelocity(this->mass, this->linearMomentum), this->impulseForceSum );
+ this->sphere.center.xyz += deltaTime * ::Utility::Value::AverageWithDelta( Formula::LinearVelocity(this->mass, this->linearMomentum), this->impulseForceSum );
this->linearMomentum += Formula::LinearMomentum( this->mass, this->impulseForceSum );
this->impulseForceSum = Float3::null;
@@ -66,12 +66,12 @@ void Particle::ApplyLinearImpulseAcceleration( const Float3 &a )
Float3 & Particle::AccessCenter()
{
- return this->sphere.center;
+ return this->sphere.center.xyz;
}
const Float3 & Particle::AccessCenter() const
{
- return this->sphere.center;
+ return this->sphere.center.xyz;
}
Float & Particle::AccessRadius()
@@ -91,7 +91,7 @@ const Float & Particle::GetMass() const
const Float3 & Particle::GetCenter() const
{
- return this->sphere.center;
+ return this->sphere.center.xyz;
}
const Float & Particle::GetRadius() const
diff --git a/Code/OysterPhysics3D/Plane.cpp b/Code/OysterPhysics3D/Plane.cpp
index a1a16b14..59ffbc47 100644
--- a/Code/OysterPhysics3D/Plane.cpp
+++ b/Code/OysterPhysics3D/Plane.cpp
@@ -10,11 +10,11 @@ using namespace ::Oyster::Math;
Plane::Plane( ) : ICollideable(Type_plane)
{
- this->normal = Float3::standard_unit_z;
+ this->normal = Float4::standard_unit_z;
this->phasing = 0.0f;
}
-Plane::Plane( const Float3 &n, const Float &p ) : ICollideable(Type_plane)
+Plane::Plane( const Float4 &n, const Float &p ) : ICollideable(Type_plane)
{
this->normal = n;
this->phasing = p;
@@ -30,23 +30,46 @@ Plane & Plane::operator = ( const Plane &plane )
}
::Utility::DynamicMemory::UniquePointer Plane::Clone( ) const
-{ return ::Utility::DynamicMemory::UniquePointer( new Plane(*this) ); }
+{
+ return ::Utility::DynamicMemory::UniquePointer( new Plane(*this) );
+}
bool Plane::Intersects( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_universe: return true;
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- case Type_ray: return Utility::Intersect( *this, *(Ray*)&target, ((Ray*)&target)->collisionDistance );
- case Type_sphere: return Utility::Intersect( *this, *(Sphere*)&target );
- case Type_plane: return Utility::Intersect( *this, *(Plane*)&target );
- // case Type_triangle: return false; // TODO:
- case Type_box_axis_aligned: return Utility::Intersect( *(BoxAxisAligned*)&target, *this );
- case Type_box: return Utility::Intersect( *(Box*)&target, *this );
- case Type_frustrum: return false; // TODO:
- case Type_line: return false; // TODO:
- default: return false;
+ case Type_universe: return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, ((const Ray&)target).collisionDistance );
+ case Type_sphere: return Utility::Intersect( *this, (const Sphere&)target );
+ case Type_plane: return Utility::Intersect( *this, (const Plane&)target );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( (const BoxAxisAligned&)target, *this );
+ case Type_box: return Utility::Intersect( (const Box&)target, *this );
+ //case Type_frustrum: return false; // TODO:
+ //case Type_line: return false; // TODO:
+ default: return false;
+ }
+}
+
+bool Plane::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{
+ switch( target.type )
+ {
+ case Type_universe:
+ worldPointOfContact = this->normal * this->phasing;
+ return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target, worldPointOfContact );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, ((const Ray&)target).collisionDistance, worldPointOfContact );
+ case Type_sphere: return Utility::Intersect( *this, (const Sphere&)target, worldPointOfContact );
+ case Type_plane: return Utility::Intersect( (const Plane&)target, *this, worldPointOfContact );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( (const BoxAxisAligned&)target, *this, worldPointOfContact );
+ case Type_box: return Utility::Intersect( (const Box&)target, *this, worldPointOfContact );
+ //case Type_frustrum: return false; // TODO:
+ default:
+ worldPointOfContact = Float3::null;
+ return false;
}
}
@@ -54,10 +77,10 @@ bool Plane::Contains( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- case Type_ray: return Utility::Contains( *this, *(Ray*)&target );
- case Type_plane: return Utility::Contains( *this, *(Plane*)&target );
- // case Type_triangle: return false; // TODO:
- default: return false;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ case Type_ray: return Utility::Contains( *this, (const Ray&)target );
+ case Type_plane: return Utility::Contains( *this, (const Plane&)target );
+ //case Type_triangle: return false; // TODO:
+ default: return false;
}
}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Plane.h b/Code/OysterPhysics3D/Plane.h
index b69c5c9f..f148ed8e 100644
--- a/Code/OysterPhysics3D/Plane.h
+++ b/Code/OysterPhysics3D/Plane.h
@@ -16,19 +16,20 @@ namespace Oyster { namespace Collision3D
public:
union
{
- struct{ ::Oyster::Math::Float3 normal; ::Oyster::Math::Float phasing; };
- ::Oyster::Math::Float element[4];
- char byte[sizeof(::Oyster::Math::Float3) + sizeof(::Oyster::Math::Float)];
+ struct{ ::Oyster::Math::Float4 normal; ::Oyster::Math::Float phasing; };
+ ::Oyster::Math::Float element[5];
+ char byte[sizeof(::Oyster::Math::Float4) + sizeof(::Oyster::Math::Float)];
};
Plane( );
- Plane( const ::Oyster::Math::Float3 &normal, const ::Oyster::Math::Float &phasing );
+ Plane( const ::Oyster::Math::Float4 &normal, const ::Oyster::Math::Float &phasing );
virtual ~Plane( );
Plane & operator = ( const Plane &plane );
virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
diff --git a/Code/OysterPhysics3D/Point.cpp b/Code/OysterPhysics3D/Point.cpp
index d81c91a3..788ab32d 100644
--- a/Code/OysterPhysics3D/Point.cpp
+++ b/Code/OysterPhysics3D/Point.cpp
@@ -10,10 +10,15 @@ using namespace ::Oyster::Math3D;
Point::Point( ) : ICollideable(Type_point)
{
- this->center = Float3::null;
+ this->center = Float4::standard_unit_w;
}
Point::Point( const Float3 &pos ) : ICollideable(Type_point)
+{
+ this->center = Float4( pos, 1.0f );
+}
+
+Point::Point( const Float4 &pos ) : ICollideable(Type_point)
{
this->center = pos;
}
@@ -35,16 +40,37 @@ bool Point::Intersects( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_universe: return true;
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- case Type_ray: return Utility::Intersect( *(Ray*)&target, *this, ((Ray*)&target)->collisionDistance );
- case Type_sphere: return Utility::Intersect( *(Sphere*)&target, *this );
- case Type_plane: return Utility::Intersect( *(Plane*)&target, *this );
- //case Type_triangle: return false; // TODO:
- case Type_box_axis_aligned: return Utility::Intersect( *(BoxAxisAligned*)&target, *this );
- case Type_box: return Utility::Intersect( *(Box*)&target, *this );
- case Type_frustrum: return false; // TODO:
- default: return false;
+ case Type_universe: return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ case Type_ray: return Utility::Intersect( (const Ray&)target, *this, ((const Ray&)target).collisionDistance );
+ case Type_sphere: return Utility::Intersect( (const Sphere&)target, *this );
+ case Type_plane: return Utility::Intersect( (const Plane&)target, *this );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( (const BoxAxisAligned&)target, *this );
+ case Type_box: return Utility::Intersect( (const Box&)target, *this );
+ //case Type_frustrum: return false; // TODO:
+ default: return false;
+ }
+}
+
+bool Point::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{
+ switch( target.type )
+ {
+ case Type_universe:
+ worldPointOfContact = this->center;
+ return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target, worldPointOfContact );
+ case Type_ray: return Utility::Intersect( (const Ray&)target, *this, ((const Ray&)target).collisionDistance, worldPointOfContact );
+ case Type_sphere: return Utility::Intersect( (const Sphere&)target, *this, worldPointOfContact );
+ case Type_plane: return Utility::Intersect( (const Plane&)target, *this, worldPointOfContact );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( (const BoxAxisAligned&)target, *this, worldPointOfContact );
+ case Type_box: return Utility::Intersect( (const Box&)target, *this, worldPointOfContact );
+ case Type_frustrum: return false; // TODO:
+ default:
+ worldPointOfContact = Float3::null;
+ return false;
}
}
@@ -52,7 +78,7 @@ bool Point::Contains( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- default: return false;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ default: return false;
}
}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Point.h b/Code/OysterPhysics3D/Point.h
index 42561909..60486373 100644
--- a/Code/OysterPhysics3D/Point.h
+++ b/Code/OysterPhysics3D/Point.h
@@ -16,18 +16,20 @@ namespace Oyster { namespace Collision3D
public:
union
{
- struct{ ::Oyster::Math::Float3 center; };
- char byte[sizeof(::Oyster::Math::Float3)];
+ struct{ ::Oyster::Math::Float4 center; };
+ char byte[sizeof(::Oyster::Math::Float4)];
};
Point( );
Point( const ::Oyster::Math::Float3 &position );
+ Point( const ::Oyster::Math::Float4 &position );
virtual ~Point( );
Point & operator = ( const Point &point );
virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
diff --git a/Code/OysterPhysics3D/Ray.cpp b/Code/OysterPhysics3D/Ray.cpp
index 79e4dbd5..e7f21de8 100644
--- a/Code/OysterPhysics3D/Ray.cpp
+++ b/Code/OysterPhysics3D/Ray.cpp
@@ -10,12 +10,19 @@ using namespace ::Oyster::Math3D;
Ray::Ray( ) : ICollideable(Type_ray)
{
- this->origin = Float3::null;
- this->direction = Float3::standard_unit_z;
+ this->origin = Float4::standard_unit_w;
+ this->direction = Float4::standard_unit_z;
this->collisionDistance = 0.0f;
}
-Ray::Ray( const Float3 &o, const ::Oyster::Math::Float3 &d ) : ICollideable(Type_ray)
+Ray::Ray( const Float3 &o, const Float3 &d ) : ICollideable(Type_ray)
+{
+ this->origin = Float4( o, 1.0f );
+ this->direction = Float4( d, 0.0f );
+ this->collisionDistance = 0.0f;
+}
+
+Ray::Ray( const Float4 &o, const Float4 &d ) : ICollideable(Type_ray)
{
this->origin = o;
this->direction = d;
@@ -43,15 +50,37 @@ bool Ray::Intersects( const ICollideable &target ) const
case Type_universe:
this->collisionDistance = 0.0f;
return true;
- case Type_point: return Utility::Intersect( *this, *(Point*)&target, this->collisionDistance );
- case Type_ray: return Utility::Intersect( *this, *(Ray*)&target, this->collisionDistance, ((Ray*)&target)->collisionDistance );
- case Type_sphere: return Utility::Intersect( *(Sphere*)&target, *this, this->collisionDistance );
- case Type_plane: return Utility::Intersect( *(Plane*)&target, *this, this->collisionDistance );
- // case Type_triangle: return false; // TODO:
- case Type_box_axis_aligned: return Utility::Intersect( *(BoxAxisAligned*)&target, *this, this->collisionDistance );
- case Type_box: return Utility::Intersect( *(Box*)&target, *this, this->collisionDistance );
- case Type_frustrum: return false; // TODO:
- default: return false;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target, this->collisionDistance );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, this->collisionDistance, ((const Ray&)target).collisionDistance );
+ case Type_sphere: return Utility::Intersect( (const Sphere&)target, *this, this->collisionDistance );
+ case Type_plane: return Utility::Intersect( (const Plane&)target, *this, this->collisionDistance );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( (const BoxAxisAligned&)target, *this, this->collisionDistance );
+ case Type_box: return Utility::Intersect( (const Box&)target, *this, this->collisionDistance );
+ //case Type_frustrum: return false; // TODO:
+ default: return false;
+ }
+}
+
+bool Ray::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{
+ switch( target.type )
+ {
+ case Type_universe:
+ this->collisionDistance = 0.0f;
+ worldPointOfContact = this->origin;
+ return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target, this->collisionDistance, worldPointOfContact );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, this->collisionDistance, ((const Ray&)target).collisionDistance, worldPointOfContact );
+ case Type_sphere: return Utility::Intersect( (const Sphere&)target, *this, this->collisionDistance, worldPointOfContact );
+ case Type_plane: return Utility::Intersect( (const Plane&)target, *this, this->collisionDistance, worldPointOfContact );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( (const BoxAxisAligned&)target, *this, this->collisionDistance, worldPointOfContact );
+ case Type_box: return Utility::Intersect( (const Box&)target, *this, this->collisionDistance, worldPointOfContact );
+ //case Type_frustrum: return false; // TODO:
+ default:
+ worldPointOfContact = Float3::null;
+ return false;
}
}
@@ -59,8 +88,8 @@ bool Ray::Contains( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_point: return Utility::Intersect( *this, *(Point*)&target, this->collisionDistance );
- case Type_ray: return Utility::Contains( *this, *(Ray*)&target );
- default: return false;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target, this->collisionDistance );
+ case Type_ray: return Utility::Contains( *this, (const Ray&)target );
+ default: return false;
}
}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Ray.h b/Code/OysterPhysics3D/Ray.h
index 5f24ea81..a85580b3 100644
--- a/Code/OysterPhysics3D/Ray.h
+++ b/Code/OysterPhysics3D/Ray.h
@@ -10,7 +10,6 @@
#ifndef OYSTER_COLLISION_3D_RAY_H
#define OYSTER_COLLISION_3D_RAY_H
-#include "OysterMath.h"
#include "ICollideable.h"
namespace Oyster { namespace Collision3D
@@ -22,21 +21,23 @@ namespace Oyster { namespace Collision3D
{
struct
{
- ::Oyster::Math::Float3 origin,
+ ::Oyster::Math::Float4 origin,
direction; /// Assumed to be normalized
};
- char byte[2*sizeof(::Oyster::Math::Float3)];
+ char byte[2*sizeof(::Oyster::Math::Float4)];
};
mutable float collisionDistance;
Ray( );
Ray( const ::Oyster::Math::Float3 &origin, const ::Oyster::Math::Float3 &normalizedDirection );
+ Ray( const ::Oyster::Math::Float4 &origin, const ::Oyster::Math::Float4 &normalizedDirection );
virtual ~Ray( );
Ray & operator = ( const Ray &ray );
virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp
index 182a5a17..3ae48511 100644
--- a/Code/OysterPhysics3D/RigidBody.cpp
+++ b/Code/OysterPhysics3D/RigidBody.cpp
@@ -8,413 +8,224 @@
using namespace ::Oyster::Collision3D;
using namespace ::Oyster::Physics3D;
using namespace ::Oyster::Math3D;
+using namespace ::Utility::Value;
-RigidBody::RigidBody( const Box &b, Float m, const Float4x4 &inertiaTensor )
+RigidBody::RigidBody( )
{ // by Dan Andersson
- this->box = b;
- this->angularMomentum = Float3::null;
- this->linearMomentum = Float3::null;
- this->impulseTorqueSum = Float3::null;
- this->impulseForceSum = Float3::null;
-
- if( m != 0.0f )
- {
- this->mass = m;
- }
- else
- {
- this->mass = ::Utility::Value::numeric_limits::epsilon();
- }
-
- if( inertiaTensor.GetDeterminant() != 0.0f )
- {
- this->momentOfInertiaTensor = inertiaTensor;
- }
- else
- {
- this->momentOfInertiaTensor = Float4x4::identity;
- }
+ this->centerPos = Float4::standard_unit_w;
+ this->axis = Float4::null;
+ this->boundingReach = Float4( 0.5f, 0.5f, 0.5f, 0.0f );
+ this->momentum_Linear = Float4::null;
+ this->momentum_Angular = Float4::null;
+ this->impulse_Linear = Float4::null;
+ this->impulse_Angular = Float4::null;
+ this->restitutionCoeff = 1.0f;
+ this->frictionCoeff_Static = 0.5f;
+ this->frictionCoeff_Kinetic = 1.0f;
+ this->mass = 10;
+ this->momentOfInertiaTensor = Float4x4::identity;
+ this->rotation = Quaternion::identity;
}
RigidBody & RigidBody::operator = ( const RigidBody &body )
{ // by Dan Andersson
- this->box = body.box;
- this->angularMomentum = body.angularMomentum;
- this->linearMomentum = body.linearMomentum;
- this->impulseTorqueSum = body.impulseTorqueSum;
- this->impulseForceSum = body.impulseForceSum;
+ this->centerPos = body.centerPos;
+ this->axis = body.axis;
+ this->boundingReach = body.boundingReach;
+ this->momentum_Linear = body.momentum_Linear;
+ this->momentum_Angular = body.momentum_Angular;
+ this->impulse_Linear = body.impulse_Linear;
+ this->impulse_Angular = body.impulse_Angular;
+ this->restitutionCoeff = body.restitutionCoeff;
+ this->frictionCoeff_Static = body.frictionCoeff_Static;
+ this->frictionCoeff_Kinetic = body.frictionCoeff_Kinetic;
this->mass = body.mass;
this->momentOfInertiaTensor = body.momentOfInertiaTensor;
+ this->rotation = body.rotation;
return *this;
}
-bool RigidBody::operator == ( const RigidBody &body )
-{
- if( this->box.center != body.box.center )
- {
- return false;
- }
-
- if( this->box.rotation != body.box.rotation )
- {
- return false;
- }
-
- if( this->box.boundingOffset != body.box.boundingOffset )
- {
- return false;
- }
-
- if( this->angularMomentum != body.angularMomentum )
- {
- return false;
- }
-
- if( this->linearMomentum != body.linearMomentum )
- {
- return false;
- }
-
- if( this->impulseTorqueSum != body.impulseTorqueSum )
- {
- return false;
- }
-
- if( this->impulseForceSum != body.impulseForceSum )
- {
- return false;
- }
-
- return true;
-}
-
-bool RigidBody::operator != ( const RigidBody &body )
-{
- return !this->operator==( body );
-}
-
-void RigidBody::Update_LeapFrog( Float deltaTime )
+void RigidBody::Update_LeapFrog( Float updateFrameLength )
{ // by Dan Andersson: Euler leap frog update when Runga Kutta is not needed
- // Important! The member data is all world data except the Inertia tensor. Thus a new InertiaTensor needs to be created to be compatible with the rest of the world data.
- Float4x4 wMomentOfInertiaTensor = TransformMatrix( this->box.rotation, this->momentOfInertiaTensor ); // RI
-
// updating the linear
- // dG = F * dt
// ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G
- Float3 linearImpulse = this->impulseForceSum * deltaTime; // aka deltaLinearMomentum
- Float3 deltaPos = ( deltaTime / this->mass ) * ::Utility::Value::AverageWithDelta( this->linearMomentum, linearImpulse );
+ this->centerPos += ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear );
// updating the angular
- // dH = T * dt
+ Float4x4 rotationMatrix; ::Oyster::Math3D::RotationMatrix( this->rotation, rotationMatrix );
+ // Important! The member data is all world data except the Inertia tensor. Thus a new InertiaTensor needs to be created to be compatible with the rest of the world data.
+ Float4x4 wMomentOfInertiaTensor = TransformMatrix( rotationMatrix, this->momentOfInertiaTensor ); // RI
+
// dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H
- Float3 angularImpulse = this->impulseTorqueSum * deltaTime; // aka deltaAngularMomentum
- Float3 rotationAxis = Formula::AngularVelocity( wMomentOfInertiaTensor.GetInverse(),
- ::Utility::Value::AverageWithDelta(this->angularMomentum, angularImpulse) );
-
- Float deltaRadian = rotationAxis.Dot( rotationAxis );
- if( deltaRadian != 0.0f )
- { // branch depending if there is rotation
- deltaRadian = ::std::sqrt( deltaRadian );
- rotationAxis /= deltaRadian;
+ this->axis += Formula::AngularVelocity( wMomentOfInertiaTensor.GetInverse(), AverageWithDelta(this->momentum_Angular, this->impulse_Angular) );
+ this->rotation = Rotation( this->axis );
- // using rotationAxis, deltaRadian and deltaPos to create a matrix to update the box
- this->box.center += deltaPos;
- TransformMatrix( RotationMatrix(deltaRadian, rotationAxis), this->box.rotation, this->box.rotation );
- }
- else
- { // no rotation, only use deltaPos to translate the RigidBody
- this->box.center += deltaPos;
- }
-
- // update momentums and clear impulseForceSum and impulseTorqueSum
- this->linearMomentum += linearImpulse;
- this->impulseForceSum = Float3::null;
- this->angularMomentum += angularImpulse;
- this->impulseTorqueSum = Float3::null;
+ // update momentums and clear impulse_Linear and impulse_Angular
+ this->momentum_Linear += this->impulse_Linear;
+ this->impulse_Linear = Float4::null;
+ this->momentum_Angular += this->impulse_Angular;
+ this->impulse_Angular = Float4::null;
}
-void RigidBody::ApplyImpulseForce( const Float3 &worldF )
-{ // by Dan Andersson
- this->impulseForceSum += worldF;
+void RigidBody::Predict_LeapFrog( Float4 &outDeltaPos, Float4 &outDeltaAxis, const Float4 &actingLinearImpulse, const Float4 &actingAngularImpulse, Float deltaTime )
+{
+ // updating the linear
+ // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G
+ outDeltaPos = ( deltaTime / this->mass ) * AverageWithDelta( this->momentum_Linear, actingLinearImpulse );
+
+ // updating the angular
+ Float4x4 rotationMatrix; ::Oyster::Math3D::RotationMatrix( this->rotation, rotationMatrix );
+ Float4x4 wMomentOfInertiaTensor = TransformMatrix( rotationMatrix, this->momentOfInertiaTensor ); // RI
+
+ // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H
+ outDeltaAxis = Formula::AngularVelocity( wMomentOfInertiaTensor.GetInverse(), AverageWithDelta(this->momentum_Angular, actingAngularImpulse) );
}
-void RigidBody::ApplyImpulseForceAt( const Float3 &worldF, const Float3 &worldPos )
+void RigidBody::Move( const Float4 &deltaPos, const Float4 &deltaAxis )
+{
+ this->centerPos += deltaPos;
+ this->axis += deltaAxis;
+ this->rotation = Rotation( this->axis );
+}
+
+void RigidBody::ApplyImpulse( const Float4 &worldJ, const Float4 &atWorldPos )
{ // by Dan Andersson
- Float3 worldOffset = worldPos - this->box.center;
- if( worldOffset != Float3::null )
+ Float4 worldOffset = atWorldPos - this->centerPos;
+ if( worldOffset != Float4::null )
{
- this->impulseForceSum += VectorProjection( worldF, worldOffset );
- this->impulseTorqueSum += Formula::ImpulseTorque( worldF, worldOffset );
+ this->impulse_Linear += VectorProjection( worldJ, atWorldPos );
+ this->impulse_Angular += Formula::ImpulseTorque( worldJ, atWorldPos );
}
else
{
- this->impulseForceSum += worldF;
+ this->impulse_Linear += worldJ;
}
}
-void RigidBody::ApplyLinearImpulseAcceleration( const Float3 &worldA )
-{ // by Dan Andersson
- this->impulseForceSum += Formula::ImpulseForce( this->mass, worldA );
-}
-
-void RigidBody::ApplyLinearImpulseAccelerationAt( const Float3 &worldA, const Float3 &worldPos )
-{ // by Dan Andersson
- Float3 worldOffset = worldPos - this->box.center;
- if( worldOffset != Float3::null )
- {
- this->impulseForceSum += Formula::ImpulseForce( this->mass, VectorProjection(worldA, worldOffset) );
-
- // tanAcc = angularAcc x localPosition
- // angularAcc = localPosition x tanAcc = localPosition x linearAcc
- // T = I * angularAcc
- this->impulseTorqueSum += Formula::ImpulseTorque( this->momentOfInertiaTensor, Formula::AngularImpulseAcceleration(worldA, worldOffset) );
- }
- else
- {
- this->impulseForceSum += Formula::ImpulseForce( this->mass, worldA );
- }
-}
-
-void RigidBody::ApplyImpulseTorque( const Float3 &worldT )
-{ // by Dan Andersson
- this->impulseTorqueSum += worldT;
-}
-
-void RigidBody::ApplyAngularImpulseAcceleration( const Float3 &worldA )
-{ // by Dan Andersson
- this->impulseTorqueSum += Formula::ImpulseTorque( this->momentOfInertiaTensor, worldA );
-}
-
-Float3 & RigidBody::AccessBoundingReach()
-{ // by Dan Andersson
- return this->box.boundingOffset;
-}
-
-const Float3 & RigidBody::AccessBoundingReach() const
-{ // by Dan Andersson
- return this->box.boundingOffset;
-}
-
-Float3 & RigidBody::AccessCenter()
-{ // by Dan Andersson
- return this->box.center;
-}
-
-const Float3 & RigidBody::AccessCenter() const
-{ // by Dan Andersson
- return this->box.center;
-}
-
const Float4x4 & RigidBody::GetMomentOfInertia() const
{ // by Dan Andersson
return this->momentOfInertiaTensor;
}
-const Float & RigidBody::GetMass() const
+Float RigidBody::GetMass() const
{ // by Dan Andersson
return this->mass;
}
-const Float4x4 RigidBody::GetOrientation() const
+const Quaternion & RigidBody::GetRotation() const
{ // by Dan Andersson
- return OrientationMatrix( this->box.rotation, this->box.center );
+ return this->rotation;
+}
+
+Float4x4 RigidBody::GetRotationMatrix() const
+{ // by Dan Andersson
+ return RotationMatrix( this->rotation );
+}
+
+Float4x4 RigidBody::GetOrientation() const
+{ // by Dan Andersson
+ return ::Oyster::Math3D::OrientationMatrix( this->rotation, this->centerPos );
}
Float4x4 RigidBody::GetView() const
{ // by Dan Andersson
- return InverseOrientationMatrix( this->GetOrientation() );
+ return ViewMatrix( this->rotation, this->centerPos );
}
-const Float3 & RigidBody::GetBoundingReach() const
+Float4 RigidBody::GetVelocity_Linear() const
{ // by Dan Andersson
- return this->box.boundingOffset;
+ return Formula::LinearVelocity( this->mass, this->momentum_Linear );
}
-Float3 RigidBody::GetSize() const
+Float4 RigidBody::GetVelocity_Angular() const
{ // by Dan Andersson
- return 2.0f * this->box.boundingOffset;
+ return Formula::AngularVelocity( this->momentOfInertiaTensor.GetInverse(), this->momentum_Angular );
}
-const Float3 & RigidBody::GetCenter() const
+Float4 RigidBody::GetLinearMomentum( const Float4 &atWorldPos ) const
{ // by Dan Andersson
- return this->box.center;
+ return this->momentum_Linear + Formula::TangentialLinearMomentum( this->momentum_Angular, atWorldPos - this->centerPos );
}
-const Float3 & RigidBody::GetImpulsTorque() const
+void RigidBody::SetMomentOfInertia_KeepVelocity( const Float4x4 &localTensorI )
{ // by Dan Andersson
- return this->impulseTorqueSum;
-}
+ if( localTensorI.GetDeterminant() != 0.0f )
+ { // insanity check! MomentOfInertiaTensor must be invertable
+ Float4x4 rotationMatrix; RotationMatrix( this->rotation, rotationMatrix );
-const Float3 & RigidBody::GetAngularMomentum() const
-{ // by Dan Andersson
- return this->angularMomentum;
-}
-
-Float3 RigidBody::GetAngularImpulseAcceleration() const
-{ // by Dan Andersson
- return Formula::AngularImpulseAcceleration( this->momentOfInertiaTensor.GetInverse(), this->impulseTorqueSum );
-}
-
-Float3 RigidBody::GetAngularVelocity() const
-{ // by Dan Andersson
- return Formula::AngularVelocity( this->momentOfInertiaTensor.GetInverse(), this->angularMomentum );
-}
-
-const Float3 & RigidBody::GetImpulseForce() const
-{ // by Dan Andersson
- return this->impulseForceSum;
-}
-
-const Float3 & RigidBody::GetLinearMomentum() const
-{ // by Dan Andersson
- return this->linearMomentum;
-}
-
-Float3 RigidBody::GetLinearImpulseAcceleration() const
-{ // by Dan Andersson
- return Formula::LinearImpulseAcceleration( this->mass, this->impulseForceSum );
-}
-
-Float3 RigidBody::GetLinearVelocity() const
-{ // by Dan Andersson
- return Formula::LinearVelocity( this->mass, this->linearMomentum );
-}
-
-void RigidBody::GetMomentumAt( const Float3 &worldPos, const Float3 &surfaceNormal, Float3 &normalMomentum, Float3 &tangentialMomentum ) const
-{ // by Dan Andersson
- Float3 worldOffset = worldPos - this->box.center;
- Float3 momentum = Formula::TangentialLinearMomentum( this->angularMomentum, worldOffset );
- momentum += this->linearMomentum;
-
- normalMomentum = NormalProjection( momentum, surfaceNormal );
- tangentialMomentum = momentum - normalMomentum;
-}
-
-void RigidBody::SetMomentOfInertia_KeepVelocity( const ::Oyster::Math::Float4x4 &localI )
-{ // by Dan Andersson
- if( localI.GetDeterminant() != 0.0f ) // insanitycheck! momentOfInertiaTensor must be invertable
- {
- Float3 w = Formula::AngularVelocity( (this->box.rotation * this->momentOfInertiaTensor).GetInverse(),
- this->angularMomentum );
- this->momentOfInertiaTensor = localI;
- this->angularMomentum = Formula::AngularMomentum( this->box.rotation*localI, w );
+ Float4 w = Formula::AngularVelocity( (rotationMatrix * this->momentOfInertiaTensor).GetInverse(), this->momentum_Angular );
+ this->momentOfInertiaTensor = localTensorI;
+ this->momentum_Angular = Formula::AngularMomentum( rotationMatrix * localTensorI, w );
}
}
-void RigidBody::SetMomentOfInertia_KeepMomentum( const Float4x4 &localI )
+void RigidBody::SetMomentOfInertia_KeepMomentum( const Float4x4 &localTensorI )
{ // by Dan Andersson
- if( localI.GetDeterminant() != 0.0f ) // insanitycheck! momentOfInertiaTensor must be invertable
- {
- this->momentOfInertiaTensor = localI;
+ if( localTensorI.GetDeterminant() != 0.0f )
+ { // insanity check! MomentOfInertiaTensor must be invertable
+ this->momentOfInertiaTensor = localTensorI;
}
}
void RigidBody::SetMass_KeepVelocity( const Float &m )
{ // by Dan Andersson
- if( m != 0.0f ) // insanitycheck! mass must be invertable
- {
- Float3 v = Formula::LinearVelocity( this->mass, this->linearMomentum );
+ if( m != 0.0f )
+ { // insanity check! Mass must be invertable
+ Float4 v = Formula::LinearVelocity( this->mass, this->momentum_Linear );
this->mass = m;
- this->linearMomentum = Formula::LinearMomentum( this->mass, v );
+ this->momentum_Linear = Formula::LinearMomentum( this->mass, v );
}
}
void RigidBody::SetMass_KeepMomentum( const Float &m )
{ // by Dan Anderson
- if( m != 0.0f ) // insanitycheck! mass must be invertable
- {
+ if( m != 0.0f )
+ { // insanity check! Mass must be invertable
this->mass = m;
}
}
void RigidBody::SetOrientation( const Float4x4 &o )
{ // by Dan Andersson
- ExtractRotationMatrix( o, this->box.rotation );
- this->box.center = o.v[3].xyz;
-}
-
-void RigidBody::SetSize( const Float3 &widthHeight )
-{ // by Dan Andersson
- this->box.boundingOffset = 0.5f * widthHeight;
-}
-
-void RigidBody::SetCenter( const Float3 &worldPos )
-{ // by Dan Andersson
- this->box.center = worldPos;
+ this->axis = ExtractAngularAxis( o );
+ this->rotation = Rotation( this->axis );
+ this->centerPos = o.v[3].xyz;
}
void RigidBody::SetRotation( const Float4x4 &r )
{ // by Dan Andersson
- this->box.rotation = r;
+ this->axis = ExtractAngularAxis( r );
+ this->rotation = Rotation( this->axis );
}
-void RigidBody::SetImpulseTorque( const Float3 &worldT )
+void RigidBody::SetMomentum_Linear( const Float4 &worldG, const Float4 &atWorldPos )
{ // by Dan Andersson
- this->impulseTorqueSum = worldT;
+ Float4 worldOffset = atWorldPos - this->centerPos;
+ this->momentum_Linear = VectorProjection( worldG, worldOffset );
+ this->momentum_Angular = Formula::AngularMomentum( worldG, worldOffset );
}
-void RigidBody::SetAngularMomentum( const Float3 &worldH )
+void RigidBody::SetVelocity_Linear( const Float4 &worldV )
{ // by Dan Andersson
- this->angularMomentum = worldH;
+ this->momentum_Linear = Formula::LinearMomentum( this->mass, worldV );
}
-void RigidBody::SetAngularImpulseAcceleration( const Float3 &worldA )
+void RigidBody::SetVelocity_Linear( const Float4 &worldV, const Float4 &atWorldPos )
{ // by Dan Andersson
- this->impulseTorqueSum = Formula::ImpulseTorque( this->momentOfInertiaTensor, worldA );
+ Float4 worldOffset = atWorldPos - this->centerPos;
+ this->momentum_Linear = Formula::LinearMomentum( this->mass, VectorProjection(worldV, worldOffset) );
+ this->momentum_Angular = Formula::AngularMomentum( RotationMatrix(this->rotation) * this->momentOfInertiaTensor, Formula::AngularVelocity(worldV, worldOffset) );
}
-void RigidBody::SetAngularVelocity( const Float3 &worldW )
+void RigidBody::SetVelocity_Angular( const Float4 &worldW )
{ // by Dan Andersson
- this->angularMomentum = Formula::AngularMomentum( this->momentOfInertiaTensor, worldW );
+ this->momentum_Angular = Formula::AngularMomentum( this->momentOfInertiaTensor, worldW );
}
-void RigidBody::SetImpulseForce( const Float3 &worldF )
+void RigidBody::SetImpulse_Linear( const Float4 &worldJ, const Float4 &atWorldPos )
{ // by Dan Andersson
- this->impulseForceSum = worldF;
-}
-
-void RigidBody::SetLinearMomentum( const Float3 &worldG )
-{ // by Dan Andersson
- this->linearMomentum = worldG;
-}
-
-void RigidBody::SetLinearImpulseAcceleration( const Float3 &worldA )
-{ // by Dan Andersson
- this->impulseForceSum = Formula::ImpulseForce( this->mass, worldA );
-}
-
-void RigidBody::SetLinearVelocity( const Float3 &worldV )
-{ // by Dan Andersson
- this->linearMomentum = Formula::LinearMomentum( this->mass, worldV );
-}
-
-void RigidBody::SetImpulseForceAt( const Float3 &worldForce, const Float3 &worldPos )
-{ // by Dan Andersson
- Float3 worldOffset = worldPos - this->box.center;
- this->impulseForceSum = VectorProjection( worldForce, worldOffset );
- this->impulseTorqueSum = Formula::ImpulseTorque( worldForce, worldOffset );
-}
-
-void RigidBody::SetLinearMomentumAt( const Float3 &worldG, const Float3 &worldPos )
-{ // by Dan Andersson
- Float3 worldOffset = worldPos - this->box.center;
- this->linearMomentum = VectorProjection( worldG, worldOffset );
- this->angularMomentum = Formula::AngularMomentum( worldG, worldOffset );
-}
-
-void RigidBody::SetImpulseAccelerationAt( const Float3 &worldA, const Float3 &worldPos )
-{ // by Dan Andersson
- Float3 worldOffset = worldPos - this->box.center;
- this->impulseForceSum = Formula::ImpulseForce( this->mass, VectorProjection(worldA, worldOffset) );
- this->impulseTorqueSum = Formula::ImpulseTorque( this->box.rotation * this->momentOfInertiaTensor,
- Formula::AngularImpulseAcceleration(worldA, worldOffset) );
-}
-
-void RigidBody::SetLinearVelocityAt( const Float3 &worldV, const Float3 &worldPos )
-{ // by Dan Andersson
- Float3 worldOffset = worldPos - this->box.center;
- this->linearMomentum = Formula::LinearMomentum( this->mass, VectorProjection(worldV, worldOffset) );
- this->angularMomentum = Formula::AngularMomentum( this->box.rotation * this->momentOfInertiaTensor,
- Formula::AngularVelocity(worldV, worldOffset) );
+ Float4 worldOffset = atWorldPos - this->centerPos;
+ this->impulse_Linear = VectorProjection( worldJ, worldOffset );
+ this->impulse_Angular = Formula::ImpulseTorque( worldJ, worldOffset );
}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/RigidBody.h b/Code/OysterPhysics3D/RigidBody.h
index 81c92ae0..a2f44480 100644
--- a/Code/OysterPhysics3D/RigidBody.h
+++ b/Code/OysterPhysics3D/RigidBody.h
@@ -12,109 +12,76 @@
namespace Oyster { namespace Physics3D
{
struct RigidBody
- { /// A struct of a simple rigid body.
+ { //! A struct of a simple rigid body.
public:
- ::Oyster::Collision3D::Box box; /** Contains data representing physical presence. (worldValue) */
- ::Oyster::Math::Float3 angularMomentum, /** The angular momentum H (Nm*s) around an parallell axis. (worldValue) */
- linearMomentum, /** The linear momentum G (kg*m/s). (worldValue) */
- impulseTorqueSum, /** The impulse torque T (Nm) that will be consumed each update. (worldValue) */
- impulseForceSum; /** The impulse force F (N) that will be consumed each update. (worldValue) */
+ ::Oyster::Math::Float4 centerPos, //!< Location of the body's center in the world.
+ axis, //!< Euler rotationAxis of the body.
+ boundingReach, //!<
+ momentum_Linear, //!< The linear momentum G (kg*m/s).
+ momentum_Angular, //!< The angular momentum H (Nm*s) around an parallell axis.
+ impulse_Linear, //!< The linear impulse sum Jl (kg*m/s) that will be consumed each update.
+ impulse_Angular; //!< The angular impulse sum Ja (kg*m^2/s) that will be consumed each update.
+ ::Oyster::Math::Float restitutionCoeff, //!<
+ frictionCoeff_Static, //!<
+ frictionCoeff_Kinetic; //!<
- RigidBody( const ::Oyster::Collision3D::Box &box = ::Oyster::Collision3D::Box(),
- ::Oyster::Math::Float mass = 12.0f,
- const ::Oyster::Math::Float4x4 &inertiaTensor = ::Oyster::Math::Float4x4::identity );
+ RigidBody();
RigidBody & operator = ( const RigidBody &body );
- bool operator == ( const RigidBody &body );
- bool operator != ( const RigidBody &body );
+ void Update_LeapFrog( ::Oyster::Math::Float updateFrameLength );
+ void Predict_LeapFrog( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime );
- void Update_LeapFrog( ::Oyster::Math::Float deltaTime );
- void ApplyImpulseForce( const ::Oyster::Math::Float3 &worldF );
- void ApplyImpulseForceAt( const ::Oyster::Math::Float3 &worldF, const ::Oyster::Math::Float3 &worldPos );
- void ApplyLinearImpulseAcceleration( const ::Oyster::Math::Float3 &worldA );
- void ApplyLinearImpulseAccelerationAt( const ::Oyster::Math::Float3 &worldA, const ::Oyster::Math::Float3 &worldPos );
- void ApplyImpulseTorque( const ::Oyster::Math::Float3 &worldT );
- void ApplyAngularImpulseAcceleration( const ::Oyster::Math::Float3 &worldA );
-
- // ACCESS METHODS /////////////////////////////
-
- ::Oyster::Math::Float3 & AccessBoundingReach();
- const ::Oyster::Math::Float3 & AccessBoundingReach() const;
- ::Oyster::Math::Float3 & AccessCenter();
- const ::Oyster::Math::Float3 & AccessCenter() const;
+ void Move( const ::Oyster::Math::Float4 &deltaPos, const ::Oyster::Math::Float4 &deltaAxis );
+ void ApplyImpulse( const ::Oyster::Math::Float4 &worldJ, const ::Oyster::Math::Float4 &atWorldPos );
+ void ApplyImpulse_Linear( const ::Oyster::Math::Float4 &worldJ );
+ void ApplyImpulse_Angular( const ::Oyster::Math::Float4 &worldJ );
+ void ApplyForce( const ::Oyster::Math::Float4 &worldF, ::Oyster::Math::Float updateFrameLength );
+ void ApplyForce( const ::Oyster::Math::Float4 &worldF, ::Oyster::Math::Float updateFrameLength, const ::Oyster::Math::Float4 &atWorldPos );
// GET METHODS ////////////////////////////////
- const ::Oyster::Math::Float4x4 & GetMomentOfInertia() const;
- const ::Oyster::Math::Float & GetMass() const;
-
- const ::Oyster::Math::Float4x4 GetOrientation() const;
- ::Oyster::Math::Float4x4 GetView() const;
- const ::Oyster::Math::Float4x4 & GetToWorldMatrix() const;
- ::Oyster::Math::Float4x4 GetToLocalMatrix() const;
-
- const ::Oyster::Math::Float3 & GetBoundingReach() const;
- ::Oyster::Math::Float3 GetSize() const;
-
- const ::Oyster::Math::Float3 & GetCenter() const;
-
- const ::Oyster::Math::Float3 & GetImpulsTorque() const;
- const ::Oyster::Math::Float3 & GetAngularMomentum() const;
- ::Oyster::Math::Float3 GetAngularImpulseAcceleration() const;
- ::Oyster::Math::Float3 GetAngularVelocity() const;
-
- const ::Oyster::Math::Float3 & GetImpulseForce() const;
- const ::Oyster::Math::Float3 & GetLinearMomentum() const;
- ::Oyster::Math::Float3 GetLinearImpulseAcceleration() const;
- ::Oyster::Math::Float3 GetLinearVelocity() const;
-
- void GetMomentumAt( const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &surfaceNormal, ::Oyster::Math::Float3 &normalMomentum, ::Oyster::Math::Float3 &tangentialMomentum ) const;
+ const ::Oyster::Math::Float4x4 & GetMomentOfInertia() const;
+ ::Oyster::Math::Float GetMass() const;
+ const ::Oyster::Math::Quaternion & GetRotation() const;
+ ::Oyster::Math::Float4x4 GetRotationMatrix() const;
+ ::Oyster::Math::Float4x4 GetOrientation() const;
+ ::Oyster::Math::Float4x4 GetView() const;
+ ::Oyster::Math::Float4x4 GetToWorldMatrix() const;
+ ::Oyster::Math::Float4x4 GetToLocalMatrix() const;
+ ::Oyster::Math::Float4 GetSize() const;
+ ::Oyster::Math::Float4 GetVelocity_Linear() const;
+ ::Oyster::Math::Float4 GetVelocity_Angular() const;
+ ::Oyster::Math::Float4 GetLinearMomentum( const ::Oyster::Math::Float4 &atWorldPos ) const;
// SET METHODS ////////////////////////////////
- void SetMomentOfInertia_KeepVelocity( const ::Oyster::Math::Float4x4 &localI );
- void SetMomentOfInertia_KeepMomentum( const ::Oyster::Math::Float4x4 &localI );
+ void SetMomentOfInertia_KeepVelocity( const ::Oyster::Math::Float4x4 &localTensorI );
+ void SetMomentOfInertia_KeepMomentum( const ::Oyster::Math::Float4x4 &localTensorI );
void SetMass_KeepVelocity( const ::Oyster::Math::Float &m );
void SetMass_KeepMomentum( const ::Oyster::Math::Float &m );
void SetOrientation( const ::Oyster::Math::Float4x4 &o );
- void SetSize( const ::Oyster::Math::Float3 &widthHeight );
- void SetCenter( const ::Oyster::Math::Float3 &worldPos );
void SetRotation( const ::Oyster::Math::Float4x4 &r );
-
- void SetImpulseTorque( const ::Oyster::Math::Float3 &worldT );
- void SetAngularMomentum( const ::Oyster::Math::Float3 &worldH );
- void SetAngularImpulseAcceleration( const ::Oyster::Math::Float3 &worldA );
- void SetAngularVelocity( const ::Oyster::Math::Float3 &worldW );
-
- void SetImpulseForce( const ::Oyster::Math::Float3 &worldF );
- void SetLinearMomentum( const ::Oyster::Math::Float3 &worldG );
- void SetLinearImpulseAcceleration( const ::Oyster::Math::Float3 &worldA );
- void SetLinearVelocity( const ::Oyster::Math::Float3 &worldV );
+ void SetSize( const ::Oyster::Math::Float4 &widthHeight );
- void SetImpulseForceAt( const ::Oyster::Math::Float3 &worldF, const ::Oyster::Math::Float3 &worldPos );
- void SetLinearMomentumAt( const ::Oyster::Math::Float3 &worldG, const ::Oyster::Math::Float3 &worldPos );
- void SetImpulseAccelerationAt( const ::Oyster::Math::Float3 &worldA, const ::Oyster::Math::Float3 &worldPos );
- void SetLinearVelocityAt( const ::Oyster::Math::Float3 &worldV, const ::Oyster::Math::Float3 &worldPos );
+ void SetMomentum_Linear( const ::Oyster::Math::Float4 &worldG, const ::Oyster::Math::Float4 &atWorldPos );
+
+ void SetVelocity_Linear( const ::Oyster::Math::Float4 &worldV );
+ void SetVelocity_Linear( const ::Oyster::Math::Float4 &worldV, const ::Oyster::Math::Float4 &atWorldPos );
+ void SetVelocity_Angular( const ::Oyster::Math::Float4 &worldW );
+
+ void SetImpulse_Linear( const ::Oyster::Math::Float4 &worldJ, const ::Oyster::Math::Float4 &atWorldPos );
+ void SetForce( const ::Oyster::Math::Float4 &worldF, ::Oyster::Math::Float updateFrameLength );
+ void SetForce( const ::Oyster::Math::Float4 &worldF, ::Oyster::Math::Float updateFrameLength, const ::Oyster::Math::Float4 &atWorldPos );
private:
- ::Oyster::Math::Float mass; /** m (kg) */
- ::Oyster::Math::Float4x4 momentOfInertiaTensor; /** I (Nm*s) Tensor matrix ( only need to be 3x3 matrix, but is 4x4 for future hardware acceleration ) (localValue) */
+ ::Oyster::Math::Float mass; //!< m (kg)
+ ::Oyster::Math::Float4x4 momentOfInertiaTensor; //!< I (Nm*s) Tensor matrix ( only need to be 3x3 matrix, but is 4x4 for future hardware acceleration ) (localValue)
+ ::Oyster::Math::Quaternion rotation; //!< RotationAxis of the body.
};
-
- // INLINE IMPLEMENTATIONS ///////////////////////////////////////
-
- inline const ::Oyster::Math::Float4x4 & RigidBody::GetToWorldMatrix() const
- {
- return this->GetOrientation();
- }
-
- inline ::Oyster::Math::Float4x4 RigidBody::GetToLocalMatrix() const
- {
- return this->GetView();
- }
-
} }
+#include "RigidBody_Inline.h"
+
#endif
diff --git a/Code/OysterPhysics3D/RigidBody_Inline.h b/Code/OysterPhysics3D/RigidBody_Inline.h
new file mode 100644
index 00000000..980442dd
--- /dev/null
+++ b/Code/OysterPhysics3D/RigidBody_Inline.h
@@ -0,0 +1,65 @@
+/////////////////////////////////////////////////////////////////////
+// INLINE IMPLEMENTATIONS
+// Created by Dan Andersson 2013
+/////////////////////////////////////////////////////////////////////
+
+#ifndef OYSTER_PHYSICS_3D_RIGIDBODY_INLINE_H
+#define OYSTER_PHYSICS_3D_RIGIDBODY_INLINE_H
+
+#include "RigidBody.h"
+
+namespace Oyster { namespace Physics3D
+{
+ inline void RigidBody::ApplyImpulse_Linear( const ::Oyster::Math::Float4 &worldJ )
+ {
+ this->impulse_Linear += worldJ;
+ }
+
+ inline void RigidBody::ApplyImpulse_Angular( const ::Oyster::Math::Float4 &worldJ )
+ {
+ this->impulse_Angular += worldJ;
+ }
+
+ inline void RigidBody::ApplyForce( const ::Oyster::Math::Float4 &worldF, ::Oyster::Math::Float updateFrameLength )
+ {
+ this->impulse_Linear += worldF * updateFrameLength;
+ }
+
+ inline void RigidBody::ApplyForce( const ::Oyster::Math::Float4 &worldF, ::Oyster::Math::Float updateFrameLength, const ::Oyster::Math::Float4 &atWorldPos )
+ {
+ this->ApplyImpulse( worldF * updateFrameLength, atWorldPos );
+ }
+
+ inline ::Oyster::Math::Float4x4 RigidBody::GetToWorldMatrix() const
+ {
+ return this->GetOrientation();
+ }
+
+ inline ::Oyster::Math::Float4x4 RigidBody::GetToLocalMatrix() const
+ {
+ return this->GetView();
+ }
+
+ inline ::Oyster::Math::Float4 RigidBody::GetSize() const
+ {
+ return 2.0f * this->boundingReach;
+ }
+
+ inline void RigidBody::SetSize( const ::Oyster::Math::Float4 &widthHeight )
+ {
+ this->boundingReach = ::Utility::Value::Abs( 0.5f * widthHeight );
+ }
+
+ inline void RigidBody::SetForce( const ::Oyster::Math::Float4 &worldF, ::Oyster::Math::Float updateFrameLength )
+ {
+ this->impulse_Linear = worldF * updateFrameLength;
+ }
+
+ inline void RigidBody::SetForce( const ::Oyster::Math::Float4 &worldF, ::Oyster::Math::Float updateFrameLength, const ::Oyster::Math::Float4 &atWorldPos )
+ {
+ this->SetImpulse_Linear( worldF * updateFrameLength, atWorldPos );
+ }
+
+} }
+
+#endif
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Sphere.cpp b/Code/OysterPhysics3D/Sphere.cpp
index 4f6f76f7..c402b2ef 100644
--- a/Code/OysterPhysics3D/Sphere.cpp
+++ b/Code/OysterPhysics3D/Sphere.cpp
@@ -6,14 +6,20 @@ using namespace ::Oyster::Math;
Sphere::Sphere( ) : ICollideable(Type_sphere)
{
- this->center = Float3::null;
+ this->center = Float4::standard_unit_w;
this->radius = 0.0f;
}
-Sphere::Sphere( const Float3 &_position, const Float &_radius ) : ICollideable(Type_sphere)
+Sphere::Sphere( const Float3 &p, const Float &r ) : ICollideable(Type_sphere)
{
- this->center = _position;
- this->radius = _radius;
+ this->center = Float4( p, 1.0f );
+ this->radius = r;
+}
+
+Sphere::Sphere( const Float4 &p, const Float &r ) : ICollideable(Type_sphere)
+{
+ this->center = p;
+ this->radius = r;
}
Sphere::~Sphere( ) {}
@@ -26,22 +32,45 @@ Sphere & Sphere::operator = ( const Sphere &sphere )
}
::Utility::DynamicMemory::UniquePointer Sphere::Clone( ) const
-{ return ::Utility::DynamicMemory::UniquePointer( new Sphere(*this) ); }
+{
+ return ::Utility::DynamicMemory::UniquePointer( new Sphere(*this) );
+}
bool Sphere::Intersects( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_universe: return true;
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- case Type_ray: return Utility::Intersect( *this, *(Ray*)&target, ((Ray*)&target)->collisionDistance );
- case Type_sphere: return Utility::Intersect( *this, *(Sphere*)&target );
- case Type_plane: return Utility::Intersect( *(Plane*)&target, *this );
- // case Type_triangle: return false; // TODO:
- case Type_box_axis_aligned: return Utility::Intersect( *(BoxAxisAligned*)&target, *this );
- case Type_box: return Utility::Intersect( *(Box*)&target, *this );
- case Type_frustrum: return false; // TODO:
- default: return false;
+ case Type_universe: return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, ((const Ray&)target).collisionDistance );
+ case Type_sphere: return Utility::Intersect( *this, (const Sphere&)target );
+ case Type_plane: return Utility::Intersect( (const Plane&)target, *this );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( (const BoxAxisAligned&)target, *this );
+ case Type_box: return Utility::Intersect( (const Box&)target, *this );
+ //case Type_frustrum: return false; // TODO:
+ default: return false;
+ }
+}
+
+bool Sphere::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{
+ switch( target.type )
+ {
+ case Type_universe:
+ worldPointOfContact = this->center;
+ return true;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target, worldPointOfContact );
+ case Type_ray: return Utility::Intersect( *this, (const Ray&)target, ((const Ray&)target).collisionDistance, worldPointOfContact );
+ case Type_sphere: return Utility::Intersect( *this, (const Sphere&)target, worldPointOfContact );
+ case Type_plane: return Utility::Intersect( (const Plane&)target, *this, worldPointOfContact );
+ //case Type_triangle: return false; // TODO:
+ case Type_box_axis_aligned: return Utility::Intersect( (const BoxAxisAligned&)target, *this, worldPointOfContact );
+ case Type_box: return Utility::Intersect( (const Box&)target, *this, worldPointOfContact );
+ //case Type_frustrum: return false; // TODO:
+ default:
+ worldPointOfContact = Float3::null;
+ return false;
}
}
@@ -49,12 +78,12 @@ bool Sphere::Contains( const ICollideable &target ) const
{
switch( target.type )
{
- case Type_point: return Utility::Intersect( *this, *(Point*)&target );
- case Type_sphere: return Utility::Contains( *this, *(Sphere*)&target );
- // case Type_triangle: return false; // TODO:
- case Type_box_axis_aligned: return false; // TODO:
- case Type_box: return false; // TODO:
- case Type_frustrum: return false; // TODO:
- default: return false;
+ case Type_point: return Utility::Intersect( *this, (const Point&)target );
+ case Type_sphere: return Utility::Contains( *this, (const Sphere&)target );
+ //case Type_triangle: return false; // TODO:
+ //case Type_box_axis_aligned: return false; // TODO:
+ //case Type_box: return false; // TODO:
+ //case Type_frustrum: return false; // TODO:
+ default: return false;
}
}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Sphere.h b/Code/OysterPhysics3D/Sphere.h
index 8e73de0b..2f483ecd 100644
--- a/Code/OysterPhysics3D/Sphere.h
+++ b/Code/OysterPhysics3D/Sphere.h
@@ -16,18 +16,20 @@ namespace Oyster { namespace Collision3D
public:
union
{
- struct{ ::Oyster::Math::Float3 center; ::Oyster::Math::Float radius; };
- char byte[sizeof(::Oyster::Math::Float3) + sizeof(::Oyster::Math::Float)];
+ 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 Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }
diff --git a/Code/OysterPhysics3D/Universe.cpp b/Code/OysterPhysics3D/Universe.cpp
index 725e2839..7eb788ae 100644
--- a/Code/OysterPhysics3D/Universe.cpp
+++ b/Code/OysterPhysics3D/Universe.cpp
@@ -1,6 +1,8 @@
#include "Universe.h"
#include "OysterCollision3D.h"
+using namespace ::Utility::Value;
+using namespace ::Oyster::Math;
using namespace ::Oyster::Collision3D;
using namespace ::Utility::DynamicMemory;
@@ -8,20 +10,24 @@ Universe::Universe() : ICollideable(Type_universe) {}
Universe::~Universe() {}
Universe & Universe::operator = ( const Universe &universe )
-{ return *this; }
+{
+ return *this;
+}
UniquePointer Universe::Clone( ) const
-{ return UniquePointer( new Universe(*this) ); }
+{
+ return UniquePointer( new Universe(*this) );
+}
bool Universe::Intersects( const ICollideable &target ) const
{ // universe touches everything
switch( target.type )
{
case Type_ray:
- ((Ray*)&target)->collisionDistance = 0.0f;
+ ((const Ray&)target).collisionDistance = 0.0f;
break;
case Type_line:
- ((Line*)&target)->ray.collisionDistance = 0.0f;
+ ((const Line&)target).ray.collisionDistance = 0.0f;
break;
default: break;
}
@@ -29,6 +35,47 @@ bool Universe::Intersects( const ICollideable &target ) const
return true;
}
-bool Universe::Contains( const ICollideable &target ) const
-{ return true; } // universe contains everything
+bool Universe::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) const
+{ // universe touches everything
+ switch( target.type )
+ {
+ case Type_point:
+ worldPointOfContact = ((const Point&)target).center;
+ break;
+ case Type_sphere:
+ worldPointOfContact = ((const Sphere&)target).center;
+ break;
+ case Type_plane:
+ worldPointOfContact = ((const Plane&)target).normal * ((const Plane&)target).phasing;
+ break;
+ case Type_box_axis_aligned:
+ worldPointOfContact = Average( ((const BoxAxisAligned&)target).minVertex, ((const BoxAxisAligned&)target).maxVertex );
+ break;
+ case Type_box:
+ worldPointOfContact = ((const Box&)target).center;
+ break;
+ case Type_frustrum:
+ worldPointOfContact = Average( ((const Frustrum&)target).leftPlane.normal * ((const Frustrum&)target).leftPlane.phasing, ((const Frustrum&)target).rightPlane.normal * ((const Frustrum&)target).rightPlane.phasing );
+ worldPointOfContact = Average( worldPointOfContact, Average( ((const Frustrum&)target).bottomPlane.normal * ((const Frustrum&)target).bottomPlane.phasing, ((const Frustrum&)target).topPlane.normal * ((const Frustrum&)target).topPlane.phasing ) );
+ worldPointOfContact = Average( worldPointOfContact, Average( ((const Frustrum&)target).nearPlane.normal * ((const Frustrum&)target).nearPlane.phasing, ((const Frustrum&)target).farPlane.normal * ((const Frustrum&)target).farPlane.phasing ) );
+ break;
+ case Type_ray:
+ ((const Ray&)target).collisionDistance = 0.0f;
+ worldPointOfContact = ((const Ray&)target).origin;
+ break;
+ case Type_line:
+ ((const Line&)target).ray.collisionDistance = 0.0f;
+ worldPointOfContact = ((const Line&)target).ray.origin;
+ break;
+ default:
+ worldPointOfContact = Float3::null;
+ break;
+ }
+ return true;
+}
+
+bool Universe::Contains( const ICollideable &target ) const
+{ // universe contains everything
+ return true;
+}
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/Universe.h b/Code/OysterPhysics3D/Universe.h
index ff8366be..5f009e0b 100644
--- a/Code/OysterPhysics3D/Universe.h
+++ b/Code/OysterPhysics3D/Universe.h
@@ -7,6 +7,7 @@
#define OYSTER_COLLISION_3D_UNIVERSE_H
#include "ICollideable.h"
+#include "OysterMath.h"
namespace Oyster { namespace Collision3D
{
@@ -20,6 +21,7 @@ namespace Oyster { namespace Collision3D
virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const;
bool Intersects( const ICollideable &target ) const;
+ bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }