月別アーカイブ: 2009年10月

何回分割すれば原子になるか

たまたま SubD を何ステップまで実行できるか、という話になりました。
せいぜい 10 くらい?とか考えていたら、ツール上では 128 までいけたとか!
そんなの想像も付かない、と思ってよくよくきいたら、やはりツール内部で上限値が
設定してあったそうです。

128 ステップだと 1ポリゴンが 10 の 77 乗個に増えると言うこと。
1 辺の長さは 10 の 38 乗 分の 1 。

想像できないので計算してみた。

例えば 1 ポリゴンを 1m 四方とみなして作ったとして、
34 ステップもやればすでに原子レベル、
50 ステップ目では陽子中間子のサイズをも下回ります。

10km 四方の範囲もわずか 60 ステップで原子核に突入です。
この段階ですでに地球丸ごと作っても分子レベルでレンダリングできます。

全然追いつきません。
いっきに 1光年の範囲に広げても桁が 16個減るだけです。
1 光年も 87 ステップでは原子のサイズ。

宇宙の端から端をおおざっぱに半径 500 億光年としても
123 ステップで原子の領域となりました。

よって 1 ポリゴンを再帰的に Subdivision Surface で細分割していったとすると、
128 ステップ実行すれば宇宙全体を原子よりずっと小さいサイズまで砕くことが出来る。

という、そんなどうでもいい話でした。

よく考えると 2^128 って 32bit 浮動小数の指数範囲を超えています。

画面を歩く虫がバグの元

光学式タッチパネルは些細なことでも反応します。
そばに置いたコンビニの袋の取っ手が画面に触れただけで、スリープが解除されたりもします。

マルチタッチ対応 HP IQ800 を長いこと机の上に置いてますが、
袖が触れたり、書類の端が触れたりすると敏感に反応。
電源が入ったり、気がつくとクリック音が鳴り続けていることがあるのです。

今日の犯人は虫でした。
突然スリープから復帰したと思ったら、よく見たらマウスカーソルが勝手に動いている!
小さな蜘蛛くらいの虫で、ぴったりトレースしてマウスカーソルが付いていく様は面白い。

でもタッチパネルだからクリックされていることに…
場所によっては勝手にダイアログのボタンが押されたり、
勝手にプログラムを起動したり、
勝手にブラウザのリンクに飛んだりする可能性もあるわけですね。
慎重な作業中は 虫 にも注意。

取りあえず今度 ペイント の上を歩かせてみます。

Direct3D ファントムダストのオブジェクトスペースノーマルマップ

また今更な古い話なので興味ない方は無視してください。(前回)

当時 CG WORLD の 2004 年 9 月号を見た人から、キャラに object space (OS) の
ノーマルマップを使っているのはなぜかと良く聞かれることがありました。
それを思い出したのでちょっと書いてみます。

●理由

Phantom Dust は、シーン全部にほぼノーマルマップまたは同等の重いシェーダーを
適用しています。

Xbox は Shader Model 1.x 世代なので、Pixel Shader は 9~12bit の低精度な
固定小数だし 8 + 4 stage という命令数制限もありました。
この制限の中に必要な機能を詰め込むにはかなり工夫が必要です。

逆に頂点シェーダー側は浮動小数演算だし命令スロット数も比較的余裕はあります。
でも頂点演算はタイトです。シェーダーが 1命令 (0.5 cycle) 増えただけで描画速度に
大きく響きます。

PixelShader
・命令数制限、演算精度が厳しいので、必要な機能を入れるだけでぎりぎり。

VertexShader
・描画速度にかなり影響が生じる。機能的には十分だが速度的には余裕がない。

キャラクタ用シェーダーの頂点は、スキニング処理が入るためただでさえ負荷が高く、
頂点データも index と weight の分だけ多くなります。

 ・頂点のデータ量を減らしたい
 ・演算量を減らして高速化したい。

よって最適化のために、キャラクタ用シェーダーではオブジェクトスペースのノーマル
マップを使っています。
速度だけでなくメモリを大量に消費することもノーマルマップでは大問題でした。

●計算

オブジェクトスペースで作られたノーマルマップは、シェイプの変形に柔軟に追従する
ことが出来ません。
そのため、法線をテクスチャに焼き込んだ形状が保存されない Maya 等のツール上では、
オブジェクトスペースのノーマルマップではアニメーションすることが不可能となります。

しかしながら焼き込んだ形状が保存されていて、かつ変形したジオメトリとの差分が求まるならば、
オブジェクトスペースのノーマルマップから変形後の法線を導き出すことが出来ます。

ボーンによるアニメーションでも全く同じことです。基準となるバインドポーズを持っていて、
ツールから出力されるメッシュはこの形状を保ったスタティックなものです。

スキニングの演算自体が、骨の移動に従った基準形状からの各頂点の変化量を求めていることに
なります。このマトリクスがそのまま使えます。

Blend された Local to World matrix をそのまま使うだけ

Phantom Dust では光源ベクトルを逆変換しているので、頂点で求めた Local To World
Matrix の逆行列 (3×3) を光源に掛けます。
これが各頂点毎の Local 空間 (OS) なので、サンプリングされたオブジェクトスペースの
ノーマルマップを使ったライティングを行えます。
基本姿勢の OS を Os0 とすると、光源を World → Os → Os0 と変換していることに
なります。

頂点に Tangent Space の Matrix を埋め込まなくて済むので、こちらの方がデータ量として
かなりお得です。Tanget Space への変換分だけ演算負荷が減るし、頂点サイズの縮小も
そのまま高速化に繋がります。

ただしオブジェクトスペースでノーマルマップを作った場合は、以後絶対に基本となる
ポーズを変えてはいけません。Export 時に、ツール上でうっかり触ってずれてしまった、
とか許されなくなるわけです。

●ムービーレンダリング

プロジェクト終盤で困ったのがムービーのレンダリングです。
ゲーム内のキャラデータを使ってムービーシーンを作る必要があったのですが、次の理由に
よりそれが困難でした。

 (1) 法線マップのレンダリング方法
 (2) アニメーション変形

(1) 当時の Maya (4.5 あたり) には法線マップ用のレンダリング機能がなかったので、
そのままではレンダリングすることが出来ません。シェーディングノードを複雑に組み合わせて
Matrix 演算を行うことも出来ますが、いろいろ無理があります。

(2) 上でも書いたとおり、オブジェクトスペースのノーマルマップはツール上だと
元の形状からの変化量が求まらないのでアニメーション変形に対応することができません。

結局ムービーレンダリングのために専用のプラグインを作成しました。
プロジェクト終盤ではすでに RADEON 9700 が出ていたので、RADEON + ShaderModel 2.0
相当の OpenGL 機能を使っています。
OpenGL + ARB_vertex_program + ARB_fragment_program を使い、
Maya ビューポートへのリアルタイムプレビュー +
Maya ハードウエアレンダーバッファへのレンダリングを行っています。

確か条件分けは 3通り。

1. TS Normal map ではそのまま何もせずレンダリング可能。アニメーションも OK。

2. OS Normal map でも変形しない物ならそのままレンダリングします。

3. OS かつアニメーションを行う場合、プラグインに対して事前に基本形状を登録する
 必要あり。

3. では登録したメッシュを内部で記録して、Object Space のレンダリング時に参照しています。
これは Transform node (Matrix) ではなくメッシュ自体を丸ごと保存しています。
そのため実機と違い、ボーンアニメーションだけでなくシェイプアニメーションにも対応
出来るようになっています。

これが可能なのは OS だけど各頂点に Tangent Space 用の Matrix を埋め込んでいるから。
変形後の頂点から Tangent Space の Matrix が求まるので、そこから逆変換すれば
OS のノーマルマップから得た法線を TS に持って行くことが出来ます。
つまり頂点が持っている Tangent Space 変換 Matrix は 2つです。

Matrix1:  Ts → Os0
Matrix2:  Ts → Os

Os0 は基本形状の Object Space 、Os はアニメーション後の Object Space とすると
サンプリングした法線は Matrix1 で逆変換後 Matrix2 に適用すればよいことになります。

●背景

背景は Tangent Space (TS) です。地面や壁などバンプマップとしてタイリングするし
同じノーマルマップテクスチャを何度も使い回すからです。
貼られる面も任意となります。

●その後

あくまで昔の話です。キャラデータに OS のノーマルマップを使用したのはこのときだけ。
変形があるとデータの扱いが難しいし、その後のシェーダーでは PixelShader もかなり
高機能化されたので、ここまで考える必要がなくなりました。

Shader Model 2.0~3.0 の描画パイプラインの設計では、全く区別のない両対応をしたものの
結局キャラにも Tangent Space を使っています。

ただしツール内で生成された Tangent Space には互換性が無いので、最終的な
レンダリングプログラムと条件を一致させなければなりません。
結局自前のツールでデータを生成することになります。

Shader Model 4.0 以降は TS のみの対応としました。
シェーダーの基本機能として当たり前に使えるけど、その比重はさらに下がっています。
すでに Direct3D 11 の時代、Shader Model 5.0 ならなおさらでしょう。

関連エントリ
Direct3D ファントムダストと破壊の穴
3D一般 ノーマルマップの互換性問題(2) UVに潜む罠

NetWalker PC-Z1 カーネルのコンパイル

SD ブートで好きなだけ実験できる環境が出来たので次はカーネルをカスタマイズします。

●仮想マシン

Windows に VirtualBox をインストール。
あらかじめ Ubuntu 9.04 のインストール iso をダウンロードしておく。

VirtualBox で仮想マシンを [新規] 作成

OS タイプ: Linux
バージョン: Ubuntu または Ubuntu (64bit)
(64bit 仮想マシンに 32bit OS を入れてもかまわない)

RAM 適量 (HOST PC の RAM 容量と相談)
可変容量で新規ディスク作成 20GB くらい

仮想マシンが出来たらいったん [設定] を開く

[設定]
→ ネットワーク
  アダプタの割り当てを「NAT」から「ブリッジアダプタ」に変更

→ CD/DVD-ROM
 CD/DVD ドライブのマウント→iso イメージファイル
 仮想メディアマネージャーからダウンロードしておいた ubuntu の iso を選択
  ubuntu-9.04-desktop-i386.iso や ubuntu-9.04-desktop-amd64.iso 等

VirtualBox の「ファイル」→「環境設定」を開いてホストキーの確認
 入力 の中の ホストキー
 必要なら変更しておく。特にキーボードに右 ctrl キーがない場合は要変更。

作成した仮想マシンを起動して ubuntu をインストール。
右 Control キー、または設定したホストキーでマウスが HOST 側に戻る。
パーティショニングは「ディスク全体を使用する」にしておく。

●クロスコンパイル

下記ページを参考にさせていただきました。

ひまじめ 組み込みLInux

「ARMクロス開発環境構築」の手順に従い ARM EABI (armel) 用ツールをインストール。
設定したら gcc-4.3-arm-linux-gnueabi binutils-multiarch を入れます。
クロス開発用ライブラリはここでは不要です。

$ sudo apt-get install gcc-4.3-arm-linux-gnueabi binutils-multiarch libncurses5-dev

次は「ARM用Linuxカーネルをソースからビルドする」を参照します。
libncurses5-dev も install 。

NetWalker のカーネルソースとビルド方法は下記ページを参考にさせていただきました。

Android Zaurusの日記 NetWalkerのカーネルをリビルド

手順に従い上記ページ “*2” の場所から tar.gz をダウンロード。
解説の通りコンパイルしてみます。
CROSS_COMPILE は arm-linux-gnueabi- を指定。
config.gz はあらかじめ NetWalker の /proc からコピーしておく。

$ tar -zxvf linux-fsl-imx51_2.6.28-15.50fsl1araneo7.tar.gz
$ zcat config.gz > jaunty-arm/arch/arm/configs/netwalker_defconfig
$ cd jaunty-arm
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-  netwalker_defconfig
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-  menuconfig

menuconfig でオプション確認と変更
以前作った 「[Ctrl] と [A] の併用化」 を動かすなら下記を enable に
( space キーを押して ‘<*>‘ にする)

Input device support --->
  Miscellaneous devices --->
    <*> User level driver support
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-  zImage modules

できあがった arch/arm/boot/zImage を 起動確認用 micro SD の /boot に
ファイル名 zImage-10 としてコピー
/boot/boot.conf の最初のパスを zImage-10 に変更
microSD からの起動を確認。

あとはカーネルの設定を変更しつついろいろテストできます。

[Ctrl] と [A] の併用化 を試すなら

# wget http://dench.flatlib.jp/arfiles/ctrla.tgz
# tar -zxvf ctrla.tgz
# cd ctrla
# mknod /dev/uinput c 10 223
# ./ctrla /dev/input/event5

動きました。左手小指を使って Ctrl-H とか Ctrl-U とか使えています。
長かったけど、この設定を常用化できれば自分としては目的達成です。

関連エントリ
NetWalker PC-Z1 Debian (2)
NetWalker PC-Z1 Debian

NetWalker PC-Z1 Debian (2)

容量増やして NetWalker の Debian に gdm, gnome を入れてみました。
入れてみただけでまだいろいろ問題があります。
取りあえず SD からの起動で環境を切り替えを行うテストなので。

netwalker_d04.jpg

オプティカルポイントの左右ボタンでクリックがきかないのに、ドラッグでウィンドウの移動はできる。
クリックしつつカーソルをわずかに動かすとボタンも反応する。
タッチパネルは補正されてないので位置がばらばら。
USB の外付けマウスだと普通に使えます。

netwalker_d03.jpg

起動直後の gdm でキー入力できない場合あり。
ネット経由で gdm を restart するか、しばらくして gdm が勝手に起動し直せば直るようです。

関連エントリ
NetWalker PC-Z1 Debian