Proper FirstPersonController


I just cant figure out how to attach a spatial to the FirstPersonController.

I can get the direction right, but not the angles, i.e. if you look up, the object wont follow.

Is there a way to make it follow, or if I could possible request a feature to add an attachChild to a firstPersonNode() typa thing?

FirstPersonController controls soley the camera. That is the camera object. There is a controller called NodeController that controls spatials. There is also a CameraNode that you can use if you want to attach something to the camera. Not quite sure what you are trying to do, but using those might get you closer. Let me know if it doesn’t.

you know in games like Medal Of Honour, or Call of Duty, the gun is attached to the camera, wherever the camera go, the gun goes.

I wanna do that, I would like to attach a spatial to a camera. I thought the FirstPersonController might do it, but im wrong.

Would cameraNode be any good?

Yeah, Camera Node is what you want.

You’d create a camera.

Create a camera node using the camera.

Create NodeController and set the camera node as the spatial to control.

Create the gun object.

Attach it as a child to the camera node.

make it’s local translation such that it is in front of the camera where you want it.

Now, you are the first to attempt this, so let me know if you run into any problems or things dont work like you’d like them to.

right, go as far as attaching the gun to the cameraNode. But how?

actually, dont dignify that question with an answer!! ://

CameraNode is a Spatial object, you can attach anything to it just as you would any other node.


il have to finish this off on sunday, i have work tomorrow (its 00:18 am here!) and I need to go to sleep.

Adios amigo

righty…so i have this code, can you seen if there is anything wrong with it? or am i just simply missing the point?

import com.jme.input.FirstPersonController;
import com.jme.input.InputController;
import com.jme.input.NodeController;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.LWJGLCamera;
import com.jme.scene.Box;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.Timer;

 * @author Ahmed
public class FirstPerson extends AbstractGame{
   private Node root, scene;
   private Camera cam;
   private CameraNode camnode;
   private Vector3f camPos;
   private TriMesh box;
   private Timer timer;
   private InputController input;
   private NodeController nodeC;

   protected void update() {
      input.update(timer.getTimePerFrame() * 7);
      camnode.setLocalTranslation(new Vector3f(1, 1, 1));

   protected void render() {

   protected void initSystem() {
      try {
         if ("LWJGL".equalsIgnoreCase(properties.getRenderer())) {
            display = DisplaySystem.getDisplaySystem("LWJGL");

         cam =
            new LWJGLCamera(properties.getWidth(), properties.getHeight());
      } catch (JmeException jmeE) {

      display.getRenderer().setBackgroundColor(new ColorRGBA(0, 0, 0, 1));

      cam.setFrustum(1f, 1000f, -0.55f, 0.55f, 0.4125f, -0.4125f);
      Vector3f loc = new Vector3f(4, 0, 0);
      Vector3f left = new Vector3f(0, -1, 0);
      Vector3f up = new Vector3f(0, 0, 1f);
      Vector3f dir = new Vector3f(-1, 0, 0);

      cam.setFrame(loc, left, up, dir);
      camnode = new CameraNode(cam);

      timer = Timer.getTimer("LWJGL");
      nodeC = new NodeController(this, camnode, "LWJGL");
      input = new FirstPersonController(this, cam, "LWJGL");

   protected void initGame() {
      Vector3f min = new Vector3f(-0.1f, -0.1f, -0.1f);
      Vector3f max = new Vector3f(0.1f, 0.1f, 0.1f);
      camPos = new Vector3f(0, 0, 0);
      box = new Box(min.mult(5f), max.mult(5f));
      root = new Node();
      scene = new Node();
      ZBufferState buf = display.getRenderer().getZBufferState();
      scene.updateGeometricState(0.0f, true);

   protected void reinit() {

   protected void cleanup() {

   public static void main(String[] args) {
      FirstPerson app = new FirstPerson();

is this whats supposed to happen or not?

I’ll look into it now…

You are the first person to try doing this, including me. So, there very well could be a bug. It might not be working how I designed it. So, I’ll play with it some and let you know what I find.

Ok, there is definately a design flaw. Let me look into it and figure out how it should be and fix it. Sorry about that.

thx mojomonk. lol, two bugs now? im getting embarrassed. Dark, DO NOT DISCOVER ANYMORE BUGS IN JME, YOU HEAR?

Well, this is good that you are finding them. I having been getting a little lax on my tests. Basically, just testing the most general part of the things, so I miss quite a bit. More bugs found now, less there will be when it matters. Not sure how long it will take to track this one down. I might have to rewrite some of CameraNode, so you might want to move on to something else for the time being.

Sorry it took so long for me to get to this, but check:


I just committed some changes to it into CVS.

Is this what you were wanting?

thats exactly what I was looking for, thx mojomonkey

A little tidbit of info that might help you.

When you use a CameraNode, it uses a node’s translation and rotation to determine position and orientation. Rotation is defined with identity as:

1 0 0

0 1 0

0 0 1

The first column denotes left, second up and third dir. So this gives you an orientation of:



| / +Z

| /

| /



> -X

So positioning "HUD" geometry will require you to think this way. So, out and to the right is (-1, 0, 1).

kewlies…thats even easier to use…cause its almost as identical as normal axis that we are getting taught!

Great, I just wanted to let you know, because the dir, up and left that you set when you create the camera are overridden by these values. I should document this.

all thats between me and my glorious 3D asteroids game is Model Loading and animation, and collisions.

Collision is in, bounding volume collision (not triangle accuracy), but that might be accurate enough for your needs. An asteroid is pretty spherical, as is a bullet as is a space ship.

Model Loading (Milkshape does work), just not the animations.

Animations are kicking my ass right now. :wink: