[英]Three.JS Orbit Controls - enabling and disabling without position jumping
我正在用Three.JS創建一個幾何操作原型。 我正在使用OrbitControls.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);
}
}
我很想聽聽人們可能提出的任何建議,謝謝!
更新2019年第一季度
現在不推薦使用noRotate
,而是使用enableRotate
。
我想到了! 仔細觀察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;
}
希望有人覺得這很有用!
我無法測試它,但我認為你的代碼應該是
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
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.