Collision and last position



hi there,
i'm having trouble figuring how to have a valid last position.
so far collision work, but then when i set last position the object stays trapped into the wall.
it seems like i store the last position after colliding , instead of last position before colliding.
thus, everytime i hit a wall, i get stuck in it..

someone could tell me what i'm doing wrong ?
any advices?

thanks !


here's the code:


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.CollisionTree;
import com.jme.bounding.CollisionTreeManager;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.intersection.CollisionData;
import com.jme.intersection.CollisionResults;
import com.jme.intersection.TriangleCollisionResults;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Box;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.ObjToJme;


public class HelloModelLoading extends SimpleGame {

    private Node boxNode, mapNode;
    private Spatial b, m;
    private CollisionResults results;
    private CollisionData oldData;
    private Vector3f lastPosition;
    private float boxSpeed = 100.0f; 

    public static void main(String[] args) {
        HelloModelLoading app = new HelloModelLoading();
        app.setConfigShowMode(ConfigShowMode.AlwaysShow);
        Logger.getLogger("").setLevel(Level.SEVERE);
        app.start();
    }


    protected void simpleInitGame() {  

        input = new InputHandler();
        CollisionTreeManager.getInstance().setTreeType(CollisionTree.Type.AABB);
        results = new TriangleCollisionResults();      

        URL model=HelloModelLoading.class.getClassLoader().getResource("data/test_01_02.obj");
        FormatConverter converter=new ObjToJme();
        converter.setProperty("mtllib",model);

        ByteArrayOutputStream BO=new ByteArrayOutputStream();
        try {

            mapNode = new Node("map node");
            converter.convert(model.openStream(), BO);
            m=(Spatial) BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
            m.setLocalScale(.1f);
            m.setModelBound(new BoundingBox());
            m.updateModelBound();


            boxNode = new Node("box node");
            b = new Box("box", new Vector3f(-20,5,0), 1, 1 ,1);
            b.setLocalScale(.4f);
            b.setModelBound(new BoundingBox());
            b.updateModelBound();

            rootNode.attachChild(b);
            rootNode.attachChild(m);

        } catch (Exception e) {   // Just in case anything happens
            System.out.println("Damn exceptions! O_o n" + e);
            e.printStackTrace();
            System.exit(0);
        }
        // change the direction camera is looking at
        cam.setAxes(new Vector3f(0,0,-1), new Vector3f(0,1,0), new Vector3f(1,0,0));

        KeyBindingManager.getKeyBindingManager().set("moveFwd", KeyInput.KEY_W);
        KeyBindingManager.getKeyBindingManager().set("moveBwd", KeyInput.KEY_S);
        KeyBindingManager.getKeyBindingManager().set("moveLeft", KeyInput.KEY_A);
        KeyBindingManager.getKeyBindingManager().set("moveRight", KeyInput.KEY_D);
    }

    protected void simpleUpdate() {
       
        //put the cam at the box position
        cam.setLocation(new Vector3f(
                b.getLocalTranslation().getX(),
                b.getLocalTranslation().getY()+1,
                b.getLocalTranslation().getZ()));

        results.clear();           
        b.findCollisions(rootNode, results);

        if (results.getNumber() > 0){ // if we are inside the dungeon, result = 1
            oldData = results.getCollisionData(0);

            if (oldData.getTargetTris().size()>0)
            {
                // if collision with dungeon wall happen set lastPosition for box & cam
                b.getLocalTranslation().set(lastPosition);
            }

            // no collision with dungeon walls, we can move..
            else if (oldData.getTargetTris().size()==0)
            {
                if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveFwd", false))
                {           
                    b.getLocalTranslation().y += boxSpeed* timer.getTimePerFrame();
                }
                if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveBwd", false))
                {           
                    b.getLocalTranslation().y -= boxSpeed* timer.getTimePerFrame();
                }
                if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveLeft", false))
                {           
                    b.getLocalTranslation().z -= boxSpeed* timer.getTimePerFrame();
                }
                if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveRight", false))
                {           
                    b.getLocalTranslation().z += boxSpeed* timer.getTimePerFrame();
                }
                // save last position
                lastPosition = b.getLocalTranslation();
            }
        }   
    }
}



and screenshot:




*bump*

.. am i asking the wrong question?
or maybe my sample program is such a mess noone knows where to start giving advices ?


any help would be cool..
tnx

keisangi said:


                // save last position
                lastPosition = b.getLocalTranslation();



You are setting lastPosition by reference, not by value. Hence lastPosition updates every time b's localTranslation updates, because it is the same object in memory!
If you didn't understand any part of this, definitely read up on "by reference vs. by value" to understand these essential concepts.
Then, change the above to:


                // save last position
                lastPosition.set(b.getLocalTranslation());


(Of course you'll have to initialize lastPosition with a new Vector3f for this to work!)

keisangi said:

*bump*

Dude, you gave us only six hours to answer your question! Please remember that everybody here is doing this on their spare time.

@hevee



thanks a lot for the explanation!

my apologies i didn't mean it to be unpolite.

i was curious why it didn't worked, and wasn't sure my 1st post was correct and intelligible english.

i'll try to be more patient



i have modified the code as shown below,

but i get the exact same result, if i touch a wall i get stuck… have i missed something ?

i did  lastPosition = new Vector3f(); in the last line of simpleInitGame()

and modified storing last position like this

                //lastPosition = b.getLocalTranslation();

                lastPosition.set(b.getLocalTranslation());





import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.CollisionTree;
import com.jme.bounding.CollisionTreeManager;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.intersection.CollisionData;
import com.jme.intersection.CollisionResults;
import com.jme.intersection.TriangleCollisionResults;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Box;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.ObjToJme;


public class HelloModelLoading extends SimpleGame {

    private Node boxNode, mapNode;
    private Spatial b, m;
    private CollisionResults results;
    private CollisionData oldData;
    private Vector3f lastPosition;
    private float boxSpeed = 100.0f; 

    public static void main(String[] args) {
        HelloModelLoading app = new HelloModelLoading();
        app.setConfigShowMode(ConfigShowMode.AlwaysShow);
        Logger.getLogger("").setLevel(Level.SEVERE);
        app.start();
    }


    protected void simpleInitGame() {   

        input = new InputHandler();
        CollisionTreeManager.getInstance().setTreeType(CollisionTree.Type.AABB);
        results = new TriangleCollisionResults();       

        URL model=HelloModelLoading.class.getClassLoader().getResource("data/test_01_02.obj");
        FormatConverter converter=new ObjToJme();
        converter.setProperty("mtllib",model);

        ByteArrayOutputStream BO=new ByteArrayOutputStream();
        try {

            mapNode = new Node("map node");
            converter.convert(model.openStream(), BO);
            m=(Spatial) BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
            m.setLocalScale(.1f);
            m.setModelBound(new BoundingBox());
            m.updateModelBound();


            boxNode = new Node("box node");
            b = new Box("box", new Vector3f(-20,5,0), 1, 1 ,1);
            b.setLocalScale(.4f);
            b.setModelBound(new BoundingBox());
            b.updateModelBound();

            rootNode.attachChild(b);
            rootNode.attachChild(m);

        } catch (Exception e) {   // Just in case anything happens
            System.out.println("Damn exceptions! O_o n" + e);
            e.printStackTrace();
            System.exit(0);
        }
        // change the direction camera is looking at
        cam.setAxes(new Vector3f(0,0,-1), new Vector3f(0,1,0), new Vector3f(1,0,0));

        KeyBindingManager.getKeyBindingManager().set("moveFwd", KeyInput.KEY_W);
        KeyBindingManager.getKeyBindingManager().set("moveBwd", KeyInput.KEY_S);
        KeyBindingManager.getKeyBindingManager().set("moveLeft", KeyInput.KEY_A);
        KeyBindingManager.getKeyBindingManager().set("moveRight", KeyInput.KEY_D);
        lastPosition = new Vector3f();
    }

    protected void simpleUpdate() {
       
        //put the cam at the box position
        cam.setLocation(new Vector3f(
                b.getLocalTranslation().getX(),
                b.getLocalTranslation().getY()+1,
                b.getLocalTranslation().getZ()));

        results.clear();           
        b.findCollisions(rootNode, results);

        if (results.getNumber() > 0){ // if we are inside the dungeon, result = 1
            oldData = results.getCollisionData(0);

            if (oldData.getTargetTris().size()>0)
            {
                // if collision with dungeon wall happen set lastPosition for box & cam
                b.getLocalTranslation().set(lastPosition);
               
            }

            // no collision with dungeon walls, we can move..
            else if (oldData.getTargetTris().size()==0)
            {
                if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveFwd", false))
                {           
                    b.getLocalTranslation().y += boxSpeed* timer.getTimePerFrame();
                }
                if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveBwd", false))
                {           
                    b.getLocalTranslation().y -= boxSpeed* timer.getTimePerFrame();
                }
                if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveLeft", false))
                {           
                    b.getLocalTranslation().z -= boxSpeed* timer.getTimePerFrame();
                }
                if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveRight", false))
                {           
                    b.getLocalTranslation().z += boxSpeed* timer.getTimePerFrame();
                }
                // save last position
                //lastPosition = b.getLocalTranslation();
                lastPosition.set(b.getLocalTranslation());
            }
        }   
    }
}

wall collision was recently added to flagrush on the wiki this might be helpful


thanks for telling about this but it's still too advanced for me :/
i'm trying to read it but it'd be nice if there would be a simplier test case.

like for example:
- create a cube with empty space it in,
- put camera inside the cube (in empty space)
- but a box attached to camera for ex..
- and test for collision with the walls (camera and box shouldn't be able to get out)

(it's basically what i'm trying to do)

this should probably be a small  test (few lines) easy to understand ...
flagrush tutorials is spanned over multiple lessons, and there's a lot to read (and understand)
i'm doing it, but i'm not there just yet.
i need something more beginner friendly i guess

got it working now .. in case it might interest someone here's the code:


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.CollisionTree;
import com.jme.bounding.CollisionTreeManager;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.intersection.CollisionData;
import com.jme.intersection.CollisionResults;
import com.jme.intersection.TriangleCollisionResults;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Box;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.ObjToJme;


public class HelloModelLoading extends SimpleGame {

   //private Node boxNode, mapNode;
   private Spatial b, m;
   private CollisionResults results;
   private CollisionData oldData;
   private Vector3f lastPosition;
   private float boxSpeed = 20.0f;

   public static void main(String[] args) {
      HelloModelLoading app = new HelloModelLoading();
      app.setConfigShowMode(ConfigShowMode.AlwaysShow);
      Logger.getLogger("").setLevel(Level.SEVERE);
      app.start();
   }

   protected void simpleInitGame() {  

      input = new InputHandler();
      CollisionTreeManager.getInstance().setTreeType(CollisionTree.Type.AABB);
      results = new TriangleCollisionResults();      

      URL model=HelloModelLoading.class.getClassLoader().getResource("data/test_01_02.obj");
      FormatConverter converter=new ObjToJme();
      converter.setProperty("mtllib",model);

      ByteArrayOutputStream BO=new ByteArrayOutputStream();
      try {

         //mapNode = new Node("map node");
         converter.convert(model.openStream(), BO);
         m=(Spatial) BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
         m.setLocalScale(.1f);
         m.setModelBound(new BoundingBox());
         m.updateModelBound();


         //boxNode = new Node("box node");
         b = new Box("box", new Vector3f(-20,5,0), 1, 1 ,1);
         b.setLocalScale(.4f);
         b.setModelBound(new BoundingBox());
         b.updateModelBound();

         rootNode.attachChild(b);
         rootNode.attachChild(m);

      } catch (Exception e) {   // Just in case anything happens
         System.out.println("Damn exceptions! O_o n" + e);
         e.printStackTrace();
         System.exit(0);
      }
      // change the direction camera is looking at
      cam.setAxes(new Vector3f(0,0,-1), new Vector3f(0,1,0), new Vector3f(1,0,0));

      KeyBindingManager.getKeyBindingManager().set("moveFwd", KeyInput.KEY_W);
      KeyBindingManager.getKeyBindingManager().set("moveBwd", KeyInput.KEY_S);
      KeyBindingManager.getKeyBindingManager().set("moveLeft", KeyInput.KEY_A);
      KeyBindingManager.getKeyBindingManager().set("moveRight", KeyInput.KEY_D);
      lastPosition = new Vector3f();
   }

   protected void simpleUpdate() {

      //put the cam at the box position
      cam.setLocation(new Vector3f(
            b.getLocalTranslation().getX(),
            b.getLocalTranslation().getY()+1,
            b.getLocalTranslation().getZ()
      ));

      results.clear();           
      b.findCollisions(rootNode, results);

      if (results.getNumber() <= 0) {
         System.out.printf("don't go out dammitn");
         System.exit(0);
      }
      oldData = results.getCollisionData(0);

      if (oldData.getTargetTris().size()==0){
         
         lastPosition.set(b.getLocalTranslation());
         
         if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveFwd", false))
         {
            b.getLocalTranslation().y += boxSpeed* timer.getTimePerFrame();
         }
         if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveBwd", false))
         {
            b.getLocalTranslation().y -= boxSpeed* timer.getTimePerFrame();
         }
         if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveLeft", false))
         {
            b.getLocalTranslation().z -= boxSpeed* timer.getTimePerFrame();
         }
         if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveRight", false))
         {
            b.getLocalTranslation().z += boxSpeed* timer.getTimePerFrame();
         }
      }

      if (oldData.getTargetTris().size()>0)
      {
         b.getLocalTranslation().set(lastPosition);
      }
   }
}