19

I'm displaying an OBJ element with Three.js using WebGlRenderer, now I'd like to allow users to rotate the camera around the object in any direction, I've found this answer:

Rotate camera in Three.js with mouse

But both examples return me errors, the first says that projector is not defined, and I don't know what it means with "projector". I've just a simple camera, the object and some light. The second code says that undefined is not a function.

Does someone know how to get the result I need?

7 Answers 7

37

This is what you want: http://threejs.org/examples/misc_controls_orbit.html

Include the orbit controls (after you have downloaded them):

<script src="js/controls/OrbitControls.js"></script>

Setup the variable:

var controls;

Attach the controls to the camera and add a listener:

controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );

and in your animate function update the controls:

controls.update();

[Update] controls.autoRotate = true; (tested in v73. Recent versions of OrbitControls.js has added this control.)

Sign up to request clarification or add additional context in comments.

9 Comments

Thank you but now is the item that rotates around the camera... how can I invert the behavior? thanks
@FezVrasta You can choose what to orbit so instead of camera you can put an object in there if you like for example "sphere" so it would be: new THREE.OrbitControls( sphere );
Thanks but I can't make it works, I use this code to load the OBJ: jsfiddle.net/7aqmB but if I use object in OrbitControls it says that object is undefined...
It's not necessary to write controls.addEventListener( 'change', render ); in the code. The library is doing it itself. And controls.update() must be inside the function render(){...}, NOT in the function animate(){...}
... even is not necessary to use controls.update() in render(). It will work.
|
5

If you don't want to mess with OrbitControls, simply add the camera to a boom Group

  const boom = new THREE.Group();
  boom.add(camera);
  scene.add(boom);
  camera.position.set( 0, 0, 100 ); // this sets the boom's length 
  camera.lookAt( 0, 0, 0 ); // camera looks at the boom's zero

then you can rotate this boom instead of the camera itself.

  boom.rotation.x += 0.01;

You may want to add some extra objects, like lights etc. to this boom, btw

Comments

2

Here is a quick hack, in case you don't want to use the OrbitControls for some reason.

            camera.position.copy( target );
            camera.position.x+=Math.sin(camera.rotationy)*3;
            camera.position.z+=Math.cos(camera.rotationy)*3;
            camera.position.y+=cameraHeight; // optional
            tempVector.copy(target).y+=cameraHeight; // the += is optional
            camera.lookAt( tempVector );

camera.rotationy is a copy of the mouse rotation value since we are changing it with the call to lookAt.

Comments

1

Indeed, if you substitute 'camera' with the object of your choice, the object will rotate. But if there are other objects surrounding it (for example a grid on the floor), they will still stand still. That might be what you want, or it might look weird. (Imagine a chair rotating floating above the floor...?)

I choose to override the center object from OrbitControls.JS from my code after initializing the Orbit Controls

controls = new THREE.OrbitControls(camera, renderer.domElement);
…
controls.center =  new THREE.Vector3(
    chair.position.x,
    chair.position.y,
    chair.position.z
);

(disclaimer: I have the impression there are different versions of OrbitControls.js around, but I assume they all use this center-object)

Comments

1

If you are using ES6, following could be used for OrbitControls

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

// this would create the orbit controls
// it would allow camera control using mouse
const orbitControls = new OrbitControls(camera, renderer.domElement);

If you need autorotate,

function init() {
  ...

  // following would enable autorotate
  const orbitControls.autoRotate = true;

  ..
}

function animate() {
  // need to update the orbitcontrols for autorotate camera to take effect
  orbitControls.update();

  ...
  renderer.render( scene, camera );
  requestAnimationFrame( animate );
}

For ref: https://threejs.org/docs/#examples/en/controls/OrbitControls

Comments

0

Add a listener to trigger render method on change of OrbitControl:

    const controls = new OrbitControls(camera, this.renderer.domElement);
    controls.enableDamping = true;   //damping 
    controls.dampingFactor = 0.25;   //damping inertia
    controls.enableZoom = true;      //Zooming
    controls.autoRotate = true;       // enable rotation
    controls.maxPolarAngle = Math.PI / 2; // Limit angle of visibility

   controls.addEventListener("change", () => {
      if (this.renderer) this.renderer.render(this.scene, camera);
    });

and in animate update controls:

  start = () => {
    if (!this.frameId) {
      this.frameId = requestAnimationFrame(this.animate);
    }
  };
  stop = () => {
    cancelAnimationFrame(this.frameId);
  };

  renderScene = () => {
    if (this.renderer) this.renderer.render(this.scene, camera);
  };


animate = () => {
    // update controls
    controls.update();
}

Comments

0

Extra info for who looking auto rotate direction change on a limit:

if (
   controls.getAzimuthalAngle() >= Math.PI / 2 ||
   controls.getAzimuthalAngle() <= -Math.PI / 2
 ) {
   controls.autoRotateSpeed *= -1;
 }

 controls.update();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.