Maya Script Python – メッシュの法線方向にカーブを配置

えーと、、何を調べていたのか忘れましたが、
確かpymelのバウンディングボックスクラスで、実用例を検索していたような気もしますが、
とにかく、何かを探していて、面白いコードだったので、それを参考に書いたものです。

 

ポリゴンメッシュを選択し、実行すると、そのメッシュに含まれる各フェイスに、そのフェイスの法線方向に
向いたカーブを生成する。と言うものです。
フェイスの法線を表示したような感じで、カーブが生成されます。

 

ミソはフェイスの中心の求め方とマトリックスの使用でしょうか。
もとのコードでは、バウンディングボックスを求めて、その中心位置をカーブの位置にしておりましたが、変更しました。
pymelだとオブジェクト指向で扱えるので、やはり楽ですねぇ。

import pymel.core as pm



def poly_center_curve_pymel():
	sel = pm.ls(sl=1)
	sel = pm.ls(pm.filterExpand(pm.polyListComponentConversion(sel,tf=1),sm=34,ex=1))
	
	if not sel:
		return
	
	up = pm.datatypes.Vector([0.0, 1.0, 0.0])
	
	for s in sel:
		pos = s.getPoints(space="world")
		
		aim = s.getNormal()
		
		center = pos[0].center(*pos[1:])

		tangent = (aim ^ up).normal()
		up = (tangent ^ aim).normal()

		mat = pm.datatypes.Matrix([	aim.x, aim.y, aim.z, 0,
									up.x, up.y, up.z, 0,
									tangent.x, tangent.y, tangent.z, 0,
									center.x,  center.y,  center.z,  1])
		curve = pm.curve(p=([0, 0, 0], [5, 0, 0]), degree=1)
		pm.xform(curve, absolute=True, matrix=mat)

poly_center_curve_pymel()

そして、Mayaコマンド版ですが、こちらは相変わらず、自作の関数を通すことを前提に作りました。

import maya.cmds as cmds

def get_poly_comp(flag = "vtx",*args):
	node = None
	
	flags = ["vtx","edge","face","uv","vtxFace"]
	sm = [31,32,34,35,70]
	kwArgs = ["tv","te","tf","tuv","tvf"]
	
	if flag not in flags:
		return -1
	
	kw = {x:{y:1} for x,y in zip(flags,kwArgs)}
	smKW = dict(zip(flags,sm))
	
	comp = cmds.filterExpand(cmds.polyListComponentConversion(*args,**kw[flag]),sm=smKW[flag],ex=1,fp=1)
	if comp:
		node = list(set([x.split(".",1)[0] for x in comp]))
	
	return node,comp

まずは上記の関数を実行し、

from itertools import chain
import maya.cmds as cmds
import pymel.core as pm

def poly_center_curve_cmds():
	sel = cmds.ls(sl=1)
	node,comp = get_poly_comp("face",sel)
	
	if not node:
		return
	
	up = pm.datatypes.Vector([0.0, 1.0, 0.0])
	
	for c in comp:
		vtxs = cmds.filterExpand(cmds.polyListComponentConversion(c,tv=1),sm=31,ex=1,fp=1)
		pos = [pm.datatypes.Point(cmds.pointPosition(x,w=1)) for x in vtxs]
		
		aim = pm.datatypes.Vector([float(x) for x in cmds.polyInfo(c,fn=1)[0].split()[-3:]])
		
		center = pos[0].center(*pos[1:])
		
		tangent = (aim ^ up).normal()
		up = (tangent ^ aim).normal()

		mat = pm.datatypes.Matrix([	aim.x, aim.y, aim.z, 0,
									up.x, up.y, up.z, 0,
									tangent.x, tangent.y, tangent.z, 0,
									center.x,  center.y,  center.z,  1])
		curve = cmds.curve(p=([0, 0, 0], [5, 0, 0]), degree=1)
		cmds.xform(curve, absolute=True, matrix=list(chain.from_iterable(mat)))

poly_center_curve_cmds()

コード自体の量はpymelと比較しても大差ありません。
ただ、Mayaコマンド版のxformが、pymelのマトリックス表記に対応していないので、リストを平坦化する必要があります。
なので、itertoolsを使い平坦化を行いました。

 
実用目的で作ったものではないのですが、pymelの各種クラスの使い方とリストの平坦化など、
色々とメモしておきたいコードでした。

アニメーションが親切に解説されております

レンダリング、ライティングの基本が分かります

図版が見やすい美術解剖書です