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.