Camera threejs:向对象平滑旋转摄影机

Camera threejs:向对象平滑旋转摄影机,camera,rotation,quaternions,Camera,Rotation,Quaternions,我刚刚开始学习three.js,我在编写一个函数时遇到了一些麻烦,该函数以对象位置(Vector3)和毫秒为参数,并在该时间内逐渐旋转相机以面对它。实际上是内置lookAt方法的lerp版本 首先,我尝试使用tweenjs来获得平滑的旋转过渡。对于“开始”和“结束”参数,我创建了一个虚拟对象,并将其位置、旋转和四元数设置为与摄影机相同,然后使用其上的lookAt函数面向对象,并将其四元数存储在一个新变量“targetQuaternion”中。然后我在TWEEN.TWEEN方法中使用这个变量作为目

我刚刚开始学习three.js,我在编写一个函数时遇到了一些麻烦,该函数以对象位置(Vector3)和毫秒为参数,并在该时间内逐渐旋转相机以面对它。实际上是内置lookAt方法的lerp版本

首先,我尝试使用tweenjs来获得平滑的旋转过渡。对于“开始”和“结束”参数,我创建了一个虚拟对象,并将其位置、旋转和四元数设置为与摄影机相同,然后使用其上的lookAt函数面向对象,并将其四元数存储在一个新变量“targetQuaternion”中。然后我在TWEEN.TWEEN方法中使用这个变量作为目标参数来更新camera.quaternion。我以前试过用四元数来避免gymbal锁定,然后用旋转,但没有一个效果好

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

所以这是行不通的

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

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

这也不起作用,最终摄影机会朝着对象旋转,但旋转不正确

有什么帮助吗?相机具有lerp旋转功能的正确方法是什么


提前谢谢

您是否更新了动画循环中的吐温

function animate() {
    requestAnimationFrame( animate );

    TWEEN.update();

    render();
}
不过,最好使用四元数而不是旋转来转动对象,以防止万向节锁定。THREE.js提供了一个方便的函数来使用球面线性插值(slerp),而不是使用tween(lerp),后者会给您带来不想要的结果,尤其是在180度转弯时。将其放入动画循环中

camera.quaternion.slerp(targetQuaternion,t); //t = normalized value 0 to 1
然后,您可以在t之间穿行,以获得所需的放松