基礎から始める3dsmax/Python(MaxPlus)プログラミング①

今週から「Brosのブロブロ」は毎週月曜と木曜の更新になります。今後ともよろしくお願いします。

さて、MayaでPython講座をやってきましたが、やはり3Dツールとしては3dsMaxの方も外せないでしょう。
「基礎から始める…Python」というタイトル通りに全く初めての方でも解る解説をしますが、3dsMaxの基本操作や知識は省略します。

まず、3dsmaxで使えるスクリプトは基本「MAXScript」というのがあります。
これは他の言語とは互換がなく、3dsMaxだけで使えるプログラミング言語です。Mayaでも「Mel」という独自のプログラミング言語があります。

独自のプログラミング言語では限界が出てしまい、やはりMaya同様に汎用的なPythonを使えると将来が明るい兆しが見えるでしょう。
それについてはここを含めて、参考にできる本やサイトがいっぱいありますのでここでは省略します。

3dsMaxでPythonを使うには2通りあります。
1つは「pymsx」で、もともとのMAXScriptをPythonで操作するもの(ラッパーといいます)で、MAXScriptでできることは全て可能です。

2つめが「MaxPlus」で、Max SDKをベースしにています。SDKというのはC++言語で3dsMaxのプラグインを作成するためのもので、大きく機能を拡張できますが、難易度が高いので、Pythonだけでできるメリットがあります。

では、いろいろ実験してみましょう。
今回は3dsmax2017を使います。
メニューから「スクリプト」→「MaxScriptリスナー」を実行します。このウインドウからプログラムを実行したり確認したりします。

起動すると2016だと、

2017ですと、

こうなります。なので、2017でPythonのモードがちゃんとできたので、こちらを使いたいと思います。

では、pymxsから実験しましょう。

まずメニュー下のラジオボタンで「Python」に切り替えて、import pymxsとキーボードで入力して、CTRL+Enterで実行します。
「>>>」と下に出ると正常に動作しています。これは3dsMaxにpymxsのライブラリ(3dsMaxの特有の機能)を読み込む命令です。
このように1行づつ実験的に入力→実行もできます。

間違えると以下のようにエラーが出ます。
エラーメッセージを含めてBSキーやDelで消して訂正して再実行できます。
※注意:ラジオボタンが「MaxScript」へ戻る場合があります。

エディタ上で右クリックから「すべてクリア」でエディタをクリアできます。

スクリプトはCTRL+Zで実行を戻せます。

では、プログラムを追加します。

rt = pymxs.runtime
tea = rt.teapot()

で実行します。

図のように、3dsMaxお馴染みのティーポットができました。
pymxs.runtimeは「ランタイム」をrtという値で設定しています。ランタイムは「プログラムとかを動かすときに必要な外部の部品」という意味です。
tea = rt.teapot()でteaという値でティーポットを作成します。ランタイムの「rt.」を付けなければなりません。

1行ごとに実行は面倒なので、VisualStudioCodeで作ります。

先ほどのティーポットを作成するのに1行追加しています。
tea.radius=10
これは大きさを10に設定する命令です。
これをmax02.pyなど「py」を拡張子にして保存します。

「MaxScriptリスナー」メニューの「ファイル」→「スクリプトを起動」します。

メインメニューの「スクリプト」→「スクリプトを起動」でもOKです。

ところが、ファイルが見つかりません・・・

これはエラーではなく、3dsmaxは基本はMaxScriptを実行するようになっているので、拡張子が「mse」「mcr」がデフォルトなのです。
Pythonに切り替えれば開くことができます。

大きさ10のティーポットができました。

では、今度は「MaxPlus」でやってみましょう。以下の4行をエディタで作成します。

import MaxPlus
obj = MaxPlus.Factory.CreateGeomObject(MaxPlus.ClassIds.Teapot)
node = MaxPlus.Factory.CreateNode(obj)
obj.ParameterBlock.Radius.Value = 10.0

1行目はMaxplusを使うライブラリを読み込みします。
2行目でティーポットのオブジェクトを作成する準備をします。
3行目でティーポットを生成

4行目でRadiusで大きさを10にします。

実行すると先ほどのpymxsで行ったのと同じ結果になります。
パッと見るとpymxsの方が簡単そうで、MaxPlusはだいぶ複雑です。

次回にもう少し詳しく解説していきます。

UnrealEngine4/Voxel Global Illumintaion (VXGI) をテスト①

先週のUE4StudioのPythonの続きをやろうと思ったのですが、ちょっと気分を変えてVXGI2.0=Voxel Global Illumintaionを試してみようと思います。

そもそもVXGI2.0って何?という方も多いと思います。まずは以下の説明が解りやすいかと思います。
https://www.hardwarezone.com.sg/feature-nvidias-next-gen-gaming-graphics-card-geforce-gtx-980-revealed/voxel-global-illumination-vxgi
ちょっと英語で解らないと思うので、簡単に言うと、
「ポリゴンでGIを計算すると大変なので、空間をボクセル(箱)にして、その面を使って簡素化した光の反射を求める」ということらしいです。
上の記事、よく見るとGTX980での説明で2014年ですね。

それが今年Ver2.0で新しくなり、UE4にも搭載したということなので、試してみましょう、ということなのです。
GDC218で「Advances in Real-Time Voxel-Based GI 」というセッション動画、
YouTubeにUE4のVXGIテスト動画がありますので、ご覧ください。

では、早速やってみましょう。
これはちょっと手間がかかります。まずはUE4を普段使っている方もC++のプロジェクトを起動してください。
その時に「VistualStudioをインストールして」と出るので、ダウンロードしてインストールしておきます。(これで1時間くらいかかる場合もあります)

以下のGitHubからUE4-VXGIのソースをダウンロードしましょう。
https://github.com/NvPhysX/UnrealEngine/tree/VXGI2-4.19
「404エラー」が出てしまいます。

UE4の開発初者向けのIDを作成して、右上のユーザ名とパスワードを入力する必要があります。詳しくはここを参考にしてください。

ログインできると上の画面になります。この右の緑のボタンをクリックして、
DownliadZipします。

これは250MBくらいですが、この後の作業で大きいサイズになるので、ディスクの空き容量にはご注意ください。なんと最終的には43GB以上になります!

ダウンロードが終わったら、GitHubのマニュアルの手順通りに作業します。

2つのバッチファイルを順にダブルクリックして、しばらくコマンドプロンプト(黒い文字だけウインドウ)が処理します。
それが終わったらUE4.slnをダブルクリックすると、すごく時間がかかってVisualStudioが起動しますので、右上のエクスプロラーで右クリックから「ビルド」します。ここでまた長い時間を待ちます。

全て終わるまで3~4時間かかるかもしれません。その間暇なので、同じフォルダにGDC2015の資料の「UE4_VXGI_Overview.pdf」があるので読んでみるといいでしょう。

「Engine」フォルダができます。つまり、これはVXGI専用のUnrealEngine4をソースからビルドしたものです。

この「Binaries」→「Win64」にUE4Editor.exeがあるので、右クリックから「管理者として起動」します。

私はこんなショートカットを作りました。もともとUE4.19他がインストールされていても、動作には問題ありません。

以下のように、いつもと違う起動が始まれば正解です。私はこのあとWindows8.1がクラッシュしましたが、2回目で正常に起動しました・

ダウロードしたフォルダにSamplesフォルダにサンプルプロジェクトが2つあります。
CornelBoxはYouTubeに動画があるので、「SciFiHallway」を起動します。

プロジェクト名で記憶がある方もいるかもしれませんが、UE4のマーケットプレイスにあるプロジェクトです。

では、VXGIを使ったら、どういう画像になるのかを動画でご覧ください。
プレイヤーにライトが付いていて、歩いている先に光があたります。ちゃんとリアルタイムでGIと反射がされているのが解ります。

キーボード「Z」でVXGIのDiffuse(拡散反射光)、「X」でSpecular(鏡面反射光)をOn/Offを試せます。

ちなみにマシンはWindow8でGPUはGTX980でメモリは64GBです。それほどのハイスペックではありませんが、コマ落ちせず、これだけのことが実現できます。
これは実用的で凄いのではないかと思います。

次回、もう少し設定など機能を細かく解説していきます。

文系デザイナーのためのmaya MEL/Python基礎の基礎 Step2-12

今回はチェックボックスと文字入力です。
今日の最初のプログラムはこんな感じです。

1から10行目までは前回とあまり変化なく、スライダー作成するだけです。
11行目からですが、これもそんなに違いはありません。For命令でスライダーの値のマイナスから繰り返しています。

def makeCube():
 hei=pm.intSliderGrp(boxH,q=True,value=True)
  for i in range(-1*hei,hei+1):
   print i
   pm.polyCube(w=0.9,h=0.9,d=0.9)
   pm.move(0,0,i)

なので、スライダーが3だと、-3,-2,-1,0,1,2,3と7回繰り返し、Cubeは-3から3まで7個作成され、0.9なので少し隙間ができます。

では、これを改造して以下のようにします。ちょっと長いですが、良く見てください。

実行すると、チェックボックスができるのでXをOnにして実行します。

XとZをOnで4つ

XYZ全部Onで5つ。好きな項目をOn/Offできる機能が付きました。
プログラムは長いですが、新しい箇所は少ないです。7~9行目で、

checkBox1 = pm.checkBox(label='X')
checkBox2 = pm.checkBox(label='Y')
checkBox3 = pm.checkBox(label='Z')

だけでチェックボックスが表示されます。簡単ですね。

あとは、その3つの変数を、関数の方の19,23,27行目でif分で判断しているだけです。

if checkBox1.getValue():
if checkBox2.getValue():
if checkBox3.getValue():

ifが3つですから、チェックボックスがOnのものは全部実行されるのです。
でも良く見てください。それぞれのifの下の3行はほとんど同じですよね?
それぞれの最後の行、22,26,30だけX,Y,Zのどれを移動するかの違いです。
これはムダで美しくありません。
それとこれはバグがあるんです。これだと、0,0,0の位置のCubeは複数あることになりますね。

では、17行め以降を書き換えます。

ほぼ同じことを3回やるので、これをcopyCubeという新しい関数にします。

def copyCube(hei,xi,yi,zi):
 for i in range(-1*hei,hei+1):
  if i != 0:
   pm.polyCube(w=0.9,h=0.9,d=0.9)
   pm.move(xi*i,yi*i,zi*i)

heiの引数を受け取って、Cubeを複数作って、,xi,yi,ziの引数でmoveで移動させる仕組みです。
さらに0の場合ダブって作るバグを取るため、if i != 0:で回避しています。
i != 0は「ゼロでなければ」という意味で「!」を使うのです。つまりゼロでない時だけCubeを作るのです。

それに併せて関数makeCubeを改造します。

def makeCube():
 hei=pm.intSliderGrp(boxH,q=True,value=True)
 if checkBox1.getValue():
  copyCube(hei,1,0,0)
 if checkBox2.getValue():
  copyCube(hei,0,1,0)
 if checkBox3.getValue():
  copyCube(hei,0,0,1)

無駄に繰り返していた部分をcopyCubeに変更して、スッキリしています。
実行結果は・・・原点が空になるだけで、さっきと同じです。

変化がないなら意味がない!とは思わないでください。プログラムは動くことが基本ですが、その後のメンテナンスや改造がしやすいことが大切です。
プロの人でも何日か経ったプログラムを見ると、何をやっていたか解らなくなることもあるのです。
初心者の多くが頑張って長いプログラムを書いてしまい、
 1)後で直すことができない
 2)どうやって動いているか解らない
 3)バグが見つからない
ことから挫折するのです。なるべく関数で処理を分解して、小さい単位で作成することを強くお勧めします。
階段を上がるのは小さな段差なら楽ですよね。

では、もうちょっと改造してみます。
長くなった・・・ようですが、追加したのは13行と29、32行のたった3行です。

実行すると、文字を入れる個所ができて、その通りにオブジェクト名を自動で設定するテキストフィールドという機能です。
13行の
boxname=pm.textFieldGrp(l=”CubeName”,editable=True)
textFieldGrpが文字を入れる機能で、変数boxnameに代入します。

29行でそれを受け取り、変数cnに入れます。
cn=pm.textFieldGrp(boxname,q=True,text=True)
32行でpm.polyCube(w=0.9,h=0.9,d=0.9,n=”myBox”+”_”+cn+str(xi*i)+str(yi*i)+str(zi*i))
というようにCubeを作るときにn=”???”と書くとオブジェクト名になるのです。
“myBox”+”_”+cnで文字を足し算します。文字の足し算は意味不明かもしれませんが、文字が連結すると考えればOKです。
xi,yi,ziは引数のmoveの移動量ですね。これは数値なので文字の足し算(連結)できません。そこでstrという関数に入れると、数値を文字に変更してくれるのです。
でもstrって関数は作ってませんね?これはPythonに初めから入っている関数なのです。
これを「Python標準ライブラリ」といって非常に便利な道具がそろっています。

なので、fukanoとテキストフィールドで入力して、xi*i,yi*i,zi*i=0,-1,0だと
オブジェクト名は「myBox_Fukano0_10」になります。
「-」はMayaでは使えないので自動で「_」に変更されてしまいました。このようにPythonとしては処理できてもMayaが受け付けないこともあるので注意です。

今回はここまでです。