【2023/5/23】3Dモデルが正しく描写されない問題についてのパターンをさらに追記。
DXライブラリとC/C++で3Dゲームを作っているのだが、3Dモデルが正しく描写されずしばらくここで足踏みしてしまった。3Dモデルが全く描写されない場合と描写はされるが何かおかしいという場合があるので両方について説明。
3Dモデルが描写されない
Blenderで最初から表示されている立方体に上の画像のようにちょいと色付けをしてをfbxで出力、DxLibModelViewerでmv1に変換。そしてDXライブラリ置き場のサンプルプログラムを参考に3Dモデルを描写してみたが、下の画像のように3Dモデルが描写されなかった(見えている線はDrawLine3Dでデバッグ用に引いたもので3Dモデルとは関係ない)。
本来ならこうあってほしいのだが…
DXライブラリでは3Dモデルの読み込みをMV1LoadModelを使って行い、MV1DrawModelで描写を行う。この2つの関数に不備があるとは思えない(あれば対策を調べた際にもっと情報が出てくるはず)ので99%こちら側のミスだろう。とりあえず超基本的なところから見直してみた。
全く描写されない場合
3Dモデルが何一つ描写されないというパターン。パス指定のミスとかカメラの視野に入ってないなど。
3Dモデルを読み込む際に指定するパスを確認する
まずMV1LoadModelで3Dモデルを読み込むのだがそのときに指定するパスが正しいかどうか最初に確認。パスには絶対パスと相対パスの2つがあるがどちらにせよ指定先を間違えていると読み込めないのでパス名に誤りがないか、パスの指定先にちゃんと3Dモデルがあるか確認する。
例えばVisual Studioで作成していてslnやvcxprojファイルがある場所に3Dモデルを入れているフォルダがある場合、相対パスで以下のように指定する。
int ModelHandle; //3Dモデルを格納する変数 /*中略*/ ModelHandle = MV1LoadModel("(フォルダ名)/(3Dモデルのファイル名).mv1");
MV1DrawModelに対応しているファイルかどうか確認する
MV1DrawModelで扱える3Dモデルのファイルは以下の4つ。
x, mqo, mmd(vmd), mv1
これ以外のファイル形式は扱うことができないので注意。fbxに関してはとある専用のファイルをDLすることで使えるようになるが大変面倒らしい。こちらのページにて。
xは一昔前の標準だったファイル形式。そのためか一部の情報を保存できないため今では使われない(今の標準はfbx)。
mqoはメタセコイアで作ったときのファイル形式。
mmd(vmd)はニコニコで有名なMMDのファイル形式。
mv1はDXライブラリ専用のファイル形式。DXライブラリをDLしたときに付属でついてくるDxLibModelViewerでこの形式で保存できる。ちなみにDxLibModelViewerで扱えるファイル形式はx, mqo, mmd(vmd), mv1, fbxの5つ。
DXライブラリと相性がいいとされているmmd(vmd)でもそのまま使うと一部挙動が変わるらしいので DxLibModelViewerでmv1に変換するのが無難。
最近出てきたVRoidモデルに使われるvroid, vrmは今のところ未対応。なのでこちらもfbxで出力してmv1に変換することになる。なおvrmからfbxに出力するときはマテリアル・テクスチャの再指定が必要なので注意。
MV1DrawModelのあるところを通っているか確認
コード上のミス。超初歩的だがコメントアウトしてるのをうっかり忘れたりすることも。デバッグで1行ずつ追って確認しましょう。
カメラの視野に3Dモデルがあるか確認
3Dモデルがカメラの視野外にあったり、3Dモデルが大きすぎてカメラが内側に入ったりすると3Dモデルが全く表示されないように見えるので注意。
3Dモデルやカメラの座標を調整する場合、DXライブラリをDLしたときについてくるDxLibModelViewerに3Dモデルを読み込ませるとカメラ座標や注視点座標が表示されるのでそれを参考に調整。
カメラの視野(カメラが描写する範囲)を調整したい場合はDXライブラリ本家のカメラ関数のリファレンスページを参考に。
モデルの大きさを調整する場合、専用の関数MV1SetScaleがあるが3Dモデルの制作ソフト側で調整するのが無難。
描写はされるがどこかおかしい場合
3Dモデルの描写はされるけどなんか暗い、一部だけ描写されていない、前後関係がおかしい場合など。
3Dモデル出力時のミス
うっかりミス。Blenderの場合、出力時に非表示となっているオブジェクトなどは出力ファイルに含まれなくなるので注意。
テクスチャが表示されない
これは3Dモデルの方のテクスチャパスが外れている、リンク切れ状態になっているせい。読み込むモデルの数が増えてきたので新しいフォルダを作って整理したりするとなりがち。
3Dモデルとテクスチャファイルの位置を正しくすれば直るが、コード上からテクスチャファイルを指定することも可能。
あと上にも書いたがvrmファイルをfbxファイルにした場合テクスチャ情報が消えるので再指定する必要があるのに注意(マテリアル情報としては残ってはいる)。
全体的に暗く描写されている
ライティングの処理をオンにしているとBlenderなどで見た時より暗く見えることがある。モデルのマテリアルの「自己発光」の値を上げると明るく見えるようになる。自己発光の値はDxLibModelViewerで調整するのが一番簡単。
ライティング描写をオフにする手もあるが光源の影響を全く受けなくなるので特定の色に照らされるといった描写はできなくなるので注意。
この問題はそれなりのクオリティの作品を作るとなると最終的にはシェーディングの処理を自前で書いて制御することになるかと。
裏面が描写されていない
Blenderなどと違ってDXライブラリでは裏面はデフォルトでは描写しない設定になっている。
MV1SetMeshBackCulling関数で描写させることはできるがライティング処理が表面の結果をそのまま使うため違和感が出ることが多い。なのでBlenderなどであらかじめ裏面を作っておくのが吉。
前後関係がおかしい
下着が上着より前に出ているとか奥にあるオブジェクトが一番前に出ているように見えるといった場合はオブジェクトの描画順に問題がある。
この場合はMV1SetUseZBuffer関数とMV1SetWriteZBuffer関数でZバッファをオンにする。3Dモデルに半透明情報がある場合は次の項目にて。
下着が上着より前に出てきてしまっているといった場合はBlenderなどで体・顔・髪・下着・上着・靴・アクセサリー…とオブジェクトを細かく分けて出力し、オブジェクト単位(DXライブラリではフレームという)で1つずつ順番描画する。
MV1SearchFrame関数でオブジェクト名と一致するフレームを検索し、そのフレーム番号をMV1DrawFrameで描画するのが基本の流れ。
3Dモデルに透明度の情報がある場合
ガラスとか氷とか半透明情報があるものを描写するときはその部分だけ別途描画する必要がある。
半透明情報がない部分を先に全部描画したあと、半透明情報がある部分をカメラから見て奥から順に描画すると正しく描画されるようになる。
DXライブラリには残念ながら半透明情報がある部分を奥から描写する関数(Zソート)はないので自分で関数を作りましょう。
コメント