Three.js - Как повернуть камеру вокруг точки Vector3?

Хорошо, я постараюсь быть максимально кратким. Я не очень хорошо разбираюсь в математике, и то, что вам может показаться очевидным, скорее всего, будет для меня ракетостроением.

Я использую Three.js с CSS3DRenderer для создания пространства виртуальной галереи.

Мне нужна перспектива от первого лица, как в игре FPS.

Я получил камеру, чтобы успешно двигаться вперед, назад, влево и вправо.

Однако, когда я иду вращать камеру, я получаю результат на фото здесь

Камера вращается вокруг своей локальной оси, но мне нужно viewport, а не камера, чтобы вращаться, как

на фото здесь

Так что мне нужно, чтобы камера вращалась вокруг точки поворота / вектора, а затем перефокусировалась с помощью Object3d.lookAt()

Я осознаю, что могу решить свою проблему, поместив камеру в качестве дочернего элемента другого объекта, а затем вращая ось объекта. Тем не менее, я бы предпочел сделать математику сам.

Короче говоря, я хочу понять, как повернуть одну векторную точку вокруг другой и как математически представить это отношение.

Я не хочу использовать скрипт, например, средства управления three.js pointer_lock, чтобы выполнить работу. Я хочу испачкать руки математикой.

Любые советы или ссылки на учебники будут высоко оценены!

2 ответа

Ниже приведен пример поворота камеры вокруг коробки.

Это работает благодаря тому факту, что применение матрицы вращения всегда вращает объект вокруг начала координат. Это в отличие от простого изменения rotation свойство, которое вращает объект вокруг своего собственного центра, как вы узнали. Хитрость здесь в том, чтобы переместить камеру на 200 единиц от начала координат, так что, когда мы применяем матрицу вращения, она вращается вокруг начала координат по кругу.

Так как коробка находится в начале координат, она будет вращать камеру вокруг коробки. затем lookAt используется для направления камеры в сторону коробки.

Вот низкоуровневое объяснение по этому вопросу, если вы хотите узнать больше: http://webglfundamentals.org/webgl/lessons/webgl-scene-graph.html

var canvas = document.getElementById('canvas');
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true});
var camera = new THREE.PerspectiveCamera(45, canvas.clientWidth / canvas.clientWidth, 1, 1000);

var geometry = new THREE.BoxGeometry(50, 50, 50);
var material = new THREE.MeshBasicMaterial({color: '#f00'});
var box = new THREE.Mesh(geometry, material);
scene.add(box);

// important, otherwise the camera will spin on the spot.
camera.position.z = 200;

var period = 5; // rotation time in seconds
var clock = new THREE.Clock();
var matrix = new THREE.Matrix4(); // Pre-allocate empty matrix for performance. Don't want to make one of these every frame.
render();

function render() {
  requestAnimationFrame(render);
  if (canvas.width !== canvas.clientWidth || canvas.height !== canvas.clientHeight) {
    // This stuff in here is just for auto-resizing.
    renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
    camera.aspect = canvas.clientWidth /  canvas.clientHeight;
    camera.updateProjectionMatrix();
  }

  // Create a generic rotation matrix that will rotate an object
  // The math here just makes it rotate every 'period' seconds.
  matrix.makeRotationY(clock.getDelta() * 2 * Math.PI / period);

  // Apply matrix like this to rotate the camera.
  camera.position.applyMatrix4(matrix);

  // Make camera look at the box.
  camera.lookAt(box.position);

  // Render.
  renderer.render(scene, camera);
}
html, body, #canvas {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.js"></script>
<canvas id="canvas"></canvas>

Стандартный метод заключается в создании var camera_pivot = new object3D() в том же месте, что и объект. Поставьте камеру как ребенка, переместите камеру назад, чтобы сделать заметное расстояние и поверните объект.

Вы можете перемещать object3D () и вращаться в соответствии с вашими потребностями. Это оптимальное решение для простого кода и для производительности.

На object3D вы можете использовать camera_pivot.translateX(), camera_pivot.rotateX(), camera_pivot.lookAt(obj) и т.д...

По-другому сложно совершать какие-либо действия без воздействия на другой объект в сцене.

Другие вопросы по тегам