为什么此代码会以某些角度返回框错误一侧的交点?
在某些角度,这将显示错误一侧的交叉点(应该在前面时向后,或者在应该正确时向左)。
怎么了?
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;
}
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 &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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这与浮点精度问题有关。如果你想要一个稳定的算法,你不能使用 == 来比较浮点,例如以下是被禁止的:
你需要做的就是用下面的 feq( ) 替换所有这些 == 比较:
有了这个函数(你如果不喜欢函数开销,也可以将其创建为 #define)您可以将 cEpsilon (也可以更改此精度,具体取决于您和您的问题定义为接近的内容)功能到其他运算符。下面是 << 的示例运算符:
检查您的代码并替换 == 和 <用这些方法。你真的不需要 >运算符,因为您也可以翻转参数并使用 <反而。
干杯
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:
What you need to do is to replace all these == comparisions with feq( ) below:
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:
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