Getting camera location between updates

I’m trying to find a way to get the default cam position between updates. In each update loop I need to know the cameras previous position. I tried storing the cameras location in a variable in the update loop only to realize the camera movement is being processed post update loop. I really don’t want to write a set of custom input controls if I don’t have too. Anyone know a good way to do this ?

Can this help you?

public class TestCam extends SimpleApplication {

    Vector3f camLoc;

    @Override
    public void simpleInitApp() {
        camLoc = cam.getLocation().clone();
    }

    
    @Override
    public void simpleUpdate(float tpf) {
        // Before anything do to camera
        camLoc.set(cam.getLocation());
        
        // Do your work
    }

}

This is the update loop I’m testing.

@Override
public void simpleUpdate(float tpf) {

    camDir.set(cam.getDirection()).multLocal(speed, 0.0f, speed);
    camLeft.set(cam.getLeft()).multLocal(strafeSpeed);
    walkDirection.set(0, 0, 0);
    if (left) {
        walkDirection.addLocal(camLeft);
    }
    if (right) {
        walkDirection.addLocal(camLeft.negate());
    }
    if (up) {
        walkDirection.addLocal(camDir);
    }
    if (down) {
        walkDirection.addLocal(camDir.negate());
    }
    
    player.setLocalTranslation(player.getLocalTranslation().add(walkDirection));
    testText.setText(player.getLocalTranslation().toString() + lastCameraLocation.toString());
    
    cam.setLocation(new Vector3f(player.getLocalTranslation().x,player.getLocalTranslation().y ,player.getLocalTranslation().z));
    lastCameraLocation.set(player.getLocalTranslation());
   
}

No matter what I do the lastCameraLocation is always the same as the players location. The solution is probably really simple and I’m over looking it.

I tried storing the cameras location in a variable

Where are you doing this in your code ?

I figured it out. I needed to subtract the walkDirection during a key press event then store the variable. What was happening is I was storing the location during down time when no keys where being pressed and no new movement was present.

if (left) {
            walkDirection.addLocal(camLeft);
            lastCameraLocation = player.getLocalTranslation().subtract(walkDirection);
        }
        if (right) {
            walkDirection.addLocal(camLeft.negate());
            lastCameraLocation = player.getLocalTranslation().subtract(walkDirection);
        }
        if (up) {
            walkDirection.addLocal(camDir);
            lastCameraLocation = player.getLocalTranslation().subtract(walkDirection);
        }
        if (down) {
            walkDirection.addLocal(camDir.negate());
            lastCameraLocation = player.getLocalTranslation().subtract(walkDirection);
        }

You set them to be exactly the same so I’m not sure why you expect them to be different. I’m not trying to be mean but I’m literally trying to understand how those above two lines could possibly leave the values different from one another in your eyes.

lastCameraLocation is the same as player’s location because you’ve set it to the player’s location.

Also:
cam.setLocation(new Vector3f(player.getLocalTranslation().x,player.getLocalTranslation().y ,player.getLocalTranslation().z));

Is functionally equivalent to:
cam.setLocation(getLocalTranslation());

Maybe take a step back and tell us what you are actually trying to do. Subtracting walk direction is probably wrong… even if it is giving you close to the right answer now.

Was going to remark the same thing like pspeed.
cam.setLocation(player.getLocalTranslation()) → can only lead to one result… :chimpanzee_smile:

Wouldn’t recording the location during simpleRender instead of simpeUpdate do the trick?

Ignore this post see below lol.

Here is a better example

 int x = 2;
  int y =2;
  
  for (int i = 0;i<10;i++){
      
      y += 1;
      System.out.printf(x + " and " + y + " next loop ");
      x = y;
      
  }

With each pass X will always be the value previously held. 2 & 3 , 3 & 4 , 4 & 5 etc. I tried doing the same thing with the location value but it doesn’t work because the value depends on the camera being moved. Whenever I stopped to check the difference in values the camera was at direction/speed(0,0,0) so both values remained the same.

The whole thing doesn’t fail because of where I set the variables but because it relies on the camera moving and I was always stopping to check the values. I also found it easier just to get the cameras current direction and subtract it from the cameras location.

It’s also very fragile.

Why do you need the last frame’s location? Let’s start there.

I implemented some custom collision detection. I need the last spot of the camera before a collision. I use the difference in position plus the collision angle to calculate a new position along a surface which creates that sliding along a wall effect in video games.

Then you might be trying to do that too early since the movement actually happens after simpleUpdate().

It goes something like (I’ve posted this to the forum at least five times so I won’t regurgitate it completely now)…
-simpleUpdate()
-app state updates
-control updates
-simpleRender()
-app state render
-actual rendering
-app state postRender or whatever

You probably want to do your collision detection after the control updates else you will be doing collision detection after the objects have already been rendered one frame in the wrong place.

Are there any drawbacks to using the render loop for collision ? I’m not using any rigid bodies or physics other than the simple custom collision I designed.

This is all “the render loop”. There are no drawbacks to modifying objects in simpleRender() (or even better in an app state render()). They aren’t really ‘rendering’ anything… they are just the ‘methods called after controls are updated but before any rendering is really done’.

Use them for what you want.

When do the physics take place ? I just tried using the SimpleRender method to over ride some of the physics but the to no avail. The physics are still taking place.

This might help you out, it’s the order in which every update method or type of update gets called. It sounds like your camera’s position is being changed sometime after or before you’re saving the position, and it’s resulting in incorrect info at the end of the frame.

-queued tasks
-input listeners
-audio renderer
-app states update()
-simpleUpdate()
-root node control update
-gui node control update
-root node geometric update
-gui node geometric update
-app states render()
-render manager render
-simpleRender()
-app states postRender()

found here: Running Code After Input Listeners Are Called [SOLVED]

I added this to simple render but physics still over ride it.

public void pullToGround(){

   CollisionResults results = new CollisionResults();
    // 2. Aim the ray from cam loc to cam direction.
    Ray ray = new Ray(cam.getLocation(), Vector3f.UNIT_Y.negate());
    // 3. Collect intersections between Ray and Shootables in results list.
    rootNode.collideWith(ray, results);

    if (results.size() > 0) {
      testText.setText("true");
      float dist = results.getClosestCollision().getDistance();
      Vector3f pt = results.getClosestCollision().getContactPoint();
      String hit = results.getClosestCollision().getGeometry().getName();
      cam.setLocation(new Vector3f(pt.x,pt.y + headHeight,pt.z));


    }

You made it sound before like you were doing your own physics.

Why are you doing your own collision detection like this if you are also using physics?

For physics you will have to use things like tick listeners and stuff.

I’m experimenting with both. I was able to get the bulletstateapp to work but it requires scaling the world down to microscopic proportions and reducing the speed drastically.