Как повернуть фигуру в другой программе 3D, чтобы вращение совпадало с вращением в Blender? - PullRequest
0 голосов
/ 07 ноября 2018

Я импортирую сетку в Blender, экспортирую ее с настройкой axis_forward='-Z', axis_up='Y', импортирую в FleX от NVIDIA, поворачиваю ее и сохраняю на диске; Я называю эту сетку X. Я также импортирую сетку в Blender и вращаю ее столько же; Я называю эту сетку Y. После того, как я импортировал X в Blender (настройка axis_forward='-Z', axis_up='Y'), я понял, что X имеет другое вращение, что означает, что FleX использует разные глобальные оси (я думаю, что -Y вперед и Z вверх) или он применяет повороты в другом порядке или их комбинации. Так что я сейчас в замешательстве. Я не хочу ничего менять на стороне FleX. Однако я хочу повернуть Y таким образом, чтобы это соответствовало тому, что экспортирует FleX (X) после поворота. Я также попробовал с Quaternions, но я все еще не могу понять, как FleX трансформирует объект. Единственное, что мне удалось выяснить эмпирически, это то, что значение вращения rx применяется одинаково для FleX и Blender. Это означает, что объекты X и Y будут полностью перекрываться, если импортироваться в сцену в Blender.

Моя цель - вращать объект в FleX, чтобы вращение объекта Y точно совпадало с объектом X, когда я импортирую X в Blender. Например, я хочу, чтобы FleX вращал объект так же, как Блендер вращает его с вектором вращения Эйлера [rx, ry, rz]. Как мне этого добиться?

Обратите внимание , что я не изменяю порядок вращения в Blender и использую вращение по умолчанию XYZ.

Вот некоторые изображения визуальных различий между FleX и Blender для таких преобразований:

Вектор вращения Эйлера: [0, 89.9, 0] для объекта Y в Blender.

После применения вращения в Blender (объект Y): enter image description here

После применения того же вращения ([0, 89.9, 0]) в FleX и импорта объекта X в Blender: enter image description here

Вектор вращения Эйлера: [0, 0, 89.9] для объекта Y в Blender. enter image description here

После применения того же поворота ([0, 0, 89.9]) в FleX и импорта объекта X в Blender: enter image description here

Может показаться, что по изображениям FleX легко угадать ry и rz при применении поворота. Если я также поменяю местами ry и rz при применении вращений в Blender, то и X, и Y перекрываются. Однако это работает, только если все компоненты вектора вращения равны нулю, кроме одной из них. Если вектор вращения имеет вид, подобный [-43.964176, 20.641195, -1.2689421] X и Y, больше не перекрываются, и расхождения начинают проявляться, как показано ниже:

enter image description here

Расхождения более заметны, если я положу ткань на X в FleX, импортирую ткань и Y в Blender и повернем Y на [-43.964176, -1.2689421, 20.641195] (обратите внимание, что я поменялся ry и rz при применении вращения в Blender, а не в FleX):

enter image description here

Обратите внимание, что если я импортирую X здесь, ткань будет идеально прикрывать его, прикасаясь к нему на поверхности:

enter image description here

После некоторого взлома для последнего примера я заметил, что если применить вектор вращения [-43.964176, 1.2689421, 20.641195] (rx, -rz, ry), объекты почти полностью перекрываются:

enter image description here

В качестве другого примера, я хочу применить вращение [87.68034, 79.94778, 82.697876] в Blender, которое должно в идеале дать мне что-то вроде этого:

enter image description here

Тем не менее, FleX дает мне следующее (без обмена перед передачей вектора вращения в FleX):

enter image description here

Я думал, что, возможно, применение поворота в порядке (rx, -rz, ry) в Blender даст мне совершенно совпадающий результат, который я получил для предыдущего примера, но вместо этого я получил очень странные результаты для другого, как показано ниже. Обратите внимание, что я хотел повернуть объект на [87.68034, 79.94778, 82.697876] `:

enter image description here

Вращая объект вручную в Blender, я в конечном итоге мог получить его как можно ближе к Y (экспортировано из FleX). Удивительно, но вектор вращения, который перекрывает X и Y, сильно отличается от [87.68034, 79.94778, 82.697876] в (rx, ry, rz) или [87.68034 -82.697876, 79.94778] в (rx, -rz, ry). Это что-то около [5.38, -10.1, 88.6] в `(rx, ry, rz), как показано ниже:

enter image description here

Хотя вам может понадобиться больше информации, чтобы точно выяснить, что происходит, но ниже я публикую код, который используется в FleX для вычисления его матриц вращения. Верхний используется, когда используются углы Эйлера, а второй используется, когда вводятся кватернионы:

// generate a rotation matrix around an axis, from PBRT p74
inline Mat44 RotationMatrix(float angle, const Vec3& axis)
{
    Vec3 a = Normalize(axis);
    float s = sinf(angle);
    float c = cosf(angle);

    float m[4][4];

    m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;
    m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;
    m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
    m[0][3] = 0.0f;

    m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;
    m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;
    m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
    m[1][3] = 0.0f;

    m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;
    m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;
    m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;
    m[2][3] = 0.0f;

    m[3][0] = 0.0f;
    m[3][1] = 0.0f;
    m[3][2] = 0.0f;
    m[3][3] = 1.0f;

    return Mat44(&m[0][0]);
}


inline Mat44 RotationMatrix(Quat q)
{
    Matrix33 rotation(q);

    Matrix44 m;
    m.SetAxis(0, rotation.cols[0]);
    m.SetAxis(1, rotation.cols[1]);
    m.SetAxis(2, rotation.cols[2]);
    m.SetTranslation(Point3(0.0f));

    return m;
}

А вот как я применяю вектор вращения Эйлера:

obj->Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 1.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 0.0f, 1.0f)));

И я думаю, что так должно быть Transform():

void Mesh::Transform(const Matrix44& m)
{
    for (uint32_t i=0; i < m_positions.size(); ++i)
    {
        m_positions[i] = m*m_positions[i];
        m_normals[i] = m*m_normals[i];
    }
}

1 Ответ

0 голосов
/ 10 ноября 2018

Мне просто нужно было внести следующие изменения, чтобы [вручную] изменить систему координат FleX на ту, которую использует Blender:

obj->Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 0.0f, -1.0f)))
obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 1.0f, 0.0f)));

То, как я это понял, я сгенерировал три вектора вращения [90, 0, 0], [0, 90, 0] и [0, 0, 90] и повернул фигуры в FleX. Затем я загрузил фигуры в Blender и эмпирически вычислил вращение, ось которого в Blender соответствует фигуре, импортированной из FleX. Я узнал, что когда я поворачиваю фигуру по оси Y на 90 градусов в Blender, она совпадает с поворотом на 90 градусов по оси Z в FleX. Кроме того, я узнал, что поворот объекта на -90 градусов по оси Z в Blender совпадает с поворотом на 90 градусов по оси Y в FleX.

...