Still Need Help With FPS camera Panning up and down + BetterCharacterControl

Can someone look at this code (cameraNode attached to BetterCharacterControl) and tell me why I can not pan up and down like I can with the flyCam.
I can look around 360 horizontal view , but I can not look up or down.

Thanks!
[java]
package mygame;

import com.jme3.app.DebugKeysAppState;
import com.jme3.app.SimpleApplication;
import com.jme3.app.StatsAppState;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.FlyByCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.CameraControl;
import com.jme3.terrain.geomipmap.TerrainQuad;

public class TestThree extends SimpleApplication implements AnalogListener {

private BulletAppState bulletAppState;
private BetterCharacterControl physicsCharacter;
private TerrainQuad terrain;
private CameraNode cameraNode;
protected Vector3f initialUpVec;
protected boolean invertY = false;
private Node characterNode;
boolean leftStrafe = false, rightStrafe = false;
private boolean left = false, right = false, up = false, down = false;
private Vector3f walkDirection = new Vector3f();
private Vector3f camDir = new Vector3f();
private Vector3f camLeft = new Vector3f();
public final float SPEED = 5.0f;
private FlyByCamera flyCam;

public TestThree() {
    super(new StatsAppState(), new DebugKeysAppState());
}

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

@Override
public void simpleInitApp() {
    this.inputManager.setCursorVisible(false);
    // activate physics
    bulletAppState = new BulletAppState();
    stateManager.attach(bulletAppState);
    initTerrian();
    initPlayer();
    initLight();
    initCameraNode();
    bulletAppState.setDebugEnabled(true);
    setUpKeys();
}

private void initLight() {
    AmbientLight ambient = new AmbientLight();
    ambient.setColor(ColorRGBA.Blue);
    rootNode.addLight(ambient);
    DirectionalLight sun = new DirectionalLight();
    sun.setDirection((new Vector3f(-0.5f, -0.5f, -0.5f)).normalizeLocal());
    sun.setColor(ColorRGBA.White);
    rootNode.addLight(sun);
}

private void initTerrian() {
    Spatial level = assetManager.loadModel("Scenes/LevelOne.j3o");
    rootNode.attachChild(level);
    terrain = (TerrainQuad) ((Node) rootNode.getChild("New Scene")).getChild("terrain-LevelOne");
    terrain.addControl(new RigidBodyControl(0));
    bulletAppState.getPhysicsSpace().add(terrain);
}

private void initPlayer() {
    // Create a node for the character model
    characterNode = new Node("character node");
    characterNode.setLocalTranslation(new Vector3f(4, 5, 2));

    // Add a character control to the node so we can add other things and
    // control the model rotation
    physicsCharacter = new BetterCharacterControl(0.3f, 2.0f, 8f);
    characterNode.addControl(physicsCharacter);
    bulletAppState.getPhysicsSpace().add(physicsCharacter);

    // Load model, attach to character node
    Node model = (Node) assetManager.loadModel("Models/Man.mesh.j3o");
    model.setLocalScale(0.25f);
    model.setLocalTranslation(new Vector3f(0, 1.1f, 0));
    model.setName("Player");

    characterNode.attachChild(model);
    // Add character node to the rootNode
    rootNode.attachChild(characterNode);
}

private void initCameraNode() {
    initialUpVec = cam.getUp();
    cameraNode = new CameraNode("CameraNode", cam);
    cameraNode.setLocalTranslation(0, 1f, 0);
    characterNode.attachChild(cameraNode);
    cameraNode.setControlDir(CameraControl.ControlDirection.SpatialToCamera);
}

@Override
public void simpleUpdate(float tpf) {

    camDir.set(cameraNode.getCamera().getDirection()).multLocal(SPEED, 0, SPEED);
    camLeft.set(cameraNode.getCamera().getLeft()).multLocal(SPEED);
    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());
    }
    physicsCharacter.setWalkDirection(walkDirection.multLocal(1));
    physicsCharacter.setViewDirection(camDir);

}

private void setUpKeys() {
    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));

    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));

    inputManager.addListener(this, "FLYCAM_Left");
    inputManager.addListener(this, "FLYCAM_Right");
    inputManager.addListener(this, "FLYCAM_Up");
    inputManager.addListener(this, "FLYCAM_Down");

}

protected void rotateCamera(float value, Vector3f axis) {
    Matrix3f mat = new Matrix3f();
    mat.fromAngleNormalAxis(SPEED * value, 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);
}

public void onAnalog(String name, float value, float tpf) {
    if (name.equals("FLYCAM_Left")) {
        rotateCamera(value, initialUpVec);
    } else if (name.equals("FLYCAM_Right")) {
        rotateCamera(-value, initialUpVec);
    } else if (name.equals("FLYCAM_Up")) {
        rotateCamera(-value * (invertY ? -1 : 1), cam.getLeft());
    } else if (name.equals("FLYCAM_Down")) {
        rotateCamera(value * (invertY ? -1 : 1), cam.getLeft());
    }
}

}
[/java]

Because of line 118

1 Like

@normen are anyone.
Even if I change to
camDir.set(cameraNode.getCamera().getDirection());
camLeft.set(cameraNode.getCamera().getLeft());

I still get no vertical movement in the camera. I am wondering if the BetterCharacterControl is somehow locking down the movement?
Thanks for any help.

Ah right, the BetterCharacter adpats the view direction to the current gravity plane. I guess you have no chance but to give up the CameraNode then and just move the cam to the character location each update.

Or, what I originally suggested is drop the camera node and use the chase camera!