[SOLVED] camNode positioning issue

Hello all!



I’ve spent a good while searching these forums/google to try and find a resolution to this problem. I’ve scoured the JavaDocs for any methods that might accomplish what I need but I feel this is just an error on my part, I’m newer to jMonkey but about intermediate java dev for the last couple of years (Android mostly).



So picture this: Super Mario Bros 1-1 but 3D. Sidescroller. I chose to just recreate this level as an introduction into jMonkey. Here is my problem.



I have my model imported and attached to a charNode which is attached to the rootNode as so:

[java]

/** Load Mario Model /

charGeom = (Geometry) assetManager.loadModel(“Models/Mario/Mario.j3o”);

/
* Move Mario Model /

charGeom.scale(.02f); //Huge model

charNode = new Node(“charNode”);

charNode.attachChild(charGeom);

charNode.setLocalTranslation(Vector3f.UNIT_Y);

[/java]



I create collisionShape, add Control, and attach charNode to rootNode here:

[java]

// Create a appropriate physical shape for it

CapsuleCollisionShape collisionShape = new CapsuleCollisionShape(.5f, 1.20f);

charControl = new CharacterControl(collisionShape, .1f);

// Attach physical properties to model and PhysicsSpace

charNode.addControl(charControl);

// Rotate CharControl which rotates spatial

charControl.setViewDirection(Vector3f.UNIT_X);

bulletAppState.getPhysicsSpace().add(charControl);



rootNode.attachChild(charNode);

[/java]

Both of the above are in initWorld() that is called during simpleInitApp(). After initWorld(), initCamera() is called with the following:

[java]

// Setup Quat to flip camera 180

reverseQuat = reverseQuat.fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y);

//create the camera Node

camNode = new CameraNode(“Camera Node”, cam);

//This mode means that spatial copies the movements of the camera:

camNode.setControlDir(ControlDirection.SpatialToCamera);

//Attach the camNode to the target:

charNode.attachChild(camNode);

//Position the camNode above and to the -X of the model/ground so it looks like a side-scroller

camNode.setLocalTranslation(charFacingRight); //

//Rotate the camNode to look at the node, add height to make the camera focus above the model

camNode.lookAt(charNode.getLocalTranslation().add(cameraHeight), Vector3f.UNIT_Y);

[/java]



My initKeys() is the standard:

[java]

if (name.equals(“Left”)) {

if (keyPressed) {

left = true;

} else {

left = false;

}

} else if (name.equals(“Right”)) {

if (keyPressed) {

right = true;

} else {

right = false;

}

[/java]



And my simpleUpdate() is where the issue actually lays:

[java]

walkDirection.set(0, 0, 0);

if (right) {

walkDirection.addLocal(Vector3f.UNIT_X.mult(tpf * charRightSpeed));

/
* Flip attached camNode opposite location to show Mario changing directions w/o camera ‘moving’ */

//camNode.setLocalTranslation(charFacingRight); // 25f, 8f, 0f

//camNode.lookAt(charNode.getLocalTranslation().add(cameraHeight), Vector3f.UNIT_Y);

}

if (left) {

walkDirection.addLocal(Vector3f.UNIT_X.negate().mult(tpf * charLeftSpeed));

}

if (walkDirection.length() == 0) {

//TODO

} else {

charControl.setViewDirection(walkDirection);

}

charControl.setWalkDirection(walkDirection);

[/java]



When I’m pressing the right arrow key the model moves rights and the camera follows and all is well in my world. BUT when I try to go left… the charControl setViewDirection makes the model look left but it takes the camera with it!. As in model never ‘looks’ like it turns around, it’s always facing right and the rest of the world turns. The localTranslation of the camNode never changes (system.out during update) which makes sense as it’s attached the the charNode.



As you can see from my commented lines in the simpleUpdate, i’ve tried moving the camNode back to the original position and doing a lookAt() but the camera always looks off into some weird direction, never back at the model. I’ve tried using both getWorldTranslation and getLocalTranslation in every instance of either I used.



I’ve tried just:

[java]

camNode.lookat(charNode.getLocalTranslation());

[/java]

instead of the adding the cameraHeight (0f, 8f, 0f) but that didn’t work either.



I’m sure I missed something as this is getting long but if anyone has any idea/questions please let me know.



Thanks!

Updating with some images:



This shows what happens when I press ‘Right’

http://i.imgur.com/pHRNy.png



This show what happens when I press ‘Left’

http://i.imgur.com/eBuv6.png



You can see the model does turn but the camera turns with it (as its supposed to im sure). I just need it to stay where it is when charControl.setViewDirection(walkDirection) is called.



Thanks again.

So maybe write your own control for the camera that does what you want? You can take some inspiration from the source:

CameraControl.java

Actually you can probably just remove stuff from that control and then it will probably be exactly what you want.



[java]//This mode means that spatial copies the movements of the camera:

camNode.setControlDir(ControlDirection.SpatialToCamera);

[/java]



No it does not, it means that the camera should do exactly what you describe is happening :slight_smile:



[java]case SpatialToCamera:

camera.setLocation(spatial.getWorldTranslation());

camera.setRotation(spatial.getWorldRotation());[/java]

@jmaasing said:
No it does not, it means that the camera should do exactly what you describe is happening :)


Whoops, as a fix I tried CameraToSpatial and forgot to change the comment back :P.

I'll look into your suggestion and let you know the outcome, thanks!

I have this solved and wanted to update in case it might help another.



I created my own version of CameraControl.java and CameraNode.java (just copy/pasted the code) and modified CameraControl.java as follows to prevent the camera from rotating with the spatial. Main.facingLeft is a static boolean that gets toggled on keypress.



[java]

//CameraControl.java



// fields used, when inversing ControlDirection:

@Override

protected void controlUpdate(float tpf) {

if (spatial != null && camera != null) {

switch (controlDir) {

case SpatialToCamera:

if (Main.facingLeft) {

reverseWorldTranslation = new Vector3f(spatial.getWorldTranslation().x,

8.5f , -spatial.getWorldTranslation().z);

camera.setLocation(reverseWorldTranslation);

}

else {

reverseWorldTranslation = new Vector3f(spatial.getWorldTranslation().x,

8.5f , spatial.getWorldTranslation().z);

camera.setLocation(reverseWorldTranslation);

}

break;

}

}

[/java]



The rogue 8.5f for the Y coordinate allowed the camera to act as if it was on a rail on only move left/right on the Y axis. If anyone sees anyway I can improve on this or a more elegant solution, please let me know. Otherwise I am satisfied with this result.



Thanks for the help sir.

talitore

1 Like