Fez Vrasta
Fez Vrasta

Reputation: 14815

Rotate camera around object with Three.js

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?

Upvotes: 19

Views: 49141

Answers (7)

joox
joox

Reputation: 253

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

Upvotes: 5

sam
sam

Reputation: 969

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

Upvotes: 1

Ray Hulha
Ray Hulha

Reputation: 11221

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.

Upvotes: 2

Ertugrul Yakin
Ertugrul Yakin

Reputation: 1

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();

Upvotes: 0

Hitesh Sahu
Hitesh Sahu

Reputation: 45042

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();
}

Upvotes: 0

Matthew Riches
Matthew Riches

Reputation: 2286

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.)

Upvotes: 37

Ideogram
Ideogram

Reputation: 1365

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)

Upvotes: 1

Related Questions