为什么这段代码在某个角度返回盒子错误一侧的交叉点?

时间:2011-02-24 16:30:43

标签: c++ 3d intersection

在某些角度,这将显示错误一侧的交叉点(当它应该是正面时返回,或者当它应该是正确时返回)。

有什么问题?

inline bool GetIntersection(f32 fDst1, f32 fDst2, 
        vector3df P1,  vector3df P2,  vector3df &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;
}

1 个答案:

答案 0 :(得分:2)

这与浮点精度问题有关。如果你想要一个稳定的算法,你不能使用==来比较浮点数。以下是禁止的:

if ( fDst1 == fDst2) 
        return 0; 

你需要做的是用下面的feq()替换所有这些==比较:

static const double cEpsilon = 1e-5;

bool feq(double lhs, double rhs)
{
  return (fabs(lhs - rhs) < cEpsilon);
}

使用此功能(如果不喜欢功能开销,也可以将其创建为#define),可以添加cEpsilon(此精度也可以更改,具体取决于您和您的问题定义为关闭)其他运营商的功能。以下是&lt;操作者:

bool lessThan(double lhs, double rhs)
{
  return (lhs < rhs && !feq(lhs, rhs));
}

浏览您的代码并替换==和&lt;用这些方法。你真的不需要&gt;运算符,因为您可以转换参数并使用&lt;代替。

干杯