简体   繁体   English

Three.JS轨道控制 - 无需位置跳跃即可启用和禁用

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

I am creating a geometry manipulation prototype with Three.JS. 我正在用Three.JS创建一个几何操作原型。 I am using OrbitControls.JS to manipulate the camera and am having trouble enabling and disabling the controls. 我正在使用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. 根据您与原始点的距离,OrbitControls会将相机旋转一段距离。 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. 这只是一个非常刺耳/混乱的行为,真正影响可用性,所以我想解决它,但似乎无法找到问题。

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. 我认为它是在OrbitControls.js中记录初始位置,然后保持它直到它们被重新启用...但是我无法弄清楚在哪里。 This occurs somewhere in the MouseUp, MouseDown, and MouseMove event handlers. 这发生在MouseUp,MouseDown和MouseMove事件处理程序中的某处。 I was hoping this might be interesting to someone who might know more about the operation of OrbitControls than I do. 我希望对于那些可能比我更了解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! 我很想听听人们可能提出的任何建议,谢谢!

UPDATE Q1 2019 更新2019年第一季度

noRotate is now deprecated, use enableRotate instead. 现在不推荐使用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! 希望有人觉得这很有用!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM