#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
они будут следовать.
Как это не сработает
Вы можете продолжать привязывать детей к своему сердцу, но в какой-то момент вы можете захотеть, чтобы один из объектов в вашей цепочке сделал что-то по отношению к внешнему или глобальному объекту. Для размотки преобразований потребуется несколько дополнительных шагов, прежде чем вы сможете выполнить желаемые действия.