javascriptthree.jsorbit

three.js(version 102) How to set default position & rotation of camera with OrbitControls


I create a scene, and it is all fine without using OrbitControls. When I use OrbitControls, I found that my camera's position and rotation has changed, and I can't modify it.

Can somebody tell me how to set a default position and rotation of the camera with OrbitControls.

Thanks! three.js - OrbitControls


Solution

  • OrbitControls require a target. Set the target such that you get the same view.

      camera.position.set(1, 8, 7);
    
      const controls = new THREE.OrbitControls(camera, canvas);
      controls.target.set(0, 3, 0);
      controls.update();  
    

    'use strict';
    
    /* global THREE */
    
    function main() {
      const canvas = document.querySelector('#c');
      const renderer = new THREE.WebGLRenderer({canvas: canvas});
    
      const fov = 75;
      const aspect = 2;  // the canvas default
      const near = 0.1;
      const far = 500;
      const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
      camera.position.set(1, 8, 7);
      
      const controls = new THREE.OrbitControls(camera, canvas);
      controls.target.set(0, 3, 0);
      controls.update();  
    
      const scene = new THREE.Scene();
    
      {
        const color = 0xFFFFFF;
        const intensity = 1;
        const light = new THREE.DirectionalLight(color, intensity);
        light.position.set(-1, 2, 4);
        scene.add(light);
      }
    
      {
        const boxWidth = 1;
        const boxHeight = 10;
        const boxDepth = 1;
        const geometry = new THREE.BoxBufferGeometry(boxWidth, boxHeight, boxDepth);
        const material = new THREE.MeshPhongMaterial({color: 'red'});
    
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);
        cube.position.y = .5;
      }
      
      {
        const geometry = new THREE.PlaneBufferGeometry(10, 10);
        const material = new THREE.MeshPhongMaterial({color: 'gray'});
    
        const plane = new THREE.Mesh(geometry, material);
        scene.add(plane);
        plane.rotation.x = Math.PI * -0.5;
      }
    
      function resizeRendererToDisplaySize(renderer) {
        const canvas = renderer.domElement;
        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        const needResize = canvas.width !== width || canvas.height !== height;
        if (needResize) {
          renderer.setSize(width, height, false);
        }
        return needResize;
      }
    
      function render(time) {
        if (resizeRendererToDisplaySize(renderer)) {
          const canvas = renderer.domElement;
          camera.aspect = canvas.clientWidth / canvas.clientHeight;
          camera.updateProjectionMatrix();
        }
    
        renderer.render(scene, camera);
    
        requestAnimationFrame(render);
      }
    
      requestAnimationFrame(render);
    }
    
    main();
    body { margin: 0; }
    #c { width: 100vw; height: 100vh; display: block; }
    <canvas id="c"></canvas>
    <script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/three.min.js"></script>
    <script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/js/controls/OrbitControls.js"></script>

    Or you could compute a target based on the current camera view. The OrbitControls orbit around the target so you'd need to choose a distance from the camera as your target

      const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
      camera.position.set(1, 2, 5);
      camera.rotation.set(.1, .2, 0);
    
      // get the direction of the camera
      const direction = new THREE.Vector3();
      camera.getWorldDirection(direction);
    
      const controls = new THREE.OrbitControls(camera, canvas);
    
      // point the target from the camera in the
      // target direction
      camera.getWorldPosition(controls.target);
      controls.target.addScaledVector(direction, 5);
      controls.update();  
    

    Note the 5 in addScaledVector means the target will be 5 units in front of the camera in the direction the camera was facing. Whether 5 is the right distance is up to you. In my sample scene the camera started at z = 5 so 5 units in front of the camera seemed like a reasonable place to put the target

    'use strict';
    
    /* global THREE */
    
    function main() {
      const canvas = document.querySelector('#c');
      const renderer = new THREE.WebGLRenderer({canvas: canvas});
    
      const fov = 75;
      const aspect = 2;  // the canvas default
      const near = 0.1;
      const far = 500;
      const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
      camera.position.set(1, 2, 5);
      camera.rotation.set(.1, .2, 0);
    
      // compute a target direction
      const direction = new THREE.Vector3();
      camera.getWorldDirection(direction);
    
      const controls = new THREE.OrbitControls(camera, canvas);
      // point the target from the camera in the
      // target direction
      camera.getWorldPosition(controls.target);
      controls.target.addScaledVector(direction, 5);
      controls.update();  
    
      const scene = new THREE.Scene();
    
      {
        const color = 0xFFFFFF;
        const intensity = 1;
        const light = new THREE.DirectionalLight(color, intensity);
        light.position.set(-1, 2, 4);
        scene.add(light);
      }
    
      {
        const boxWidth = 1;
        const boxHeight = 10;
        const boxDepth = 1;
        const geometry = new THREE.BoxBufferGeometry(boxWidth, boxHeight, boxDepth);
        const material = new THREE.MeshPhongMaterial({color: 'red'});
    
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);
        cube.position.y = .5;
      }
      
      {
        const geometry = new THREE.PlaneBufferGeometry(10, 10);
        const material = new THREE.MeshPhongMaterial({color: 'gray'});
    
        const plane = new THREE.Mesh(geometry, material);
        scene.add(plane);
        plane.rotation.x = Math.PI * -0.5;
      }
    
      function resizeRendererToDisplaySize(renderer) {
        const canvas = renderer.domElement;
        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        const needResize = canvas.width !== width || canvas.height !== height;
        if (needResize) {
          renderer.setSize(width, height, false);
        }
        return needResize;
      }
    
      function render(time) {
        if (resizeRendererToDisplaySize(renderer)) {
          const canvas = renderer.domElement;
          camera.aspect = canvas.clientWidth / canvas.clientHeight;
          camera.updateProjectionMatrix();
        }
    
        renderer.render(scene, camera);
    
        requestAnimationFrame(render);
      }
    
      requestAnimationFrame(render);
    }
    
    main();
    body { margin: 0; }
    #c { width: 100vw; height: 100vh; display: block; }
    <canvas id="c"></canvas>
    <script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/three.min.js"></script>
    <script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/js/controls/OrbitControls.js"></script>