【问题标题】:How do you rotate ursina entities around their local axes?你如何围绕它们的局部轴旋转 ursina 实体?
【发布时间】:2022-01-16 02:12:52
【问题描述】:

我无法让我的代码围绕其局部轴旋转 3D 对象以正常工作。我正在使用 Ursina 游戏引擎。我要旋转的 3D 对象扩展了 Entity 类,它有一个 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 代替矩阵乘法,但这些都不起作用。

我在rotate 方法中做错了什么?

【问题讨论】:

    标签: python matrix rotation rotational-matrices ursina


    【解决方案1】:

    ursina中默认的旋转轴如下:

    • x:绕 x 轴顺时针旋转,从外向内看。
    • y:绕 y 轴顺时针旋转,从外向内看。
    • z:从外向内看,围绕 z 轴顺时针旋转。这是相反的,因为 2d 游戏:|

    欧拉角在某些情况下是有限的。要将角度获取/设置为四元数,请使用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()

    【讨论】:

      猜你喜欢
      • 2018-05-20
      • 1970-01-01
      • 1970-01-01
      • 2016-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多