Limiting camera movement in first person controller

i admit that i'm greener than green at using jme but i've been using the first person controller and wanted to limit the up and down range of movement in the camera. For example, i want the character to be able to look at his feet but not to look backwards upside down through his arse hole.



To do this i figured that i'd need to change the KeyLookUpAction.performAction code:


   public void performAction(InputActionEvent evt) {
        incr.fromAngleNormalAxis(-speed * evt.getTime(), camera.getLeft());
        incr.mult(camera.getLeft(), camera.getLeft());
        incr.mult(camera.getDirection(), camera.getDirection());
        incr.mult(camera.getUp(), camera.getUp());
        camera.normalize();
        camera.update();
    }


now, my math is going to need brushing up, but is there an easy way to get the angle in regard to the world axis that the camera is rotated? ie up and down rotation?

do you think i should keep a matrix3f or a quaternion or calculate the angle each time through?

i've worked out how to calculate the angle that the camera is at. the following code is the move down handler.


    private Vector3f up = new Vector3f(0.0f,1.0f,0.0f);
    private Vector3f newDir = new Vector3f();
   
    public void performAction(InputActionEvent evt) {
       
       incr.fromAngleNormalAxis(speed * evt.getTime(), camera.getLeft());
       incr.mult(camera.getDirection(),newDir);
       float angle = FastMath.acos(up.dot(newDir));
       System.err.println(angle + " - " + evt.getTime());
       
       if ( angle > 3.0f ) return;

       incr.mult(camera.getLeft(), camera.getLeft());
       incr.mult(camera.getDirection(), camera.getDirection());
        incr.mult(camera.getUp(), camera.getUp());
        camera.normalize();
        camera.update();
    }



BUT ... the problem is that the user can quickly spin the camera all the way around so that the camera returns to the correct angle range ... i can fix that tho.

is there a better way that anyone can think of that doesn't require so much math?

on second thought, i'm stumped, how would i stop that camera rotating all the way around?

I don't quite understand your problem… Do you want to limit the angle range of the camera for both movements?



If so, then I would suggest writing your own controller so you will have more freedom as to what to allow. As you have already discovered, Camera has methods for getting the up vector direction, that means you can simply apply a dot product to get the angle between that vector and your favorite one  :stuck_out_tongue: (for instance a y-axis unit vector). That would let you decide whether the camera is pointing too much in one direction or not.

okay … but say the camera angle exceeds the minimum (or maximum) and instead i want to set it to the minimum (or maximum)?



i currently have the following code in my movement handler for looking up:


    public void performAction(InputActionEvent evt) {
        incr.fromAngleNormalAxis(-speed * evt.getTime(), camera.getLeft());

       incr.mult(camera.getDirection(),newDir);
       float angle = FastMath.acos(up.dot(newDir));
       System.err.println(angle + " - " + newDir);
       
       if ( angle < 0.5f ) return;
       
        incr.mult(camera.getLeft(), camera.getLeft());
        incr.mult(camera.getDirection(), camera.getDirection());
        incr.mult(camera.getUp(), camera.getUp());
        camera.normalize();
        camera.update();
    }



i guess what i'm asking is how to i compute the parameter (evt.getTime()) so that the angle = 0.5 ?

Well, you really don't have to do it that way. Camera has a method called lookAt() you could use to set the direction if the angle is outside range. It will require some calculations, but they are not that complicated.  :wink: