Как рассчитать орбиту вокруг Земли относительно проекции Меркатора? - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь создать маленькую интерактивную сцену, летающую вокруг НЛО, в Three.js.

Я подумал, что было бы хорошо контролировать НЛО в 2D-проекции карты (например, на мини-карте), преобразовывать координаты пикселей в координаты широты и долготы и, наконец, преобразовывать широты и долготы в вектор, который я могу использовать для своих 3D сцена.

Как оказалось, это не так.

Прекрасно работает, если НЛО летает вокруг экватора (+/- некоторые градусы), но наверняка я забыл применить проекцию к своим 2D элементам управления:

enter image description here

Теперь я немного растерялся. Мои элементы управления (клавиши 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))
}
...