OrbitControl - 限制平移运动

3

有没有办法限制场景中相机的平移运动?

尝试修改orbitControls中的pan方法,但结果并不令人满意,我希望有更方便/合适的方法来实现这一功能。

if ( scope.object instanceof THREE.PerspectiveCamera ) {
    // perspective
    var position = scope.object.position;

    var offset = position.clone().sub( scope.target );
    var targetDistance = offset.length();

    // half of the fov is center to top of screen
    targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );

    // we actually don't use screenWidth, since perspective camera is fixed to screen height
    var dist_l = ( 2 * deltaX * targetDistance / screenHeight );
    var dist_u = ( 2 * deltaY * targetDistance / screenHeight );

    /////// X,Y limit calculation //////
    var limit = 100;
    if( (position.x - dist_l) <= -limit ){
        dist_l = -0.1;
    }else if( (position.x - dist_l)  >= limit){
        dist_l = 0.1;
    }
    if( (position.z - dist_u) <= -limit ){
        dist_u = -0.1;
    }else if( (position.z - dist_u) >= (limit*2.5) ){
        dist_u = 0.1;
    }
    /////// X,Y limit calculation //////

    scope.panLeft( dist_l );
    scope.panUp( dist_u );

} else if ( scope.object instanceof THREE.OrthographicCamera ) {

    // orthographic
    scope.panLeft( deltaX * ( scope.object.right - scope.object.left ) / screenWidth );
    scope.panUp( deltaY * ( scope.object.top - scope.object.bottom ) / screenHeight );

}
2个回答

9

我遇到了同样的问题。解决方法不是修改pan()函数,而是检查update()函数中的限制条件。请定位至第162行:

// move target to panned location
scope.target.add( panOffset );

在此行之后立即进行您的限制计算:

if (scope.target.x > 1000)
    scope.target.setX(1000);
if (scope.target.x < 0)
    scope.target.setX (0);
...

这将夹紧目标x轴位置。它工作得非常顺畅。

1
你可以使用clamp()而不是手动检查并设置scope.target的每个属性,如下所示:scope.target.clamp(new THREE.Vector3(minX, minY, minZ), new THREE.Vector3(maxX,maxY,maxZ)) - Le Jeune Renard
@LeJeuneRenard 有没有办法可以在不修改orbitcontrol源代码的情况下完成呢?因为这可能会在发布项目时引起问题。 - Charles Ye

0

我有完全相同的问题,感谢David的解决方案,给了我很多启示。我对David的答案有一些补充:

如果我们只设置目标X,当保持到达该限制时,会产生一些不必要的旋转效果。这是因为OrbitControls与两个东西一起工作:目标和相机。为了解决这个问题,我们需要同时设置目标和相机。

scope.target.setX(0); 
camera.position.setX(0);

以此方式,我们保证相机始终在物体的顶部,因此不会发生无意的旋转。
如果我们想要保持当前的旋转角度,我们需要进行一些数学计算。例如,在我的案例中,我仅启用了极坐标旋转:
let polarAngle = scope.getPolarAngle(); 
scope.target.set(0, camera.position.y + camera.position.z * Math.tan(polarAngle), 0);
camera.position.setX(0);

这个想法是设置目标和相机位置,但不尝试改变旋转角度。如果有旋转,则进行一些数学计算来先计算目标位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接