2014-05-11 107 views
5

我正在用Three.JS創建一個幾何操作原型。我使用OrbitControls.JS來操作相機,並且無法啓用和禁用控件。Three.JS軌道控制 - 無位置跳躍啓用和禁用

這裏是我的演示: http://moczys.com/webGL/Prototype_V02-05.html

的想法是,當你將鼠標懸停在四面體的頂點,將出現一個灰色球體。通過點擊球體,您可以調出一個頂點操作手柄。然後通過單擊拖動箭頭,可以沿該方向移動頂點。然後,您應該能夠從幾何體中單擊以離開此模式。

當您單擊時發生問題。如果在移動頂點後點擊&拖動,相機會有點瘋狂。根據距離原點的距離,OrbitControls會在相同的方向上旋轉相機一段距離。這只是一個真正震動/混淆的行爲,它會影響可用性,所以我想解決它,但似乎無法找到問題所在。

我認爲它是在OrbitControls.js中記錄初始位置,然後保持這個狀態,直到它們重新啓用......但是我一直無法弄清楚在哪裏。這發生在MouseUp,MouseDown和MouseMove事件處理程序的某處。我希望對於那些可能比我更瞭解OrbitControls的操作的人來說,這可能會很有趣。

這裏是我的點擊/拖動事件處理代碼:

function onDocumentMouseMove(event) 
{ 
// the following line would stop any other event handler from firing 
// (such as the mouse's TrackballControls) 
//event.preventDefault(); 

// update the mouse variable 
mouse.x = (event.clientX/window.innerWidth) * 2 - 1; 
mouse.y = - (event.clientY/window.innerHeight) * 2 + 1; 

if(MOUSEDOWN&&editMode==2) 
{ 
    var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5); 
    projector.unprojectVector(vector, camera); 

    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); 
    //lastPoint = vertexIntersects[0].object; 
    var instance = vertexTargets.indexOf(lastPoint); 
    if(vertexEdit==1){ 
     var intersects = raycaster.intersectObject(XYplane); 

     vertexTargets[instance].position.x=intersects[0].point.x; 
     targetList[0].geometry.vertices[instance].x=intersects[0].point.x; 
     //console.log("x = "+intersects[0].point.x); 
    } 
    else if(vertexEdit==2){ 
     var intersects = raycaster.intersectObject(XYplane); 
     vertexTargets[instance].position.y=intersects[0].point.y; 
     targetList[0].geometry.vertices[instance].y=intersects[0].point.y; 
     //console.log("y = "+intersects[0].point.y); 
    } 
    else if(vertexEdit==3){ 
     var intersects = raycaster.intersectObject(YZplane); 
     vertexTargets[instance].position.z=intersects[0].point.z; 
     targetList[0].geometry.vertices[instance].z=intersects[0].point.z; 
     //console.log("z = "+intersects[0].point.z); 
    } 
    setAxisPosition(vertexTargets[instance].position.clone()); 
    var geom = targetList[0].geometry; 
    geom.computeCentroids(); 
    geom.computeFaceNormals(); 
    geom.computeVertexNormals(); 
    geom.verticesNeedUpdate = true; 
    geom.normalsNeedUpdate = true; 
    updatePanels(targetList[0]); 

    } 
} 


function onDocumentMouseDown(event) 
{ 
// the following line would stop any other event handler from firing 
// (such as the mouse's TrackballControls) 
// event.preventDefault(); 

//console.log("Click."); 
MOUSEDOWN = true; 
// update the mouse variable 
mouse.x = (event.clientX/window.innerWidth) * 2 - 1; 
mouse.y = - (event.clientY/window.innerHeight) * 2 + 1; 

checkSelection(); 
if(editMode==2){ 
    controls.enabled = false; 
    controls.rotate = false; 
} 
else{ 
    controls.enabled = true; 
    controls.rotate = true; 
} 

} 

function onDocumentMouseUp(event) 
{ 
//event.preventDefault(); 
if (editMode!=2){ 
    controls.enabled = true; 
    controls.rotate = true; 
} 
MOUSEDOWN = false; 
if(editMode==2){ 
    //editMode=1; 
    //updateVertexTargets(targetList[0].geometry); 
} 

} 

我很樂意聽到任何建議,人們可能有,謝謝!

回答

8

我想通了!在仔細觀察OrbitControls.JS之後,可以設置一個「noRotate」標誌,該標誌可以從循環函數中返回,完全消除了像我上面提到的那樣創建一個開始向量。

這裏的工作演示: http://moczys.com/webGL/Prototype_V02-05-2.html

這裏是有改動的代碼註釋:

function onDocumentMouseMove(event) 
{ 
// the following line would stop any other event handler from firing 
// (such as the mouse's TrackballControls) 
//event.preventDefault(); 

// update the mouse variable 
mouse.x = (event.clientX/window.innerWidth) * 2 - 1; 
mouse.y = - (event.clientY/window.innerHeight) * 2 + 1; 


if(MOUSEDOWN&&editMode==2) 
{ 
// Added to stop rotation while moving a vertex with the arrow handles 
    controls.noRotate = true; 

    var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5); 
    projector.unprojectVector(vector, camera); 

    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); 
    //lastPoint = vertexIntersects[0].object; 
    var instance = vertexTargets.indexOf(lastPoint); 
    if(vertexEdit==1){ 
     var intersects = raycaster.intersectObject(XYplane); 

     vertexTargets[instance].position.x=intersects[0].point.x; 
     targetList[0].geometry.vertices[instance].x=intersects[0].point.x; 
     //console.log("x = "+intersects[0].point.x); 
    } 
    else if(vertexEdit==2){ 
     var intersects = raycaster.intersectObject(XYplane); 
     vertexTargets[instance].position.y=intersects[0].point.y; 
     targetList[0].geometry.vertices[instance].y=intersects[0].point.y; 
     //console.log("y = "+intersects[0].point.y); 
    } 
    else if(vertexEdit==3){ 
     var intersects = raycaster.intersectObject(YZplane); 
     vertexTargets[instance].position.z=intersects[0].point.z; 
     targetList[0].geometry.vertices[instance].z=intersects[0].point.z; 
     //console.log("z = "+intersects[0].point.z); 
    } 
    setAxisPosition(vertexTargets[instance].position.clone()); 
    var geom = targetList[0].geometry; 
    geom.computeCentroids(); 
    geom.computeFaceNormals(); 
    geom.computeVertexNormals(); 
    geom.verticesNeedUpdate = true; 
    geom.normalsNeedUpdate = true; 
    updatePanels(targetList[0]); 

} 
} 


function onDocumentMouseDown(event) 
{ 
// the following line would stop any other event handler from firing 
// (such as the mouse's TrackballControls) 
// event.preventDefault(); 

//console.log("Click."); 
MOUSEDOWN = true; 
// update the mouse variable 
mouse.x = (event.clientX/window.innerWidth) * 2 - 1; 
mouse.y = - (event.clientY/window.innerHeight) * 2 + 1; 

checkSelection(); 
if(editMode==2){ 
    //controls.enabled = false; 
    //controls.rotate = false; 

// Added here to disable rotation when the arrow handles are active 
    controls.noRotate = true; 
} 
else{ 
    //controls.enabled = true; 
    //controls.rotate = true; 

// Added here to enable rotation all other times 
    controls.noRotate = false; 
} 

} 

function onDocumentMouseUp(event) 
{ 
//event.preventDefault(); 
if (editMode!=2){ 
    //controls.enabled = true; 
    //controls.rotate = true; 
} 
MOUSEDOWN = false; 

// add here to enable rotation whenever the mouse button is lifted 
controls.noRotate = false; 

} 

希望有人認爲這有用!

+0

非常有用!把我以爲會成爲令人頭疼的事情給我留下了深刻的印象。謝謝! – AndroidNoobie

+0

謝謝,這很有用。我注意到軌道控制的變焦繼續工作。 – steveOw

0

我一直無法對其進行測試,但我認爲你的代碼應該是

function onDocumentMouseDown(event) 
{ 
// the following line would stop any other event handler from firing 
// (such as the mouse's TrackballControls) 
// event.preventDefault(); 

//console.log("Click."); 
MOUSEDOWN = true; 
// update the mouse variable 
mouse.x = (event.clientX/window.innerWidth) * 2 - 1; 
mouse.y = - (event.clientY/window.innerHeight) * 2 + 1; 

checkSelection(); 
    if(editMode==2){ 
     controls.enabled = false; 
     controls.rotate = false; 
    }else{ 
     controls.enabled = true; 
     controls.rotate = true; 
     controls.onMouseDown (event); // added this line to set the correct state 
    } 
} 
+0

嗯...這似乎沒有做任何事情。它看起來不像你可以從函數外調用它,因爲它會拋出一個錯誤,並說它的未定義。 – moczys