How to control camera.position.x from dat.GUI

I’ve made a test page that uses a dat.GUI to edit various properties of a PerspectiveCamera.

The PerspectiveCamera has a helper so I can see what’s going on, plus the scene has xyz axes in RGB colours.

Using the gui to update near, far, aspect & fov all work fine.

The problem is with testPerspectiveCamera.position.x

My code to update from the gui is as follows

function initGui(){
  const controls = {
    get near(){return testPerspectiveCamera.near;},
    set near(value){
      testPerspectiveCamera.near = value;
      testPerspectiveCamera.updateProjectionMatrix();
      testPerspectiveCameraHelper.update();
    },
    get far(){return testPerspectiveCamera.far;},
    set far(value){
      testPerspectiveCamera.far = value;
      testPerspectiveCamera.updateProjectionMatrix();
      testPerspectiveCameraHelper.update();
    },
    get aspect(){return testPerspectiveCamera.aspect;},
    set aspect(value){
      testPerspectiveCamera.aspect = value;
      testPerspectiveCamera.updateProjectionMatrix();
      testPerspectiveCameraHelper.update();
    },
    get fov(){return testPerspectiveCamera.fov;},
    set fov(value){
      testPerspectiveCamera.fov = value;
      testPerspectiveCamera.updateProjectionMatrix();
      testPerspectiveCameraHelper.update();
    },
    get positionX(){return testPerspectiveCamera.position.x;},
    set positionX(value){
      testPerspectiveCamera.position.x = value;
      scene.updateMatrixWorld();                         //?
      testPerspectiveCamera.updateProjectionMatrix();    //?
      testPerspectiveCameraHelper.update();              //?
    }
  };
  const gui = new dat.GUI();
  const perspectiveCameraFolder  = gui.addFolder('testPerspectiveCamera');
  perspectiveCameraFolder.add(controls, 'near', 0, 50);
  perspectiveCameraFolder.add(controls, 'far', 0, 200);
  perspectiveCameraFolder.add(controls, 'aspect', 0, 4);
  perspectiveCameraFolder.add(controls, 'fov', 0, 100);
  perspectiveCameraFolder.add(controls, 'positionX', -LIMIT, LIMIT);
}

On attempting to change testPerspectiveCamera.position.x, I see no change in the scene. I’m wondering if the matrix operations after updating x are wrong.

Could anyone tell me what I’m doing wrong?

Fiddle here: https://jsfiddle.net/fiddleuser01/0fsqogb1/49/

Using the same technique to control the position of a cube via a gui seems to work fine: https://jsfiddle.net/fiddleuser01/rezcpgh4/7/

Hey there,

I am also not an expert here but:
Your helper can´t access this cameras transform information…
I see two options

  1. add this camera to the scene graph like this:
testPerspectiveCamera = new THREE.PerspectiveCamera( 45, 2, 20, 100);
scene.add(testPerspectiveCamera)

or 2. update this cameras worldMatrix like this:

testPerspectiveCamera.position.x = value;
testPerspectiveCamera.updateWorldMatrix()
1 Like

I seem to have found the cause of the problem. After updating testPerspectiveCamera.position.x, testPerspectiveCamera.updateMatrixWorld(); was required.

    function initGui(){
      const controls = {
        get near(){return testPerspectiveCamera.near;},
        set near(value){
          testPerspectiveCamera.near = value;
          testPerspectiveCamera.updateProjectionMatrix();
          testPerspectiveCameraHelper.update();
        },
        get far(){return testPerspectiveCamera.far;},
        set far(value){
          testPerspectiveCamera.far = value;
          testPerspectiveCamera.updateProjectionMatrix();
          testPerspectiveCameraHelper.update();
        },
        get aspect(){return testPerspectiveCamera.aspect;},
        set aspect(value){
          testPerspectiveCamera.aspect = value;
          testPerspectiveCamera.updateProjectionMatrix();
          testPerspectiveCameraHelper.update();
        },
        get fov(){return testPerspectiveCamera.fov;},
        set fov(value){
          testPerspectiveCamera.fov = value;
          testPerspectiveCamera.updateProjectionMatrix();
          testPerspectiveCameraHelper.update();
        },
        get positionX(){return testPerspectiveCamera.position.x;},
        set positionX(value){
          testPerspectiveCamera.position.x = value;
          testPerspectiveCamera.updateMatrixWorld();
        },
        get positionY(){return testPerspectiveCamera.position.y;},
        set positionY(value){
          testPerspectiveCamera.position.y = value;
          testPerspectiveCamera.updateMatrixWorld();
        },
        get positionZ(){return testPerspectiveCamera.position.z;},
        set positionZ(value){
          testPerspectiveCamera.position.z = value;
          testPerspectiveCamera.updateMatrixWorld();
        }
      };
      const gui = new GUI();
      const perspectiveCameraFolder  = gui.addFolder('testPerspectiveCamera');
      perspectiveCameraFolder.add(controls, 'near', 0, 50);
      perspectiveCameraFolder.add(controls, 'far', 0, 200);
      perspectiveCameraFolder.add(controls, 'aspect', 0, 4);
      perspectiveCameraFolder.add(controls, 'fov', 0, 100);
      perspectiveCameraFolder.add(controls, 'positionX', -LIMIT, LIMIT);
      perspectiveCameraFolder.add(controls, 'positionY', -LIMIT, LIMIT);
      perspectiveCameraFolder.add(controls, 'positionZ', -LIMIT, LIMIT);
    }

Demo here: https://mytestpages.com/three/update-perspective-camera-from-gui.html

I’ll put the demo back on jsfiddle once I find out how I’ve managed to lock myself out of my account!

2 Likes

Hi @Drumstructor

Looks like I just posted at the same moment as you.

Experimenting with all the methods that looked potentially relevant, I found that the same one as you just gave me seems to work.

Bit hit and miss. I need to learn a bit of matrix maths here.

Thanks for your help.

1 Like

no worries…

have a look at the helpers code: three.js/CameraHelper.js at 1c1ddb397591bb1894225227debd1b82a03d59e9 · mrdoob/three.js · GitHub

it says that the helper and its cameras world matrix must be identical.
Since world matrices do not auto update, you have to update them by yourself by one of many solutions.

1 Like