如何使用Python将三维向量转换为Maya中的欧拉旋转

0 投票
3 回答
5755 浏览
提问于 2025-04-18 05:46

有一个三维向量。
我想把这个向量转换成一个旋转,这样可以让立方体的一个局部轴(比如X轴)对齐到这个向量的方向。

我准备了两张图片,但因为我的声望不够,无法贴出来。我还是个新手。

我尝试了很多次,但还是没能成功。我觉得这可能和我旋转立方体时的旋转顺序有关。

3 个回答

0

我建议使用NumPy或者类似的库来处理数学运算,因为它们经过高度优化,提供了各种函数和运算符。

在Python中解决矩阵和向量相乘的问题,我们可以假设:

  • 向量是1维的列表,视作列向量
  • 矩阵是2维的列表,其中m[R][C]表示第R行第C列的元素

那么旋转矩阵和某个向量相乘的结果是

[
  sum([m * v for m, v in zip(m_column, some_vector)]) 
      for m_column in rotation_matrix
]

一些实用的链接:zip - 手册Python 列表推导

1

正如@theodox所说,使用约束是完全有效的,使用xform也是可以的。我只是提供一些其他的信息(下面的附录中还有更多信息)。

不过,Maya里有一个叫decomposeMatrix的节点,如果你只是想做这个转换,它可以帮你完成。Maya API里也有一个用于分解的函数:

import maya.OpenMaya as om

util = om.MScriptUtil()

mat = om.MMatrix()
util.createMatrixFromList(
    [
    1., 0., 0., 0., 
    0., 1., 0., 0.,
    0., 0., 1., 0.,
    0., 0., 0., 1.
    ], mat)
rot = om.MEulerRotation.decompose(mat, om.MEulerRotation.kXYZ)

# result in radians which in this are is known but my example is just a placeholder
print rot.x, rot.y, rot.z

不过你最好还是使用节点,因为它们会在你需要更新的时候自动更新,除非你在做一些静态的东西,比如不需要动画的内容,或者你在做一个导出器。

无论如何,将来你可能会在Maya之外做这个,或者使用不同的组合顺序来处理缩放和剪切等情况,这时候我建议你去看看Christoph Gohlke的主页,里面有Transformations.pytransformations.c,它们提供了很多关于矩阵数学的信息和原始资料的参考,比如在这个案例中,Ken Shoemake对旋转的出色分析。

附注:这是一个近似重复的问题,里面也包含了一些关于矩阵数学的信息,就像@theodox的回答一样。

3

你可以通过使用目标约束来实现你想要的效果。如果你只想一次性操作(不想在场景中保持这个约束),你可以直接这样做:

 lc = cmds.aimConstraint( 'your_object_here', 'target_object_here') 
 cmds.delete(*lc)

不过,如果你想通过代码来进行数学计算,而不使用欧拉角的话,也是可以的。因为欧拉角的组合方式很多,对于同一个方向都有很多有效的组合,所以构建起来比较复杂。直接设置对象的矩阵,让它的局部轴线指向你想要的方向会更简单。

在Maya中,矩阵是这样工作的:

Xx  Xy  Xz  0
Yx  Yy  Yz  0
Zx  Zy  Zz  0
Tx  Ty  Tz  1

其中

  • (Xx, Xy, Xz) 是矩阵的局部X向量
  • (Yx, Yy, Yz) 是矩阵的局部Y向量
  • (Zx, Zy, Zz) 是矩阵的局部Z向量
  • (Tx, Ty, Tz) 是矩阵的平移部分

如果有缩放的话,缩放信息就包含在这些向量的大小里;对于一个缩放为1且没有旋转的矩阵,这些向量是标准化的,所以矩阵会是:

1 0 0 0 
0 1 0 0
0 0 1 0 
0 0 0 1

你可以使用Pymel来创建一个矩阵,方法是用4个元组来表示矩阵的行:

import pymel.core as pm
# in practice these vectors would reflect the orientation you want
new_mat = pm.core.matrix  (
    ( 1, 0, 0, 0),
    ( 0, 1, 0, 0), 
    ( 0, 0, 1, 0),
    ( 0, 0, 0, 1) 
    )

然后可以通过xform命令将这个矩阵应用到一个对象上:

pm.xform(my_object, matrix = new_mat)

撰写回答