Three.js 将相机保持在地面上(使用OrbitControls.js)

Three.js 将相机保持在地面上(使用OrbitControls.js),three.js,camera,controls,Three.js,Camera,Controls,所以我有一个非常简单的情况,地平面基本上是y=0的位置,我想让相机一直在地面上。我还想要感觉直观(并且触摸兼容)的好控件,我发现OrbitControls.js似乎最适合这一点,还因为我可以通过将maxPolarAngle设置为小于或等于Math.PI/2(四分之一圈)的值来轻松限制极轴角度 不过,即使这样做,用户也可以在地面下平移,除非完全禁用平移功能(我不想这样)。手动限制使y永远不会变为负值感觉很奇怪,但我认为简单地忽略y轴上的任何更改,例如将第165行(平移功能)更改为以下内容 panO

所以我有一个非常简单的情况,地平面基本上是y=0的位置,我想让相机一直在地面上。我还想要感觉直观(并且触摸兼容)的好控件,我发现OrbitControls.js似乎最适合这一点,还因为我可以通过将maxPolarAngle设置为小于或等于Math.PI/2(四分之一圈)的值来轻松限制极轴角度

不过,即使这样做,用户也可以在地面下平移,除非完全禁用平移功能(我不想这样)。手动限制使y永远不会变为负值感觉很奇怪,但我认为简单地忽略y轴上的任何更改,例如将第165行(平移功能)更改为以下内容

panOffset.set( te[ 4 ], 0, te[ 6 ] );
panOffset.normalize();
导致了一个快速而肮脏的解决方案,满足了我的需求

但现在用户只能通过缩放来更改相机高度

你能想出更好的解决办法吗?也许这条线索可以作为一个官方解决方案的思想食粮,我相信我不会是唯一一个受益于这种解决方案的人


/编辑:一开始我没有规范化偏移向量,这导致了另一个问题,现在已更改。

我在让OrbitsControl.js按我的要求工作时遇到了问题。最适合我的解决方案是创建我自己的CamaraControl,它能够按照我的要求运行。我怀疑这不是你想要的答案,因为这需要一些工作。您可以添加自己的更新函数来钳制这些值

THREE.OrbitControls.clampedUpdate = function () {
    THREE.OrbitControls.update.call(this);
    if (this.object.position.y < 0) {
        this.object.position.y = 0;
    }
}
THREE.OrbitControls.clampedUpdate=函数(){
三.轨道控制.更新.调用(this);
if(this.object.position.y<0){
this.object.position.y=0;
}
}

以防有人需要答案:

您可以找到相对于控件目标的角度和相机的地面位置(不考虑高度),并指定maxPolarAngle。调整你的上轴,我的是Y轴。在控件更改事件中:

var centerPosition = controls.target.clone();
centerPosition.y = 0;
var groundPosition = camera.position.clone();
groundPosition.y = 0;
var d = (centerPosition.distanceTo(groundPosition));

var origin = new THREE.Vector2(controls.target.y,0);
var remote = new THREE.Vector2(0,d); // replace 0 with raycasted ground altitude
var angleRadians = Math.atan2(remote.y - origin.y, remote.x - origin.x);
controls.maxPolarAngle = angleRadians;

不要到地下去:

controls.maxPolarAngle = Math.PI / 2
这也是我尝试过的(只是我在相机里做的),但就像我写的那样,感觉很奇怪。可能是重复的