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

时间:2014-05-11 18:18:12

标签: javascript three.js

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

}

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

2 个答案:

答案 0 :(得分:9)

更新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;

}

希望有人觉得这很有用!

答案 1 :(得分:1)

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

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