Camera node

Hello everybody.



I'm new in jME, and that's the reason why this question could be "stupid" :wink:



I want to create camera which I can move like this from simple game. I'm thinking about going forward, back, left, right but also rotate camera in every direction. From this what I try with .setFrame, I can't make rotate camera, just move it. The only idea I have was to create CameraNode, but I don't know exactly how to add this to my scene correctly. In my InitSystem() i am calling InitCamera which is looking like that:


    private void InitCamera() {
      
       cam =
            display.getRenderer().createCamera(
            display.getWidth(),
            display.getHeight());
        cam.setFrustumPerspective(45.0f,
                                (float) display.getWidth() /
                                (float) display.getHeight(), 1, 1000);
      
        loc = new Vector3f(0.0f, 0.0f, 25.0f);
        left = new Vector3f(-1.0f, 0.0f, 0.0f);
        up = new Vector3f(0.0f, 1.0f, 0.0f);
        dir = new Vector3f(0.0f, 0f, -1.0f);
       
        cam.setFrame(loc, left, up, dir);
        cam.update();
       
        display.getRenderer().setCamera(cam);
       
        cn = new CameraNode("camera node",cam);
        cn.setCamera(cam);
       
        scene.attachChild(cn);

}



but when I try to run it I have problem with " scene.attachChild(cn);", there is error: "java.lang.NullPointerException".
I will be grateful for any help.

It depends on when you are calling this function… most likely scene has not yet been initialized… the best way around would be to call it in simpleInitGame()

Thank you duenez that help.



Unfortunetly now I have another problem. I have create this Camera node, and name it 'cl'. Next I want to make rotate this node, to do this, I'm trying to use SpatialTransformer, and I write function rotate();


private void rotate() {
        // I create a controller to rotate my pivot
        SpatialTransformer st=new SpatialTransformer(1);
              // I tell my spatial controller to change pivot
              st.setObject(cn,0,-1);

              Quaternion x90=new Quaternion();
              x90.fromAngleAxis(FastMath.DEG_TO_RAD*90,new Vector3f(0,1,0));
             
              cn.setLocalRotation(x90);
   }



And it works almost like I want, but I have other problem. I have set keys to move my camera. But ofter I call this function, when i push "forward" my camera is moving left :/ I understand that this is a reason becouse my camera still have front from "before I rotate it". What I should use to make sure that after I rotate my camera, this will be front of my node also? I was trying lookAt, but have some problems with it.

Be sure to call updateGeometricState on the camera node before handling the keyboard input.

Ok, I change my update function, and it looks like that:


   protected void update(float interpolation) {
      //update the time to get the framerate
      timer.update();
      interpolation = timer.getTimePerFrame();
      
      scene.updateGeometricState(interpolation,true);

      //if escape was pressed, we exit
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
         finished = true;
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("test")) {
         rotate(); <- this call my rotate
      }

               // and few others keyboard input
      
   }



Is it ok?
I am asking because it didn't change much, still after I rotate my camera I cannot move correctly.

Could you post the entire code (or zip it and upload it someplace) so I can look at it further?

I use http://rifers.org/paste/ for pasting code online.

Ok, I have clear code from useless things, and here it is all for my question:


package testowy;

import java.net.URL;

import javax.swing.ImageIcon;

import mission.MissionOne;

import com.jme.animation.SpatialTransformer;
import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.InputSystem;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.intersection.PickResults;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.ImageBasedHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
 
public class Testowy extends BaseGame {
   
   int lookAt = 0;

   private Vector3f loc = new Vector3f(0.0f, 0.0f, 25.0f);
   private Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
   private Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
   private Vector3f dir = new Vector3f(0.0f, 0.0f, -1.0f);
   
   
   float moveX = 0.0f;
   float moveY = 0.0f;
   float moveZ = 0.0f;
   Vector3f CameraLoc = new Vector3f(moveX, moveY, moveZ);

   CameraNode cn;

   TerrainBlock tb;
   
   protected Timer timer;
   
   //Our camera object for viewing the scene
   private Camera cam;
   
   //the root node of the scene graph
   private Node scene;
   
   
   //display attributes for the window. We will keep these values
   //to allow the user to change them
   private int width, height, depth, freq;
   private boolean fullscreen;
 
   /*** Main entry point of the application */
   public static void main(String[] args) {
      Testowy app = new Testowy();
      //We will load our own "fantastic" Flag Rush logo. Yes, I'm an artist.
      app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG, Testowy.class.getClassLoader()
            .getResource("jmetest/data/images/FlagRush.png"));
      app.start();
   }
 
   /** During an update we only look for the escape button and update the timer
    * to get the framerate. */
   protected void update(float interpolation) {
      //update the time to get the framerate
      timer.update();
      interpolation = timer.getTimePerFrame();
   
      scene.updateGeometricState(interpolation,true);
      cn.updateGeometricState(interpolation,true);
      

      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
         finished = true;
      }
      
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("left")) {
         camLeft();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("right")) {
         camRight();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("forward")) {
         camForward();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("back")) {
         camBack();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("up")) {
         camUp();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("down")) {
         camDown();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateLeft")) {
         rotateLeft();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateRight")) {
         rotateRight();
      }
      
   }

   /******************* draws the scene graph *********************************/
protected void render(float interpolation) {
   //Clear the screen
   display.getRenderer().clearBuffers();
   display.getRenderer().draw(scene);
}
 
   /******************** initializes the display and camera. *******************/
   protected void initSystem() {
      //store the properties information
      width = properties.getWidth();
      height = properties.getHeight();
      depth = properties.getDepth();
      freq = properties.getFreq();
      fullscreen = properties.getFullscreen();
   
       timer = Timer.getTimer(); /** Get a high resolution timer for FPS updates. */
      
      try {
         display = DisplaySystem.getDisplaySystem(properties.getRenderer());
         display.createWindow(width, height, depth, freq, fullscreen);
 
         cam = display.getRenderer().createCamera(width, height);
      } catch (JmeException e) {
         e.printStackTrace();
         System.exit(1);
      }
 
      //set the background to black
      display.getRenderer().setBackgroundColor(ColorRGBA.black);
      
      InitCamera();
        display.getRenderer().setCamera(cam);
       
        checkInput();
   }
 
   /******************* initializes the scene ****************** */
   protected void initGame() {
      scene = new Node("Scene graph node");
      
        addBox();
        LoadingTerrain();
        InitCameraNode();
 
      //update the scene graph for rendering
      scene.updateGeometricState(0.0f, true);
      scene.updateRenderState();
   }
   /** **************************************************************/

   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
   }
 
   /** **************************************************************/
   protected void cleanup() {
      //ts.deleteAll();
   }

   /** **************************************************************/
   private void LoadingTerrain() {
        URL MapaTerenu=MissionOne.class.getClassLoader().getResource("mission/concrete.jpg");
        URL Trawa=MissionOne.class.getClassLoader().getResource("mission/grass.jpg");
        URL Kamien=MissionOne.class.getClassLoader().getResource("mission/skala.jpg");
        ImageBasedHeightMap ib=new ImageBasedHeightMap(
                new ImageIcon(MapaTerenu).getImage()
        );
        tb=new TerrainBlock("image icon",ib.getSize(),
                new Vector3f(1.0f,.05f,1.0f),ib.getHeightMap(),
                new Vector3f(0,0,0),false);
            ProceduralTextureGenerator pg=new ProceduralTextureGenerator(ib);
        pg.addTexture(new ImageIcon(Trawa),0,0,60);
        pg.addTexture(new ImageIcon(Kamien),40,256,256);

        pg.createTexture(256);
        TextureState ts=display.getRenderer().createTextureState();
        ts.setTexture(
                TextureManager.loadTexture(
                        pg.getImageIcon().getImage(),
                        Texture.MM_LINEAR_LINEAR,
                        Texture.FM_LINEAR,
                        true
                )
        );
        tb.setRenderState(ts);

        tb.setModelBound(new BoundingBox());
        tb.updateModelBound();

        tb.setLocalTranslation(new Vector3f(0,0,0));
        lookAt = ib.getSize()/2;
        scene.attachChild(tb);
    }
    /** **************************************************************/
   private void InitCamera() {
      
       cam = display.getRenderer().createCamera(
              display.getWidth(),
              display.getHeight());
        cam.setFrustumPerspective(45.0f,
                                (float) display.getWidth() /
                                (float) display.getHeight(), 1, 1000);
       
        // Move our camera to a correct place and orientation.
       cam.setFrame(loc, left, up, dir);
       cam.update();   
       }

   /** **************************************************************/    
   private void InitCameraNode() {
       cn = new CameraNode("Camera Node", cam);
       cn.setLocalTranslation(new Vector3f(0, 0, 0));
       cn.updateWorldData(0);
       scene.attachChild(cn);
   }

   /** **************************************************************/
   private void checkInput() {
         KeyBindingManager.getKeyBindingManager().set("exit",
               KeyInput.KEY_ESCAPE);
         
         KeyBindingManager.getKeyBindingManager().set("forward",
               KeyInput.KEY_W);
         
         KeyBindingManager.getKeyBindingManager().set("back",
               KeyInput.KEY_S);
         
         KeyBindingManager.getKeyBindingManager().set("right",
               KeyInput.KEY_D);
         
         KeyBindingManager.getKeyBindingManager().set("left",
               KeyInput.KEY_A);
         
         KeyBindingManager.getKeyBindingManager().set("up",
               KeyInput.KEY_R);
         
         KeyBindingManager.getKeyBindingManager().set("down",
               KeyInput.KEY_F);
         
         KeyBindingManager.getKeyBindingManager().set("rotateLeft",
               KeyInput.KEY_Q);
         
         KeyBindingManager.getKeyBindingManager().set("rotateRight",
               KeyInput.KEY_E);
      }
   /** **************************************************************/
   private void addBox() {
       Box b2=new Box("Blarg2",new Vector3f(-.5f,-.5f,-20.5f),new Vector3f(.5f,.5f,-19.5f));
        b2.setModelBound(new BoundingBox());
        b2.updateModelBound();
        scene.attachChild(b2);
   }
   /** **************************************************************/

   private void camDown() {
      CameraLoc = CameraLoc.add(0.0f, -0.1f, 0.0f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
      }

   private void camUp() {
      CameraLoc = CameraLoc.add(0.0f, 0.1f, 0.0f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
      }

   private void camBack() {
      CameraLoc = CameraLoc.add(0.0f, 0.0f, -0.1f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
   }

   private void camForward() {
      CameraLoc = CameraLoc.add(0.0f, 0.0f, 0.1f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
   }

   private void camRight() {
      CameraLoc = CameraLoc.add(-0.1f, 0.0f, 0.0f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
   }

   private void camLeft() {
      CameraLoc = CameraLoc.add(0.1f, 0.0f, 0.0f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
   }
   
   private void rotateLeft() {
      Quaternion x90 = new Quaternion();
      x90.fromAngleAxis(FastMath.DEG_TO_RAD*90,new Vector3f(0,1,0));
      cn.setLocalRotation( x90 );
   }
   
   private void rotateRight() {
      Quaternion x270 = new Quaternion();
      x270.fromAngleAxis(FastMath.DEG_TO_RAD*270,new Vector3f(0,1,0));
      cn.setLocalRotation( x270 );
   }

}



The controls are:
W, A, S, D - for moving
Q,E - rotate (left/right)
R, F - going up and down

i have an alternative approch which can work the same way u want but eaier to implement.



create a player node.



create a firstpersn view camera.



attach the first person view camera to the player node.



then move the player and the camera will follow. :smiley:

I see two problems:


  1. rotateLeft and rotateRight do not call cam.update() at the end.


  2. The rotation in these methods is absolute (90 or 170), what you want, is to add the rotation to the current rotation. You can do this with one auxiliary variable (cameraAngle or something like that), and do:


private void rotateLeft()
{
    Quaternion x90 = new Quaternion();
    cameraAngle += 10; //or 90 or whatever.
    x90.fromAngleAxis(FastMath.DEG_TO_RAD*cameraAngle,new Vector3f(0,1,0));
    cn.setLocalRotation( x90 );
    cam.update();
}



and likewise for rotateRight.

Hope it helps  ;)

Thanks for advice neakor, I was thinking about that solution, but still didn't try it.



duenez thx for advice, but this don't resolve problem, that when you rotate, and then push 'w' you will not go straight, but in other direction.

I would like to know how to rotate and still have w,a,s,d works correctly.

Yeah, yeah, you are right  :frowning: My fault!



Well I would suggest to do the following: Have the camera node be attached to another node, and perform rotations in that node, and translations in the camera.


scene.attachChild( camRotation );
camRotation.attachChild( cn );



This should do it.

np dude.



i just thought it would make more sense to move the actual object which then triggers the camera to follow.



coz after all, the camera is just a port to view.



good luck on ur game~and have fun with jme :smiley:

neakor: still long way… ;]



duenez: I have done like you said. I have create another node and attach camera node to it, and now when I'am rotating I am doing it on "camRotation", but when I'm pressing w,a,s,d I'm making translation of my "cn". Still didn't work :frowning:



Could you please look at it one more time?



package testowy;

import java.net.URL;

import javax.swing.ImageIcon;

import mission.MissionOne;

import com.jme.animation.SpatialTransformer;
import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.InputSystem;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.intersection.PickResults;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.ImageBasedHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
 
public class Testowy extends BaseGame {
   
   // poÅ‚owa szerokoÅ›ci kamery, sÅ‚uży do ustawienia kamery na Å›rodku
   int lookAt = 0;
   int cameraAngle = 0;

   //ustawienia kamery
   private Vector3f loc = new Vector3f(0.0f, 0.0f, 25.0f);
   private Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
   private Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
   private Vector3f dir = new Vector3f(0.0f, 0.0f, -1.0f);
   
   
   float moveX = 0.0f;
   float moveY = 0.0f;
   float moveZ = 0.0f;
   Vector3f CameraLoc = new Vector3f(moveX, moveY, moveZ);

   CameraNode cn;
   
    Node camRotation;

   TerrainBlock tb;
   
   protected Timer timer;
   
   //Our camera object for viewing the scene
   private Camera cam;
   
   //the root node of the scene graph
   private Node scene;
   
   
   //display attributes for the window. We will keep these values
   //to allow the user to change them
   private int width, height, depth, freq;
   private boolean fullscreen;
 
   /*** Main entry point of the application */
   public static void main(String[] args) {
      Testowy app = new Testowy();
      //We will load our own "fantastic" Flag Rush logo. Yes, I'm an artist.
      app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG, Testowy.class.getClassLoader()
            .getResource("jmetest/data/images/FlagRush.png"));
      app.start();
   }
 
   /** During an update we only look for the escape button and update the timer
    * to get the framerate. */
   protected void update(float interpolation) {
      //update the time to get the framerate
      timer.update();
      interpolation = timer.getTimePerFrame();
   
      scene.updateGeometricState(interpolation,true);
      
      

      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
         finished = true;
      }
      
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("left")) {
         camLeft();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("right")) {
         camRight();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("forward")) {
         camForward();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("back")) {
         camBack();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("up")) {
         camUp();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("down")) {
         camDown();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateLeft")) {
         rotateLeft();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateRight")) {
         rotateRight();
      }
      
   }
   /******************* draws the scene graph *********************************/
protected void render(float interpolation) {
   //Clear the screen
   display.getRenderer().clearBuffers();
   display.getRenderer().draw(scene);
}
 
   /******************** initializes the display and camera. *******************/
   protected void initSystem() {
      //store the properties information
      width = properties.getWidth();
      height = properties.getHeight();
      depth = properties.getDepth();
      freq = properties.getFreq();
      fullscreen = properties.getFullscreen();
   
       timer = Timer.getTimer(); /** Get a high resolution timer for FPS updates. */
      
      try {
         display = DisplaySystem.getDisplaySystem(properties.getRenderer());
         display.createWindow(width, height, depth, freq, fullscreen);
 
         cam = display.getRenderer().createCamera(width, height);
      } catch (JmeException e) {
         e.printStackTrace();
         System.exit(1);
      }
 
      //set the background to black
      display.getRenderer().setBackgroundColor(ColorRGBA.black);
      
      InitCamera();
        display.getRenderer().setCamera(cam);
       
        checkInput();
   }
 
   /******************* initializes the scene ****************** */
   protected void initGame() {
      scene = new Node("Scene graph node");
      
        addBox();
        LoadingTerrain();
        InitCameraNode();
       
 
      //update the scene graph for rendering
      scene.updateGeometricState(0.0f, true);
      scene.updateRenderState();
   }
   /** **************************************************************/

   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
   }
 
   /** **************************************************************/
   protected void cleanup() {
      //ts.deleteAll();
   }

   /** **************************************************************/
   private void LoadingTerrain() {
        URL MapaTerenu=MissionOne.class.getClassLoader().getResource("mission/concrete.jpg");
        URL Trawa=MissionOne.class.getClassLoader().getResource("mission/grass.jpg");
        URL Kamien=MissionOne.class.getClassLoader().getResource("mission/skala.jpg");
        ImageBasedHeightMap ib=new ImageBasedHeightMap(
                new ImageIcon(MapaTerenu).getImage()
        );
        tb=new TerrainBlock("image icon",ib.getSize(),
                new Vector3f(1.0f,.05f,1.0f),ib.getHeightMap(),
                new Vector3f(0,0,0),false);
            ProceduralTextureGenerator pg=new ProceduralTextureGenerator(ib);
        pg.addTexture(new ImageIcon(Trawa),0,0,60);
        pg.addTexture(new ImageIcon(Kamien),40,256,256);

        pg.createTexture(256);
        TextureState ts=display.getRenderer().createTextureState();
        ts.setTexture(
                TextureManager.loadTexture(
                        pg.getImageIcon().getImage(),
                        Texture.MM_LINEAR_LINEAR,
                        Texture.FM_LINEAR,
                        true
                )
        );
        tb.setRenderState(ts);

        tb.setModelBound(new BoundingBox());
        tb.updateModelBound();

        tb.setLocalTranslation(new Vector3f(0,0,0));
        lookAt = ib.getSize()/2;
        scene.attachChild(tb);
    }
    /** **************************************************************/
   private void InitCamera() {
      
       cam = display.getRenderer().createCamera(
              display.getWidth(),
              display.getHeight());
        cam.setFrustumPerspective(45.0f,
                                (float) display.getWidth() /
                                (float) display.getHeight(), 1, 1000);
       
        // Move our camera to a correct place and orientation.
       cam.setFrame(loc, left, up, dir);
       cam.update();   
       }

   /** **************************************************************/    
   private void InitCameraNode() {
       cn = new CameraNode("Camera Node", cam);
       cn.setLocalTranslation(new Vector3f(0, 0, 0));
       cn.updateWorldData(0);
       scene.attachChild(cn);
      
       camRotation = new Node("jakis");
        scene.attachChild( camRotation );
        camRotation.attachChild( cn );
          
   }

   /** **************************************************************/
   private void checkInput() {
         KeyBindingManager.getKeyBindingManager().set("exit",
               KeyInput.KEY_ESCAPE);
         
         KeyBindingManager.getKeyBindingManager().set("forward",
               KeyInput.KEY_W);
         
         KeyBindingManager.getKeyBindingManager().set("back",
               KeyInput.KEY_S);
         
         KeyBindingManager.getKeyBindingManager().set("right",
               KeyInput.KEY_D);
         
         KeyBindingManager.getKeyBindingManager().set("left",
               KeyInput.KEY_A);
         
         KeyBindingManager.getKeyBindingManager().set("up",
               KeyInput.KEY_R);
         
         KeyBindingManager.getKeyBindingManager().set("down",
               KeyInput.KEY_F);
         
         KeyBindingManager.getKeyBindingManager().set("rotateLeft",
               KeyInput.KEY_Q);
         
         KeyBindingManager.getKeyBindingManager().set("rotateRight",
               KeyInput.KEY_E);
      }
   /** **************************************************************/
   private void addBox() {
       Box b2=new Box("Blarg2",new Vector3f(-.5f,-.5f,-20.5f),new Vector3f(.5f,.5f,-19.5f));
        b2.setModelBound(new BoundingBox());
        b2.updateModelBound();
        scene.attachChild(b2);
   }
   /** **************************************************************/

   private void camDown() {
      CameraLoc = CameraLoc.add(0.0f, -0.1f, 0.0f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
      }

   private void camUp() {
      CameraLoc = CameraLoc.add(0.0f, 0.1f, 0.0f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
      }

   private void camBack() {
      CameraLoc = CameraLoc.add(0.0f, 0.0f, -0.1f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
   }

   private void camForward() {
      CameraLoc = CameraLoc.add(0.0f, 0.0f, 0.1f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
   }

   private void camRight() {
      CameraLoc = CameraLoc.add(-0.1f, 0.0f, 0.0f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
   }

   private void camLeft() {
      CameraLoc = CameraLoc.add(0.1f, 0.0f, 0.0f);
      cn.setLocalTranslation(CameraLoc);
      cam.update();
   }
   
   private void rotateLeft() {
      Quaternion x = new Quaternion();
       cameraAngle += 1; //or 90 or whatever.
       x.fromAngleAxis(FastMath.DEG_TO_RAD*cameraAngle,new Vector3f(0,1,0));
       camRotation.setLocalRotation( x );
       cam.update();
   }
   
   private void rotateRight() {
      Quaternion x = new Quaternion();
       cameraAngle -= 1; //or 90 or whatever.
       x.fromAngleAxis(FastMath.DEG_TO_RAD*cameraAngle,new Vector3f(0,1,0));
       camRotation.setLocalRotation( x );
       cam.update();
   }

}



OK… two problems detected, and I think this time it will work!  :wink:


  1. You forgot to remove the line to attach cn to the scene. (commented here)

    private void InitCameraNode()
    {
        cn = new CameraNode("Camera Node", cam);
        cn.setLocalTranslation(new Vector3f(0, 0, 0));
        cn.updateWorldData(0);
        //scene.attachChild(cn);
       
        camRotation = new Node("jakis");
        scene.attachChild( camRotation );
        camRotation.attachChild( cn );
        scene.updateGeometricState(0, true);
    }



2) Now that you have two nodes, it is not sufficient to call cam.update(), you need to call

scene.updateGeometricState( 0, true );


at the end of all your rotation and movement calls. (It should be sufficient to call it on camRotation or cn depending on what you change, but you could try that yourself).

Hope this is now working.  XD

Thats it!

Love you guys :smiley:



Big thanks for help.

ok i made some small changes, but this code does what u want. u can rotate the cam, u can move it backward and forward.



since i dont have ur missionone file, so i commented out the terrain part and create my own terrain. but u can change that back.



have fune~ :smiley:



package test;

import java.net.URL;

import javax.swing.ImageIcon;

import com.jme.animation.SpatialTransformer;
import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.InputSystem;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.intersection.PickResults;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.HillHeightMap;
import com.jmex.terrain.util.ImageBasedHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;

public class Testowy extends BaseGame {
   
   int lookAt = 0;

   private Vector3f loc = new Vector3f(0.0f, 0.0f, 25.0f);
   private Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
   private Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
   private Vector3f dir = new Vector3f(0.0f, 0.0f, -1.0f);
   
   
   float moveX = 0.0f;
   float moveY = 0.0f;
   float moveZ = 0.0f;
   Vector3f CameraLoc = new Vector3f(moveX, moveY, moveZ);

   Node node = new Node("holder");
   CameraNode cn;

   TerrainBlock tb;
   
   protected Timer timer;
   
   //Our camera object for viewing the scene
   private Camera cam;
   
   //the root node of the scene graph
   private Node scene;
   
   
   //display attributes for the window. We will keep these values
   //to allow the user to change them
   private int width, height, depth, freq;
   private boolean fullscreen;

   /*** Main entry point of the application */
   public static void main(String[] args) {
      Testowy app = new Testowy();
      //We will load our own "fantastic" Flag Rush logo. Yes, I'm an artist.
      app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG, Testowy.class.getClassLoader()
            .getResource("jmetest/data/images/FlagRush.png"));
      app.start();
   }

   /** During an update we only look for the escape button and update the timer
   * to get the framerate. */
   protected void update(float interpolation) {
      //update the time to get the framerate
      timer.update();
      interpolation = timer.getTimePerFrame();
   
      scene.updateGeometricState(interpolation,true);
      cn.updateGeometricState(interpolation,true);
      

      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
         finished = true;
      }
      
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("left")) {
         camLeft();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("right")) {
         camRight();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("forward")) {
         camForward();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("back")) {
         camBack();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("up")) {
         camUp();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("down")) {
         camDown();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateLeft")) {
         rotateLeft();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateRight")) {
         rotateRight();
      }
      
   }

   /******************* draws the scene graph *********************************/
protected void render(float interpolation) {
   //Clear the screen
   display.getRenderer().clearBuffers();
   display.getRenderer().draw(scene);
}

   /******************** initializes the display and camera. *******************/
   protected void initSystem() {
      //store the properties information
      width = properties.getWidth();
      height = properties.getHeight();
      depth = properties.getDepth();
      freq = properties.getFreq();
      fullscreen = properties.getFullscreen();
   
       timer = Timer.getTimer(); /** Get a high resolution timer for FPS updates. */
      
      try {
         display = DisplaySystem.getDisplaySystem(properties.getRenderer());
         display.createWindow(width, height, depth, freq, fullscreen);

         cam = display.getRenderer().createCamera(width, height);
      } catch (JmeException e) {
         e.printStackTrace();
         System.exit(1);
      }

      //set the background to black
      display.getRenderer().setBackgroundColor(ColorRGBA.black);
      
      InitCamera();
        display.getRenderer().setCamera(cam);
       
        checkInput();
   }

   /******************* initializes the scene ****************** */
   protected void initGame() {
      scene = new Node("Scene graph node");
      
        addBox();
        LoadingTerrain();
        InitCameraNode();

      //update the scene graph for rendering
      scene.updateGeometricState(0.0f, true);
      scene.updateRenderState();
   }
   /** **************************************************************/

   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
   }

   /** **************************************************************/
   protected void cleanup() {
      //ts.deleteAll();
   }

   /** **************************************************************/
   private void LoadingTerrain() {
        /*URL MapaTerenu=MissionOne.class.getClassLoader().getResource("mission/concrete.jpg");
        URL Trawa=MissionOne.class.getClassLoader().getResource("mission/grass.jpg");
        URL Kamien=MissionOne.class.getClassLoader().getResource("mission/skala.jpg");
        ImageBasedHeightMap ib=new ImageBasedHeightMap(
                new ImageIcon(MapaTerenu).getImage()
        );
        tb=new TerrainBlock("image icon",ib.getSize(),
                new Vector3f(1.0f,.05f,1.0f),ib.getHeightMap(),
                new Vector3f(0,0,0),false);
            ProceduralTextureGenerator pg=new ProceduralTextureGenerator(ib);
        pg.addTexture(new ImageIcon(Trawa),0,0,60);
        pg.addTexture(new ImageIcon(Kamien),40,256,256);

        pg.createTexture(256);
        TextureState ts=display.getRenderer().createTextureState();
        ts.setTexture(
                TextureManager.loadTexture(
                        pg.getImageIcon().getImage(),
                        Texture.MM_LINEAR_LINEAR,
                        Texture.FM_LINEAR,
                        true
                )
        );
        tb.setRenderState(ts);

        tb.setModelBound(new BoundingBox());
        tb.updateModelBound();

        tb.setLocalTranslation(new Vector3f(0,0,0));
        lookAt = ib.getSize()/2;
        scene.attachChild(tb);*/
      HillHeightMap heightMap = new HillHeightMap(129, 2000, 5.0f, 20.0f,
            (byte) 2);
      heightMap.setHeightScale(0.001f);
      Vector3f terrainScale = new Vector3f(10, 1, 10);
      TerrainPage terrain = new TerrainPage("Terrain", 33, heightMap
            .getSize(), terrainScale, heightMap.getHeightMap(), false);
      terrain.setDetailTexture(1, 16);
      scene.attachChild(terrain);
   }
    /** **************************************************************/
   private void InitCamera() {
      
      cam = display.getRenderer().createCamera(
              display.getWidth(),
              display.getHeight());
        cam.setFrustumPerspective(45.0f,
                                (float) display.getWidth() /
                                (float) display.getHeight(), 1, 1000);
       
        // Move our camera to a correct place and orientation.
      cam.setFrame(loc, left, up, dir);
      cam.update();   
      }

   /** **************************************************************/    
   private void InitCameraNode() {
      cn = new CameraNode("Camera Node", cam);
      node.attachChild(cn);
      node.setLocalTranslation(new Vector3f(0, 0, 0));
      cn.updateWorldData(0);
      scene.attachChild(node);
   }

   /** **************************************************************/
   private void checkInput() {
         KeyBindingManager.getKeyBindingManager().set("exit",
               KeyInput.KEY_ESCAPE);
         
         KeyBindingManager.getKeyBindingManager().set("forward",
               KeyInput.KEY_W);
         
         KeyBindingManager.getKeyBindingManager().set("back",
               KeyInput.KEY_S);
         
         KeyBindingManager.getKeyBindingManager().set("right",
               KeyInput.KEY_D);
         
         KeyBindingManager.getKeyBindingManager().set("left",
               KeyInput.KEY_A);
         
         KeyBindingManager.getKeyBindingManager().set("up",
               KeyInput.KEY_R);
         
         KeyBindingManager.getKeyBindingManager().set("down",
               KeyInput.KEY_F);
         
         KeyBindingManager.getKeyBindingManager().set("rotateLeft",
               KeyInput.KEY_Q);
         
         KeyBindingManager.getKeyBindingManager().set("rotateRight",
               KeyInput.KEY_E);
      }
   /** **************************************************************/
   private void addBox() {
       Box b2=new Box("Blarg2",new Vector3f(-.5f,-.5f,-20.5f),new Vector3f(.5f,.5f,-19.5f));
        b2.setModelBound(new BoundingBox());
        b2.updateModelBound();
        scene.attachChild(b2);
   }
   /** **************************************************************/

   private void camDown() {
      Vector3f change = new Vector3f(0.0f, -0.1f, 0.0f);
      node.getLocalTranslation().addLocal(change);      
      cam.update();
      }

   private void camUp() {
      Vector3f change = new Vector3f(0.0f, 0.1f, 0.0f);
      node.getLocalTranslation().addLocal(change);   
      cam.update();
      }

   private void camBack() {
      Vector3f change = new Vector3f(0.0f, 0.0f, -0.1f);
      node.getLocalTranslation().addLocal(change);   
      cam.update();
   }

   private void camForward() {
      Vector3f change = new Vector3f(0.0f, 0.0f, 0.1f);
      node.getLocalTranslation().addLocal(change);   
      cam.update();
   }

   private void camRight() {
      Vector3f change = new Vector3f(-0.1f, 0.0f, 0.0f);
      node.getLocalTranslation().addLocal(change);   
      cam.update();
   }

   private void camLeft() {
      Vector3f change = new Vector3f(0.1f, 0.0f, 0.0f);
      node.getLocalTranslation().addLocal(change);   
      cam.update();
   }
   
   private void rotateLeft() {
      Quaternion x90 = new Quaternion();
      x90.fromAngleAxis(FastMath.DEG_TO_RAD*90,new Vector3f(0,1,0));
      node.setLocalRotation( x90 );
   }
   
   private void rotateRight() {
      Quaternion x270 = new Quaternion();
      x270.fromAngleAxis(FastMath.DEG_TO_RAD*270,new Vector3f(0,1,0));
      node.setLocalRotation( x270 );
   }

}

I would like to make some changes to how this camera rotates.



when you run this code, then go back (S) and little up ®, you will see that when you try to rotate (Q,E), it rotates but not like it should. It looks that all world rotate but note this node which I was hoping camera will be.



Could anyone help me, and tell what's wrong with this code?

that was a long time ago, but with what code?

this code which is in your post, check how it rotate.