SOLUTIONモトスクウェアソリューションは、システム開発やイラスト制作などのIT関連業務を手掛ける個人事業です。XNA以前の記事で作成したKinectアプリのサンプル「DroidForKinectSample」を、夏コミで配布しようと思っていたのですが、バージョンアップしたKinectのSDKに同様のサンプルが同梱されるようになったため、もうモチベーションが下がりニーズはないだろうと思い、公開を見送っておりました...(T△T)ですが、ありがたいことに沢山のお問い合わせをいただいておりますので、同人誌をご購入いただいた方々を対象に、本サンプルのソースコードを公開させていただきます!ということで、まずは本サンプルのポイントから解説させていただきます~(≧▽≦)/プロジェクトの構成は?まずは、KinectのSDKに付属している純正のサンプルコード「Avateering-XNA」の構成をご覧ください(右図)。たくさんのソースコードがあって、何やらとても高度であろう印象を受けますが、私個人としては、こういうサンプルは読む気がしません。機能を付加するのもいいですが、サンプルである以上、やはり理解しやすいことが大切だと思うのです...。そこで、今回公開するサンプル「DroidForKinectSample」は、理解しやすいようにシンプルな構成にしています(左図)。いえ、膨大な行数のコードを無理やり集約しているわけではなく、余計な機能を極力省き、キネクトで3Dモデルを動かすために必要な処理のみを簡潔に実装しています。ちなみに、このサンプルは「Avateering-XNA」が公開される前に作成したものですので、アルゴリズムは異なるものの、プロジェクトの構成は偶然にもほとんど同一となっています。「SkinnedModelPipeline」と「SkinnedModelWindows」は、純正のサンプルにも含まれているプロジェクトです。これらはもともと「スキニングモデル」というサンプルのソースコードを流用したものであり、人体の様に繋ぎ目のない関節を持つ3DモデルをXNAに取り込めるようにするためのプロジェクトです。今回利用するドロイド君の3Dモデルも、一部の関節に繋ぎ目がありませんので、これらのプロジェクトを利用します。次に「DroidForKinectSampleContent」は、ドロイド君の3Dモデルを格納しています。この際、3Dモデルのプロパティから、先のプロジェクトで定義した「SkinnedModelProcessor」を指定します。いうことで、残る「DroidForKinectSample」がメインプロジェクトです。DroidForKinectSampleプロジェクトの内容は?まず「Program.cs」は、エントリーポイントを保持するだけのクラスです。次に「MainGame.cs」は、XNA経験者であればお馴染みのUpdateメソッドとDrawメソッドを定義したクラスです。この際に特筆すべきは、90行目付近で3Dモデルが持つボーンの番号を列挙体にマッピングしている点です。3Dモデルを動かすために定義する骨の事であり、3Dモデルごとに異なるボーンの番号をここでマッピングすることで差異を吸収しています。他にも「CameraHandler.cs」は、キーボードで視点を操作するためのクラスですので、不要なら削除しても問題ありません。「SkeletonHelper.cs」は、キネクトの骨格データを左右反転させる(鏡で映したようにする)ためのクラスですので、削除したところでモデルの動きが左右逆になるだけの些細なクラスです。いうことで、肝となるのは「AvateerHandler.cs」です。AvateerHandlerクラスの内容は?AvateerHandlerクラスのAPIはシンプルで、UpdateメソッドとDrawメソッドがMainGameクラスから呼び出されるようになっています。この中で、キネクトの骨格追跡機能から得られる20個の「関節」の3次元座標を、3Dモデルの「ボーン」にマッピングして動かします。具体的には、隣接する2つの関節(例えば肩と肘、肘と手首など)とボーン(例えば上腕、前腕など)をswitch構文で関連付けて、ボーンの初期ポーズに関節の移動量を合成することで3Dモデルを動かします。マトリックスやクォータニオンなど、若干難しい技術を利用してはいるものの、コメントを含めても250行程度ですし、その内の100行くらいはswitch構文ですので、比較的読みやすいソースコードになっていると思います。今回のサンプルはドロイド君の3Dモデルの初期ポーズ(両手両足を垂直に下した状態)を前提に作成しています。このため、各ボーンの初期ベクトルをVector3.Downに決め打ちで実装していますので、初期ポーズがドロイド君と異なる3Dモデルを利用する場合は、この初期ベクトルを修正する必要がある点に留意してください。ドロイド君の3Dモデルは?なお今回は、ソースコードの他にも、ドロイド君のボーン入り3Dモデルを同梱しています。3Dモデルは、「メタセコイア」というモデリングソフトで作成しており、Metasequoia専用のプラグインである「Keynote」を用いてボーンを設定しています。いうプラグインにより、ボーン入りのFBXファイルに変換してXNAで利用します。(5000円)を使用する必要があります。キネクトから得られる関節の座標は20個となっていますので、キネクトで動かす3Dモデルを作成する場合は、このドロイド君の様に15本のボーン(=20個の関節)で構成するとマッピングしやすいです。ダウンロードはこちらから!ということで、同人誌をご購入いただいた方への感謝の気持ちを込めて、ソースコードと3Dモデルを公開させていただきます。ダウンロードしたファイルは自己解凍形式のEXEファイルで、パスワードを入力することで解凍できます。パスワードは、「デベロッパーズハウツー3」の最後が「何オチ」であったかを、漢字二文字で入力してください(最後のコマを参照)。ソースコードを利用したことによる一切の責任は負いかねますので、あらかじめご了承ください。DroidForKinectSampleをダウンロードそれでは、この度は同人誌をご購入いただき、誠にありがとうございました~!。ご覧のように紆余曲折はあったんですが、原因はどれも計算ミスによるものだったので、割愛させていただきます。SDK」のAPIが扱いやすいということでもあります。機能が少ないために全体像を把握しやすかったというのが一番の理由かもですね。多少の不満はあるけれど!それでも、キネクトに抱いた不満はいくつかあります。1つめは骨格情報のミラーリングがサポートされていないということです。これは実装側でデータを変換すれば(X座標を入れ替えれば)よいだけなので、大きな問題ではありません。2つめは、関節の情報が三次元座標だけということです。これも、関節の角度を実装側で割り出せばいいだけなので、やっぱり大きな問題ではありませんでした。欲を言えば関節の向きも取得できたら嬉しいです。この向きが取得できないと、前向きか後ろ向きかはもちろん、身体をくるりと一回転するような動きをトレースできません。3つめは、デバッグがしにくいことで、確認のたびにポーズをとるのは大変でした。v1.5で改善されるというお話ですので、今から楽しみにしています~(o*゚ー゚)oそれでもここまでできちゃいます!自分の動きに合わせて、リアルタイムに3Dモデルが動くというのは、個人的にとても新鮮な感動です!惜しむらくはこれが...ドロイド君であって窓辺さんではないことですが...。このように、一見するとおぉ~な感じ(?)のキネクトアプリも、実装自体は大したことありません。これからリファクタリングを行いますが、コメントをふんだんに盛り込んだとしても500行には満たないかなと。リファクタリング中に気付いたことや思い出したことがあれば、またブログに書いていきたいと思います。キネクトは本当に簡単で面白いです!ネタに選んで大正解でした♪(。́ゝω・)ソースコードは夏コミで!このサンプルの3Dモデルとソースコードは夏コミの同人誌のオマケとして配布する予定(当選すれば)です。在庫の撲滅にご協力ください!他にもサンプルを作成したら、併せて配布しちゃいます。時間があれば、次は3Dスキャナーモドキを作ったり、音声認識を検証してみたいですね。Windows」を利用して、思い通りに3Dモデルを動かすサンプルの開発に挑戦してみたいと思います。いわゆるひとつの「モーションキャプチャー」的なサンプルです。普通のドロイド君では物足りません。そこで今回は、驚異の7000ポリゴンオーバーで作成したハイエンドなドロイド君...つまり「ハイエンド・ドロイド」を利用します~!なんということでしょう!曲面やエッジの成形にポリゴンを贅沢に使用しています。̄)スキニング・ドロイド!何と!こいつ...動くぞ!Kinectから取得できる骨格情報を参考に、ボーンを仕込んで動くようにしてみました。個人的なこだわりポイントは、頭と胴体の間に「首」となるポリゴンを仕込んだことです。これによって頭を動かすと首が口のように見えるので、なんだかとってもチャーミング♪最終的にKinectでこのポーズが取れれば目標達成です!使えるものは流用すべし!ご覧のようにこのドロイド君は、肘や膝が人間の肌みたいに「グニャリ」と動きます。いう3Dモデルのことを「スキニングモデル」というんです。モデル」というサンプルを参考にすると便利です。今回もこのサンプルを一部参考にして、Kinectで3Dモデルを動かすサンプルを開発していきたいと思います。意外と情報が少ない?しかし...この手のサンプルってネットで全然公開されていないんですね。ネタがありきたりすぎるかと思っていましたが、意外とそうでもないみたいです。単純に骨格を描画しているサンプルはよく見かけるんですが、あれってあくまで2D画像として骨格を描画しているので、実はとっても簡単なんです。SDKのAPIには、骨格と画像をマッピングするAPIも用意されていますしね。骨格を3Dモデルにマッピングさせようとすると、一筋縄ではいきません。勉強会」に参加された皆様、お疲れ様でした~!(*≧∀≦)ノ勉強会はいいものですね!わたし自身、久しぶりの勉強会でしたので、色々な技術に触れられてとても楽しかったです!でも、色々な方々から刺激を受けられるということが、勉強会における一番の醍醐味ですよね~。スピーカーとしても、もっと笑えて楽しいお話ができるように今後とも精進致します。資料はこちらから!私のセッションで利用した資料は、以下のサイトから閲覧することが可能です。勉強会レポートソースコードはこちらから!セッションで利用したアプリケーション(上記画像)のソースコード及び3Dモデルは、以下のリンクからダウンロードすることが可能です。ご覧いただけるとわかると思いますが、基本的にはプロジェクトテンプレートから生成される雛形に対して、3Dモデルを追加してGamePageに処理を実装しているだけです。Phoneで利用できる3Dモデルの作成手順と、作成した3Dモデルを読み込んで描画するアプリケーションの作成方法をご紹介します。オーラスということで、やっと3Dアプリらしい内容になってきました~(T△T)なお今回も、ライブコーディング的な演出を狙って、作成手順を記録した動画を公開していますので、不明な点はそちらで補っていただけると思います。今回は、イチから3Dモデルを作成する手順と、作成した3Dモデルを描画するアプリをイチから作成する手順を動画にしております。どちらも再生時間は4分程度ですので、カップラーメンが完成するまでの暇つぶしにでもご覧いただけましたら幸いです(麺やわめ)。動画の効果は?...もっとも、今までの記事でも同様に動画を掲載してはいるのですが、再生回数はイマイチ芳しくありません(T△T)。何とか見ていただけるように、再生時間を明記したりとか、マウス操作を中心とした手順を記録するなど、色々と工夫したりはしているのですが...現状では100人に1人が見てくれているかどうかといった感じです...orz。動画撮るの...結構大変なんだけどにゃー...(TωT;)最終回は?...というわけで、最終回となる次回は今回作成したサンプルを基にして、右記のような3Dアプリケーションを作成する手順を解説します。実際にSilverlight/XNAを利用する上で大切なポイントを紹介したり、SilverlightからXNAを操作してみたり、XNAからSilverlightを操作したりする実例をご紹介する予定です。右記の3Dアプリでは、3Dモデルをリストボックスにバインドしたり、選択された3Dモデルのパーツを発光させたりしています。XNAなななんとっ!このたび、CodeZine様で連載させていただくことが決定致しました~!...といいますか、すでに第1回が本日公開となっております。関係者の皆様には、この場をお借りして深くお礼申し上げます!やった~!。7.5で新たに追加された新機能である「SilverlightとXNAの相互運用」について、その概要と実装方法をご紹介させていただきます。現状では全4回を予定しておりまして、SilverlightとXNAの基礎にはじまり、2つのフレームワークを融合させる方法や、3Dモデルを作成して描画する方法に触れつつ、最後に3Dアプリケーションの開発方法をご紹介していきたいと思います。Phoneは、まだ発売されて日の浅いプラットフォームですので、なんといっても日本語による情報が圧倒的に少ないです。それでも、基礎的な情報はそれなりに日本語化されているのですが...少し込み入ったことをやろうとすると途端に情報が少なくなります。日本語化されていたとしても...、MSDNの記事とかって文字だらけで読み辛いですし...実際にどうすればいいの?っていう情報がスゴク読み取りずらいです...@私的にそこで本連載では、そんな教訓を活かしつつ、動画やサンプルプログラムなどを交えながら、わかりやすくて実践的な内容をお送りしたいと思います。アーキテクチャがどうとか、そういった小難しいことは極力避けつつ(...というか出来ませんので)、どうすれば利用できるのか、どんな点に気を付ければいいのかなど、実戦向きの連載にしていきたいと考えております。隔週ごとの掲載になると思いますので、最後まで気長にお付き合いいただけましたら幸いです!(T△Tゞどぅぃーんって...ちょっと古くない?描いたときは...旬なネタだったんです...。元ネタをご存じない方は、以下の動画をご覧ください。XNA前回の検証結果(左記の画像)より、XNAのゲームループ(GameTimerクラスのイベントハンドラ)はUIスレッド上で動作することがわかりました。これには大きな危険が潜んでいます。UIスレッドの占有はダメ!お気づきの方も多いと思いますが、この事実から読み取れる危険...、それはUIスレッドの占有には今まで以上に注意しなくてはならないということです。何を当たり前のことを...と思うかもしれませんが、ちょっと待ってください!たとえば、SilverlightのUIコントロールのイベントハンドラにおいて長時間処理を実行した場合、そのぶん、同様にUIスレッドを利用するGameTimerクラスのイベント発行が遅延してしまいます。このため、ゲームループのFPS(1秒間に処理する回数)が低下しますよね。この際に厄介なのは、OnUpdateイベントまでもがUIスレッドで動作するという事実です。これはつまり、UIスレッドの占有による弊害は、描画のコマ落ちなんて生易しいものではなく、ゲームの処理落ちに直結するということです。XNAのみを利用する場合、処理に時間を喰ってしまった際は、意図的に描画処理をスキップして更新処理を優先させたりします。することにより、描画のコマ落ちは発生しますが、ロジックの処理落ち(ボタンを押したのに認識されない等)を回避させることは可能です。Silverlightと相互運用させる場合、こういう危険性を理解しないまま使用してしまうと後々厄介なことになりそうです。まとめ!後編に引っ張りましたけど、いいたいことはこれだけです。う~...ん、個人的にはOnUpdateイベントがUIスレッドである必要性が理解できません。Silverlightコントロールから値を取得するだけならば別段UIスレッドである必要はないわけですし...。UpdateとDrawの実行順序を保証させたいがためだとすれば...なんとなく理解できるかも?いやでも...なんでかなー...。7.1β」ではありますが、ことSilverlightとXNAの相互運用に関してはホント素晴らしいと思います。7.1β」では、SilverlightとXNAを相互運用することが可能となりました。この機能を利用することにより、例えばSilverlightのコントロールとXNAのゲームロジックを同一の画面内で共存させることが可能となります。個人的にイチ押しの機能です。ちなみにこの機能は、Silverlight5のDrawingSurfaceクラスにおいて、より洗練された形で実装されています。それでも、利用する際にはXNAに関する知識が少なからず必要となります。WP7も将来的にはSilverlight5ベースになるでしょうし、今のうちからXNAの使い方を理解しておくのも良いと思います。話が少しそれましたが、左記画像のアプリではこの機能を利用して、UIコントロールをSilverlightで制御し、ローザさんの3DモデルをXNAで制御しています。メッシュデータの利用方法など、XNAの基礎知識に関してはまた別の機会にご紹介するとして、今日の本題はXNAのゲームループからSilverlightのUIコントロールを操作することは可能か?という内容です。3Dモデルのアニメーションが終わったらUIコントロールの状態を変更する、みたいなことが可能かどうかということですね。おさらい!SilverlightとXNAを相互運用する場合、WP7.1ではGameTimerクラスを利用します。早い話、このタイマーがOnUpdateイベントとOnDrawイベントを交互に発行...つまりゲームループを発生してくれるので、これらのイベント内でXNAの更新処理と描画処理をしてあげればよいわけです。概略は右記画像のとおりです。仕組みは単純ですね~!このため、当然ではありますが、SilverlightのUIコントロールをXNAのゲームループから参照しても、別にビルドエラーにはなりません。あ実行時に、XNAのゲームループ内からSilverlightのUIコントロールを操作した場合は...一体どうなるのでしょう?やってみよう!ということで、やってみました!結論から先に申しますと、XNAのゲームループからSilverlightのUIコントロールを操作することは可能です!やったね、たえちゃん!...ん?でも待てよ。SilverlightのUIコントロールはUIスレッド以外から操作することはできないはず...。うまく動くのは...なぜ?調べてみよう!これを検証するために、左記のようなコードにおいて、SilverlightのイベントハンドラとXNAのゲームループのスレッドIDを取得し比較してみました。すると面白いことに、上記のスレッドIDは完全に一致します。このことから、XNAのゲームループはUIスレッド上で実行されていることがお分かりいただけると思います。GameTimerクラスは、普通のTimerというよりはむしろDispatcherTimerに近い感じなんですね。これで、XNAのゲームループ内からSilverlightコントロールをガンガン更新しても何ら問題ないことがわかりました。実際に、最大FPSで回しているゲームループからテキストボックスのテキストを(1秒間に数十回)変更しても、問題なく更新されます。潜む危険......でも、この事実に喜んでばかりもいられません。この事実にはある重大な危険性が潜んでいるからです。