我正在实现一些与视锥体相关的代码,即使有很多可见对象,剔除测试也不会返回任何内容。我的数学支持库不提供平面支持或类似的东西,因此很多代码都是从头开始编写的,几乎没有可用的测试。如果您对故障点有任何建议,请告知。幸运的是,它并不多,所以Little'Wall'o'Code如下:
class Plane {
public:
Plane() {
r0 = Math::Vector(0,0,0);
normal = Math::Vector(0,1,0);
}
Plane(Math::Vector p1, Math::Vector p2, Math::Vector p3) {
r0 = p1;
normal = Math::Cross(p2 - p1, p3 - p1);
}
Math::Vector r0;
Math::Vector normal;
};
class Frustum {
public:
Frustum(
const std::array<Math::Vector, 8>& points
)
{
planes[0] = Plane(points[0], points[1], points[2]);
planes[1] = Plane(points[4], points[5], points[6]);
planes[2] = Plane(points[0], points[1], points[4]);
planes[3] = Plane(points[2], points[3], points[6]);
planes[4] = Plane(points[0], points[2], points[4]);
planes[5] = Plane(points[1], points[3], points[5]);
}
Plane planes[6];
};
// http://www.cescg.org/CESCG-2002/DSykoraJJelinek/index.html
bool Intersects(Math::AABB lhs, const Frustum& rhs) const {
for(int i = 0; i < 6; i++) {
Math::Vector pvertex = lhs.TopRightFurthest;
Math::Vector nvertex = lhs.BottomLeftClosest;
if (rhs.planes[i].normal.x <= -0.0f) {
std::swap(pvertex.x, nvertex.x);
}
if (rhs.planes[i].normal.y <= -0.0f) {
std::swap(pvertex.y, nvertex.y);
}
if (rhs.planes[i].normal.z <= -0.0f) {
std::swap(pvertex.z, nvertex.z);
}
if (Math::Dot(nvertex - rhs.planes[i].r0, rhs.planes[i].normal) > 0.0f) {
return false;
}
}
return true;
}
另外值得注意的是,我使用的是左手坐标系,所以我颠倒了交叉积的结果(在Cross函数内)。
编辑:正如准确说明的那样,我错过了顶点索引。它们被编入索引,以便每个位指示一个轴上的角 - 即0表示右侧,顶部和后部,按此顺序。
此外,我为问题的质量普遍低而道歉,但我不知道还有什么要补充。我没有编译器警告或错误,也没有足够的理解来理解我可能在调试器中读到的任何内容 - 这超出了我的正常范围。代码使用Vector
和AABB
的相对明显的实现进行编译。
答案 0 :(得分:3)
我怀疑这取决于您对顶点的标注以及指定点的顺序。您应该在指定顶点的方向上保持一致,顺时针或逆时针取决于您的坐标系。这应该是关于看外表面(或内表面,取决于你如何看待它)。
在我看来,看起来你的法线指向同一方向是错误的。
所以逆着法线逆时针指定那些表面给我
0 1 2
5 4 7
1 5 6
4 0 3
3 2 6
1 0 4
你的0 1 2和4 5 6的例子产生2个法线指向相同的方向,当它们指向相反的方向时