如何围绕局部轴旋转 ursina 实体?
How do you rotate ursina entities around their local axes?
我无法使围绕其局部轴旋转 3D 对象的代码正常工作。我正在使用 Ursina 游戏引擎。我要旋转的 3D 对象扩展 Entity
class,它有一个 rotation
属性,即欧拉角。我通过测试得知 Ursina 按 Z、X、Y 顺序进行欧拉旋转——如果我错了请纠正我。我在Ursina的文档中没有找到欧拉阶
import numpy as np
from scipy.spatial.transform import Rotation as R
from ursina import *
class FreeRotateEntity(Entity):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def rotate(self, angles):
self.rotation = Vec3(*[360 + a if a < 0 else a for a in [
R.from_matrix(
np.matmul(
R.from_euler('zxy', (self.rotation.z, self.rotation.x, self.rotation.y), degrees=True).as_matrix(),
R.from_euler('zxy', [angles[i] for i in (2, 0, 1)], degrees=True).as_matrix()
)
).as_euler('zxy', degrees=True)[i] for i in (1, 2, 0)
]])
class Ship(FreeRotateEntity):
…
代码将对象的当前旋转矩阵与要应用的新旋转矩阵(围绕局部而非全局轴)相乘。旋转不正常。
我尝试交换矩阵乘法的顺序,更改欧拉阶数,并使用 scipy.spatial.transform.Rotation.apply
代替矩阵乘法,但其中 none 行得通。
我在rotate
方法中做错了什么?
ursina中默认的旋转轴如下:
- x:从外向内绕x轴顺时针旋转
- y:从外向内绕y轴顺时针旋转
- z:从外向内绕 z 轴顺时针旋转 counter。这是相反的,因为 2d-games :|
欧拉角在某些情况下有点受限。要 get/set 角度作为四元数使用 entity.quat
.
如果您能解释一下您的实际问题是什么,那就太好了。
如果您的目标是单独旋转轴,请考虑使用实体层次结构。
这就是第一人称或第三人称射击游戏的工作方式。您在 y 轴上旋转播放器,使其始终站立,但分别上下旋转相机:
from ursina import *
app = Ursina()
cube_parent = Entity()
cube = Entity(parent=cube_parent, model='cube', texture='white_cube')
def update():
cube_parent.rotation_y += 100 * (held_keys['a'] - held_keys['d']) * time.dt
cube_parent.rotation_x += 100 * (held_keys['w'] - held_keys['s']) * time.dt
app.run()
如果你想连续旋转某个东西,欧拉角是不够的,因为你会 运行 进入万向节锁定。考虑使用这样的技巧,它会像球一样旋转实体。
from ursina import *
app = Ursina()
rotation_resetter = Entity()
cube = Entity(parent=rotation_resetter, model='cube', texture='white_cube')
def update():
rotation_resetter.rotation_x += 100 * (held_keys['a'] - held_keys['d']) * time.dt
rotation_resetter.rotation_z += 100 * (held_keys['w'] - held_keys['s']) * time.dt
cube.rotation = cube.world_rotation
rotation_resetter.rotation = (0,0,0)
EditorCamera()
app.run()
另一种使旋转更容易的方法是使用 entity.look_at()
我无法使围绕其局部轴旋转 3D 对象的代码正常工作。我正在使用 Ursina 游戏引擎。我要旋转的 3D 对象扩展 Entity
class,它有一个 rotation
属性,即欧拉角。我通过测试得知 Ursina 按 Z、X、Y 顺序进行欧拉旋转——如果我错了请纠正我。我在Ursina的文档中没有找到欧拉阶
import numpy as np
from scipy.spatial.transform import Rotation as R
from ursina import *
class FreeRotateEntity(Entity):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def rotate(self, angles):
self.rotation = Vec3(*[360 + a if a < 0 else a for a in [
R.from_matrix(
np.matmul(
R.from_euler('zxy', (self.rotation.z, self.rotation.x, self.rotation.y), degrees=True).as_matrix(),
R.from_euler('zxy', [angles[i] for i in (2, 0, 1)], degrees=True).as_matrix()
)
).as_euler('zxy', degrees=True)[i] for i in (1, 2, 0)
]])
class Ship(FreeRotateEntity):
…
代码将对象的当前旋转矩阵与要应用的新旋转矩阵(围绕局部而非全局轴)相乘。旋转不正常。
我尝试交换矩阵乘法的顺序,更改欧拉阶数,并使用 scipy.spatial.transform.Rotation.apply
代替矩阵乘法,但其中 none 行得通。
我在rotate
方法中做错了什么?
ursina中默认的旋转轴如下:
- x:从外向内绕x轴顺时针旋转
- y:从外向内绕y轴顺时针旋转
- z:从外向内绕 z 轴顺时针旋转 counter。这是相反的,因为 2d-games :|
欧拉角在某些情况下有点受限。要 get/set 角度作为四元数使用 entity.quat
.
如果您能解释一下您的实际问题是什么,那就太好了。
如果您的目标是单独旋转轴,请考虑使用实体层次结构。 这就是第一人称或第三人称射击游戏的工作方式。您在 y 轴上旋转播放器,使其始终站立,但分别上下旋转相机:
from ursina import *
app = Ursina()
cube_parent = Entity()
cube = Entity(parent=cube_parent, model='cube', texture='white_cube')
def update():
cube_parent.rotation_y += 100 * (held_keys['a'] - held_keys['d']) * time.dt
cube_parent.rotation_x += 100 * (held_keys['w'] - held_keys['s']) * time.dt
app.run()
如果你想连续旋转某个东西,欧拉角是不够的,因为你会 运行 进入万向节锁定。考虑使用这样的技巧,它会像球一样旋转实体。
from ursina import *
app = Ursina()
rotation_resetter = Entity()
cube = Entity(parent=rotation_resetter, model='cube', texture='white_cube')
def update():
rotation_resetter.rotation_x += 100 * (held_keys['a'] - held_keys['d']) * time.dt
rotation_resetter.rotation_z += 100 * (held_keys['w'] - held_keys['s']) * time.dt
cube.rotation = cube.world_rotation
rotation_resetter.rotation = (0,0,0)
EditorCamera()
app.run()
另一种使旋转更容易的方法是使用 entity.look_at()