Mudbox2013

image936l
Mudboxです。
以前ZBrushで使ったものと同じ素体を使ってみました。

 

前に使っていた時は、Autodeskに買収される前でした。
久しぶりなので、使い方を覚えるのが大変かなぁ、と思っていたのですが、
そもそもの使い方が単純な上に、使ってゆくうちに思い出しました。変わっていない。

 

ZBrushよりも一段下のサブディビジョンレベル7で、約3百万ポリゴンくらいです。
Geforce8800GTという随分前のGPUを使っておりますが、殆ど問題ありません。
「グラブ」ツールというZBrushで言うところの「Move」ツールをメッシュが集中する手の部分に使おうとすると、重くて使い物になりません。
サブディビジョンレベルを下げれば、問題ありません。

 

で、値段を調べてみると、11万円です。
うーん、ZBrushのように面白い機能はありませんが、いかにも、という感じのCGツールです。癖がなくて使いやすい。
でもブラシの使いやすさはやはりZBrushに分があるように思います。Ptexが使えるのが強みかな?

Maya Script Python リスト内包表記でのウェイトの四捨五入 その2

前回に引き続き、リスト内包表記をテストしてみました。
コードを見なおしているうちに、ここはもっとまとめられるのではないか?
という事に気が付き、色々といじくり回してみました。
 

大分すっきりしました。相変わらず可読性は低いです。

import maya.cmds as cmds
import maya.mel
import math

def round_weight_test():
	oSel = cmds.ls( selection=True )
	oShp = oSel[0]
	gMainProgressBar = maya.mel.eval( '$tmp = $gMainProgressBar' )
	oVcount = cmds.polyEvaluate( oSel, v=True )
	oSkt = cmds.listHistory( oShp )
	oCls = cmds.ls( oSkt, type= "skinCluster" )[0]
	oMxc = cmds.getAttr( oCls+".maxInfluences" )
	oVtx = cmds.ls( oShp + ".vtx[*]", fl=True )
	oRoundLen = 2
	cmds.progressBar( gMainProgressBar, edit=True,beginProgress=True, status='Now Rounding...', maxValue=oVcount )
	[[cmds.progressBar(gMainProgressBar,e=1,s=1),cmds.skinPercent(oCls,v1,nrm=0,zri=1,tv=zip(*l1))] if sum(l1[1])==1.0 else [cmds.progressBar(gMainProgressBar,e=1,s=1),cmds.skinPercent(oCls,v1,nrm=0,zri=1,tv=zip(l1[0],[round(1.0-sum(l1[1][:-1]),oRoundLen) if i==len(l1[1])-1 else x for i,x in enumerate(l1[1])]))]
	for (v1,l1) in [[v,zip(*sorted(dict(zip(cmds.skinPercent(oCls,v,q=1,t= None),[round(w,oRoundLen) for w in cmds.skinPercent(oCls,v,q=1,v=1) if w>0.0])).items(),key=lambda x:x[1])[-oMxc:])]
	for v in oVtx]]
	cmds.progressBar( gMainProgressBar, edit=True, endProgress=True )
round_weight_test()

しかし、驚いたことに、前回の物よりも実行速度が遅くなる、、
分岐を減らしたからだろうか?短くすれば良い。というものでもないようです。
ああ、悔しい。
 

ウェイトエディタを更新しました。
前回のままだと、恐らく一つのシーンに同一名のオブジェクトがあるとうまく機能しないかと思います。
一応機能するようにしましたが、四捨五入はできるだけオブジェクト単位でしたほうが良いかと思います。
何でMayaはオブジェクトがシェイプノードとトランスフォームノードにわかれているのだろうか。
名前が取得しにくいです。
オブジェクトとしての移動値とそれ以外。という感じなのでしょうか。扱いにくいなぁ、、
もっとスマートな方法があるのだろうか。

Maya Script Python リスト内包表記でのウェイトの四捨五入

ついに完成しました。多分。
ポリゴンのエラー表示のスクリプトを前回作りましたが、よくよく見てみるとエラーのリスト表示もリスト内包表記で書けそうなことに気が付きました。
早速実装してみると、それなりに体感で速くなったような気がしました。
なので、前回のスクリプトを更新しました。

 

それである程度リスト内包表記の経験値が溜まったようで、
四捨五入のスクリプトを見てみると、これも書けるんじゃないか?と思い、書き始めました。
まぁ、どうせ無理だろう。と思っていたのですが、やってゆくうちにひとつひとつ確実にハードルを越え、
できそうで、できない。という状態を続けておりました。
それがようやく出来ました。

 

しかし、
それほど速くはない、、
5千ポリゴンくらいのモデルで0.何秒かのスピードアップです。もっと早くなると思ったのに、、
更にコードを見直し、記述を少なくしてみたのですが大して変わりません。
因みにこちらです。

import maya.cmds as cmds
import maya.mel
import math

def round_weight():
	gMainProgressBar = maya.mel.eval( '$tmp = $gMainProgressBar' )
	oSel = cmds.ls( selection=True )
	oShp = oSel[0]
	oSkt = cmds.listHistory( oShp )
	oCls = cmds.ls( oSkt, type= "skinCluster" )[0]
	oMxc = cmds.getAttr( oCls+".maxInfluences" )
	oVtx = cmds.ls( oShp + ".vtx[*]", fl=True )
	oVcount = len(oVtx)
	oRoundLen = 2
	cmds.progressBar( gMainProgressBar, edit=True,beginProgress=True, status='Now Rounding...', maxValue=oVcount )
	[[cmds.progressBar(gMainProgressBar,e=1,s=1),cmds.skinPercent(oCls,v3,nrm=0,zri=1,tv=zip(*l2))]
	if sum(l2[1])==1.0 else [cmds.progressBar(gMainProgressBar,e=1,s=1),cmds.skinPercent(oCls,v3,nrm=0,zri=1,tv=zip(l2[0],[round(1.0-sum(l2[1][:-1]),oRoundLen)
	if i==len(l1)-1 else x for i,x in enumerate(l2[1])]))]
	for v3,l2 in [[v2,zip(*l1[-oMxc:])] if len(l1)>oMxc else [v2,zip(*l1)]
	for v2,l1 in [[v1,sorted(dict(zip(oJnt,oWei)).items(),key=lambda x:x[1])]
	for (v1,oWei,oJnt) in [[v,[round(w,oRoundLen) for w in cmds.skinPercent(oCls,v,q=1,v=1) if w>0.0],cmds.skinPercent(oCls,v,q=1,t= None)]
	for v in oVtx]]]]
	cmds.progressBar( gMainProgressBar, edit=True, endProgress=True )
round_weight()

全く読みにくい。
開発していた時の物とは違い、プログレシブバーを付けたり、色々と改行を加えたりしたので、動作は保証しません。
一応大丈夫のようでした。もう面倒くさいので、しばらく見直したくない。本当に読みにくい。
ここまで可読性を損なっても、大して変わらないならやめたほうがよさそうです。
しかし、色々と勉強になりました。

Maya Script Python ポリゴンエラーの検出

image935l

# -*- coding: utf-8 -*-
import maya.cmds as cmds
import maya.mel

def gkn_list_select_es( flag,oVtx ):
	if flag == 1:
		oSel = cmds.textScrollList( "PolyList" , q = 1 , sii = 1 )
	else:
		oSel = cmds.textScrollList( "VtxList" , q = 1 , sii = 1 )
	oHi = []
	[ oHi.extend([oVtx[j-1]]) for j in oSel]
	cmds.select( oHi , r= 1 )

def gkn_error_search():
	polys = cmds.ls( sl= 1, o= 1 )
	if polys != [] :
		tVtx = []
		lPoly = []
		tVtxElog = []
		lPolyElog = []
		lVtx = []
		fPoly = []
		lVtxElog = []
		fPolyElog = []
		selPoly = []
		polyElog = []
		selVtx = []
		vtxElog = []
		oCount = len(polys)
		gMainProgressBar = maya.mel.eval( '$tmp = $gMainProgressBar' )
		cmds.progressBar( gMainProgressBar, edit=True,beginProgress=True, status='Now Search...', maxValue=oCount )
		for p in polys :
			tVtx.extend( cmds.ls(cmds.polyInfo( p, nmv= 1), fl= 1 ) )
			tVtxElog.extend( [u"非多様体" for x in tVtx] )
			lPoly.extend( cmds.ls(cmds.polyInfo( p, lf= 1), fl= 1 ) )
			lPolyElog.extend( [u"ラミナフェース" for x in lPoly] )
			faces = cmds.ls(p + ".f[*]",fl=1)
			oVtx = cmds.ls(p + ".vtx[*]",fl=1)
			lVtx.extend([oVtx[i] for i,x in enumerate([cmds.polyNormalPerVertex( v, q=1 , al = 1 ) for v in oVtx]) if x == [True]])
			lVtxElog.extend( [u"法線ロック" for x in lVtx] )
			fPoly.extend([p+".f["+"".join(x).split()[1].split(":")[0]+"]" for x in [cmds.polyInfo(f, fv= 1) for f in cmds.ls(p+".f[*]",fl=1)] if len("".join(x).split()[2:]) > 4])
			fPolyElog.extend( [u"多角形" for x in fPoly] )
			cmds.progressBar( gMainProgressBar, edit=True, step=1 )
		cmds.select(cl=1)
		cmds.progressBar( gMainProgressBar, edit=True, endProgress=True )
		selPoly.extend(lPoly)
		selPoly.extend(fPoly)
		polyElog.extend(lPolyElog)
		polyElog.extend(fPolyElog)
		selVtx.extend(tVtx)
		selVtx.extend(lVtx)
		vtxElog.extend(tVtxElog)
		vtxElog.extend(lVtxElog)
		if selPoly == [] :
			selPoly.append(u"エラーは見つかりませんでした")
			polyElog.append("")
		if selVtx == [] :
			selVtx.append(u"エラーは見つかりませんでした")
			vtxElog.append("")
		if cmds.window("errorpolyUI", q=1, ex=1) :
			cmds.deleteUI("errorpolyUI")
		oErrorp = cmds.window("errorpolyUI", title="ErrorPolys", w=400, h= len(selPoly)*20 )
		cmds.columnLayout(adjustableColumn=True)
		oScrollLayout = cmds.scrollLayout( h= 400 )
		cmds.rowLayout( nc= 2, adj= 2, cw2= ( 300, 100 ) )
		cmds.textScrollList( "PolyList" , w = 280 , h= len(selPoly)*15+10, ams = 1 )
		cmds.textScrollList( "PolyList" , e = 1 , ra= 1 )
		cmds.textScrollList( "PolyeList" , w = 100 , h= len(selPoly)*15+10, ams = 1,en= 0 )
		cmds.textScrollList( "PolyeList" , e = 1 , ra= 1 )
		for i,r in enumerate(selPoly) :
			cmds.textScrollList( "PolyList" , e= 1, a= u"{0}".format( r ) )
			cmds.textScrollList( "PolyeList" , e= 1, a= u"{0}".format( polyElog[i] ) )
		if selPoly[0] != u"エラーは見つかりませんでした":
			cmds.textScrollList( "PolyList" , e = 1 , sc= "gkn_list_select_es( 1," + str(selPoly) +" )" )
		else :
			cmds.textScrollList( "PolyList" , e = 1 , en= 0 )
		cmds.showWindow(oErrorp)
		if cmds.window("errorvtxUI", q=1, ex=1) :
			cmds.deleteUI("errorvtxUI")
		oErrorv = cmds.window("errorvtxUI", title="ErrorVtxs", w=400, h= len(selVtx)*20 )
		cmds.columnLayout(adjustableColumn=True)
		oScrollLayout = cmds.scrollLayout( h= 400 )
		cmds.rowLayout( nc= 2, adj= 2, cw2= ( 300, 100 ) )
		cmds.textScrollList( "VtxList" , w = 280 , h= len(selVtx)*15+10, ams = 1 )
		cmds.textScrollList( "VtxList" , e = 1 , ra= 1 )
		cmds.textScrollList( "VtxeList" , w = 100 , h= len(selVtx)*15+10, ams = 1, en= 0 )
		cmds.textScrollList( "VtxeList" , e = 1 , ra= 1 )
		for i,r in enumerate(selVtx) :
			cmds.textScrollList( "VtxList" , e= 1, a= u"{0}".format( r ) )
			cmds.textScrollList( "VtxeList" , e= 1, a= u"{0}".format( vtxElog[i] ) )
		if selVtx[0] != u"エラーは見つかりませんでした":
			cmds.textScrollList( "VtxList" , e = 1 , sc= "gkn_list_select_es( 2," + str(selVtx) +" )" )
		else :
			cmds.textScrollList( "VtxList" , e = 1 , en= 0 )
		cmds.showWindow(oErrorv)
gkn_error_search()

すみません、適当なコードです。

 

単一、もしくは複数のオブジェクトを選択し実行して使います。
コードをスクリプトエディタにペーストすると直ぐに実行されます。
選択されているオブジェクトの非多様体頂点、頂点の法線ロック、多角形ポリゴン、ラミナフェースを検出します。
検出されれば、それらがリストとしてウィンドウに表示されます。
ウィンドウに表示されているリストを選択すると、エラーとして検出された頂点、もしくはポリゴンを選択します。

 

どれだけ早く動くのだろうか、と、forループでひとつひとつの頂点やポリゴンを見ていたのですが、
リスト内包表記に変えてみました。
大分早くはなったようです。ただ、可読性が著しく低い、、
エラーが多すぎると、ウィンドウに表示するのに時間がかかります。

 

modoもクリーンナップを自動でしてくれますが、自動ではなく選択してくれるとありがたいのですが、、
でも多角形ポリゴンは直ぐに見つけられるのが良いです。
Maya2012でも2013でも動きます。

※追記2012/5/15
リスト表示もリスト内包表記にしました

ウェイトエディタ更新 その4

またまた更新です。
Maya2013でも動作確認できました。
今までジョイントのリストを取得する際にわざわざ頂点から情報を取得していました。
速度に問題は無いかと思うのですが、その場合スキニングした後に頂点を追加してエディタで見てみると
正しく表示されませんでした。
その場合は無視するようにしました。

 

それと、スキニングする際に「ウェイトの正常化」が「インタラクティブ」以外の時は、
ウェイトを編集しても正規化が行われなかったため、強制的にインタラクティブにするようにしました。

 

そして、ウィンドウの小型化です。

 

しかし、いくらいじり倒してもMayaは好きにはなれないなぁ、、
modoの画面を見るとほっとする。

ZBrush4 久々のZBrush

image931l
そういえば、久しぶりのZBrushで久しぶりの画像の投稿です。

 

ZBrushを久しぶりに触りました。
すっかり下手になっている。元々大したことはないが。
作り始めて1時間くらいでしょうか、紆余曲折しながらやっております。
(ビューはこの角度で、この部分をこういじりたいんだよなぁ、)とか考えてしまいます。
すると、(じゃあ粘土でやれば良いじゃない。)
で、(それはそうなんだけどさぁ、、)と自問自答しております。
慣れればもっと効率的に手が動くのでしょうが、そのへんはまだまだです。

 

因みに、
image932l
これが元の形です。
できるだけセグメントを切らずにZBrushに持ってゆきました。
感想としては、確かにその方がサブディビジョンレベルを大きく上げることはできるが、
形の制御が難しい。
ある程度セグメントを切って持ってゆくのも、形を締める、という意味合いからで言うと良いのかも知れません。

 

そういえば、MudBoxを更に久しぶりに触りました。ちょっとだけですが。
どのくらいの負荷に耐えられるのだろうか、と細分化をしたところ、意外と大きく上がりました。
使い勝手は知りません。なにせもう何年も触っていません。
うーん、意外といけるのかも。と思ったくらいです。
海外でCGをやられている方々で、ZBrushとMudBoxを併用している人がいますが、あれはどんな意味があるのだろうか。
気が向いたらその辺も身を持って体験してみようかと思います。

ウェイトエディタの更新 その3

性懲りもなくウェイトエディタを更新しています。
色々と機能をいじっていたら、Round機能が正しく動かないことが判明しました。
複数オブジェクトに対応できていなかっただけです。対応しました。
あれやこれやと追加しているので、どうしてもそうなってしまう。

 

ポイント選択の時に選択しているオブジェクトの名前を取得する方法って、正攻法があるのだろうか?
良くわからないので、とりあえず動くようにしました。ちょっと釈然としません。
メインの機能についてはあらかたバグは取れたかと思いますが、それ以外では知りません。
汎用に作るとなると、やはり面倒くさい。自分で使う分にはある程度でいいので楽です。

 

コピー・ペーストの機能、ちょっと変えました。
コピー元とコピー先が同じ数であれば、それぞれ選択順にウェイトの値を入れるようにしました。
意外と矩形選択でもそれなりに使えるようです。あくまでもそれなりです。
modoのように順繰りにキーボードを使って選択を追加できると良いのですが。
うーん、その機能追加してみようかなぁ、、出来るのかぁ、、

初めてのPython


買いました。

 

実は前に図書館で借りて勉強しました。
とても参考になったので、いつかは欲しいなぁ、と思っていました。
ダメ元で古本屋に行ってみると、ありました。

 

自分が買ったのは第二版だったのですが、価格を見ると1250円。
これは買わねば、と、内心小躍りして、レジに持って行くと、「2400円になります。」と言われました。
「えっ、でも1250円って、」と裏表紙をめくって値段を見せたのですが、表紙には2400円の値札が貼られていました。
ついつい、通常の古本屋の気分で値段を見ておりましたが、大手ではどうやら違うようです。
店員さんが慌てて偉い人に聞きに行きました。まぁ、この値段で買えるのならば仕方がないかなぁ、と諦めお金を出していると、
「書き込みがあるので、廃棄処分になります。どうしても、というのであれば、105円でお売りすることになります。」
元々1250円で得られていたものを2400円で売るとは厚かましい。などとは一瞬足りとも思わず。
「是非ください。」と買わせて頂きました。

 

前回読んだ感想ですが、ところどころ重複する部分がありますが、全体的に網羅されているかと思います。
自分が最初に買った本が、「みんなのPython」という本でしたが、これは確かに初歩的なことを全体的に説明はされているのですが、
実際の使い方などがなかったりします。
始めの頃は分からなかった事が最近改めて読んでみると、あぁ、そういうことを言っているのか。と理解ができます。

 

これも人間の脳の生理的なものを考えると当然の事ですが、自分の頭の中で当たり前になったことを何も知らない人に説明するのは難しい。
人間を含めた生物は、物事をできるだけ早く理解するために、要素をパターンで認識する癖があります。
人の顔を覚えているのは、その人の顔のパーツそれぞれを正確に覚えているのではなく、大まかなパターンとして認識しています。
なので、見れば直ぐにその人であることが分かっても、文章にするのは難しい。
そもそも言語化するものではない。

 

言語を説明するのに言語化出来ない。とは何とも皮肉なものです。
やればわかる。

 

それは大変便利な機能ではありますが、思い込み、という面も併せ持ちます。
昔は速読できる人が羨ましい。と思い、自分もそれに挑戦してみました。
しかし、今から考えると、それはパターン認識に当てはめているだけで、部分的な名称などはそれなりに記憶できるのでしょうが、
恐らく全体の繋がりなどは、思い込みで繋げてしまうのだろうと思います。
ゆっくり読むにしろ、速読するにしろ、結局は思い込みというバイアスを持った人間の脳が理解することなので、変わらない。
という言い方もできると思います。
だからどうでもいい。と考えるようになりました。

 

とにかくより深くPythonを勉強できる環境が整いました。
第二版ではありますが、105円では文句の付けようがない。
大変ありがたい買い物をさせて頂きました。

ウェイトエディタの更新 その2

また更新してしまいました。
内部的な変更です。

 

Roundでウェイトを四捨五入する際に、設定されているインフルエンスの数を見るようにしました。
以前はつけていたのですが、無くても良いんじゃないか。
と思い、取っていたのですが、ペイントスムースを使うとやはり数を超えてしまうようです。

 

それと、無意味であろう分岐の削除。
何を思って分岐をさせたのか自分でも良く分かりません。自分で書いておきながら身に覚えがない。
意味のないエラーが発生することがあったので、取ってしまいました。

 

機能を後付にし、言語そのものを習得している最中なので、色々とまずいところがあります。
バグ報告、追加機能、あれば善処します。

雑記94 ケミカルマシンか電子回路か

突然ですが、脳みその話です。

 

脳科学では脳の本質は化学反応にある、という人もいれば、そういったものはコンピュータにおける
回路内での分子の量子的な振る舞いで、それらが違っていても計算は変わらないのと同じように、電子回路である。
という人もいます。

 

脳が薬品によって作用されることは、麻薬や抗鬱剤でも分かります。
近年ではアメリカにおいて、抗鬱剤が効かなくなった患者に対して頭骨越しに磁気を当てることで治療する方法が流行っているそうです。
磁場が発生すれば、電場が発生する。と言うことのようです。

 

脳神経細胞であるニューロンは3つの部位により構成されています。
大本である細胞体、そこから植物の根のように伸びる樹状突起、そしてこれまた植物の茎のように伸びる軸索。
軸索の先にはシナプスと呼ばれる植物の花のような房が多数付き、別のニューロンの樹状突起に接続される。
接続といっても完全にくっついているわけではなく、少し離れている。
細胞体から発せられた電気信号が軸索を伝わり、シナプスに到達すると、そこにあるシナプス小胞が破裂し、化学物質を放出し、
次のニューロンの樹状突起へと信号が伝わる。
薬を飲むと変化が起こるのはその際に受信される化学物質に変化が起こるからだと思います。

 

記憶がどこに存在するか、長年の謎ですが、ネットワークの構造そのものが持つ部分と化学物質として保存されている部分があるのだと思います。
電気では直ぐに消えてしまう。

 

以前五感について書きました。また補足して書きます。
人の五感は大きく分けて2つに分けられる。触覚、視覚、聴覚という波や圧力という物理量を計測する感覚器と、
味覚や臭覚といった化学反応を検出する感覚器です。
といっても、辛味や苦味の一部は物理量です。だから個人差が激しい。

 

線形で表現可能な物理量はリバースエンジニアリングが容易です。
既に身の回りにある様々なセンサーを見れば分かります。
それに対して化学反応は難しい。しかし最近ではアメリカ軍の開発した爆発物検出器は嗅覚のリバースエンジニアリングだそうで、
東京ドームに水を満たし、その中に角砂糖一つを入れた程度の濃度を検出できるそうです。
 

話がそれました。
味覚と臭覚は大脳辺縁系と呼ばれる、脳の中でも古い方の部位に接続されている。
人間の脳が大きい、といっても新皮質の部分が大きいだけであって、辺縁系は他の動物と大して違わない。
だからそれらの感覚器で受診したものは、新皮質の機能の一つである、言語化が難しい。
人間の嗅覚も実は大したものだそうで、鍛えれば犬に近づけるそうですが、視覚情報に重きを置くので中々そうは行かない。
味覚という点では、面白いことに年によって差が出てくる。
味蕾と呼ばれる味覚器は他の神経細胞と同様、年とともに減少します。
なので、感覚器という点においては子供のほうが優れている。だから子供は甘いモノが好きで、苦いものが苦手なのだろうと思います。
感覚器の減少、脳による情報の蓄積それらが合わさると、苦味や渋みの良さが分かるようになる。

 

ああ、話が戻らなかった。
生命が始めて手に入れた感覚器は嗅覚だと言われております。
要するに我々生命体が始めて外界を知覚したのは化学反応だった。と言う事です。
そしてその検出器の面白いところは、化学物質と検出器は古めの鍵と鍵穴のような関係にあり、同一の化学物質のみを検出するのではなく、
ある程度形があえば、違う物質で合っても鍵穴に入ってしまう。といういい加減さを持っています。
その中でも無臭の化学物質、フェロモンも嗅覚によって知覚されます。統計的な有意性が認められ、ドミトリー効果という名前が付けられた現象は、
同じ職場で働く女性、同じ部屋で生活する女性の月経周期に同期が見られたそうです。
哺乳類そのものがフェロモンを使った通信を行うので、当然といえば当然のようにも思います。
そういえば、養老孟司さんがどこかに書いておりましたが、好き好んで満員電車という同種が同じ空間に集まる哺乳類はそういない。
そのストレスがフェロモンとなって電車に充満する。だから都会の人間は頭がオカシイのだろう。そんな事を書かれていたように思います。

 

電気と化学物質、どっちも都合よく使ったんじゃないかな?
進化の歴史を紐解くと、身近にあるものをその場しのぎで使ってゆく。そんな場面しかありません。
散々書いておいて何ですが、どっちでも良くないか。と思います。

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

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

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