2014-04-07 189 views
0

如何旋转圆形,使其y轴与所提供的矢量一致?此示例脚本中的矢量是使用场景中的两个定位器创建的。代码分为3个部分。第一部分只是创建测试场景。第二部分收集矢量。第三部分是我需要帮助确定如何使用矢量来调整圆的旋转,因此它的Y轴指向收集的矢量。感谢你们。python + maya:将Y轴旋转为矢量

import maya.cmds as cmds 
import random 
import math 

cmds.select(all=True) 
cmds.delete() 

#------------------------------TEST SCENE SETUP 

def genPos(): 
    x = random.uniform(-5,5) 
    y = random.uniform(0,5) 
    z = random.uniform(-5,5) 
    return (x, y, z) 

a = cmds.spaceLocator(n='ctrl_00') 
b = cmds.spaceLocator(n='ctrl_00') 

cmds.xform(a, t=(genPos())) 
cmds.xform(b, t=(genPos())) 

cmds.createDisplayLayer(name="Ctrls") 
cmds.editDisplayLayerMembers('Ctrls', a, b) 
cmds.setAttr('Ctrls.color' ,14) 

cmds.select(clear=True) 


#-----------------------THE SCRIPT 
def normlizedVector(vecA,vecB,offset): 

    nX = vecB[0] - vecA[0] 
    nY = vecB[1] - vecA[1] 
    nZ = vecB[2] - vecA[2] 

    #vectorLength = distance vecA vecB 
    # find the distance between the two supplied point3 values 
    distX = pow((vecA[0] - vecB[0]) , 2.0) 
    distY = pow((vecA[1] - vecB[1]) , 2.0) 
    distZ = pow((vecA[2] - vecB[2]) , 2.0) 

    vecLength = math.sqrt(distX + distY + distZ) 

    # the normalized vector is calculated by dividing the X, Y and Z coordinates by the length 
    calcX = nX/vecLength 
    calcY = nY/vecLength 
    calcZ = nZ/vecLength 

    # project point along vector, offset by a given value 
    ptX = vecB[0] + (calcX * offset) 
    ptY = vecB[1] + (calcY * offset) 
    ptZ = vecB[2] + (calcZ * offset) 

    return (ptX, ptY, ptZ) 


posA = cmds.xform(a,q=1,ws=1,rp=1) 
posB = cmds.xform(b,q=1,ws=1,rp=1) 

pt = normlizedVector(posA,posB,10) 

#--------MOVE AND ALIGN CIRCLE 
cir = cmds.circle(nr=(0, 0, 1), c=(0, 0, 0)) 
cmds.xform(cir, t=posB) 
+0

得到的比赛速度。我更喜欢使用约束而不是在代码中重新创造硬数学。在你的情况下,目标限制是一种选择吗? – mhlester

+0

如果我去那条路线。我将制作一个虚拟定位器并使用约束对齐它,并避免与实际的圆形相混淆。然后将圆的变换对齐到哑元。如果那样的话,是否有一种快速和肮脏的方法来将一个节点与另一个变换明智地对齐? – JokerMartini

+0

@mhlester它不算数学,事实上很琐碎。无论如何,请不要自行默认向量函数。让他们形成一些包,它只是一个非常不恰当的错误来源。 – joojaa

回答

2

使用像Maya这样的软件包的威力在于,您并不需要自己完成所有的工作。你可以做到这一点,但与使用Maya相比,它会更慢,效率更低。事实上,如果你坚持这样做,你应该考虑彻底放弃Maya,因为它只是一个你不再需要的额外成本中心。

现在maya为此提供工具。在这种情况下,显而易见的工具是如果你建立一个钻井平台的限制。调用现有工具没有任何问题。你一直都在用函数做这件事,为什么不用玛雅节点呢,它们毕竟是功能性的。最明显的是直接在想要正常指定nr选项的位置创建圆。但看起来你想要一些实际的索具:

#aim 00 to 01 swap if you need the other way around 
cmds.aimConstraint("ctrl_01", "ctrl_00", 
        aimVector=(0, 1, 0), upVector=(0, 0, 1), 
        worldUpType="vector", worldUpVector=(0, 1, 0)); 

就是这样。但是,如果您想要在代码中重现此内容或修改解决方案,则需要稍加解释,因为这不是免费的方法。目标节点所做的是从3个向量手动构建一个矩阵,但是有一个无限数量的方法可以以不同的方式做到这一点。在这种情况下,如果你的目标矢量指向矢量方向,你会遇到一些问题,极矢量是一个问题。

现在矩阵只是指向基本方向的一组向量是微不足道的。玛雅存储矩阵中的载体是行格式,以便在y中沿着一个矢量指向一个矩阵,其中a是归一化到单位长度,一个将如下所示:

? ? ? ? 
a.x a.y a.z a.w=0 
? ? ? ? 
0 0 0 1 

现在对于这对工作,你需要任何正交值为问题标记的向量。输入向量,在这种情况下,采取与本地向上方向交叉产品。并把它的值在x列(最多载体适用作为未知向上向量的占位符),让我们称这家B,你会得到:

b.x b.y b.z b.w=0 
a.x a.y a.z a.w=0 
? ? ? ? 
0 0 0 1 

现在你可以重新计算了载体,因为它必须是正交A和b这样的AB交叉对C,你会得到:

b.x b.y b.z b.w=0 
a.x a.y a.z a.w=0 
c.x c.y c.z c.w=0 
0 0 0 1 

可以分解这种矩阵得到欧拉角。你可以使用这个主题的变体,通过加起来以得到比如

+0

虽然我会用aimconstraint自己做,但这是正确的数学。不过,我并没有分解矩阵,我只是把矩阵的左下角的3个单元应用到xform中(矩阵= joojas_matrix_from_vectors) – theodox

+0

@theodox完全忘记了这一点。主要是我在考虑节点构建,或者如果你没有可用的maya,那么可能并不总是如此,那么它很好地知道用于查找目的的操作的名称。 – joojaa