PyBullet и OpenGL - в OpenGL вращения меняются местами

Я пишу базовый игровой движок, чтобы помочь со своей докторской диссертацией по многоагентному обучению. Я использую PyBullet в качестве внутреннего физического движка и OpenGL для визуального отображения. У меня есть буферы OpenGL, настроенные для хранения информации об объекте, такой как положение (vec3) и вращение (matrix4x4), при этом вращения выполняются с использованием кватернионов, но для удобства хранятся с использованием углов Эйлера.

Моя проблема в том, что когда я вращаю объект в игровом мире OpenGL (вокруг любой оси), вращение pyBullet (как видно из графического интерфейса pyBullet) происходит в противоположном направлении и иногда полностью выключается. Мне, должно быть, не хватает чего-то простого, и я извиняюсь, если это простое решение. Я также предоставил видео, чтобы показать проблему, с которой я столкнулся - ссылка на видео об ошибке ( https://youtu.be/4VpBUx5LBYQ):

Когда я извлекаю поворот из PyBullet, используя getBasePositionAndOrientation() и преобразовать кватернион в углы Эйлера, используя pybullet.getEulerFromQuaternion(), результатом будет правильный vec3, но после преобразования в матрицу вращения pybullet.getMatrixFromQuaternion(), кажется, меняет направление вращения.

Пожалуйста, посмотрите мой код ниже:


'obj = Class BaseSceneObject'
'action = Euler rotation angle in degrees to apply vec3(x, y, z) e.g.(1., 0., 0.) apply +1 degree rotation to x-axis'

'Collect current position and rotation of object and update PyBullet'
# get the rotation - euler angles in degrees vec3(x,y,z)
rot = obj.get_rotation()
# add rotation action (e.g. +1 degree to x = vec3(1., 0., 0.)) and convert to radians
rot = math.radians(rot[0] + action[0]), math.radians(rot[1] + action[1]), math.radians(rot[2] + action[2])
# convert rotation from euler to quaternion
quat = pybullet.getQuaternionFromEuler(rot)
# update position and orientation
pybullet.resetBasePositionAndOrientation(bodyUniqueId=obj.get_rigid_body_id(),
                                         posObj=obj.get_position(),
                                         ornObj=quat)

'Collect PyBullet results and update OpenGL'
# get position and rotation from PyBullet
position, rotation = pybullet.getBasePositionAndOrientation(bodyUniqueId=obj.get_rigid_body_id())
# update object position
obj.set_position(position=position)
# convert rotation quaternion to euler angles
rot_r = pybullet.getEulerFromQuaternion(rotation)
# convert radians to degrees
rot_d = math.degrees(rot_r[0]), math.degrees(rot_r[1]), math.degrees(rot_r[2])
# construct OpenGL object rotation matrix
rot_m_final = numpy.identity(4)
rot_mr = numpy.array(pybullet.getMatrixFromQuaternion(rotation)).reshape(3, 3)
rot_m_final[:3, :3] = rot_mr
# update OpenGL rotation matrix
obj.set_rotation(rotation=rot_d,
                 rotation_matrix=rot_m_final)

1 ответ

Оказывается, приведенный выше код верен. Проблема заключалась в шейдере OpennGL, где я забыл, что вычисления матриц некоммутивны, т.е. numpy.matmul(Mat4(вращение), Vec4(положение)) не то же самое, что numpy.matmul(Vec4(положение), Mat4(вращение))).

После обновления моего кода шейдера: vec4 aRPos = vec4(aRotation * aVertex); Кому: vec4 aRPos = vec4(aVertex * aRotation);

Это сработало отлично. Спасибо.

Другие вопросы по тегам