I can’t get my code for rotating a 3D object around its local axes to work correctly. I’m using the Ursina game engine. The 3D objects that I want to rotate extend the Entity
class, which has a rotation
property that’s Euler angles. I learned via testing that Ursina does Euler rotations in the Z,X,Y order—correct me if I’m wrong. I didn’t find the Euler order in Ursina’s documentation.
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):
…
The code multiplies the object’s current rotation matrix with the matrix of the new rotation (around local, not global, axes) to be applied. It doesn’t rotate properly.
I tried swapping the order of the matrix multiplication, changing the Euler orders, and using scipy.spatial.transform.Rotation.apply
instead of matrix multiplication, but none of these worked.
What did I do wrong in the rotate
method?