Collision detection in 1st person shooter

I have tried to to create the collision detection for the 1st person shooter after reading the various postings. I created two nodes, one is a box which follows the camera all the time and the other is the box I am colliding with.



Box which is following camera:



       Vector3f loc = new Vector3f(0,6,0);
       Box camBox= new Box("CameraBox", loc, 0.1f, 0.1f, 0.1f);             
       camBox.setModelBound(new OrientedBoundingBox());
       camBox.updateModelBound();       
       camBox.setTextureCombineMode(TextureState.OFF);

       camBox.addController(new FollowCam(camBox));
       camBoxNode = new Node("Camera box");
       camBoxNode.attachChild(camBox);
       sceneNode.attachChild(camBoxNode);   



and the other box


       box3.setModelBound(new OrientedBoundingBox());
       box3.updateModelBound();
       box3.setRenderState(boxTex);
       box3.setTextureCombineMode(TextureState.REPLACE);

       box3Node = new Node("box three");
       box3Node.attachChild(box3);
       sceneNode.attachChild(box3Node);



I use this code (which was posted in the WiKi to follow the camera:


public class FollowCam extends Controller
{

    public Spatial[] toChange;

    public FollowCam()
    {
        toChange = new Spatial[0];
    }

    public FollowCam(Spatial node)
    {
        toChange = new Spatial[1];
        toChange[0] = node;
    }

    public void addSpatial(Spatial node)
    {
        // only add if a new node
        int i;
        for (i=0; i<toChange.length; ++i)
            if (toChange[i]==node)
                return;
        // increase toChange size
        // I do this because I assume this method is called only a few times
        // during init, so optimise for update() (below)
        Spatial[] temp = new Spatial[toChange.length+1];
        for (i=0; i<toChange.length; ++i)
            temp[i] = toChange[i];
        toChange = temp;
        toChange[i] = node;
    }


    /* (non-Javadoc)
     * @see com.jme.scene.Controller#update(float)
     */
    public void update(float time)
    {
        Camera cam = DisplaySystem.getDisplaySystem().getRenderer().getCamera();
        Vector3f v = new Vector3f(cam.getLocation());
        for (int i=0; i<toChange.length; ++i)
        {
            toChange[i].setLocalTranslation(v);
        }
    }
}



In the initGame() method I add collision detection


        results = new BoundingCollisionResults()
        {
            public void processCollisions()
            {
                if (getNumber() > 0)
                {
                    dbg("Collision: YES");
                } else
                {
                    dbg("Collision: NO");
                }
            }
   };
        results.addCollision(camBox, box3);



and in the update(float i) method I add this to detect collisions


results.clear();
camBoxNode.calculateCollisions(sceneNode, results);



but the only response I get is "Collision: No". I think I have covered just about everything to get the collision working, but I am doing something wrong and I am not detecting collision. Any ideas what's going wrong?

tomcat

Is there any other way to do collision detection with camera? I am now stuck :frowning: .

tomcat

You could use the physics system and place a Box - which you turn into a PhysicsObject - at the cameras position (and synchronizing it every frame).



Then you set a ContactHandler to that PhysicsObject and simply override its (the ContactHandler, that is) onContact method to move the camera to its previous location…



However, if you’r not using the physics system for anything else, this wouldn’t be the ideal solution :frowning:

why would it not be per? :slight_smile:



What I would do, is init a cameraNode, and attach an invisble sphere at local translation (0, 0, 0). Add a boundingSphere/orientatedBoundingBox and check for collisions with the cameraNode.



I haven’t looked at your code there tomcat, but this is what i would do to check collisions AFTER ive setup the setup from above:



boolean collisionBetweenXAndCamera = nodeX.findCollision(cameraNode);

if (collisionBetweenXAndCamera) {
  sysout("True");
}



Notice above is just pseudo-code. :)

DP
why would it not be per? Smile

Because of the redundancy of a physics system never really being used.

Whoops forgot to login. ^^;

Thanks for this. I’ll try it tonight and hope I can get mine to work.

"Anonymous" wrote:

results.addCollision(camBox, box3);


What does this do? I never used it in my code. I'm pretty sure you don't need it. I think this function is called by findCollisions() to populate the collisions results list and you don't have to invoke it directly.

OK I used this code to say that I am looking for collision between those two objects so I knew which ones are colliding. My reason was that I wasnt sure how to find out which objects collide if I didnt use this. Is there anyway to do this if you had say 10 objects which were collision enabled?

tomcat

Depending on how you’ve got things set up, I’d say you can use instanceof or Spatial.getName().

"Per" wrote:
Depending on how you've got things set up, I'd say you can use instanceof or Spatial.getName().

Is this

 results.addCollision(camBox, box3);



correct in order to set objects for collision or do you use something else?
tomcat

You don’t need to do that to get a collision. I never called addCollision() and it still found any collisions between the ship and objects in the scenegraph.

Here’s an extended code snippet



   //Clear the collision results
   results.clear();
   //Check to see if our ship has collided
   rootNode.updateGeometricState(tpf, true);
   ship.findCollisions(rootNode, results);
   
   if (results.getNumber() > 0) {
      int[] indexBuffer = new int[3];
      collisionData = results.getCollisionData(0);
      if(results.getCollisionData(0).getSourceTris().size() > 0){
         ship.velocity.x = ship.velocity.x * -1;
         ship.velocity.z = ship.velocity.z * -1;
         ship.setLocalTranslation(ship.previousPos);
         ship.setLocalRotation(ship.getPrevRot());
      }
      else{
         if(results.getCollisionData(0).getTargetTris().size() > 0){
            ship.velocity.x = ship.velocity.x * -1;
            ship.velocity.z = ship.velocity.z * -1;
            ship.setLocalTranslation(ship.previousPos);
            ship.setLocalRotation(ship.getPrevRot());
         }
      }
//Outputs the triangles on the source that collided
      for (int i = 0; i < results.getCollisionData(0).getSourceTris().size(); i++) {
         int triIndex = ((Integer) results.getCollisionData(0).getSourceTris().get(i)).intValue();
         ship.getTriangle(triIndex, indexBuffer);
         System.out.println("Collision: Triag:" + indexBuffer[0]);
      }
//Outputs the name of the target spatial that was hit
      String Name = results.getCollisionData(0).getTargetMesh().getName();
      System.out.println("Collided with: " + Name);
   }



You use the following


         String Name = results.getCollisionData(0).getTargetMesh().getName();



To get the name of the spatial you collided with. You can also just have it return a pointer to the spatial if you do.


         Spatial targetSpatial = results.getCollisionData(0).getTargetMesh();



That way you can make changes to the spatial you collided with

Note the above code assumes your object is colliding with only one object at a time. If you want to check for multiple collisions you just have to loop through all the indices in results. (i.e. results.getCollisionData(1), results.getCollisionData(2) etc.)

(My code is pretty sloppy since I'm still in the experimenting phase of using collision detection but hopefully it'll help you get it working)

Thx for this. I modify mine and see what results I get.

tomcat

Let me know ifyou notice any of the bugs I seem to have and posted about here http://www.jmonkeyengine.com/jmeforum/viewtopic.php?t=1324

Thx shocho. After a few more configurations, its now working. I am doing collision detection with geometry (well Boxes) at the moment and havent come across the problem you mentioned. When I start triangle collision detection I keep an eye for the problem.

tomcat

Awesome … you should take a look at the physics library DP and Per did. It’s pretty nice if you need to incorporate physics based collision response.

Great. Thats next in my list once I have got a few other things sorted in this program.

tomcat