【问题标题】:OrbitControls moving object keep distanceOrbitControls 移动物体保持距离
【发布时间】:2022-07-22 10:09:51
【问题描述】:

我通过以下方式获得 OrbitControls 更新目标: orbitControls.target = target.position 每一帧。

但是,如果目标正在移动,并且我单击并拖动到轨道到对象向相机移动的位置,则对象最终会“穿过”相机,因为相机停止与目标一起移动.

有没有办法让 orbitControls 与目标保持最小距离?我已经尝试过minDistance,但是当我单击并拖动时,它似乎不起作用。

【问题讨论】:

    标签: three.js


    【解决方案1】:

    想出了一个办法(但仍有问题):

    orbitControls.target = player.mesh.position;
            // find distance from player to camera
            const dist = camera.position.distanceTo(player.mesh.position);
            // if distance is less than minimum distance, set the camera position to minimum distance
            if (dist < MINIMUM_CAMERA_DISTANCE) {
                      const dir = camera.position.clone().sub(player.mesh.position).normalize();
      
               camera.position.copy(player.mesh.position.clone().add(dir.multiplyScalar(MINIMUM_CAMERA_DISTANCE)));
            }
    

    【讨论】:

      【解决方案2】:

      你的回答有很好的副作用,在“周围”移动对象而不是在最小距离处停止相机(在某些情况下,这甚至可能是一个功能,如果整个事情正常的话),但具有相同的和你一样有问题,我明白你说你的方式仍然有问题的意思,当从最小距离区域缩小时相机失去了方向。

      这是另一种方式,不幸的是,仍然也有问题,即使它应该可以完美地工作。将控件的 change 事件设置为类似于 - 在必要时调整名称或变量:

        controls.addEventListener("change", function(e)
        {
          if (camera.position.distanceTo(targetmesh.position) < mincam)
          {
            camera.translateZ(maxcam - mincam);
            var scaledobject = new THREE.Mesh(targetmesh.geometry.clone(), targetmesh.material.clone());
            scaledobject.geometry.scale(mincam, mincam, mincam);
            scaledobject.updateMatrixWorld();
            var cameradirection = new THREE.Vector3();
            camera.getWorldDirection(cameradirection);
            cameradirection.normalize();
            var cameraorigin = new THREE.Vector3();
            camera.getWorldPosition(cameraorigin);
            var raycaster = new THREE.Raycaster(cameraorigin, cameradirection);
            var intersects = raycaster.intersectObjects([scaledobject], true);
            if (intersects.length > 0) {camera.position.copy(scaledobject.worldToLocal(intersects[0].point));} else {camera.translateZ(mincam - maxcam);};
          };
          renderer.render(scene, camera);
        });
      

      显然,controls 是您的“orbitControls”,targetmesh 是您的“player.mesh”等价物,mincammaxcam 是您的“MINIMUM_CAMERA_DISTANCE”和假定的“MAXIMUM_CAMERA_DISTANCE”变量,后者选择方便使相机尽可能远离最小点。

      上面的操作是检查控件的每个change事件与对象的距离是否小于设置的最小值,如果是这样,请将相机移动后退(局部空间中的正 Z 平移,如 other SO answers 中所述)足以使从它沿其方向投射的光线可以安全地与原始对象的缩放克隆相交(或不相交)以产生相交点。由于克隆被缩放到最小相机距离“边界”,它将精确地包括您不希望相机进入和离开原始对象的区域,无论其形状如何。因此,相交点(如果存在)将是您希望相机停止的点,因为由于克隆缩放,它与原始对象的距离最小,并且在相机方向/路径上由于从相机沿该方向投射的光线。

      这种方法的问题显然是,Three.js 在正确进行光线投射方面仍然存在一些问题,因为对于某些最小距离值(在我的情况下为 1.02,当使用具有许多宽度和高度段的球体时) X = 0 和 Y = 0 作为相机)相交数组第一次出现空,即使它不应该 - 而对于 1.5 等其他值,它每次都有效。奇怪的是,在对相机执行一些其他随机更改(例如通过控件平移或旋转一点 - 我使用 Arcball )之后,问题被“修复”了,所以它要么是 Three.js 中 this (unsolved?) bug 的变体,要么我'我在代码中遗漏了一些明显的东西。关键是,它应该始终有效,所以如果有人知道如何永久修复它,请随时分享。

      除此之外,它工作得很好。如果目标对象/网格有其他子对象,则需要稍加注意,但如果需要,您可以在这种情况下将.intersectObjects() 方法的递归参数设置为false

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-23
        • 1970-01-01
        • 1970-01-01
        • 2015-04-16
        相关资源
        最近更新 更多