CEDEC2008 2日目

ちょっと色々事情があって実家に帰ってました。

何があったかとかは察してください。

それはともかく2日目。まずはカプコンの稲船氏の基調講演です。

すでに本職の人の記事が上がっているので書く必要もなさそうですが、とりあえず簡単にまとめて見ます。

稲船氏の講演の基本は”甘えるな!”ということ。クリエイターは甘えすぎだと。

クリエイティブとビジネスは相反する部分もあるけど、だからといって対立しててもいいものは出来ない。

矛盾するものを作れば売れるんだと。安くて美味いものなら売れるでしょ?

男にしても優しいけど頼り甲斐のある人のほうがもてるってのと同じだそうだ。

カプコンどん底の時、経営者には8?9割は続編を作れといわれたそうですが、これにはいと答えたとか。でも実際には逆にして、8?9割は新作にしようとしたとか。

そもそも、どん底にいるときのクリエイターは疲れている。それに続編作れといっても疲れるだけ。新しいことを!という方がクリエイターは喜びます。

それでも上は絶対を求めてきます。絶対売れるものを作れ、と。そういう時は嘘をつく。嘘も方便。

とにかく経営者もユーザーと同じように考える。ユーザーのことを考えるように経営者のことも考えるべき。

たとえば上場企業なら自社の株価をみる。株が下がるのはどういう状態か、上がるのはどういう状態かを考える。上がるように努力すれば経営者の気持ちもわかるだろうと。

ただし任天堂の株は別。任天堂ははるか彼方の存在だと。ですよねぇ。

クリエイターも作るだけでなく経営の方に関わっていこうよ、というお話でした。

1コマ目はコーエーの津田さんによる物理エンジンのお話。

コーエーでは物理エンジンを自前で作成していて、これを作ったときの理論や高速化、安定化の話も最後のほうで少しやっています。

そもそも自前で作成している理由として、物理シミュレーションを使った特殊な処理を作成するために基盤技術をブラックボックスにしたくなかったからだそうです。

最初は拘束のない剛体運動について。これはうちのサイトでもやっている慣性テンソルとかの解説をさらっとやっただけです。

それから拘束のある運動について。これが今回のメイン。コーエーの物理シミュレーションも剛体運動のコードの9割はこれについてのものだそうです。

拘束の解き方にはいくつか方法がありますが、今回は解析法が解説されました。これはたぶんODEで使われているものと同じです。

拘束にはジョイントによる等式拘束とコリジョンによる不等式拘束があります。そして、その等式、不等式は何に対して適用されるのかというと、昔は加速度が用いられていましたが、現在は速度が多いようです。

ボールソケットジョイントで接合された点 a,b があり、その速度を Va,Vb とすると、Va=Vb となります。コリジョンの接触の場合、接触面の法線を n とすると n・(Va-Vb)≧0 となります。これが等式拘束、不等式拘束です。

でまあ、この辺りから一般化速度(速度と角速度を並べた6要素のベクトル)やら質量マトリクス(質量と慣性テンソルを組み合わせた6*6行列)やらヤコビアン(異なる座標系の間で速度を変換する演算子)やら出てきます。

数式なんかもいっぱい出てきてるんですが、この辺りから理解不能になってきました。多体の物理くらいまで来ると何を言ってるのかさっぱり。

というわけで、資料参照。見ても判らない人は仲間。判る人は物理エンジンくらい作れるんじゃないかと思います。

Gauss-Seidel法は聞いたことがありますが、聞いたことがあるだけ。困ったね。

安定化と高速化についてはSlop(許容貫通誤差)、Permutation(行入れ替え)、WarmStart(前ステップ解による初期化)、Shock Propagationなどが簡単に解説されました。なんとなくわかるものもあるのですが、そこに行く前の段階で問題があるのでほとんど理解できず。すまぬ。

というわけで、物理エンジンを自分で作るのは難しいんだなぁ、と強く感じた講演でした。

2コマ目はMGS4の各種技術についての話です。これも本職の記事が上がっているので少し簡潔にまとめます。

HDRレンダリングは当初FP16でやっていましたが、フィルレートが低いこととMSAAが使用できないことから断念。エンコードレンダリングに変更したそうです。

エンコードレンダリングは、32ビットのうちのα値に輝度の逆数を格納して実際に使用する際に計算によって必要な値を計算するようにしています。

計算負荷は軽いのですが、α値を使用しているために直接半透明描画が出来ないという問題も抱えています。

これを解決するため、半透明、および加算合成のオブジェクトをブレンドバッファという別バッファに描画してあとで合成するという方法を取っています。

ブレンドバッファはHDRレンダリングできず、また、減算合成なども出来ません。ただ、減算については何とかなるかもしれないとは言ってました。

また、エフェクトの一部(手前側のもの)については1/4の縮小ブレンドバッファに描画しています。フィルレートの低いPS3では画面いっぱいの半透明オブジェクトは負荷が高く、これを解決するのが主な目的です。

なぜ手前のエフェクトに限定されているかというと、深度バッファの判定をミスしやすいためだそうです(手前は深度バッファの精度が高いためミスが減る)。

ライティングは影ありの平行光源と点光源を平行光源に変換した光源などに加え、環境光、リムライト、分離プリライトなどがあるようです。

環境光は半球ライティングですが、方向と適用範囲を設定できるようにしています。ツールは専用ツール。

リムライトは順光と逆光で別の効果が出るようにしています。順光はソフトライト、逆光はハイライトが出るようになります。

順逆の向きは半球ライトの軸を使っているそうです。また、そのバウンディングボックスに色々なデータを入力できるようにしています。

分離プリライティングは頂点に基準3方向のライティング結果を格納しておく方法です。基本的に静的なデータですが、初期化時に計算されるため、なんらかのライティングの変化があったときに再計算することでライティング結果を変更することが出来ます。

また、ライト数制限がないので、デザイナの力で間接光も表現できます。

ただ、品質はあまりよくないのと、RSXと相性が悪いのが少し問題のようです。

エフェクトは色々ありますが、それぞれで別の処理を行っています。

まず、血や水濡れですが、これは今までと同様に頂点カラーを使っています。テクスチャでやることも考えたようですが、他で色々使っているので難しい。

半透明の被せモデルは乗算合成が使えないので断念。結局、頂点カラーの各成分にそれぞれ血や水濡れを割り当て、その値を使って計算しているようです。

積雪エフェクトは半透明の被せモデルです。これはα値に積雪量を書き込み、αテストして終了です。合成の必要がないため被せモデルでも問題ありません。また、風の方向によって積雪する場所も変わります。

水面の波紋はシミュレートではなくそのままの波紋エフェクトを使っています。しかし、ただ表示するのではなくハイトマップに波紋テクスチャを書き込むという方法です。

ここでの工夫はこれをビュー座標で行っていること。これによる恩恵としては、見えない部分は書く必要がなくなることです。

DOFは錯乱円の計算式を用いてシミュレートしています。ただし、ゲーム中用の簡易版もあり。

サンプリングは19点で、六角形の絞りの形になるようにサンプリングしています。

問題はエンコードバッファで、デコードしてサンプリングは重いのでデコードしていません。そのため、当初のトレーラーのような映像は出せなかったようです。

カメラの手前に流れるようなフォグや砂煙を出すときは1/16の縮小バッファに描画しています。描画順番による矛盾は無視。

深度バッファはWバッファに変換してテクスチャ化しています。ソフトパーティクルの他、デカールに使用したり(通常、ポリゴン切断で行う処理だが、深度バッファを見て深度に開きがあるなら描画しないという方法で処理している)、グレネードの着弾点の描画(実際に描画しているのはスプライトらしい)に使っているそうです。

スクリプト言語は独自のGCLという言語。パラメータの設定、およびゲーム進行管理に使用しています。

日本語対応、C++プログラムとの変数共有、使用されているリソースを収集して自動ビルドまで出来ます。

リアルタイムムービーはポリデモと呼ばれ、アニメーションデータは時間軸で圧縮、フレーム単位でスライスされパケット化されています。これによりストリーミングが可能です。プレビューは実機。

問題点はゲームとのシームレスな移行が難しいこと、カット切り替え時の物理シミュレーションがおかしくなるなどです。

リアルタイム2DムービーはFlashで作成し、独自のシステムへ変換しています。

ただ、Flashの機能は一部しか使えず、アクションスクリプトも使えないらしい。

…簡単なまとめになってないよ、これ。

3コマ目はムームーの森川氏による遺伝的アルゴリズム(GA)の解説です。

GAやNNといえば森川氏はまさに先駆者といっていい方で、AIに興味がある人間としては聞いておきたい講義だったので。

最初はGAの解説で、これについては以前の三宅さんの解説とほぼ同じです。違いがあるとすれば、スライドが三宅さんのものに比べて見やすいことくらいですかね。

次にGAを使ったゲーム『アストロノーカ』を用いて実例を交えての解説。

そのうち資料なんかも公開されると思いますが、『アストロノーカ』で実際に行っている処理方法についてきちんと解説されています。

たとえば、パラメータの計算方法。これは8ビットの各ビットに別々の数値を割り当て、すべて足すと100になるように考えられています。

しかも0?100までの数値のうち、表現できない数値は4つぐらいしかないそうです。

交叉は三宅さんは1回と予想していましたが、実際には2回らしいです。

子を生んだ親はそのまま残し、最も成績の悪かった2つを消去するようにしているそうです。世代交代は1回のゲームで10代交代だそうです。

最後に自分のゲームにAIを組み込むべきかどうかという診断テストみたいなものが行われましたが、森川氏の言うとおり適当っぽいないようでした。

質問も興味深いものがいくつか出ていました。

まず、GAを選んだ理由ですが、GAの事がよくわからなかったからと言ってました。GAのことがよくわかっている現在ならGAを持ち出すことをためらうかも、ということでした。

デバッグについてですが、やはりこれは経験則でやるしかないとのこと。もちろん、それを簡単にするためのツールなどはあった方がいいでしょうけど、バランス調整はゲームによるとしか言えそうにないようです。

4コマ目は長谷川先生による衝突判定法についての講演です。

衝突判定を細かく見ていくとポリゴンとポリゴンの衝突などになるわけですが、これを総当りで行うのは当然のことながら遅いです。

まずはBroadPhaseとして、バウンディングボリュームのチェックを行うでしょう。

このとき、バウンディングボリュームの総当りを行う方法もありますが、それより早くなる可能性のある方法としてSweet&Pruneという方法があります。

ある軸(たとえばX軸)に対して各バウンディングボリュームの最大値と最小値を求めます。

そしてすべての最小値の中から最も小さい値を探し出し、ここから処理を開始します。

その最小値は対応するバウンディングボックスとともに保存され、これと同じバウンディングボックスの最大値が出てくるまで保存しておきます。

その間に別のバウンディングボックスが入ってきた場合、その2つのオブジェクトは接触している可能性があります。

もし、同一オブジェクトの最大値が入ってきた場合、そのバウンディングボックスは保存場所から削除します。

すべてのオブジェクトが削除されると終了です。もちろん、すべてのオブジェクトがX軸に対して重なっているようでしたら高速化にはなりません。

Sweet&Pruneを総当りの場合、オーダーは O(n^2) となりますが、QuickSortをしている場合は O(nlogn) となります。

このオーダーの計算は n が∞に向かった場合の処理の速さを相対的に表現したものに過ぎません。O(n^2) と O(nlogn) なら O(nlogn) の方が速いわけです。

なので、どんな場合でも総当りがQuickSortより遅いというわけではありません。アプリケーションで扱うデータの量によっては総当りのほうが速い場合もあります。

また、Sweet&Pruneを物理シミュレーションで用いる場合はInsertSortが有利です。通常は速い方法ではないのですが、前回のソート結果を用いることが出来るため有利となります。物理シミュレーションではあまり大きく位置関係が動かないためです。

UniformGridとBucketSortを利用するのも悪くないですが、1箇所に集まるようであれば遅くなってしまいます。このような場合は、集まった場所でまたUniformGridを用いるのがよいでしょう。

BSPの切断面についても、ゲームによる、としか言えません。ただ、個人的にはBSPってそんなに速いという印象がありません。

BVHの構築法としてはトップダウン法、ボトムアップ法、改良ボトムアップ法などがあるとか。この辺も資料を参照した方がいいかと。

さて、BroadPhaseで刈り込みを行った後はNarrowPhaseとしてポリゴン形状同士の判定を行います。

ポリゴン形状同士の衝突判定を取るライブラリは結構色々ありますが、物理シミュレーションを行う場合は衝突後の処理を行うのに必要な情報を取得できるものを選ぶべきです。

解析法を使うのであれば、接触点、法線、接触面が取得できる必要があります。

また、ポリゴン形状が凸形状であるほうが望ましい理由は、凸形状の場合は極小値が最小値となるためです。一般に極小を求めるのは簡単ですが、最小を求めるのは難しいのです。

基本プリミティブ同士の判定であれば幾何計算で求まるものも多いのですが、凸形状のポリゴンモデルともなると話は別です。

これらの判定を取る手法としてGJKアルゴリズムなどがあります。簡単に解説もされたのですが、図なしで解説するのは難しいよね…。

あとはConvexHull(凸包体)を求める方法としてQuickHullやAndrewのアルゴリズムが紹介されていました。この辺りはそのうちプログラムを書いて公開するかも。

最後にこの辺がいいよ、という本をいくつか紹介されました。

出版者とかよくわかりませんが、『プログラミングのための線形代数』、『計算幾何入門』、『計算幾何工学』がいいようです。

また、数式萌えを知りたいならということで『数学ガール』という小説も紹介されています。ちょっと面白そうなので、他の本と一緒に注文してみるかな。

2日目はこんな感じです。

このあとデベロッパーズナイトという懇親会があったのですが、そこに宮本茂さんが来てました。

生で見たのは初めて。ほとんどアイドル状態で、名刺交換、写真撮影、握手と大変そうでした。

途中で新さんが止めてました。まあ、ゆっくり話したいこともあるでしょうしね。

知り合い曰く、「仕事で名刺交換するのが目標」。がんばれ。