我正在尝试在 three.js 中创建一个小型交互式 UFO 绕地球飞行的场景。
我认为最好在地图的 2D 投影(如小地图)上控制 UFO,将像素坐标转换为 lat/lng 坐标,最后将 lat/lng 转换为可用于 3D 场景的向量。
事实证明,事实并非如此。
如果 UFO 绕赤道飞行(+/- 几度),效果很好,但可以肯定的是,我忘记将投影应用于我的 2D 控件:
现在我有点迷路了。我的控件(WASD 键)基本上设置了小地图上 UFO 的速度和旋转,但我必须为播放器添加某种“校正”。这就是目前设置值的方式:
let left = parseFloat(this.minimapPlayer.style.left) + this.speed * Math.cos(Math.PI / 180 * this.rotation)
let top = parseFloat(this.minimapPlayer.style.top) + this.speed * Math.sin(Math.PI / 180 * this.rotation)
有没有办法创造一个“真实”的轨道,这样我的 UFO 就不会总是飞过两极?或者是否有更好的方法来处理 UFO 的轨道(可能没有小地图)?
到目前为止,这是完整的动画代码:
animatePlane(firstRender) {
requestAnimationFrame(this.animatePlane)
// set next position
let left = parseFloat(this.minimapPlayer.style.left) + this.speed * Math.cos(Math.PI / 180 * this.rotation)
let top = parseFloat(this.minimapPlayer.style.top) + this.speed * Math.sin(Math.PI / 180 * this.rotation)
// handle border collisions
if (left < 0) {
left = this.minimapBounds.width
}
if (left > this.minimapBounds.width) {
left = 0
}
if (top < 0 || top > this.minimapBounds.height) {
this.rotation = this.rotation * -1
if (this.rotation > 0) {
this.plane.up.set(0, 1, 0)
} else {
this.plane.up.set(0, -1, 0)
}
top = top + this.speed * Math.sin(Math.PI / 180 * this.rotation)
if (left < this.minimapBounds.width / 2) {
left = left + this.speed * Math.cos(Math.PI / 180 * this.rotation) + this.minimapBounds.width / 2
} else {
left = left + this.speed * Math.cos(Math.PI / 180 * this.rotation) - this.minimapBounds.width / 2
}
}
this.minimapPlayer.style.left = `${left}px`
this.minimapPlayer.style.top = `${top}px`
// convert to lat/lng
const lat = (180 / this.minimapBounds.height) * (top - this.minimapBounds.height / 2) * -1
const lng = (360 / this.minimapBounds.width) * (left - this.minimapBounds.width / 2)
// convert to vector
const p = this.latLongToVector3(lat, lng, this.radius, 200)
this.plane.position.set(p.x, p.y, p.z)
// bottom of the plane should always look the the middle of the earth
this.plane.lookAt(new THREE.Vector3(0,0,0))
}