[英]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.