Использование кватернионов для обновления камеры на основе Эйлера с помощью glm

#c #3d #glm #quaternions #euler-angles

Вопрос:

У меня есть структура, которую я передаю в качестве аргумента. Идея заключается в том, чтобы создать кватернион с помощью slerp функции, сравнивая кватернион объекта камеры и некоторую другую целевую amp;t ориентацию.

Проблема, вероятно, в том, что я не понимаю математику. В настоящее время камера работает с углами Эйлера (в настоящее время у меня с этим проблем нет). Поэтому я хочу взять кватернион slerp, преобразовать его в Эйлера, применить преобразование к векторам камеры, а затем сохранить новую четверть на основе новых значений Эйлера для использования в качестве сравнения.

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

Структура, которую я передаю, передается в качестве аргумента для std::function члена в другом месте:

 struct panning_camera_handle {  Camera* cam;   bool operator ()(glm::quatamp; s, const glm::quatamp; t) {  float dps{ 180.0f }; // degrees per second   //first calculate the distance (angular magnitude between two rotation quaternions)  float cosOmega = glm::dot(s, t);  float sinOmega = glm::sqrt(1.0f - cosOmega * cosOmega);  float omega = glm::degrees(atan2(sinOmega, cosOmega)); // the diff. angle   if (omega lt; 1.0f) {  // CALC QUAT TO MOVE ORIENTATION TO TARGET  auto q = glm::slerp(s, t, 1.0f); //single slerp step  cam-gt;update_camera_vectors(q);   return true; //if angular distance is very small  } //we are done, return true.  else {  float min = dps * ejn::deltaTime * 0.001f; // min ang. displacement this cycle   if (omega lt; min) {  //CALC AS ABOVE   auto q = glm::slerp(s, t, 1.0f); //single slerp step  cam-gt;update_camera_vectors(q);  return true;  }  else {  //CALC THE INCREMENT AND UPDATE CAMERA VECTORS  float tt = min / omega;  auto q = glm::slerp(s, t, tt);   cam-gt;update_camera_vectors(q);   return false; //test for completion on next cycle  }  }  } };  

Текущая редакция функции камеры (их было несколько…), которую я хотел бы изменить. Обратите внимание на orient элемент, который является переменной, которую я хочу использовать для дальнейших сравнений в приведенной выше структуре.

 void enjyn_Camera::update_camera_vectors(glm::quat q) {  eul = glm::degrees(glm::eulerAngles(q));    if (eul.x gt; 89.0f)  eul.x = 89.0f;   if (eul.x lt; -89.0f)  eul.x = -89.0f;   glm::vec3 front;  front.x = cos(glm::radians(eul.y)) * cos(glm::radians(eul.x));  front.y = sin(glm::radians(eul.x));  front.z = sin(glm::radians(eul.y)) * cos(glm::radians(eul.x));   Front = Front   glm::normalize(front);  Right = glm::normalize(glm::cross(Front, WorldUp)); // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.  Up = glm::normalize(glm::cross(Right, Front));   orient = glm::quat(glm::radians(eul)); }