ZBrush – トルソ

2016_02_28_002
久しぶりにZBrushの投稿。

 

思えば、何回ディアクティベーションしただろうか、、
OS変えたり、パソコン変えたり、HDD壊れたり。
Pixologicのサポートでチケットを発行してディアクティベーションすることが多い。
何故か「Web Deactivation」できないことが多い。
休日前だと休日すぎに処理されるが、大抵は遅くとも次の日には処理されている。
意外と手厚いサポートで助かっています。

Python – 整数の特定の位で四捨五入

整数の特定の位で四捨五入する方法って、あるのだろうか?
と、必要に駆られて調べてみました。
恐らく、文字列に変換して桁数をlen関数で数えて使うのではないか、という発想の元に調べてみると、
format関数に「g」という機能(?)があるのを知りました。有効桁数の指定だそうです。
それで、こんな感じに作ってみました。

def iRound(val):
	nVal = int(round(val))
	valStr = str(nVal)
	num = len(valStr) - 1
	return int(float("{0:.{1:}g}".format(nVal,num)))

print iRound(745)

結果は「740」
1の位を四捨五入したかったんですが、これだと切り捨てになってしまう、、
で、更に調べてみると、そもそも四捨五入するround関数の引数にマイナスを指定すると整数の桁の指定が可能。
ということを知り、こんな感じです。

def iRound(val):
	return int(round(val,-1))

print iRound(745)

結果は「750」
ああ、、簡単だった、、
どちらの関数ともに、浮動小数、もしくは整数の入力を想定しております。

Maya Script API2.0 – ハードエッジの選択

このサイトを探せばあるとは思うのですが、どこにあるのか改めて書いておきます。
タイトルと内容が一致しないと、後から探すのが大変なもので、、

 

import maya.cmds as cmds
import maya.api.OpenMaya as om2

def select_soft_or_hard_edges(flag = "hard"):
	sel = cmds.ls(sl=1)
	node,comp = get_ploy_comp("edge",*sel)
	
	if not comp:
		return
	
	selList = om2.MGlobal.getActiveSelectionList()

	if not selList:
		return

	selObj = []
	for x in range(selList.length()):
		mDag = selList.getDagPath(x)
		
		if mDag.hasFn(om2.MFn.kMesh):
			selObj.append(om2.MFnMesh(mDag))

	if selObj:
		cmds.selectMode(co=1)
		cmds.selectType(smp=0,sme=1,smf=0,smu=0,pv=0,pe=1,pf=0,puv=0)

		if flag == "soft":
			cmds.select(["{0:}.e[{1:}]".format(x.fullPathName(),i) for x in selObj for i in range(x.numEdges) if x.isEdgeSmooth(i)],r=1)
		elif flag == "hard":
			cmds.select(["{0:}.e[{1:}]".format(x.fullPathName(),i) for x in selObj for i in range(x.numEdges) if not x.isEdgeSmooth(i)],r=1)

select_soft_or_hard_edges()

API2.0を使用したハードエッジの選択です。
前回のスクリプト、「get_ploy_comp」関数を使用することを前提にしております。
一応動きはするのですが、すでに選択されているエッジからハードエッジのみを抽出したりなどの処理を入れるのが適当かと思います。
これには入っておりません。

 

しかし、このスクリプト、動作は早くないです、、
うーん、やはりMayaコマンドから渡して、最終的にもMayaコマンドで選択を適用しているからだろうか、、
つい面倒くさいので、できるだけMayaコマンドに頼ってしまいます。
やっぱり全部API2.0で書いてプラグイン化しないと最適ではないんだろうなぁ。

Maya Script Python – コンポーネントの取得2と上を向いているフェースの選択

以前書いたとことある、コンポーネントの取得用の関数を更新します。

import maya.cmds as cmds

def get_ploy_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

使い方は上記の関数を登録し(スクリプトエディタで一回実行)

sel = cmds.ls(sl=1)
node,comp = get_ploy_comp("vtx",*sel)
print node,comp

を実行すると、選択されているものがポリゴンメッシュであれば、その要素をプリントします。
フラグとして「vtx」,「edge」,「face」,「uv」,「vtxFace」を与えることで、返ってくるコンポーネントの種類を選べます。
前は、関数内で完結させておりましたが、今回は使いやすいように、引数を設定しました。

 

pymelだと無駄に遅くなってしまうので、コンポーネントの操作の場合はMayaコマンドの方が良いかと思います。
で、それを使った例として、上を向いているフェースを選択するスクリプトです。
動作としては、オブジェクト選択では、単純に上を向いている面を選択します。引数として小数の値を入力することで、
範囲を設定できます。デフォルトが「1.0」で、小さくなると範囲が狭くなり、大きくなると範囲が広くなります。
既にフェースを選択している場合は、選択されているフェース内から上を向いているもののみを残して選択します。

 

まずはMayaコマンド版

import pymel.core as pm
import maya.cmds as cmds
def select_yup_face_cmds(val = 1.0):
	sel = cmds.ls(sl=1)
	node,comp = get_ploy_comp("face",*sel)
	
	if comp:
		yUp = []
		axis = pm.datatypes.Vector(0,1,0)
		cmds.select(cl=1)
		for x in comp:
			xyz = pm.datatypes.Vector(float(z) for z in cmds.polyInfo(x,fn=1)[0].split()[-3:])
			if xyz.angle(axis) < val:
				yUp.append(x)
		if yUp:
			cmds.selectMode(co=1)
			cmds.selectType(smp=0,sme=0,smf=1,smu=0,pv=0,pe=0,pf=1,puv=0)
			cmds.select(yUp,r=1)
		else:
			pm.confirmDialog(t=u"Select Yup",m=u"yUpのフェースは見つかりませんでした",b="OK",db="OK",ds="OK")
			return
	else:
		pm.confirmDialog(t=u"Select Yup",m=u"ポリゴンフェース、もしくはポリゴンフェースを持ったノード\nを選択してから実行して下さい",b="OK",db="OK",ds="OK")
		return

使い方は、オブジェクト、もしくはコンポーネント選択で。

select_yup_face_cmds()

範囲指定する場合は

select_yup_face_cmds(0.5)

のような感じです。
次にAPI2.0版

import pymel.core as pm
import maya.cmds as cmds
import maya.api.OpenMaya as om2

def select_yup_face_om2(val = 1.0):
	sel = cmds.ls(sl=1)
	node,comp = get_ploy_comp("face",*sel)
	
	if not comp:
		return
	
	
	yUp = set()
	axis = om2.MVector(0,1,0)

	selList = om2.MGlobal.getActiveSelectionList()

	if not selList:
		return

	selObj = []
	for x in range(selList.length()):
		mDag = selList.getDagPath(x)
		
		if mDag.hasFn(om2.MFn.kMesh):
			selObj.append(om2.MFnMesh(mDag))

	if selObj:
		for s in selObj:
			for i in range(s.numPolygons):
				xyz = s.getPolygonNormal(i)
				if xyz.angle(axis) < val:
					yUp.add("{0:}.f[{1:}]".format(s.fullPathName(),i))
		if yUp:
			comp = list(set(comp) & yUp)
			cmds.selectMode(co=1)
			cmds.selectType(smp=0,sme=0,smf=1,smu=0,pv=0,pe=0,pf=1,puv=0)
			cmds.select(comp,r=1)
		else:
			pm.confirmDialog(t=u"Select Yup",m=u"yUpのフェースは見つかりませんでした",b="OK",db="OK",ds="OK")
			return
	else:
		pm.confirmDialog(t=u"Select Yup",m=u"ポリゴンフェース、もしくはポリゴンフェースを持ったノード\nを選択してから実行して下さい",b="OK",db="OK",ds="OK")
		return

使い方は同じく

select_yup_face_om2()

どちらもpymelモジュールを読んでますが、UIに使用しているだけです。
なので、「pm」を「cmds」に変更すればpymelを読む必要はありません。
やはりUIを作るのはpymelの方が簡単なのでpymelを使ってしまいます。
なので、コピペして使っている部分は残ってしまいます。記事を書いていて気が付きました、、
でも、見なおしてみると、Mayaコマンド版ではVectorをpymelのデータ・タイプを使っているので、必要ですね。
こちらもAPI2.0などで置き換えれば、pymelは必要なくなります。
因みにそのVectorを使っているところの値を変更すれば、上面だけでなく他の面でも同様の処理を組むことができます。
汎用化するのであれば、引数として外に出したほうが良いですね。
そうなると関数名も変えなくてはおかしくなる。
そうやって命名規則って狂ってゆくんですよねぇ。

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

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

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