2009-06-28

[]PTAMテスト(その2) PTAMテスト(その2) - Nao_uの日記 を含むブックマーク はてなブックマーク - PTAMテスト(その2) - Nao_uの日記 PTAMテスト(その2) - Nao_uの日記 のブックマークコメント

PTAMとDirectXの連携について

今回のテストでは、PTAMでカメラ情報を取得する部分と、そのカメラ情報を使ってDirectXで描画する部分を別の実行ファイルとして作成してみた。PTAM側のアプリはWebカメラの画像からカメラの位置情報を生成し、描画側のアプリはそのカメラ位置をアプリケーション間通信のような形で受け取って描画のみを行っている。

PTAMのサンプルは非常にたくさんのライブラリに依存しているため、自作のDirectXの描画ルーチンに完全な形で組み込むのはとても手間がかかりそうだったので、このような手法を採ってみた。

この手法のメリットとしては、

  • PTAMのサンプルソースにわずかに手を加えるだけで、他の任意のアプリケーションでPTAMの機能を利用することができる
  • PTAMと描画アプリが非同期で実行できる
  • 描画アプリを再起動してもカメラの再キャリブレーションが不要

などがある。

DirectXアプリ側が必要とするのはカメラの位置だけなのでアプリケーション間通信といってもそんな大げさなことをやっているわけではなく、PTAMアプリが自分のウインドウのタイトルバーに文字列としてカメラ行列の内容を書き出し、DirectX側はそのウインドウを探して文字列を取得してカメラ位置に変換して使っているだけだったりする。PTAMが出力する情報の通信量が少ないため、このようなインチキ臭いやりかたでも十分に動いてくれている。

実際にPTAM側はほぼサンプルソースそのままにほとんど手を加えていない状態で、フレームごとにウインドウのタイトルバーにカメラの内容を文字列として吐き出す処理を追加したのと、デフォルトの目玉のモデルを表示しないようにコメントアウトした程度で、両方あわせても数行書き換える程度しか変更していない。そのため、もし将来的にPTAMがバージョンアップしても簡単に対応することができるはず。

DirectX側も既存のプログラムにPTAMのウインドウから文字列とカメラの画像を取得するコードを追加するだけなので、かなりシンプルな形で導入することができた。

2番目のメリットとして、もともと個別のアプリケーションとして動作しているため、PTAMの処理速度とは非同期にDirectX側の描画を行うことができる。

もしPTAMが15fps程度でしか動作しないような環境であっても、DirectX側の描画はカメラの更新速度とは無関係に60fpsを維持できる。カメラが大きく動かないような状況であれば、見た目には常に高フレームレートが維持できるためにとても効果的。

また、別アプリケーションになっていればOSが自動的にCPUの各コアに分散して実行してくれるため、プログラム側では何の工夫をしなくても勝手にマルチコア環境に適応して高速に動作してくれるのも、手間いらずで嬉しいところ。

3番目のメリットは、描画アプリ側を再起動したときにPTAMの再キャリブレーションが不要、という点。

もし単一アプリで作成していたなら、アプリケーションを再起動するたびにPTAMのカメラキャリブレーションが必要になってしまう。この操作は意外とシビアで、一回ではうまくいかないことも多いし、一度あわせた座標系を再現するのも難しい。アプリケーションの開発中は頻繁に再起動を行うことになるため、そのたびにキャリブレーションするのはとても面倒。

この手法であればDirectX側のアプリを停止してもPTAMアプリは以前の状態を保持したまま動き続けているため、再起動したときに動いているPTAMのウインドウから自動的にカメラ情報を取得しなおすことができる。

このような効果を意図してこの設計にしたわけではなかったけれど、パラメータやライトの微調整などで頻繁に再起動を行う必要があったので、これなしでは作業に余分な時間がかかっていたはず。この特性は地味ながらも開発効率の向上に貢献してくれていたように思う。

逆に、この手法のデメリットとして、

  • 画面の占有面積が大きくなる
  • フルスクリーンモードでは動かない

という点がある。

いろいろ試してみたのだけど、1つのWebカメラからの入力を2つのアプリケーションが同時に取得することができなかったため、仕方なくPTAMのウインドウの範囲をデスクトップキャプチャのような手法で取得した画像を、DirectX側のアプリのカメラ画像入力として使っている。

この手法だとPTAMのウインドウに何か別のウインドウが重なっているとカメラ画像に被って正常な絵が取得できないため、PTAMとDirectX側のウインドウをずらして配置しなくてはならないし、同様の理由でフルスクリーンモードで動かすこともできない。

DirectX側のアプリを半透明ウィンドウにしてPTAMに重ねる手法も考えたけれど、後々の自由度が低くなりそうだったので採用しなかった。バックグラウンドにあるウインドウの描画情報を取得できる方法があれば解決しそうなんだけど、あまりWindowsプログラミングには詳しくないのでとりあえずは現状のやり方で進めてみている。

今回やってみたPTAMと描画部分を別アプリにする手法をとることで、比較的簡単に既存のアプリケーションにPTAMを導入することができる。手軽にPTAMを触ってみたい、というような興味のある方には、このやり方をオススメしておきます。

追記:PTAMテスト(その3)