Bug fixing

SimpleRigidBody::GetNormal returned wrong results.
Second bounce impulse in OnPossibleCollision, should be subtracted
instead of added.
This commit is contained in:
Dander7BD 2013-12-19 14:01:02 +01:00
parent 9b9e549a5e
commit 461fecd1d2
2 changed files with 44 additions and 11 deletions

View File

@ -54,7 +54,7 @@ namespace
deuterG_Magnitude = deuterG.Dot( normal );
// bounce
sumJ += normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(),
sumJ -= normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(),
protoState.GetMass(), protoG_Magnitude,
deuterState.GetMass(), deuterG_Magnitude );
// FRICTION

View File

@ -8,6 +8,39 @@ 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 );
@ -128,25 +161,25 @@ Float4 & SimpleRigidBody::GetNormalAt( const Float4 &worldPos, Float4 &targetMem
if( distance != 0.0f )
{ // sanity check
Ray ray( Float4::standard_unit_w, offset / (Float)::std::sqrt(distance) );
Ray axis( Float4::standard_unit_w, offset / (Float)::std::sqrt(distance) );
Float minDistance = numeric_limits<Float>::max();
if( ray.Intersects(Plane(this->rigid.box.xAxis, this->rigid.box.boundingOffset.x)) )
if( Private::Intersects(axis, Plane(this->rigid.box.xAxis, -this->rigid.box.boundingOffset.x), axis.collisionDistance) )
{ // check along x-axis
if( ray.collisionDistance < 0.0f )
if( axis.collisionDistance < 0.0f )
normal = -this->rigid.box.xAxis.xyz;
else
normal = this->rigid.box.xAxis.xyz;
minDistance = Abs( ray.collisionDistance );
minDistance = Abs( axis.collisionDistance );
}
if( ray.Intersects(Plane(this->rigid.box.yAxis, this->rigid.box.boundingOffset.y)) )
if( Private::Intersects(axis, Plane(this->rigid.box.yAxis, -this->rigid.box.boundingOffset.y), axis.collisionDistance) )
{ // check along y-axis
distance = Abs( ray.collisionDistance ); // recycling memory
distance = Abs( axis.collisionDistance ); // recycling memory
if( minDistance > distance )
{
if( ray.collisionDistance < 0.0f )
if( axis.collisionDistance < 0.0f )
normal = -this->rigid.box.yAxis.xyz;
else
normal = this->rigid.box.yAxis.xyz;
@ -155,11 +188,11 @@ Float4 & SimpleRigidBody::GetNormalAt( const Float4 &worldPos, Float4 &targetMem
}
}
if( ray.Intersects(Plane(this->rigid.box.zAxis, this->rigid.box.boundingOffset.z)) )
if( Private::Intersects(axis, Plane(this->rigid.box.zAxis, -this->rigid.box.boundingOffset.z), axis.collisionDistance) )
{ // check along z-axis
if( minDistance > Abs( ray.collisionDistance ) )
if( minDistance > Abs( axis.collisionDistance ) )
{
if( ray.collisionDistance < 0.0f )
if( axis.collisionDistance < 0.0f )
normal = -this->rigid.box.zAxis.xyz;
else
normal = this->rigid.box.zAxis.xyz;