20人くらいのKinect hackingの集まりに行ってコードを書いてきた。コードを書いたといっても、実際には各種の既成部品の組み合わせに近いのだけど。
今回は、OpenNI.netで受け取ったKinectのユーザー認識情報をnode.jsのWebサーバ兼用TCPサーバに送り、WebSocketsを使ってブラウザ上のWebALを叩く、という試みだった(いわゆる誰得というものと言える)。残念ながらまだ見栄えの良いコードが出来たわけではないのだけど、とりあえずやったことを記録しておこう。
OpenNI.net : 今回はUserGestureを使うサンプルを想定していたので、libfreenectは使わなかった。そしてOSの制約でNITEパッケージが存在しない(non-Ubuntu) Linuxは選択肢に出来ず、結局Windowsを使うことになった。一方でOpenNI.netのunstable版に含まれるC# wrapperはどうにも64ビットWindows環境の.NET上で動作しない。というわけでランタイムはmono/WindowsだOpenNI.netの使い方はサンプルコードに含まれているWindows Formsのものを流用するだけで簡単にできた。
今回は、Kinectの使用は簡単なUserTrackingにとどめ、対象の中心座標を送ることにした。
node.js : 今回はKinectから受信したイベントをWebブラウザ上に反映させるので、WebSocketsを使ってプッシュ処理を行う。そのため、WebSocketsに対応したwebサーバが必要になった。とりあえず、Kinectでメッセージを受信したものをHttpListenerで処理することはできない(実は以前HttpListenerの実装に手を加えてWebSocketsを実装しようとしたことがあるのだけど、残念ながら途中で放置している)。C#環境なら実は例のAndroidのビルドサーバに使用しているHTTPサーバが数日前にWebSocketsにも対応していて、一番慣れているのだけど、Windowsでビルドできないので、先の条件と矛盾するので断念した。というわけで今回は次善策でnode.jsにした。
node.jsサーバでは、socket.io-nodeのWebSocketsサーバを結びつけたHTTPサーバと、net.createServer()で生成したTCPサーバを起動する。HTTPリクエストはstatic fileに対するアクセスのみなので、要求されたものをそのまま返す(今回はproof of conceptなのでセキュリティは完全に度外視している)。HTTPページの中には、WebSockets接続を確保するものがある。一方、KinectのメッセージはTCPサーバが受信する。そのメッセージはWebSocketsで接続しているクライアント宛に送信される。
SceneJS : Webページ側では、WebGLのキャンバスの視点を動的に変更するはずだったのだけど、そこまで到達しなかったので未実装。これはSceneJSを使用して、全く知らない3Dモデリングを、サンプルコードから見よう見まねで作ってみた。モデルの(オブジェクトの)ノードは、実際には音源(source)を配置した位置に何かしらのマークとして表示するためのものだった。
WebAL : これはFlashを利用してOpenALの機能をWebGLよろしくJavascriptのAPIとして実装したもので、まだkhronosのstandardのようなものがあるわけではない、非公式なものだ。今回はこれを使用して、初めてOpenALというものを(間接的に)いじってみた。コードとしては、(WebALのサンプルを流用しただけに近いけど、)ALのsourceを複数設置しておいて、Kinectから送信されたユーザーの位置をlistenerの位置として設定している...はずだけど、これもいまいち上手くいかずに時間切れになった。
これは、単に座標設定が良くないということはある(OpenNI/NITEで取得したUserTrackingのデータは、mm単位の浮動小数点で送られてくるので、その範囲は実際に自分で動いてある程度調整している)。ただ、WebALのlistenerのPOSITIONが機能していない可能性もある(sourceのPOSITIONは機能した)。これは調べてみないと分からない。
普段触れることのないものにいろいろ手を出してみたので、あまり目覚ましい成果は出なかったのだけど、その分いろいろ知ることが出来た。
https://github.com/atsushieno/kinecthack