【问题标题】:three.js getWorldPosition not returning expected results三.js getWorldPosition 不返回预期结果
【发布时间】:2015-09-21 02:29:49
【问题描述】:

请参考我在

处创建的要点

https://gist.github.com/sparkbuzz/f1f8d0d8bbc7757b679f

它包含一个名为 OrbitControls 的 TypeScript 类。作为学习 3D 和 three.js 的尝试,到目前为止,我在创建轨道样式控件方面取得了成功,并从 MrDoob's JS OrbitControls. 获得了指导和指导

我的实现略有不同,但简而言之,我使用 mousedownmousemovemouseup 事件来导航相机世界起源。当 mousedown 被触发时,我使用以下代码抓取相机的初始位置:

this.subjectPositionStart = this.subject.getWorldPosition();

mousemove 期间用于计算需要添加到相机初始位置的角度,就像触发 mousedown 时一样。

mousemove 期间,thetaphi 角度是根据鼠标在 HTML 画布上移动的距离计算的,并用于重新定位相机:

this.subject.position.x = rho * Math.cos(theta) * Math.sin(phi);
this.subject.position.y = rho * Math.sin(theta) * Math.sin(phi);
this.subject.position.z = rho * Math.cos(phi);

一切正常,但是,在下一个 mousedown 时,有时,当相机位置围绕 z 轴的旋转角度超过 90° 或低于 -90° 时,相机位置捕捉到一个看起来与它应该是相反的位置。

所以我看到的是相机翻转,以反映其位置,度数是正确的,但只是镜像。

当我不超过 90° 时,下一个 mousedown 工作正常,导航行为符合预期,并且从 getWorldPosition() 正确检索相机位置,但是我怀疑我错误地使用了这个函数,或者完全使用了错误的技术来确定相机位置相对于原点的角度。

问题肯定与 mousedown 处理程序有关,因为虽然只有 mousemove 触发,但超过 90° 角没有问题,并且导航工作正常。

对可能出现的问题有任何想法吗?

编辑:

我认为我calculating baseTheta 的方式不正确:

var baseTheta:number = Math.asin(this.subjectPositionStart.y / rho / Math.sin(basePhi));

如果我使用:

var baseTheta:number = Math.acos(this.subjectPositionStart.x / rho / Math.sin(basePhi));

我遇到了同样的问题,但它在 180° 和 360° 之间翻转,我认为这是一个线索......

【问题讨论】:

  • 我查看了 lookAt() 搞砸的可能性,但似乎并非如此,然而,在添加一些调试覆盖数据后,我可以看到,每当 X 变为负数时,在下一次鼠标按下,计算会导致 - 以某种方式变为 +,例如,如果 X 为 -0.5,它将跳转到 0.5。但是 Y 和 Z 值仍然正确...

标签: javascript 3d three.js typescript


【解决方案1】:

您的问题可能与 Three.js 试图让摄像头朝上的方式有关

看看这个:rotating-camera-around-the-x-axis-three-js

Orbit controls source 中,对于如何旋转有一些限制。将这些添加到您的代码中可能会解决您的问题。

        // restrict theta to be between desired limits
        theta = Math.max( this.minAzimuthAngle, Math.min( this.maxAzimuthAngle, theta ) );

        // restrict phi to be between desired limits
        phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );

        // restrict phi to be betwee EPS and PI-EPS
        phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );

【讨论】:

  • 我肯定会尝试这个,但只要我不调用 getWorldPosition,例如在按住鼠标按钮连续拖动鼠标时,这绝不是问题。相机按预期运行。只有在调用 getWorldPosition 来重置 mousemove 的初始位置时,在 mousedown 事件中,以及当相机围绕 z 轴的角度 > 90° 或
【解决方案2】:

事实证明 baseThetabasePhi 没有被正确计算,而且这个问题实际上出现在我问的另一个问题中。

Calculate θ and ø angles between origin and x,y,z coordinate

在上面链接中 Paul.S 的回答的帮助下,我更改了以下代码:

var basePhi:number = Math.acos(this.subjectPositionStart.z / rho);
var baseTheta:number = Math.asin(this.subjectPositionStart.y / rho / Math.sin(basePhi));

var basePhi:number = Math.acos(this.subjectPositionStart.z / rho);
var baseTheta:number = Math.atan2(this.subjectPositionStart.y, this.subjectPositionStart.x);

问题就解决了。不用再胡思乱想了。

【讨论】:

  • 很高兴您能够解决您的问题并感谢您提出您的解决方案。
猜你喜欢
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-07
相关资源
最近更新 更多