Вращающиеся объекты, прикрепленные к другим объектам

У меня есть вопрос, касающийся одной сетки (здания), которая содержит коллекцию анимированных объектов (эти объекты составляют законченное здание, поднимаясь над землей, когда оно строится, с разными скоростями и вращениями).

Все анимированные объекты в сетке имеют свои собственные дорожки анимации положения и вращения. Я экспортирую его из 3DS Max как ASE, конвертирую в подходящий формат и использую в своем игровом движке.

Итак, на данный момент я могу успешно отображать анимированные позиции всех анимированных объектов в сетке. Делать следующее:

Переменные масштаба, поворота и перевода - это информация о преобразовании здания. Это действительно для всех подобъектов. Переменная pos указывает положение подобъектов относительно центра здания.

foreach (GeometricObject geoObject in mesh.GeoObjects)
{
  Vector3 pos = geoObject.AnimationData.PositionTrack[(int)m_keyFrameTime];
  Vector3 translatedPos = new Vector3(translation.X + pos.X, 
                                      translation.Y + pos.Y, 
                                      translation.Z + pos.Z)
  _eRenderer.ActiveCamera.World = Matrix.CreateScale(scale) *
                    Matrix.CreateFromQuaternion(rotation) *
                    Matrix.CreateTranslation(translatedPos);
}

Это прекрасно отображает анимированное здание (поднимающееся с земли), и все субобъекты находятся в правильных положениях.

Теперь проблема возникает, когда я пытаюсь повернуть подчиненные объекты. Я испробовал несколько разных подходов, но перевод подобъектов всегда, кажется, запутался после того, как я повернул подобъект. Это то, что у меня есть в настоящее время, но оно все еще запутано:

foreach (GeometricObject geoObject in mesh.GeoObjects)
{
  Vector3 pos = geoObject.AnimationData.PositionTrack[(int)m_keyFrameTime];
  Vector3 translatedPos = new Vector3(translation.X, translation.Y, translation.Z)

  Matrix rotateSubObjects; 
  rotateSubObjects = Matrix.CreateTranslation(new Vector3(pos.X, pos.Y, pos.Z));
  rotateSubObjects *= Matrix.CreateFromQuaternion(geoObject.AnimationData.RotationTrack[(int)m_keyFrameTime]);

  _eRenderer.ActiveCamera.World = Matrix.CreateScale(scale) *
                    Matrix.CreateFromQuaternion(rotation) *
                    Matrix.CreateTranslation(translatedPos) *
                                  rotateSubObjects;
}

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

У меня нет идей, любая помощь будет оценена! С уважением, Риан.

1 ответ

Решение

Преобразование, которое вы ищете, таково:

Matrix positionRotationMatrix = Matrix.CreateTranslation(-parentPosition) 
                               * Matrix.CreateFromQuaternion(parentRotation) 
                               * Matrix.CreateTranslation(parentPosition);
Vector3 translation = Vector3.Transform(parentPosition + relativePosition,
                               positionRotationMatrix);

Вы определяете свою мировую матрицу с новой позицией подобъектов (translation переменная):

Matrix worldMatrix = Matrix.CreateScale(scale)
                * Matrix.CreateFromQuaternion(rotation)
                * Matrix.CreateFromQuaternion(parentRotation)
                * Matrix.CreateTranslation(translation);

Чтобы продемонстрировать, вот куб (родитель), который вращается вокруг своей позиции со стрелкой, положение и вращение которой определены относительно его родительской позиции и вращения. Стрелка следует за вращением куба и вращается вокруг своей оси Z независимо.

Значения, использованные для демонстрации:

parentPosition = Vector3(-1.1f, 0f, -2); //cube
relativePosition = Vector3(0, 0, -3); //arrow
parentRotation = Quaternion.CreateFromRotationMatrix(
                       Matrix.CreateRotationZ(angle) 
                     * Matrix.CreateRotationY(angle) 
                     * Matrix.CreateRotationX(0.5f));
rotation = Quaternion.CreateFromYawPitchRoll(0f, 0f, angle);
angle += 0.05f;
Другие вопросы по тегам