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

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

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

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

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

Start position

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

X-axis rotation

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

Z-axis rotation

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

desired XZ rotation

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

enter image description here

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

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

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

ОБНОВЛЕНИЕ: Потратив день на просмотр «книг» (он же 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 Ответ

2 голосов
/ 23 ноября 2011

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

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

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 хранят значение поворота в градусах.

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

...