How to constraint angle of flybyCam?

Hi,

I want to constraint movement of angle of flyByCam to say 90 degrees (horizontal plane along z axis) and restrict it totally in the orthogonal direction.

please give comments on how can this be possible??

Hi,
Is there any hope with this. I have been trying to get into jME code but I’m not able to find the right module where I should start looking into??

Open flycam.
Select all.
Copy
Open new file “MyFlyCam”
Paste code
Modify to limit angles.

you forgot the last step

“share the result, so other people in the futur won’t have to do it again”.

@bubuche said: you forgot the last step

“share the result, so other people in the futur won’t have to do it again”.

I’m not sure it matters. Simpler results have been shared before but apparently can’t be found.

I just googled “flycam limit angle” (using our search box up there to the right) and the first link was the right thread. If you read a bit in, you come to this simple solution:
http://hub.jmonkeyengine.org/forum/topic/several-first-person-camera-pitfalls-speed-and-angle-jme3/page/2/#post-178336

You even get a little further down where someone has posted a fully working implementation, I guess.

@pspeed said: I just googled "flycam limit angle" (using our search box up there to the right) and the first link was the right thread. If you read a bit in, you come to this simple solution: http://hub.jmonkeyengine.org/forum/topic/several-first-person-camera-pitfalls-speed-and-angle-jme3/page/2/#post-178336

You even get a little further down where someone has posted a fully working implementation, I guess.

But Paul, that involves SEARCHING! And searching is hard. It drains mental energy and is just a general PITA. It’s so much easier to beg.

1 Like

Thanks a lot, I got it a few days back.

I preffered inheriting classes rather than copying/pasting and modifying code. I’m not sure though but class SimpleApplication should have a method to provide a custom FlyByCamera thing, which would have made things quite intuitive.

flyByCamera::
[java]

public class FlyByCameraMod extends FlyByCamera {
/**
* Creates a new FlyByCameraMod to control the given Camera object.
* @param cam
*/

private float angle=0.0f;
private float boundLeft;
private float boundRight;

private static String[] mappings = new String[]{
        "FLYCAM_Left",
        "FLYCAM_Right",
        "FLYCAM_Up",
        "FLYCAM_Down",

        "FLYCAM_StrafeLeft",
        "FLYCAM_StrafeRight",
        "FLYCAM_Forward",
        "FLYCAM_Backward",

        "FLYCAM_ZoomIn",
        "FLYCAM_ZoomOut",
        "FLYCAM_RotateDrag",

        "FLYCAM_Rise",
        "FLYCAM_Lower",
        
        "FLYCAM_InvertY"
    };

public FlyByCameraMod(Camera cam){
    super(cam);
}

/*
 * Set both as 0 to make camera unconstrained..
 */
public void setCamBound(float valLeft, float valRight) {
    boundLeft=valLeft;
    boundRight=valRight;
    
    // Resetting the angle
    angle=0.0f;
}

/**
 * Registers the FlyByCameraMod to receive input events from the provided
 * Dispatcher.
 * @param inputManager
 */
@Override
public void registerWithInput(InputManager inputManager){
    this.inputManager = inputManager;
    
    // both mouse and button - rotation of cam
    inputManager.addMapping("FLYCAM_Left", new MouseAxisTrigger(MouseInput.AXIS_X, true),
                                           new KeyTrigger(KeyInput.KEY_LEFT));

    inputManager.addMapping("FLYCAM_Right", new MouseAxisTrigger(MouseInput.AXIS_X, false),
                                            new KeyTrigger(KeyInput.KEY_RIGHT));
    /*
     * Removed to restrict movement only along Up vector 

    inputManager.addMapping("FLYCAM_Up", new MouseAxisTrigger(MouseInput.AXIS_Y, false),
                                         new KeyTrigger(KeyInput.KEY_UP));

    inputManager.addMapping("FLYCAM_Down", new MouseAxisTrigger(MouseInput.AXIS_Y, true),
                                                    new KeyTrigger(KeyInput.KEY_DOWN));
    */

    // mouse only - zoom in/out with wheel, and rotate drag
    inputManager.addMapping("FLYCAM_ZoomIn", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
    inputManager.addMapping("FLYCAM_ZoomOut", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
    inputManager.addMapping("FLYCAM_RotateDrag", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));

    // keyboard only WASD for movement and WZ for rise/lower height
    
    inputManager.addMapping("FLYCAM_StrafeLeft", new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping("FLYCAM_StrafeRight", new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping("FLYCAM_Forward", new KeyTrigger(KeyInput.KEY_W));
    inputManager.addMapping("FLYCAM_Backward", new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping("FLYCAM_Rise", new KeyTrigger(KeyInput.KEY_Q));
    inputManager.addMapping("FLYCAM_Lower", new KeyTrigger(KeyInput.KEY_Z));
   

    inputManager.addListener(this, mappings);
    inputManager.setCursorVisible(dragToRotate || !isEnabled());

    Joystick[] joysticks = inputManager.getJoysticks();
    if (joysticks != null && joysticks.length > 0){
        for (Joystick j : joysticks) {
            mapJoystick(j);
        }
    }
}

@Override
protected void rotateCamera(float value, Vector3f axis){        
    if (dragToRotate){
        if (canRotate){

// value = -value;
}else{
return;
}
}

    // -ve is for android controls reversal
    float rot = -rotationSpeed * value;
    //angleRight += rot;
    //angleLeft -=rot;
    //System.out.println("Camera angle: " + angle);

    if (boundRight !=0 || boundLeft!=0) {
        if (angle+rot<boundRight) {
            //angleRight =-0.9f;
            return;
        }
        else if (angle+rot > boundLeft) {
            //angleRight =0.0f;
            return;
        }
        else {
            angle += rot;
        }            
    }

    Matrix3f mat = new Matrix3f();

    mat.fromAngleNormalAxis(rot, axis);

    Vector3f up = cam.getUp();
    Vector3f left = cam.getLeft();
    Vector3f dir = cam.getDirection();

    mat.mult(up, up);
    mat.mult(left, left);
    mat.mult(dir, dir);

    Quaternion q = new Quaternion();
    q.fromAxes(left, up, dir);
    q.normalizeLocal();

    cam.setAxes(q);
}

}
[/java]

A new FlyCamAppState
[java]

public class FlyCamAppStateMod extends AbstractAppState {

private Application app;
private FlyByCameraMod flyCam;

public FlyCamAppStateMod() {
}    

/**
 *  This is called by SimpleApplication during initialize().
 */
public void setCamera( FlyByCameraMod cam ) {
    this.flyCam = cam;
}

public FlyByCameraMod getCamera() {
    return flyCam;
}

@Override
public void initialize(AppStateManager stateManager, Application app) {
    super.initialize(stateManager, app);
    
    this.app = app;

    if (app.getInputManager() != null) {
    
        if (flyCam == null) {
            flyCam = new FlyByCameraMod(app.getCamera());
        }
        
        flyCam.registerWithInput(app.getInputManager());
    }               
}
        
@Override
public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);
    
    flyCam.setEnabled(enabled);
}

@Override
public void cleanup() {
    super.cleanup();

    flyCam.unregisterInput();        
}

}
[/java]

Inherited simpleApplication
[java]
public abstract class SimpleApplicationMod extends SimpleApplication {

private SimpleApplicationMod.AppActionListener actionListener = new SimpleApplicationMod.AppActionListener();
private class AppActionListener implements ActionListener {

    public void onAction(String name, boolean value, float tpf) {
        if (!value) {
            return;
        }

        if (name.equals(INPUT_MAPPING_EXIT)) {
            stop();
        }else if (name.equals(INPUT_MAPPING_HIDE_STATS)){
            if (stateManager.getState(StatsAppState.class) != null) {
                stateManager.getState(StatsAppState.class).toggleStats();
            }
        }
    }
}


public SimpleApplicationMod() {
    super();
}

public SimpleApplicationMod( AppState... initialStates ) {
    super(initialStates);        
}

@Override
public void initialize() {
    
    super.initialize();

    /* This create a flyByCamMod instance if you have attached a 
     * FlyByCameraAppStateMod to the stateManager.
     * 
     * Don't attach FlyByCameraAppState and FlyByCameraAppStateMod
     * at the same time otherwise the this will reassign the reference of 
     * flyCam to FlyByCamera...
     */
    if (stateManager.getState(FlyCamAppStateMod.class) != null) {
        flyCam = new FlyByCameraMod(cam);
        flyCam.setMoveSpeed(1f); // odd to set this here but it did it before
        
        // This is because in our use case we will attach this appstate for TAB.
        flyCam.setDragToRotate(true);
        stateManager.getState(FlyCamAppStateMod.class).setCamera((FlyByCameraMod)flyCam ); 
    }                
}

}[/java]

Ugh…

There are about 50 articles on how to disable the current fly cam and all of them mention the easy way to add your own. We could add everything and an MMO to SimpleApplcation but then we’d have to change it’s name to TheWholeInternet. :wink:

[java]
public class MyCoolGame extends SimpleApplication {
public static void main( String … args ) {
MyCoolGame app = new MyCoolGame();
app.start();
}

public MyCoolGame() {
    super( new MyCoolFlyCamReplacement() );
}

}
[/java]

Tadah.

The fact that there is a flyCam local variable is an uncorrectable abomination, unfortunately. I’d rip all of those protected fields out with a rusty dull spoon if I could but it’s too late now.

@pspeed said: We could add everything and an MMO to SimpleApplcation but then we'd have to change it's name to TheWholeInternet. ;)

Yup, and everyone would still be stuck in the noob area after 200 hrs. >.<