【本サイトのご利用指針】
当サイトはSPAM対策等のためJavaScriptを使っています。
JavaScriptの実行を可能な状態にしてご利用下さい。
Please enable the execution of JavaScript!




Vocaloid初音ミクMikuMikuDanceという驚愕のソフトウェア

  【リンクフリー】 私設研究所ネオテックラボ Neo-Tech-Lab.co.uk
【記載者】 上田智章 ☆Tomoaki Ueda☆ NTLMMD

 
ここにチェックボックス型外部コンテンツ・メニューが入ります。




【ブラウザはGoogle Chrome】

●最新版ダウンロードはこちら

【お知らせ】

現在、特にお知らせする事項はありません。

【メニュー】 PMDファイルの構造に関する記述や、Excel VBAでPMDモデルを3次元表示するあふぉな試みなど。
  【Excel VBA編】【ソース公開中】 ●ポリゴン・フィルとテクスチャー・マッピング  ●透視変換  ●光源計算
  【NyARToolkitCSで拡張現実編】【ソース公開中】 ●【ポリゴン、テクスチャーマッピング、Sphere Mapping編】  ●【表情処理編】
  【拡張現実センサ編】 ●AR sensor(拡張現実センサ)

  【予想】●IK bone制御[ただのメモだよ]
  【過去記事メニューへ】 【期間】2008/03/11~                      【English page】

■記載日2011年12月25日■19:24頃記載
【またなんかブラウザの仕様が変更になったかも?】
WebGLで書いたちびミク表示デモが動作しなくなっていることに気が付いた。
調べてみると、特定のサンプルプログラムだけ動作がおかしい。というかJavaScriptファイルの読込速度が著しく低下している。
JSONPっぽく誤魔化してクロスドメインでデータを受け渡しているコード付近でフリーズするようだ。
試しに、JSON形式で記述したモデルデータを読み込むと、ローカルだと一瞬なのに、インターネットからだと異常に遅く、途中で停止してしまう。
ブラウザはGoogle Chrome, Apple Safari, FireFoxで同じ症状が出る。???
知らないうちにセキュリティー関連の変更があったようだ。
.bmp形式ファイルのデータ領域にPMDフォーマットのデータとテクスチャーを詰め込んでコンテナ化したファイルをbase64形式に変換したものはすんなり通るようだ。

【実験サンプル】ちびミクをWebGLで表示する (base64形式コンテナを使ったPMD表示)

どうせ抜け道は100通り以上あるのに、随分くだらないことをするなぁ。
なんちゃって初音ミク風味のWebVocaloidも現状動かなくなった。こっちは原因解明中。

■記載日2011年12月07日■21:21頃記載
【MMDのダウンロードページにボタンを発見!】
久々にYouTubeでKinect導入に関する質問があったのでVPVPに行ってみたときに、意味ありげなボタンを発見。
これ、いつからあったのでしょうか? 今日初めて気が付きました。
クリックするとpictフォルダー内のnew page(空ページ)に飛びました。
クリスマスに何かあったりします?
それとも開発再開が近い?


【MMDへのKinect導入トラブル対応から】
【質問】(オーストラリア) OK I did all you told me to and these are the errors
The Program can't start because MSVCR100.dll is missing from your computer.
Try reinstalling the program to fix this problem.
(This also happened when I tried opening Smaple Skeletal Viewer)
GetProcAddress: 126:The specified module coul not be found.
Cannot move OpenNI. OpenNI mayhave failed install

OpenNI導入トラブルのようでした。
Windows7またはWindows8 Preview限定ですが、OpenNIをインストールするのが困難な人のようなのでMogg氏の開発されたMoggNUIを薦めました。
ところがOpenNIと同じようにMSVCR100.dllが見つからないというエラーが出るとの事。
MSVCR100.dllはVisual c++に実装されているDLLパッケージのようなので下記のインストールを薦めました。
  ついでに、DirectX9も実装されていないようだったのでダウンロードを薦めました。

【Kinect最速導入手順】

もし、あなたのパソコンがWindows7なら、以下の手順をお薦めします。
1. まず、下記URLからMicrosoft社のKinect for Windows SDK Beta2をインストールします。
   http://www.kinectforwindows.org/download/
2. Kinect for Windows SDKのインストールが完了して再起動したら、サンプルプログラムのSkeletal Viewerを起動して動作を確認します。
3. もし、サンプルプログラムのSkeletal Viewer起動直後にMSVCR100.dllが見つからないというエラーが発生したら、それはVisual C++をインストールしていない場合だと考えられますので、Microsoft Visual C++ 2010 Redistributable Package (x86)をインストールします。
  Microsoft Visual C++ 2010 Redistributable Package (x86)
4. 多分そういう場合には、DirectX9もインストールされていないと思われるので、MicrosoftのDirectX End User Runtimeもインストールしましょう。
  MicrosoftのDirectX End User Runtime
5. 樋口さんのMMDダウンロードサイトからMMD最新版をダウンロードして、解凍します。
   http://www.geocities.jp/higuchuu4/pict/MikuMikuDance_v739dot.zip
6. Mogg氏のサイトに行ってKinect for Windows対応のMoggNUIをダウンロードします。
   https://sites.google.com/site/moggproject/
7. 日本語ユーザーは『jaフォルダ』と下記モジュールをMMDのDataフォルダ内にコピーします。
    - DxOpenNI.dll
    - MoggNuiConfig.exe

以上、10分程度の作業でKinect導入が完了します。
ちょっと気になったのは、ミクの足のIKが地面に張り付いて離れなかった現象くらいです。
でもこれは動作チェックした部屋が狭くて足元まで撮影できていなかったからかも。
以上の指示を相手に送付したところ、現地でも直ぐに動作したとのことです。

■記載日2011年11月09日■21:18頃記載
【MMD最新版Version7.39.dotリリース!】
もう2週間程前のことらしいが、Version7.39.dotがリリースされていた。
修正内容は安定性改善に関するもののようでダウンロード推奨。
(モーションエディットのときコピーすると足が捻じれるバグは未対応みたい。)

■記載日2011年10月06日■23:28頃記載
【MMD海外ユーザーにKinect導入者が増え始めた】
アクセス解析の結果から9月頃からKinectを導入してMMDを楽しもうとするユーザーが増え始めたようだ。果たして、何名がインストールに成功しているのかは分からないが、日本語版と英語版を同時に開きながら導入しようとしているユーザーもいる。国はばらばらだが日本人でKinect導入ページを閲覧する人とほぼ同数の閲覧者がいる。
ところで、将来的にはブラウザでNative Codeの実行を可能にするNative Client (NaCl)が実装されるそうだ。Pepper経由でセキュリティーを保つようなので、NaCl + Pepper(塩コショウ)となる。その頃には、Audio Data APIも実装されるだろうから、VocaloidとMikuMikuDanceのWeb版が可能になる。
現状ではかなり背伸びしても安定さに欠く。原因はJavaScriptでWebGL関連を使うとメモリリークを発生するためだ。文字コードの変換の方は簡単だったが、これもメモリを食う。モデル1体動かすのも途中でぶっ飛ぶ場合があった。JSON形式PMDでモデルをロードしているからかもしれない。一番飛びにくいChromeでさえ5回程走らせると飛んでしまう。orz.....
せめてもうちょっとメモリリークを起こりにくくしてほしいものだ。
どうせWeb Agentによるモデル制御もなんかうまくいかない(歩けないで倒れてしまう)ので地道に1個1個問題を解決していくことにしよう。

■記載日2011年9月12日■09:21頃記載
【MMD世界傾向】
私の作成したYouTube上のMMD初心者用動画のアクセス数のトレンドから見て、2011年6月末頃から顕著に減少を始めた。周囲にMMDを知っている人が増え、ニーズに合わなくなった事が一番なのだが、MMDの開発が終了したことも関係していそうだ。
これに連動して、米国Microsoft社、IBMとか米国企業からPMDフォーマット関連の調査アクセスが始まったように思う。検索エンジンで無く、人間による長時間閲覧を確認。カナダのIT企業も何か開発していたようだ。
米トヨタのCM等では『初音ミク』を流しているので人気が無くなったわけではないようで、多分MMD仕様の商用利用が検討されているのだろう。
予想されるのは、PMD Editorも加えたMMDのクラウド・サービス版、それもVocaloidとMIDI Synthesizer機能を備えた動画コンテンツ製作ツールであるようだ。
残念ながらBGM Playerのソースに紛れ込ませたWeb Sensor Probe(閲覧者見守りセンサ)を発見されてしまったようで、データセンターに吸い上げられ、ドキュメントから分離されてしまったようだ。これで追尾できないなぁ。ちょっと残念かも。

★知り合いから音楽専門書『楽典』著者:石桁真礼生ら を借りて読んでみたら、楽器の音は不規則な非定常波である噪(そう)音と、倍音を含んだ周期性の楽音により構成されるそうだ。例えばピアノの場合には、鍵盤を引いた瞬間に弦が叩かれる際に発する過渡的な噪音と、弦振動で共鳴して連続的に鳴る楽音に相当する。これはボーカロイドの場合にも適応できる。子音が噪音にあたり、母音が楽音にあたる。つまり、音階に依存するのは楽音(母音)だと理解できる。なので、DDS(Direct Digital Synthesizer)で実装できるわけだ。
★この『楽典』には、純正律12平均律についてもかかれており、協和と不協和についての疑問が氷解した。流石、専門書。
★こうなると後は3D-CGとsoundのsynchronization問題とAI学習による滑らかな会話が課題として残るだけ。
■記載日2011年8月12日■09:21頃記載
【Web シンセサイザ/ボーカロイドを一から製作してみた】(第1次試作)
前はあんなに苦労していたのに、結構あっさりとカーネル(Kernel)の試作が完了してしまった。シンセサイザとボーカロイドの発声(なんちゃって初音ミク)と歌唱のコーディングを行い、取り敢えず、Google Chrome12, Mozilla FireFox5, Apple Safari5.1で動作するシンセサイザ/ボーカロイドのカーネルを製作してみた。
  ●【Finland民謡】『Ieavan Polkka』(ドラム、なんちゃって初音ミクの声付き)
  ●【Webシンセ/ボカロのメニュー】
  ●『なんちゃって初音ミク声でごあいさつ』(5~6秒の短いスピーチならすぐ)
【注意】 ●波形データを演算(rendering)して、音が出るまで10秒~20秒程かかります。

FireFox5以外のブラウザで動作することからわかるようにAudio Data API(audioタグの事ではない。)は使っていない。
まだまだ改善するべき点は多いが、かなり短いコードで済んだ。とにかく動作原理の確認には成功した。
次は、初音ミクやその他のボーカロイドのサンプル音を本格的にWeb Agent Mikuを使ってAI学習させてみようと思う。
本家YAMAHAでは1000パターン以上のサンプルが必要らしいが、Web AgentにはAI学習機能でそんな必要はない。
合わせて、今回、子音と母音を分離しなかったので次は分離してデータを小さく抑えるつもりだ。
任意の話者で録音したサンプル音で学習すれば、音声合成、歌唱が可能だ。
もっと滑らかに喋れるように学習させる必要があるが、これをブラウザに実装するのは負荷的にちょっと無理か。
フィルターバンクを用意すれば、任意曲の耳コピ・モードも実現可能かもしれないし、テキスト読み上げ機能、任意言語通訳機能など、今秋に発売予定とされるVocaloid3以上の機能を搭載することも可能かもしれない。実際、今現在はGoogle Text-To-Speechに依存しているため、Google Chrome12でしか実行できないが、音声認識と音声合成を組み合わせたプログラムもこんなに簡単だ。(iSpeech APIを使えばブラウザの制約は無くなるが考え中。)
それと試作中に、いい声を持った歌手の声の成分がある特徴をもっているらしい事が判明。成程、こんな法則が!


【YouTube】サンプル音 テスト


■記載日2011年8月9日■23:54頃記載
【Web シンセサイザ/ボーカロイドを一から製作してみよう】
Vocaloidをインストールしていたノートパソコンが壊れたので、別のパソコンにインストールしようとしたらインストールできない。(LANに接続しているのに『接続できない』とメッセージが出てそのせいかアクティベートできない!)
頭にきたので、シンセサイザとボーカロイド(正確には真似ロイド)を一から製作してみようと思い立つ。(どうせ途中で飽きるだろうけど。)
取り敢えず、Google Chrome12, Mozilla FireFox5, Apple Safariで動作するシンセサイザのコアを製作してみた。
FireFox5以外で動作することからわかるようにAudio出力API(audioタグの事ではない。)は使っていない。シンセサイザは思ったより短いコードで済んだ。
【Finland民謡】『Ieavan Polkka』
  波形データを演算(rendering)して、音が出るまで10秒~20秒程かかります。
で、次はボーカロイドの方に着手。どうせなら、喋りと歌の両方ができるのを作ってみたい。
ただし、7月30日の記事で書いたYouTube動画の学習型発話器をソフトウェアで実行させる方式だ。
ミクの音源データを学習させて、ミクっぽい声を出させてみたい。

■記載日2011年7月31日■15:32頃記載
【MikuMikuDanceは開発終了?】
全然知らなかったが、『初音ミクが踊る神ツール「MikuMikudance」の作成者がクレームに耐えかねて開発終了』という記事に気が付いた。
7.39が出てから変化が無かったので、気にはしていたのだが、樋口さん、長い間お疲れ様でした。
バージョン番号が39(ミク)で終わるというのがらしいと言えばらしいかも。
はたから見ても本業は何だろうと思う程、物凄い開発スピードだった。
本業で中心的存在になると、もはや趣味での開発にも限度があるだろうと思います。
振り返れば、物理エンジンBulletの実装とKinectは偉業だったと思う。内容を追いかけるだけでもだいぶ勉強になった。
本業には全く無関係と思われたのだが、この2年間は役に立ったこともあり、とても感謝しています。
KinectもMicrosoft社がWindows7限定だがSDKのβ版を発表したため、OpenNIも間もなく終わりを告げるだろうし、タイミングはいいかも。(SDKはOpenNIと違って誰でも5分でインストールできるようになった。)
しかし、クレーマー恐るべしだな。1人に頼るだけ頼っておいて。
私の本業に無関係なしょぼい電子工作サイトでも、仕事で利用しようとする人達が何度も問い合わせをしてきて無駄な時間を割く事が多かった。
樋口さんの場合は大変だったろうと想像できます。
現状、海外のハッカーでMikuMikuDanceのfunctionを一生懸命調べている人もいるが、どうでしょうね?
いきなり互換ソフト開発はハードル高そう。同じプラットフォームでの開発を選択する人が出ないと思われるからだ。
今から開発ならインターネット接続で使える方式(JavaScript版)が好ましいと思う。
クラウド・コンピューティングの時代に、鯖負荷の重い言語は使うべきでないからだが、
かといって、WebGLも動画記録等の細かな仕様にはモジュールがかなり不足しているので、手間が大変だしね。
まだ1年くらい過渡期なんだろうなと思う。
WebGL以前には、バイナリーデータが扱えなかったせいもあり、仕様上の問題でFloat変換もコーディングしなければならなかった。日本語テキスト1つとっても、shift-jis⇒utf-8変換を書かねばならなかった。
取り敢えず趣味でやるなら、VMD Viewerから作るのが一番かなあ。


【Pocaloid2の例:カナダ】

【RoboTech2011】
■記載日2011年7月30日■12:43頃記載
【Pocaloid2って何ですか?】
『Pocaloid2って安全ですか』という検索で辿りついた人がいるので、ちょっと検索してみました。
海外ハッカーがハッキングして切り出したものだろうか?YouTubeで幾つか動画を発見。
ソフトウェア自体を使いこなしてはいないようだけど、データベース自体は同じものを利用しているっぽい。
vsqがそのまま使えるようで、YouTubeに動画をいくつも発見した。
ちょっとJavaScript使い過ぎのサイトだったので警戒して使ってはいませんが。.....人の事は言えないか...(^_^;)

ところで、Mozilla FireFox5では、Audio APIが実装されて、Float32Arrayを使って直接音を演算して出す事が可能になった
WebGLの導入に伴って、バイナリ型やFile APIの実装が進んでいるからだが、Vocaloid2もまねたソフトウェアは可能かもしれないと思っていたところ。
Robo Tech 2011のロボットでは教師信号に一致するように発話させる方式をメカニカルで実現している。
シミュレーション・ソフトウェアに詳しい人なら、メカニカル部は必須ではないことがわかりますよね?
でもこのアイディアはいただきです。
Vocaloid2の発音データを教師信号にして、同じ声が出るような発声方法をニューラルネットか最小2乗法システムで学習させれば、Parrot-loidも実現できそうに思えます。
つまり、一口で言えば『コロッケロイド』のようなもんですね。
ミクっぽい声、ルカっぽい声を出すモードを持つ新型ボカロ。
あくまでもモノマネなら著作権は関係ないように思えます。
そうでなければ、モノマネで食ってる俳優さん全員失職ですから。
また遊びで試作してみる価値あるかも。

■記載日2011年7月16日■06:43頃記載
【WebGLでPMDを表示してみた】
ローカルのPMDファイルをドラッグドロップして読込み、JSON形式に変換して、WebGLで3次元表示するように改良してみた。
取り敢えず、最新版のGoogle Chrome 12とMozilla FireFox5で動作するようにした。
FireFox5でうまく動作しない機種(Graphic Media Accelerator)の場合の対処法も上のリンク先に書いておいた。(あるいは7月1日に記載のコメント参照)
本来バイナリー形式のPMDが読み込めるのは、JavaScriptにFile APIと型付き変数が導入されたため。
FileReaderでバイナリー⇒readAsBinaryString⇒Uint8Array⇒JavaScript数値という変換の流れで、JSON化。JSONデータは別途表示する。
まだテクスチャーの読込部分は作っていないので、眼の色は茶・黒になってしまうが、テクスチャーが眼だけのモデルなら読み込めるところまでできた。 困っているのはshift-jisをutf-8に変換する処理を製作しないと、表情処理等に進めない事。文字コードから勉強する必要がありそうだ。
将来的にはブラウザだけで、PMDファイルをJSONデータに完全変換したり、vmdを読み込めるようにしようと思う。
  【注】ソースはJavaScriptなのでブラウザの『ソースを表示』で読める。

■記載日2011年7月7日■19:43頃記載
【WebGLでちびミクを表示してみた】
ちびミクのPMDからJSON形式に変換して、WebGLでちびミクを表示してみた。JSON変換時の注意点は、頂点座標と法線ベクトルのz値を正負反転させること。
漸くWebGLの意味がわかってきたような気がする。WebGLはDirectXを利用しているので、indexの取り扱い制限がunsigned short(65535個)となっている。なので、材質毎にIndexBufferを分割定義することにした。O3Dのときには何故気が付かなかったのだろう。
取り敢えず、最新版のGoogle Chrome 12とMozilla FireFox5に対応した。
JavaScriptだからデバッグが不自由だけど、WebGLは結構面白いかも。
今まで変数型が存在しないへんてこな言語だと思っていたが、WebGL導入を機に型付き変数が導入された。File APIやAudio Data APIなど劇的な変化を遂げつつあるようだ。
Audio Data APIは、現在のところMozilla FireFox5に限定されるが、リアルタイムにスペクトラム表示をしたり、音の合成して出力(シンセサイザの基本原理)したり、信号処理まがいのこと(カラオケ)までできるのだ。非常に面白い。Vocaloidさえも作れるかもしれない。

6月13日に記載したbullet.jsも使えるようになりたかったので少し触ってみた。CANVAS(2D)で書かれていた
『積み木の落下・衝突デモ』をWebGLにのせ換えてみた。次は『ragdoll』のデモを目指したい。
【WebGL】【Bullet.js】【物理演算】『ragdoll』デモ

■記載日2011年7月2日■19:43頃記載
【Kinect for Windows SDK Betaをインストールしてみた】
2011年6月16日にKinect for Windows SDK Betaが発表されていた。早速、ダウンロードしてデモプログラム2種を動かしてみた。
実は現在の所、Windows7にしかインストールできない。インストールは超簡単で手順を書く必要は全くないレベルだ。5分もかからずインストールを完了して、デモプログラムを動かすことができた。
C++, C#, Visual Basic, JScriptに対応しているようだ。これから使ってみようと思う。

■記載日2011年7月2日■19:43頃記載
【FireFox5でWebGLを動かそうとすると発生する不具合】
WebGLではscriptタグを使ってfragmentとshaderの処理を記述するが、ここで日本語でコメントを入れると、Google Chrome12は問題なく動作するのに、Mozilla FireFox5ではエラーが発生する場合がある。
WebGLに関する情報がたまってきたのでページを分離した。

■記載日2011年7月1日■13:15頃記載
【FireFox5でWebGLを動作させるには?】
Vistaではデフォルト状態でもFireFox5でWebGLを使うことができたのですが、Windows7のノートパソコンではちょっと深みにはまってしまいましたので、メモを残しておきます。現象としては、Windows7のノートパソコンで、FireFox5でWebGLサンプルを動作させようと試みたのですが、コンテクスト取得に失敗してしまうのです。CPUはIntel Core i3です。実装されたGMA(Graphic Media Acceralator)を使っている機種です。
Google Chrome12の方では問題なく動作しましたので、原因はFireFox5がデフォルトで機種によって禁止しているからだろうと推測しました。
いろいろ情報を探して彷徨った挙句に、Google検索で『FireFox5 WebGL GMA』で検索トップに出てくるページに解決策が載っていました。
  ●【MozillaWiki】『Blocklisting/Blocked Graphics Drivers』
   ■FireFox5のアドレスバーに『about:config』と入力します。
   ■『最新の注意を払って使用する』ボタンをクリック
   ■フィルタ欄にwebglと入力。⇒ webgl.force-enabledの値をダブルクリック。値をtrueにする。
   ■フィルタ欄にlayersと入力。⇒ layers.acceleration.force-enabledの値をダブルクリック。値をtrueにする。
   ■フィルタ欄にgfxと入力。⇒ gfx.direct2d.force-enabledの値をダブルクリック。値をtrueにする。
以上で、サンプルを動作させることができました。

【利用できるブラウザ】
Google Chrome12, FireFox5, InternetExplorer9
【非対応】OperaやSafariには非対応です



■記載日2011年6月27日■17:00頃記載
【FireFox5.0ではWebGLでCross-DomainイメージをTextureにできなくなった件】
WebGLでは『重大な』セキュリティー問題が指摘されています。所謂『クロスドメイン問題』で、Google Chrome12及びFireFox4では外部ドメインのイメージ画像をテクスチャーとして使えてとても便利だったのですが、なんとFireFox5.0では塞がれてしまいました。(-_-;)
きっと将来的にGoogle Chrome13辺りで塞がれてしまう運命でしょう。orz.....
なんて事をしてくれるんだ? めちゃくちゃ不便じゃないかぁ?
GPUから一旦フレームバッファに書き込んでまた読み出すと、データの出所に関する情報が消え、それでPCの遠隔操作などの悪い事をしようと思えばできるからという理由からなのですが。
.....でも『必要は発明の母』です。....scriptタグは実はどんなファイル形式でも使えることに気付きました。
base64エンコーダを製作して、mp3, ogg, png, gif, jpgなどをbase64形式に変換してやればクロスドメインで読めることがわかりました。つまりデータを外部ドメインから読み込んでから、型を変換してそれぞれのオブジェクトに入れることでaudioタグやimgタグで同一ドメイン内のデータとして取り扱えるんです。結果、2次元のcanvasでもgetImageDataで読み出したり、WebGLでテクスチャとして取り扱うことに成功しました。
左欄左上隅のボタンをクリックすると、外部の2ドメインからaudioデータと、imageデータを読み込みます。HTML5のaudioタグで音楽を再生。canvas(2D)にイメージを表示し、一部をgetImageDataで切り取り、putImageDataで貼り付けます。
結構短いscriptで済みましたので応用は広そうです。
今回利用した方法はJSONPの通信原理を利用しているので、これを塞ぐ事はできないでしょう。
(ハイパーテキストプロセッサは未使用で、データは普通のレンタルサーバー上にあります。)
大体、今更気にするセキュリティーホールじゃないんですよね。これ。
クロスドメイン自体を全部禁止にしても本当の所意味はないんですよ。(^_^;)

■記載日2011年6月13日■18:15頃記載
【WebGL / bullet.js のデモを見つけました】
検索していたら、MikuMikuDanceでおなじみの物理エンジンBulletが、Javaに移植され、そこからさらにJavaScriptにも移植(bullet.js)されたようで、WebGLとbullet.jsを組み合わせて作られたゲームを公開されている個人サイトを見つけました。 ブログには製作されたゲームが公開されていました。
開発途上の初期のデモも発見できました。 ざっと読むと、Vecmathというベクトル演算ライブラリ(Vecmath.js)と、物理エンジンBullet本体(Bullet.js)、この方のライブラリ(Pl4n3.js)、及びWebGLに分かれていましたので勉強のためダウンロードいたしました。
解析中のWebGL/bullet.jsのデモでソースを眺めているところです。
Vecmath.jsはともかく、Bullet.jsはすさまじいですね。これ全部理解しないと使えないのかなぁ?(-_-;)

■記載日2011年6月10日■06:25頃記載
【WebGLに関する解り易いページは?】
検索してさまよった挙句に次のページに辿りつきました。閲覧は最新版Google Chromeで。

『Hack The WebGL (WebGL勉強会)』

日本語のWebGLチュートリアルページ。Lesson1からLesson16までサンプルコード有。
以下は個人的に勉強のためチュートリアルページのコードをちょっといじってみました。WebGLの描画領域が判別できるようにα=0.1に設定しています。
ブラウザさえWebGLに対応していれば、JavaScriptだけでリアルタイム3次元グラフィックス表示が楽しめます。
最新版Google Chromeをお使いならプラグインなど必要とせず、何もしなくても表示されます。
WebGL Lesson1 三角形と四角形の単色描画 ■WebGL Lesson2 三角形と四角形のシェーディング描画 ■WebGL Lesson3 三角形と四角形の回転処理
WebGL Lesson4 三角錐と立方体の回転処理 ■WebGL Lesson5 立方体へのテクスチャーマッピング処理
WebGL Lesson5_A 立方体へのテクスチャーマッピング処理(テクスチャのみ変更) テクスチャーのサイズには制約がある模様。
WebGL Lesson6 立方体へのテクスチャーマッピング処理(キー入力の例)
  ⇒  ■WebGL Lesson6_A 弱音ハク箱(キー入力の例)(テクスチャのみ変更) ■WebGL Lesson6_B はちゅねミク(キー入力の例)
WebGL Lesson7 光源計算の方法 ■WebGL Lesson8 αブレンディング ■WebGL Lesson9 ブレンディング
  Lesson10はtextデータをクロスドメインで取得するのはやりづらいのとデータを作るのが面倒なのでパス。
  以降のデモは暗くしないとやりづらいので殆ど編集せず。
WebGL Lesson11 月とマウスのドラッグで回転 ■WebGL Lesson12 月と箱と光源計算 ■WebGL Lesson13 月と箱と点光源
WebGL Lesson13 月と弱音ハク箱と点光源 ■WebGL Lesson14 ティーポット JSONデータのクロスドメイン取得は面倒なのでパス。
WebGL Lesson15 拡散光や鏡面反射項の光源計算 ■WebGL Lesson16 パソコン画面にテクスチャー JSONデータのクロスドメイン取得は面倒なのでパス。

『WebGLのデモ』



■記載日2011年6月10日■04:45頃記載
【Vocaloid3 Editorが今秋発売予定】
Slashdot『ヤマハ、VOCALOID 3を今秋発売』によれば、今秋にVocaloid3 Editorが発売されるとのこと。今までは伴奏は他のMIDIソフトで製作しなければならなかったが、機能が統合され、Vocaloid3だけで曲の作曲が行えるようになるそうだ。言わばSinger Song Writerのような作曲支援ソフトと統合したようなものらしい。海外での人気を反映して各国語バージョンも出るらしい?? 価格は1万円前後とのうわさ。

■記載日2011年6月4日■14:58頃記載
【WebGLが面白そう】
Google Chromeの開発チームが製作した『ブラウザやウェブについて知っておきたい20のこと』に眼を通したところ、WebGLという言葉があるのに気が付いた。どうやら以前に開発されたO3D路線を変更して、ブラウザ標準実装のテキストベースOpenGLを開発したとのことらしい。
現時点では最新のGoogle Chromeを使うしか方法はないようだが、実際の描画はDirectX 9を使っているので高速だった。
アクアリウム(水族館)のデモは面白い。
JavaScript自体の実行速度も速くなったし、DirectX9でGPUが直接描画しているのだから高速だし。
で私の頭で当然考えることは、PMDの描画になってくる。PMD, VMD, VPDをJavaScript(プログラム)化して動的に読み込めば、MikuMikuDanceのクラウド化が行えるかもしれない。
動画や静止画に落すところはサーバーアプリになるかもしれないが。
あるいはGoogle Translateで使われているiSpeech APIの音声合成(Text-To-Speech)や音声認識(Automated Voice Recognition)と組み合わせて、Web Agentを構成するのも面白そうだ。
クロスドメインに起因するセキュリティーホールがあるとの指摘もあるが、既存ブラウザには報告されていないだけで他にもセキュリティーホールはあるのだから、これはこれで面白い。



■記載日2011年5月24日■14:58頃記載
【MikuMikuDanceのモデルデータにPMX仕様が追加された模様】
海外からの質問でMikuMikuDanceに何が起こったのかと聞かれて樋口優さんのダウンロードサイトを訪れてみたところ、MikuMikuDanceのバージョンが7.37になっているのを確認。『PMX』という言葉が登場している?
検索をかけてみると、pironさんのブログ(4/1版)で登録できる頂点座標の個数が16bit(65,000程度)から拡張され(恐らくは32bit?)、テセレーションにも対応したとの事。より美しいモデルを追及してきた人達には朗報だろう。
で、Kinectのインストール方法を聞かれたんだったが、手元に英字表示のパソコンがないから環境変数を変更するところをどう説明したものかな?
動画でとってアノテーション入れて説明しておくか。しかし、それにしてもちょっと中高生にはどうなんだろうな。若いからかえっていけるかも。トライさせてみるか。
で、早速作ってみた。How to use Kinect Sensor on MikuMikuDance Ver.7.xx
あれ、前のバージョンだと動いたが、Vistaでエラーが出る。もう一度、最新版のOpenNIを再インストールしてみるかな?
・・・・・・・・・・・・・・・・・・・・・再度、チェックしてみた。
DxOpenNI.zipに同梱のSamplesConfig.xmlのLicenseの部分をUserFileフォルダにコピーする前に修正するのを忘れていたためだった。よかった。

が、またまたgithubのavin2が更新されていた。
結局、『avin2-SensorKinect-28738dc』を入れて動作した。こっちも、ほっ!

■【OpenNI導入について】
例のWindows7 64bit版がインストールできなくなり、32bit版のOpenNIとNITEを入れなければ動作できなくなった件に関連していると思われるが、取り敢えず私はWindows7 64bit版にOpenNIとNITEは32bit版をインストールして動作させている。これで問題は生じていない。また、時間を浪費したくないので64bit版での再チャレンジはしていない。
   ●【English Version】How to install OpenNI onto your PC

【SamplesConfig.xml】

<OpenNI> <Licenses> <License vendor="PrimeSense" key="0KOIk2JeIBYClPWVnMoRKn5cdY4="/> </Licenses> <Log writeToConsole="false" writeToFile="false"> <!-- 0 - Verbose, 1 - Info, 2 - Warning, 3 - Error (default) --> <LogLevel value="3"/> <Masks> <Mask name="ALL" on="true"/> </Masks> <Dumps> </Dumps> </Log> <ProductionNodes> <Node type="Image" name="Image1"> <Configuration> <MapOutputMode xRes="640" yRes="480" FPS="30"/> <Mirror on="true"/> </Configuration> </Node> <Node type="Depth" name="Depth1"> <Configuration> <MapOutputMode xRes="640" yRes="480" FPS="30"/> <Mirror on="true"/> </Configuration> </Node> <!-- <Node type="Audio" name="Audio1"> </Node> --> </ProductionNodes> </OpenNI>

■記載日2011年5月9日■05:58頃記載
【OpenNI.Net.dllが仕様変更になった件】
手持ちのWindows7数台にOpenNIの最新版をインストールし直したら、C# WrapperのOpenNI.net.dllがOpenNI.Net.dllに1文字名称変更になっている。嫌な予感。
予感的中。ドライバがAudio対応になったためだろうか、名前空間Xnは姿を消し、OpenNI.Netに変更になっている。しかも、参照を変更してコンパイルしたぐらいでは動かない。
どうも仕様の大変更があった模様。まだ詳しくは細部を見ていないが、サンプルプログラムを見て1から調べ直す必要がありそうだ。大ショック。

■ソフトウェア構造が大変更されたC# wrapper OpenNI.Net.dllだったが、取り敢えず問題個所をコンパイラの機嫌が良くなるように直す後ろ向きな方法で動作するようにできた。『OpenNI』のページに修正したソースをアップ。

■記載日2011年5月8日■21:00頃記載
【米ToyotaのCollora CMにMiku登場】
おぉ?
すっかりVocaloid曲も定着しているようですね。
右動画は、ToyotaのYouTubeチャンネルから。

【HTML5】

実質、Google ChromeFire Foxだけですが、HTML5だとこんなに簡単。ソースをご覧ください。



■記載日2011年5月5日■21:00頃記載
【Google翻訳の音声合成の件、記事を分離します】
Google翻訳の音声合成機能( Text-To-Speech: TSS )についてちょっと調べてみました。これは実は、『www.ispeech.orgのiSpeech API』を使って構成されているようです。
iSpeech APIとは、テキストを読み上げる機能( Text-To-Speech: TSS )と、音声認識機能( Automated Voice Recognition )により構成されたインターネット接続で使うオーディオ・デバイス用入出力インターフェースです。
まだ、全然使えていませんが、なかなか奥深いかもしれないので、まだ目処も立っていませんが、ページを独立して『iSpeech API [TSS]の使い方』のページを設けることにしました。
技術の進歩は凄いですね。殆どテキストに『?』マークやスペース、句読点を入れるだけでナレーションを作ることができます。私はWindows標準アクセサリのサウンド・レコーダーと組み合わせて使っています。
欲を言えば、ピッチ、抑揚、声質が変更できたらいいのにと思います。クロスドメインで利用できるのも今はGoogle Chromeだけのようです。(Fire Foxも可能かも?)(すみません。勘違いでした。HTML5だとローカルでしかダメなようです。でも1つ前に書いたiframeの方法だとOKなようです。隠蔽もdivタグのstyle属性でvisibility:hiddenとすればOKでした。).....でもまぁ、そのうち実現されるんでしょうね。
個人的には、インターネット上から、Web Agent 'Miku'に音声入出力で指示ができるようになりそうなので凄く興味を持っています。ゲームも予め決められた選択肢が出るだけでなく、もっとストーリーに広がりが出せそうに思えます。
実用的なアプリなら、例えばKinectのジェスチャー、3D CGと組み合わせて、『手話 ⇔ 音声』というインターフェースも開発に手が届くのではないでしょうか?
WiMax搭載パソコンを持ってアメリカに行けば、殆どの地域でClear(現地プロバイダー)に接続することができます。音声インターフェースで通訳だって可能ですね。
音声認識『Automated Voice Recognition』の方も調べてみようと思います。

左のデモではボタンをクリックすると、
onclick="SendGoogle('en', en1.value );
のように、クリックイベントで下の関数が呼ばれてdivタグ内にaudioタグを生成するだけです。
autoplay属性を与えているので読込完了で再生が自動スタートするわけです。
デモでは、divタグのid名は何でもかまわないのですが、'speechOutput'と名付けています。
また、オーディオ・プレーヤーのelementコントロールは現在のGoogle Chromeではまだ対応できてないようです。

function SendGoogle(language, message) {
var source="<audio id=\"speechOutputAudio\" src=\"http://translate.google.com/translate_tts?tl=" + language + "&q=" + message +"\" controls autoplay=\"true\" style=\"width:300px\" ></audio>";
document.getElementById("speechOutput").innerHTML = source;
}






【未確認情報】
使えるかどうかわからないが、Google Translateの仕様から言語コードは以下の通りであると推察される。

【日本語】 ja
【英語】  en
【スペイン語】 es
【イタリア語】 it
【ドイツ語】 de
【ロシア語】  ru
【中国語】zh-CN
【韓国語】 ko
【オランダ語】 nl
【ギリシャ語】 el
【ポルトガル語】pt
【ポーランド語】pl
■記載日2011年5月3日■21:00頃記載
【Google翻訳の音声合成が凄い件】
【注:現在クロスドメインで使えるのはGoogle Chromeだけのようです。】
以前から、ウェブサイトで音声合成が簡単に実現できないかといろいろ試行錯誤してきたのだが、4月23日にGoogle翻訳に音声合成機能が備わっていることに気が付いた。リンク先のスピーカーマークをクリックすると、なかなかいい感じで女性の声が聞こえるのだ。
で、今日はこれをなんとかウェブ上で使えないものかと試行錯誤してみた。やったぁ。できる。できる。正式に公開されているわけではないのだが、こんな感じで記述すればブラウザで再生できる。日本語は少しなまりがでるので、句読点とか『?』マークを間にいれて調整する必要がある。
言い忘れたが、大前提として音声ファイルはflash(.swf)でやり取りされているようなので、shockwaveかflash playerは必要だ。

【日本語】 http://translate.google.com/translate_tts?tl=ja&q=こんにちは?あなたは、ミクミクダンスが好きですか?
【英 語】 http://translate.google.com/translate_tts?tl=en&q=Hello.+Do+you+like+miku+miku+dance?
【注】ブラウザのアドレスバーにコピペすれば、IE, Safari, Fire Foxでも使うことはできました。

そうなると欲が出てくる。iframeで実行して、divタグのz-indexで隠蔽すれば任意の音声、言語で喋らせることができるんじゃないの?
.....というわけでまた試行錯誤。.....結果はIEだと何故かQuickTimeが起動し、うまく隠蔽できなかったが、Google ChromeではAdobe Flash Playerが起動してうまく隠せた。
下のJavaScript関数は、idが'Voice'と名付けられたdivタグ内にiframeを構成し、音声合成させるための実施例だ。
左は3カ国語デモの事例。わざと音声合成の隠蔽がわかるように透過pngを手前に置いた。テキストボックスに日本語、英語、スペイン語を入力してボタンをクリックすると喋らせることができる。
一体何カ国語に対応しているのかわからないが、日本語も英語もまあ聞ける。試しにスペイン語もやってみた。翻訳できているのかどうかは不明だが。
   var msg="?tl=ja&q=こんにちは?"; //【日本語の場合 ja】
   MikuVoice(msg);

   function MikuVoice(msg) {
      var base=document.getElementById("Voice");
      base.innerHTML="【Google翻訳の音声合成を用いたアナウンス】";
      var obj=document.createElement("iframe");
      obj.setAttribute("border", "0");
      obj.setAttribute("frameborder", "0");
      obj.style.width = 300;
      obj.style.height = 50;
      obj.src="http://translate.google.com/translate_tts" + msg;
      base.appendChild(obj);
   }


【追記】

現状、Google Chromeでないとうまくいかないようだ。IEでJavaScript実行中、タグの中をのぞいてみたら以下のようになっていた。
iframeの中に下の様に埋め込んでから実行しないとだめなのかな?
<object id="input_tts_flash" codeBase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="18" height="18">
<PARAM NAME="_cx" VALUE="476">
<PARAM NAME="_cy" VALUE="476">
<PARAM NAME="FlashVars" VALUE="">
<PARAM NAME="Movie" VALUE="http://www.gstatic.com/translate/sound_player2.swf">
<PARAM NAME="Src" VALUE="http://www.gstatic.com/translate/sound_player2.swf">
<PARAM NAME="WMode" VALUE="Transparent">
<PARAM NAME="Play" VALUE="0">
<PARAM NAME="Loop" VALUE="-1">
<PARAM NAME="Quality" VALUE="High">
<PARAM NAME="SAlign" VALUE="">
<PARAM NAME="Menu" VALUE="-1">
<PARAM NAME="Base" VALUE="">
<PARAM NAME="AllowScriptAccess" VALUE="always">
<PARAM NAME="Scale" VALUE="ShowAll">
<PARAM NAME="DeviceFont" VALUE="0">
<PARAM NAME="EmbedMovie" VALUE="0">
<PARAM NAME="BGColor" VALUE="">
<PARAM NAME="SWRemote" VALUE="">
<PARAM NAME="MovieData" VALUE="">
<PARAM NAME="SeamlessTabbing" VALUE="1">
<PARAM NAME="Profile" VALUE="0">
<PARAM NAME="ProfileAddress" VALUE="">
<PARAM NAME="ProfilePort" VALUE="0">
<PARAM NAME="AllowNetworking" VALUE="all">
<PARAM NAME="AllowFullScreen" VALUE="false">
<param name="movie" value="http://www.gstatic.com/translate/sound_player2.swf">
<param name="flashvars" value="sound_name=&sound_name_cb=_inputTTSSoundFile">
<param name="wmode" value="transparent">
<param name="allowScriptAccess" value="always">
</object>

■記載日2011年4月8日■21:00頃記載
【コミPo!がまた進化したらしい】
 誰でも簡単に漫画を作成できる『コミPo!』にユーザー3Dデータ読込機能が追加されたそうだ。読込形式はMetasequoiaのMQOファイルのようだ。
 【無料体験版ダウンロード】


■記載日2011年4月5日■9:00頃記載
【KinectのC#による使い方】
 Kinectを使った拡張現実(Augmented Reality)センサも試作してみました。まずRGBカメラやDepthバッファ等のC#サンプルプログラムのソースを公開しました。左に加え、骨格情報の表示まで実装しています。Augmented Reality Sensorも改良後公開する予定です。Kinectを使ったシステムはARToolkitのようにマーカーを使わなくてもよいので、認識率も高く使い勝手が良いようです。但し、手首認識可能に改造する必要はあるかも。今後、Mogg氏のMoggDxOpenNI0.53を参考にして手首とか首の傾斜等の認識にもトライしてみたいと思います。
 ところでDepthバッファなのですが、Kinectから近距離で使うとDepth値0の部分が大きくなる問題があります。(左図で左手の横の部分。) 多分、レーザー光線の死角部分なのでしょう。



■記載日2011年3月31日■20:30頃記載
【Kinectが反転していた理由】
OpenNIフォルダの下にDataフォルダがあって、SamplesConfig.xmlがあるが、そこに次のように記述されていた。初期化状態に関係なく、通常の向きで表示させるためには、26日に書いたようにC#のソース中で記述しておくべきなのであまり意味はないけど。
<ProductionNodes>
   <Node type="Image" name="Image1">
      <Configuration>
         <MapOutputMode xRes="640" yRes="480" FPS="30"/>
         <Mirror on="true"/>
      </Configuration>
   </Node>
   <Node type="Depth" name="Depth1">
      <Configuration>
         <MapOutputMode xRes="640" yRes="480" FPS="30"/>
         <Mirror on="true"/>
      </Configuration>
   </Node>
■記載日2011年3月26日■19:20頃記載
【Kinectが左右反転している件】
 Skeltonの認識率は、極力背景と異なる色の服を着ることで向上した。
 Kinectが左右反転しているのは、ゲームで画面に向かい合った場合に、鏡に映すような表示の方が都合がいいからかもしれない。
 UserTracker.netを修正して実写画像上にスケルトンを表示させることに成功したが、当たり前のことだがSkeltonJointの座標まで左右反転していたし、実写画像を撮影するカメラと赤外線カメラの撮影位置が横にずれているからスケルトンの表示位置が少し横にずれる不具合があった。が、以下のようにすることで簡単に問題が解決できることがわかった。
  context.SetGlobalMirror(!context.GetGlobalMirror());    //【Mirror表示の切り替え】
  context.SetGlobalMirror(true);    //【鏡像表示】
  context.SetGlobalMirror(false);   //【通常カメラ画像】
  depth.GetAlternativeViewPointCap().SetViewPoint(image); //【Depthを実写位置に補正】
  depth.GetAlternativeViewPointCap().ResetViewPoint();    //【Depthの位置を元に戻す】
    
 実際に試してみたところ、System.Drawing.Imaging.PixelFormat.Format24bppRgb(B,G,Rのバイト順でデータが整列)の場合のポインタの処理は以下のようにシンプルで済んだ。
     //【image情報】
     for (int y = 0; y < imageMD.YRes; ++y)
     {
        byte* Dest = (byte*)data.Scan0.ToPointer() + y * data.Stride;
        for (int x = 0; x < imageMD.XRes; ++x, pImage += 3, pDest += 3)
        {
           pDest[0] = *(pImage + 2); //【青】
           pDest[1] = *(pImage + 1); //【緑】
           pDest[2] = *(pImage);     //【赤】
        }
     }
    
 ちなみに、System.Drawing.Imaging.PixelFormat.Format32bppArgbの場合には、
        for (int x = 0; x < imageMD.XRes; ++x, pImage += 4, pDest += 4)
        {
           pDest[0] = *(pImage + 2); //【青】
           pDest[1] = *(pImage + 1); //【緑】
           pDest[2] = *(pImage);     //【赤】
           pDest[3] = 255;           //【α】
        }
    
とする。


【追記】
 コンパイルオプションでunsafeを許可し、private unsafe void 関数名()のように記述すると、その関数内でポインタの記述が可能になる。何が嬉しいかというと画像データの引き渡しが簡単になるということなのだ。この記述方法がわかってとても嬉しい。

■記載日2011年3月25日■15:30頃記載
【OpenNIでIR, image共に左右反転している件】
 imageだけでなく、IR, depthも左右が反転しているらしいことに気が付いてしまった。何故に?OpenGLとの違いからなのだろうか?全部、imageのfor文で記述したように直さなくちゃ...面倒だなぁ。
 それともDirectXでテクスチャーマッピング使って後でひっくり返すか?その方が簡単かも。
 そう言えば、MikuMikuDanceも左右反転しているかもしれない。モーションがリアル過ぎて今まで全然気が付かなかったよ。

■記載日2011年3月24日■21:00頃記載
【KinectをC#で使う方法は? その2】
 前日に引き続いてKinectをC#で使い、カメラキャプチャー画像を表示できるようにサンプルプログラムSimpleViewer.netに少し修正(赤字部分)を加えてみた。参考の為、本来不必要なDepth処理部分を残しています。
 左右ひっくりかえっているが、これでKinectをWebカメラのキャプチャーにも使える目途がたった。
 NyARToolKitCSによるマーカー検出と、Kinect自身によるSkeltonJoint検出を両立させることができるわけだ。
 Kinectは本当にお得なセンサだ。ちょっと前まで400万円~2000万円したモーションキャプチャーがたった1万5千円弱で手に入るわけだから。
 樋口さんのDxOpenNI.dllのソースとOpenNIバイナリのサンプルプログラムUserTracker.netのSkeltonJointの部分をよく読んで、自分なりにまとめてみるかな。
 SkeltonJointで殆ど3次元モデルと位置が一致する状態で、首の回転角を合わせたり、手先部分だけをキャプチャーしたりと改良が可能かもしれない。

 ところで、C#でも関数の型の前にunsafeを付けて書くと、関数内部でポインタを使って記述できるとは知らなかった。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using xn;
using System.Threading;
using System.Drawing.Imaging;

namespace SimpleViewer.net
{
   public partial class MainWindow : Form
   {
        private readonly string SAMPLE_XML_FILE = @"../../../Data/SamplesConfig.xml";
        private Context context;
        private DepthGenerator depth; //【深さ情報】
        private ImageGenerator image; //【画像情報】
        private Thread readerThread;
        private bool shouldRun;
        private Bitmap bitmap;
        private int[] histogram;
        
        public MainWindow()
        {
	    InitializeComponent();
	    this.context = new Context(SAMPLE_XML_FILE);
            this.depth = context.FindExistingNode(NodeType.Depth) as DepthGenerator;
            this.image = context.FindExistingNode(NodeType.Image) as ImageGenerator;
            if (this.depth == null) { throw new Exception("Viewer must have a depth node!"); }
            if (this.image == null) { throw new Exception("Viewer must have a image node!"); }

            this.histogram = new int[this.depth.GetDeviceMaxDepth()];

      //    MapOutputMode mapMode = this.depth.GetMapOutputMode();
            MapOutputMode mapMode = this.image.GetMapOutputMode();

            this.bitmap = new Bitmap((int)mapMode.nXRes, (int)mapMode.nYRes, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            this.shouldRun = true;
            this.readerThread = new Thread(ReaderThread);
            this.readerThread.Start();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            lock (this)
            {
                e.Graphics.DrawImage(this.bitmap,
                   this.panelView.Location.X,
                   this.panelView.Location.Y,
                   this.panelView.Size.Width,
                   this.panelView.Size.Height);
            }
        }

	protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            //Don't allow the background to paint
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            this.shouldRun = false;
            this.readerThread.Join();
            base.OnClosing(e);
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if (e.KeyChar == 27) { Close(); }
            base.OnKeyPress(e);
        }

        private unsafe void CalcHist(DepthMetaData depthMD)
        {
            // reset
            for (int i = 0; i < this.histogram.Length; ++i)  { this.histogram[i] = 0; }

            ushort* pDepth = (ushort*)depthMD.DepthMapPtr.ToPointer();

            int points = 0;
            for (int y = 0; y < depthMD.YRes; ++y)
            {
                for (int x = 0; x < depthMD.XRes; ++x, ++pDepth)
                {
                    ushort depthVal = *pDepth;
                    if (depthVal != 0)
                    {
                        this.histogram[depthVal]++;
                        points++;
                    }
                }
            }

            for (int i = 1; i < this.histogram.Length; i++)
            {
                this.histogram[i] += this.histogram[i-1];
            }

            if (points > 0)
            {
                for (int i = 1; i < this.histogram.Length; i++)
                {
                    this.histogram[i] = (int)(256 * (1.0f - (this.histogram[i] / (float)points)));
                }
            }
        }

        private unsafe void ReaderThread()
        {
            DepthMetaData depthMD = new DepthMetaData();
            ImageMetaData imageMD = new ImageMetaData();

            while (this.shouldRun)
            {
                try
                {
                    this.context.WaitOneUpdateAll(this.depth);
                }
                catch (Exception)
                {
                }

                this.depth.GetMetaData(depthMD); //【depth情報を得る】
                this.image.GetMetaData(imageMD); //【image情報を得る】

                CalcHist(depthMD); //【depth情報によるヒストグラムの計算】

                lock (this)
                {
                    Rectangle rect = new Rectangle(0, 0, this.bitmap.Width, this.bitmap.Height);
                    BitmapData data = this.bitmap.LockBits(rect, ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

                    ushort* pDepth = (ushort*)this.depth.GetDepthMapPtr().ToPointer();
                    // set pixels
                    /*
                    //【depth情報に基づくHistgramで着色】
                    for (int y = 0; y < depthMD.YRes; ++y)
                    {
                        byte* pDest = (byte*)data.Scan0.ToPointer() + y * data.Stride;
                        for (int x = 0; x < depthMD.XRes; ++x, ++pDepth, pDest += 3)
                        {
                            byte pixel = (byte)this.histogram[*pDepth];
                            pDest[0] = 0; // pixel; //【青】
                            pDest[1] = pixel; //【緑】
                            pDest[2] = pixel; //【赤】
                        }
                    }
                    */

                    //【image情報】
                    for (int y = 0; y < imageMD.YRes; ++y)
                    {
                        byte* pImage = (byte*)this.image.GetImageMapPtr().ToPointer() + 3 * (y+1) * imageMD.XRes -3;
                        byte* pDest = (byte*)data.Scan0.ToPointer() + y * data.Stride;
                        for (int x = 0; x < imageMD.XRes; ++x, pImage -= 3, pDest += 3)
                        {
                            pDest[0] = *(pImage + 2); //【青】
                            pDest[1] = *(pImage + 1); //【緑】
                            pDest[2] = *(pImage);     //【赤】
                        }
                    }

                    this.bitmap.UnlockBits(data);
                }
                this.Invalidate();
            }
        }
    }
}



【備考】
 2011年3月25日現在、OpenNI binariesのWindows向けサンプルプログラムの表示(image, IR, depth)は左右反転しているようだ。鏡に映る自分を見ているように表示されているため、気が付くのが遅れてしまった。恐らく原因は大元のプログラムがOpenGLで記述されていたためだと思われる。解決方法は読み出しポインタか格納ポインタの向きをincreaseからdecreaseに変えて、初期位置を調整するか、テクスチャーマッピングで左右反転させるかだ。上にサンプルプログラムを示した。(赤字部分)
■記載日2011年3月23日■23:00頃記載
【KinectをC#で使う方法は?】
 KinectをC#で使いたいので検索してみたら、OpenNI.orgのダウンロードにC# Wrapperを含んだWindowsのOpenNIバイナリーのUnstable(暫定)版『OpenNI Unstable Build for Windows v1.0.0.25』が公開されていることがわかった。
 早速、ダウンロードしてVisual C#で『参照を追加』してオブジェクトブラウザで確認してみた。おぉ、SkeltonJointとかSceneMetaData, IRMetaData, DepthGeneratorとか使いたいキーワードが見つかった。早速、サンプルプログラムを動かしてみようとしたが、実行時にエラーが出てしまった。エラーメッセージでGoogle検索したら英文で書かれた質問3件が見つかったものの、未解決のエラーらしい。なんでもキーの不整合が原因とか。ちょっと自分でコーディングして動かそうとしたが、やはり同じエラーが出て強制終了してしまう。
 諦めようかと思ったが、SourceフォルダにOpenNI.net.dllのソースが見つかったので、Visual C# 2008でFrameWorks2.0対象にして、OpenNI.net.dllをコンパイルしてみた。正常終了したので、少しサイズが違うが新規にコンパイルし直したものを置き換えてみた。
 ....すると、再コンパイルすればデモ(SimpleRead.net, SimpleViewer.net, UserTracker.net)が3つとも正常に動作してくれた。つまりコンパイラのライセンスに関係したエラーだったようだ。まぁ、動いたからいいや。
 注意点は、ソースに添付のprojectファイルではAssemblyInfo.csしか読み込んでくれないので、『既存項目の追加』で他の.csを読み込む事、幾つか参照を取れていない部分の参照を取り直す事。Dataフォルダ内のSampleConfig.xmlのLicenseタグの正しい指定を追加すること。
<Licenses>
      <License vendor="PrimeSense" key="0KOIk2JeIBYClPWVnMoRKn5cdY4="/>
</Licenses>

 取り敢えず、関節(SkeltonJoint)の3次元座標やキャプチャー画像を使うことができそうだ。殆ど重要な処理はサンプルプログラムUserTracker.netに記述されている。樋口さんのDxOpneNI.dllのソースもDirectXを使う上でとても参考になる。
 不明な点はSkeltonJointをなかなか認識してくれない場合があること。

 ところで、インターネットのニュースで知ったのだが、Microsoft社が今春(正確な日程は不明)Kinect APIを正式に公開してくれるようだ。

 自宅はラビットハウスなのでKinectを使いづらい。京都ラボで作業続行するとしよう。



【DxOpenNI.cppからDxOpenNI.dllを作成する方法は?】

 TK's HPに詳しく書かれていた。
 Visual C++ 2010でビルドする場合、インクルードやライブラリのフォルダーを指定するには、プロジェクト(P)⇒DxOpenNIのプロパティ(P)で『構成プロパティー』の『VC++ディレクトリ』の該当項目を1クリックで選択して指定する。
 ビルドはできたがまだチェックはしていない。なぜかコードサイズが2kB程小さい?? expの分くらい。何か指定が足りない??

 もうひとつ不明点は、C#でDllImportを使ってDxOpenNI.dllを呼ぼうとするが、実行時に各関数を見つけてくれない。Win32APIなら問題なく呼べるのだが、何故なんだろう? そもそも無理なことをしようとしているのだろうか?
 調べたら、.dll呼ぶのに.hと.libが必要らしい。あるいはポインタ(int32)やfloat, charのような単純な型でしか引き渡せないようだ。どこかでTextureをchar[]やファイルにするとか、Vector3をfloat[3]に書き直して引き渡せばいいのかな?作り直してみよう。

【追記】2011/02/07
 OpenNIをダウンロードすると付いてくるドキュメントを見ると、スケルトン情報だけでなく、カラー映像、赤外線映像、Depthバッファ(深さ情報)も得られるようだ。これだけのものがこの値段とは....。1桁~2桁違うような....。
■記載日2011年2月5日■20:00頃記載
【MMDのKINECT】その2
 MikuMikuDanceのDxOpenNI.dllのダウンロードをしてみたら、C++のソース(DxOpenNI.cpp)が付いているのに気が付きました。で樋口優さんのDxOpenNI.cppを読んでみたらとってもわかりやすい関数に思えました。Kinectのデータの取り出しが、部位の番号を指定すれば、DirectXのVector3形式で3次元座標が得られるようです。赤色の画像の方はTextureとして渡されるようなのです。
 こっ、これは便利かも? 私の専門分野はセンシングなので、Kinectをセンサとして重宝できそうです。早速、今日、Kinectを買いに行きました。センサ単体で購入でき、13,320円(ヨドバシカメラ京都店)でした。

【Windows Vistaへのインストール方法】

 で、先にOpenNIというドライバを入れてサンプルプログラムが動くのを確認せよとのことだったので、主にこのページ『まとめ?ブログ』のお世話になりました。
 私の環境(Vista)の場合、『avin2-SensorKinect-0124bd2』ではなく、『avin2-SensorKinect-b7cd39d』をインストールしなければならなかったこと、MikuMikuDanceのDataフォルダに入れるSamplesConfig.xmlのLicensesを以下のように書き換えるところが最後まで引っかかりました。やれやれ、13,320円が無駄にならなくてよかったぁ。(非XBOXユーザーなので)
<Licenses>
      <License vendor="PrimeSense" key="0KOIk2JeIBYClPWVnMoRKn5cdY4="/>
</Licenses>
 テストした感じではサンプリング速度が凄く速いと思いました。
 VB.NETやC#でトライしてみたいと思います。
 Kinectには通常カメラ以外に赤外線カメラが搭載されており、赤外線強度が近くほど強いことを根拠に奥行き(Depth)を測定し、Boneの手前を判定しているようです。よくぞこの値段で製品化したもんだ。これって、Kinectセンサだけ購入されたら売れば売るほど赤字になるんじゃないだろうか?

【Windows7へのインストール方法は?】

 Vistaへの方法は右側に記載した方法で行えたのだが、Windows7はダメだった。いろいろ検索して試したところ、『kinectでMMD(ミクミクダンス)』の方法で動作した。
 原因はProgram Files(x86)/Prime Sense/NITE/Dataフォルダにある3つのxmlだった。前述のページの指定通りにエディットしたものを一旦デスクトップに作成し、該当フォルダにコピー&ペーストして強制的に上書きして初めて動作した。

■記載日2011年2月4日■23:00頃記載
【MMDのPMDで拡張現実:Bone制御のテスト】
 Bone制御のコーディングにかなり手間取っている。多分、PMDファイルのBone制御の部分の意味をしっかり理解できていないからにちがいない。
 今まで知らなかったが、最先端ボーンが存在したり、取り扱いが不明なボーン(回転専用?)ができていたりするためだ。
 このため、ボーン制御の機能チェックを円滑に行うためにもツールを作る必要がありそうだ。問題山積みになってしまった。
 Vertexバッファとの関係がわからなくなってきた。かなりこんがらがってきた。最新版のPMDを使わずにVer.5.xxくらいに戻った方がよいのかも。
 当初は、Web Agent Interfaceだけ製作すれば良いと考えたが、基本操作用のエディタくらいは必要だとわかった。
 頂点、インデックス、材質情報だけ使った固定モデルと違って、汎用性が高いPMDファイルの情報で表示しようとするのはかなり難しい。
 ここまででも明らかなことだが、PMDファイルにはエディタ用と表示用の保存データが存在するが、それ以外にワーキング用のデータも必要で、その使い方とか割り当て方法とかが複数考えられる。実際にMikuMikuDanceがそれらをどのように使っているのか不明なので想像して絨毯爆撃してしらみつぶしに調べるしか方法はない。ここまででPMD爆発事件も30回以上発生。orz....
 下はオリジナルのボーン位置を表示しながら腕や髪の毛を操作しているところ。IKは取り敢えず、後回しだ。
 1か所のボーンを回転させた場合、以降の子ボーンも追従するか試している。
 髪の毛や肌、服の色はPMDファイルはそのままで、ソース中でMaterialを変更している。



■記載日2011年1月29日■23:00頃記載
【MMDのPMDで拡張現実:表情のテスト】
 Bone、IK Boneブロックの読み込みに手間取ったため、時間がかかってしまいましたが、やっと表情処理に成功しました。なるほど、樋口さんが作られたデータ構造がとても合理的だということがよくわかりました。Boneの部分にちょっと不明な点があるのですが、まぁ、ぼちぼちやるとしますか。楽しみです。あと、表情をやってみてAIの方にも力を入れたいと思いました。
【ソース公開中】表情のデモプログラムのソースをプロジェクトファイルで公開しています。



■記載日2011年1月27日■14:00頃記載
【MMDのKINECT】
 2つか3つくらい前のバージョンからMMDにMMDにXbox 360® Kinect™センサー(税込14,800円)で得られるモーションキャプチャー情報を取り込み可能になったとのことだったが、いろいろ忙しくて今日漸く調べることができた。
 樋口優さんのYouTubeチャンネルにテスト動画がアップされていた。動画を見る限り、KINECTのモーションキャプチャー・サンプリング速度が非常に早く、位置が精確であることがわかる。ここまでダイレクトだと、動きから性別までわかってしまう。調教主にハイレベルの踊りのセンスが要求されるわけだ。
 インターネットの情報を見る限り、XBOX本体は必要なく、KINECTセンサだけあればいいようだ。従来800万円~2000万円以上したモーションキャプチャーセンサが1万5千円弱で済むことになるようだ。凄い。
 ドライバーもオープンソースらしい。ということは、ソースを読めばモーションキャプチャーセンサとしてKINECTを使えることになりそうだ。1万5千円なら試にKINECTを買ってみようかなと思える。BONEまでコーディングし終えたらトライしてみたい。
 面白いセンサ・アプリケーションを製作できるかも。




【メモ】
 まだソースに反映していないが、思いついたのでメモ。Sphere Mappingでかなり重くなった負荷を少し軽減する方法を思いついた。
 現状は材質ごとにGPUにVertexデータを転送しているが、通常のパスとSphere Mappingのパスの2回に分離すれば転送は2回で済む。
 1回目は、通常のPositionNormalのポリゴン・フィルとPositionTextureのテクスチャーマッピングを行い、Sphere Mappingはスキップする。このとき、頂点追尾ポインタだけはPMDm.nPointsでスキップする。
 2回目は、Sphere MappingのためにTu, Tvを変更して再度GraphicStreamを転送し直し、レンダリングする。
 これならCPUからGPUへの転送時間がかなり節約されるはず。

【メモ2】
 オブジェクトブラウザで見ていたら、TextureCoordinateIndex.SphereMapとVertexProcessingCaps.SupportsTextureGenerationSphereMapというのがあるようだ。
 使い方は不明だが、楽にGPU側で実行できる方法(レンダリング・モード)があるのかもしれない。勿論、GPUの互換性の問題もあるかもしれない。
■記載日2011年1月27日■11:30頃記載
【PMDで拡張現実】Sphere Mappingにトライ(続き)YouTubeメモ動画
 ちょっと眠ったらなんかひらめいた。GraphicStreamの問題のようで、Sphere Mapping用にUV値を変更する頂点バッファ(Vertex Buffer)とオリジナルの頂点バッファを作り、パフォーマンスはかなり落ちてしまったが、なんとかSphere Mappingには成功したようだ。
 Sphere Mapping用の『初音ミクmetal.pmd』のデータは材質1が全身緑色のメタリックで、テスト用なのか、それともAlpha Blendingとか使用して描画するための下地なのかはわからない。これに関しては情報不足だし、もう考えないことにしよう。
 MikuMikuDanceの仕様は私のようなDirectX初心者には複雑過ぎる。本も読んでないし、GPUとCPUの切り分けも理解できず、無理。なので、Sphere Mappingらしきものになんとか成功したことで大満足。
 もっとManaged DirectXに慣れてきたら、このStream関連部分を見直すことにしようと思う。
 今回、『Sphere Mapping』のコーディングを通して、CPU側で座標変換を実施する練習ができた。Bone制御は実現できそうに思える。先に表情に入ろうと思う。だが、AIとのインターフェース仕様をよく考えておかないと.....。

                    int j = 0; int k = 0; int sw;                       //【Traverse関連】[sw] 0:通常 1:テクスチャー 2:Sphere
                    Matrix matWorld, matView, matWV;                    //【SphereMap関連】
                    float m11, m12, m13, m21, m22, m23, m31, m32, m33;  //【SphereMap関連】
                    float nx, ny, nz;                                   //【SphereMap関連】
                    for (int i = 0; i < PMDm.nMaterial; i++)
                    {
                        this._device.Material = PMDm.Material[i];
                        k = PMDm.nPoints[i];
                        this._device.SetTexture(0, null);
                        sw = 0; 
                        if (PMDm.TextureFileName[i] != "")
                        {   sw =1; if (PMDm.SphereMap[i]) { sw = 2; }
                        }
                        
                        switch(sw)
                        {   case 0: //【Polygon Fill】通常のポリゴン描画
                                this._device.SetTexture(0, null);
                                //【頂点バッファをロックする】
                                using (GraphicsStream data = this._vertexBuffer.Lock(0, 0, LockFlags.None))
                                {
                                    data.Write(PMDv.OriginalVertex); // 頂点データを頂点バッファにコピーします
                                    this._vertexBuffer.Unlock(); // 頂点バッファのロックを解除します
                                }
                                break;
                            case 1: //【Texture Mapping】
                                this._device.SetTexture(0, PMDm.Texture[i]);
                                //【頂点バッファをロックする】
                                using (GraphicsStream data = this._vertexBuffer.Lock(0, 0, LockFlags.None))
                                {
                                    data.Write(PMDv.OriginalVertex); // 頂点データを頂点バッファにコピーします
                                    this._vertexBuffer.Unlock(); // 頂点バッファのロックを解除します
                                }
                                break;
                            case 2: //【Sphere Mapping】
                                this._device.SetTexture(0, PMDm.Texture[i]);
                                // 現在のワールドビュー座標を取得
                                matView = this._device.GetTransform(TransformType.View);
                                matWorld = this._device.GetTransform(TransformType.World);
                                matWV = matWorld * matView;
                                // 処理速度を上げるためにワールドビュー座標の要素を抽出
                                m11 = matWV.M11; m21 = matWV.M21; m31 = matWV.M31;
                                m12 = matWV.M12; m22 = matWV.M22; m32 = matWV.M32;
                                m13 = matWV.M13; m23 = matWV.M23; m33 = matWV.M33;
                                // 各頂点に対してをループし、トランスフォームと正しいテクスチャ座標の計算を行う
                                int jj;
                                for (int ii = j; ii < (j + k); ii++)
                                {
                                    jj = ii % PMDv.nPoints;  //【VertexBufferを何回もなめているようだ。MMDはAlphaBlendしてる?】
                                    nx = PMDv.UserVertex[jj].Normal.X;
                                    ny = PMDv.UserVertex[jj].Normal.Y;
                                    nz = PMDv.UserVertex[jj].Normal.Z;
                                    // zコンポーネントをチェックして後ろ側を向いている頂点をスキップ
                                    if (nx * m13 + ny * m23 + nz * m33 > 0.0f)
                                    {   // スフィアマップのテクスチャ座標を割り当てる
                                        PMDv.UserVertex[jj].Tu = 0.5f * (1.0f + (nx * m11 + ny * m21 + nz * m31));
                                        PMDv.UserVertex[jj].Tv = 0.5f * (1.0f - (nx * m12 + ny * m22 + nz * m32));
                                    }
                                }
                                //【頂点バッファをロックする】
                                using (GraphicsStream data = this._vertexBuffer.Lock(0, 0, LockFlags.None))
                                {
                                    data.Write(PMDv.UserVertex); // 頂点データを頂点バッファにコピーします
                                    this._vertexBuffer.Unlock(); // 頂点バッファのロックを解除します
                                }
                                break;
                        }
                        this._device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, PMDv.nPoints - 1, j, k);
                        j += k;
                    }
    




■記載日2011年1月27日■04:00頃記載
【PMDで拡張現実】Sphere Mappingにトライ
 『Sphere Mapping』が気になったので対応を試みた。結果はSphereMap自体はポイのができたが、眼のUVがおかしくなった。
 ??? うーん、難しい.....。
 『Sphere Mapping』とは、視線ベクトルとモデル頂点の法線ベクトルのなす角によって球状UV空間へのマッピングを行い、疑似的に周囲空間の映り込みを表現する手法だ。MikuMikuDanceではステージ衣装にメタリック感を与えるために使われている。
 sphファイルはbmp形式ファイルの修飾子だけを変えたbitmapファイルだ。このsphファイルに魚眼レンズで見たように周囲の環境をマップしておけば服に周囲の様子が映り込むのだ。
 注視点から周囲環境へのビューを毎フレームごとに球体(sphファイル)にマップするように作れば、疑似環境マッピングが行えるはず。
 Microsoftのサイトを参考にしてコーディングしてみたが、前述の眼の表示不具合が発生してしまった。なかなかうまく行かない。
 いろいろ試行錯誤してみてVertexBufferが何回かトラバースされていることがわかった。Shere Mappingに伴ってUV空間データが上書きされているのが原因のようだが......
 Sphere Mappingモデルでは眼にキラキラ感を与えるために、Alpha Blendingしてあるのだろうか?
 ここら辺の詳細仕様は不明だし、樋口さんのモデル表示品質仕様へのこだわりがあって結構複雑なのかもしれない。
 toneの使い方もわからないし、全く同じように表示するのは不可能だろうなぁ.....。
                    int j = 0; int k = 0;                               //【Traverse関連】
                    Matrix matWorld, matView, matWV;                    //【SphereMap関連】
                    float m11, m12, m13, m21, m22, m23, m31, m32, m33;  //【SphereMap関連】
                    float nx, ny, nz;                                   //【SphereMap関連】
                    for (int i = 0; i < PMDm.nMaterial; i++)
                    {
                       k = PMDm.nPoints[i];
                       if (PMDm.TextureFileName[i] != "")
                       {  this._device.SetTexture(0, PMDm.Texture[i]); 
                          //【SphereMapの為の処理】
                       if (PMDm.SphereMap[i]) //【ファイル名がsph形式の場合】
                       {
                           this._device.RenderState.AlphaBlendEnable = true;                 //【SphereMapの為のテスト】
                           this._device.RenderState.SourceBlend = Blend.SourceAlpha;         //
                           this._device.RenderState.DestinationBlend = Blend.InvSourceAlpha; // 
                           
                           // 現在のワールドビュー座標を取得
                           matView = this._device.GetTransform(TransformType.View);
                           matWorld = this._device.GetTransform(TransformType.World);
                           matWV = matWorld * matView;
                           // 処理速度を上げるためにワールドビュー座標の要素を抽出
                           m11 = matWV.M11; m21 = matWV.M21; m31 = matWV.M31;
                           m12 = matWV.M12; m22 = matWV.M22; m32 = matWV.M32;
                           m13 = matWV.M13; m23 = matWV.M23; m33 = matWV.M33;

                           // 各頂点に対してをループし、トランスフォームと正しいテクスチャ
                           // 座標の計算を行う
                           int jj;
                           for (int ii = j; ii < (j + k); ii++)
                           {
                               jj = ii % PMDv.nPoints;  //【VertexBufferを何回もなめているようだ。MMDはAlphaBlendしてる?】
                               nx = PMDv.UserVertex[jj].Normal.X;
                               ny = PMDv.UserVertex[jj].Normal.Y;
                               nz = PMDv.UserVertex[jj].Normal.Z;
                               // zコンポーネントをチェックして後ろ側を向いている頂点をスキップ
                               if (nx * m13 + ny * m23 + nz * m33 > 0.0f)
                               {   // スフィアマップのテクスチャ座標を割り当てる
                                   PMDv.UserVertex[jj].Tu = 0.5f * (1.0f + (nx * m11 + ny * m21 + nz * m31));
                                   PMDv.UserVertex[jj].Tv = 0.5f * (1.0f - (nx * m12 + ny * m22 + nz * m32));
                               }
                           }
                       }
                       else
                       {
                           this._device.RenderState.AlphaBlendEnable = false;                 //【SphereMapの為のテスト】
                           int jj;
                           for (int ii = j; ii < (j + k); ii++)
                           {
                               jj = ii % PMDv.nPoints;  //【VertexBufferを何回もなめているようだ。MMDはAlphaBlendしてる?それとも上書きのせい?】
                               PMDv.UserVertex[jj].Tu = PMDv.OriginalVertex[jj].Tu;
                               PMDv.UserVertex[jj].Tv = PMDv.OriginalVertex[jj].Tv;
                           }
                       
                       }
                       }
    



■記載日2011年1月23日■
【PMDで拡張現実】
 Excel VBAでやりかけて長い間中断していた作業をVisual C# 2010で再開【ソース公開】しました。NyARToolkitCSで拡張現実センシングにトライ中ですが、ちびミクはテクスチャーマッピングなしの簡単モデルに改造していたので、今回はテクスチャーマッピング混在モデルでも表示できるようにMikuMikuDanceのPMDファイル形式に合わせて作り直しています。SPHやJPGにはまだ対応していませんが、まぁまぁ表示できるようになってきました。やっぱりExcel VBAなんかやってられませんね。(当たり前か。)
   【ソース公開中】
 FileStreamとBinaryReaderを使ってPMDファイルからデータを読み込むようにしました。この過程で、構造体を少し変更。C#でのString演算やManaged DirectXの事も殆ど理解できていないので、CustumVertex.PositionNormalTextured形式の効用を理解できるまで、ちょっと試行錯誤してしまいました。結果、樋口さんの設計されたPMDファイルの構造は結構簡単に材質分割描画できる優れた構造だったということが理解できました。
 まだ、Meshの使い方がわからないので、とりあえず次は表情から行きます。

 CQ出版の【トランジスタ技術 増刊】『今すぐ使える パソコン計測USBマイコン基板』を使って、内蔵温度センサで一連の動作ができるところまで、プログラミング・テクニックを身に着けることが今回の目標です。『バイナリは配布しませんが、ソースはプロジェクトを公開します。』ARsensorのページにて予定。
 Excel VBAではポリゴン・フィルやテクスチャーマッピングまで全部記述していたのに比べれば、Managed DirectXはシンプルな記述で済んで、短時間でコーディングできてしまうのですが、如何せん仕様が私には少し複雑過ぎるようです。
 Meshとか理解できていたらもっと楽なんでしょうね。きっと。..................今回、使いませんでしたが。

 気が付いた点は、まず、NyARToolkitCSの座標系は左手系なので、PMDファイルから読み込む際に、頂点座標Zと法線ベクトルNzはそれぞれ-Z, -Nzに変換しています。袖の中やスカートの中が透明にならないように
    this._device.RenderState.CullMode = Cull.None;
と指定しています。このCullは本来は非力なハードウェアで少しでも描画速度を上げる際のオプションです。三角形の法線ベクトル(外積)の向きが視点方向なら描画し、反対向きなら『隠れて見えない側』にあるポリゴンと判断して描画しないことで、半数のポリゴンを描画せずに済ませようという考えから生まれたのですが、これは分子設計CADの時代の名残です。スカートなどはモデルの内側を向いていても、視点からは見えなければならないので、このオプションは不都合があるわけです。

■記載日2011年1月20日■
コミPo!(その3)
コミPo!の無料体験版がVer.1.10となり、ダウンロードできます。無料で2/28まで使えるそうです。
で、Ver.1.05を削除して、Ver.1.10をダウンロードしてみました。
改善された点は下図に示すように、ポーズ選択ダイアログで首の傾きを変更できるようになった点。
3つのスライダーで首のボーンだけ変更できるようになった。
プリセット・ポーズからQuartanionを使って、全ボーン変更可能になる日も近いか?
やっぱり、ボーン変更は要望が多かったんだろうなぁ。いっそMMDのPMDが使えればもっといいんだろうけど。




■記載日2011年01月11日■
 下の記述に加えて、目的のソリューションを開いてからVisual C# 2010 Expressのメニューで『プログラム(P)』-『*******のプロパティー(P)』でプログラムのプロパティー・ダイアログを開く。『アプリケーション』タブを選択して『対象のフレームワーク(G)』を『.NET Framework 3.5』に設定し、『ファイル(F)』-『全てを保存(L)』で保存したら一度Visual C# 2010を終了し、再起動。『ビルドB』し直せば、ヤッタぁ!!NyARToolkitCSがVisual C# 2010で動いた!  ●これで漸く2010年4月20日時点の状態に復帰。

■記載日2011年01月10日■
 下のメモを書いた後、もう一度Windowsのフォルダを調べていたら偶然に見つけた。
   C:/Windows/Microsoft.NET/DirectX for Managed Code/1.0.2902.0/  の下にMicrosoft.DirectX.dll, Microsoft.DirectX.Direct3D.dll, Microsoft.DirectX.DirectDraw.dllがあった。  Microsoft.DirectX.Direct3DX.dllも同じフォルダにあるが、フォルダ1.0.2911.0/の下にある方が最新版のMicrosoft.DirectX.Direct3DX.dllのようだ。
 Visual C# 2010のメニューから、プログラム(P)-参照の追加(F)で『参照の追加』ダイアログを表示し、『参照』タブを選択クリックして、前述のdllを参照すればいいようだ。
 これでManaged DirectXが使えそう。

■記載日2011年01月09日■
 久しぶりにCQ出版のトランジスタ技術に『ARセンサ』の件で記事を投稿しました。2011年2月号(1/8発売)に『磁界&超音波リアルタイム・ビューワ』が掲載されました。この記事は、トランジスタ技術【増刊】『今すぐ使える パソコン計測USBマイコン基板』付録の基板を使って作ったセンサでNyARToolkitCSを使って計測結果を拡張現実表示させたのですが、電子回路初心者のために付録基板に内蔵された温度センサを使っただけのデモ・プログラムも作りソース公開しました。
 簡単な動画も作成しました。CQ出版のサポートページにも掲載されています。
 この付録基板、内蔵温度センサの他にアナログ入力3チャンネルとディジタルI/Oを7ビット分備えており、パソコンと簡単なテキスト通信だけでやりとりできるので、いろいろな拡張現実用操作デバイスの実験に使えそうです。
 Windows7にVisual C# 2010 Expressを入れたらManaged DirectXFrameworksがすっかり変わっているし、ウェブカメラや付録基板のデバイスドライバはうまくインストールできなくて手間取るは...パソコンとの通信プロトコールを調べるのに手間取ってしまうし... 3次元モデルを使うところまで間に合わなかったのがちょっと残念。結局、間に合わないからまだ公開されているVisual C# 2008 Express版をインストール、1時間半程でPowerPointの基本図形を使って11コマの2次元パターン画像を作り、ごまかしてしまいました。orz....(本当はちびミクちゃんの髪の毛をドライヤーで乾かす動画を製作したかったのだが... orz...4月まで時間が取れそうにない。)
 今度は3軸加速度センサとGPSレシーバを実装して再チャレンジしてみようと思います。

 MikuMikuDanceの方もバージョンアップに伴ってKinectとのインターフェース機能が実装されたようですし、ますます拡張現実化が進んでいきそうで楽しみです。

■記載日2010年11月19日■
NyARToolkitCSで遊んでみました
今年4月にちょっとだけNyARToolkitCSに触っていましたが、センサから作って実際に動かしてみました。センサがないと意味はあまりないんだけれどソースは公開するつもりで資料作成始めました。亀足です。
ガンのポリゴンモデル作るのが面倒だったので、3次元ゲージとちびミクの2次元表示面だけですけどね。遊びで作るとDirect3Dも理解し易いですね。今度はPMD版作ってみたいと思います。冬休みにでも書いてみるかなぁ。
センサの種類も吟味して考えれば何か使い道あるかも。

【説明】左側にあるコイルに高周波電流を流して微弱な磁界を発生させています。大層な回路は高周波磁界を捉えるセンサです。パソコンにデータを引き込んで、NyARToolkitCSで検出したマーカーオブジェクトに対する座標変換マトリックスからセンサ位置への座標変換マトリックスを求めて測定値に応じて球体の表示色を変えて表示しているだけです。しきい値レベル200で表示をちょっとだけ変えています。
AR sensor(拡張現実センサ)のページを独立して作成することにします。

【過去記事メニュー】

【↓記事へのリンク】

【↓記事題名】

記載日2010年11月19日~2011年12月25日の記事 記載日2010年11月19日~2011年12月25日の記事
まだまとめていません。
記載日2010年12月10日 コミPo!(その2)
記載日2010年11月10日 コミPo!って知ってます?
記載日2010年10月29日 イギリスで初音ミクが人気
記載日2010年08月04日 PMDデータを再利用されにくくする方法
記載日2010年07月31日 PMDデータに著作権はあるのか?
記載日2010年07月22日 Holophonics Augmented Realityに挑戦中
記載日2010年06月27日 【YouTubeで樋口優さんのチャンネル発見!
記載日2010年06月20日 【待望のKumane Mikuの動画が完成したとのこと】
記載日2010年06月15日 【Panoramio向け写真閲覧用公開ツール上でMikuMikuDanceの布教活動】
記載日2010年06月13日 【MikuMikuDanceに実装された機能に今頃気が付いたよ】
記載日2010年06月08日 【やっぱりなかなか速度がでない。ぱらぱらならどうだろうか。】
記載日2010年05月23日 【初音ミクが『あかつき』に搭乗。宇宙へ。】
記載日2010年04月16日 【Mikuが逆パターン[実写⇒カメラVMD]を発見。それに続いて同パターン先行事例も。】
記載日2010年04月15日 【VMDデータってどうなっているんでしょ?】
記載日2010年04月10日 【ARToolKitを少しいじってみる(続き2)】
記載日2010年04月09日 【ARToolKitを少しいじってみる(続き)】
記載日2010年04月07日 【ARToolKitを少しいじってみる】
記載日2010年04月03日 【VBAのバグ直しておきました】
記載日2010年04月02日 【久しぶりにVBAを触ってみる】
記載日2010年04月01日
記載日2010年04月15日
(セルフ・シャドウに関して勘違いに勘違いを重ねたので記事移動してまとめます。)
記載日2010年03月15日 【えぇ?設定ミス?】
記載日2010年03月13日 【ちょっと忘れていたけど動画削除対応をMikuに移管する】

過去記事・メニューの表示】 チェックを入れると2008年3月11日~2010年2月までの記事メニューがプルダウン表示されます。