Как вы комбинируете вращения X, Y и Z в локальном пространстве модели (не глобальном)?

Я начинаю на Molehill и у меня много проблем с захватом Matrix3D. Моя первая проблема - как управлять Matrix3D, который описывает ориентацию отдельной модели.

Я использую Matrix3D.appendRotation() для этого. Но в зависимости от порядка добавления, я получаю другой результат (очевидно, поскольку я вращаюсь по одному в глобальном пространстве). Я знаю, что это распространенная проблема, я столкнулся с ней при 3D программном моделировании. Но на этот раз я должен это исправить программно. Это где мне нужна помощь.

Во-первых, в случае путаницы, вот проблема на картинках:

Шаг 1: Я отрисовываю модель.

Начальная позиция

Шаг 2а: я вращаю его по оси X. Выглядит правильно!

Вращение оси X

Шаг 2b: Я вращаю его по оси Z. Выглядит правильно!

Вращение по оси Z

Итак... если я вращаюсь по оси X и Z модели, я хочу это:

желаемое вращение XZ

Но, грустно, я получаю это:

Я вижу проблему. Я добавляю вращения по одному в глобальном пространстве. Мне нужно вращаться в локальном пространстве объекта. Я понятия не имею, как это сделать или что я должен искать (терминология и т. Д.). Код прост (и неправильн):

modelLocalMatrix.identity();
modelLocalMatrix.appendRotation(modelZRot, Vector3D.Z_AXIS);
modelLocalMatrix.appendRotation(modelXRot, Vector3D.X_AXIS);
//eventually y-axis rotation as well...
renderMatrix.append(modelLocalMatrix);

Я предполагаю, что вместо использования констант оси Vector3D, я хочу использовать некоторый нормализованный вектор и некоторые... эээ... вещи... вместо modelZRot, modelXRot и, в конечном счете, modelYRot. Может кто-нибудь сказать мне, что лучшее решение для применения желаемого типа вращения выше?

ОБНОВЛЕНИЕ: потратив день на просмотр "книг" (он же KhanAcademy на YouTube) и начав эту презентацию здесь: Математика трехмерной матрицы вращения Я наткнулся на своего рода метод "взгляда", который очень близок к моему желанию. решение. К сожалению, я только на 50% понимаю это. Я все еще надеюсь, что кто-то может пролить свет на эту тему!

var angleOfRotation:Number = Math.PI / 2; //90 degrees...
var axisOfRotation:Vector3D = new Vector3D(0, 1, 0); //some point to look at... 
//normalize the vector!
axisOfRotation.normalize();
var x:Number = axisOfRotation.x;
var y:Number = axisOfRotation.y;
var z:Number = axisOfRotation.z;
var c:Number = Math.cos(angleOfRotation);
var s:Number = Math.sin(angleOfRotation);
var t:Number = 1 - c;

//Graphics Gems (Glassner, Academic Press, 1990). 
modelLocalMatrix = new Matrix3D(new <Number>[
  t * (x * x) + c,   t * x * y - s * z,   t * x * z + s * y,   0, 
  t * x * y + s * z,   t * (y * y) + c,   t * y * z - s * x,   0, 
  t * x * z - s * y,   t * y * z + s * x,   t * (z * z) + c,   0, 
  0,           0,           0,           1
]);

Дело в том, что это кажется довольно неуклюжим. Тем более что угол поворота для Vector3D должен быть четвертым (w) значением. Что еще более важно, у Matrix3D уже есть метод lookAt(). Я еще не понял... пожалуйста, кто-нибудь, спасите меня от проб и ошибок!

1 ответ

Решение

Хорошо, я в основном понял, как это сделать. Это НАМНОГО проще, чем я это делал. Это также помогло пересмотреть Matrix3D API (в нем есть несколько потрясающих функций!).

Во-первых, исходный код, который я использовал для поворота моей модели по ее локальным осям:

var raw:Vector.<Number> = modelLocalMatrix.rawData;
var right:Vector3D = new Vector3D(raw[0], raw[1], raw[2]);
var up:Vector3D = new Vector3D(raw[4], raw[5], raw[6]);
var out:Vector3D = new Vector3D(raw[8], raw[9], raw[10]);

modelLocalMatrix.appendRotation(modelXRot, right);
modelLocalMatrix.appendRotation(modelYRot, up);
modelLocalMatrix.appendRotation(modelZRot, out);

Нормализованные векторы "вверх", "вправо" и "выход" обсуждаются в ссылке в моем оригинальном посте. В основном это оси тангажа, рыскания и крена модели. Достаточно сказать, что когда вы инициализируете свой объект, эти векторы идентичны Vector3D.X_AXIS, Y_AXIS и Z_AXIS. Я извлек их, используя свойство Matrix3D.rawData, хотя может быть лучший способ.

Теперь вы можете вращаться вдоль любой из этих осей по своему выбору, но как только вы это сделаете, ориентация двух других осей сразу же изменится. Это имеет смысл. Ваша модель вращается, и ее "вправо", "вверх" и "вперед" теперь разные! Поэтому, если вы начнете вращаться по "правой" оси модели (помните, что это начинается так же, как глобальная X_AXIS), а затем вы хотите свернуть модель по ее оси "out", вам нужно получить ее из локальной модели. матрица. Очевидно, это больше не то же самое, что глобальная Z_AXIS. Обратите внимание, что я не вызываю Matrix3D.identity(). Если бы я сделал это, то оси моей модели были бы сброшены! Это нормально для моего цикла рендеринга, хотя мне пришлось немного изменить свой код (и образ мышления), так как я перезагружал все свои матрицы перед применением преобразований и вращений. Обратите внимание, что modelXRot, modelYRot и modelZRot хранят значение поворота в градусах.

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

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