#graphics #three.js #3d #camera
#графика #three.js #3D #камера
Вопрос:
Смотрите Здесь Скрипку: 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. Прочитайте о правостороннем правиле, поскольку оно применяется к правой системе координат. Это скажет вам, какое направление вращения положительное, а какое отрицательное.
2. Спасибо за ответ. Я знаю, что в three js используется правосторонняя система координат, при этом вектор (0, 1, 0) по умолчанию равен up. Как показано на моем чертеже, при этом я бы ожидал, что поворот для просмотра на (1, 0, 0) от прямого взгляда вниз (0, 0, -1) будет равен 90 градусам, а не -90.
Ответ №1:
Первоначально пространство камеры выровнено с мировым пространством. Это означает, что камера находится в (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: "amp;nbsp;"
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 />