一、摘要
分析了OrbitControl的基本原理。
二、資源
源碼地址:
三、分析
最外層框架:OrbitControl 為函數對象,原型處理
THREE.OrbitControls = function ( object , domElement){ ... } THREE.OrbitControls.protorype = Object.create ( THREE.EventDispatcher.prototype);
object : 控制的對象
domElement : 3D模型控制范圍 , 缺省為document 。
接下去開始是一些變量定義以及函數定義,看旋轉實現即
this.domElement.addEventListener( 'mousedown', onMouseDown, false );
onMouseDown函數處理:捕捉event.button時間(0|1|2)分別對(left|middle|right),對應事件(rotate|zoom|pan)
if ( event.button === 0 ) { if ( scope.noRotate === true ) return; state = STATE.ROTATE; rotateStart.set( event.clientX, event.clientY ); } else{ ..... } scope.domElement.addEventListener( 'mousemove', onMouseMove, false ); scope.domElement.addEventListener( 'mouseup', onMouseUp, false ); scope.dispatchEvent( startEvent );
變量說明:
scope = this;
rotateStart , rotateEnd 為Vector2。記錄當前二維坐標為初始終止點。
增加監聽mousemove,mouseup。
mousemove事件onMouseMove:
if ( state === STATE.ROTATE ) { if ( scope.noRotate === true ) return; rotateEnd.set( event.clientX, event.clientY ); rotateDelta.subVectors( rotateEnd, rotateStart ); // rotating across whole screen goes 360 degrees around scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); rotateStart.copy( rotateEnd ); } else{ ... } scope.update();
鼠標移動中,記錄當前坐標為rotateEnd,計算start與End差為rotateDelta。rotateLeft與rotateUp將二維差值記錄到 角度差值 thetaDelta 與 phiDelta中。
代碼中可以看到thetaDelta 與x方向偏移的,phidelta與y偏移成正比。直觀得想,x方向移動即讓物體沿經度大圓的旋轉,過中心繞Y軸。y方向即物體的上下旋轉。
接下來就是theta 和 phi 的問題。高中立體幾何基本知識了。theta和phi就是下面2個角度了。
重點在於scope.update.
update做的主要事情也就幾件
重新計算theta和phi,計算移動后的三維坐標。控制旋轉。之后可加上自己對旋轉角度的控制。
theta += thetaDelta;
phi += phiDelta;
加上pan改變target的位置,調整位置。
// move target to panned location this.target.add( pan ); offset.x = radius * Math.sin( phi ) * Math.sin( theta ); offset.y = radius * Math.cos( phi ); offset.z = radius * Math.sin( phi ) * Math.cos( theta ); position.copy( this.target ).add( offset ); this.object.lookAt( this.target );
四、總結
OrbitControl處理比較好理解,ThrackballControl.js的方式好像是放在一個半斤為1的球上來控制。
