Maya Python API缩放关于另一个矩阵的矩阵

时间:2013-08-19 15:38:48

标签: python api matrix maya

所以我在玛雅有两个矩阵。我想反映一个关于其他矩阵的x和y的矩阵。

以此为例:

对象1的矩阵是这样的: [1.0,0.0,0.0,0.0,0.0,0.70710678118654746,0.70710678118654757,0.0,0.0,-0.70710678118654757,0.70710678118654746,0.0,0.0,0.0,0.0,1.0] 这是原点上沿x旋转45度的物体。

对象2的矩阵是这样的: [1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,2.0,2.0,2.0,1.0] 坐在世界空间的2,2,2,没有旋转值。

当反映在object1的scaleX上时,我们得到一个这样的矩阵: [1.0,0.0,-0.0,0.0,-0.0,0.70710678118654746,-0.70710678118654757,0.0,0.0,0.70710678118654757,0.70710678118654746,0.0,2.0,2.8284271247461898,-2.2204460492503131e-16,1.0]

当我手动反映对象的比例时,这只是我查询矩阵。在python API中执行此操作的方法是什么?

我假设某种方式使用MTransformationMatrix,但却无法解决这个问题。

非常感谢任何帮助!

4 个答案:

答案 0 :(得分:2)

通常,您可以在API中创建MMatrix或MTransformationMatrix,并将它们串联在一起以获得所需的转换。麻烦是将Python中的值转换为这些类,这需要可怕的MScriptUtil

import maya.OpenMaya as OpenMaya
import maya.cds as cmds


def APIMatrix ( valList ):  # where vallist is a list of floats
    mat = OpenMaya.MMatrix()
    OpenMaya.MScriptUtil.createMatrixFromList( valList, mat )
    return mat

例如,可以从python数字列表中创建一个MMatrix。在Pymel中,使用Matrix类更容易:

import pymel.datatypes as dt

i = dt.Matrix() # creates an identity matrix
m = dt.Matrix ( list_of_values) # use supplied numbers

一旦你的矩阵相乘,你就可以用xform命令来应用它们:

cmds.xform(item, m = my_new_matrix)

或在pymel中:

import pymel.core as pm
pm.xform(item, my_new_pymel_matrix)

MMatrix是一个原始矩阵 - 只是数学MTransformationMatrix的数字更像是对象的实际变换:它提供了一些方法,例如,将数字戳入平移或旋转而不知道哪些矩阵成员旋转手工:

def get_obj_quaternion ( mayaTransform, worldSpace=True ):
    '''
    gets the rotation quat for the supplied dag node in world or local space
    '''
    #convert from mMatrix to MTransformationMatrix....
    mMatrix = matrix_from_transform( mayaTransform, worldSpace=worldSpace )
    mTransformMtx = OpenMaya.MTransformationMatrix( mMatrix )

    # MscriptUtil. Sigh
    xPtr = OpenMaya.MScriptUtil(0.0)
    x = xPtr.asDoublePtr()

    yPtr = OpenMaya.MScriptUtil(0.0)
    y = yPtr.asDoublePtr()

    zPtr = OpenMaya.MScriptUtil(0.0)
    z = zPtr.asDoublePtr()

    wPtr = OpenMaya.MScriptUtil(0.0)
    w = wPtr.asDoublePtr()

    mTransformMtx.getRotationQuaternion( x, y, z, w )
    # getRotationQuaternion is an MTransformationMatrix method

    #convert them back to normal python floats
    x = OpenMaya.MScriptUtil().getDouble( x )
    y = OpenMaya.MScriptUtil().getDouble( y )
    z = OpenMaya.MScriptUtil().getDouble( z )
    w = OpenMaya.MScriptUtil().getDouble( w )

    return x, y, z, w

所以在你的情况下你想要:

1)获取目标对象的矩阵

2)获取反射对象的矩阵

3)制作一个反射矩阵,例如:

 -1  0  0  0
  0  1  0  0 
  0  0 -1  0
  0  0  0  1

是反射X轴和Z轴的反射矩阵

4)将目标反映为:

reflected_matrix = reflectXZMatrix * reflectionObjectMatrix
result = target_matrix * reflected_matrix
cmds.xform( target_object, m = result)

这是仅使用MMatrices的极简主义版本 - 如果您需要自己构建矩阵,MTransformationMatrix将允许您设置旋转或缩放矩阵,而无需手动管理矩阵中的数字。

答案 1 :(得分:0)

这是我用你给我的想法的代码。现在非常有意义!

import maya.OpenMaya as OpenMaya
import maya.cmds as cmds
import math

reflectObj = cmds.xform('pSphere1', query=True, ws=True, matrix=True)
targetObj = cmds.xform('pSphere2', query=True, ws=True, matrix=True)
reflectXZ = [-1 * reflectObj[0], -1 * reflectObj[1], -1 * reflectObj[2], reflectObj[3],
             -1 * reflectObj[4], -1 * reflectObj[5], -1 * reflectObj[6], reflectObj[7],
             reflectObj[8], reflectObj[9], reflectObj[10], reflectObj[11],
             reflectObj[12], reflectObj[13], reflectObj[14], reflectObj[15]]

targetMMatrix = OpenMaya.MMatrix()
OpenMaya.MScriptUtil.createMatrixFromList(targetObj, targetMMatrix)

reflectObjMMatrix = OpenMaya.MMatrix()
OpenMaya.MScriptUtil.createMatrixFromList(reflectObj, reflectObjMMatrix)

reflectXZMMatrix = OpenMaya.MMatrix()
OpenMaya.MScriptUtil.createMatrixFromList(reflectXZ, reflectXZMMatrix)

reflected_matrix = targetMMatrix * reflectObjMMatrix.inverse()
result = reflected_matrix * reflectXZMMatrix

mt = OpenMaya.MTransformationMatrix(result)

trans = mt.translation(OpenMaya.MSpace.kWorld)
eulerRot = mt.rotation().asEulerRotation()
angles = [math.degrees(angle) for angle in (eulerRot.x, eulerRot.y, eulerRot.z)]
loc = cmds.spaceLocator()
cmds.move(trans[0], trans[1], trans[2], loc[0])
cmds.rotate(angles[0], angles[1], angles[2], loc[0])

在这种情况下,我只做了两个球体,并能够反映这些矩阵。 编辑:更正此项以解决任何轮换问题。

答案 2 :(得分:0)

结束使用向量来获取位置。将obj1和obj2替换为您的反射对象和对象以反映。

import maya.OpenMaya as OpenMaya
import maya.cmds as cmds
from functools import partial

get_pnt = partial(cmds.xform,
                 query=True,
                 worldSpace=True,
                 translation=True)

N = OpenMaya.MVector(*get_pnt('obj1'))
N.normalize()
V = OpenMaya.MVector(*get_pnt('obj2'))
R = (N * 2.0) * (V * N) - V

loc = cmds.spaceLocator()
cmds.move(R.x, R.y, R.z, loc[0])

Formula for vector reflection

答案 3 :(得分:0)

接受的答案包含一个不正确的例子。 从不撰写ptr = OpenMaya.MScriptUtil().asDoublePtr()之类的内容。为了解释原因,请阅读第二点:http://around-the-corner.typepad.com/adn/2013/03/possible-misuse-of-mscriptutil-in-maya.html

此外,相同的示例有助于展示如何使用类MScriptUtil,但是,对于此特定方法,这里的版本更便于编写和更快地运行:

def get_obj_quaternion ( mayaTransform, worldSpace=True ):
    '''
    gets the rotation quat for the supplied dag node in world or local space
    '''
    #convert from mMatrix to MTransformationMatrix....
    mMatrix = matrix_from_transform( mayaTransform, worldSpace=worldSpace )
    mTransformMtx = OpenMaya.MTransformationMatrix( mMatrix )
    q = mTransformMtx.rotation()
    return [q.x, q.y, q.z, q.w]