Вот немного фона : я работаю над игровым движком, и недавно я добавил физический движок (в данном случае Physx).проблема в том, что мой класс преобразования использует углы Эйлера для вращения, а класс преобразования физического движка использует углы Эйлера.поэтому я просто реализовал метод, чтобы изменить класс преобразования на преобразование физического движка и обратно.Это работает хорошо, но я обнаружил странную ошибку.
Поведение, которое я получаю:
Когда угол поворота (второй элемент вектора Эйлера) вращения выше 90 градусов, он больше не заставляет объект вращаться наось у и начало возятся с полем и креном (странные тряски пропускают от 0 до 180 и много назад).Инструменты отладки показывают, что вращение не превышает 91, а достигает 90.0003 макс. Я передаю градусы в радианы. Пример: Чтобы показать эту ошибку, у меня есть куб с вращающимся скриптом Python:
from TOEngine import *
class rotate:
direction = vec3(0,10,0)
def Start(self):
pass
def Update(self,deltaTime):
transform.Rotate(self.direction*deltaTime*5)
pass
Сам движок написан на cpp, но у меня есть система сценариев, работающая со встроенным python.TOEngine - это просто мой модуль, а сам скрипт просто вращает куб каждый кадр.Куб начинается с 0, 0, 0 вращения и вращается нормально, но останавливается и поворачивается на 90 градусов и начинает дрожать.
Это происходит только тогда, когда физическая система включена, поэтому я знаю, что ошибка должна быть в методе передачивращение от эйлера к квату и обратно каждый кадр с использованием glm.
Вот фактический проблемный код :
void RigidBody::SetTransform(Transform transform)
{
glm::vec3 axis = transform.rotation;
rigidbody->setGlobalPose(PxTransform(*(PxVec3*)&transform.position,*(PxQuat*)&glm::quat(glm::radians(transform.rotation))));//Attention Over Here
}
Transform RigidBody::GetTransform()
{
auto t = rigidbody->getGlobalPose();
return Transform(*(glm::vec3*)&t.p, glm::degrees(glm::eulerAngles(*(glm::quat*)&t.q)), entity->transform.scale);
}
Избегайте странного типа ударов PxQuat в основном то же самоепоскольку glm :: quat и PxVec3 в основном совпадают с glm :: vec3.Я ожидаю, что этот код будет передаваться между классом преобразования физического движка и моим классом преобразования, изменяя угол поворота с угла падения Эйлера на кват с радианами ( жесткая часть ).
И внутрифизическая система:
void PreUpdate(float deltaTime)override { //Set Physics simulation changes to the scene
mScene->fetchResults(true);
for (auto entity : Events::scene->entities)
for (auto component : entity->components)
if (component->GetName() == "RigidBody")
entity->transform = ((RigidBody*)component)->GetTransform(); //This is running on the cube entity
}
void PostUpdate(float deltaTime)override { //Set Scene changes To Physics simulation
for (auto entity : Events::scene->entities)
for (auto component : entity->components)
if (component->GetName() == "RigidBody")
((RigidBody*)component)->SetTransform(entity->transform);//This is running on the cube entity
mScene->simulate(deltaTime);
}
PreUpdate запускается перед обновлением каждого кадра PostUpdate запускается после обновления каждого кадра.метод Update (показанный в приведенном выше сценарии), как следует из названия, запускается при обновлении ... (между PreUpdate и PostUpdate).Куб имеет компонент твердого тела.То, что я ожидаю получить: вращающийся куб, который не прекращает вращаться, когда достигает 90 градусов.
Я знаю, что это немного сложно.Я старался изо всех сил, чтобы объяснить ошибку, я полагаю, что проблема заключается в изменении углов Эйлера на quat.