Графический дизайн, арт игры, концепт, персонажи, текстуры, анимации, модели
GameDev.ru / Графический Дизайн / Форум / Unity -> BVH -<- Blender

Unity -> BVH -<- Blender

TrouyanПостоялецwww8 июня 201814:52#0
Добрый день.
Больше месяца бьюсь над проблемой перевода анимации из юнити в BVH файл чтобы Blender его адекватно прочитал.

Сейчас сравниваю кватернионы локальной ориентации одной из кости тела скелетона в юнити и блендере. Данная кость наклонена двумя поворотами относительно начального положения.
Результаты двух сравнений(поворот по вертикальной оси + наклон вперед/назад) ниже на картинке :

Blender Unity | Unity -> BVH -<- Blender


Рассчитываю кватернион локальной ориентации кости в Unity следующим образом:

Qlocal=(Qparentglobal)^-1 * Qglobal

Далее рассчитываю ориентацию этой кости относительно начальной(стартовой) ориентации данной кости

Q=Qlocal * (QStartLocal)^-1  // в моем примере это пока ни на что не влияет т.к. QStartLocal={-1,0,0,0}


Я не понимаю как блендер рассчитывает локальную ориентацию кости... чтобы потом ее преобразовав в углы Эйлера записать в BVH файл.
Знаю что в Юнити и Блендере разные СК. Но Я не вижу алгоритма как их связать .....

Традиционный рекомендуемый на многих форумах алгоритм:
w=-w
x=x
y=z
z=y
не подходит


Помогите пожааалуйста...

Правка: 8 июня 2018 14:53

TrouyanПостоялецwww8 июня 201814:56#1
.... тааак, может попробовать :
w=-w
x=-x
y=y
z=z

Да, похоже на то... прозрел пока писал )))) А почему так ?

Правка: 8 июня 2018 15:00

SuslikМодераторwww8 июня 201819:09#2
Trouyan
потому что в них разные системы координат, а представление кватерниона зависит от ориентации системы координат.
TrouyanПостоялецwww13 июня 201815:45#3
Suslik, спасибо!

новая проблема =(
Хочу понять как Blender рассчитывает BVH файл, для этого в модели левую ногу повернул вокруг ее оси на 45 и поднял вперед на 60 град как на рисунке ниже.
Blender BVH Troble | Unity -> BVH -<- Blender
Кватернион ориентации ноги (взят из Блендера):
w=0,8
x=-0,462
y=-0,331
z=-0,191

Экспортирую модель из Blender в BVH файл и далее читаю его, там написано:
x= -59.823714
y= -29.708376
z= 21.164062

Далее пытался и в Блендере и в этой утилите: http://andre-gaschler.com/rotationconverter/ найти по какому алгоритму он рассчитывает углы Эйлера но ни один не подходит !!! Я в тупике ... просто не понимаю как так !??!

Правка: 13 июня 2018 15:47

SpeedLuckyЗабаненwww13 июня 201816:45#4
там кажется при импорте или экспорте надо ставить галочку какую-то чтобы инвертировать оси, или указать какая ось в качестве Z. что-такое,
поищи на ютубе.
TrouyanПостоялецwww13 июня 201818:02#5
Да, там при импорте есть возможность выбора осей, в результате после экспорта получаем другие улы....
не понимаю куда копать, вроде неделю назад настроил все углы Эйлера  кроме рута (первый пост был об этом). Потом сделал рут слетели остальные кости....
TrouyanПостоялецwww13 июня 201818:44#6
В общем, имею модель человека в Unity и пытаюсь сделать BVH файл, ниже алгоритм:

Всё дерево BVH фала строю так:
Root (поясница) 6 координат:  "  CHANNELS 6 Xposition Yposition Zposition Xrotation Yrotation Zrotation"
Остальные кости: "CHANNELS 3 Xrotation Yrotation Zrotation"

Сохранение кадра:

            ....
            rotQuat = GetBoneLocalRotation(HumanMotion.BVH_ID_BONE_ORDER[i]) * m_aZeroRot[i];  // Здесь ZeroRot Для смещения отсчета  относительно нулевого кадра
            TMPRotQ = rotQuat;
            rotQuat.x = TMPRotQ.y;
            rotQuat.y = TMPRotQ.x;
            rotQuat.z = -TMPRotQ.z;
            rotVect = CMyMath.GetEulerAngles(rotQuat, CMyMath.RotSeq.zxy)
  
 File.AppendAllText(filename_tmp, "\t" + rotVect.z.ToString("0.000") + "\t" + rotVect.x.ToString("0.000") + "\t" + rotVect.y.ToString("0.000"));

Расчет локальной ориентации кости:

Quaternion GetBoneLocalRotation(uint IDbone)
...
                // ID родительской кости
                int IDParentBone = (int)GetIDParentBone(IDbone);
                q1 = HumanMotion.m_aBVHBones[IDbone].rotation;
                q2 = HumanMotion.m_aBVHBones[IDParentBone].rotation;
                q = Quaternion.Inverse(q2) * q1; 
...

m_aZeroRot = это инвертированная локальная Ориентация кости в нулевом кадре.

Для расчета углов Эйлера нахожу сначала из кватерниона матрицу

            public static Vector3 GetEulerAngles(Quaternion Q,RotSeq rotSeq)
            {
                Vector3 V;
                float[][] M = new float[3][];   // матрица поворота
                for (int i = 0; i < 3; i++)
                    M[i] = new float[3];
                float a = Q.w;
                float b = Q.x;
                float c = Q.y;
                float d = Q.z;
                //Создаем матрицу поворота
                // первая строка
                M[0][0] = a * a + b * b - c * c - d * d;
                M[0][1] = 2 * b * c - 2 * a * d;
                M[0][2] = 2 * b * d + 2 * a * c;
                // вторая строка
                M[1][0] = 2 * b * c + 2 * a * d;
                M[1][1] = a * a - b * b + c * c - d * d;
                M[1][2] = 2 * c * d - 2 * a * b;
                // третья строка
                M[2][0]= 2 * b * d - 2 * a * c;
                M[2][1] = 2 * c * d + 2 * a * b;
                M[2][2] = a * a - b * b - c * c + d * d;

                V = MatrixToEuler(M, rotSeq);
                
                return V;
            }

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

Но всё равно в результате что-то ерунда получается.... нету понимания как эти углы рассчитываются, много литературы прочитал, но всё равно остаюсь в тупике =/ от Offsets тоже эти углы зависят ... а Offsets задаются при описании иерархии костей

/ Форум / Графический Дизайн / Моделирование

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