Merge remote-tracking branch 'origin/Physics' into Sprint2

This commit is contained in:
Dander7BD 2013-12-20 12:18:30 +01:00
commit fba52398c3
46 changed files with 2682 additions and 1270 deletions

View File

@ -166,6 +166,8 @@
<ClInclude Include="Implementation\SimpleRigidBody.h" />
<ClInclude Include="Implementation\SphericalRigidBody.h" />
<ClInclude Include="PhysicsAPI.h" />
<ClInclude Include="PhysicsFormula-Impl.h" />
<ClInclude Include="PhysicsFormula.h" />
<ClInclude Include="PhysicsStructs-Impl.h" />
<ClInclude Include="PhysicsStructs.h" />
</ItemGroup>

View File

@ -42,6 +42,12 @@
<ClInclude Include="PhysicsStructs-Impl.h">
<Filter>Header Files\Include</Filter>
</ClInclude>
<ClInclude Include="PhysicsFormula.h">
<Filter>Header Files\Include</Filter>
</ClInclude>
<ClInclude Include="PhysicsFormula-Impl.h">
<Filter>Header Files\Include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Implementation\PhysicsAPI_Impl.cpp">

View File

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

View File

@ -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<ICustomBody*> 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<ICustomBody> API_Impl::CreateRigidBody( const API::SimpleBodyDescription &desc ) const
{

View File

@ -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<ICustomBody> 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<ICustomBody> CreateRigidBody( const SimpleBodyDescription &desc ) const;
::Utility::DynamicMemory::UniquePointer<ICustomBody> CreateRigidBody( const SphericalBodyDescription &desc ) const;

View File

@ -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<ICustomBody> 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<Float>::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 );
}
//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 );
//}

View File

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

View File

@ -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<ICustomBody> 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 );
}
//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 );
//}

View File

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

View File

@ -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,30 +309,30 @@ 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
@ -362,6 +340,18 @@ namespace Oyster
********************************************************/
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_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_KeepMomentum(...)
********************************************************/
virtual void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI ) = 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::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::?? @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

View File

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

View File

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

View File

@ -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 &centerPos, 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 &centerPos, 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 &centerPos )
inline void CustomBodyState::SetCenterPosition( const ::Oyster::Math::Float4 &centerPos )
{
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;
}
}
} }

View File

@ -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 &centerPos = ::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 &centerPos = ::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;
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 SetSize( const ::Oyster::Math::Float3 &size );
void SetReach( const ::Oyster::Math::Float3 &halfSize );
void SetCenterPosition( const ::Oyster::Math::Float3 &centerPos );
void SetRotation( const ::Oyster::Math::Float3 &angularAxis );
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 &centerPos );
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;
};
}
} }

View File

@ -266,6 +266,12 @@ namespace LinearAlgebra3D
return ::std::asin( ::LinearAlgebra::Vector4<ScalarType>(rotationMatrix.v[1].z, rotationMatrix.v[2].x, rotationMatrix.v[0].y, 1) );
}
template<typename ScalarType>
inline ::LinearAlgebra::Vector4<ScalarType> ExtractAngularAxis( const ::LinearAlgebra::Matrix4x4<ScalarType> &orientationMatrix )
{
return ::std::asin( ::LinearAlgebra::Vector4<ScalarType>(orientationMatrix.v[1].z, orientationMatrix.v[2].x, orientationMatrix.v[0].y, 0) );
}
template<typename ScalarType>
inline ::LinearAlgebra::Matrix4x4<ScalarType> & TranslationMatrix( const ::LinearAlgebra::Vector3<ScalarType> &position, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{
@ -275,6 +281,106 @@ namespace LinearAlgebra3D
0, 0, 0, 1 );
}
template<typename ScalarType>
inline ::LinearAlgebra::Quaternion<ScalarType> Rotation( const ScalarType &radian, const ::LinearAlgebra::Vector3<ScalarType> &normalizedAxis )
{
ScalarType r = radian * 0.5f,
s = std::sin( r ),
c = std::cos( r );
return ::LinearAlgebra::Quaternion<ScalarType>( normalizedAxis * s, c );
}
template<typename ScalarType>
inline ::LinearAlgebra::Quaternion<ScalarType> Rotation( const ScalarType &radian, const ::LinearAlgebra::Vector4<ScalarType> &normalizedAxis )
{
ScalarType r = radian * 0.5f,
s = std::sin( r ),
c = std::cos( r );
return ::LinearAlgebra::Quaternion<ScalarType>( (normalizedAxis * s).xyz, c );
}
template<typename ScalarType>
inline ::LinearAlgebra::Quaternion<ScalarType> Rotation( const ::LinearAlgebra::Vector3<ScalarType> &angularAxis )
{
ScalarType radius = angularAxis.Dot( angularAxis );
if( radius != 0 )
{
radius = (ScalarType)::std::sqrt( radius );
return Rotation( radius, angularAxis / radius );
}
else
{
return ::LinearAlgebra::Quaternion<ScalarType>::identity;
}
}
template<typename ScalarType>
inline ::LinearAlgebra::Quaternion<ScalarType> Rotation( const ::LinearAlgebra::Vector4<ScalarType> &angularAxis )
{
ScalarType radius = angularAxis.Dot( angularAxis );
if( radius != 0 )
{
radius = (ScalarType)::std::sqrt( radius );
return Rotation( radius, angularAxis / radius );
}
else
{
return ::LinearAlgebra::Quaternion<ScalarType>::identity;
}
}
template<typename ScalarType>
inline ::LinearAlgebra::Matrix4x4<ScalarType> & RotationMatrix( const ::LinearAlgebra::Quaternion<ScalarType> &rotationQuaternion, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{
::LinearAlgebra::Quaternion<ScalarType> conjugate = rotationQuaternion.GetConjugate();
targetMem.v[0] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(1,0,0)*conjugate).imaginary, 0 );
targetMem.v[1] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(0,1,0)*conjugate).imaginary, 0 );
targetMem.v[2] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(0,0,1)*conjugate).imaginary, 0 );
targetMem.v[3] = ::LinearAlgebra::Vector4<ScalarType>::standard_unit_w;
return targetMem;
}
template<typename ScalarType>
inline ::LinearAlgebra::Matrix4x4<ScalarType> & OrientationMatrix( const ::LinearAlgebra::Quaternion<ScalarType> &rotationQuaternion, const ::LinearAlgebra::Vector3<ScalarType> &translation, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{
::LinearAlgebra::Quaternion<ScalarType> conjugate = rotationQuaternion.GetConjugate();
targetMem.v[0] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(1,0,0)*conjugate).imaginary, 0 );
targetMem.v[1] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(0,1,0)*conjugate).imaginary, 0 );
targetMem.v[2] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(0,0,1)*conjugate).imaginary, 0 );
targetMem.v[3] = ::LinearAlgebra::Vector4<ScalarType>( translation, 1 );
return targetMem;
}
template<typename ScalarType>
inline ::LinearAlgebra::Matrix4x4<ScalarType> & OrientationMatrix( const ::LinearAlgebra::Quaternion<ScalarType> &rotationQuaternion, const ::LinearAlgebra::Vector4<ScalarType> &translation, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{
::LinearAlgebra::Quaternion<ScalarType> conjugate = rotationQuaternion.GetConjugate();
targetMem.v[0] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(1,0,0)*conjugate).imaginary, 0 );
targetMem.v[1] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(0,1,0)*conjugate).imaginary, 0 );
targetMem.v[2] = ::LinearAlgebra::Vector4<ScalarType>( (rotationQuaternion*::LinearAlgebra::Vector3<ScalarType>(0,0,1)*conjugate).imaginary, 0 );
targetMem.v[3] = translation;
return targetMem;
}
template<typename ScalarType>
inline ::LinearAlgebra::Matrix4x4<ScalarType> & ViewMatrix( const ::LinearAlgebra::Quaternion<ScalarType> &rotationQuaternion, const ::LinearAlgebra::Vector3<ScalarType> &translation, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{
OrientationMatrix( rotationQuaternion, translation, targetMem );
return InverseOrientationMatrix( targetMem, targetMem );
}
template<typename ScalarType>
inline ::LinearAlgebra::Matrix4x4<ScalarType> & ViewMatrix( const ::LinearAlgebra::Quaternion<ScalarType> &rotationQuaternion, const ::LinearAlgebra::Vector4<ScalarType> &translation, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{
OrientationMatrix( rotationQuaternion, translation, targetMem );
return InverseOrientationMatrix( targetMem, targetMem );
}
template<typename ScalarType>
inline ::LinearAlgebra::Matrix3x3<ScalarType> & RotationMatrix_AxisX( const ScalarType &radian, ::LinearAlgebra::Matrix3x3<ScalarType> &targetMem = ::LinearAlgebra::Matrix3x3<ScalarType>() )
{
@ -400,18 +506,35 @@ namespace LinearAlgebra3D
}
template<typename ScalarType>
::LinearAlgebra::Matrix4x4<ScalarType> & OrientationMatrix( const ::LinearAlgebra::Vector3<ScalarType> &sumDeltaAngularAxis, const ::LinearAlgebra::Vector3<ScalarType> &sumTranslation, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{ /** @todo TODO: not tested */
ScalarType radian = sumDeltaAngularAxis.Dot( sumDeltaAngularAxis );
::LinearAlgebra::Matrix4x4<ScalarType> & OrientationMatrix( const ::LinearAlgebra::Vector3<ScalarType> &angularAxis, const ::LinearAlgebra::Vector3<ScalarType> &translation, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{
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<ScalarType>::identity;
targetMem.v[3].xyz = sumTranslation;
targetMem.v[3].xyz = translation;
return targetMem;
}
}
template<typename ScalarType>
::LinearAlgebra::Matrix4x4<ScalarType> & ViewMatrix( const ::LinearAlgebra::Vector3<ScalarType> &angularAxis, const ::LinearAlgebra::Vector3<ScalarType> &translation, ::LinearAlgebra::Matrix4x4<ScalarType> &targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>() )
{
ScalarType radian = angularAxis.Dot( angularAxis );
if( radian > 0 )
{
radian = ::std::sqrt( radian );
return InverseOrientationMatrix( OrientationMatrix(angularAxis / radian, radian, translation, targetMem) );
}
else
{
targetMem = ::LinearAlgebra::Matrix4x4<ScalarType>::identity;
targetMem.v[3].xyz = -translation;
return targetMem;
}
}
@ -534,9 +657,17 @@ namespace LinearAlgebra3D
inline ::LinearAlgebra::Vector3<ScalarType> VectorProjection( const ::LinearAlgebra::Vector3<ScalarType> &vector, const ::LinearAlgebra::Vector3<ScalarType> &axis )
{ return axis * ( vector.Dot(axis) / axis.Dot(axis) ); }
template<typename ScalarType>
inline ::LinearAlgebra::Vector4<ScalarType> VectorProjection( const ::LinearAlgebra::Vector4<ScalarType> &vector, const ::LinearAlgebra::Vector4<ScalarType> &axis )
{ return axis * ( vector.Dot(axis) / axis.Dot(axis) ); }
template<typename ScalarType>
inline ::LinearAlgebra::Vector3<ScalarType> NormalProjection( const ::LinearAlgebra::Vector3<ScalarType> &vector, const ::LinearAlgebra::Vector3<ScalarType> &normalizedAxis )
{ return normalizedAxis * ( vector.Dot(normalizedAxis) ); }
template<typename ScalarType>
inline ::LinearAlgebra::Vector4<ScalarType> NormalProjection( const ::LinearAlgebra::Vector4<ScalarType> &vector, const ::LinearAlgebra::Vector4<ScalarType> &normalizedAxis )
{ return normalizedAxis * ( vector.Dot(normalizedAxis) ); }
}
#include "Utilities.h"

View File

@ -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 &centerOfMass, 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 );
}
} }

View File

@ -9,17 +9,19 @@
#include "LinearMath.h"
#include <limits>
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<Float> Float2; /// 2D Linear Vector for Oyster
typedef ::LinearAlgebra::Vector3<Float> Float3; /// 3D Linear Vector for Oyster
typedef ::LinearAlgebra::Vector4<Float> Float4; /// 4D Linear Vector for Oyster
typedef ::LinearAlgebra::Vector2<Float> Float2; //!< 2D Linear Vector for Oyster
typedef ::LinearAlgebra::Vector3<Float> Float3; //!< 3D Linear Vector for Oyster
typedef ::LinearAlgebra::Vector4<Float> Float4; //!< 4D Linear Vector for Oyster
typedef ::LinearAlgebra::Matrix2x2<Float> Float2x2; /// 2x2 Linear Matrix for Oyster
typedef ::LinearAlgebra::Matrix3x3<Float> Float3x3; /// 3x3 Linear Matrix for Oyster
typedef ::LinearAlgebra::Matrix4x4<Float> Float4x4; /// 4x4 Linear Matrix for Oyster
typedef ::LinearAlgebra::Matrix2x2<Float> Float2x2; //!< 2x2 Linear Matrix for Oyster
typedef ::LinearAlgebra::Matrix3x3<Float> Float3x3; //!< 3x3 Linear Matrix for Oyster
typedef ::LinearAlgebra::Matrix4x4<Float> Float4x4; //!< 4x4 Linear Matrix for Oyster
typedef ::LinearAlgebra::Quaternion<Float> 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<Float>::epsilon(), const Float &farClip = ::std::numeric_limits<Float>::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; }
} }

View File

@ -22,8 +22,10 @@ namespace LinearAlgebra
char byte[sizeof(ScalarType[2])];
};
static const Quaternion<ScalarType> null;
static const Quaternion<ScalarType> identity;
Quaternion( );
Quaternion( const Quaternion &quaternion );
Quaternion( const Vector3<ScalarType> &imaginary, const ScalarType &real );
operator ScalarType* ( );
@ -53,40 +55,54 @@ namespace LinearAlgebra
// Body
///////////////////////////////////////////////////////////////////////////////////
template<typename ScalarType> const Quaternion<ScalarType> Quaternion<ScalarType>::null = Quaternion<ScalarType>( Vector3<ScalarType>((ScalarType)0), (ScalarType)0 );
template<typename ScalarType> const Quaternion<ScalarType> Quaternion<ScalarType>::identity = Quaternion<ScalarType>( Vector3<ScalarType>((ScalarType)0), (ScalarType)1 );
template<typename ScalarType>
Quaternion<ScalarType>::Quaternion( ) : imaginary(), real() {}
template<typename ScalarType>
Quaternion<ScalarType>::Quaternion( const Quaternion &quaternion )
{ this->imaginary = quaternion.imaginary; this->real = quaternion.real; }
template<typename ScalarType>
Quaternion<ScalarType>::Quaternion( const Vector3<ScalarType> &_imaginary, const ScalarType &_real )
{ this->imaginary = _imaginary; this->real = _real; }
Quaternion<ScalarType>::Quaternion( const Vector3<ScalarType> &imaginary, const ScalarType &real )
{
this->imaginary = imaginary;
this->real = real;
}
template<typename ScalarType>
inline Quaternion<ScalarType>::operator ScalarType* ( )
{ return this->element; }
{
return this->element;
}
template<typename ScalarType>
inline Quaternion<ScalarType>::operator const ScalarType* ( ) const
{ return this->element; }
{
return this->element;
}
template<typename ScalarType>
inline Quaternion<ScalarType>::operator char* ( )
{ return this->byte; }
{
return this->byte;
}
template<typename ScalarType>
inline Quaternion<ScalarType>::operator const char* ( ) const
{ return this->byte; }
{
return this->byte;
}
template<typename ScalarType>
inline ScalarType & Quaternion<ScalarType>::operator [] ( int i )
{ return this->element[i]; }
{
return this->element[i];
}
template<typename ScalarType>
inline const ScalarType & Quaternion<ScalarType>::operator [] ( int i ) const
{ return this->element[i]; }
{
return this->element[i];
}
template<typename ScalarType>
Quaternion<ScalarType> & Quaternion<ScalarType>::operator = ( const Quaternion<ScalarType> &quaternion )
@ -154,27 +170,39 @@ namespace LinearAlgebra
template<typename ScalarType>
inline Quaternion<ScalarType> Quaternion<ScalarType>::operator * ( const ScalarType &scalar ) const
{ return Quaternion<ScalarType>(*this) *= scalar; }
{
return Quaternion<ScalarType>(*this) *= scalar;
}
template<typename ScalarType>
inline Quaternion<ScalarType> Quaternion<ScalarType>::operator / ( const ScalarType &scalar ) const
{ return Quaternion<ScalarType>(*this) /= scalar; }
{
return Quaternion<ScalarType>(*this) /= scalar;
}
template<typename ScalarType>
inline Quaternion<ScalarType> Quaternion<ScalarType>::operator + ( const Quaternion<ScalarType> &quaternion ) const
{ return Quaternion<ScalarType>(*this) += quaternion; }
{
return Quaternion<ScalarType>(*this) += quaternion;
}
template<typename ScalarType>
inline Quaternion<ScalarType> Quaternion<ScalarType>::operator - ( const Quaternion<ScalarType> &quaternion ) const
{ return Quaternion<ScalarType>(*this) -= quaternion; }
{
return Quaternion<ScalarType>(*this) -= quaternion;
}
template<typename ScalarType>
inline Quaternion<ScalarType> Quaternion<ScalarType>::operator - ( ) const
{ return Quaternion<ScalarType>(-this->imaginary, -this->real); }
{
return Quaternion<ScalarType>(-this->imaginary, -this->real);
}
template<typename ScalarType>
inline Quaternion<ScalarType> Quaternion<ScalarType>::GetConjugate( ) const
{ return Quaternion<ScalarType>(-this->imaginary, this->real ); }
{
return Quaternion<ScalarType>(-this->imaginary, this->real );
}
}
#endif

View File

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

View File

@ -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<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }

View File

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

View File

@ -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<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }

View File

@ -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<ICollideable> Frustrum::Clone( ) const
{ return ::Utility::DynamicMemory::UniquePointer<ICollideable>( new Frustrum(*this) ); }
{
return ::Utility::DynamicMemory::UniquePointer<ICollideable>( 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;
}
}

View File

@ -39,6 +39,7 @@ namespace Oyster { namespace Collision3D
virtual ::Utility::DynamicMemory::UniquePointer<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};

View File

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

View File

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

View File

@ -30,6 +30,7 @@ namespace Oyster { namespace Collision3D
virtual ::Utility::DynamicMemory::UniquePointer<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }

View File

@ -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 &centerDistance, 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);
@ -321,6 +525,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
Float connectOffset;
@ -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<Float>::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<Float>::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 )

View File

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

View File

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

View File

@ -163,6 +163,7 @@
<ClInclude Include="Point.h" />
<ClInclude Include="Ray.h" />
<ClInclude Include="RigidBody.h" />
<ClInclude Include="RigidBody_Inline.h" />
<ClInclude Include="Sphere.h" />
<ClInclude Include="Spring.h" />
<ClInclude Include="Universe.h" />

View File

@ -75,6 +75,9 @@
<ClInclude Include="RigidBody.h">
<Filter>Header Files\Physics</Filter>
</ClInclude>
<ClInclude Include="RigidBody_Inline.h">
<Filter>Header Files\Physics</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Box.cpp">

View File

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

View File

@ -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<ICollideable> Plane::Clone( ) const
{ return ::Utility::DynamicMemory::UniquePointer<ICollideable>( new Plane(*this) ); }
{
return ::Utility::DynamicMemory::UniquePointer<ICollideable>( 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;
}
}

View File

@ -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<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }

View File

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

View File

@ -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<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }

View File

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

View File

@ -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<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }

View File

@ -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<Float>::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) );
this->axis += Formula::AngularVelocity( wMomentOfInertiaTensor.GetInverse(), AverageWithDelta(this->momentum_Angular, this->impulse_Angular) );
this->rotation = Rotation( this->axis );
Float deltaRadian = rotationAxis.Dot( rotationAxis );
if( deltaRadian != 0.0f )
{ // branch depending if there is rotation
deltaRadian = ::std::sqrt( deltaRadian );
rotationAxis /= deltaRadian;
// 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 );
}

View File

@ -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 SetSize( const ::Oyster::Math::Float4 &widthHeight );
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 SetMomentum_Linear( const ::Oyster::Math::Float4 &worldG, const ::Oyster::Math::Float4 &atWorldPos );
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 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 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 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

View File

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

View File

@ -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<ICollideable> Sphere::Clone( ) const
{ return ::Utility::DynamicMemory::UniquePointer<ICollideable>( new Sphere(*this) ); }
{
return ::Utility::DynamicMemory::UniquePointer<ICollideable>( 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;
}
}

View File

@ -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 &center, const ::Oyster::Math::Float &radius );
Sphere( const ::Oyster::Math::Float4 &center, const ::Oyster::Math::Float &radius );
virtual ~Sphere( );
Sphere & operator = ( const Sphere &sphere );
virtual ::Utility::DynamicMemory::UniquePointer<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }

View File

@ -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<ICollideable> Universe::Clone( ) const
{ return UniquePointer<ICollideable>( new Universe(*this) ); }
{
return UniquePointer<ICollideable>( 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;
}

View File

@ -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<ICollideable> Clone( ) const;
bool Intersects( const ICollideable &target ) const;
bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const;
bool Contains( const ICollideable &target ) const;
};
} }