Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Преобразовании матрицы в Position, Rotation, Scale, а потом обратно

Преобразовании матрицы в Position, Rotation, Scale, а потом обратно

Страницы: 1 2 Следующая »
DivisionПостоялецwww6 янв. 201813:02#0
Привет. Делаю скелетную анимацию и столкнулся с проблемой.
Написал скрипт экспорта collada -> свой формат. Скрипт читает матрицы костей из коллады, получает из них позицию, кватернион, масштабирование.
Потом при проигрывании анимации я собираю матрицы из pos / rot / scale и передаю в шейдер.
Работает всё ок, кроме того, что модель выглядит криво, когда некоторые матрицы при преобразовании в pos / rot / scale, а потом обратно, не соответствую изначальным.
Причём замечал я это только с корневой костью, которая довольно сильно повёрнута чтоб модель была головой наверх.

Пример:

// Hard code 'broken' matrix
mat4.set(this._transform, 6.76443e-7, 2.54, 0, 0, 0, 0, 2.54, 0, 2.54, -6.76443e-7, 0, 0, 3.94238e-7, 132.1051, -6.627069, 1);
console.info('SRC matrix', this._transform);

// Get components
mat4.getRotation(this._rotation, this._transform);
quat.normalize(this._rotation, this._rotation);
mat4.getScaling(this._scale, this._transform);
mat4.getTranslation(this._position, this._transform);
        
console.info('PRS', this._position, this._rotation, this._scale);

mat4.fromRotationTranslationScale(this._transform, this._rotation, this._position, this._scale);
console.info('generated matrix', this._transform);


================
Output:

SRC matrix:
[6.764429940631089e-7, 2.5399999618530273, 0, 0, 
 0, 0, 2.5399999618530273, 0, 
 2.5399999618530273, -6.764429940631089e-7, 0, 0, 
 3.942379862564849e-7, 132.1051025390625, -6.627068996429443, 1]

->

Translation: [3.942379862564849e-7, 132.1051025390625, -6.627068996429443] 
Quaternion(normalized): [0.5629895925521851, 0.5629894137382507, 0.5629894137382507, 0.22164954245090485] 
Scale: [2.5399999618530273, 2.5399999618530273, 2.5399999618530273]

->

Generated matrix: 
[-0.6802839040756226, 2.2440571784973145, 0.9762278199195862, 0, 
0.9762278199195862, -0.6802849173545837, 2.2440567016601562, 0, 
2.2440571784973145, 0.9762271046638489, -0.6802849173545837, 0, 
3.942379862564849e-7, 132.1051025390625, -6.627068996429443, 1]

Пробовал нормализовывать и не нормализовывать кватернион, не помогает.

Пишу на js, использую эту мат либу:
https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/mat4.js#L1003
Код либы основывается на этом: http://www.euclideanspace.com/maths/geometry/rotations/conversion… ion/index.htm

Что я делаю неправильно?

Правка: 6 янв. 2018 13:03

foxesПостоялецwww6 янв. 201813:33#1
Из матрицы ты можешь вытащить только Translation. Можно попробовать вытащить Scale через длину каждой оси, но если это многослойное преобразование с разными масштабами то про это можно забыть. Также чтобы вытащить из матрицы поворот нужны единичные ортогональные вектора без масштаба.

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

Правка: 6 янв. 2018 15:13

SuslikМодераторwww6 янв. 201813:37#2
Division
> Написал скрипт экспорта collada -> свой формат. Скрипт читает матрицы костей из
> коллады, получает из них позицию, кватернион, масштабирование.
> Потом при проигрывании анимации я собираю матрицы из pos / rot / scale и
> передаю в шейдер.
как ты думаешь, почему в колладе они хранятся как отдельные поворот и масштабирование?
DivisionПостоялецwww6 янв. 201815:04#3
Suslik
В колладе при экспорте можно настроить, экспортировать трансформации в виде матриц или нет. Матрицы естественно удобней читать.
Я пишу в свой формат отдельно position / rotation / scale потому что мне так удобней + меньше данных.
Матрицы, которые лежат в колладе - правильные, я проверил.


foxes
Поищу


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

UPD:
Suslik, предлагаешь использовать колладу без матриц, с отдельными position / euler angles / scale? Да наверно это бы решило мою проблему, надо попробовать.

Правка: 6 янв. 2018 15:25

foxesПостоялецwww6 янв. 201815:23#4
Division
> без конвертаций туда-сюда.
Мне кажется сама конвертация на производительность будет влиять, особенно обратная, так что лучше без нее. Опять же если матрица хранит только один слой преобразований TRS то это обратимо.
Конкретно в твоей задаче неправильно считается поворот. потому что вот эти вектора надо с начало нормализовать.
(6.764429940631089e-7, 2.5399999618530273, 0)
(0, 0, 2.5399999618530273)
(2.5399999618530273, -6.764429940631089e-7, 0)

А потом уже считать из них кватернион. Опять же неизвестно каким алгоритмом ты это считаешь. Можно использовать LookAt, вектор (0, 0, 2.5399999618530273) это вектор вверх, а (2.5399999618530273, -6.764429940631089e-7, 0) направление взгляда. Нормализовать сам кватернион по моему бесполезно.

Правка: 6 янв. 2018 16:40

DivisionПостоялецwww6 янв. 201815:41#5
foxes
Конвертация на этапе экспорта, не важно. Вообще наверно сделаю как Suslik советует. По нормализации сейчас проверю.

Правка: 6 янв. 2018 15:41

foxesПостоялецwww6 янв. 201815:43#6
Division
> Вообще наверно сделаю как Suslik советует.
Это очевидно.
DivisionПостоялецwww6 янв. 201816:21#7
foxes
Спасибо большое, нормализация базиса решила проблему. Поправил экспорт и всё заработало:
https://monosnap.com/file/xV6n3VeEAZZ28pJ2GjtDU7buxhqxIh

Ну и для меня это в разы проще, чем парсить трансформации из коллады покомпонентно

Правка: 6 янв. 2018 16:22

AndreyПостоялецwww6 янв. 201817:03#8
Division
И как тебе Collada ? нету проблем с ней? а то не все ее жалуют.
DivisionПостоялецwww6 янв. 201817:43#9
Andrey
Я ж в продакшене не использовал. Просто балуюсь. Из сложностей:
- Экспортить (из Maya) может быть придётся сторонним плагином, тк нативный экспорт умеет не всё (кастомные проперти точно не умеет)
- Может потребоваться конвертировать LHS <-> RHS, тк при экспорте в .dae такой опции я не видел (в плагине).
- Приходится вникать в формат, читать спецификацию. Возможно с чем-то вроде FBX SDK это проще.
AndreyПостоялецwww6 янв. 201818:12#10
Division
понятно, спасибо за инфу.
innuendoПостоялецwww6 янв. 201818:55#11
Andrey
> И как тебе Collada ? нету проблем с ней? а то не все ее жалуют.

наши художники не особо любят, но используют ... а где ты работаешь ?

DivisionПостоялецwww6 янв. 201822:28#12
innuendo
А где ты работаешь?
nesПостоялецwww7 янв. 201814:49#13
Division
У иннуенды "где ты работаешь" длиннее.
werasaimonПостоялецwww9 янв. 201820:46#14
foxes
> Из матрицы ты можешь вытащить только Translation
С матрицы можно вытащит всю композицию переобразований , то бишь Translation Rotation Scale , при чём это можно сделать без всяких дополнительных единичных осей!
С чего ты взял что это сделать неможно?
static void DecomposeMatrixToComponents(const float *matrix, float *translation, float *rotation, float *scale)
        {
            Matrix4 mat = *(Matrix4*)matrix;

            scale[0] = mat.v.right.length();
            scale[1] = mat.v.up.length();
            scale[2] = mat.v.dir.length();

            mat.OrthoNormalize();

            rotation[0] = RAD2DEG * atan2f(mat.m[1][2], mat.m[2][2]);
            rotation[1] = RAD2DEG * atan2f(-mat.m[0][2], sqrtf(mat.m[1][2] * mat.m[1][2] + mat.m[2][2]* mat.m[2][2]));
            rotation[2] = RAD2DEG * atan2f(mat.m[0][1], mat.m[0][0]);

            translation[0] = mat.v.position.x;
            translation[1] = mat.v.position.y;
            translation[2] = mat.v.position.z;
        }

[Right_4, Up_4 ,Dir_4, Position_4 ] = M_4x4

Правка: 9 янв. 2018 20:58

Страницы: 1 2 Следующая »

/ Форум / Программирование игр / Графика

Тема закрыта.

2001—2018 © GameDev.ru — Разработка игр