python + maya: повернуть ось Y вдоль вектора

Как я могу повернуть форму круга, чтобы ее ось y находилась вдоль предоставленного вектора? Вектор в этом примере скрипта создается с использованием двух локаторов в сцене. Код разбит на 3 части. Первый раздел просто создает тестовую сцену. Вторая часть собирает вектор. В третьей части мне нужна помощь, чтобы понять, как использовать вектор для регулировки вращения круга, чтобы его ось 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 )

person JokerMartini    schedule 07.04.2014    source источник
comment
Я предпочитаю использовать ограничения, чем заново изобретать сложную математику в коде. Является ли ограничение цели вариантом в вашем случае?   -  person mhlester    schedule 08.04.2014
comment
если я пойду по этому пути. Я сделаю фиктивный локатор и выровняю его, используя ограничение, и не буду путаться с реальным кругом. Затем совместите преобразование круга с манекеном. Если это так, есть ли быстрый и грязный способ выровнять один узел с другим преобразованием?   -  person JokerMartini    schedule 08.04.2014
comment
@mhlester это не сложная математика, на самом деле довольно тривиальная. В любом случае, пожалуйста, не пишите векторные функции по умолчанию самостоятельно. Получите их из некоторого пакета, это просто источник ошибок, который совершенно неэффективен.   -  person joojaa    schedule 08.04.2014
comment
Действительно, @joojaa, в данном случае это не так уж сложно. Однако есть много случаев, когда это не так, и я видел, как люди заходят слишком далеко, заново изобретая что-то, что может быть просто ограничением цели/вверх. Хорошо, что мы знаем о встроенных инструментах   -  person mhlester    schedule 08.04.2014


Ответы (1)


Сила использования такого пакета, как 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 векторов, но существует бесконечное количество способов сделать это по-другому. В этом случае вектор полюса представляет собой небольшую проблему, если ваш вектор прицеливания когда-либо указывает в направлении вектора вверх, и у вас возникнут некоторые проблемы.

Теперь матрица — это просто набор векторов, указывающих в кардинальном направлении, — это тривиально. Maya хранит матрицы в формате in vectors is rows, поэтому матрица, указывающая на y вдоль вектора, где a нормирована на единицу длины, 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, поэтому скрестите b для 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

Вы можете разложить эту матрицу, чтобы получить углы Эйлера. Вы можете использовать варианты этой темы, добавляя к, например, чтобы получить ссылку на пейсхолдер.

person joojaa    schedule 08.04.2014
comment
Хотя я бы сделал это сам с ограничением цели, это правильная математика. вместо того, чтобы разлагать матрицу, я бы просто поместил перевод в 3 нижних левых блока матрицы и применил их с помощью xform(matrix=joojas_matrix_from_vectors) - person theodox; 09.04.2014
comment
@theodox да совсем забыл об этом. В основном я думал о построении узла или, если у вас нет Maya, что может быть не всегда, то полезно знать имя операции для целей поиска. - person joojaa; 09.04.2014