2013-08-23 81 views
2

在Three.js中,我想讓攝像頭看着場景中的物體,當我點擊另一個物體時,讓攝像機平穩地旋轉以查看新物體。 (即賦予相機旋轉動畫效果)。如何在three.js中動畫相機以查看對象?

從來就在SO檢查,這是最類似的問題:

Three.js How to use quaternion to rotate camera

我也試着在這個website修改代碼,我設法讓這樣的事情http://jsfiddle.net/F7Bh3/

var quat0 = mesh2.quaternion; 
var eye = mesh2.position; 
var center = mesh.position; 
var mat = new THREE.Matrix4(); 
mat.lookAt(center, eye, new THREE.Vector3(0,1,0)); 
var quat1 = new THREE.Quaternion(); 
quat1.setFromRotationMatrix(mat); 

var qm = new THREE.Quaternion(); 

deltaTheta = angleBetweenQuats(quat0,quat1); 
var frac = 0.2/deltaTheta; 
if (frac>1) frac=1; 

mesh2.quaternion.slerp(quat1,frac); 
mesh2.quaternion.normalize(); 

但是當我試圖旋轉相機而不是對象時,我所得到的全部是:http://jsfiddle.net/5Peq9/1/

我錯過了什麼?在此先感謝

+0

對於相同問題的更詳細的答案,看看這裏:http://stackoverflow.com/questions/14567712/how-to-animate-camera-lookat-using-three-js – kjyv

回答

7

我設法使用四元數在three.js中平滑地動畫相機。我花了一段時間才弄明白,但一旦完成,觀察四元數是如何工作的很好。

的方法是:

  • 存儲初始四元數
  • 定義目標四元數的吐溫
  • 期間從0
  • 吐溫東西1
  • 插值四元數的每一幀上應用內插四元數回到相機每幀

而且一個簡單的例子的代碼的關鍵部分:

var camera  // camera 
var cameraPos0 // initial camera position 
var cameraUp0 // initial camera up 
var cameraZoom // camera zoom 
var iniQ   // initial quaternion 
var endQ   // target quaternion 
var curQ   // temp quaternion during slerp 
var vec3   // generic vector object 
var tweenValue // tweenable value 

// init camera 
function setup() 
{ 
    camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 1, 2000) 
    camera.position = new THREE.Vector3(0, 0, 80) 
    cameraPos0 = camera.position.clone() 
    cameraUp0 = camera.up.clone() 
    cameraZoom = camera.position.z 
} 

// set a new target for the camera 
function moveCamera(euler, zoom) 
{ 
    // reset everything 
    endQ = new THREE.Quaternion() 
    iniQ = new THREE.Quaternion().copy(camera.quaternion) 
    curQ = new THREE.Quaternion() 
    vec3 = new THREE.Vector3() 
    tweenValue = 0 

    endQ.setFromEuler(euler) 
    TweenLite.to(this, 5, { tweenValue:1, cameraZoom:zoom, onUpdate:onSlerpUpdate }) 
} 

// on every update of the tween 
function onSlerpUpdate() 
{ 
    // interpolate quaternions with the current tween value 
    THREE.Quaternion.slerp(iniQ, endQ, curQ, tweenObj.value) 

    // apply new quaternion to camera position 
    vec3.x = cameraPos0.x 
    vec3.y = cameraPos0.y 
    vec3.z = cameraZoom 
    vec3.applyQuaternion(curQ) 
    camera.position.copy(vec3) 

    // apply new quaternion to camera up 
    vec3 = cameraUp0.clone() 
    vec3.applyQuaternion(curQ) 
    camera.up.copy(vec3) 
} 

的最後一步是尋找目標Euler旋轉傳遞給moveCamera。在我的情況下,我使用TrackballControls來尋找一些有趣的相機位置/旋轉,然後用euler = camera.rotation.clone()檢索它們並將其作爲目標傳遞。例如:

moveCamera(new THREE.Euler(2.20, -0.15, 0.55), 120) 

這種方法的應用可以在這裏看到:http://brunoimbrizi.com/experiments/#/08

0

相機有它自己的LookAt方法。我懷疑這是因爲相機的lookAt邏輯與兩個3d物體的邏輯稍有不同,因爲相機的運動會反過來影響渲染視圖(向右移動相機,並且場景看起來向左移動),所以需要反向思考或者隱藏該反向邏輯的特定方法。

我建議你試試相機的外觀。

+0

嗯,我試過相機在提出這個問題之前,先看一下方法。看着我的問題是相機立即改變其旋轉角度,我想要的是將相機從一個物體旋轉到另一個物體的動畫。儘管感謝您的回答。 – EduG

+2

怎麼樣這個問題: 1)使相機矩陣 2)使用相機的lookAt生成目標矩陣 3)用分解矩陣日常在三到兩個矩陣分解成他們的翻譯,季,和等級表組件。 4)使用tween.js插入兩個分解矩陣的值之間。 完成。 –

2

對於使用Tween.js庫的:我適應imbrizi的例子旋轉一組對象。同樣可以應用於相機。

function tweenRotation(targetQuaternion, duration){ 
    //tweens between zero and 1 values along Quaternion's SLERP method (http://threejs.org/docs/#Reference/Math/Quaternion) 

    qm = new THREE.Quaternion(); //initiate an empty Qt to be filled by the .slerp function 
    curQuaternion = group.quaternion; //the starting point of your rotation 

    var tween = new TWEEN.Tween({t:0}).to({t:1}, duration) 
     .easing(TWEEN.Easing.Quadratic.InOut) 
     .onUpdate(function(){ 
      THREE.Quaternion.slerp(curQuaternion, targetQuaternion, qm, this.t); 
      qm.normalize(); 
      group.rotation.setFromQuaternion(qm); 
    }); 

    tween.start(); 
} 

我原本使用Tween.js原始和目標矢量之間補間,和所使用的group.lookat(向量)函數在在每一步補間向量指向的對象。但是我發現它會產生不穩定的結果,特別是當原始和目標載體接近反平行時。這種使用球面線性插值(slerp)的方法給了我更平滑的結果。