three.js getWorldPosition 未返回预期结果
three.js getWorldPosition not returning expected results
请参考我在
创建的要点
https://gist.github.com/sparkbuzz/f1f8d0d8bbc7757b679f
它包含一个名为 OrbitControls 的 TypeScript class。作为学习 3D 和 three.js, I've been successful so far in creating orbit style controls, with guidance and insparation taken from MrDoob's JS OrbitControls.
的尝试
我的实现略有不同,但简而言之,我使用的是 mousedown、mousemove 和 mouseup 事件以在世界原点周围导航相机。当 mousedown 被触发时,我使用以下代码获取相机的初始位置:
this.subjectPositionStart = this.subject.getWorldPosition();
在 mousemove 期间用于计算需要添加到相机初始位置的角度,就像 mousedown 时一样解雇了。
在mousemove期间,theta和phi角度是根据鼠标的距离计算的已经穿过 HTML canvas 并用于重新定位相机:
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° 之间翻转,我认为这是一个线索...
您的问题可能与 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 ) );
事实证明 baseTheta 和 basePhi 计算不正确,这个问题实际上出现在另一个问题中问。
借助上面 link 中 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);
问题解决了。再也不用翻来覆去。
请参考我在
创建的要点https://gist.github.com/sparkbuzz/f1f8d0d8bbc7757b679f
它包含一个名为 OrbitControls 的 TypeScript class。作为学习 3D 和 three.js, I've been successful so far in creating orbit style controls, with guidance and insparation taken from MrDoob's JS OrbitControls.
的尝试我的实现略有不同,但简而言之,我使用的是 mousedown、mousemove 和 mouseup 事件以在世界原点周围导航相机。当 mousedown 被触发时,我使用以下代码获取相机的初始位置:
this.subjectPositionStart = this.subject.getWorldPosition();
在 mousemove 期间用于计算需要添加到相机初始位置的角度,就像 mousedown 时一样解雇了。
在mousemove期间,theta和phi角度是根据鼠标的距离计算的已经穿过 HTML canvas 并用于重新定位相机:
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° 之间翻转,我认为这是一个线索...
您的问题可能与 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 ) );
事实证明 baseTheta 和 basePhi 计算不正确,这个问题实际上出现在另一个问题中问。
借助上面 link 中 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);
问题解决了。再也不用翻来覆去。