3D вращение с осью и углом - PullRequest
       14

3D вращение с осью и углом

14 голосов
/ 28 сентября 2010

Я знаю, что 3D-ротация хорошо документирована на SO и многих других сайтах, но, несмотря на чтение бесчисленных объяснений, я до сих пор не понял, где я ошибаюсь.Я занимаюсь искусством и дизайном, а не математикой и программированием, и я никогда не уверен, правильный ли у меня угол атаки (без каламбура).Вместо того, чтобы вставлять лоскутное одеяло из моего мрачного кода, я включаю изображение, описывающее мою проблему.Что мне действительно нравится, так это пошаговая формулировка того, как ее решить.Псевдокод полезен, но я узнаю больше, если кто-то просто нацелит меня в правильном направлении или укажет на распространенные ошибки.


alt text

Красный = ось X,Зеленый = Ось Y, Синий = Ось Z

Пурпурные векторы = начало координат -> некоторая точка X, Y, Z

Пурпурный куб = среднее из конечных точек двух пурпурных векторов (есть ли лучшее имя для этого?)

Белый вектор = перекрестное произведение двух пурпурных векторов (расширенный для отображения, фактический вектор нормализован)

Объект голубого куба = ошибка поворота


Ранее я использовал Away3D и Papervision;в этих библиотеках, применяя углы Эйлера к свойствам rotX, RotationY или RotationZ объекта, будет поворачивать объект локально, как если бы он находился в начале координат независимо от его фактического положения.С Three.js это не так.Изменение свойств объекта direction.x и вращение объекта производит странный эффект, где объект очевидно немного наклоняется на оси Z.Еще более запутанным является то, что это происходит, когда объект лежит в начале координат.Я подумал, что, возможно, использование функций Quaternion -> Matrix или Axis / Angle -> Matrix решит мою проблему, но без кубиков.Кажется, есть основная концепция, которую я не понимаю.

В любом случае, я бы хотел ориентировать куб на вектор перекрестного произведения (белый), чтобы верхняя часть куба была обращена кнаправление этого вектора.Затем я хотел бы повернуть куб вдоль той же оси.Изображение, которое я приложил, показывает результат большего количества часов, чем я хотел бы признать, пытаясь достичь этого результата.Мой код выглядит примерно так:

axis = Vector3.cross(a, b)
axis.normalize()
angle = 45 * TO_RADIANS;
quat = AxisAngle2Quaternion(axis, angle)
rot = Quaternion2Matrix(quat)
cube.matrix = rot

Заранее спасибо,

Кейси


Редактировать: Начинается вознаграждение

Может быть, я неправильно понимаю, как это должно работать.Вот еще одно изображение:

alt text

Неправильно ли я считаю, что этот пурпурный вектор является осью, а оранжевые стрелки указывают поворот вокруг этой оси на основе угла?Так или иначе, я хочу ориентировать голубой куб на некоторый вектор направления и вращать его.Что я делаю не так!?

Ответы [ 3 ]

4 голосов
/ 30 сентября 2010

Ваш подход звучит правильно, но вы не показываете, что такое векторы a, b и постоянный угол, я полагаю, только для тестирования. Я делал это раньше, поэтому я выкопал свой код, и это математика, которую я нашел ...

Дано:
originalVec = единичный вектор, направленный вверх по оси Y (направление вершины куба / нормали)
targetVec = белый вектор

Теперь вы хотите, чтобы ось и угол, который будет вращать originalVec, выравнивались с targetVec. Самая прямая ось вращения перпендикулярна обоим входным векторам, поэтому возьмите их перекрестное произведение. Эта ось не является единичным вектором, поэтому также нормализуйте ее. Угол поворота (в радианах) является обратным косинусом точечного произведения.

axis = Vector3.cross(originalVec, targetVec)
axis.normalise
angle = inversecos(Vector3.dot(originalVec, targetVec))

quat = AxisAngle2Quaternion(axis, angle)
rot = Quaternion2Matrix(quat)
cube.matrix = rot

Вместо замены матрицы куба, я думаю, вы хотите скомпоновать ее с новым преобразованием ...

cube.matrix.multiplyBy(rot)

... но я не уверен на 100% в этом. Кроме того, я видел реализации, где AxisAngle2Quaternion принимает угол в градусах. Когда входные векторы параллельны или противоположны оси, это <0,0,0>, так что следует проверить на. Если куб вращается не в ту сторону, тогда параметры вектора перекрестных произведений находятся в неправильном порядке, я никогда не помню, какой, и просто попробую их обоих. НТН.

Редактировать
У меня была возможность поиграть с Three.js и взломать один из примеров, чтобы сориентировать куб. Комментарии показывают, куда я добавил материал, и все ориентирующие математические операции выполняются в alignCube ().
Пример выравнивания и вращения
Мышь вверх / вниз перемещает целевую линию. Мозговые левые / правые спины на линии.

Кажется, что все объекты сцены в Three.js наследуются от Object3D, у которого свойство autoUpdateMatrix по умолчанию установлено в true. Это должно быть установлено в ложь, иначе вызывается функция updateMatrix, которая пересчитывает матрицу из свойств положения, масштаба и поворота объектов. Также вы можете назначить другую функцию updateMatrix.

Было бы неплохо, если бы Three.js имел какую-то документацию:)

3 голосов
/ 01 октября 2010

Из примера Trochoid, вот функция, которую я использую для достижения выравнивания и вращения из второго изображения:

//object, normalized direction vector, rotation in radians
function align(target, dir, rot) {
    //Three.js uses a Y up coordinate system, so the cube inits with this vector
    var up = new THREE.Vector3(0, 1, 0);

    //euler angle between direction vector and up vector
    var angle = Math.acos(up.dot(dir));

    //cross product of the up vector and direction vector
    var axis = new THREE.Vector3();
    axis.cross(up, dir);
    axis.normalize();

    //rotation to aligns the target with the direction vector
    var rotate = THREE.Matrix4.rotationAxisAngleMatrix(axis, angle);

    //rotation around direction vector
    var revolve = THREE.Matrix4.rotationAxisAngleMatrix(dir, rot);

    //compose the rotations (order matters, can be done other ways)
    revolve.multiplySelf(rotate);

    //assign matrix (autoUpdateMatrix = false)
    target.matrix = revolve;
}
0 голосов
/ 29 сентября 2010

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

Есть 3 возможных проблемы, и у вас есть одна из них:

  1. Математика не верна, или вы ее не понимаете. (Здесь не должно быть столько проблем)
  2. Арифметика с плавающей запятой всегда является проблемой для компьютеров (Это также не должно быть проблемой, потому что она довольно проста. Если ваш фреймворк не может предоставить решение, то фреймворк вообще не имеет никакого значения для 3D-программирования)
  3. Вы не правильно используете рамки

Поскольку вполне вероятно, что дело № 3, попробуйте найти список рассылки или форум поддержки или что-то еще для фреймворка и поговорить с людьми там. Они должны быть в состоянии объяснить вам, что вы делаете не так с их рамками. Тогда вернитесь и отправьте решение здесь!

...