Telling which side of a voxel was hit by an object

In XNA, I have an axis-aligned BoundingBox representing the object's hit box, and a Vector3 representing the object's velocity. I also have a stationary 1x1x1 axis-aligned BoundingBox representing a voxel. Using object.box.intersects(voxel.box), I can tell that they intersect. However, I do not know which side of the voxel was first hit by the object.

I am assuming you can just take the direction from the center of the player to the center of the voxel and use that to determine which face it hit. However, my brain is not working right now and I can't figure out the math.

I already know how to respond when you learn which face was hit (from my previous question). I just don't know how to figure out which face the player hit.

• Is the player hit box axis aligned?
– House
Jan 26 '12 at 17:32
• Vector math should be very expensive, but is very accurate too. Consider. Jan 26 '12 at 17:39

You can always check each face that can collide. Since the bounding boxes are AA, you'll have these collision scenarios: (-> indicates collision, X_Plus represents the YZ plane on the X plus side of the box)

• Box1_X_Plus -> Box2_X_Minus
• Box1_Y_Plus -> Box2_Y_Minus
• Box1_Z_Plus -> Box2_Z_Minus
• Box1_X_Minus -> Box2_X_Plus
• Box1_Y_Minus -> Box2_Y_Plus
• Box1_Z_Minus -> Box2_Z_Plus

You can narrow the choices to half by checking if one box is further along an axis than the other. For example, if Box1 is at x=1 and Box2 is at x=5, there's no way that the Xminus side of Box1 could be colliding with the XPlus side of Box2, so you can remove it from the options.

I'm not sure exactly what would work, but you could do it something like:

public Face GetCollisionFaceOfPlayer(Vector3f voxelPos, Player player) {
if(player.x < voxelPos.x) {
//See if player Xminus is close enough to voxel XPlus
if(Abs((player.Position.x - player.Width/2) - (voxelPos.x +.5f)) < PreDeterminedCollisionBufferDistance)
return Face.XMinus;
}
else {
//See if player XPlus is close enough to voxel XMinus
if(Abs((player.Position.x + player.Width/2) - (voxelPos.x -.5f)) < PreDeterminedCollisionBufferDistance)
return Face.XPlus;
}
//Other faces

}

Or you can keep track of the distances for all the faces it could be and return the minimum.

If the box is axis aligned you can simply take the highest absolute value of the three coordinates of the box centre to player vector. The collision is along that axis, and the coordinate is either positive or negative depending on which side of the box the player collided with.

If the player figure is an axis aligned box it's pretty simply to take it's size into consideration, say for instance it's 2 units high and 1 by 1 units wide, then you simply subtract half of the player boxes respective dimension from the absolute centre to centre distance before comparing. So you'd be looking for max(abs(distanceX)-.5, abs(distancey)-1, abs(distanceZ)-.5) (Of course set up as a series of if clauses so that you not only get to know the maximum value, but also which one of them constitute this.)

• However, the player's box is not a cube, so the max-distance isn't necessarily the collision direction. This is what I put in originally, and it does not work.
– user10835
Jan 26 '12 at 18:23
• Would you please be so kind as to not tell me what something is not. What collision figure do you use for the player? Jan 26 '12 at 23:45
• My guess is that it's a cuboid, or a 3d rectangle (not square). Since the OP still calls it a box. But agreed, requiring us to guess isn't too helpful.
– House
Jan 27 '12 at 21:05