【问题标题】:Three.JS Orbit Controls - enabling and disabling without position jumpingThree.JS Orbit Controls - 启用和禁用无位置跳转
【发布时间】:2014-06-29 01:27:58
【问题描述】:

我正在使用 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);
}

}

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

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

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

    希望有人觉得这很有用!

    【讨论】:

    • 非常有用!救了我一个我认为会很头疼的事情。谢谢!
    • 谢谢,这很有用。我注意到轨道控制的缩放继续起作用。
    • controls.enableRotate 似乎是在较新版本的 THREE.js 中设置的正确属性
    【解决方案2】:

    我无法测试它,但我认为你的代码应该是

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

    【讨论】:

    • 嗯......这似乎没有做任何事情。看起来你不能从函数外部调用它,因为它会引发错误并说它未定义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    相关资源
    最近更新 更多