ZBrush – Terrain Tools

TerrainToolsというZBrushのプラグインを買いました。
gumroadではいつも無料のものばかりをダウンロードするのですが、今回は2.5ドルの有料ツールを買ってみました。

 

WorldMachineを使わずに、侵食がきれいにできるか、疑問だったのですが、中々です。
しかも速い、、
そして、各種マップも出力でき、それらをSubstanceDesignerで合成すると
2017_03_15_6064
こんな感じです。

 

これがたった3百円程度のプラグインで生成できるって、凄いですぇ、、
因みにZBrushでは、
2017_03_15_6066
こんな感じに生成され、SubstanceDesignerで見るのとほぼ同じようにできます。
あぁ、2年前にあれば、だいぶ助かったのに、、

 

そんなかんなで、驚いていたら、
こんなものを見つけましたが、
何なのでしょうか?
リンク元を忘れましたが、Unityで動いていたような気もするのですが気のせいでしょうか。

 

それはそうと、今後テクスチャはフォトスキャンが主流になるだろうなぁ、などと思っていたのですが、
SubstanceDesigerではScanProcessingというカテゴリが追加され、一つの素材を4から8方向の照明で取った写真を元に、
各種情報を再現させる、という方向性を提示し、どちらも一長一短の手法のように思います。
特にフォトスキャンの場合は、取ってきた素材が、現像した後に使い物にならないことがわかるとゲンナリしますし、
Substanceの手法の場合は、特殊な自作装置でも作らない限りは、スキャンするのが難しそうです。
そんなことを思っていると、こんなものがありました。
Nvidiaが作ったようですが、Unity上でフォトスキャン、という感じでしょうか?
ノートパソコンを持ち歩いて、その場で現像出来るようなので、これは中々良さそうです。

 
と、思ったら、さらにこんなのもあります。
トラッキングツールのようですが、下の方におまけのような形で、メッシュの出力、各種マップの出力が出来る。というようなことが書いてあります。
ああ、これが最強ですね、、
以前シーグラフで、撮影した動画を元に、陰影を抜いたアルベドとメッシュ形状を生成する。というようなものがありましたが、あのテクノロジーなのでしょうか?

 

いやー、進化がはやいですねぇ。
進化と言えば、MayaのUV編集、とてつもなくパワーアップしていて、ビックリでした、、うーんMODOより便利かも、、

Substance Designer – Bevel node

おう、、今年まだ更新してなかったのですね、、すっかり疎かになっております。

 

Substance Designer、6がリリースされ、HDRStuidoが不要になってしまいそうですねぇ。
なんとも凄いです。

 

今回はそこまででは無いのですが、Bevelノードを使ったノーマルの作成において、ジャギーが酷くて使い物にならないのを何とかする。
というのを紹介します。

 

まずは普通にBevelしたもの。
2017_02_27_6041
ちょっと引きでわかりにくいですが、
2017_02_27_6042
拡大するとこんな感じです。
画像自体は1kでつくっております。まぁ、とてもじゃないけど使い物にはなりません。
調べてみると、同じように困っている人がいるようで、解決策をフォーラムで書かれておりました。
一応言っておきますが、それを見つける以前に同じ方法を発見しました。まぁ、どうでもいいのですが、、

 

簡単にいってしまうと、大きく作って、縮小する。です。
なので、今回の場合はSVGを使っているので、拡縮は自在にできますから、
大本のSVGのノードの解像度設定を2段階ほど上げておくといい感じです。
もちろん上げれば上げるほどにきれいにはなりますが、重くなります。
で、その結果。
2017_02_27_6044
こんな感じになります。まだ少しジャギが残っていますが、まぁ、許容範囲ではないでしょうか。
Bevelの後にブレンドノードをつなげておりますが、個人的には解像度を合わせる方法として、最も楽でスマートではないかと思っております。
上の方の接続に刺せば、アウトプットのサイズに変更してくれます。
なので、変更するのは大本のSVGの解像度だけになります。

 

因みにフォトショップでやれば、そもそもそんなことは起きないのではないか、と思いやってみると、
2017_02_27_6043
シゼルソフトでほぼ同じようになります。
デフォルトの「滑らかに」では丸まりすぎだと思います。
ああ、書いていて思い出しましたが、手っ取り早くよりきれいにするには、Bevelノードの「Smoothing」の値を増やしてやると滑らかになります。
やりすぎると丸まりすぎます。

 

ついでに、輪郭が欲しいときは「Edge Detect」ノードが役立ちます。
2017_02_27_6046
こんな感じに輪郭線を抽出して加工できます。
ただ、際の部分が丸くなってしまいます。
鋭角を保ちたい場合は、こちらのノードが役に立ちます。
2017_02_27_6047
ただこの場合、Bevelに一度繋いで、Histogram Maskでエッジを抽出した後に再びBevelで加工。という手順が必要になります。

 

だいぶ前にこの手法を編み出し、記事に書こうと思っていたのですが、忘れており。
最近同じ処理が必要になったときに、どうやってきれいなノーマルを作ったのか、すっかり忘れて焦りました。
段々と物忘れが多くなってくるようです、、

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の各種クラスの使い方とリストの平坦化など、
色々とメモしておきたいコードでした。

AOマップ

2016_10_16_6015
AOマップって、微妙じゃないですか?
SubstanceDesignerに標準で入っている、HightmapからAOを作成するノードだと、情報が飛びすぎていて、正直使い物にはならないかと思います。
で、自作で作ったノードで表現したのが上図のものです。
ちょっとフォトスキャンっぽい感じが出たかと思います。

 

わかりやすく、どこかで拾った(恐らくSubstanceShare)岩肌のマテリアルでテストです。
2016_10_16_6016
まずはSDデフォルトのノードです。
暗いところが黒すぎるし、明るいところが白すぎる、、まぁ、パラメータをいじってはいないのですが、
いじったところで、そう劇的に変わるものでもありません。
2016_10_16_6017
これが今回作ったノードのデフォルト値です。
パラメータをいじると、
2016_10_16_6018
これはちょっと濃すぎますが、自在に情報量を変化させることができます。

 

内容は単純で、マスクを作る際に使用する、Lightノードと、フォトショップで言うところの、ドロップシャドウを組み合わせたのがベースになり、
入力したノーマルマップのBlueチャンネルを乗算したり、Curvatureをブレンドしたりします。
幾つかのマップで試して見ましたが、今のところ、見た感じがフォトスキャンで生成したAOマップっぽい感じが出ているかと思います。
添付しておきます。
Nor2AO

さて、話題は変わりますが、MODO10.2。
10.1は色々とバグだらけで、すぐに落ちたり、動作が妙に重かったりしましたが、今のところそのどちらも解消されているように思います。
最も嬉しいのは、スクリプトを実行したときの遅延がなくなっていることでした。当たり前のことなのですが、正直一番きつかったです、、
で、本日MODOとUnityのセミナーがありましたので、参加させていただきました。

 

10.2が昨日リリースされたことを受け、初めの方で10.2の新機能を説明していただきましたが、
説明されている方の声を聞いてびっくりしました、、MODO Japanのブログで動画解説されている方だったのですね。
いつもありがとうございます。

 

中々仕事でMODOを使える機会が減りましたが、久しぶりに旧知の人に会えたような感じで、良かったです。
是非ともこれからは安定したバージョンのリリースをお願いします。

V-Ray for MODO 2

vrayRenderEames01

結局V-Rayでレンダリングしておりました。
Unrealははやり、ライトマップが面倒なので、やめにしました。
ひたすらVrayMODOをいじり倒していたのですが、中々いい具合の設定が見つけられずに、しかもMODO10が落ちまくり、遅々として作業が進みませんでした。
なので、MODO8でやることにしたのですが、色味が違うのですねぇ、、
まぁ、設定したばかりだったので、大した苦労はなかったのですが、落ちなくなって快適に作業は進みました。

 

しかし、どうにもレンダリングするごとに勝手に画像サイズを変更されたり、
幾つかのジオメトリが表示されずにレンダリングされたりと、不可解な現象に悩まされました。
RTレンダリングと交互に行うと、解消されることがあるので、バグなのでしょう。早く直してください、、

 

サブスタンスではこんなものを作ってみました。
2016_10_07_6012
サブスタンス上で形状を作って、立体化させて、破壊を施す。というグラフです。
数学の知識があれば、入力した形状を三次元で変形させる仕組みが出来るのでしょうが、無いのでできません。

Architectural 建築モデリング 日本語版

ものすごい今更ながら、なのですが、「Architectural 建築モデリング」のチュートリアルをやってみました。

 

このチュートリアル、modo302の時に作られたようです。
因みに英語版だと、ただで見ることができます。

 

ここ数年、仕事上はMayaでしかモデリングが許されない環境で、渋々Mayaを使っております。
確かに2016では、それ以前と比べ大幅にポリゴンモデリングの機能が増え、格段にモデリングはしやすくなっているのですが、MODOに比べてしまうとやはりその差は大きいです。
久しぶりに、モデリングとは楽しいものである、ということを感じることができました。

 

ビデオは3本で、約30分2つと約40分が一つ。
恐らく操作に慣れていれば、ビデオを止めることなく、作業が出来るかもしれません。なので、再生時間が完成の時間になりうるかもしれません。
ただ、このビデオの問題は、単位がインチ、フィートであること、があげられると思います。入力が面倒くさい、、
そして、場所によっては、指示がいい加減で、このあたりのポリゴン、とか、この辺りまで移動、という表現が出てきてしまいます。
まぁ、仕方ないところでもあるとは思うのですが、、
でも、それがあってもこのチュートリアルは凄い。もっと早くに出会っていれば、と痛感させられます。
未だに色褪せない、数々のテクニックが紹介されております。
MODO10と比較すると、その部分はこうすればもっと手早く出来る、と思うところもありますが、なるほど、と勉強になる部分もありました。
やはり、Mayaにも作業平面と多彩なフォールオフは入れて欲しいなぁ、、

 

で、完成がこちら。
2016_09_18_127
モデリングのみです。
それをUE4に持って行ったのが、こちら
2016_09_18_128
持って行って、ライトマップを焼いただけです。

 

MODO10ではUVの機能も強化されており、「矩形」ツールで歪んだUVを矩形にしてくれる機能や、
変形ツールの「放射状」を「4」で実行することで、マップを強制的に四角形にすることができ、ライトマップの生成に大いに貢献出来るかと思います。
できれば、矩形ツールがもう少し柔軟になってくれるとありがたくはあるのですが。

 

まぁ、まとめてしまうと、久しぶりにMODOでモデリングして、羽を得たような感覚を覚えてしまい、とても楽しかった。ということでした。

V-Ray for MODO

aa_vray05a
V-Ray for MODOを導入しました。
ずっとテストをしていたのですが、まだマニュアルが完備されていないので、半ば手探りです。
床のノイズが消えない、、

 

シーンは以前購入した「modo 実践チュートリアルビデオ インテリア編」です。
頑張ったのですが、随分元と比べると眠い画像です。
始めのうちはマテリアルはMODOで使用されているものを使っていたのですが、最終的にはV-Ray用のものに変更しました。
Denoiserというノイズ除去の機能を使用してみました。因みにそれを使わないとこんな感じです。
aa_vray05b

 
MODOのV-Rayは他のと比べると随分と遅いようで家の環境では19分もかかりました。
CPUはi7-3770です。
確かに使っていて早い印象は受けませんでした。
Denoiserはレンダリング時間が少し追加されます。
色々と数値をいじっては見たのですが、これ以上ノイズを取るには至りませんでした。
50分以上かかる方法でもやってみたのですが、比較しても差はほぼなかったです。まだまだです。

 

そういえば、久しぶりにMODOの記事でした。ボロノイの事やMayaのスクリプトでの備忘録が溜まっているのですが、無精で記事にし損ねております。

Python – カラーの値変換 float to RGB – RGB to float

Maya関係ないし、ただの備忘録です。
たまーに使うのですが、たまーにしか使わないので、忘れてしまう。

f = 0.5
i = 128
print int(f*256) if f <= 1.0 else 255
print i/255.0
#Result
128
0.501960784314

超初等数学ですね、、

Substance Designer – ボロノイ図1 形状を加味したひび割れ

2016_08_05_114
なんだか連日の投稿が続きます。
随分と前から地道に進めていたのですが、中々突破口を見いだせずに悶々としておりました。
SubstanceDesignerとWorldMachineは実は同じ用途のツールで、どちらもノードを組み合わせて画像を生成します。
大きな違いを上げるとしたら、方や線形方程式で、もう一方が非線形方程式(多分完全ではない)ということがあげられるかと思います。

 

その辺の話は置いといて、SubstanceDesignerでマテリアルを作成するときの弱点は形状に準じた効果を入れづらい。
ということがあるかと思います。その辺りが線形、非線形に関わってくると思うのですが、
どうもSubstanceDesignerとしては、その弱点をSubstancePainterで補おうとしているように感じます。
ただ、どうもPainterは重くて、個人的には気が引けます。やはりテクスチャペイントには3Dcoatの方が未だやりやすいと感じてしまいます。

 

前置きが長くなりました。
ともかく今回は形状(ここではハイトやノーマル)によってマテリアルのダメージ具合を変更することに成功したように思います。
高いところがひびが多く、細かい状態で、低いところがその逆です。
できてますよね?
しかもなぜだか知りませんが、端の方では放射状にひびが広がっている。偶然の副産物です。
今回の形状がそういった偶然が重なるものなのかも知れません。
今後他の形状も試してみて、うまく行けば公開します。

Maya Script – 上向きのフェースを選択する

地形などのデータを作るときは、そのフェースが地面に適しているかを判定する必要があります。
ゲームデータの話です。
以前、そういったスクリプトを書いたのですが、ベクトルでの指定で、角度ではなかったので、角度指定が出来るように変更しました。

 

ただ、問題が、、
以前書いた時に汎用となる関数、の名前が「get_ploy_comp」でした、、
「l」と「o」が反対です。
よりによって、汎用的に使える関数でスペルミスをするとはなぁ、、と気づいて愕然としました。

 

なので、今回はちゃっかり直して、公開します。
以前のものは、直しません。

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

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

def select_yup_face_om2(val = 45.0):
	sel = cmds.ls(sl=1)
	node,comp = get_poly_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 pm.datatypes.degrees(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(55.0)

関数「select_yup_face_om2()」に任意の引数を入れて実行してください。
今回は「55.0」垂直から55度傾いたフェースまでは許容するよ。という感じです。
実行すると、
2016_08_04_113
こんな感じで、地面として許容されるフェースが選択できるので、意図したようになるよう調整することができます。

 

で、作っていて思ったのですが、選択だと、頂点を動かす、などの調整を行い、再びスクリプトを実行して確認する必要がある。
瞬時にできて、便利だ。と思っていたのですが、そもそもそれをリアルタイムで判定して色を変えれば良いじゃないの。
と、シェーダを作ることを思い立ちました。
そのほうが圧倒的に早いですよねぇ、、ばかみたいな事をしておりました。
まぁ、せっかく作ったんだし。これはこれでいいか。と、公開です。
pymelのdatatypesを使って変換しているだけなので、大した事はしてないんですけどね。

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

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

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