『3D格闘ゲーム プログラミング』 Q&A

以下の回答で問題が解決しなかった場合には、 こちらから ご連絡ください。

コンパイル・ビルドに関する質問

2008/09/17
Q.
DShow.hがincludeできないためにビルドできません。
A.
 DShow.hはDirectShow関連のヘッダファイルです。DShow.hはWindows SDKに含まれています。誠にお手数ですが、本書p.290〜を参考にWindows SDKをインストールしてください。
 なお、本書のライブラリにはDShow.hを使ったクラスが含まれていますが、サンプルではこのクラスを使用していません。そのため、以下の要領でこれらのクラスを削除してビルドする方法もあります。


実行に関する質問

2009/10/13
Q.
シェーダを有効にすると正常に描画されません。
A.
 シェーダを有効にしたときに正常に描画が行われない場合には、誠にお手数ですが、以下をお試しください。

 以上の条件を満たした場合でも、グラフィックカードによっては描画に不具合が出てしまうことがあります。以下はご連絡を頂いたものです。ドライバやランタイムのバージョンなど、環境によっては以下とは動作が異なる場合も考えられます。  大変申し訳ございませんが、この場合はシェーダを無効にしてご利用頂けますようお願い申し上げます。影の生成はできないのですが、キャラクターの表示・アニメーション・技の発生・当たり判定処理といった他の機能は、シェーダの有無にかかわらず同等にお使い頂けます。

2009/10/13
Q.
debugモードよりもreleaseモードが高速なのはなぜですか。
A.
 debugモードは主にデバッグに使用するビルドモードです。一般に最適化を行わず、インクリメンタルリンク(差分だけをリンクする機能)を行うため、ビルドが短時間で済みます。一方、最適化を行わず、デバッグ用のコードを含むために、実行速度は遅くなります。
 releaseモードは主にリリース時に使用するビルドモードです。一般に最適化を行い、フルリンク(差分ではなく全体をリンクする機能)を行うため、ビルドにはdebugモードよりは多少の時間がかかります。一方、最適化を行い、デバッグ用のコードは含まないため、実行速度は速くなります。
 プログラムの開発・デバッグ時にはdebugモードを利用し、リリース時にはreleaseモードを利用するとよいでしょう。ただし、リリース時だけではなく、ときどきreleaseモードでビルドしてみることも有用です。これは実際のプログラムの実行速度を知ったり、releaseモードだけで顕在化するバグを発見するためです。


プログラミングに関する質問

2009/04/02
Q.
固定機能パイプラインを使った描画のソリューションが欲しい。
A.
 固定機能パイプラインを使った個別のソリューションはないのですが、

を参考にして頂くと、モデルやアニメーションを表示する仕組みが分かりやすいのではないかと思います。
 本書のサンプルは大きくViewerとVersusに分かれています。Versusは対戦機能があるので少し複雑ですが、Viewerは表示だけなので比較的簡単です。
 サンプルでは色々なモードを起動オプションやキー操作で切り替えられるので、ぜひ動かしながらソースコードを眺めてみてください。

2009/04/02
Q.
gameSpace Lightやメタセコイアを使ったモデリングの注意点は。
A.
本書のサンプルは.xファイルの読み込みに対応しています。サンプルのモデルはLightWaveで作成し、.xファイルに変換して出力しています(p.8参照)。

gameSpace Lightも.xファイルを出力することができますが、LightWaveとは出力内容に若干の違いがあるため、内容によってはデータやプログラムに多少の手直しが必要な場合もあります。

メタセコイアも.xファイルを出力できますが、アニメーションやスキニングに対応していませんので、格闘ゲーム用の人体モデルを作るのは難しいかもしれません。

2009/04/02
Q.
付属のサンプルデータはLightWaveを用いて作成したとあるが、具体的な作成方法や設定方法は。
A.
3Dキャラクターと3Dモーションの作成と出力には、LightWaveとともに3Dモデル制作者が開発した独自のプラグインやスクリプトを併用しています。標準機能のみを用いて近い内容の出力をすることは可能と思われますが、具体的な設定方法は確立しておりません。大変申し訳ございませんが、お使いのツールのマニュアルと、本書で採用したデータの制作・出力方法の概要(p.36〜)を参考に、設定方法をご検討頂けましたら幸いです。

.xファイルの内容については、例えばLightWaveとgameSpace Lightでは同じ.xファイルにもかかわらず形式が違うなど、使用するツールやプラグイン等によって微妙な違いがあるようです。実際にゲームを制作される際には、お使いのツールが出力したファイルの内容を確認し、それに合わせてデータの読み込み処理をアレンジするのがお勧めです。出力ファイルの読み込み処理については、p.48から詳細に解説しています。

本書3Dモデル制作者より:

LightWaveでデータを作成し、.xファイルとして出力する場合には、LightWave上で編集した全ての情報がファイルに出力されるとは限らない、という点に注意する必要があります。例えばモーフマップやディスプレースメントマップ、ボーン変形の範囲指定などは出力されないかもしれません。お使いのバージョンによって動作が異なる可能性があるので、詳細は製品のマニュアル等をご確認ください。

LightWaveの使い方として注意すべきなのは、 といった点です。これらは必ず守らなければならないということではありませんが、こういった制約を行った方が、出力結果が予想しやすくなります。いずれにしても、本格的に制作する前に簡単なモデルで実験を行うのがお勧めです。

2009/04/02
Q.
.xファイルの読み込みに関して、AnimationKeyのキータイプが0の場合にはどうすればよいのか。
A.
DirectX SDKのリファレンスによると、キータイプには以下の4種類があります。

本書ではキータイプ4(行列)に対応しています。

キータイプが0の場合には回転です。未確認なのですが、もしもキーに4個のfloat値が与えられている場合には、クォータニオンと思われます。DirectXにはクォータニオンの演算や行列への変換を行うための機能(D3DXMatrixRotationQuaternionなど)があるので、これらを用いて座標変換を行うプログラムを書く必要がありそうです。

キータイプが1の場合には拡大縮小、2の場合には位置(移動)です。拡大縮小はD3DXMatrixScalingなど、位置はD3DXMatrixTranslationなどを用いて行列を作成し、座標変換を行うことになるでしょう。

なおLightWaveのDirectX Exportを使用して、行列で出力したい場合には、Use Matrix KeyオプションをONにしてみてください。

2010/01/22
Q.
.xファイルに膨大なパラメータが出力されるが、手作業で修正する必要はあるか。
A.
モデルやアニメーションの複雑さにもよりますが、.xファイルに膨大なパラメータが出力されることはよくあります。しかし、これらのパラメータを手作業で修正することは、作業が大変なことや、後でツールを使った変更が加えにくくなることなどから、あまりお勧めできません。以下のような方法を検討してみてはいかがでしょうか。

いずれにしても、手作業で.xファイルを修正するのではなく、プログラムを使って自動的に処理する方法を考えるのが得策と思われます。

2010/06/03
Q.
頂点数8の立方体を作ったが、法線数が24になってしまう。
A.
一般に頂点の法線は、その頂点を共有する面の法線の平均とします(面法線ベクトルの平均をとったもの)。頂点法線を使うことで、面と面の継ぎ目を目立たせずに、滑らかにシェーディングすることができます。

立方体の場合、頂点を3枚の面が共有していますが、これらの面は直交しています。そのため、面法線の平均を頂点法線とするのは適切ではありません。本来はエッジが立っているべき境界が滑らかになるように、おかしなシェーディングがされてしまいます。

正しいシェーディングを行うには、3枚の面で頂点を共有しない方法があります。同じ位置に3個の頂点が重なっており、各々が異なる法線を持ちます。ただし、頂点や法線の数は増えてしまいます。

正しいシェーディングを行う別の方法としては、面法線を用いる方法もあります。ただし、通常の頂点法線を使った描画処理とは別に、独自の描画処理を構築する必要があります。

頂点や法線の数を減らすには、重なった頂点を結合して、単一の頂点にします。多くの3Dツールには、選択した複数の頂点を単一の頂点に結合する機能があります。ただし、シェーディングは不正確になります。

このように頂点を共有する面間の角度が急峻な場合、頂点を共有して頂点数や法線数を減らすか、頂点を分離して正しいシェーディングにするか、考慮の余地があります。

2010/07/11
Q.
DrawIndexedPrimitive関数の引数の意味は。
A.
例えばp.104では、DrawIndexedPrimitive関数を次のように呼び出します。

Device->DrawIndexedPrimitive(
  D3DPT_TRIANGLELIST, 0, 0, VertexCount,
  subset->FaceIndex*3, subset->FaceCount);

本書のサンプルでは、次のような構成のモデルを使っています。

引数の意味は次の通りです。引数の指定方法はこれに限るものではなく、モデルの構成が上記と異なる場合には、異なる指定方法になります。

2010/12/5
Q.
CModel::AnimateFrame関数におけるkeyと*keyの違いは。
A.
p.120のCMode::AnimateFrame関数では、変数keyを使ってCModelAnimationKeyクラスのメンバを参照します。

if (time<key->Time.front()) {

一方、*keyのように記述した箇所もあります。

frame->TransformMatrix+=*key->Matrix.front()*anim->Weight;

*演算子は->演算子よりも優先順位が低いので、この箇所は以下のように解釈できます。*keyの*はkeyに適用されているのではなく、key->Matrix.front()に適用されています。

frame->TransformMatrix+=*(key->Matrix.front())*anim->Weight;

key->Matrix.front()でCModelAnimationKeyクラスのMatrixメンバを参照します。Matrixメンバの定義は以下の通りです。

vector<D3DXMATRIXA16*> Matrix;

vectorクラスのfront()関数は、可変長配列に格納された最初の要素を返します。key->Matrix.front()はD3DXMATRIXA16*というポインタ型なので、*(key->Matrix.front())とすることで、ポインタが指すD3DXMATRIXA16型になります。これにanim->Weightを掛けると、行列の各要素にanim->Weightが乗算されます。

2011/6/8
Q.
TransformMatrixはどのクラスに属しているか。
A.
p.86-88で解説しているTransformMatrixは、CModelFrameクラスに属しています。 CModelFrameクラスはModel.hで宣言しています。

2011/6/8
Q.
new CModelFrame(&Frame);を変数に代入しない理由は。
A.
p.86のList3-28では、次のようにCModelFrameクラスのインスタンスを生成しますが、生成したインスタンスを変数に格納しません。

new CModelFrame(&Frame);

このインスタンスは、p.87のList3-29において、次のように引数frameが表すvectorに格納されます。そのため、List3-28ではインスタンスを変数に格納していません。

frame->push_back(this);


最終更新