note報告とか備忘録とか。Calendarの2日目の記事です。バインドの発表をしてきたです。明日の記事はboochnichさんです。JavaFX8で3D周りの機能が正式に追加され、JavaFX単体で3Dを扱うアプリケーションが作られるようになったのでMMDモデルを表示することに挑戦してみました。今まで自分は3Dプログラミングをほとんどやったことがなかったのでいろいろと探りながらの挑戦になりましたが、その過程で感じたことや思ったことについて書いていきます。MMDモデルとは最近では個人制作によるモデル以外に、アニメ制作会社やメディア系の学校による公式MMDモデルが配布されるようになるくらいには知名度のある3Dモデルフォーマットになったと個人的に感じているMMDモデルですが、元は樋口氏によって開発されたMikuMikuDance専用の3Dモデルフォーマットです。これが実際にモデルを表示しているところです。左で表示をちょっとだけコントロールすることができます。右では読み込まれたモデルの情報を確認できます。Viewerのようにマウスクリックでグリグリ動かせるようにしたかったのですがそこまでは時間とかの都合で実装できませんでした......。ソースコードはGitHubに上げてあるのでいろいろとアドバイスなどもらえると嬉しいです。JARファイルはこちらからダウンロードできます。プログラムを書いていく上で思ったこととか感じた事ここから実際に書いていく上でどうだったかについて述べていきたいと思います。3Dですが、日本語で書かれた資料が少ないと感じました。Overflowなど海外の情報サイトなどをあたりながら理解を深めていきました。TriangleMesh特に厄介だったのはTriangleMeshの扱いです。TriangleMeshは三角メッシュによる3D形状を表現するクラスなのですが、このTriangleMeshの使い方についての情報が少なく非常に苦労しました。Viewerのソースを読めば良かったんじゃないかと思ってます。TriangleMeshは主に3つの要素から成り立っています。1つ目は頂点情報の配列、2つ目がテクスチャ座標情報の配列、そして3つ目は面情報の配列です。それぞれgetPoints()、getTexCoords()、getFaces()で取得でき、ObservableArrayの拡張クラスが返ってきます。ここで取得したObservableArrayの拡張クラスに対して座標や座標インデックスを追加していくことで3Dモデルを構築できます。getPoints()で取得できるのはObservableFloatArray型のオブジェクトで、1つの点についてx座標、y座標、z座標の順に格納していく必要が有ります。そのため、このオブジェクトに格納されるデータ数は3の倍数となります。3Dはy座標が正の方向が下向きになっているので、何もしていないと構築したモデルが上下逆向きになってしまいます。getTexCoords()で取得できるのはObservableFloatArray型のオブジェクトで、1つのテクスチャ座標についてx座標、y座標の順に格納していく必要が有ります。そのため、このオブジェクトに格納されるデータ数は2の倍数となります。getFaces()で取得できるのはObservableFaceArray型のオブジェクトで、1つの三角面について3つの座標インデックスとテクスチャインデックスが必要になります。格納順序は座標1、テクスチャ座標1、座標2、テクスチャ座標2、座標3、テクスチャ座標3となります。そのため、このオブジェクトに格納されるデータ数は6の倍数となります。テキストだけで書くと分かりづらいので図にしてみます。図にしても微妙に分かりづらい気がしますがこんな感じです。これら3つの要素以外にもスムージングの設定などがあります。TriangleMesh関連は今後もいろいろと記事を書いていこうと思います。SceneとSubSceneJavaFXアプリケーションでは起動時にSceneを作成してステージにセットするのが普通だと思いますが、この時のSceneは2D用であることがほとんどだと思います。深度バッファが無効なため、そのまま3Dモデルを表示しようとすると酷いことになります。深度バッファが無効のときちょっとホラーっぽいですね。そのため、SubSceneを深度バッファを有効にして作成し、適当なNode内に貼り付けそこに3Dモデルを表示することになります。この時にアンチエイリアスについても設定できます。最初から3Dのみで画面を構築するならSceneを3D用に生成するのもありだと思いますが、コントローラーなどを置こうとするとSceneとSubSceneで分けるほうが良いと思います。3DではPhongシェーダーしか利用できません。そのため、デフォルトでトゥーンシェーダー寄りのMMDでの表示結果とはやや異なった雰囲気になります。アンビエントライトの設定などを行うとそれっぽくはなりますが、調整が難しかったです。シェーダーを導入しようという計画はあったそうですが、前回の関Java報告記事で書いたように見送られたそうなので非常に残念です。Materialを自分で実装すればPhongシェーダー以外も使えるのかもしれませんが試してないのでわかりません。3Dプログラミングの知識がないと引っかかるある程度簡単に3Dが扱えるとは思いましたが、それでも3Dプログラミングの知識がない状態だと所々で躓きました。事前に3Dプログラミングについて勉強してから触るほうがすんなり書けるんじゃないかと思います。3D特有の問題を除けば。3Dを一通り触ってみて感じたのは、少し癖はありますが慣れればそれなりに書きやすいということです。3Dプログラミングの知識がゼロだと分りにくい場所があるのと、座標系の扱いが一般的でないので事前知識や工夫が必要な部分が面倒でした。今回作ったMMD表示アプリケーションですが、拡張してモーションなどにも対応させたいと思います。IKやボーンの処理が非常に辛いものになりそうな気がしますが。この記事を皮切りに、JavaFXや3D関係の記事を書いていきたいと思います。コメントをキャンセルメールアドレスが公開されることはありません。