How to rotate the camera around an object in Three.js?

You need to write an algorithm for rotating and moving the camera around the object. I tried using sinuses and cosines , but it didn't work. Is there any library on this topic? I will also be happy to just give hints in the construction of the algorithm Thank you in advance.

Camera.position.x = Math.cos(camera.degree) * 1100;

Camera.position.z = Math.sin(camera.degree) * 1100;

Camera.lookAt(new THREE.Vector3(0, 0, 0));

Render.render(scene, camera);

  • where camera.degree is the angle to rotate the camera relative to the object, determined by the coordinate differences in the mousemove event.
Author: Chamond, 2017-01-12

2 answers

To set a stable angular velocity, we need an object THREE.Clock() (documentation).

Then everything is more or less simple:

var clock = new THREE.Clock();
var angle = 0; // текущий угол
var angularSpeed = THREE.Math.degToRad(20); // угловая скорость - градусов в секунду
var delta = 0;
var radius = 20;
function animate() {
  delta = clock.getDelta(); // getDelta() - возвращает интервал в долях секунды
  requestAnimationFrame(animate);

  camera.position.x = Math.cos(angle) * radius;
  camera.position.z = Math.sin(angle) * radius;
  angle += angularSpeed * delta; // приращение угла

  camera.lookAt(mesh.position);

  renderer.render(scene, camera);
}

Jsfiddle example

Another option, if you need to organize the rotation via mouse control, then using OrbitControls will do.

Everything you need for this:

Create a control object

var controls = new THREE.OrbitControls(camera, renderer.domElement);

In the case that you want the rotation around the object to be only horizontal, then you need to limit the minimum and maximum vertical rotation angles, since they can be within [0 .. Math.PI], then half of 180 degrees (Math.PI) will be 90 (Math. PI / 2)

controls.minPolarAngle = Math.PI / 2;
controls.maxPolarAngle = Math.PI / 2;

After that, in the animation loop, you can add

controls.update();

Jsfiddle example

 2
Author: prisoner849, 2017-01-13 15:41:25

I will explain the mat part:

This is

camera.position.x = Math.cos(camera.degree) * 1100;
camera.position.z = Math.sin(camera.degree) * 1100;

The parametric equation of the circle, so the camera constantly rotates in the same plane around the axis Y describing the circle on the sphere.

If you need to move around the sphere, then you need to apply the parametric equation of the sphere, where the radius is the distance from the camera to the point at which it looks, and the center is the beginning of the coordinate in the world system( world space), in other words (0, 0, 0).

But it is necessary to take into account that In webgl (opengl), the notation for coordinate axes differs from the standard mathematical notation.

In webgl (x+ - to the right, y+ - to the top, z+ - to itself).

In mathematics, most often (x+ - to the right, y+ - to yourself, z+ - to the top).

Therefore, the equation will be different.

Example in jsfiddle

And then

let camera, scene, renderer, light, cube, sphere;
let cameraParams = {
    distance: 1,
    mdown: new THREE.Vector2(),
    mmove: new THREE.Vector2(),
    phi: 25,
    theta: -15,
    phim: 0,
    thetam: 0,
    fov: 53
};
let updateCamera = function() {
    camera.position.x = cameraParams.distance * Math.sin(cameraParams.theta * degToRad) * Math.cos(cameraParams.phi * degToRad);
    camera.position.y = cameraParams.distance * Math.sin(cameraParams.phi * degToRad);
    camera.position.z = cameraParams.distance * Math.cos(cameraParams.theta * degToRad) * Math.cos(cameraParams.phi * degToRad);

    camera.lookAt(cube.position);
};
const degToRad = Math.PI / 180;

function init() {
    renderer = new THREE.WebGLRenderer({
        antialias: true
    });
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(50.0, window.innerWidth / window.innerHeight, 0.1, 1000);
    renderer.setClearColor(0xffffff);
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
}

function initScene() {
    let cubeGeom = new THREE.BoxGeometry(60, 60, 60);
    let cubeMat = new THREE.MeshPhongMaterial({
        color: 0xaa0000
    });
    cube = new THREE.Mesh(cubeGeom, cubeMat);
    cube.position.set(-100, 0, 0);
    scene.add(cube);

    let sphereGeom = new THREE.SphereGeometry(45, 60, 60);
    let sphereMat = new THREE.MeshPhongMaterial({
        color: 0x0000ff
    });
    sphere = new THREE.Mesh(sphereGeom, sphereMat);
    sphere.position.set(100, 0, 0);
    scene.add(sphere);

    let plane = new THREE.GridHelper(250, 25);
    scene.add(plane);

    light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(-25, 50, 50);
    scene.add(camera);
    camera.add(light);

    camera.position.set(0, 0, 500);
    cameraParams.distance = camera.position.clone().sub(cube.position).length();
    updateCamera();
}

function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

document.onmousedown = function(e) {
    cameraParams.mdown.set(e.clientX, e.clientY);
    cameraParams.thetam = cameraParams.theta;
    cameraParams.phim = cameraParams.phi;

    document.onmousemove = function(e) {
        cameraParams.mmove.set(e.clientX, e.clientY);
        cameraParams.theta = -(cameraParams.mmove.x - cameraParams.mdown.x) * 0.5 + cameraParams.thetam;
        cameraParams.phi = (cameraParams.mmove.y - cameraParams.mdown.y) * 0.5 + cameraParams.phim;
        cameraParams.phi = Math.min(90, Math.max(-90, cameraParams.phi));

        updateCamera();
    };

    document.onmouseup = function(e) {
        document.onmousemove = null;
    };
};



init();
initScene();
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.min.js"></script>
 2
Author: ampawd, 2017-01-13 15:45:09