Почему camera.LookAt, когда камера в (0, 0, 0), говоря, что она поворачивается на -90 градусов вокруг оси, чтобы смотреть (1, 0, 0)? - PullRequest
1 голос
/ 18 апреля 2019

См. Скрипку здесь: https://jsfiddle.net/pkaru0xn/12/

  box.position.set(1, 0, 0);

  var camera = new THREE.PerspectiveCamera();
  camera.position.set(0, 0, 0);
  camera.lookAt(box.position);

Я позиционирую куб в (1, 0, 0). Камера расположена в (0, 0, 0). Согласно документам three.js камера смотрит вниз по своей локальной отрицательной оси Z.

Таким образом, я ожидаю, что при взгляде на куб он будет поворачиваться на 90 градусов вокруг оси y. Почему функция lookat возвращает -90 градусов? Почему это работает?

1 Ответ

1 голос
/ 18 апреля 2019

Изначально пространство камеры выровнено с мировым пространством. Это означает, что камера находится на (0, 0, 0) с вектором вверх (0, 1, 0) и смотрит вниз по оси -Z.

Правило правой руки заставляет вращение применяться против часовой стрелки. Это означает, что поворот вокруг оси +Y с положительным значением приведет к смещению взгляда камеры в направлении оси -X. Задание отрицательного значения угла поворота заставит взгляд камеры двигаться в направлении оси +X.

В приведенном ниже коде используются lookAt и rotateOnAxis для изменения положения камеры. Обратите внимание, что взгляд на объект слева соответствует положительному углу поворота.

const renderer = new THREE.WebGLRenderer({antialias: true, alpha: true})
document.body.appendChild(renderer.domElement)
renderer.setSize(200, 200)
renderer.setClearColor(0x55ccff)

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(28, 1, 1, 1000)

const geo = new THREE.SphereBufferGeometry(10, 32, 32)

const leftMat = new THREE.MeshBasicMaterial({color:"red"})
const rightMat = new THREE.MeshBasicMaterial({color:"blue"})
const frontMat = new THREE.MeshBasicMaterial({color:"green"})

const left = new THREE.Mesh(geo, leftMat)
left.position.set(-50, 0, 0)
const right = new THREE.Mesh(geo, rightMat)
right.position.set(50, 0, 0)
const front = new THREE.Mesh(geo, frontMat)
front.position.set(0, 0, -50)

const light = new THREE.PointLight(0xffffff, 1)

scene.add(left, right, light, front, camera)

function render(){
  renderer.render(scene, camera)
}
render()

document.getElementById("reset").addEventListener("click", ()=>{
  camera.lookAt(front.position)
  render()
})

document.getElementById("leftLook").addEventListener("click", ()=>{
  camera.lookAt(left.position)
  render()
})
document.getElementById("rightLook").addEventListener("click", ()=>{
  camera.lookAt(right.position)
  render()
})

const axis = new THREE.Vector3().set(0, 1, 0)
document.getElementById("leftTurn").addEventListener("click", ()=>{
  camera.rotateOnAxis(axis, Math.PI / 2)
  render()
})
document.getElementById("rightTurn").addEventListener("click", ()=>{
  camera.rotateOnAxis(axis, Math.PI / -2)
  render()
})
.test input {
  width: 150px;
}
.right {
  float: right;
}
.test {
  width: 100%;
}
.test:after {
  content: " "
  clear: both;
}
canvas {
  margin-left: auto;
  margin-right: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>
<div class="test">
<input id="leftLook" type="button" value="LEFT" /><input id="rightLook" type="button" value="RIGHT" />
</div>
<div class="test">
<input id="leftTurn" type="button" value="LEFT" /><input id="rightTurn" type="button" value="RIGHT" />
</div>
<input id="reset" type="button" value="RESET" /><br />
...