Why does this code return an intersection point on the wrong side of the box at some angles?
At some angles this will show an intersection on the wrong side (back when it should be front OR left when it should be right).
What is wrong?
inline bool GetIntersection(f32 fDst1, f32 fDst2,
vector3df P1, vector3df P2, vector3df 开发者_JS百科&Hit) {
if ( (fDst1 * fDst2) >= 0.0f)
return 0;
if ( fDst1 == fDst2)
return 0;
Hit = P1 + (P2-P1) * ( -fDst1/(fDst2-fDst1) );
return 1;
}
inline bool InBox(vector3df Hit, vector3df B1, vector3df B2, const int AXis) {
if ( AXis==1 && Hit.Z > B1.Z &&
Hit.Z < B2.Z && Hit.Y > B1.Y && Hit.Y < B2.Y)
return 1;
if ( AXis==2 && Hit.Z > B1.Z &&
Hit.Z < B2.Z && Hit.X > B1.X && Hit.X < B2.X)
return 1;
if ( AXis==3 && Hit.X > B1.X && Hit.X < B2.X &&
Hit.Y > B1.Y && Hit.Y < B2.Y)
return 1;
return 0;
}
// returns true if line (L1, L2) intersects with the boX (B1, B2)
// returns intersection point in Hit
bool CheckLineBox( vector3df B1, vector3df B2,
vector3df L1, vector3df L2, vector3df &Hit) {
if (L2.X < B1.X && L1.X < B1.X) return false;
if (L2.X > B2.X && L1.X > B2.X) return false;
if (L2.Y < B1.Y && L1.Y < B1.Y) return false;
if (L2.Y > B2.Y && L1.Y > B2.Y) return false;
if (L2.Z < B1.Z && L1.Z < B1.Z) return false;
if (L2.Z > B2.Z && L1.Z > B2.Z) return false;
if (L1.X > B1.X && L1.X < B2.X &&
L1.Y > B1.Y && L1.Y < B2.Y &&
L1.Z > B1.Z && L1.Z < B2.Z) {
Hit = L1;
return true;
}
if ((GetIntersection( L1.X-B1.X, L2.X-B1.X, L1, L2, Hit) &&
InBox(Hit, B1, B2, 1)) ||
(GetIntersection( L1.Y-B1.Y, L2.Y-B1.Y, L1, L2, Hit) &&
InBox(Hit, B1, B2, 2)) ||
(GetIntersection( L1.Z-B1.Z, L2.Z-B1.Z, L1, L2, Hit) &&
InBox(Hit, B1, B2, 3)) ||
(GetIntersection( L1.X-B2.X, L2.X-B2.X, L1, L2, Hit) &&
InBox(Hit, B1, B2, 1)) ||
(GetIntersection( L1.Y-B2.Y, L2.Y-B2.Y, L1, L2, Hit) &&
InBox(Hit, B1, B2, 2)) ||
(GetIntersection( L1.Z-B2.Z, L2.Z-B2.Z, L1, L2, Hit) &&
InBox(Hit, B1, B2, 3)))
return true;
return false;
}
This is related to problems with floating point precision. You can't compare floating points by using == if you want a stabile algorithm, e.g. the following is forbidden:
if ( fDst1 == fDst2)
return 0;
What you need to do is to replace all these == comparisions with feq( ) below:
static const double cEpsilon = 1e-5;
bool feq(double lhs, double rhs)
{
return (fabs(lhs - rhs) < cEpsilon);
}
With this function in place (you can create it as a #define too if don't like the function overhead) you can add the cEpsilon (this accuracy can also be changed, depending on what you and your problem define as close) functionality to the other operators. Below is an example of the < operator:
bool lessThan(double lhs, double rhs)
{
return (lhs < rhs && !feq(lhs, rhs));
}
Go through your code and replace == and < with these methods. You dont really need the > operator since you might as well turn around the arguments and use < instead.
Cheers
精彩评论