кватернионы — преобразование ориентации приложения 3ds max в C ++ / DirectX

Я хочу экспортировать объект из 3ds max в мое приложение C ++ / DirectX, и у меня возникла проблема с ориентация экспорта.

3ds Max использует правша Z-Up система координат и мое приложение использует левша Y-Up система координат. я использую {x, y, z, w} обозначения компонентов во всем этом вопросе.

У меня есть 3 кости (или любые другие иерархические объекты) в 3ds Max:

Для экспорта их ориентации я использую MaxScript:

if hasParent then
localOrientation = boneNode.transform.rotationPart * inverse boneNode.parent.transform.rotationPart
else
localOrientation = boneNode.transform.rotationPart

Я сохраняю эту локальную ориентацию в файл:

BoneRoot no_parent 0.707107 0.0 0.0 0.707107 //stands for (-90, 0, 0) Euler rotation in 3ds max UI
Bone001 BoneRoot 0.0 -0.382683 0.0 0.92388 //local orientation (parent space)
Bone002 Bone001 -0.353553 -0.612372 0.353553 -0.612372

Я читал, что, несмотря на 3ds Max петь правую систему координат, это использует левостороннюю систему для transform.rotationPart,

Мой вопрос Как теперь преобразовать локальное вращение из этого файла в мое приложение? Может быть, я должен применить некоторые преобразования только корень кости? Я попытался применить это к каждой ориентации кости:

Quaternion convertFrom3dsMax(const Quaternion &input) {
auto q = input;
//swap Y and Z
auto temp = q.getZ();
q.setZ(q.getY());
q.setY(temp);

//invert
//q.setX(-q.getX());
q.setY(-q.getY());
q.setZ(-q.getZ());
q.setW(-q.getW());
return q;
}

И многие другие комбинации обмена осями, инвертирования аргументов и даже оставления всего как есть. Но каждый из моих импортных файловых костей ориентирован неправильно.


Дополнительная информация (при необходимости):

Моя сцена 3ds max выглядит так:
введите описание изображения здесь

И мое заявление (для convertFrom3dsMax функция, которую я представил; не зацикливайтесь на меше, который просто помощник, смотреть на линии которые представляют кости):
введите описание изображения здесь
(например, но не только, последняя кость идет вверх, а не вниз)

Когда я не применяю ничего к загруженным кватерионам в моем convertFrom3dsMax сцена выглядит так:
введите описание изображения здесь
(например, но не только, средняя кость движется «от» вместо «к» экрану)

Обратите внимание, что я использую операции левой руки для DirectX в моем приложении (например, XMMatrixLookAtLH(...)) и я отношусь к Y как «вверх».

Матрица вращения в приложении:

DirectX::XMMATRIX rotationMatrix = DirectX::XMMatrixRotationQuaternion(
DirectX::XMVectorSet(
object->global.getX(),
object->global.getY(),
object->global.getZ(),
object->global.getW()
)
);

И глобальная ориентация рассчитывается так: global = local * parent->global где local загружается для каждой кости из файла (с помощью convertFrom3dsMax) а также operator* определяется как:

Quaternion operator* (const Quaternion by) const {
//"R" for result
float wR = w * by.getW() - x * by.getX() - y * by.getY() - z * by.getZ();
float xR = x * by.getW() + w * by.getX() + y * by.getZ() - z * by.getY();
float yR = y * by.getW() + w * by.getY() + z * by.getX() - x * by.getZ();
float zR = z * by.getW() + w * by.getZ() + x * by.getY() - y * by.getX();
return Quaternion(xR, yR, zR, wR);
}

Я высоко ценю convertFrom3dsMax как источник моих проблем (а не математика Quaternion или вызовы DirectX внутри приложения).


Для положения, которое не так сложно, как ориентация, которую я использую boneNode.transform.pos а также:

Point3D convertFrom3dsMax(const Point3D &input) {
auto result = input;
//swap Y and Z
auto tempZ = result.getZ();
result.setZ(result.getY());
result.setY(tempZ);
return result;
}

которая выглядит правильно (начальная позиция каждой линии / кости в порядке, позиция не повернутых вершин вспомогательной сетки в порядке).

14

Решение

С 3DS, используя RH Z-Up, и вы используете LH Y up. Самое простое — игнорировать ось X, поскольку она не меняется; просто скопируйте данные. Вам нужно поменять местами 3DS Up — Z с Y — Up. После перестановки этих двух осей вам нужно инвертировать Z после перестановки; это связано с тем, что система LH + z выходит из экрана к вам.

Пример:

3DS Max указывают в RHS как [Право (+ x), Вверх (+ z), Вперед (+ y)] и с вашей LHS [Вправо (+ x), Вверх (+ y) и Вперед (-z)] , Поэтому, если у вас есть вершина или точка в системе RHS, такая как [3,4,5], когда вы переходите в свою систему LHS, точка должна теперь быть [3,5, -4]. Предполагая, что + Z в вашем LHS выходит из экрана.

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

Так это должно выглядеть примерно так:

mat4 convertRHStoLHS( mat4 model ) {
mat 4 newModel;
newModel.x = model.x;   // Where X is X-Axis
newModel.y = model.z;   //       Y is Y-Axis & Z is Z-Axis
newModel.z = -model.y;  //       Z is Z-Axis & Y is Y-Axis

return newModel;
}

Где mat4 будет матрица преобразования модели вашей модели в пространстве модели.

1

Другие решения

Других решений пока нет …