Colission detection: semantic error

Hi everyone,



i've got a camNode (where a sphere is attached to) and I want it to collide with my walls (attached to scene)



So I tried this:



    @Override
    protected void simpleUpdate() {


            LocX = camNode.getLocalTranslation().getX();
            LocY = camNode.getLocalTranslation().getY();
            LocZ = camNode.getLocalTranslation().getZ();


            if (camNode.hasCollision(scene, false)){


            LocXnew = LocX *  .99f;
            //LocXnew = LocX * 1.01f;
            LocYnew = LocY * 1.00f;
            LocZnew = LocZ * 1.00f;


           camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew);

}



But see now what happens as a coroally:




The camNode can still pass from one side.

Has anyone an idea how I can do it in a different way?

Thank you so far.

you could put an invisible sphere or box on the location of the camNode and then do collision with that sphere or box

There is allready a sphere.

I've attached it to the camNode.

So actually the sphere collides with the wall

I think that colliding the wall with a cam wouldn't work because the cam has no geometry, would it?

Sorry for pushing, but I still can't handle it.



I also considered to do sth like this:


if (camNode.hasCollision(wall1, false)){
        if (LocX > LocXwall1){
        LocXnew = LocX *  1.01f;
        }
        else if (LocX < LocXwall1)
        {
        LocXnew = LocX * 0.99f;
        }
}

if (camNode.hasCollision(wall2, false)){
        if (LocX > LocXwall2){
        usw. }



So if the player (camNode) has a collision with wall1 and his x-coordinate is larger than the x-coordinate of the wall, he should do LocXnew = LocX *  1.01f.

But the problem with that: I created the map with mw3d, imported it, and added it to the node scene.
So I don't know how to get the position of a wall.

Anyone knows how to get?
Or any idea for another approach?

and another push

You could use 6 raychecks, with the length a few units: Top, bottom, left, right, front, back.

if(topRayCheck < 1.0 || bottomRayCheck < 1.0)
  currentY = lastY;
....



But a bounding-volume would be better.

But I allready have a bounding volume.

It is added to the camNode


Sphere camSphere=new Sphere("Camera Sphere",10,10,1f);
camSphere.setModelBound(new BoundingBox());
camSphere.setLocalScale(2.0f);
camSphere.setLocalTranslation(new Vector3f(0, 3, 20));
camSphere.updateModelBound();
sphereNode = new Node("Sphere Node");
sphereNode.attachChild(camSphere);
camNode.attachChild(sphereNode);



So actually the camSphere is colliding with the scene.
But as the sphere is added to the camNode, i do the collision detection for scene and camNode.



or am I misunderstanding you?

The bounding box you are using is only for view-frustum-clipping, not for collision.

Sorry for that stupid question, but I still can't follow:



Why is it not for collision  :?



Anyhow the sphere can't pass through the wall from one side, but it still does from the other side.

Well, there are a few problems and approaches.

I don't see in your code how fast your sphere is moving, that could affect things.

Also, if you don't do triangle accurate collisions or raytracing you don't know at what angle the sphere is hitting the wall. If all walls are aligned north-south / east-west it could be done without it though, I guess…



Anyway, you could save a speed variable (or a direction variable) so you would know in which direction the sphere is moving when it hits the wall. If your step isn't as large as to go half through the wall you would know on what side you were and change the direction of movement as you've done (with your examples *.99 for one direction and 1.01 for the other).



Example:



if (camNode.hasCollision(scene, false)){

  if(speed >0) {

      x *= .99f;

  }

  else if(speed < 0) {

      x *= 1.01f;

  }

}



I'm not quite sure what you're wanting to do, but perhaps this could help as a start.

This is a smart approach, but I allready considered a solution like you suggested.

The problem: I don't know how to get a direction (or speed) variable.



I thought about saving an old x-coord (0.1 seconds ago or sth like this), than taking the current x-coord and comparing both. But I didn't find a way to save the old x-coord.



At the moment I'm moving the Node with a NodeHandler


input = new NodeHandler( camNode, 60, 0.475f );



So is there a way to find out the direction I'm moving?

Well, I haven't used NodeHandler, nor have I used SimpleGame much, so I can't be quite sure.

But you have your node (camNode) that you want to get the direction from.

So you create an instance variable that stores the previous x-coord and one for your change:



private float prevX = Float.POSITIVE_INFINITY;

private float change;



Then in the update method you check direction (after second iteration) and set the variable:



if(prevX != Float.POSITIVE_INFINITY) {

  change = camNode.getLocalTranslation().x-prevX;

}

prevX = camNode.getLocalTranslation().x;



Then when finding a collision you just check if change is positive or negative.

Perhaps that could work?

Thx 4 your help, and sorry for late reply, been pretty busy.



Tried out your really smart idea (I wouldn’t have figured that out by myself) but now see what happens (sorry for poor quality):



http://www.youtube.com/watch?v=dLP1gAEYx0I



The sphere collides and sometimes jumps back. Everything fine so far.

But than it suddenly ignores the collision and walks through the wall again.




import ...



public class labyrinth extends SimpleGame {


    private ...




    public static void main(String args[]) {
        labyrinth game = new labyrinth();
        game.start();
    }
  




    protected void simpleInitGame() {
       

        camNode();
    }

//***************Usually the Map-Import stands here ********//




        private void camNode() {
        cam = display.getRenderer().getCamera();
        cam.setFrustum(1.0f, 1000.0f, -0.55f, 0.55f, 0.4125f, -0.4125f);
        camNode = new CameraNode("Camera Node", cam);
        camNode.setLocalTranslation(new Vector3f(230, 25, -220));
        camNode.lookAt(new Vector3f(200, 25, 200), new Vector3f(0, 1, 0));
        camNode.updateWorldData(0);
        rootNode.attachChild(camNode);
        cam.update();
  
     Sphere camSphere=new Sphere("Camera Sphere",10,10,1f);
          camSphere.setModelBound(new BoundingBox());
          camSphere.setLocalScale(2.0f);
     camSphere.setLocalTranslation(new Vector3f(0, 3, 20));
     camSphere.updateModelBound();
          sphereNode = new Node("Sphere Node");
     sphereNode.attachChild(camSphere);
          camNode.attachChild(sphereNode);


            input.addAction(new KeyNodeForwardAction( camNode, 50 ), "forward", true);
            input.addAction(new KeyNodeBackwardAction( camNode, 50 ), "backward", true);
            KeyNodeRotateRightAction rotateRight = new KeyNodeRotateRightAction( camNode, 1.5f );
            rotateRight.setLockAxis( camNode.getLocalRotation().getRotationColumn( 1 ) );
            input.addAction( rotateRight, "strafeRight", true );
            KeyNodeRotateLeftAction rotateLeft = new KeyNodeRotateLeftAction( camNode, 1.5f );
            rotateLeft.setLockAxis( camNode.getLocalRotation().getRotationColumn( 1 ) );
            input.addAction( rotateLeft, "strafeLeft", true );




            input = new NodeHandler( camNode, 60, 0.475f );
               NodeMouseLook MouseLook = new NodeMouseLook(mouse, camNode, 5);
            MouseLook.setLockAxis(new Vector3f(cam.getUp().x, cam.getUp().y, cam.getUp().z));
            input.update(1);    

    }



    @Override
    protected void simpleUpdate() {




        LocX = camNode.getLocalTranslation().getX();
        LocY = camNode.getLocalTranslation().getY();
        LocZ = camNode.getLocalTranslation().getZ();


           

        if(prevX != Float.POSITIVE_INFINITY) {
             changeX = camNode.getLocalTranslation().x-prevX;
            }
        prevX = camNode.getLocalTranslation().getX();


        if(prevZ != Float.POSITIVE_INFINITY) {
             changeZ = camNode.getLocalTranslation().z-prevZ;
            }
        prevZ = camNode.getLocalTranslation().getZ();


        if (camNode.hasCollision(scene, false)){
        if (changeX > 0 ){
        LocXnew = LocX *  .95f;
        LocYnew = LocY;
        LocZnew = LocZ * .95f;
        camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew);
        }
        else if (changeX < 0)
        {
        LocXnew = LocX * 1.05f;
        LocYnew = LocY;
        LocZnew = LocZ * 1.05f;
        camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew);
               
       
        if (changeZ > 0 ){
        LocXnew = LocX *  .95f;
        LocYnew = LocY;
        LocZnew = LocZ * .95f;
        camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew);
        }
        else if (changeZ < 0)
        {
        LocXnew = LocX * 1.05f;
        LocYnew = LocY;
        LocZnew = LocZ * 1.05f;
        camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew);

        }



        }
        }
        }
    }
}
   



I'm quite stumped

afaik i don't have to update my input. simpleGame does it somewhere else (?)



thx a lot for your very helpful hints. i'm starting to understand it.


you could be colliding in straight x-direction but also moving in z-direction without a collision


i think this could be the main cause why it doesn't work.
maybe i can find a way like


if (changeX > changeZ ){
if (changeX > 0 ){
        LocXnew = LocX - 2.5f;
        LocYnew = LocY;
        LocZnew = LocZ ;
        camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew);
        }
        else if (changeX < 0)
        {
        LocXnew = LocX + 2.5f;
        LocYnew = LocY;
        LocZnew = LocZ;
        camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew); }

else if (changeX <changeZ) {
        if (changeZ > 0 ){
        LocXnew = LocX;
        LocYnew = LocY;
        LocZnew = LocZ - 2.5f;
        camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew);
        }
        else if (changeZ < 0)
        {
        LocXnew = LocX;
        LocYnew = LocY;
        LocZnew = LocZ + 2.5f;
        camNode.setLocalTranslation(LocXnew, LocYnew, LocZnew);

        }



or sth like this...

let me think about it and try it out ;)

i'll let you know if i was successful or not.

This really seems to work.

Still have some trouble in the corners, but this could be a other problem.



Thx all 4 ur help!