Quantcast
Channel: DF TALK
Viewing all 131 articles
Browse latest View live

ハロウィンとセミナーのお話

$
0
0

日頃からDF TALKをご愛読頂いてる皆様、こんにちは。DF野澤(@lphing)です。
早いものでもう11月ですね。2012年も残す所あと2ヶ月ですね。
今年を悔いのない一年で締めくくれるようにラストスパートしていきましょう。
ところで、昨日はノー残業デイの水曜日だったので、有志の人が集まって大々的にハロウィンパーティを開催しました。
会社からは宅配ピザの差し入れもしてもらえてみんな大喜び
アメリカ育ちの実行委員長とその仲間達のおかげで大盛り上がりのパーティとなりました。
簡単にですがレポートさせて頂きます。

社内ページに謎の招待状が…













entrance
エントランスには不吉な絵が掲げられています。















スクリームなアレと正体不明の軍人さん















ティムバートン的な人も・・・。恐いですね。















不敵な笑みを浮かべる女















顔が近い















ハロウィン版、箱の中身はなんでしょなをやる二人。










前川ディレクターもフェイスペインティングに夢中















テロ?















たこ?















ちょっぱー?















仲睦まじい軍人さんたち













つかもうぜ!何ボール?














Ustreamで生中継したりめちゃくちゃ楽しいイベントでした。
是非来年はもっと盛大なハロウィンにしたいと思います。

ところで、全然話は変わりますが、11/26(月)にアキバホールで開催されるセミナーもご紹介したいと思います。

img

事の発端は、今年のSIGGRAPHにて今回の登壇者でいらっしゃる吉田さんにお会いした事でした。
吉田さんは、それはそれはものすごい経歴をお持ちなのですが、海外のVFX事情に対してど素人の
我々の質問に対してとても気さくに答えてくれました。

吉田さんがおっしゃっていた海外のアセットマネジメントやパイプラインのお話はどれも目から鱗でとても貴重なものでした。
吉田さんのこれまでの経験談や知識は私だけでなく、
日本でCG制作をしている方ならどなたでもすごく聞きたいだろうなと強く思いました。

そこで、まず吉田さんにライティングに特化したセミナーの企画を相談させて頂きました。
そしたらなんと三橋さんというこれまた超強力なパートナーまでつけてもらえて、
アーティストとテクニカル両サイドから見たLighting/LookDevelopmentのセミナーを提案して頂けました。

こんなスペシャルな企画が実現したらホントに夢の様だと思いつつセミナーでいつもお世話になっている
ボーンデジタルさんにこの企画を持ち込ませて頂き、そこから何度か相談しあいながら無事ここまでこぎつける事が出来ました。

これはあくまで個人的な意見ですが、海外の作品と日本の作品の差が一番如実に表れているのが
Lighting/LookDevelopmentじゃないかなと思っています。

この機会に技術的に分からない所や海外の独特なパイプラインなどをガッツリ
勉強させてもらって今後の作品作りに役立てたいと思いませんか?

そんなみなさんのご参加を心からお待ちしております。
私もモデレーターとして参加させて頂き、分からない事は
聞くは一時の恥、聞かぬは一生の恥
と思ってガンガン質問させて頂こうと思っています。

セミナーの詳細は以下のサイトでご確認ください。
http://www.borndigital.co.jp/seminar/1180.html

最後までお付き合い頂きありがとうございました。
野澤


ステレオ(3D)酔い止め

$
0
0

ステレオムービーチェック、あなたは酔いませんか!

どうも、前回の記事で下ネタな名前のツールを紹介した後社内の女性陣から嫌な視線を感じたソルです。
10月27日にはバイオハザードのCGムービー第2弾「バイオハザードダムネーション」が公開されました!
本作は3Dステレオムービーでも公開されましたが、もうご覧になりましたでしょうか!

S3D映画を制作する上で最も大切な事は、安全に目に優しい画作りをされているかであり、我々も実際にステレオの環境で品質のチェックをしています。長時間3D眼鏡をかけ何回も繰り返して検査するこの作業は目も痛くなりむかむか胸焼けにもなるなど意外と大変な作業なのです。
「同じファイルをLRのカメラだけ変えてレンダーするだけじゃん。そんなにエラー出るの」と思われる方もいらっしゃるかもしれませんが、レンダーした環境の違いや後からのデータの修正など色々な原因によって、色が若干違ったり形状が若干違ったりするなど様々なエラーが発生するのです。
特に左右が微妙に違うエラーは脳に妙な違和感を感じさせ、見る方が気持ち悪くなりがちなので徹底的にこれを選別しなければいけないのです。
ということで今回の記事はこのステレオ酔いに関する内容を紹介させて頂きたいと思います。

時は約1年半前、私はDFに入社しデザイナーとして「鉄拳 blood vengeance」のコンポジット作業をやらせて頂いていました。
この作品も同じくS3DムービーでLチャンネルのコンポジット後にはRチャンネルムービーの変換作業がありました。私は、所属しているチームのRチャンネルの変換作業を担当することになりました。
ステレオチェックはつらい作業ですし、また残念なことにチェック用のマシン数に限りがあり順番待ちが発生したり、チェックマシンが違うフロアにあったため確認したい時はファイルを送り席を移動しなければいけなかったのです!(実は席の移動が一番大変)(当時DFのオフィスは今のようなワンフロアではなかったのです)
これをチェックマシンではなく自分の席でチェックする方法はないかと考え、色々な方法を試してみて一番簡単に実践できたのはAfterEffectsのブレンドモードの「差」で見る方法でした。


<正常フレーム>


<異常フレーム>

上の二つの写真のようにLRの視差による差以外に不自然な差がある場合はエラーの可能性が高いということでした。
この方法でかなり楽になりましたが色などがわずかに違う場合にはエラーだという確信ができなく結局両方を重ねて交差してみるしかありませんでした。


そして、二番目でやったのが1フレームずつ交互に見る方法です。


この方法を使って再生速度を速くしたり遅くしたりする事で大抵のエラーは選別できました。

どちらもAfterEfectsなどのプログラムでも簡単に実践できかなりフロア移動回数を減らすことができましたが、
エラーを確認する為のプレイヤーがあればもっと楽だろうなと思った怠け者の私は
openCVというライブラリーを使いシンプルなプレイヤーを作ることにしました。(そっちのほうが面倒くさそうだけど)
ただ当時は会社でツールを作った経験もほとんどなくみんなに配布する方法も知らず、結局自分のチームだけが使いました。(ただ、これはこれでまた別の種類の酔いが・・・・)

下は当時のコードの一部です。(交互で再生)

[php num =1]
// Window作成
cvNamedWindow(“ChicaChica”, CV_WINDOW_AUTOSIZE);
// 二つの動画からビデオキャプチャを初期化
CvCapture* cvCaptureL = cvCreateFileCapture(argv[1]);  // argv[1]からLビデオキャプチャ
CvCapture* cvCaptureR = cvCreateFileCapture(argv[2]);  // argv[2]からRビデオキャプチャ
// 画像処理IplImage
IplImage* cvFrameImage;
// 再生速度
int iPlaySpeed = 33;
// 偶数と奇数判断
int i = 0;
// キー入力結果
int iKey;
// Loop
while(1){
// 偶数の場合L動画から、奇数の場合R動画から
if(i % 2 == 0){
//動画を1フレーム進め、現在フレームのイメージをIplImageに格納
cvFrameImage = cvQueryFrame(cvCaptureL);
}
else{
cvFrameImage = cvQueryFrame(cvCaptureR);
}
// 動画が終わると最初のフレームに戻す
if(!cvFrameImage ){
cvSetCaptureProperty(cvCaptureL, CV_CAP_PROP_POS_MSEC, 0);
cvSetCaptureProperty(cvCaptureR, CV_CAP_PROP_POS_MSEC, 0);
i = 0
}
else{
// cvFrameImageイメージをwindowに描画する
cvShowImage(“ChicaChica”, cvFrameImage);
// キー入力待ち。iPlaySpeed(ミリ秒)まで待つ
iKey = cvWaitKey(iPlaySpeed);
// ESCキーが押されたらLoop終了
if(iKey==27) break;
}
i++;
}
// キャプチャを解放
cvReleaseCapture(cvCaptureL);
cvReleaseCapture(cvCaptureR);
// Windowを破棄
cvDestroyWindow(“ChicaChica”);
[/php]

その1年半後、バイオハザードダムネーションではEXR連番対応、Gamma調整機能などなどさらにパワーアップしたステレオチェックプレーヤーを作り配布しましたが、新しく導入されたRenderPackageシステム(レンダーに必要なデータを集めて同じ環境を再現する)の活躍でエラーが激減したため、あまり使われることなく静かに消えていったのでした。これが私のファーストツールのストーリーでした。

では、また。

レンダーパッケージのお話

$
0
0

先月(10/27)にとうとう「バイオハザードダムネーション」が公開になりましたが
みなさんご覧いただけましたでしょうか?
制作中にゾンビになりかけた たつみ(@mtazmi)です。

今回は「レンダーパッケージ」について記事にしたいと思います。

最近開催されているメイキングセミナーやCGWorld11月号(vol.171)の記事などで、
名前だけでも聞いたことがあるかもしれません。

twitterなどでもちらほら反応があったようなので
もしかして需要あるかなと思いましてネタに選んでみました。


 
それではさっそく始めましょう!
 

なぜこのような仕組みが必要なの?

 ・弊社では、立体視の映画をまず左目用のLチャンネルで2D版を作ります
          ↓
 ・2D版がOKになったら今度は右目用のRチャンネルをレンダリングして立体視版にします
          ↓
 ・RのレンダリングはLよりだいぶ後になるので、カットによっては2~3ヶ月後というのもあります
          ↓
 ・その期間にデータが更新されてしまうと、当然LとRで合わなくなってしまいます
 dfTalk_tatsumim_v02_01
 
鉄拳ブラッドベンジェンスでは、こうしたRとLが合わずに結局両方同時にやり直し、
ということが多発してとても大変だったと聞きます
(僕はダムネーションから参加なので直接は知らないのですが、その辺の黒歴史は各所から耳にしていました)

          ↓↓↓

 そこでLをレンダリングする時点でのデータ環境をまるっとタイムカプセルのように
 閉じ込めて残しておき、Rをレンダリングするときに再利用するのがパッケージシステムです!

 
 イメージ図
dfTalk_tatsumim_v02_02
 ・各サーバーはどれも同じ階層構造に統一してあります
 ・そして、パッケージの中身の階層もファイルサーバーとまったく同じ構成になっています
 (小さなサーバー、と言うとイメージしやすいかもしれません)
 
 ・レンダーシーンが参照するリファレンスシーンやテクスチャなどは、
  パッケージのルートフォルダ以下からアクセス出来るように変更します
 ・そのため、パッケージ自体は専用サーバーやローカルPCなど、どこに作ってもかまいません
 
 ・海外のレンダーファームを使う場合は、パッケージのルートフォルダから圧縮すれば1ファイル送るだけで済みます
 
ではお次は、パッケージ処理の大まかな流れについて解説します
 


 

パッケージ処理の大まかな流れ

※解説中のサンプルコードはpymelありきとなっております(maya2011以前のバージョンをお使いの方すいません)
 また、ファイルパスの階層は、事実を元にしたフィクションみたいな感じになっています

 

maya内の処理

1、レンダーシーンを開き、ロードされているプラグインを調べて回収

 以下のようにロードされているプラグインを取得してコピーしてきます
 
 取得の仕方はこんな感じです[python]
import pymel.core as pm
pluginList = []
for plugin in pm.pluginInfo(query=True, listPlugins=True):
pluginPath = pm.pluginInfo(plugin, query=True, path=True)
pluginList.append(pluginPath)
print pluginList
[/python]
 
 メンタルレイはこちら[python]
import pymel.core as pm
mrPluginList = []
for plugin in pm.mrFactory(query=True, allLoaded=True):
mrPluginList.append(plugin)
print mrPluginList
[/python]
 

2、レンダー設定で絶対これに統一、という項目は間違いを防ぐためにも改めて設定しておく

 例えば出力する画像形式をOpenEXRに、フレーム番号は4桁にしておくという場合
 [python]
import pymel.core as pm
DRG = pm.PyNode(‘defaultRenderGlobals’)
# padding >> 4
DRG.extensionPadding.set(4)
# imageFormat >> openExr
DRG.imageFormat.set(51)
DRG.imfPluginKey.set(‘exr’)

MRG = pm.PyNode(‘mentalrayGlobals’)
#openexr compression zip
MRG.imageCompression.set(4)
[/python]
 

3、シーン修正結果をMAで保存し直す

 unknownノードなどゴミ掃除をしてから、次のテキスト処理をかけるためにMA形式で保存します
 


 

maya外のパッケージスクリプトで行うこと

1、プロジェクト用に用意されているスクリプト、プラグインを回収

 固めている場所は決められた場所なので、フォルダごとまるっとパッケージフォルダ内へコピーします
 

2、MAファイルの書き換え

 maya内編3で保存したMAファイルをテキストとして読み込み、
 中の記述からファイルパスと思われる部分をパスの一部を環境変数($DF_RENDER_PACKAGE_PATH)に置き換えて再度保存
 
 基本的にファイルパスならなんでも拾うようにしたおかげで、あとから○○ファイルを追加対応という手間が省けました

 こうすることでパッケージフォルダからレンダリング出来るように準備が出来ます
 [python]
# -*- coding: utf-8 -*-
#===========================================================
# MAファイルを読み込んでいろいろする
#===========================================================

def readMayaFile(mayaFilePath):
f = open(mayaFilePath, ‘r’)
lines = f.readlines()
f.close()

result = [] # 処理結果を入れておくもの
# 文字列からファイルパスっぽい対象を検索し、見つけたら置き換え処理にまわす
for line in lines:
# コメントアウトは無視
if line.startswith(‘//’):
result.append(line)
continue

# ドットを含まなければ拡張子無しとしてスルー
if not ‘.’ in line:
result.append(line)
continue

# ドライブっぽい表記があればファイルパスっぽい気がするー
if ‘:/’ in line or ‘:\\’ in line or ‘//’ in line or ‘\\\\’ in line:
replacedLine = パスの置き換え処理へ(line)
result.append(replacedLine)
ファイルコピー処理(line)

# 特に何も無かった(´・ω・`)
result.append(line)

return result
[/python]
 
  ↑の「パスの置き換え処理へ」と書かれた部分
  正規表現を使って、例えばMAファイル内の記述を、
   setAttr “.ftn” -type “string” “Z:/DA/asset/chara/LEON/sourceimages/LEON_color01.tex”;
          ↓
   setAttr “.ftn” -type “string” “$DF_RENDER_PACKAGE_PATH/asset/chara/LEON/sourceimages/LEON_color01.tex”;
   というように書き換えを行います(DAはダムネーションの頭文字です)
 [python]
# -*- coding: utf-8 -*-
#===========================================================
# 渡された文字列からパス書き換え対象部分を処理して返す
#===========================================================

import re

def replacePath(getLine):
env = ‘$DF_RENDER_PACKAGE_PATH’

# 置き換え用正規表現キーワード
regex = re.compile(‘(?P

.*”).*[\\\\/][dD][aA](?P[\\\\/].*)’)
result = None
m = regex.match(getLine)

# 正規表現が正しく取れない場合スキップ
if not m:
print None
return getLine

# 正規表現が成立したら置き換え文字列を作って返す
result = m.group(‘head’) + env + m.group(‘tail’) + ‘\n’
return result
[/python]
 
mayaではファイルパスが /区切りの場合と、\区切りの場合があるので苦労しました。。
 

4、置き換え処理をしたファイルもパッケージ階層に回収する

 3の置き換えと同じような感じでファイルパスを抜き出してきてファイルをコピーしてきます
 

5、パッケージ内からレンダリングジョブを送るためのbatを作る

 レンダリング管理ソフトによって違うと思いますが、
 どのソフトでもレンダリングするカメラを何にするかフラグがありますので、
 カメラは変数として出しておけば簡単にLのbatがRをレンダリングするbatに切り替えられます

[code]
SET CAMERA=L
    ↓
SET CAMERA=R
[/code]
 

6、環境変数をセットしてレンダリング

 パッケージ内でレンダリングするための必要な環境変数は、
 レンダリング管理ソフトでレンダリングが始まる前に動くbatで設定されます
 
 パッケージルートは必ずレンダーシーンの4つ上の階層ということを利用し、
 そこからさかのぼって行った先のディレクトリを取得して設定しています[vb]
cd “レンダーシーンがあるフォルダ”
cd..
cd..
cd..
cd..
SET DF_RENDER_PACKAGE_PATH=%cd%
[/vb]
 
  その他、スクリプトやプラグイン、シェーダなどのパスも設定します[vb]
SET MAYA_PLUG_IN_PATH=%DF_RENDER_PACKAGE_PATH%\tool\plug-ins;%MAYA_PLUG_IN_PATH%;
SET MAYA_SCRIPT_PATH=%DF_RENDER_PACKAGE_PATH%\tool\scripts;%MAYA_SCRIPT_PATH%;
SET PYTHONPATH=%DF_RENDER_PACKAGE_PATH%\Assets\tool\python;%PYTHONPATH%;
SET MI_LIBRARY_PATH=%DF_RENDER_PACKAGE_PATH%Assets\tool\mentalRay\lib;%MI_LIBRARY_PATH%;
SET MI_CUSTOM_SHADER_PATH=%DF_RENDER_PACKAGE_PATH%\tool\mentalRay\include;%MI_CUSTOM_SHADER_PATH%;
[/vb]
という感じです。
 


 

~実際に起きたトラブルと対処法~

その1!

 書き換え処理をしたMAファイルをテキストエディタで開いて検索しても全て置き換わっているのに
 回収されていないテクスチャがあるし、実際シーンを開いてみたら置き換え処理されていないファイルノードが…なぜ(´・ω・`)
    ↓
 どうやらレンダーシーンでリファレンスしてるデータに特に何も変更が無い場合、
 maファイルに保存されない場合があるようなのです!

 というわけで、同じ値をセットし直して、変更したという状況を作りました
 こんな感じで[python]
import pymel.core as pm
for fileNode in pm.ls(type=’file’):
filePath = fileNode.fileTextureName.get()
if filePath:
fileNode.fileTextureName.set(filePath, type=’string’)

for fileNode in pm.ls(type=’mentalrayTexture’):
filePath = file.fileTextureName.get()
if filePath:
fileNode.fileTextureName.set(filePath, type=’string’)
[/python]
 
 はい解決
 

その2!

 わぁ、ログが真っ赤だぁ!(某目薬のCMのように)

 メンタルレイは環境変数を含むパスだとエラーになってしまう!
    ↓
 これについてはシーンを開いたときに実行されるイベント処理で、
 環境変数を実際のパスに書き戻す処理を追加しました

 これはプラグイン実装でしたが、PreRenderMELに仕込んでもいいです

 パッケージ化中に以下のコマンドでPreRenderMELを仕込んでおく[python]
import pymel.core as pm
DRG = pm.PyNode(‘defaultRenderGlobals’)
DRG.preMel.set(‘DA_preRender();’)
[/python]
 
 実行するPreRenderMEL
 preRender.mel[c]
global proc DA_preRender(){
python(“import forcePackagePath”)
python(“forcePackagePath.setMrTexPath()”)
}
[/c]
 
 PreRenderMELが呼ぶ処理
 forcePackagePath.py[python]
# -*- coding: utf-8 -*-
import pymel.core as pm
def setMrTexPath():
packagePath = os.environ['DF_RENDER_PACKAGE_PATH']
for tex in pm.ls(typ=’mentalrayTexture’):
# ファイルパスが空っぽならスキップ
getPath = tex.fileTextureName.get()
if not getPath:
continue

# 環境変数始まりなら置き換え処理
if getPath.startswith(‘$’):
newPath = getPath.replace(‘$DF_RENDER_PACKAGE_PATH’, packagePath)
tex.fileTextureName.set(newPath, typ=’string’)
[/python]

 いっちょあがりっ!
 
 

そのた

 ・初めの頃に正規表現にパスの区切り文字(/, \\)を入れ忘れていたせいで、
  エイダ・ウォン(ADA)、携帯端末(PDA)といったIDに、プロジェクト名のDAが引っかかり軽い惨事になってしまった
 ・スペースが入ったフォルダ名で回収漏れ
 ・土日分レンダリングする用に金曜日にせっせとパッケージを作って帰ったら、
  ツールバグのせいで数百ジョブがレンダリング出来ない悲惨な状況に。。
 ・海外のレンダーファームが謎の不調に
 ・パッケージデータが大量になりサーバーを圧迫

 ・休日かかってくる電話に恐怖
 ・初めて話をする人がツールバグの謝罪
 ・2kg痩せた
 


 
 いかがだったでしょうか?
 かなり規模が大きいツールなので全部紹介しきれていませんが、何かのヒントになれば幸いです。
 
 パッケージツールはレンダリングと並行してツールを作っていたため、
 いろんなトラブルに見舞われましたが、こうして公開にこぎつけることが出来て本当によかったです。
 エンドクレジットに載った名前を見たときは感動でした。
 

プローシージャルアニメーションで簡単カット作成

$
0
0

[ごあいさつ]

はじめまして。アシスタントTDの 護守(ごのかみ) です。
「ごのかみ」って書きにくいので「ごの」とか略してもらってもいいですよ。
DFにご厄介になってまだ半年ほどですが、MassiveとTDワークを担当しております。
周りの皆さんが非常にできる方ばかりな上、勉強することが多く四苦八苦している現在です。
他のスタッフの方々のように有益な情報をご紹介できるかどうかわかりませんが、
お時間ある方はお付き合いください。

最近はスクウェア・エニックス様(以下スクエニ様)のオープンカンファレンスが楽しかったですね。
刺激を受けて創作意欲がわいてきました。
プリレンとリアルタイムの垣根が薄くなってきた昨今を鑑みると、
こちらの業界でもスクエニ様のような技術というのは必要になってきますからね。

さてさて話は全然変わりますが、僕は3DCGの中でもアニメーションの分野が一番好きなんですね。
しかし、作業していると機械的にやってほしいとことかが出てくるんですよね。
そこに時間割かれると、アニメーションのクオリティアップの時間が削られてしまうので、
そういったところを手でやるというのがあまり好きではないんですよ。
そこで、そのめんどくさいことを省きつつアニメーションを作れるということで、
プロシージャルアニメーションに注目しております。

というわけで、今回のテーマは

「プロシージャルアニメーションを使ってそれっぽいカットを簡単に作る」

です。

今回お話するプロシージャルアニメーションとは、人型キャラに適用できるものではなく、
オブジェクト自体のアニメーションに関わるシンプルなものなのであしからずです。
それからオペレーションにはmayaを使っております。

※注意※ 本記事内でダウンロード可能なツール、コードを使用したことによって
引き起こるいかなる損害も当方は一切責任を負いかねます。
自己責任でご使用ください。

 
 
 

[ぷろしーじゃるあにめの基礎の基礎]

プロシージャルアニメーションって書くと、なんだかすごい複雑なこと
やっているんだろうなぁとか思われるかもしれませんが、実はそんなことありません。

[python]y = sin x[/python]


これは中学校でも習った、sin関数ですね。
はい。これでプロシージャルアニメーションです。

…( ゚Д゚)
…(゚Д゚)

唐突過ぎますね。もうちょいわかりやすく説明します。

てけとうにcubeを作ってexpressionにこの数式を適用してみます。
[python]
pCube1.tx = frame;
pCube1.ty = sin(frame);
[/python]
これで再生すると先ほどのグラフのように動きます。
(クリックで再生)

オブジェクトに数式を与えることで、自動でアニメーションをつけてくれます。
これがプロシージャルアニメーションなわけですね。

さて、これをちょっと応用した数式に変えて、見栄えをよくしてみましょう。
どうせやるなら楽しくです。
ちなみに、ここからはスクリプトエディタ(python)で実行します。

[python]
# -*- coding: utf-8 -*-
import pymel.core as pm
import random

def spiralUpper(numCubes):
yspeed = 0.2 # y方向の速さ
interval = 0.5 # オブジェクト同士のインターバル

startFrame = 0
for i in range(0, numCubes):
obj = pm.polyCube()

a = random.uniform(6.0, 14.0) # 軸からの距離
b = random.uniform(11.5, 12.5) # 回転する速さ
c = random.uniform(-0.1, .1) # 軸のオフセット

expstr = “”
expstr += “$t=frame+” + str(startFrame) + “;\n”
expstr += “tx=” + str(a) + “*sin($t/” + str(b) + “)+” + str(c) + “;\n”
expstr += “ty=$t*” + str(yspeed) + “;\n”
expstr += “tz=” + str(a) + “*cos($t/” + str(b) + “)+” + str(c) + “;\n”

pm.expression(object=obj[0], string=expstr, n=”sincos_exp1″)
startFrame += interval

spiralUpper(400)
[/python]
スクリプトエディタでこれを実行します。
で、後は再生するだけです。

(クリックで再生)

数を増やしただけでも、さっきよりは見ごたえのあるものになりましたね。
このスクリプトでは、選択したオブジェクトにsin関数とcos関数のexpressionを
自動で書き込んでいます。なので、エクスプレッションエディタで確認してもらうと
何が書いてあるのかわかるはずです。

ちなみにオブジェクトが整然としないように、ここではあえてランダム値を入れてます。
spiralUpper(400)←この数字はcubeの数です。暇があったらここの数字部分も変えてみてください。

ポイントその壱: 単体のアニメーションは微妙でも物量出せばそれなりに見れる
 
 
 

[数式作るのめんどい…]

というわけで、数学関数さえ当てはめてあげれば、プローシージャルアニメーションが
できるというのがわかったと思います。
でも、ここで問題が。
sin関数やcos関数などの比較的動きが予測できる関数は制御しやすいんですが、
それ以外の複雑な関数って作ってみないと動きがわからないですよね。
それに加え、基本的に数値での調整が主になるので扱いにくいんです。

というわけで、手でアニメーションをつけちゃいましょう

支離滅裂だと思われるかもしれませんが、怒らずにお付き合いください。
アニメーションというのはやはり手でつけるのにはかないません。
自分の思い通りのアニメーションを思うとおりに作れるわけですから。
今回ご紹介しているプロシージャルというのは
冒頭でも述べたように、「機械的にめんどくさいところを短縮する」というのが目的です。
手でアニメーションをつけるための補助的な手段でしかないのです。
ですから、手でつけた方が結果的に早くなるならそうするに越したことはないわけです。

では、この節では何をご紹介するのかと言うと、
ひとつのオブジェクトにアニメーションをつけるだけで見栄えを良くする方法 です。

ここでポイントその壱を思い出してください。
物量あれば、それなりに見栄えよく見えるんです。
一個にアニメーションをつけて、それに他のオブジェクトを追従させるだけでも
それっぽいものになるんですよ。
 
 

やり方をひとつひとつ書いていくと記事が長くなりそうなので、ツールをつくりました。
delayLocus.py
※備考※ 使用方法はファイル内にも記述してあります。
0フレームで位置がリセットされます。

このツールでやっていることは簡単です。
アニメーションがついているオブジェクト(以下、オリジナルオブジェクト)の
前のフレームの位置を記憶しておいて、現在のフレームとの差異分だけ
ツールが適用されたオブジェクトを動かしてます。
フレーム単位で記憶しているので、毎フレーム再生にしないとうまく動かないです。
あとexpressionで強引にやってるので数が増え過ぎると重くなるので注意です。

[使用方法]
    1. C:\Users\ユーザー名\Documents\maya\mayaバージョン\scripts にこのpythonを置く
    2. maya上でpythonコマンド import delayLocus を実行(2回目以降は reload(delayLocus) )
    3. 縦横の数を指定して、サンプルオブジェクトを作成
    
    4. ひとつのオブジェクトにアニメーションをつける
    
    5. 追従させたいオブジェクトを全て選択して、アニメーションさせたオブジェクトを最後に追加選択
     ※全選択して、オリジナルオブジェクトを選択解除→選択とすると楽
    
    6. AddAttrを実行(offsetアトリビュートが追加される)
    
    7. 先程のを選択したままで、delay Locusを実行
    
    8. 再生する

[備考]
    ・オリジナルオブジェクトのオフセット値を変えて再生することで、
     追従するオブジェクトの遅れてくる度合いが一括調節できます。
    
 

で、こちらを使ったのがこのサンプルです。

けっこう楽しくなりましたね(=゚ω゚)

自画自賛みたいであれですが、使ってて楽しいですね、これ。
暇があったらもう少し遊んでみたいです。
 
 
 

[カット作成]

さてアニメーションもできたのでサクッとレンダリングしてみましょう。
ここで用意するものはHDRIのみです。
ネットに落ちてるので適当に探してみましょう。(擬似HDRIもあるので注意)
自分で作成するのも意外と簡単にできたりするのでオススメです。

ポイントその弐: Imaged Based Lighting(IBL) を使えば簡単にライティングできる

IBLってなんぞやという人に軽く説明しておきます。
IBLとは画像を光源とみなしてライティングするものです。
フォトリアリスティックなライティングを簡単にできるのが特徴です。
そこでライティングに使うため、広い輝度情報を持つHDRIが必要なわけです。

レンダラーをメンタルレイに変えてIBLを作ります。

そこに先程のHDRIを貼り付けます。では、レンダリングして確認してみます…

おっとその前に、 Enable Default Light を切って、
Final Gathering を有効にしてください。
じゃないと IBL の効果が出ないので注意です。

いいライト具合になるように Color Gain や Color Offset で調整します。
このとき背景が変な感じになっても気にせず、
オブジェクトのライティングのみに着目してください。
これはあくまでライティング用に使うだけなので後で背景はオフにします。
ちなみに、IBLの Primary Visibility をオフにすると背景が消えるので見やすくなりますよ。

ライティングが終わったら背景用の球を用意します。
IBLと同じ大きさの球を用意してそこに同じHDRIを貼り付けます。
後はカメラを決めてから、レンダーレイヤーなんかを使って
オブジェクトだけ、背景だけをレンダリングします。

最後に合成すればこんな感じになります。


 
 
 

[後記]

物量出すならパーティクルでやればいいじゃん
という至極ごもっともなご意見があるかと思いますが、
こうやってオブジェクト自体をいじるのも楽しいですよってことも言いたかったのです。
実際の使い道はあまりないかもしれません。
しかし、割と簡単に作れることがわかったと思いますので、お時間ある方は遊んでみてください。

ちなみに、このムービーで使っているオリジナルオブジェクトのアニメーションは
重力とバウンドの数式を使って作っております。こんなこともできますのでご参考までに。

しょうもないツールですが、これを使って作品など自由に作ってもらってかまいません。
作品を発表する場合はDFか僕のクレジット入れてくれたり、報告してくれたりすると
嬉しいなぁとか何とか思ったり。

それでは今回はこのへんで_(:зゝ∠)_

MotionBuilderでツールをより使ってもらうために

$
0
0

はじめまして、アシスタントTDの森本です。

6年ほどアニメーションデザイナーとして作業しつつ、
たまにちょっと役立つスクリプトを書いてましたが、
今回TDチームが発足するのに合わせてアニメーションTDに専念することになりました。
TDとしてはまだまだ知識、経験至らない部分が多々ありますが
元アニメーションデザイナーとしての経験を生かして
デザイナー視点から扱いやすいスクリプトでサポートしていければと思っています。

さて、今回のテーマですが「MotionBuilderでよりツールを使ってもらうために」です。
弊社ではアニメーション作業のメインツールとしてMotionBuilderを使用していますが、
MotionBuilderにはMAYAのScriptEditorのように履歴が残ったりする機能はありません。

そのためにちょっとしたことをスクリプトで実行したくても
履歴のコピペが出来ずにPythonでコードを書かないといけないため
普段からスクリプトに慣れていない人もいます。

そこでTD側でスクリプトをMotionBuilderのメニューに自動登録する仕組みを作っていて
新しいスクリプト追加や旧スクリプトのバージョンアップ等を
デザイナーが意識しなくてもメニューが更新されるようにしています。
よくある仕組みとは思いますが今回はそちらの紹介をしようと思います。

なお、これ以降でてくるスクリプトに関しては
MotionBuilder2013SP1にて動作を確認しています。

まずベースになっているスクリプトが
MotionBuilderのデフォルトのサンプルスクリプトにある
FBMenu.pyになります。
こちらを実行すると下記図のようにメニューに項目が追加されます。

ただし、メニューの内容がすべてFBMenu.py内に記述されてしまっているため、
同じ方式にするとメニューを追加するたびにPyファイルを配って更新してもらう必要があります。
これだとさすがにTD、デザイナー共に面倒です。
スタートアップスクリプトフォルダの設定をサーバーのフォルダで共通にすれば
同じスクリプトを参照できますが個人単位でスタートアップの設定ができなくなります。

そこでメニューの追加する設定に関しては外部に設定ファイルとして保存して
その外部ファイルをTDチーム側で調整することでスクリプト登録を変更しています。

実際単純化したもので説明しこうと思います。

まずは外部設定テキストを準備します。
test.txt
中身については
F:\Hello.py
登録したいスクリプトファイルのアドレス(複数の場合は行を変えて)
が書かれたテキストです。

例としてあげているHello.pyですが
[python]
# *- coding: utf-8 -*-
from pyfbsdk import *
FBMessageBox(“スクリプト実行テスト”,”Hello!”,”閉じる”)
[/python]
MotionBuilder上で簡単なメッセージボックスがでるスクリプトです。

上記ファイルを適当な場所(例ではFドライブ直下)に配置した状態で
メニュー追加スクリプトの簡単なコードを以下に記します。

[python]
# *- coding: utf-8 -*-

from pyfbsdk import *
import os

# メニューを選んだときにスクリプトを実行
def eventMenu(control, event):
ScriptFile=ScriptDic[event.Name]
FBApplication().ExecuteScript(ScriptFile)

# 外部設定テキストからスクリプトをメニューに追加
# 追加時に設定内容を辞書に追加
def MenuAdd(pRootMenu,pFullSetTxt,pScDic):

# 設定ファイルの読み込み
f=open(pFullSetTxt)
oSettingTxt = f.read()
f.close()
lSettingList = oSettingTxt.split(“\n”)

# メニュー登録
insideMenu=FBGenericMenu()
i=0
for FullPyFile in lSettingList:
i+=1
FileName=os.path.basename(FullPyFile)
insideMenu.InsertLast(FileName,i)
pScDic[FileName]=FullPyFile
insideMenu.OnMenuActivate.Add(eventMenu)

# 親メニュー登録
pMenuName=os.path.basename(pFullSetTxt).replace(“.txt”,”")
pRootMenu.InsertLast(pMenuName,100,insideMenu)

# 外部設定テキストの場所
PyListTxt=r”F:\MBPyTest\test.txt”

# ルートメニューの設定
menuMgr = FBMenuManager()
RootItem = menuMgr.InsertAfter(None, “PythonTools”,”AnimTools”)
RootMenu = menuMgr.GetMenu(“AnimTools”)

# メニュー選択時に使用するスクリプトの場所を設定した辞書作成
ScriptDic={}
MenuAdd(RootMenu,PyListTxt,ScriptDic)

[/python]
スクリプト上の36行目でテキストファイルの場所を指定します。

以上のスクリプトをMotionBuilder上で実行すると
メニューにAnimToolsが追加されてさらにtestのメニュー項目内に
設定テキストファイル内のスクリプトファイルが登録されています。
登録されたスクリプトのメニュを選択するとスクリプトが実行されます。

以上がベースのスクリプトになりますが
実際に使用しているスクリプトはサーバー上に設定ファイルを用意してメニューを作っているため
メニュースクリプトをMotionBuilderのスタートアップスクリプトに登録した人は
TD側で登録したスクリプトはどの人でも自動的にMotionBuilderを起動するとメニューに登録されます。
また、カテゴリ分け、個人登録機能の追加などの調整が入っています。

しかし、登録の仕組み自体はベースのスクリプトとほぼ変わりがありません。

この仕組みにより個人でスクリプトの設定をしていたときと違って
スクリプトの更新、追加の手間が省けるためスクリプト関連のエラーを減らすことができます。
(バグがある古いスクリプトを使っていた等)

ただし、問題点として選択時にそのまま実行されるため
説明を入れる隙間がなくスクリプトの使い方がわからない点があります。
例)
 ・キャラを選択して実行
 ・シーンデータがあるルールに合わせた仕様になってないと動かない

UI付のスクリプトに関してはUI上で説明がありますが、
選択後即実行されるスクリプトに関しては説明を入れる余地がないため、
それぞれのスクリプトで間違った使い方の場合はエラーウィンドウで説明するなどの処理を入れておくことが必要です。

また、よりカスタマイズして使っていきたい人向けに
下記図のようなシェルフスクリプトも作って配布しています。
(下図のようにアイコン画像も追加できますがアイコンのセンスのなさはご勘弁を)

以上です。
簡単なスクリプトの紹介にしかなっていませんが
比較的にMotionBuilderのスクリプト自体情報が少ないので
何かの参考になれば幸いです。

では、また。

Nukeのターミナルモードを使ってみよう

$
0
0

はじめまして、開発室の山口です。
DFにはデザイナーとして入社し、4ヶ月ほど前に開発室へ異動しました。

デザイナーのころにNukeを触っていたのと、最近DFで導入したのをきっかけに
現在はNukeの開発を担当しています。

今回はNukeのターミナルモードを使用した簡易ツールを紹介したいと思います。

ターミナルモードとは?

ターミナルモードとは、GUIを立ち上げず、pythonコマンドを駆使してnukeを動かすモードの事です。
このターミナルモードを使う事で、GUIを立ち上げずにNukeファイルを作成したり編集したりすることが出来ます。

簡単に操作してみましょう。コマンドプロンプトを立ち上げ下記のコマンドを入力します。

[code]"C:\Program Files\Nuke7.0v1\Nuke7.0.exe" -t[/code]

※Nuke.exeファイルのパスはPCの環境に合わせて書き変えてください。

コマンドプロンプト上ではこんな感じです。

これでNukeをUI無しで立ち上げた状態になり、Pythonで操作できるようになりました。
ためしにReadノードとWriteノードを作成し、保存してみます。

下記のコマンドをコマンドプロンプトに一行ずつ実行してください。
Nukeファイルは自分の好きなところに保存してください。

[python]
nuke.createNode(‘Read’)
nuke.createNode(‘Write’)
nuke.scriptSave(‘D:/render.nk’)
[/python]

ちなみにコマンドプロンプトで全て実行すると、こんな感じになります。

確認のため保存されたNukeファイルを開いてみてください。
下図のようにReadノードとWriteノードが作成されれば成功です。

このようにターミナルモードを使用すると,Pythonを使ってUIを立ち上げずにNukeファイルを構築することができます。

ターミナルモードを使って画像変換

ここまでで、ターミナルモードがどんなものか大体理解できたかと思います。

そこで今回はこのターミナルモードを使用し、画像ファイルをOpenExrファイルの圧縮形式Zip scanline 1
変換するツールを紹介したいと思います。

●なぜこのようなツールが必要か

NukeでOpenExrファイルを使う際にはZip scanline 1の圧縮形式が相性がよく
他のものと比べてもプレビュースピードが速いのですが、レンダラーによってはZip scanline 1
出力できないものがあります。

例えばMayaのmentalrayでもZipは選択できますが、この圧縮形式はZip scanlines 16という形式で
Zip scanline 1ではありません。ですのでプレビュースピードを早くするためには、変換してあげる必要があります。

ちなみに現在弊社ではレンダリングにVrayを使用しているのですが、Vrayではscanline 1
scanlines 16の両方が選べるので、変換の必要はありません。

●ではさっそくツールを作ってみましょう

今回紹介する方法は、ターミナルモードでPythonコマンドを入力するものではなく、外部のPythonファイルで
あらかじめコマンドを作成したものを読み込み使用する方法をとります。

1.適当な場所に変換用のPythonファイルを作成します。

まず適当な場所にPythonファイルを作成します。

D:\exr2zipScan1.py

Pythonファイルの中に以下を記述して下さい。

[python]
# -*- coding: utf-8 -*-

import os
import sys
import nuke

# フォルダのパスを取得
dirPath = sys.argv[1]

# フォルダからReadノードを作成
nuke.tcl(‘drop’, dirPath)

# 作成されたReadノードを取得
readNode = nuke.selectedNode()

# Readノードが作成されていれば次に進む
if readNode > 0:

# 作成されたReadノードからスタートフレームとラストフレームを取得
firstFrame = readNode['first'].value()
lastFrame = readNode['last'].value()

# 作成されたReadノードからファイルパスを取得し,書き出し用のファイルパスを作成
readFilePath = readNode['file'].value()
folderName = readFilePath.rsplit(‘/’,1)[0] + ‘_scan1′
saveName = readFilePath.rsplit(‘/’,1)[1].rsplit(‘.’,1)[0] + ‘.exr’

# フォルダを保存するためのフォルダの作成。すでにあれば作成しない
if not os.path.exists(folderName):
os.mkdir(folderName)

# Writeノードを作成し、書き出し用のファイルパスを入力
writeNode = nuke.createNode(‘Write’)
writeNode['file'].setValue(folderName + ‘/’ + saveName)

# ファイルタイプをexr、圧縮タイプをZip scanline 1 へ変換
writeNode['file_type'].setValue(‘exr’)
writeNode['compression'].setValue(‘Zip (1 scanline)’)

# Writeノードをレンダリング
nuke.execute(writeNode, firstFrame, lastFrame)
[/python]
    

2.Pythonファイルを実行するためのバッチファイルを作成します

ツールっぽくするためにPythonファイルと同階層にバッチファイルを作成します。

D:\exr2zipScan1.bat

バッチファイルの中身はこんな感じです

[code]"C:\Program Files\Nuke7.0v1\Nuke7.0.exe" -t "D:\exr2zipScan1.py" %1[/code]
 
これで変換したい連番が入ったフォルダをドラッグ&ドロップすることでツールが起動し
exrのZip scanline 1へ変換されるようになります。

ためしに連番の入ったフォルダをバッチファイルにドラッグしてみてください。

どうでしょうか、下図のようにtest_scan1ディレクトリが作られ
画像ファイルが無事変換できていれば完成です。

次に中で何が行われているのか説明します。


  

バッチファイルの解説

  
まずは、バッチファイルから説明します。

[code]"C:\Program Files\Nuke7.0v1\Nuke7.0.exe" -t "D:\exr2zipScan1.py" %1[/code]

1.EXEファイルを指定します

“C:\Program Files\Nuke7.0v1\Nuke7.0.exe” -t

上記で説明したように、Nukeをターミナルモードで立ち上げるためのコマンドです。

2.Pythonファイルを指定します

D:\exr2zipScan1.py

-t フラグの後ろにPythonファイルのパスを記述することで、Nukeをターミナルモードで立ち上げた後に
Pythonファイルが実行されます。

※下記のように記述すると相対パスで記述できます。バッチファイルと同階層にある場合に使用してください。

%~dp0exr2zipScan1.py

[例]
[code]"C:\Program Files\Nuke7.0v1\Nuke7.0.exe" -t "%~dp0exr2zipScan1.py" %1[/code]

3.ドラッグファイルのパスをPythonファイルに受け渡す

%1

Pythonファイルの次に%1を記述する事で、バッチファイルにドラッグ&ドラッグしたフォルダの
パスをPythonファイルに受け渡すことが出来ます。他にも渡したい情報があればスペースを入れて追加します。

Pythonファイルの解説

  

1.最初にモジュールをインポートします

[python]
# -*- coding: utf-8 -*-

import os
import sys
import nuke

[/python]

2.バッチファイルから情報を受け取ります

バッチファイルからドラッグ&ドロップされたフォルダのパスを受け取ります。
ここで気をつけなければいけないのが変数の”0番目”にはPythonファイル自身のパスが
入っていることです。したがって素材フォルダのパスは”1番目”に受け渡されます。

[python]
dirPath = sys.argv[1]
[/python]

sys.argv[0] ← pythonファイルのパスが入っています
sys.argv[1] ← 素材フォルダのパスが入っています

これでdirPathの中にフォルダのパスが受け渡されました。

3.フォルダパスからReadノードを作成

フォルダのパスからReadノードを作成します。

[python]
nuke.tcl(‘drop’, dirPath)
[/python]

※このコマンドはフォルダをNuke内にドラッグしたのと同じ操作になります。
フォルダの中に複数のシーケンスが入っている場合はReadノードが複数できてしまうので
注意してください。

4.選択されているReadノードを変数に代入、無事取得できれば次へ

ノードを作成すると、作成後に自動的に選択されるので、この特性を利用して作成したReadノードを取得します。
またif文を使用し選択されたReadノードが選択されている場合にのみツールが走るようにします。

[python]
readNode = nuke.selectedNode()

if readNode > 0:
[/python]

5.作成されたReadノードからスタートフレームとラストフレームを取得

“3″の操作でReadノードを作成すると、スタートフレーム、ラストフレームに連番から取得されたフレームレンジが
設定されるので、これを利用してレンダリングのフレームを取得します。

[python]
firstFrame = readNode['first'].value()
lastFrame = readNode['last'].value()
[/python]

6.Readノードのファイルパスから書き出しようのファイルパスを作成し、フォルダを作成します

現在Readノードには、ドラッグしたフォルダに入っていた連番のパスが入力されているので
ここから、レンダリングするためのフォルダパスと、連番の名前を作成します。

[python]
readFilePath = readNode['file'].value()
folderName = readFilePath.rsplit(‘/’,1)[0] + ‘_scan1′
saveName = readFilePath.rsplit(‘/’,1)[1].rsplit(‘.’,1)[0] + ‘.exr’
[/python]

例)上の変数にはこんな感じで代入されています。
readFilePath → D:/test/test.%04d.tif
folderName → D:/test_scan1
saveName → test.%04d.exr

Nukeで連番を書き出す際にはフォルダが無いとエラーになってしまうので出力先のフォルダを作成します。
ただし、すでにフォルダがあるとエラーになってしまうので、念のためif文を使用して、重複を避けます。

[python]
if not os.path.exists(folderName):
os.mkdir(folderName)
[/python]

こんな感じでレンダリングのフォルダが作成されます。

7.Writeノードを作成し、書き出し用のファイルパスを入力

この時点ではReadノードが選択された状態ですので、Writeノードを作成すると
自動的にReadノードとコネクトされます。つづけてWriteノードへ出力パスを入力します。

[python]
writeNode = nuke.createNode(‘Write’)
writeNode['file'].setValue(folderName + ‘/’ + saveName)
[/python]

8.Writeノードのファイル形式をexr、圧縮形式をZip scanline 1 へ設定

[python]
writeNode['file_type'].setValue(‘exr’)
writeNode['compression'].setValue(‘Zip (1 scanline)’)
[/python]

※実はファイル形式をexrへ設定すると、圧縮形式はデフォルトでZip scanline 1へ設定されるので
二行目は必要ありません。ここでは分かりやすくするために記述しています。

9.Writeノードをレンダリング

作成したWriteノードに”5″の工程で取得したスタートフレームとラストフレームを設定してレンダリングします。

[python]
nuke.execute(writeNode, firstFrame, lastFrame)
[/python]

以上でツールの説明は終わりです。

その他の小ネタ

●Nukeファイルをターミナルモードで開いて変更する

ターミナルモード + PythonはNukeファイルに対しても有効です。

これを利用すると、Nukeファイルに対してPythonを実行できるので、複数のカットに対しPythonで一定の処理を
加えたいときには有効です。

記述方法はこんな感じ。

[code]"C:\Program Files\Nuke7.0v1\Nuke7.0.exe" -t "D:\testPython.py" "D:\testScene.nk"[/code]

Pythonに何かの値を受け渡したい場合はPythonファイルの後ろにスペースを入れて入力します。


最後に

初めてのDFtalkの記事ということもあって、初歩的な部分も多かったですが
最後まで読んでいただいてありがとうございます。

実はこれマニュアルに似たような例が乗ってたりするんですよね。記事を書き終えてから
気付いてしまい、あっ!っと思ったのですがもう遅かったです。

内容的には違う部分もあるので、見比べてみて何かのヒントにしていただければ幸いです。

やっぱりマニュアルは最後まで読まないといけないですねヾ(_ _*)ハンセイ・・・
次は、もうちょっと専門的なことを書けるように頑張ります。

コピペからはじめるphotoshopスクリプト

$
0
0

別にはじめてじゃない気がするのですがとりあえずはじめまして、社内の軟体動物ことタコ(@takowasabi)です。
去年の9月に入社して以来、アニメーションチームのTDとして
使い慣れないmotionbuilder(以下MB)を相手に四苦八苦しております(´д`)
今回はMBではなくて自分的に馴染みのあるphotoshop(以下Ps)のツール作成について記事にしたいと思います。

[作業ログ出しツールでログを出してみよう]
softimageにしろmayaにしろ自分がした作業がログとして表示される機能がありますが、Psにも実はその機能があるのです。
そのやり方はadobeのhelpにこっそり載っていたり。
ScriptingListener プラグイン

PsCS6の場合、ScriptListener.8liをC:¥Program Files¥Adobe¥Adobe Photoshop CS6 (64 Bit)¥Plug-ins¥に置くと
Psでの作業に応じてデスクトップにScriptingListenerJS.logという名前の作業ログがテキスト形式で保存されます。
「ちゃんとScriptListener.8liをPlug-insフォルダに入れたのにScriptingListenerJS.logなんてもんデスクトップに無いぞー!」
って方は一度Psを終了させた後、再び立ち上げて新規のプロジェクト立ち上げるなりCtrl+Oで何か画像を開くなりしてください。
ScriptingListenerJS.logが生成されているかと思います。
今回はそのScriptingListenerJS.logを使用して今回は簡単なツールを作成してみたいと思います。

[ScriptingListenerJS.logを利用してコンテ切り抜きツールを作ろう]
Psの場合選択範囲の指定をスクリプトで最初から書くのは実は非常にめんどくさかったりするのですが、
ScriptListenerを使用すると選択範囲の指定そのものがログとして出るので非常に楽だったりするのです。
早速ScriptingListenerJS.logを使用してコンテの絵の部分だけを切り出して各々別に保存するツールを作成してみましょう。

[まずは手作業で行い、ログ出ししてみよう]
とりあえずログを用意する為に一連の手順を手作業でやってみましょう。
つまり、
選択ツールで絵の部分のみを囲う→コピー(Ctrl+C)→新規プロジェクトの作成(Ctrl+N)→作成した新規プロジェクトへペースト(Ctrl+V)→別名で保存、名前&ファイル形式は任意(Ctrl+shift+S)
の動作を手作業でするのです。

一連の作業を手作業で行なった後、デスクトップに作成されたScriptingListenerJS.logを開いてみましょう。

スラッシュ2つと破線で区切られてる区間に書かれてる呪文のような言葉、これが作業ログとなります。
softimageやmayaと比べると長ったらしいのですが、Psの場合複数行にわたって書かれてるコードで1つの動作を体現しています。

[Adobe ExtendScript Toolkitでコードを動かしてみよう]
adobe製品のスクリプトエディタ的役割のあるExtendScript Toolkitを使用して吐き出されたコードを動かしてみましょう。
adobe製品が何かしらインストールされていればExtendScript Toolkitはインストールされていると思いますが
んなもんねーよ!という方はadobeのサイトからダウンロードしておきましょう。 Adobe Scripting Center


そのままコピペして、実行すると先ほど手作業で行なった動作がスクリプトで自動化されてるかと思います。
先ほど吐き出されたログをベースに、コンテの絵を描く場所5コマ全て切り抜き、コンテのある場所に別名保存、その際の名前は元のコンテの名前+‐(ハイフン)+番号.jpg
というサンプルを書いてみました。
弊社のコンテ用紙をベースにしているのでほかのコンテで正しい動作を得たい場合、変数AddValueと関数Selecter()内の値を変更してもらえると正しく動作するかと思います。
また、見やすくするためにインデントつけときました。

[javascript]
function ConteScrap(){
for (var i=0;i<5;i++){
var AddValue= 151*i
var DocName = activeDocument.fullName
var SaveNo =i+1
var SaveName = DocName.toString().replace(".","-"+SaveNo+".")
Selecter(AddValue)
CopyContePicture()
NewDocment ()
PaseteContePicture()
SaveContePicture(SaveName)
CloseDoc()
}

//選択範囲の指定
function Selecter(AddValue){
var idsetd = charIDToTypeID( "setd" );
var desc210 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref166 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idfsel = charIDToTypeID( "fsel" );
ref166.putProperty( idChnl, idfsel );
desc210.putReference( idnull, ref166 );

var idT = charIDToTypeID( "T " );
var desc211 = new ActionDescriptor();
var idTop = charIDToTypeID( "Top " );
var idRlt = charIDToTypeID( "#Rlt" );
desc211.putUnitDouble( idTop, idRlt,59+AddValue);
var idLeft = charIDToTypeID( "Left" );
var idRlt = charIDToTypeID( "#Rlt" );
desc211.putUnitDouble( idLeft, idRlt, 170);
var idBtom = charIDToTypeID( "Btom" );
var idRlt = charIDToTypeID( "#Rlt" );
desc211.putUnitDouble( idBtom, idRlt, 196+AddValue);
var idRght = charIDToTypeID( "Rght" );
var idRlt = charIDToTypeID( "#Rlt" );
desc211.putUnitDouble( idRght, idRlt, 413);
var idRctn = charIDToTypeID( "Rctn" );
desc210.putObject( idT, idRctn, desc211 );
executeAction( idsetd, desc210, DialogModes.NO );
}

//選択範囲の絵をコピー
function CopyContePicture(){
var idcopy = charIDToTypeID( "copy" );
executeAction( idcopy, undefined, DialogModes.NO );
}

//新規ドキュメントを作成
function NewDocment (){
var idMk = charIDToTypeID( "Mk " );
var desc213 = new ActionDescriptor();
var idNw = charIDToTypeID( "Nw " );
var desc214 = new ActionDescriptor();
var idpreset = stringIDToTypeID( "preset" );
desc214.putString( idpreset, "クリップボード" );
var idDcmn = charIDToTypeID( "Dcmn" );
desc213.putObject( idNw, idDcmn, desc214 );
executeAction( idMk, desc213, DialogModes.NO );
}

//ペースト
function PaseteContePicture(){
var idpast = charIDToTypeID( "past" );
var desc215 = new ActionDescriptor();
var idAntA = charIDToTypeID( "AntA" );
var idAnnt = charIDToTypeID( "Annt" );
var idAnno = charIDToTypeID( "Anno" );
desc215.putEnumerated( idAntA, idAnnt, idAnno );
executeAction( idpast, desc215, DialogModes.NO );
}

//選択範囲の解除
function RemoveSelection (){
var idsetd = charIDToTypeID( "setd" );
var desc243 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref182 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idfsel = charIDToTypeID( "fsel" );
ref182.putProperty( idChnl, idfsel );
desc243.putReference( idnull, ref182 );
var idT = charIDToTypeID( "T " );
var idOrdn = charIDToTypeID( "Ordn" );
var idNone = charIDToTypeID( "None" );
desc243.putEnumerated( idT, idOrdn, idNone );
executeAction( idsetd, desc243, DialogModes.NO );
}

//jpegで名前をつけて保存
function SaveContePicture(SaveName){
var idsave = charIDToTypeID( "save" );
var desc254 = new ActionDescriptor();
var idAs = charIDToTypeID( "As " );
var desc255 = new ActionDescriptor();
var idEQlt = charIDToTypeID( "EQlt" );
desc255.putInteger( idEQlt, 12 );
var idMttC = charIDToTypeID( "MttC" );
var idMttC = charIDToTypeID( "MttC" );
var idNone = charIDToTypeID( "None" );
desc255.putEnumerated( idMttC, idMttC, idNone );
var idJPEG = charIDToTypeID( "JPEG" );
desc254.putObject( idAs, idJPEG, desc255 );
var idIn = charIDToTypeID( "In " );
desc254.putPath( idIn, new File(SaveName) );
var idCpy = charIDToTypeID( "Cpy " );
desc254.putBoolean( idCpy, true );
executeAction( idsave, desc254, DialogModes.NO );
}

//コピペ先のドキュメントを閉じるよ
function CloseDoc (){
var idCls = charIDToTypeID( "Cls " );
var desc275 = new ActionDescriptor();
var idSvng = charIDToTypeID( "Svng" );
var idYsN = charIDToTypeID( "YsN " );
var idN = charIDToTypeID( "N " );
desc275.putEnumerated( idSvng, idYsN, idN );
executeAction( idCls, desc275, DialogModes.NO );
}
}
ConteScrap()
[/javascript]

[通常のスクリプトでは不可能なことでもScriptingListenerJS.logで出来るようになるよ!]
スクリプティングをかじったことのある方なら、「こんな単調で長ったらしいコードどういう時に役に立つねん」と思うかもしれません。
実はコレ、ScriptingGuideに載っていない&不可能な作業も可能としてくれるのですよ!ワーイ
以前私のblogでも触れましたが、レイヤーを複数(飛び飛び)選択するとかレイヤー効果の追加なんかもまるっとコピペで出来るようになります。
あとあれですね、コピペだしイチからScriptingGuide読んでチクチク書くよりかはずっと精神的なハードルが低いかと思います、気楽!

やー、これAfterEffectsにも欲しいですね!コピペ!

※免責事項※
本記事内で公開している全てのコードの有用性、安全性について、当方は一切の保証を与えるものではありません。
これらのコードを使用したことによって引き起こる直接的、間接的な損害に対し、当方は一切責任を負うものではありません。
自己責任で使ってね☆

マニアックリグその2 poseBlend

$
0
0

どうも、こんにちは。TDチームの石田(@1null4null)です。

今回はアニメーションカーブを利用したRigを解説しようかと思います。
マニアックかと言われるとマニアックじゃない…?

アニメーションカーブにinputというアトリビュートがありますが、ここに何かを繋げるとアニメーションのoffsetが出来ます。
今回はこれを利用してループアニメーションとポーズのブレンドを解説しようと思います。

■ループアニメーション
ループアニメーションは簡単にチャラッと解説します。
虫の羽などはループアニメーションをさせるかと思いますが、過去のプロジェクトでexpressionを書いてあの独特な動きを計算式で表現した例があります。
なぜexpressionで表現したかというと強弱、速さなどを簡単にattirbute入力で設定出来るからです。
ですがscriptが書けないとなるとなかなか難易度が高い手段ですよね。
めんどくさい計算をしたくないからアニメーションでループ出来て簡単に強弱と速さ変えられたらいいんでない??
ってことでアニメーションカーブを使用してアトリビュート設定でその辺やっちゃいましょう。

ではまず下図のようなアニメーションを付けます。10~20フレくらいのアニメーションです。
そしてpreInfinity,postInfinityを設定。これでループの完成。

どこでもいいのですがrootノードに「time」Attributeをaddします。※以下root.time

root.timeとanimCurve.inputを繋げます。下図
これでroot.timeにアニメーションを打てば速さが自由に設定できるようになります。
試しにroot.timeに適当にアニメーションを打ってみてください。

次に強弱の設定を出来るようにします。
multiplyDivideを使用します。
ちなみに過去の記事にも紹介があったかと思いますが、NodeEditer>tabキー>mul…と打つとmulで始まるノード名が出てきます。
作りたいノードを選んでEnterを押すとノードが出来ます。便利ですね。
下図のように繋げます。

multiplyDivideを設定します。例↓
setAttr "multiplyDivide1.input2X" 0.25;
setAttr "multiplyDivide1.input2Y" 0.5;
setAttr "multiplyDivide1.input2Z" 1;

こんな感じに入力すると順に抑えられた動きになります。下図

ぬー、長くなった…。
ここらへんはいろんな方のブログでも解説されているかと思います。参考にしてみてください。
さて、次はこれを応用してポーズのブレンドを解説したいと思います。


■ポーズのブレンド

ポーズのブレンドとはどういうこっちゃと言いますと、MayaにはBlendShapeがありますがBlendShapeはバーテックス移動のブレンドですよね。
ポーズのブレンド = コントローラー(transform.SRT)のブレンドです。
弊社では poseBlend と呼んでます。というか一人プロジェクトの時に考えて使ったので呼んでるのは僕だけですが…。

例えばフェイシャルのリグを組むときに、コントローラーが多いから一つのコントローラーで制御したいけどsetDrivenKeyを使うと数が多いからよくわからなくなるしブレンドすると設定が失敗しやすくなったりめんどくさい…。

というわけで作っちゃいます。
どんなもの作るの?と疑問に思う方もいらっしゃるかと思いますので先に説明します。
Softimageを知っている方はアニメーションミキサーがイメージが付きやすいかと思います。
アニメーションミキサーと似たものをノードコネクションで作っちゃいます。

上の図を例に説明します。
5つのコントローラーがあります。
左側に二つのスライダーコントローラーがこの5つのコントローラーを制御しています。
赤いcloseのコントローラーは中心に集まるアニメーションを制御しています。
青のopenのコントローラーは外側に広がるアニメーションを制御しています。
closeとopenの両方のスライダーが上がってもブレンドし合って形作っているかと思います。
簡単に説明しますと先ほど解説した「ループアニメーション」(これにはループの設定はしてません)に「ブレンド」を施しているだけです。

現在は二つだけですがいくつものposeを付けることが可能です。blendShapeと一緒ですよね。
コネクションは「ループアニメーション」で解説した方法とほとんど変わりません。
最後にサンプルデータを用意しています。サンプルではcontainerNodeを使用していますが何でもいいです。
アニメーションカーブのブレンドってどうするの?ってことで次にブレンドの解説をします。


○アニメーションカーブのブレンド

setDrivenKeyを複数設定していると出来るNodeがあります。
blendWeightedというノードです。これを使用すればアニメーションカーブがブレンド出来るようになります。
気をつけなければいけないのはデフォルト値がゼロ以外だとどんどん加算されてしまいます。
なのでコントローラーの数値は必ずゼロにしましょう。

デフォルト値がゼロでないものもあります。scaleです。
1+1=2になってしまうのでplusMinusAverageやaddDoubleLinearなどを使用してweightBlentedにゼロが入るようにします。
すべてゼロにするとデフォルト値がゼロになっちゃうので一つだけデフォルトの1にします。

■Trax Editorを使う
さてここまで頑張って書きましたがTraxEditorを使う方法もあります。
上記の方法ではscriptを書いていましたがTraxEditorのほうが楽でしたorz。
終わった後に気が付く、、、良くあることですねw
これもサンプルデータがありますので参考にしてください。

○traxPoseBlend作成の流れ

  1. コントローラーをアニメーションします。
  2. そのコントローラーを選択したまま  Animate > CreateClip 実行
  3. clipが作られます。 ※Window > Animation Editors > Trax Editor で TraxEditorが開きます。
  4. 1,2と同じ手順でclipを作ります。 ※clipとコントローラーが繋がってますがキーを打てます。ですが動いてしまうので先ほど作ったclipのenableをoffにします。
  5. 後は好きなだけclipを作ります。
  6. 制御コントローラー(スライダーコントローラーなど)をclip.weightにそれぞれコネクションします。
  7. clip.startFrameを設定します。

ここで注意して欲しいのは下図のようにclipの範囲からマイナスを見ている場合はweightを1にしても反応しません。
なのでclip.startFrameを-1000とかにします。でも気持ち悪いのでカット毎のstartFrameを入れたいとこですね。
エクスプレッションかコネクションで仕込んであげるといいかもしれません。

TraxEditorだと後からアニメーションカーブの編集も可能ですし使い回しも追加も簡単です。
以上で解説は終わりです。

悪名高いと噂のTraxEditorと聞いていて今まで触らずでしたが調べてみたら使い所あるなと、食わず嫌いはよくないですね!!
マニアックなのかそうでないのか分からなくなってきましたけれどこういうの考えていると他のプロダクションさんではどうやってるのか気になってきます…。
次回もお楽しみに~!!

<<サンプルデータ>>
poseBlend.ma(zip)
poseBlend_Trax.ma(zip)

※注意※ 本記事内でダウンロード可能なサンプルシーンを使用したことによって引き起こるいかなる損害も
当方は一切責任を負いかねます。自己責任でご使用くださいませ。


BRDF Explorerでシェーダーを書いてみよう

$
0
0

はじめに

はじめまして。自称DF随一のゆるふわ系社員、松岡です。
春になってきて、ぽかぽか陽気の日も多くなってきました。
眠くて眠くて・・・ほんと・・・zzz・・・いやいや、ちゃんと仕事しますよ!
今回は、シェーダーを自分で書いてみようという記事を書いてみます。
CGにおいて、見た目のキモになる部分といえば、シェーダーですよね!(ホントですか?
シェーダーしだいで無味乾燥なポリゴンも実写と見違えるような絵に大変身するなんてこともあるわけです!

BRDF Explorer

今回はDinsneyがフリーで公開しているツール「BRDF Explorer」を使ってシェーダーを書いて、表示してみたいと思います。

以下のURLが公式ページになります。
http://www.disneyanimation.com/technology/brdf.html

まずは公式ページからバイナリをダウンロードしてサクっと使ってみちゃいましょう。
まずGet Startedの”win32 binary”をクリックして以下のページからダウンロードします。
現在、brdf-1.0.0-win32.zipが最新みたいですね。
こいつは単なるzipファイルなので適当なフォルダ展開しちゃえばOKです。

使ってみる

さあ、早速使ってみましょう。展開したフォルダのbrdf.exeが本体ですね。起動してみましょう。

以上のような、画面が出たと思います。この状態はなんのこっちゃわからないので、BRDF Explorerのシェーダーファイルである.brdfファイルを読み込んでみます。
メニューから[File]-[Open BRDF]で、ファイル選択ダイアログが出てくると思いますので、ファイルを選択します。

.brdfファイルは、brdfsフォルダにあります。brdfsフォルダの下にはblinnやphongなどの一般的なシェーダーモデルで記述されたファイルが配置してあります。
手始めに、今回はblinn.brdfでも選択してみましょうか。
すると以下の様な画面が表示されたはずです。

さて、下のほうのタブLit Sphereを選択した状態にしておいてください。
これで、このblinnモデルは古典的なシェーダーモデルの一つで、プラスティックなどを表現したりしますね。

左にあるのが、blinnモデルのパラメーターです。
“n”や”ior”を変更して、どう絵が変わるか試してみましょう。例えば、”n”を大きくすると、スペキュラーの値が変わるのがわかると思います。

他にも、cook-torranceモデルや、oren-nayerモデルなどがあるので試してみましょう。

自分でシェーダーを書いてみる

ここからはbrdfsフォルダにはない、自分オリジナルの俺々なシェーダーを記述したいと思います。

まずは、適当な.brdfファイルをコピーして別の名前をつけてください。
ここでは、phong.brdfをコピーして、oreore.brdfとしてみます。
では、まずはこのoreore.brdfを読み込んで見ましょう。すると、何も変更していないので当たり前ですが、blinnシェーダーと同じようなシェーダーになると思います。

それでは、oreore.brdfを変更して名実ともに俺々なシェーダーにしていきましょう。

oreore.brdfをテキストエディターで開いて見ましょう。

.brdfファイルは大きく2つの部分に分けられます。

○パラメータ定義部
[code]
::begin parameters
//略
::end parameters
[/code]
ここにGUIからのパラメータを定義します。

○シェーダー定義部
[code]
::begin shader
//略
::end shader
[/code]
ここに、以下の関数を定義することでシェーダーを記述します。
つまり、この関数がシェーダー本体だと考えていいでしょう。
[code]
vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y )
[/code]
この関数の引数の意味は以下の表のようになっています。

変数 意味 説明
vec3 L ライトの方向 シェーディングする点へ照射される光の方向
vec3 V 視点の方向 シェーディングする点から見たカメラのある方向
vec3 N 法線方向 シェーディングする点の法線方向
vec3 X 接線方向 シェーディングする点の接線方向。tangent。異方向性シェーディングを実現するときに用いる。
vec3 Y 従法線方向 シェーディングする点の従法線方向。binormal。異方向性シェーディングを実現するときに用いる。

返り値のvec3はシェーディング結果の色を返します。

変更してみる

まず、oreore.brdfは全体的に暗いですね。
元のphong.brdfはphongのシェーディングモデルを記述してあるのですが、これだけではスペキュラーだけでディフューズがありません。それでは寂しいのでディフューズを足してみましょう。lambertがいいかなと思います。
以下のように書き換えてください。
[code]
//lambertのディフューズモデル
float lambert( vec3 L, vec3 N)
{
return max(0, dot(L,N));
}

//phongのスペキュラーモデル
float phong( vec3 L, vec3 V, vec3 N)
{
vec3 R = reflect(L,N);
return pow(max(0, dot(R,V)),n);
}

vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y )
{
//diffuse
float diffuse = lambert(N,L);

// specular
float specular = phong(L,V,N);

float val = diffuse + specular;

return vec3(val);
}
[/code]

書き換えた.brdfファイルの反映は以下のようにreloadすればOKです。

見慣れた絵が出てきたと思います。

それでは次はシェーディングに色を付けてみましょう。

[code]
::begin parameters
float n 1 1000 100
float r 0 1 1
float g 0 1 1
float b 0 1 1
::end parameters

//略

vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y )
{
//diffuse
float diffuse = lambert(N,L);

// specular
float specular = phong(L,V,N);

return vec3(r,g,b)*diffuse + vec3(specular);
}
[/code]

これで、パラメータr,g,bを変更することでディフューズの色が変更できるようになりました。

スペキュラーの反射モデルの変更

ここまでだったら、普通のphongモデルのシェーダーなのでつまらないですね。仕上げに異方向性反射に挑戦してみます。
今回はkajiya-kayの異方向性反射を実装してみたいと思います。
kajiya-kayモデルはよく髪の毛などのシェーディングに用いられます。

それではoreore.brdfを以下のように変更してみてください。

[code]
::begin parameters
float n 1 1000 100
float d_weight 0 1 1
float s_weight 0 1 1
float r 0 1 1
float g 0 1 1
float b 0 1 1
::end parameters

::begin shader

vec3 reflect(vec3 I, vec3 N)
{
return 2*dot(I,N)*N - I;
}

float KajiyaDiffuse( vec3 hairTangent, vec3 lightVector)
{
float df = dot( hairTangent,normalize( lightVector ) );
df = 1.0 - (df * df);
if ( df < 0 ) df = 0; if ( df > 0 ) df = sqrt( df );

return df;
}

float KajiyaSpecular( vec3 hairTangent, vec3 lightVector, vec3 viewVector )
{
float kspec;
float sintl;
float sinte;
float vt;

sintl = KajiyaDiffuse( hairTangent, lightVector );

vt = dot(viewVector,hairTangent);
sinte = 1.0 - (vt * vt);
if ( sinte < 0 ) sinte = 0; if ( sinte > 0 ) sinte = sqrt( sinte );

// equl on paper : (t.l)(t.e) + sin(t,l)sin(t.e)
kspec = sintl * sinte - dot( normalize(lightVector), hairTangent ) * vt;

if ( kspec < 0 ) kspec = 0;

kspec = pow(kspec,n);
return kspec;
}

//
vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y )
{
vec3 T = Y;//
//diffuse
float diffuse = KajiyaDiffuse(T,L);

// specular
float specular = KajiyaSpecular(T,L,V);

return vec3(r,g,b)*diffuse*d_weight + vec3(specular)*s_weight;
}

::end shader

[/code]

すると、以下のように異方向性反射が実現できるはずです。

なんとなく髪の毛っぽくなったでしょうか?

おわりに

今回は、BRDF Explorerを用いてシェーダーを記述してみました。
もちろんBRDF Explorerで作ったシェーダー(.brdf)はそのままでは各種ゲームエンジンやレンダラにはもっていけません。
しかしシェーダー記述における基本は、ベクトルをかけたり足したりして色を求めるだけですので、その他のツールに移植するのも難しくないでしょう。
BRDF Explorerの場合、シェーダーを変更したら、すぐにそのシェーディング結果を確認できるのがいいですね。
みなさんもぜひBRDF Explorerで遊んでみてください。
それではまた!

徒然なるままに #1 [MayaでAttributeEditorをドッキングさせたくない]

$
0
0

こんにちはー。開発室のひらく[@horonig]です。

今回ちょっと力を抜いて、簡単なtipsを紹介します。
手抜き記事ではないですよ!ちょっと時間が取れないだけで!(あれ、デジャブ。。?)

 

■MayaでAttributeEditorをドッキングさせない方法

皆さんはAttributeEditorがメインUIに勝手にドッキングされそうになるのをウザい!!と思った事はありませんか?僕はこれが嫌でたまりませんでした。心の底から。井戸の底から貞子を召喚したいくらいに。
要は、AttributeEditorをメインUIの方へ動かすと以下の図のようにグイッとしゃしゃり出てくるのを防止したいわけです。

[mayaがAttributeEditorを一生懸命ドッキングしようとしている図]

点線とか出して受け入れ可能な感じを演出しちゃってます

maya2011からUIにQtを採用したことでこのウザいドッキングの仕組みが始まったわけですが、AttributeEditorまでドッキングせんでもええやん。。と夜な夜な思ったものです。「俺のMultiListerを返せ…!」と枕を濡らした夜もありましたが、それはまた別のお話。

実は以前、AttributeEditorをドッキングさせないで済む方法が無いかautodesk様に確認した事があります(正確に言うと、確認したの僕じゃないんですけどw)。したら意外とすんなり方法論が出てきたので、その内容をお伝えしてしまいます。
こういう情報はシェアしてみんなで幸せにならないとね^^^

今回説明する方法は、PyQt もしくは PySide が使える環境である事を前提としております。
その環境が無い方は地団太を踏んで下さい。
否、どこかに落ちてる PySidePyQt を使えるように配置&設定を行ってから実践して下さい。

 
方法は簡単です。以下のダウンロードファイルに含まれる userSetup.py を、PYTHONPATH が通ってるパスに置いてmayaを起動するだけです。
ダウンロード

PYTHONPATH が良く分からない方は、
C:\Users\USERNAME\Documents\maya\scripts で大丈夫です。
※PyQt版とPySide版では内容が違いますので、ご自身の環境に合わてご使用下さい

コードはこんな感じになってます。

[PyQt版][python]
def attrEdit():
import maya.mel as mel
import maya.OpenMayaUI as OpenMayaUI
import sip
import PyQt4.QtGui, PyQt4.QtCore
ae = mel.eval(‘getUIComponentDockControl(“Attribute Editor”, false);’)
aeWidgetPtr = OpenMayaUI.MQtUtil.findControl(ae)
aeWidget = sip.wrapinstance(long(aeWidgetPtr), PyQt4.QtCore.QObject)
aeWidget.setAllowedAreas(PyQt4.QtCore.Qt.NoDockWidgetArea)

import maya.cmds as cmds
cmds.evalDeferred( attrEdit )
[/python]

 
[PySide版][python]
def attrEdit():
import maya.mel as mel
import maya.OpenMayaUI as OpenMayaUI
import PySide.shiboken as shiboken
import PySide.QtGui, PySide.QtCore
ae = mel.eval(‘getUIComponentDockControl(“Attribute Editor”, false);’)
aeWidgetPtr = OpenMayaUI.MQtUtil.findControl(ae)
aeWidget = shiboken.wrapInstance(long(aeWidgetPtr), PySide.QtGui.QDockWidget)
aeWidget.setAllowedAreas(PySide.QtCore.Qt.NoDockWidgetArea)

import maya.cmds as cmds
cmds.evalDeferred( attrEdit )
[/python]

 
attrEdit(関数)の部分は読むとなんとなく分かるかと思います。
要は、AttributeEditorをドッキングさせないよう再設定しちゃってるわけです(そのまんま…)。

それよりこのコードのキモは、evalDeferred でしょうか。
userSetup.py はmaya起動時に走るわけですが、mayaの設定(スタートアップ)がまだ終わってないタイミングでこのスクリプトが走ってしまうと、「必要なprocedureが足りない」というエラーが出ます。ところがこの evalDeferred を用いる事でこの問題は解決します。evalDeferred は「mayaが暇になったら実行する」という意味合いの関数なので、mayaの設定(スタートアップ)が諸々終わったタイミングで実行してくれる、という事になるわけです。便利ですね~。

結果、AttributeEditorのドッキングが出来なくなれば成功です。

一度これをやってしまうとAttributeEditorのドッキングは常に不可能となるので、再びドッキング可能にしたい場合は userSetup.py の中身を書き換えるか、削除しちゃって下さい。
 

■甘味紹介 #1 [スフレパンケーキ at 星乃珈琲]

DF_talkのネタとして(何故か)甘味情報も載せて欲しいという要望が寄せられたので、今後は「お勧めの甘味」や「これは!と思った甘味」なんかも載せていこうかなと思います。

というわけで、今回はその第一弾!

渋谷で食べた甘味で何がパンチ力あったかなーと思って思い出したのがパンケーキ。
渋谷にもあるわけですよ。でっかいパンケーキを食べさせるお店が。

それがこちら↓

『星乃珈琲 109 MEN’S店』 の スフレパンケーキダブル!!

アップしたまんまだとデカイなwwww まいっかwwwww

総評としては何というかこう。。とにかくパンチ力があって美味かったです!w
珈琲も旨くてパンケーキに良く合います。

『星乃珈琲 109 MEN’S店』
http://tabelog.com/tokyo/A1303/A130301/13130132/

脳の疲れには甘味が一番なので、CGに疲れた人は是非行ってみて下さい!
てかこんな雑な記事で良いのだろうか。。

…ではまた!!

Maya2013導入で発生した開発室での出来ごと

$
0
0

お久しぶりです
開発室の齊藤です

Autodesk 2014製品が発表されました! 早速2014の紹介を!!
ではなく、今回はMaya 2013 を導入する際に起こった、開発室での出来事から2つを紹介します

Pythonモジュールの用意

最初はPythonモジュールについて。
Maya2013からWinodwsでは開発環境が、VisualStudio2008から2010へと変わりました。
この変更は、一部のPythonモジュールにも影響が及びます。

Maya2013でPythonモジュールインポートするとエラーが出る報告がありました。

ImportError: DLL load failed: The specified module could not be found.

エラーを見ても、いつも通りぶっきらぼうに言っています。 “どの”DLLなのか教えてくれない。
最初は環境変数PATHの設定間違えか?などと疑いました。
しかし、このエラー原因を突き詰めていくとあるファイルに辿りつきます。

拡張子がpydのファイルです。

pydファイルはC/C++で書かれたコードをビルドすることで作られるファイルです。
この問題の原因は、pydファイルがMSVCR90.dllを要求することに起因します。

MSVCR90.dllはVisualStudio2008です。
冒頭の通り2013から、VisualStudio2010です。

と言うことで、モジュールをVisualStudio2010でビルドすることで、エラーは解決します。

じゃぁビルドしていくかとなるわけですが、ここからが大変な話でした。
ビルドする際に以下のコマンドを使うモジュールがあります

> python setup.py build

この場合にもちろんpython.exeが必要ですが、ここに問題があります。
Mayaが使っているPythonのバージョンは2.6です。公式で配布されているものはVisualStudio2008でビルドされたものです。
VisualStudio2010でビルドされたPythonは配布されていません。

今回の対象はMayaだったので、そもそもMayaにないのか?っと探るとありました。名前を変えて。

Mayaインストールディレクトリ/bin/mayapy.exe

このexeを用いて、モジュールのビルドは進みました。

しかし、ビルド途中でエラーが発生するモジュールが現れます。NumPyです。
NumPyではビルド途中で、”マニフェストが見つからない”とエラーが発生しました。

最初はNumPyビルド時の設定ミスか、バグかと疑いました。
しかし、エラーを探るとPythonのIssue TrackerからIssue16296というのを発見しました。
バグに対してパッチが出ていたので、パッチを当てたPythonを使うことでビルドが通りました。

このようにエラーが出るモジュールもあれば、すんなりビルドが通るモジュールもあります。
エラーが出れば都度解決方法を見つけてビルドしていきました。

現在、リビルドが必要だと分かっているモジュールとしては、以下のものが挙げられます

・NumPy
・PyQt
・PySide
・PyWin32 (Python for Windows extensions)

モジュールの中でも一部だけがエラーを起こすこともあり、最初は使えると思っていても後に問題になることがあります。

MFnBaseの仕様変更

次は、Maya APIの仕様変更で起きたことを1つ。
Maya2013から、MFnBaseクラスのコピーコンストラクタがプライベートになりました。

だから何だという話もあると思います。

Mayaのバージョンが変わると、社内で開発されたプラグインをMaya2013に向けてビルドをします
ビルドが成功する中、とあるプラグインで以下のC2248のエラーが大量に発生しているプラグインが現れました。

error C2248: ‘MFnMeshData::operator =’ : private メンバー (クラス ‘MFnMeshData’ で宣言されている) にアクセスできません。(省略)

何が起きたんだと探っていると、MFnBaseクラスのコピーコンストラクタがプライベートになっていることを発見。
そこから、問題のプラグインのコードを探っていき問題のコードに辿りつきました。

std::vector< MFnMesh > …

問題のクラスはMFnBaseですが、クラス名からの想像通りこのクラスは、MFn~となっているクラスに影響をします。
今回のは上記のコードが原因で、MFnMeshのコピーコンストラクタを呼ぶことになり、エラーを出していたというものです。
このエラーを出しているプラグインには、他にもstd::vector< MFn~> があり大量のエラーを生み出していました。
なので以下のように書き換え

std::vector< MFnMesh* > …

その後、他の部分も正常に動作するようにコードを書き換えて、この問題は解決しました。

最後に

MFnBaseの仕様変更については、あまり話が出ないのはわかるんですが
Pythonモジュールの話は、あまり情報が無いんですよね。

今回発表された2014導入するとなると、どんな出来事があるのかドキドキします。

RampShaderで簡単なトゥーンシェーディング

$
0
0

はじめに

はじめまして、DFの武山です。

道を歩いていると、桜もだいぶ散ってしまったように感じます。
また、気候もたまに寒くなったりしてちょっと体の調子が…。
それでも、がんばっていきたいと思います。

今回は、トゥーンシェーディングについて簡単に紹介したい思います。
その前に、RampShaderのColor Inputについて説明したいと思います。

Color Inputについて

RampShaderのカラーは以下のように設定されているとします。

また、ライトとカメラの位置は以下のような配置になっています。

・Light Angleの場合

Color Inputに「Light Angle」を指定すると上図のようなイメージになります。
「LightAngle」ですが、この場合サーフェス法線とライトの角度によってランプの色が決定されます。
サーフェス法線をN、ライトをLとすると、

dot(L、N)

つまりLとNの内積で求めることができます。
ランプの一番右側の色は、サーフェス法線が、ライトにまっすぐに向いたときの色を表します。
また、一番左側の色は、サーフェス法線がライトに対して正反対に向いたときの色です。

・Facing Angleの場合

Color Inputに「Facing Angle」を指定すると上図のようなイメージになります。
「Facing Angle」ですが、この場合サーフェス法線と視線の角度によってランプの色が決定されます。
サーフェス法線をN、視線をVとすると、

dot(V、N)

つまりVとNの内積で求めることができます。
ランプの一番右側の色は、サーフェス法線が、カメラにまっすぐに向いたときの色を表します。
また、一番左側の色は、サーフェス法線がカメラに対して垂直に向いたときの色です。

・Brightnessの場合

Color Inputに「BrightNess」を指定すると上図のようなイメージになります。
この場合、拡散ライティングの明るさが1.0以上の場合、一番右側の色が使用されます。
0.0の場合、一番左側の色が使用されます。

この状態で以下のにように、Ramp ShaderのInterpolationを「None」にします。

このようにすることで、シェーディングの色が段階的に変化するようになり、
トゥーンシェーディングに向いたシェーディングになります。

トゥーンシェーディング

RampShaderでトゥーンシェーディングを行います。

まず、HypershadeでRamp Shaderを作成します。

Interpolationを、「Linear」から「None」に変更します。
Color Inputを、「Light Angle」から「Brightness」に変更します。

「Specularity」を「0.0」、「Eccentricity」を「0.0」に変更します。

あとは、以下のようにColorで好きな色を設定します。

この状態でレンダリングすると以下のようになります。

ここから、mentalrayのContourを使用してアウトラインを作成します。
RenderSettingを以下のように設定します。

「Custom Shaders」の「ContrastShader」と「StoreShader」を
以下のように設定します。

「contour_contrast_function_levels1」を以下のように設定します。

ここまで設定したら、Hypershadeで「contour_shader_simple」を作成します。
あとは、以下のようにShadingGroupにcontour_shader_simpleを接続します。
(繋げるのは、contour_shader.outValue → miContourShaderです)

Contour_shader_simpleの設定を適当に設定してレンダリング。
(ここでは、色を青に設定しました)

この状態でレンダリングすると以下のようになります。

これでトゥーンシェーディングについてはおしまいです。

トゥーンシェーダといえば、アニメによく使われますよね。
ここからは、アニメつながりでアニメについて書いていきます。

BlackJackついて

BlackJackは、漫画家の手塚治虫さんの作品の一つです。
OVAや、TVシリーズなどアニメ化もされています。

内容は、医師免許を持たない天才外科医のBlackJack(本名:間 黒男)が、難病や奇病を
治すというのが大まかな流れです。

おもしろいのは、必ずしも治せるというわけではないところです。
失敗も結構してます。

また、多額の手術代を請求したりして、悪徳医師のように描かれたりもしています。
その辺が、一般的な主人公とはちょっと違うのではないかなと思います。

OVAについて

BlackJackのアニメ化は、自分が知る限りこのOVAが最初じゃないかと思います。
第一話の製作は、1993年に行われています。
今から、なんと20年前です。

当たり前ですが、メディアもDVDとかレーザーディスクとかではなくVHSです。
(現在では、DVDでの販売になっています)

自分が見た時点では、全10話でした。
現在では、全12話になっています。
(2011年に2話追加されています)

OVAですが、基本的には原作のストーリーを踏襲しつつ、OVAオリジナルの要素が加えられています。
また、OVAオリジナルストーリーも2話ほどあります。

このOVAなんですが、作画のクオリティが非常に高いです。
現在では若干古い印象を受けますが、まだまだ通用するレベルだと思います。

個人的に好きな話は、第5話の「サンメリーダの梟」です。

少年の身体を診察したBlackJackが、少年がかなり昔に手術をされていることに気づきます。
そして、手術の技術力の高さから、執刀した医師に会いたいと思いサンメリーダという場所に向かうという
話です。

この話は、全体的に不思議でちょっと切ない感じがします。
サンメリーダという場所を知らないはずの少年が、なぜか村の地形を知っていたり、
体験したことのない過去がフラッシュバックされたりし、徐々にサンメリーダという場所でなにが
起こったのかということが解き明かされていきます。

ちょっと気になった人はレンタルビデオ屋さんにもあると思うので、借りてみてください。

かなり昔のOVAなので、公式のホームページはもうないようです。

リンクは貼れませんが、googleなどで検索すると個人の方の紹介記事など結構ヒットすると思います。

それではノシ

これでトゥーンシェーディングについてはおしまいです。
トゥーンシェーダといえば、アニメによく使われるのでここからは、
アニメについて書いていきます。

MotionBuilderをカスタマイズしよう

$
0
0

こんにちは、TDチームの森本です。

今年もつらい花粉症との闘いが一段落ついてほっとしているところです。

前回はMotionBuilderのメニューにスクリプトを追加する方法を紹介しましたが
今回は設定まわりのカスタマイズについて、いくつか紹介しようと思います。

はじめに

これからMotionBuilder(以下MB)の設定周りについて説明するのですが
設定ファイル自体をバックアップをとっておくことができます。
MBが強制終了したりした場合に設定が初期化されてしまう場合がありますが
カスタマイズ後の設定ファイルをバックアップとっておくことで
初期化されても設定をすぐにもどすことができるのでお勧めです。

また、MBの挙動が変になった場合に
設定周りのファイルを削除することで修正される場合があります
(設定ファイルを削除しても起動時にデフォルトで自動生成されます)

MotionBuilderの設定について

MBの設定はメニューの[Settings]>[Preferences]にありますが
この場所の設定以外にテキストで設定を変えれる場所があります。

設定ファイルの場所ですがMBのバージョンによって変わります。

MB2013の場合(MB2011以降)
 C:\Users\[ユーザー名]\Documents\MB\2013-x64\config
MB2010の場合
 C:\Users\[ユーザー名]\AppData\Local\Autodesk\MB2010\config

主にMB2011以降とその前とで場所が違っています。

こちらにあるテキストファイルに設定が書き込まれているので
MBを立ち上げなくてもこの中にあるファイルを修正すれば設定を変更できます。

MBを立ち上げてから設定を変えても再起動しないと反映されないため
バッチ処理で一括でスクリプトにかける際にこちらの設定ファイルを変更してから
MBを立ち上げるようにスクリプトを書いておけば
各個人でMBの設定が違う環境でも常に正しい設定でバッチ処理にかけれます。

また普段の設定画面では設定できない項目も含まれています。

例えば
[PC名].Application.txt
内にある[VertexMode]の項目をNoからYesに書き換えて保存します。

この状態でMBを立ち上げると
VertexMode時にVertexの位置を動かすことができます。

例えば弊社では背景モデルで木と地面がCombineされて1つのモデルになっていて
レイアウト時にどうしても木の配置を変えたい場合に
Vertexモードで木をオフセットするのに使用しています。

ただし、単に動かしただけだと最終的にMAYAのシーンを構築した際に元にもどってしまうので
木のVertexで動かしたモデルを書き出してBGチームに渡してそれを参考にして
BGの調整をしてもらっています。

ショートカット設定について

ショートカットについても設定ファイルを修正することでカスタマイズができます。

デフォルトではCtrl+SがセーブですがSキーの周りにも良く使う機能のショートカットがあるため
よく間違ってセーブしてしまいがちな人はショートカットを変更してしまうと解決するかもしれません。

やはりMBのバージョンによってファイルの場所が違っていて

MB2013の場合(MB2011以降)
 [インストール先]\Autodesk\MotionBuilder 2013\bin\config\Keyboard
MB2010の場合
 C:\Users\[ユーザー名]\AppData\Local\Autodesk\MB2010\config\Keyboard

にあるテキストファイルが設定ファイルになります。

MB2010の場合はユーザーフォルダに設定があるので変更しても本人のみに適応されますが
MB2013の場合はインストールフォルダにあるため全体的に変更が有効になりますので
MB2013で個人だけの設定を作る際は設定ファイルを
C:\Users\[ユーザー名]\Documents\MB\2013-x64\config\Keyboard
にコピーして変更してください。

設定ファイル自体は以下のような分かりやすいテキストファイルになっているので
書き換えるのは簡単に出来ると思います。
書き換える際にまずはNameの項目を他の設定とかぶらないように名前を変えてください。

また、空欄になっているショートカットもあるので
日頃不便だとおもってた処理のショートカットがあるかもしれません。

さらにスクリプトをショートカット登録することが可能です。
その場合
1.ショートカット設定でショートカットのボタンを設定しておく
2.ショートカットの際に実行されるスクリプトの設定をする
の手順が必要になります。

1.に関しては先ほどのショートカット設定の中で
action.global.script1のような設定がありますが
これがスクリプトショートカットの設定になってます

2.に関してはMBのバージョンで場所が違っていて

MB2010の場合
 C:\Users\[ユーザー名]\AppData\Local\Autodesk\MB2010\config\Scripts\ActionScript.txt
MB2013の場合(MB2011以降)
 [インストール先]\Autodesk\MotionBuilder 2013\bin\config\Scripts\ActionScript.txt

にあるテキストファイルが設定ファイルになりますが
MB2013の場合はこのActionScript.txtを
C:\Users\[ユーザー名]\Documents\MB\2013-x64\config\Scripts
にコピーして設定ファイルを書き換えてください。

ActionScript.txtの中身は以下のようになっていて
pyファイルの指定としては相対パスかフルパスで指定しても使えます。

上記1,2の工程を踏まえた上で登録したショートカットを使うと
登録したスクリプトが実行されます。

レイアウト設定について

つづいてレイアウト設定について説明します。
基本的にはメニューにある[Layout]で登録できますが
Layout設定自体もテキストベースで保存されているため
中身を変更することで詳細にレイアウトを変更することができます。

メニューの[Layout]項目内で作ったLayout設定については
以下の場所に保存されています。

MB2010の場合
 C:\Users\[ユーザー名]\AppData\Local\Autodesk\MB2010\config\Layouts
MB2013の場合(MB2011以降)
 C:\Users\[ユーザー名]\Documents\MB\2013-x64\config\Layouts

通常のレイアウト項目でMB上のレイアウトを登録する場合では
できないTabウィンドウ化が設定テキストを書き換えることで可能になります。

例えばRenderウィンドウを下にあるウィンドウに追加してみます。

レイアウトの設定ファイルを開いて以下の部分を変更します

以上の設定をするとRenderウィンドウがTabで追加されます

またレイアウト登録ですが
UIのあるスクリプトも登録することができます。
その場合登録したいスクリプトをPythonStartUpFolderに登録されたアドレス内においておく必要があります。

PythonStartUpFolderに置いてあるスクリプトを実行してレイアウトを設定すると
レイアウト選択時に配置されます。
またレイアウト設定ファイル内にも記述されているためTab化等の詳細設定をすることも可能です。

注意点として弊社ではMB2013でUIスクリプトをスタートアップに登録すると
起動時にウィンドウが壊れる不具合がありました。
MB2013SP1以降に更新することで修正されていることを確認しています。

最後に

以上、MBのカスタマイズについて簡単に説明してきました。

これらの設定を行ってもアニメーションには劇的な変化があるわけではありませんが
日頃からずっと使い続けるツールに関してカスタマイズをすることで効率よく作業できます。
最初一通り設定をするのは中々面倒かもしれませんが
一度やればずっと使っていけるので
是非自分流のカスタマイズを探ってみてください。

ではまた。

MayaでsiToon!

$
0
0

ど~もお久しぶりです。
流石にそろそろぽかぽか陽気になって欲しい開発室ゴトー[@jackybian]です。

今回はMayaでの輪郭線についてのお話です。
レンダラーにもよりますが輪郭線はデプスやノーマルの差が閾値を超えている箇所などに線を描画するものが多いかと思います。
実際に輪郭線を使うに当たっては、線の太さ、線の色、深度による線の太さ、線を出す出さないなど色々と調整したくなります。
Mayaにも標準でContourシェーダーがありますがこのあたりを色々調整して使おうとするとなかなか…なんですよね~。
本来なら使い勝手のよいカスタムContourシェーダーを開発してといきたいところですが、時間もないしなぁ。
Softimage(以下SIと略)のToonみたく調整できたらなぁとググっていたら某フォーラムに
”XSI Toon for 3dsmax”なんてのが載ってるじゃないですか!むむむ。こりゃMayaでもいけるでしょ!という訳で
今回は”MayaでsiToon!”をご紹介しようと思います。

SIのToonシェーダーと言えば、元々かのマイケル氏が作ったもので
Toon Paint, Toon Host, Toon Ink Lensなどのシェーダーから構成されています。

今回は輪郭線ということでToon Ink Lens, Toon Hostの2つをMayaで使えるようにします。
残念ながらToonシェーダーのソースコードは提供されていませんが、
MayaもMentalrayが使えるのでSIのdllをそのままMayaで利用するわけです。
ただしSIのToonシェーダーはmiではなくspdlという独自形式で成り立っていますので
Mayaで使う場合、別途miファイルを作成してやる必要があります。と言う訳で、

●いざっ実践!

①【spdlファイルをmiファイルへ変換】
RenderTree内でそれぞれのシェーダーを選択した状態でRMBメニュー⇒Edit Shaderを実行すると
Shader Code Editorでspdlファイルが開かれます。

spdlファイルにはシェーダーがもつパラメータやレイアウトなどの情報が記述されています。
この中でmiファイルへの変換に必要な情報は、PropertySet “sitoon_ink_params”{}内のinputパラメータです。

ここでパラメータ名、型、default値などを確認することが出来ます。
これらinputパラメータを全てmiファイルのフォーマットで記述すると
[cpp]
declare shader

color “sitoon_ink”
(
boolean “bypass”,
boolean “ct_only”,
integer “ct_only_surface”, #: default 1,
color “color”, #: default 0 0 0 1,
integer “mix_mode”,
scalar “spread”, #: default 2,
integer “spread_absrel”,
integer “spread_rel_xres”, #: default 720,
scalar “aniso_angle”,
scalar “aniso_mag”,
scalar “n_taper”,
integer “n_taper_vec_select”,
integer “n_taper_space_select”, #: default 1,
vector “n_taper_vec”,
scalar “n_taper_profile”, #: default 0.5,
integer “n_taper_profile_math”, #: default 7,
scalar “n_taper_dir_min”,
scalar “n_taper_dir_max”, #: default 90,
scalar “n_taper_spread_min”, #: default 1,
scalar “n_taper_spread_max”,
scalar “z_taper”,
scalar “z_taper_profile”, #: default 0.5,
integer “z_taper_profile_math”, #: default 7,
scalar “z_taper_dist_min”,
scalar “z_taper_dist_max”, #: default 100,
scalar “z_taper_spread_min”, #: default 1,
scalar “z_taper_spread_max”,
scalar “trace_taper”, #: shortname “trace_taper” max 1.0
integer “max_samples”, #: shortname “max_samples” min 0 max 30 default 5,
integer “max_trace_depth”, #: shortname “max_trace_depth” min 1 max 5 default 2,
boolean “detect_obj_bg”, #: default on,
boolean “detect_obj_obj”, #: default on,
boolean “detect_mat_mat”, #: default on,
boolean “detect_paint”,
boolean “detect_transparency”,
boolean “detect_shadow”,
boolean “detect_facet_enable”,
boolean “detect_facet_merge_coplanar”,
scalar “detect_n_delta_min”, #: default 30,
scalar “detect_n_delta_max”, #: default 90,
scalar “detect_z_delta_min”, #: default 1,
scalar “detect_z_delta_max”, #: default 1,
scalar “detect_delta_fade_amount”,
scalar “detect_delta_fade_dist_min”,
scalar “detect_delta_fade_dist_max”,#: default 100,
boolean “host_mat_only”,
scalar “near_epsilon”, #: default 0.05,
integer “aperture”, #: default 1,
boolean “state_modify”, #: default on,
scalar “variation”,
vector “variation_frequency”, #: default 10 10 10,
scalar “variation_animation”,
integer “variation_basis”,
integer “variation_space”,
scalar “variation_profile”, #: default 0.5,
integer “variation_profile_math”, #: default 7,
scalar “variation_var_min”,
scalar “variation_var_max”, #: default 1,
scalar “variation_spread_min”, #: default 1,
scalar “variation_spread_max”,
boolean “pressure_s_enable”,
scalar “pressure_s_org_min”,
scalar “pressure_s_org_max”, #: default 1,
scalar “pressure_s_dest_min”,
scalar “pressure_s_dest_max”, #: default 1,
boolean “pressure_v_enable”,
scalar “pressure_v_org_min”,
scalar “pressure_v_org_max”, #: default 1,
scalar “pressure_v_dest_min”,
scalar “pressure_v_dest_max”, #: default 1,
boolean “pressure_a_enable”,
scalar “pressure_a_org_min”,
scalar “pressure_a_org_max”, #: default 1,
scalar “pressure_a_dest_min”,
scalar “pressure_a_dest_max”, #: default 1,
boolean “bg_comp_enable”,
color “bg_comp_color”, #: default 1 1 1 0,
boolean “fisheye_enable”,
scalar “fisheye_amount”, #: default 1,
scalar “fisheye_scale_x”, #: default 1,
scalar “fisheye_scale_y”, #: default 1,
boolean “fisheye_scale_uniform”, #: default off,
boolean “bulge_enable”,
scalar “bulge_amount”, #: default 1,
scalar “bulge_scale_x”,
scalar “bulge_scale_y”
)

version 3
apply lens
scanline off
trace on
#: nodeid 335001

end declare
[/cpp]
となります。同様にsitoon_hostシェーダーも変換した行をこの後に追記した上で、”sitoon.mi”として保存します。

②【miファイル,dllファイルの配置(Maya2013の場合)】
sitoon.mi(①で作成したファイル)
 ⇒ …\Maya2013\mentalray\shaders\include
sitoon.dll(Softimageのインストールフォルダ\Application\bin\nt-x86-64)
 ⇒ …\Maya2013\mentalray\shaders
へコピーします。

実際にはシェーダー毎のAETemplateも作成してラベルやレイアウトを整理しますが今回は割愛します。

という訳でMayaを起動してHyperShadeで確認してみると

こんな感じで使えるようになります。ただし一部の機能はMayaでは動作してませんでした(´Д⊂ヽ 
まっそもそもが動作保障対象外の使い方ですから仕方ありませんけど。いつかソースコードが提供されたらステキなのになぁ♪

SIのtoon Inkを使ったことがある方は分かると思いますが標準のContourに比べて色々な調整機能が備わっていますので
バリエーションに富んだ表現が出来ると思います。墨絵的な何か?とか。

SIもMayaも使っている方で標準Contourだとちょっと物足りない方はトライしてみてもいいかもしれませんね。
という訳でお時間がきたようなので今回はこのあたりで。では(´∀`*)ノ マタ~

※免責事項※
本記事内で公開している全ての手法・コードの有用性、安全性について、当方は一切の保証を与えるものではありません。
これらのコードを使用したことによって引き起こる直接的、間接的な損害に対し、当方は一切責任を負うものではありません。
自己責任でご使用ください

3Dスキャナーサンプルデータ

$
0
0

弊社の3Dスキャナーを使用して撮影されたサンプルデータは下記のリンクからダウンロードできます。
データは、
Autodesk Maya2012の.maデータ
.objデータ
.fbxデータ
を一パッケージにまとめております。
※ファイルサイズ 185MB
サンプルデータのダウンロードに際しまして事前に下記びの使用許諾に関する注意をご確認頂き、
内容に承認頂いた方のみダウンロードをお願い致します。


このサンプルデータ(以下「本データ」といいます)の利用は、閲覧利用目的に限定します。
本データの第三者に対する譲渡・貸与その他あらゆる二次利用は、肖像権を侵害することとなります。
万一上記条件に違反して利用していることが発覚した場合には、肖像権者より請求される賠償内容に認諾することを予め承諾していただきます。
また、本データをダウンロードすることによって、利用者のパソコン等に不具合が生じたとしても、その損害について当社は一切責任を負いません。
以上の内容に同意することを条件に、本データのダウンロードを許諾します。
なお利用者は本データをダウンロードすることにより、上記条件に同意したものとみなします。
もし、上記条件を確認の上、同意できない場合は本データをダウンロードしないでください。




3Dスキャナー レポート

$
0
0

デジタル・フロンティアでは、フォトリアルな人物や造形をより効率よく制作する為に、2011年より
4d dynamics社が開発、販売している3D Scannerシステム「Mephisto 3D Body Scanner EX-Pro」を導入しました。
今年の1月に放映されたBSフジ「ジャパコンTV」の中で弊社のスキャナーを題材に取り上げて頂きましたが
こちらでもご紹介したいと思います。

弊社のスキャナーシステムは、形状を撮影する為のカメラ、形状の起伏を縞模様で表現する為のプロジェクター
テクスチャー撮影用の一眼レフカメラ、ラップトップの組み合わせで構成されています。

通常人物の全身を3Dスキャンするには、被写体全体を撮影エリアに含む為に非常に大きな設備が必要でした。
しかし弊社の3Dスキャナーでは、被写体の大きさや状況に合わせて組み立てる事が出来るだけでなく、
映画の衣装の様な、持ち運びが困難な場合であっても、撮影所までスキャナーを持ち運ぶ事で容易に撮影が行えます。
http://www.dfx.co.jp/dftalk/?p=4201
こちらの記事にて紹介している弊社イベントでは、2m以上もある大きな怪獣もスキャンし3Dモデル化する事が出来ました。
また、カメラのレンズや位置のレイアウトを変える事により、あるカメラは上半身にフォーカスしより高解像度に、
その他のカメラはワイドレンズで死角が生れないようにカバーするといった調整が行えます。

衣服の皺や形はもちろんのこと、レースやニットなどの素材感も非常に高精細にスキャンする事が出来ます。
3D スキャンデータを活用する事により、被写体の素材のデティールを活かすことが可能です。

また弊社のスキャナーの特徴は、1台につき約3秒、4台を合計しても約12秒ほどで撮影が行える為、
撮影中に被写体が動いてしまうことで起こるノイズも最小限に抑えることが出来ます。
また内蔵されているソフトウェアによって被写体の動きを検出しノイズを撮影と同時に除去することが可能です。
弊社のスキャンで撮影されたデータには、同じく4d dynamics社が開発しているポスト処理用のソフトウェアによって
不要な部分が取り除かれ、穴などの不正なポリゴンも最適化された状態で出力する事が可能です。

近年では、3Dスキャンされたハイポリゴンデータを映像用途に適したポリゴン状態に容易に再編集できるソフトウェアも
多数販売されています。今までに比べ3Dスキャンを作品の中で使用することも容易になってきました。
是非一度弊社のスキャナーで撮影したポリゴンデータをご覧頂ければと思います。
下記のリンクでサンプルモデルのターンテーブルをご確認ください。
今回のレポートでご紹介しているこちらの女性のサンプルデータはこちらよりダウンロード出来ますので是非ご覧ください。
http://www.dfx.co.jp/dftalk/?p=8003

弊社の3Dスキャナーに関するご質問等ございましたら、こちらまでお寄せください。
お問い合わせ先

3D Scanner Report

$
0
0

Digital Frontier installed 4DDynamics Mephisto 3D Body Scanner EX-Pro in 2011 to create photo realistic figures more efficiently. While the system was featured in Fuji Satelite Broadcasting (BS FUJI) in January of 2013 on a show called “Japacon TV”, we would like to give you a brief introduction about the scanner here.

The scanner system is made out of several objects; cameras that capture the shape of the object, projectors that project straight lines onto the object to distinguish the object surface, DSLR cameras that capture object texture, and laptops for control and display.

Until recently, scanning a complete body required a large facility. However, our 3D scanner allows us to adjust the size of the scanning device depending on the object. Since setting up the system is fairly simple it can be brought to other studios.
http://www.dfx.co.jp/dftalk/?p=4201
In the article above we scanned a creature over 2m high to create a 3D model from the data.
By adjusting the position of the lens and the overall layout we can have one high resolution camera scan the upper body and use a wide lens for the rest to avoid getting blind spots.

The scanner not only scans wrinkles and shapes but also the fine lace and nit textures of the fabric with great precision. By using the 3D scanner data we can collect detail information about the object.

In addition, this scanner can capture the object in 3 seconds per camera. Since it can scan from all four corners in 12 seconds we can minimize the data noise caused by the model’s slight movements that may occur during the scanning process. The data noise is then deleted by the software and using 4DDynamics postproduction software we also delete the blank areas around the figure object. Polygon errors such as these holes on the scanned data are cleaned up.

Recently there are several softwares in the market that allow us to edit the polygons of 3D scanned data for specific use. It is now easier to use 3D scanners in projects. We hope you have the chance to see our polygon data of our scanned image.
You can download sample data which I’ve shown you on this page.
http://www.dfx.co.jp/dftalk/?p=8052
If you have any questions regarding the scanner, please feel free to send us a message.
Contact

[DF Spotlight] 田淵玲児 ~ 「おおかみこどもの雨と雪」について

$
0
0

DF SpotlightDF Facebookの新しいコンテンツとしてデビューした「DF Spotlight」。
ここでは、普段のTECH TALKとはまた一味違うコンテンツをご紹介しています。

今回は、シニアアーティスト兼DFセットアップチームリーダーの田淵玲児さんにSpotlight。
田淵さんの自己紹介と彼がリーダーを務めているDFセットアップチームの紹介はFacebookで公開中!ここでは、彼が担当した作品の中で一番印象に残ったアニメーション映画「おおかみこどもの雨と雪」に関してちょっとしたメイキングをご紹介します。



【過去作品について】

過去に携わった作品で思い出深いアニメーション映画「おおかみこどもの雨と雪」の仕事について紹介します。
仕事の内容はカーテンが出てくるカットのClothSimulation。
作品の見せ場の一つで、作画に合わせてタイミング良く風を吹かせ、人物を隠すというのを
何度か繰り返すという、少し特殊なSimulationカットです。

要望としては
①カーテンの真ん中辺りで風を含ませて下へ抜けていく感じ
②風の当たっている箇所は皺を無くす
③アニメを意識してリアルに成り過ぎない
というものがありました。

まずは風の当て方ですが、ForceのWindにアニメーションをつけて当ててみます。

カーテンの全体に風の影響が受けてしまい、全く要望通りの動きにはなりません。
ここで使用したのがAttenuation Sphereです。
Attenuation Sphereだと影響範囲を移動させられるので効果的でした。

動画では横に移動させていますが、実際はSphereを下斜めに動かし、抜けて行く感じにします。

次に風が当たっている箇所の皺を無くしていく事ですが、
作業期間も短かったため擬似的に皺を無くす方法を取りました。
そこでやったのが下図の仕込み

SimulationしているMeshにLowMeshのPolygonをWrapしたものとBlendShapeを組み合わせる事で
皺を無くす箇所を自由にコントロールできるようにしています。
この皺の無くなる影響をコントローラで移動できるようにExpressionを組むとこんな感じ↓になります。

これとWindを組み合わせると、大体要望通りの動きが作れます。

後はBlendShapeの影響範囲とカーテンの硬さ、AttenuationSphereの動きを調節すれば完成です。

こういったカットを10カット前後、時間が無い中で仕上げないといけなかったので、
Try&Errorを少なく、イメージ通りの動きを作り易い仕込みが要求されました。

自分が携わった中では初のアニメ映画だったので、絵を作る際にいくらでも嘘がつける事に
驚きと気楽さを感じ、かなり楽しみながら作業が出来た作品ですね。

おおかみこどもの雨と雪
(C)2012 「おおかみこどもの雨と雪」製作委員会   監督・脚本・原作:細田守  スタジオ地図作品

[DF Spotlight] Ryoji Tabuchi – On “Wolf Children”

$
0
0

DF SpotlightDF Spotlight is an extension of DF’s Facebook initiative. Here we introduce content made specifically with our Facebook audience in mind.

In this edition, we aim the Spotlight at senior artist and DF’s rigging team leader Ryoji Tabuchi. Check out our Facebook for Ryoji’s self introduction as well as an introduction to DF’s rigging team! Here you’ll find a small “making-of” from Ryoji about an especially memorable project for him, the anime feature film Wolf Children.



【Regarding my previous works】

Wolf Children was a distinctly memorable project for me.
Here I’d like to present some ClothSimulation work I did for a shot in Wolf Children that involved movement of curtains.
Curtains, you say? Yes, curtains.
These were particularly important curtains, where the wind had to blow at just the right timing so as to hide a specified character, and this movement had to be repeated a number of times.
It actually makes up one of the most important scenes in the film!

The direction was as follows:
①The wind blows in towards the middle area of the curtain and passes through the bottom 
②There should be no wrinkles in the curtain where the wind is touching 
③The look should have an anime feel to it, avoiding looking too realistic

First up – making the wind blow. I tried adding animation to Wind under Force.

As you can see, the entire curtain receives the effect of the wind, completely missing the first point of direction we received.
This is where I decided to use an Attenutation Sphere.
This allowed me to change and move the area where the effect was applied, giving me the look I needed.

Here the sphere is moving horizontally – however for this shot I animated the sphere at a downwards tilt, passing through the bottom of the curtain.

Next, we’ll take a look at getting rid of the wrinkles in the curtains where the wind is touching.
As we were on a tight schedule, I used a method that made it appear to get rid of the wrinkles, as you can see below:

I combined a BlendShape with a Mesh that itself was Wrapped with a LowMesh Polygon.
This way, I was able to freely control the areas where I wanted to get rid of the wrinkles.
I then created an Expression to adjust this effect using a controller, which you can see below:

By combining this with Wind, I was able to achieve the basic look that was requested.

All I needed to do then was adjust the effect area of the Blendshape, the curtain’s hardness, and the movement of the AttenuationSphere, and my work here was done.

There were about ten or so shots similar to this one, and all of them had to be accomplished on a tight schedule.
As a result there was little room for trial and error – my job was then to achieve the required look in the most simple way possible.

This was the first anime film I worked on, and I found it very surprising and somewhat relieving that I could so often “cheat” my way to get the desired look.
It was an extremely fun and extremely educational experience!

Wolf Children
(C)2012 “Wolf Children” Film Partners  | Direction/Screenplay/Story: Mamoru Hosoda | a Studio Chizu production

Houdini Smoke Solver part1

$
0
0

お久しぶりです。開発の吉田[タック]です。 最近Houdini12.5が出てから、もっと注目されようになった気がします。
4月のユーザー・ミーティングで結構な人が集まってました。特にFLIPのFluid Solverが新しくなり、スケールが大きいFluidに対応したり、OpenVBに対応したり、雲と海の機能追加もされています。

エフェクト人にたまらない項目ばかり…

そこで軽くHoudiniのVolume Field Solverを紹介し、Part2で実際使った例を紹介したいと思っています。
今回Part1ではSolverを理解し、ノードの概念を少し説明します。まだHoudiniを始めたばかりですが…
 

SOP vs DOP

Surface Operator(SOP)はGeometryを作るためのノードでDynamic Operator(DOP)はDynamicsを行うためのノードになります。実際、Particle Operator(POP)を使ってDynamicsも行えますが、今回はスルーします。
簡単に言いますとSOPでVolumeの形やそこに入れる煙を作り、作ったSOPをDOPでシミュレーションを行います。
 

Gridとは?

SOPとDOPでGridは何か?

HoudiniではSOPのGridはVolumeと呼ばれ、そのVolumeをDOPでFieldとして使います。
Fieldの種類としてScalarとVectorがあります。
Scalarの場合はGrid1つの箱(Voxel)に対し、1つの値を持てて、Vectorの場合は3つになります。
 

Fog Volume vs Signed Distance Field(SDF)

オブジェクトがVoxelに入っているか、入っていないかの計算が2つあります。

Fog Volumeでは0か1、1が入っている、0が入っていない。
SDFでは値がマイナスでは存在している。プラスでは存在していない。
SurfaceのエッジをFog Volumeより細かく出来るのがメリットです。
 

Houdiniで

先にVolumeを作って、それに対してDynamicsを行います。

①Volume

Volumeノードを直接作ったり、GeometryをVolumeに変換したり出来ます。
Geometryを変換する時、isooffsetやfluidsourceを使ったりします。

②Dynamics

DOP networkノードを使ってDynamicsを行います。

DOP networkノードにこのようなNetworkを組みます。

左側のData chainでは作ったSOP Volumeを使い、Fieldとして扱います。
右側のSolver chainではDynamicsに関するノードを準備します。
Multisolverでまとめ計算を行います。

Advection(移流)

Solver chainの方でgravityや風とか作りますがAdvection(移流)も追加したりします。
Advection Typeは3つ用意されています。
    1. Single Stage: 1パスadvection
    2. Modified MacCormack: 2パス advection, 計算エラーを削減しもっとシャープなfluid結果が得られます。
     ゆっくり動くFluidでの結果はいいですが、早く動くFluidほど結果が化けます。
    3. BFECC:3パス advection, さらにシャープな結果。早く動くFluidで一番いい結果を得られます。
     でもその分時間がかかります。

ここで終わりと言いたいところですが、Divergenceの問題が残っています。
Volumeの全体にdensityが流れていかない。

Divergenceを0にする必要があります。

それを行うのに3つのノードが用意されています。
    1. Gas Project Non Divergence
    2. Gas Project Non Divergence Multigrid: 早い、collisionやfree surfaceに対応していない。
    3. Gas Project Non Divergence Variationa: 角度があるところでvelocity fieldの計算がベター。
     角度があるところで階段ができにくい。collisionやfree surfaceに対応していない。

今回はここまでにしておきます。
Part2を楽しみにしてください。
では!

Viewing all 131 articles
Browse latest View live