March 2011 Archives

jQuery UIを使ってみた

| No Comments | No TrackBacks

大震災の後なかなか落ち着いてコードを書けることが無かったのだけど、ひさしぶりにwebアプリのコードに手を加えた。これまでJavascriptを全く使わずに実装してきたのだけど、jQuery UIを使って入力フォームにダイアログを加えてみた。

7,8年前のASP.NET 1.0の頃を最後に、Webアプリケーションを書くことが皆無だったので、jQueryを使ったことはあまりなく、jQuery UIも初めて使ってみた。今回使ったのはdialogだけで、他にflexigridのテーブルなども使ってみたのだけど、結局tableの代わりにlistを使うことにしたので不要になった。flexigridはドキュメント不足が多少引っかかるものの、ソースの初期化関数や使用例を眺めれば概ね使い方は分かると思う。

あと、jQueryのajax関数で呼び出せるように、サーバ側にJSONリクエストの処理を用意したのだけど、これがC#の列挙型と相性が悪くて少々困った。DataContractJsonSerializerという標準ライブラリのクラスでも、列挙型はまともに処理出来ておらず、動的なコードで特にデシリアライズしてうまくやるというのは厳しそうだ。

1日jQueryをいじっていて、ようやくjQueryの$()が返すオブジェクトには元のDOMオブジェクトのプロパティが存在しているわけではないということに気がついた。DOMのvalueプロパティがとれないのは、そもそも$()の戻り値がDOMオブジェクトではなく、またjQueryのオブジェクトに元オブジェクトのメンバー全てが反映されているはずはない(いちいちメンバーを追加するコストは膨大だ)、ということに、昨日ようやく気付いたわけだ。Javascriptの仕様から考えればとても納得のいく話で、ひとつjQueryのポイントを理解できたような気になったのだった。

kinect hacking

| No Comments | No TrackBacks

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

opentk.webgl ... not yet

| No Comments | No TrackBacks

WebGLに対応するAPI定義ファイルが出来たので、今度はいよいよBind.exeに手を加えてWebGLのC#バインディングを作成する作業に入った。しかしこれがたいへん面倒で、とりあえず1日で出来なかったので今はとりあえずあきらめることにした(他にもやらなければならない作業があるので)。

とはいえ、ここまででもそれなりの量の作業が行われたので、現状の差分(パッチと追加ファイルのセット)を置いておくことにした: http://dl.dropbox.com/u/493047/2011/opentk-webgl-files.tar.bz2

差分を適用すれば、生成されたコードも含まれているが、コード生成にも問題があるので、修正するためにはBind.exeを(おそらく全面的に)加工しなければならない。Bind.exeはOpenTK/Graphics/XXX 以下のファイル(の大部分)を生成するものだけど、webglサポートは、Bind/Specifications/WebGL 以下のファイルをもとに、Bind.exe -l:webgl -mode:WebGL を実行すれば生成されるようになっている。

コード生成のためには、WebGLGenerator.csという派生クラスのソースを作ったり、Generator.csやFuncProcessor.csにいろいろ手を加えたりしている。Silverlightプロファイルではunsafeコードが生成出来ないので、unsafeに依存している部分をばっさり変更しなければならないのだけど、ここが大変だ。P/Invokeでnative interopするために行われているのだけど、Silverlightの場合はScriptObjectのbrowser interopするためのコード(を生成するよう)に書き換える必要がある。

ちなみに、Bind/Specifications/WebGL/signatures.xml、は昨日のwebidlパーサをもとに生成されている。つまり、signatures.xmlを再生成したらこれを置き換える必要がある。(他のOpenGL/ESのsignatures.xmlはConverter.exeで生成されている。) Bind/Specifications/WebGL/overrides.xml は、ES20から引っ張ってきたものだけど、無駄なものが多いので結局ほとんどコメントアウトしてある。

コード生成の他に、Platform/FactoryやらGraphicsContextやらをWebGL向けに追加しなければならず、これにも苦労させられた。アセンブリと前提に出来るAPIが異なるため、Windows/Mac/X11用のバインディングなどはもちろん同一のアセンブリに組み込めないので、全て除外することになる。そうすると今度は依存クラスが足りずにビルドできなくなる...というのを試行錯誤して、とりあえず何とかNotImplementedExceptionを投げるクラスをいくつか追加するかたちで、この部分でのビルドエラーは全て解消できた。NotImplementedExceptionを投げる部分は、ビルドできるようになった後に再訪する必要がある。

...ともあれ、ここまでの作業はこれくらい記録しておけばいずれ時間が出来て気が向いた時に再開できるだろう。

webidl-sharp

| No Comments | No TrackBacks

WebGLのAPIに合わせたOpenTK APIを自動生成するためには、まずWebGLのAPIからOpenTKが使用する定義ファイル (signatures.xml) を生成する必要がある。WebGLのAPIはdraft specificationの中にあるWebIDLを解析することで得られそうだ。

ということで、今度はWebIDLの処理系を探してみることにした。が、これが厳しい探索になった。とりあえずjavascript版とruby版とhaskell版を発見したのだけど、javascript版は"long long"の解析に失敗し、ruby版はconstの16進数の解析に失敗した。haskell版はどうやら最新のghcではビルド出来ないようだ(hackageにそのようなビルドログがあった)。

仕方がないので、IDL程度の文法なら簡単に解析できるだろうと思って、Ironyを使って自分で実装した。実装してから気づいたのだけど、WebGL IDLでは定数のカテゴリをコメントで書いていて、Ironyで普通に実装したらコメントは削り落とされてしまう(たぶんこれは既存のどのパーサでもそうだっただろう)。とはいえIronyならコメントは削り落とさないように自分で修正できる(ただ、コメントノードをあらゆる場所でsignificantなトークンとして扱うのは無理があるので、特定のIDLファイルで実際に使われている部分だけ対応するしかない)。というわけで、汎用的なWebIDLパーサとは別に、WebGLのIDLの解析に特化したバージョンを作った。

ちなみに汎用的なパーサの方はパース以降は何もしないので、まだ実用性は無いと言っていい。WebGLの解析に特化したものについては、実行ファイルを作って、OpenTKのsignatures.xmlに相当するテキストを書き出せるようにした。この書式にも多少癖があるといえなくもないのだけど、とりあえず差分を見ながらいろいろ違いを埋めていって、現状ではそれなりに小さい差分に収まっている。

差分について見て取れるのは:

  • gl2ext.hに相当するAPI、つまりベンダー拡張のようなAPIは、(当然ながら)無い
  • GetPName列挙型の内容は、WebGLではいくつかの列挙型に分散している
  • IMGほげほげ列挙型は消えている
  • バッファなどに、汎用ポインタではなく、特定の型を活用している
  • BufferData関数などは、WebGLではオーバーロードで引数型に特化している(上記の項目に関連)
  • genほげほげ関数は、WebGLではcreateほげほげ関数になっている

...他にもありそうだけど、実のところOpenGLをいじったことが一度もないのでまだわからない。

とりあえず、今度はC#のAPIを生成する必要がある。まだまだ大変そうだ。そもそも出来るかどうか分からない。

ちなみに、ruby版webidlについては、バグレポートを送ったら即日修正してくれた。すばらしい。しかし上記のような事情で、残念ながら改めて使うには至らなかった。(そもそもrubyコードの生成に特化していることもあるかもしれないし、コメントも多分削り落とされているだろう。)