(Пожалуйста, обратитесь также к моей иллюстрации проблемы: http://i.stack.imgur.com/SfwwP.png)
описание проблемы и идеи
Я создаю несколько объектов в стандартной системе координат XYZ. Они добавляются в THREE.group.
Пожалуйста, подумайте о группе как о стене с несколькими рамами и изображением, висящим на ней. Я хочу создать свои объекты кадра, например. размер (40, 20, 0,5). Таким образом, я получаю довольно плоскую рамку / произведение искусства в ландшафтном формате. Я создаю и размещаю несколько таких. Потом добавляю их в группу, которую хотел свободно вращать в мире по двум векторам start
и end
.
Проблема, с которой я борюсь, заключается в том, как повернуть и расположить группу из заданного вектора start
в заданный вектор end
.
До сих пор я пытался решить это с помощью THREE.Matrix4().lookAt
:
var group = new THREE.Group();
startVec = new THREE.Vector3( 100, 0, -100 );
endVec = new THREE.Vector3( -200, 0, 200 );
matrix = new THREE.Matrix4().lookAt(startVec, endVec, new THREE.Vector3( 0, 1, 0 ));
group.matrixAutoUpdate = false;
var object1 = new THREE.Mesh(new THREE.BoxGeometry(0.5, 20, 40), mat);
// etc. -> notice the swapping of X and Z coordinates I have to do.
group.add(object1);
group.applyMatrix(matrix);
Вы можете увидеть пример на jsfiddle: http://jsfiddle.net/y6b9Lumw/1/
Если вы откроете jsfiddle, вы увидите, что объекты не размещаются вдоль линии от start
до end
, хотя я размещаю их вдоль внутренней оси X групп, например: addBox(new THREE.Vector3( i * 30, 0 , 0 ));
Полный код:
<html>
<head>
<title>testing a rotation matrix</title>
<style>body { margin: 0; } canvas { width: 100%; height: 100% } </style>
</head> <body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js"></script>
<script>
var scene, camera, renderer, light, matrix;
var startVec, endVec;
var boxes;
function addBox(v) {
var boxmesh;
var boxgeom = new THREE.BoxGeometry( 15, 5, 1 );
var boxmaterial = new THREE.MeshLambertMaterial( {color: 0xdd2222} );
boxmesh = new THREE.Mesh( boxgeom, boxmaterial );
//boxmesh.matrix.makeRotationY(Math.PI / 2);
boxmesh.matrix.setPosition(v);
boxmesh.matrixAutoUpdate = false;
boxes.add(boxmesh);
}
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0x222222 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( -20, 30, 300 );
var light = new THREE.PointLight (0xCCCCCC, 0.5 );
scene.add(light);
startVec = new THREE.Vector3( 100, 0, -100 );
endVec = new THREE.Vector3( -200, 0, 200 );
matrix = new THREE.Matrix4().lookAt(startVec, endVec, new THREE.Vector3( 0, 1, 0 ));
boxes = new THREE.Group();
for (var i = -100; i < 100; i++) {
addBox(new THREE.Vector3( i * 30, 0 , 0 ));
}
boxes.matrixAutoUpdate = false;
boxes.applyMatrix(matrix);
scene.add(boxes);
var linegeometry = new THREE.Geometry();
linegeometry.vertices.push( startVec, endVec);
var line = new THREE.Line(linegeometry, new THREE.LineBasicMaterial({color: 0x33eeef}));
scene.add(line);
render();
}
function render(){
requestAnimationFrame(render);
renderer.render(scene, camera);
}
init();
</script>
</body> </html>
Это хорошо работает только до некоторой степени. Поскольку вектор взгляда обычно ориентирован по оси Z (я думаю, что это (0,0,1)). Так что, к сожалению, объекты внутри группы также вращаются. На самом деле это то, что вы ожидаете от вращательного преобразования lookAt(). Это не то, что я хотел бы иметь, так как это помещает всех дочерних элементов в группу на их ось Z, а не их ось X.
Чтобы все выглядело правильно, мне пришлось инициализировать дочерние группы, поменяв местами X и Z. Вместо:
var object1 = new THREE.BoxGeometry( 40, 20, 0.5 );
Я должен сделать:
var object1 = new THREE.BoxGeometry( 0.5, 20, 40 );
то же самое, если я хочу перевести объекты в группе по оси X, я должен использовать ось Z, так как это вектор взгляда, вдоль которого вся стена ориентируется матричным преобразованием.
мой вопрос: как моя матрица должна быть построена/выглядеть, чтобы выполнить то, что я хочу: обычно создавать объекты, а затем размещать их ось X вдоль вектора start
и вектора end
, например, размещать произведения искусства на стене, что может быть двигался? Я подумал о создании матрицы, ось X которой равна end.sub(start)
, поэтому вектор от начала до конца может быть тем, что мне нужно сделать? Если да, то как бы я его построил?
иллюстрация проблемы с изображением
Я попытался проиллюстрировать свою позицию двумя изображениями. Одна из них — стена, другая — стена внутри мира, с теми же объектами, прикрепленными к стене (см. начало поста).
На первом рисунке вы видите локальную систему координат группы с двумя добавленными дочерними элементами, один из которых перенесен по X. На втором рисунке вы можете увидеть ту же локальную систему внутри мира, как мне бы хотелось быть. Зеленые оси — это мировые оси. Также показаны векторы start
и end
. Вы можете видеть, что оба прямоугольника правильно расположены вдоль этой линии.
position
,rotation
илиquaternion
иscale
. Средство визуализации вычисляет матрицу для вас. Вот скрипт, который поможет вам начать работу: jsfiddle.net/1wfvL1bt. - person WestLangley   schedule 23.02.2015position
,rotation
и т. д. вместо того, чтобы возиться с матрицей. Я почему-то подумал, что лучше в этом случае создать матрицу вращения. Я исправляюсь. С помощью вашего вдохновения в коде и подсказки использовать стандартные методы three.js я вскоре отвечу на свой вопрос. - person nylki   schedule 24.02.2015