みなさん、今日は何の日かご存じですか?
そう、イエス・キリストがこの世に降誕したと言われるクリスマスです。
それに因んでクリスマスまでのカウントダウンカレンダーをAdvent(降臨) Calendarと呼ぶ風習がキリスト教国で出来ました。
そして、その風習がエンジニアに見つかってしまった結果、12月は色々なもの[1][2]が降臨する月となりました。
このD言語 Advent Calendarもその一つです。
最終日となる今日は、D言語を書いてD言語くんを降臨させましょう
D言語くんとは
ちなみに日本語訳版サイトだとトゲトゲしい粗い画像になってます。
D言語くんはD Ver.0.x時代から存在しているので、おそらく後から本家の方がハイレゾに差し替わったんだと思います。
下のD言語くんが日本で広く知られている方のD言語くんの姿ですね。
三次元と化したD言語くん
D言語くんの二次元画像は昔から存在していましたが、
ポリゴンモデルは長い間ありませんでした。
ですが先週唐突に3Dモデルが誕生しました。
![D言語くん](https://pbs.twimg.com/media/Bbvd_jfCQAAuSH5.png)ボーンを入れて、例のポーズ取らせて出来上がり! #D 言語 pic.twitter.com/8aTkaIMbbt
— イ五 (@fifth_tea) December 18, 2013
モデルもMetasequoiaフォーマット(.mqo)とMiku Miku Dance用フォーマット(.pmd)で公開されています。skydrive
今回はこれを使ってD言語くんを降臨させます。
使用ライブラリ
最初の課題
Derelict3に含まれているOpen Asset Import Library(Assimp3)とGLFW3を使って実装しようかと思いましたが、非常に大きな問題がありました。
- .mqoと.pmdに対応していない
なんとAssimp3は日本で圧倒的なアマチュア人気を誇るMetasequoiaとMiku Miku Danceに対応していません。
Blender等でCOLLADAかFBXにエクスポートしてやれば使えますが、 ただただ面倒くさい(フォーマット変換が万能というわけでもないし) - Assimp3→GLFW3変換が面倒
Assimp3は多くのモデルファイルを読み込めますが、読み込むだけでOpenGL等で表示するためには更に一手間蓋手間必要となります。
そうなるとAssimp3とGLFW3のコード量が増えD言語の記事では無くなるので今回はやめにしました。
この記事を書こうと決めたこと自体たった5日前だし
なので今回は
- メタセコイア形式もMiku Miku Danceモデルも読める
- 高機能APIなのでサンプルコードがシンプル
なDXライブラリを使ってD言語くんを表示します。
D言語はC言語とバイナリ互換なので 、C言語製のライブラリをちゃっちゃと弄ればD言語プログラムの中で関数や変数や構造体を使うことも出来ます。
今回は羽流布さんが公開しているD言語版DXライブラリ3.11を用います。vector
コードを書く
初めてDXライブラリを書いたので良く分かってませんがこういうコードでMMDモデルを表示できるみたいです。
PMDファイルとVMDファイルは事前に用意したものを置いておけば1行で読み込めるみたいです。
module main;
import dx4d;
import string;
import std.file;
void main()
{
int count, x, y;
try
{
int mHandle;
VECTOR Camera;
dx_ChangeWindowMode(TRUE);
if (dx_DxLib_Init() < 0 )
{
throw new Exception("DXライブラリの初期化に失敗");
}
if ((mHandle = dx_MV1LoadModel("data/Mr_D.pmd")) == -1)
{
throw new Exception("モデルの読み込みに失敗");
}
Camera.x = 0.0f;
Camera.y = 10.0f;
Camera.z = -20.0f;
dx_SetBackgroundColor(0, 0, 255);
dx_ClearDrawScreen();
dx_SetCameraNearFar(1.0f, 150.0f);
dx_SetCameraPositionAndTarget_UpVecY(Camera, dx_VGet(0.0f, 10.0f, 0.0f));
if (dx_MV1AttachAnim(mHandle, 0, -1, FALSE) == -1)
{
throw new Exception("アニメーションの再生に失敗");
}
dx_MV1SetAttachAnimTime(mHandle, 0, 0.0f);
if (dx_MV1DrawModel(mHandle) == -1)
{
throw new Exception("モデルの描画に失敗");
}
dx_WaitKey();
}
catch( Exception e )
{
std.file.write( "error.log", e.msg );
}
finally
{
dx_DxLib_End();
}
}
くぅ~疲れましたw これにて完結です!