threejs:将摄像头朝对象平滑旋转 [英] threejs: smoothly rotate camera towards an object

查看:2082
本文介绍了threejs:将摄像头朝对象平滑旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始研究three.js,但是我在编写一个函数时遇到了一些麻烦,该函数将对象位置(Vector3)和一个时间(以毫秒为单位)作为参数,然后逐渐旋转相机使其在该时间内面对它。

i have just started to study three.js and i am having some trouble to write a function that takes as arguments an object position (Vector3) and a time in milliseconds, and gradually rotate the camera to face it in that time. Substantially a lerp version of the builtin lookAt method.

首先,我尝试使用tweenjs获得平滑的旋转过渡。对于开始和结束参数,我创建了一个虚拟对象,并将其位置,旋转和四元数设置为与相机相同,然后使用其上的lookAt函数面向该对象,并将其四元数存储在新变量 targetQuaternion。然后,我已将此变量用作TWEEN.Tween方法中的目标参数来更新camera.quaternion。我曾经尝试过使用四元数来避免健身房锁定,然后再进行旋转,但是都无法正常工作。

First i've tried using tweenjs to get smooth rotate transition. For the start and end parameters i've created a dummy object and set its position, rotation and quaternion the same as the camera, then i have use the lookAt function on it to face towards the object and i've stored its quaternion in a new variable "targetQuaternion". Then i have used this variable as the target parameter in the TWEEN.Tween method to update camera.quaternion. I've tried before with quaternions to avoid gymbal lock and then with rotation, but none works fine.

function rotateCameraToObject(object3D, time) {

var cameraPosition = camera.position.clone();               // camera original position
var cameraRotation = camera.rotation.clone();               // camera original rotation
var cameraQuaternion = camera.quaternion.clone();           // camera original quaternion

var dummyObject = new THREE.Object3D();                     // dummy object


// set dummyObject's position, rotation and quaternion the same as the camera
dummyObject.position.set(cameraPosition.x, cameraPosition.y, cameraPosition.z);
dummyObject.rotation.set(cameraRotation.x, cameraRotation.y, cameraRotation.z);
dummyObject.quaternion.set(cameraQuaternion.x, cameraQuaternion.y, cameraQuaternion.z);


// lookAt object3D
dummyObject.lookAt(object3D);

// store its quaternion in a variable
var targetQuaternion = dummyObject.quaternion.clone();


// tween start object
var tweenStart = {
    x: cameraQuaternion.x,
    y: cameraQuaternion.y,
    z: cameraQuaternion.z,
    w: cameraQuaternion.w
};

//tween target object
var tweenTarget = {
    x: targetQuaternion.x,
    y: targetQuaternion.y,
    z: targetQuaternion.z,
    w: targetQuaternion.w
};

// tween stuff
var tween = new TWEEN.Tween(tweenStart).to(tweenTarget, time);

tween.onUpdate(function() {
    camera.quaternion.x = tweenStart.x;
    camera.quaternion.y = tweenStart.y;
    camera.quaternion.z = tweenStart.z;
    camera.quaternion.w = tweenStart.w;
});

tween.start();

}

所以这不起作用

我还尝试了另一种方法,计算摄像机矢量和物体矢量之间的角度,并将该角度用作目标旋转:

I've also tried another approach, computing the angle between camera vector and object vector and use that angle as target rotation:

function rotateCameraToObject(object3D, time) {

// camera original position
var cameraPosition = camera.position.clone();

// object3D position
var objectPosition = object3D.position.clone();

// direction vector from camera towards object3D
var direction = objectPosition.sub(cameraPosition);

// compute Euler angle
var angle = new THREE.Euler();
angle.setFromVector3(direction);


/*
 * tween stuff    
 */
var start = {
    x: camera.rotation.clone().x,
    y: camera.rotation.clone().y,
    z: camera.rotation.clone().z,
}

var end = {
    x: angle._x,
    y: angle._y,
    z: angle._z,
}

var tween = new TWEEN.Tween(start).to(end, time);

tween.onUpdate(function() {
    camera.rotation.y = start.x;
    camera.rotation.y = start.y;
    camera.rotation.y = start.z;
});

tween.start();    

}

这不起作用两者都不是,最终摄像机朝着对象旋转,但是旋转不正确。

This doesn't work neither, eventually camera rotate towards the object but the rotation is not right.

有帮助吗?为相机提供拉环旋转功能的正确方法是什么?

Any help? What is the correct way to have a lerp rotate function for the camera?

预先感谢!

推荐答案

您是否已在动画循环中更新了补间?

Have you updated the tween in your animation loop?

function animate() {
    requestAnimationFrame( animate );

    TWEEN.update();

    render();
}

不过,最好使用四元数而不是旋转来旋转对象-防止万向节锁定。 THREE.js提供了一个方便的函数来使用球面线性插值(slerp),而不是使用补间(lerp),后者可能会给您带来不良结果,尤其是在180度转弯时。

However it's probably better to use the quaternion and not the rotation to turn objects - prevents gimbal lock. THREE.js provides a handy function to use spherical linear interpolation (slerp) as opposed to using tween (lerp) which can give you undesired results, most notably at a 180 deg turn. Put this in your animation loop.

camera.quaternion.slerp(targetQuaternion,t); //t = normalized value 0 to 1

然后可以补间 t 为您提供所需的放松。

You could then tween t to give you your desired easing.

这篇关于threejs:将摄像头朝对象平滑旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆