javascript 三.JS Orbit Controls - 启用和禁用无位置跳跃

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23596249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 01:11:23  来源:igfitidea点击:

Three.JS Orbit Controls - enabling and disabling without position jumping

javascriptthree.js

提问by moczys

I am creating a geometry manipulation prototype with Three.JS. I am using OrbitControls.JS to manipulate the camera and am having trouble enabling and disabling the controls.

我正在用 Three.JS 创建一个几何操作原型。我正在使用 OrbitControls.JS 来操纵相机,但在启用和禁用控件时遇到了问题。

Here is my demo: http://moczys.com/webGL/Prototype_V02-05.html

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

The idea is that when you hover over a vertex of the Tetrahedron, a grey sphere appears. By clicking on the sphere, you bring up a vertex manipulation handle. Then by clicking an dragging on an arrow, you can move the vertex in that direction. You should then be able to click away from the geometry to get out of this mode.

这个想法是,当您将鼠标悬停在四面体的顶点上时,会出现一个灰色球体。通过单击球体,可以调出顶点操作手柄。然后通过单击箭头上的拖动,您可以沿该方向移动顶点。然后,您应该能够在远离几何体的地方单击以退出此模式。

The problem occurs when you click away. If you click & drag after moving the vertex, the camera goes a little crazy. Depending on how far away from the original point you are, the OrbitControls will spin the camera a distance in that direction. This is just a really jarring/confusing action that really impacts the usability, so I'd like to fix it, but can't seem to locate the problem.

当您单击离开时会出现问题。如果在移动顶点后单击并拖动,相机会变得有点疯狂。根据您离原点的距离有多远,OrbitControls 将在该方向上旋转相机一段距离。这只是一个真正影响可用性的非常刺耳/令人困惑的操作,所以我想修复它,但似乎无法找到问题所在。

I think that it is recording the initial position in the OrbitControls.js, and then keeping that until they are re-enabled... however I haven't been able to figure out where. This occurs somewhere in the MouseUp, MouseDown, and MouseMove event handlers. I was hoping this might be interesting to someone who might know more about the operation of OrbitControls than I do.

我认为它正在记录 OrbitControls.js 中的初始位置,然后保持它直到它们被重新启用......但是我一直无法弄清楚在哪里。这发生在 MouseUp、MouseDown 和 MouseMove 事件处理程序中的某处。我希望这对那些可能比我更了解 OrbitControls 操作的人会很有趣。

And here is my clicking/dragging event handler code:

这是我的单击/拖动事件处理程序代码:

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

}

I'd love to hear any suggestions that people might have, thanks!

我很想听听人们可能有的任何建议,谢谢!

回答by moczys

UPDATE Q1 2019

2019 年第一季度更新

noRotateis now deprecated, use enableRotateinstead.

noRotate现在已弃用,请enableRotate改用。



I figured it out! After looking closer at OrbitControls.JS, there is a "noRotate" flag that can be set that returns out of the rotate function, completely eliminating the creation of a start vector like I was talking about above.

我想到了!在仔细查看 OrbitControls.JS 之后,可以设置一个“noRotate”标志,该标志可以从旋转函数中返回,完全消除了像我上面所说的那样创建起始向量。

Here is the working demo: http://moczys.com/webGL/Prototype_V02-05-2.html

这是工作演示:http: //moczys.com/webGL/Prototype_V02-05-2.html

And here is the code with changes commented:

这是注释了更改的代码:

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;

}

Hope somebody finds this useful!

希望有人觉得这很有用!

回答by vals

I haven't been able to test it, but I think that you code should be

我还没有能够测试它,但我认为你的代码应该是

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
    }
}