Това, до което стигнах чрез проба и грешка, работи, бихте ли обяснили защо?

Първо, не бях сигурен дали този въпрос е добре дошъл тук и проверих ЧЗВ и открих, че „Бих искал другите да обясни" въпросите са.

Основният проблем е, че трябва да съхранявам ротациите на всички обекти два пъти в моето приложение. Това е така, защото от една страна физическата симулация, за която използвам Bullet Physics, съхранява своето представяне. От друга страна, аз сам съхранявам ротации, които са общи за всички обекти, независимо дали са във физическата симулация или не, като светлини, мишени за мисии и т.н. В допълнение към библиотеката по физика използвам библиотеката по математика GLM.

Трябва да синхронизирам и двете представяния. Между другото позициите и мащабът не създават проблеми. Трудността е, че физическата симулация всяко мое собствено представяне е различно, така че не мога просто да копирам стойности. Не съм открил всички тези разлики, но може да е свързано с лявата спрямо дясната координатна система, градусите спрямо радианите и Y координатата нагоре срещу Z нагоре.

Моето собствено представяне просто съхранява ъгли на Ойлер в glm::vec3 вектор. Тъй като използвам OpenGL за рисуване, предполагам, че пространството е дясно. За ъглите на Ойлер редът има значение. Това, което правя, за да изчисля ротационна матрица, е първо да създам матрица на всеки компонент и след това да ги умножа в X * Y * Z ред. Освен това в моето собствено представяне положителната Y координата сочи нагоре.

Физическата симулация използва кватерниони за съхраняване на ротации. След известно проучване прочетох предположението, че пространството е лява ръка в тази библиотека. Нямам информация коя координата е нагоре, нито в какъв ред се връщат ъглите на Ойлер.

Тук идва кодът за преобразуване на ротации от физична симулация в мое собствено представяне и обратно.

#include <GLM/glm.hpp>
#include <GLM/gtc/quaternion.hpp>
#include <BULLET/btBulletDynamicsCommon.h>

/*******************************************************************
 * euler angles "glm::vec3 input" from my own representation
 * to quaternion "btQuaternion output" of physics simulation
 *******************************************************************/
glm::quat quaternion(glm::vec3(input.x, input.z, input.y) * 3.14159f / 180.f);
btQuaternion output(quaternion.x, quaternion.y, quaternion.z, quaternion.w);

/*******************************************************************
 * quaternion "btQuaternion input" from physics simulation
 * to euler angles "glm::vec3 output" of my own representation
 *******************************************************************/
glm::quat quaternion(input.getW(), -input.getX(), -input.getY(), -input.getZ());
glm::vec3 angles = glm::eulerAngles(quaternion);
glm::vec3 output(-angles.x, -angles.y, -angles.z);

Намерих този мръсен код чрез проба и грешка и работи. Но както можете да видите там отрицания, промяна на компоненти и преобразувания на типове чрез различни типове кватерниони. Предполагам, че много от тях са ненужни и задачата може да се изпълни много по-лесно.

Бихте ли обяснили защо преобразуванията ми работят и как да ги опростя? Между другото, искам да видя как изглежда, ако преобразуването не работи, ето екранна снимка...


person danijar    schedule 30.04.2013    source източник
comment
Преобразуването обратимо ли е? Т.е., какво се случва, ако преобразувате вашите ъгли на Ойлер в кватернион и обратно, без да ги променяте? Освен това няма ли грешка в реда на аргументите в първия ред? Не трябва ли да е input.x, input.y, input.z?   -  person F.X.    schedule 30.04.2013
comment
Изглежда като грешка, но това е, което измислих случайно. Последователният ред, както предполагате, че е правилен, не работи. Проверих дали преобразуването е обратимо и не е. Например ъглите на Ойлер 2, 5, 52 се връщат като -3.15, 51.9, 5.56. Но не знам дали това представлява същата ротация. Доколкото знам, има безкрайно различни начини за представяне на едно и също въртене чрез ъгли на Ойлер.   -  person danijar    schedule 30.04.2013


Отговори (1)


Очевидно има много различни дефиниции на Ойлерови ъгли и вашите две библиотеки използват различни конвенции.

От източника на GLM те използват Pitch , Yaw, Roll :

template <typename T> 
GLM_FUNC_QUALIFIER detail::tvec3<T> eulerAngles
(
    detail::tquat<T> const & x
)
{
    return detail::tvec3<T>(pitch(x), yaw(x), roll(x));
}

... докато в документацията на Bullet те използват Yaw, Pitch, Roll .

Не съм проверил, но съставянето на завъртания определено не е комутативно, което би обяснило вземането на отрицателните стойности на някои координати -- същото като вземането на обратното завъртане.

person F.X.    schedule 30.04.2013
comment
Така че редът на ъглите на Ойлер определено е причина. Знаете ли как да опростите реализациите? - person danijar; 30.04.2013
comment
Хм, изглежда толкова просто, колкото може да се получи, честно. Просто напишете някои модулни тестове, за да сте сигурни, че няма да се забърквате много с това след това;) - person F.X.; 30.04.2013
comment
Моят код изглежда ли ви разумен? Аз лично не разбирам защо работи. - person danijar; 01.05.2013
comment
За първото преобразуване има смисъл, ако двете координатни оси са с различна посока, т.е. използвате XYZ, тогава трябва да преобразувате в различна посока (XZY), след което да създадете кватернион от тези ъгли. - person F.X.; 01.05.2013
comment
Всъщност, поглеждайки назад към отговора ми, той може да не е точен. Има нещо друго в играта и не мога да разбера какво. Има ли причина да не можете да използвате кватерниони докрай, тъй като те не зависят от ръчността? - person F.X.; 01.05.2013
comment
Да, искам да използвам ъгли на Ойлер в интерфейса, защото са по-лесни за представяне, да речем за художници и сценаристи. Благодарение на вашето обяснение сега разбирам и първото преобразуване. За съжаление второто все още не е ясно. - person danijar; 02.05.2013
comment
Разбирам мисълта ти. Честно казано, все още не разбирам как работи цялата работа, ще трябва да се заровите в математиката, за да направите това. Но не можете ли просто да съхранявате и използвате кватерниони вътрешно и да ги конвертирате само ако ги показвате на потребителя? Ще ви бъде много по-лесно, тъй като ще трябва да работите само с един тип променлива. Нещо повече, те се справят с ротациите много по-естествено, математически казано, отколкото ъглите на Ойлер. - person F.X.; 03.05.2013
comment
Ще го обмисля. Благодаря за вашата помощ. - person danijar; 03.05.2013