Collision Detection Problems

Hey All,



I’ve been looking through all the work that’s been done for exact collision detection and I’m excited about the possibilities for my current project.



I’ve based my code off of the TestOBBTree code and I’ve gotten positive results, but I did notice some anomalies last night before I called it quits.



It seems that the orientation of the triangles is having some effect on the Triangle-Triangle collision detection. Even on a simple box where each face is made up of two triangles, only one of the triangles will properly detect the collision. My projectile will pass straight through the other triangle.



At first I thought that it might be a symptom of the bullet being too small and too fast so that it was actually “skipping” the surface between updates and that it might not be catching the collision detection. I tried to test that theory by making the bullet bigger and also by making the angle of incidence to the surface smaller. Neither of these worked (although there were some other missed detections that it did fix).



Here are some screenshots:







And wireframe:







You can see how the bottom triangle of the visible face is detecting collisions, but the upper one is not. The bullets are being captured by the opposite face of the box (visible in the wireframe shot).



Does anyone have any ideas to what might be causing this? Thanks.

Hmmm thanks for noticing this. First of all, how did you call the collision methods? That is, I’m currently revamping the high level collisions (the collision detection system that decides when the OBBTree needs to be called). So are you doing:



Node wall, bullet;



bullet.hasCollision(wall, results);



or



TriMesh wall, bullet;



bullet.findIntersection(wall,a,b);



Might help narrow the search for the problem.

I can’t debug your system until mojo commits what he has saved up. I’ve emailed him some bug fixes that were in the current CVS version. Those may fix the problem. If they don’t, I’ll look into it more later. There’s really no such thing as back facing triangles in triangle-triangle collision detection so that shouldn’t matter here. After the commit of the new system, see if that helps.

Cep, the OBBTree code and OBB2 code is unmodified by me and the new collision detection, so if you want to commit those two classes that’s fine by me (they are still yours), The stuff I’m working on just calls them.

Thanks for the quick response guys. Mojo, I’m using the first method listed



bullet.hasCollision(wall, results);



Here is my code exactly:




/** Check all of the objects from our original MousePick for this bullet */
         for (int i = 0; i < pickResults.getNumber(); i++) {
            
            /** Clear the collision results */
            results.clear();
            
            /** Collision check */
            bullet.hasCollision(pickResults.getGeometry(i), results);            
            
            if (results.getNumber() > 0) {      
               
               /** If we're inside the BB, we need to check on triangle-triangle collision */
               if(bullet.hasTriangleCollision(results.getCollisionData(0).getMesh())) {   
                  
                  //System.out.println("Triangle Collision: " + results.getCollisionData(0).getMesh());
                  
                  Sphere hitSphere = new Sphere("hitSphere", 4, 4, .5f);
                  hitSphere.setLocalTranslation(bullet.getWorldTranslation());
                  hitSphere.setModelBound(new BoundingSphere());
                  hitSphere.updateModelBound();
                  sceneNode.attachChild(hitSphere);

                  /** destroy this bullet and remove it's controller */
                  sceneNode.detachChild(bullet);
                  bullet.removeController(this);
               } // end if
            } // end if
         } // end for



Basically, I perform a mousepick at the time of bullet creation. The controller carries those pick results with it the whole time and only checks those objects that the bullet might hit. I hoped that this would allow for greater effeciency, but maybe it is unnecessary.

Anyway, you guys rock. When I'm done with this project, I hope that I'll be able to add much of what I've learned to the Wiki (I'm taking notes as I go).

While this is not going to explain why half the wall isn’t working, we can discuss how you are handling collisions.



when you call hasCollisions the following happens:


//first see if these two bounds intersect if they do look further, if not
//throw away this node (this allows you to quickly parse an entire scene
//graph).
if (bound1 intersects bound2) {
    if (target is a Node) {
        //check each child, they still might be nodes, they might be
        //trimeshes
        for each child of the node call this method      
    } else {
       //we have a leaf
       //if it's a trimesh and we have high detail collisions turned on
       //check the OBBTree
       target.obbtree intersection test         
    }
}


That is when it's a leaf, it calls the OBBTree stuff straight and keeps track of the triangles hit. Now, this means that you don't have to call hasTriangleCollision (you can examine the results of the collision to determine what triangles are hit). I understand you just want the simple boolean, and that is going in soon in hasCollision.

For the time being, you can examine the CollisionResults for the triangles hit, and can determine where (if) the bullet hit the wall. This might provide a better way of debugging, as you can provide us with data (both triangles of the wall are in the results but hasTriangleCollision returned false, or whatever it might be).

There is a method in Intersection that brute force checks for triangle/triangle intersections between two TriMesh. If that returned true and the OBBTree test returned false, we’ld know it’s in the OBB. But if they both return false, then we’ld know it’s in the Triangle/Triangle code

Mojo, if I understand you correctly, my calling of ‘hasTriangleCollision’ is redundant because that is already being done in ‘hasCollision’? I will definately go back and take a look at this, but in the mean time, I did update my code to give a little debugging information. I am making use of the brute force call you mentioned, Cep.



Here is my code now:



/** Check all of the objects from our original MousePick for this bullet */
         for (int i = 0; i < pickResults.getNumber(); i++) {
            
            /** Clear the collision results */
            results.clear();
            
            /** Collision check */
            bullet.hasCollision(pickResults.getGeometry(i), results);            
            
            if (results.getNumber() > 0) {
               System.out.println("Possible Collisionnwith Mesh: " + results.getCollisionData(0).getMesh());
            
               boolean detectedByIntersectionCode = false;
               boolean detectedByOBBCode = false;
               
               if(Intersection.meshIntersection(bullet, results.getCollisionData(0).getMesh())) {
                  System.out.println("Intersection detected by 'Intersection' code.");
                  detectedByIntersectionCode = true;
               }
               
               /** If we're inside the BB, we need to check on triangle-triangle collision */
               if(bullet.hasTriangleCollision(results.getCollisionData(0).getMesh())) {
                  System.out.println("OBB Detected proper triangle collision.");
                  detectedByOBBCode = true;
                  
                  Sphere hitSphere = new Sphere("hitSphere", 4, 4, .5f);
                  hitSphere.setLocalTranslation(bullet.getWorldTranslation());
                  hitSphere.setModelBound(new BoundingSphere());
                  hitSphere.updateModelBound();
                  sceneNode.attachChild(hitSphere);

                  /** destroy this bullet and remove it's controller */
                  sceneNode.detachChild(bullet);
                  bullet.removeController(this);
               } // end if
               
               if(detectedByIntersectionCode && !detectedByOBBCode) {
                  System.out.println("WARNING! Intersection detected that OBBTree code did not detect.");
               }
            } // end if
         } // end for



Same scenario as the original post. Here is an excerpt of what I'm getting on my output:


Possible Collision
with Mesh: Box01 (com.jme.scene.TriMesh)
Possible Collision
with Mesh: Box01 (com.jme.scene.TriMesh)
Possible Collision
with Mesh: Box03 (com.jme.scene.TriMesh)
Intersection detected by 'Intersection' code.
WARNING! Intersection detected that OBBTree code did not detect.



And if the detection does occur (as it does on one of the triangles):


Possible Collision
with Mesh: Box04 (com.jme.scene.TriMesh)
Intersection detected by 'Intersection' code.
OBB Detected proper triangle collision.