как вращать по глобальным осям Ursina Python
Вращаю объект с помощью команды 'rotation_z', но при это также воращаются все оси этого объекта. Как предотвратить вращение осей? Есть команда 'world_rotation_z', но не совсем понятно как она работает. Документация умалчивает.
from ursina import *
app = Ursina()
cube_1 = Entity(model='cube')
delta=0
def update():
global delta
delta = delta + 0.1
cube_1.rotation_z = delta
app.run()
Ответы (1 шт):
Вы хотите вращать объект вокруг осей X, Y, Z независимо друг от друга. Оси фиксированы в пространстве. Для вращения используем присвоение значений свойствам rotation_x, rotation_y, rotation_z.
Например начнем с нулевых поворотов и повернем сперва по X, потом по Y:
rotation_x = 0 rot X rotation_x = 90 rot Y rotation_x = 90 rotation_y = 0 ------> rotation_y = 0 ------> rotation_y = 90 rotation_z = 0 rotation_z = 0 rotation_z = 0
Тоже начальное положение, сперва по Y, потом по X:
rotation_x = 0 rot X rotation_x = 0 rot Y rotation_x = 90 rotation_y = 0 ------> rotation_y = 90 ------> rotation_y = 90 rotation_z = 0 rotation_z = 0 rotation_z = 0
В обоих случаях результат одинаков. Действительно, какая разница в каком порядке присваивать значения свойствам объекта.
Но вращения по разным осям в пространстве не могут быть переставлены с сохранением результата. Вращения не коммутируют. В наших двух примерах должны были получится разные результаты.
Противоречие заключается в том что вы не можете вращать объект вокруг разных осей просто присваивая значения каким-то свойствам. Сам способ присваивания порождает схему в которой операции перестановочны, а они не могут быть таковыми.
Ursina в этом не виновата.
Я, наверно, объясняю непонятно. Попытайтесь поиграть с программой ниже. Она реализует нужную вам логику и показывает получившиеся углы. Клавиши q/a вращают по X, w/s по Y, e/d по Z. Чтобы всё работало как ожидается, требуется идти на хитрости с изменением иерархии сцены. Хочу вас успокоить, на такие хитрости идут все кто разрабатывает интерфейсы для поворотов в пространстве в любых трехмерных пакетах.
NB: Переключение предков в иерархии соответствует операциям на матрицах вращения - обращениям и произведениям матриц. Если вы знакомы с линейной алгеброй и тем как матрицы связаны с поворотами, вы можете по программе выписать матричные операции для поворотов вокруг фиксированных осей. И наоборот, по формулам составить требуемую последовательность операций ("смена папы-поворот-смена папы").
from ursina import *
app = Ursina()
origin = Entity(model='cube', scale=(0.2, 0.2, 0.2))
Entity(model='cube', parent=origin, color=color.red , position=(5, 0, 0), scale=(10, 0.5, 0.5))
Entity(model='cube', parent=origin, color=color.green, position=(0, 5, 0), scale=(0.5, 10, 0.5))
Entity(model='cube', parent=origin, color=color.blue , position=(0, 0, 5), scale=(0.5, 0.5, 10))
x_handle = Entity()
y_handle = Entity()
z_handle = Entity()
def switch_parent(entity, parent):
old_world_rotation = entity.world_rotation
entity.parent = parent
entity.world_rotation = old_world_rotation
def update():
old_parent = origin.parent
switch_parent(origin, x_handle)
x_handle.rotation_x += held_keys['q'] * 50 * time.dt
x_handle.rotation_x -= held_keys['a'] * 50 * time.dt
switch_parent(origin, y_handle)
y_handle.rotation_y += held_keys['w'] * 50 * time.dt
y_handle.rotation_y -= held_keys['s'] * 50 * time.dt
switch_parent(origin, z_handle)
z_handle.rotation_z += held_keys['e'] * 50 * time.dt
z_handle.rotation_z -= held_keys['d'] * 50 * time.dt
switch_parent(origin, old_parent)
app.run()