【问题标题】:OrbitControl - restrict panning movementOrbitControl - 限制平移运动
【发布时间】:2016-11-30 00:37:17
【问题描述】:

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

尝试更改 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 );

}

【问题讨论】:

    标签: javascript html three.js


    【解决方案1】:

    我遇到了完全相同的问题,感谢 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);
    

    这个想法是设置目标和相机的位置,但不要试图改变旋转角度。如果有旋转,先做一些数学运算来计算目标位置。

    【讨论】:

      【解决方案2】:

      我也遇到了同样的问题。解决方案不是触摸 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 位置。它工作得非常顺利。

      【讨论】:

      • 您可以像这样使用clamp(),而不是手动检查和设置scope.target的每个属性:scope.target.clamp(new THREE.Vector3(minX, minY, minZ), new THREE.Vector3(maxX,maxY,maxZ))
      • @LeJeuneRenard 有没有什么方法可以在不修改轨道控制源代码的情况下做到这一点?因为发布项目时可能会出现问题
      猜你喜欢
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      • 2014-06-29
      • 1970-01-01
      • 2019-06-30
      • 2019-09-05
      • 1970-01-01
      • 2011-05-26
      相关资源
      最近更新 更多