在光线平面相交之前选择边界框的相关平面

发布于 2024-11-18 08:07:32 字数 1207 浏览 3 评论 0原文

我正在跟踪需要测试它们是否位于立方体/边界框内部或外部的对象。如果它们在外面,我会进行射线平面相交来计算立方体平面之一上的点。射线从盒子的中心开始,指向对象。该平面是构成立方体的 6 个平面之一。

我想避免的是我一直在 6 个平面中的每一个上测试光线平面相交。所以我想我会很聪明,首先计算每个平面法线和光线之间的点积。然后选择角度最小(最接近 1)的那个。

这只能起到一半作用。在某些位置,当对象与其中一个平面对齐时,我的函数会选择错误的平面。大多数时候它都有效,我想知道为什么会这样。我认为我的方法一定有根本性的错误。

这是我定义的平面,每个平面都有一个标签。坐标系的 0,0,0 是立方体的一个角。

planes = {
    xnear = { normal = {1, 0, 0}, d = 0 },
    xfar = { normal = {-1, 0, 0}, d = cubeSize.x },
    ynear = { normal = {0, 1, 0}, d = 0 },
    yfar = { normal = {0, -1, 0}, d = cubeSize.y },
    znear = { normal = {0, 0, 1}, d = 0 },
    zfar = { normal = {0, 0, -1}, d = cubeSize.z }, 
}

然后我使用以下函数:

-- Determine what plane to use for collision testing. The angle is calculated
-- between the plane normal and the direction of the ray
function whatPlane(pos)
local direction = vec3.sub(cubeCenter, pos)
local result
local max = -1
for label, plane in pairs(planes) do
    local dotproduct = vec3.dot(plane.normal, direction)
    if dotproduct > max then
        max = dotproduct
        result = label
    end
end
return result
end

我在这里缺少什么?

我想我可以在每个平面上进行碰撞测试,然后选择最接近立方体中心的点,但这似乎是一种浪费。

I am tracking objects for which I need to test if they are located inside or outside a cube / bounding box. If they are outside, I do a ray-plane intersection to calculate a point on one of the planes of the cube. The ray starts at the center of the box, and points towards the object. The plane is one of the 6 which make up the cube.

What I would like to avoid is that I am testing the ray-plane intersection on every one of the 6 planes all the time. So I thought I'd be clever and calculate first the dot product between each of the plane normals and the ray. Then select the one which has the smallest angle (closest to 1).

This works only halfway. There are locations when the object is aligned with one of the planes, where my function selects the wrong plane. Most of the time it works though, and I wonder why that is. I figure there must be something fundamentally wrong with my approach.

Here are my defined planes, which each have a label. The 0,0,0 of the coordinate system is one corner of the cube.

planes = {
    xnear = { normal = {1, 0, 0}, d = 0 },
    xfar = { normal = {-1, 0, 0}, d = cubeSize.x },
    ynear = { normal = {0, 1, 0}, d = 0 },
    yfar = { normal = {0, -1, 0}, d = cubeSize.y },
    znear = { normal = {0, 0, 1}, d = 0 },
    zfar = { normal = {0, 0, -1}, d = cubeSize.z }, 
}

Then I use the following function:

-- Determine what plane to use for collision testing. The angle is calculated
-- between the plane normal and the direction of the ray
function whatPlane(pos)
local direction = vec3.sub(cubeCenter, pos)
local result
local max = -1
for label, plane in pairs(planes) do
    local dotproduct = vec3.dot(plane.normal, direction)
    if dotproduct > max then
        max = dotproduct
        result = label
    end
end
return result
end

What I'm I missing here?

I guess I could just do the collision test on every plane and then choose the point which is closest to the center of the cube, but that seems like a waste.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一念一轮回 2024-11-25 08:07:32

如果立方体确实是立方体,即所有尺寸都相同(并且仅适用于位于正多面体中心的情况),那么您的论点就没有问题。但看起来每个轴都有不同的尺寸。

如果一个长度相当小(想象一个非常薄的盒子),无论您朝哪个方向看,几乎在任何情况下您都会碰到那些大平面,而几乎不会碰到薄边。

如果您按盒子的确切长度缩放方向,则可以对此进行补偿。即,您使用 direction/(cubeSize.x,cubeSize.y,cubeSize.z) 而不是 direction ,其中通过坐标进行划分。

另一条评论:请注意,比较工作正常,即使在非标准化方向上也是如此,但如果您保持点积非标准化,则可能会在其他方面遇到问题。

Your argument would be fine if the cube was indeed a cube, i.e. all dimensions are the same (and only for the case of being in the center of a regular polyhedron). But as it looks like you have different dimension for each of the axes.

If one length is rather small (think of a very thin box) no matter what direction you look in almost any case you'll hit those big planes and almost never the thin sides.

You can compensate this if you scale your direction by the exact lengths of the box. I.e. instead of direction you use direction/(cubeSize.x,cubeSize.y,cubeSize.z) where the divison is done by coordinate.

Another remark: note that the comparison works fine, also with unnormalized direction but you may run into problems in other if you keep your dot-product unnormalized.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文