Three.js — Как установить положение относительно положения и направления объекта?

#javascript #three.js

Вопрос:

Я пытаюсь сделать так, чтобы мой 2-й объект находился непосредственно позади (- расстояние) моего 1-го объекта, который был повернут.

Допустим, у меня есть 2 объекта:

 var object1 = new THREE.Object3D();
object1.position.set(5, 10, 53);
object1.rotateX(1);
object1.rotateY(1.5);


var distance = 20; //place object2 20 units behind object1
var object2 = new THREE.Object3D();
object2.position.set( /*position object2 right behind object1 -distance */);
object2.lookAt(object1);
 

В этом случае, как мне разместить object2 непосредственно за object1 тем, что было повернуто?

Визуальный 2D пример. Не масштабировать

введите описание изображения здесь

Ответ №1:

Сделай это вот так:

 let camera, scene, renderer;

init();
animate();

function init() {

  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 100);
  camera.position.set(5, 10, 55);

  scene = new THREE.Scene();

  const geometry = new THREE.PlaneGeometry();
  const material = new THREE.MeshNormalMaterial();

  const mesh1 = new THREE.Mesh(geometry, material);
  mesh1.position.set(5, 10, 53);
  mesh1.rotateX(1);
  mesh1.rotateY(1.5);
  scene.add(mesh1);

  const mesh2 = new THREE.Mesh(geometry, material);
  scene.add(mesh2);

  const v1 = new THREE.Vector3(0, 0, 1).applyQuaternion(mesh1.quaternion);
  mesh2.quaternion.copy(mesh1.quaternion);
  mesh2.position.copy(mesh1.position).add(v1.multiplyScalar(-2));

  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  const controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.target.copy(mesh1.position);
  controls.update();

}

function animate() {

  requestAnimationFrame(animate);
  renderer.render(scene, camera);

} 
 body {
      margin: 0;
} 
 <script src="https://cdn.jsdelivr.net/npm/three@0.128/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128/examples/js/controls/OrbitControls.js"></script> 

Идея состоит в том, чтобы применить вращение object1 to object2 , а также использовать его для вычисления позиции позади object1 . Это делается путем применения поворота к вектору, который затем масштабируется на значение расстояния (в приведенном выше случае -2 ), а затем добавляется к object1 значению положения.

Ответ №2:

В этом конкретном случае использования вы можете добавить object2 object1 и просто установить object2 положение по одной оси на нужное вам расстояние, независимо от того , какая ось служит «позади» object1 .

 // given: object1, object2
// assuming: the meshes' "forward" direction is locally  Z, both "up" are  Y

scene.add( object1 )

object1.add( object2 )

object2.position.z = -distance
 

Несколько уточнений:

«прямое» направление сеток локально Z

Это важно для определения того, что означает «позади». Например, фары автомобиля будут направлены в направлении Z.

оба «вверх» равны Y

Это еще один аспект ориентации модели. Если направление «вверх» обеих моделей равно Y, то обе они «вертикальны» относительно друг друга. Это все равно, что сказать, что для двух автомобилей обе их крыши ориентированы в направлении Y.

Как это работает:

Учитывая, что обе сетки-в их базовой ориентации-ориентированы одинаково, то, что вы можете сделать, это манипулировать object2 относительно object1 . Вы можете сделать это , создав object2 дочернее object1 устройство, которое object2 теперь будет выполнять свои преобразования в object1 локальном пространстве, а не в мировом пространстве. Это возможно , потому Mesh что является производным от Object3D , который является универсальным 3D-контейнером в three.js. Как ребенок, object2 автоматически наследует object1 преобразования, поэтому при перемещении/вращении object1 object2 они будут следовать.

Как это не сработает

Вы можете продолжать привязывать детей к своему сердцу, но в какой-то момент вы можете захотеть, чтобы один из объектов в вашей цепочке сделал что-то по отношению к внешнему или глобальному объекту. Для размотки преобразований потребуется несколько дополнительных шагов, прежде чем вы сможете выполнить желаемые действия.