Collision detection doesn't work for automated elements in XNA 4.0

I have a really weird problem. I made a 3D simulator of an "assembly line" as a part of a college project. Among other things it needs to be able to detect when a box object passes in front of sensor. I tried to solve this by making a model of a laser and checking if the box collides with it. I had some problems with BoundingSpheres of models meshes so I simply create a BoundingSphere and place it in the same place as the model. I organized them into a list of BoundingSpheres called "spheres" and for each model I create one BoundingSphere. All models except the box are static, so the box object has its own BoundingSphere (not a member of the "spheres" list). I also implemented a picking algorithm that I use to start the movement. This is the code that checks for collision:

if (spheres.Count != 0)
{

for (int i = 1; i < spheres.Count; i++)
{
if (spheres[i].Intersects(PickingRay) != null && Microsoft.Xna.Framework.Input.ButtonState.Pressed == Mouse.GetState().LeftButton)
{
start = true;
break;
}
if (BoxSphere.Intersects(spheres[i]) && start)
{
MoveBox(0, false);//The MoveBox function receives the direction (0) and a bool value that dictates whether the box should move or not (false means stop)
start = false;
break;
}
if (start /*&& Microsoft.Xna.Framework.Input.ButtonState.Pressed == Mouse.GetState().LeftButton*/ && !BoxSphere.Intersects(spheres[i]))
{
MoveBox(0, true);
break;
}

}


The problem is this: When I use the mouse to move the box (the commented part in the third if condition) the collision works fine (I have another part of code that I removed to simplify my question - it calculates the "address" of the box, and by that number I know that the collision is correct). But when I comment it (like in this example) the box just passes trough the lasers and does not detect the collision (the idea is that the box stops at each laser and the user passes it forth by clicking on the appropriate "switch"). Can you see the problem? Please help, and if you need more informations I will try to give them. Thanks

• Your variable names are somewhat confusing. Can you rewrite your code for more descriptive names? Also, does the 'start' variable govern when the boxes are moving? – Seth Battin Sep 1 '12 at 4:15
• Sorry, the original variable names are in croatian so I translated them, but I think they are appropriate - which one confuses you? The start variable determines when the box will start moving, and it might be omitted when I solve this problem and the MoveBox function does the work (translates the boxes world matrix). I understand that the start variable and the bool value that MoveBox receives practically do the same thing, but these were my attempts to solve the problem – NDraskovic Sep 1 '12 at 11:37
• That might be part of the problem. If you have a mix of ways to determine when the box is moving, then do other things, then check if the box is moving another way, it becomes very difficult to track what is happening in your code. Likewise, you shouldn't have a MoveBox function that also determines if the box is moving, etc. – Seth Battin Sep 1 '12 at 17:29
• I introduced the MoveBox's bool value later, originally there was only the start variable, but I was having the same problem – NDraskovic Sep 1 '12 at 18:45
• Just a tip - Rather than entering Microsoft.Xna.Framework.*.ButtonState, just use ButtonState, right-click on it, select "Resolve", and pick the one that says "add Using." Or, hit F12. – 3Dave Sep 6 '12 at 22:58

It seems like you may not be hitting your MoveBox method if you hold down your Left Mouse Button since the statement keeps breaking. An alternative would be to check to see if the mouse is pressed after we check to see if there is a collision.

if(spheres.Any())
{
var mousePressed = ButtonState.Pressed == Mouse.GetState().LeftButton;
for (int i = 1; i < spheres.Count; i++)
{
if(!start)
var sphereIntersects = spheres[i].Intersects(PickingRay) != null;
if (sphereIntersects && mousePressed)
{
start = true;
break;
}
}
else
{
if(!mousePressed)
{
start = false;
break;
}
var intersects = BoxSphere.Intersects(spheres[i]);
if (intersects)
{
MoveBox(0, false);
start = false;
break;
}
else
{
MoveBox(0, true);
break;
}
}
}
}

• Unfortunately this does not work either, I still get the same problem. – NDraskovic Sep 3 '12 at 7:21
• @NDraskovic Honestly there isn't enough information to go by (or I may just be a noob). – Dustin Kingen Sep 3 '12 at 17:47
• Or both :D I managed to solve it by myself, thanks anyway – NDraskovic Sep 4 '12 at 6:45
• @NDraskovic then at least post the solution or delete the question :) – Dustin Kingen Sep 4 '12 at 18:02

If the spheres[i].Intersects(PickingRay) != null check succeeds, and your pressing the mouse button, you set start = true and then promptly exit the for loop.

The next time the for loop is called start will presumably still be true, but the only way it can get to BoxSphere.Intersects(spheres[i]) is if the ray intersection fails (or you let go of the mousebutton first).

This means that the only box that it can try to pick, is one that does not intersect with the ray (since if it does it will break the for loop).

It also just occured to me that your going through the list starting at i=1 lists in C# start at index 0, if your list (as mentioned in comment) only hold one item it would simply skip over that single box.

• There is only one box on the screen at this point. What I'm trying to achieve is to detect if the box is colliding with the laser, but also which laser is it colliding with (it is important because it determines the following action). The problem is that the number and position of lasers is not predetermined, I load the configuration from a file (that is why I use the spheres list, I can simply add any number of items). I use the picking algorithm to control the simulation by clicking on triggers, the box does not have an action bound to it if clicked on. Do you have any suggestions? – NDraskovic Sep 1 '12 at 18:44
• Its not clear from your code exactly how it would execute. As mentioned, as soon as the picking ray is found to match your single box, it will break out of the loop, never getting to the if statement that would move the box. Also, lists start at index 0, uncommenting the third if statement shouldn't work unless you made other changes as well to the code – Daniel Carlsson Sep 2 '12 at 9:34
• Honestly I have no idea what is wrong with this code. Like I said, my goal is to get the box to detect that it collided with any other object on the scene (I know that lists start with 0 index, but the 0 index is boxes BoundingSphere and it would be wrong to test if box collides with itself). Could you please suggest a solution (in code or pseudo-code) how I could solve this problem. Please keep in mind that number and location of objects is not predetermined (only thing certain is that there is only one box and it's boundingSphere is on index 0) – NDraskovic Sep 2 '12 at 13:20

This is the code that works properly:

        if (ButtonState.Pressed == Mouse.GetState().LeftButton)
{
start = true;
}
if (start)
{
MoveBox(0,true);
}
for (int i = 1; i < spheres.Count; i++)
{
if (BoxSphere.Contains(spheres[i])== ContainmentType.Contains)
{
start = false;
}
}