Я пытаюсь создать маленькую интерактивную сцену, летающую вокруг НЛО, в Three.js.
Я подумал, что было бы хорошо контролировать НЛО в 2D-проекции карты (например, на мини-карте), преобразовывать координаты пикселей в координаты широты и долготы и, наконец, преобразовывать широты и долготы в вектор, который я могу использовать для своих 3D сцена.
Как оказалось, это не так.
Прекрасно работает, если НЛО летает вокруг экватора (+/- некоторые градусы), но наверняка я забыл применить проекцию к своим 2D элементам управления:
Теперь я немного растерялся. Мои элементы управления (клавиши WASD) в основном устанавливают скорость и вращение НЛО на миникарте, но я должен добавить некую «коррекцию» для игрока. Вот как устанавливаются значения в данный момент:
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)
Есть ли способ создать "настоящую" орбиту, чтобы мой НЛО не всегда летал через оба полюса? Или может быть лучший подход для обработки орбиты НЛО (может быть, без миникарты)?
Вот полный анимационный код:
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))
}