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 ); deuterG_Magnitude = deuterG.Dot( normal );
// bounce // bounce
sumJ += normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(), sumJ -= normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(),
protoState.GetMass(), protoG_Magnitude, protoState.GetMass(), protoG_Magnitude,
deuterState.GetMass(), deuterG_Magnitude ); deuterState.GetMass(), deuterG_Magnitude );
// FRICTION // FRICTION

View File

@ -8,6 +8,39 @@ using namespace ::Oyster::Collision3D;
using namespace ::Utility::DynamicMemory; using namespace ::Utility::DynamicMemory;
using namespace ::Utility::Value; 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() SimpleRigidBody::SimpleRigidBody()
{ {
this->rigid = RigidBody( Box(Float4x4::identity, Float3::null, Float3(1.0f)), 16.0f, Float4x4::identity ); 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 ) if( distance != 0.0f )
{ // sanity check { // 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(); 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 { // check along x-axis
if( ray.collisionDistance < 0.0f ) if( axis.collisionDistance < 0.0f )
normal = -this->rigid.box.xAxis.xyz; normal = -this->rigid.box.xAxis.xyz;
else else
normal = this->rigid.box.xAxis.xyz; 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 { // check along y-axis
distance = Abs( ray.collisionDistance ); // recycling memory distance = Abs( axis.collisionDistance ); // recycling memory
if( minDistance > distance ) if( minDistance > distance )
{ {
if( ray.collisionDistance < 0.0f ) if( axis.collisionDistance < 0.0f )
normal = -this->rigid.box.yAxis.xyz; normal = -this->rigid.box.yAxis.xyz;
else else
normal = this->rigid.box.yAxis.xyz; 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 { // 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; normal = -this->rigid.box.zAxis.xyz;
else else
normal = this->rigid.box.zAxis.xyz; normal = this->rigid.box.zAxis.xyz;