XNAを使用したシンプルな3Dゲームの作成/モデルのレンダリング

はじめに編集

まず、 Visual c#を開き、 'File'/'New Project'と選択します。 そこから選択して、新規 C# プロジェクトを作成しましょう。

あなたの前に表示されているものは、標準的な起動時のXNAの初期コードです。 以前にダウンロードしたスキンモデルサンプルから 'SkinnedModelPipeline' と 'SkinnedModelWindows' というプロジェクトを追加し、それらへの参照を追加するために、他のusingステートメントと一緒に using SkinnedModel; を入力し、プロジェクトを右クリックして、 'Add Reference'の下でそれらを選択します。

プラス、クラスの最初の行を変更することにより、以下のようにクラスが確実に 'Game' クラスを参照するようにします。

public class ModelRenderer : Microsoft.Xna.Framework.Game

そして、'SkinnedModelWindows'プロジェクトから 'SkinnedModel.fx' ファイルをプロジェクトのコンテンツフォルダに 配置して、モデルがそれをレンダリングに使用するようにします。

魚のレンダラ編集

次は、 'ModelRenderer'という名前の新しいゲームコンポーネントファイルを作成します。 これのために、次のクラス変数を追加します。

public AnimationPlayer animationPlayer; //Controls the animation, references a method in the pre-loaded project
public AnimationClip clip; //Contains the animation clip currently playing
public Model currentModel; //Model reference
public SkinningData skinningData; //Used by the AnimationPlayer method
public Vector3 Translation = new Vector3(0, 0, 0); //Fishes current position on the screen
public Vector3 Rotation = new Vector3(0, 0, 0); //Current rotation
public float Scale = 1.0f; //Current scale

コンストラクタを次のように変更します。

public ModelRenderer(Model currentModelInput)
{
    currentModel = currentModelInput;
    // Look up our custom skinning information.
    skinningData = currentModel.Tag as SkinningData;
    if (skinningData == null)
        throw new InvalidOperationException
            ("This model does not contain a SkinningData tag.");
    // Create an animation player, and start decoding an animation clip.
    animationPlayer = new AnimationPlayer(skinningData);
}

このコードは、多少なりとも元のサンプルから取られていて、最終的にアニメーション処理のために使用される初期化メソッドとなります。

次に、既製のupdateメソッドからコードを削除し、これと置き換えてください。

if ((clip != null))
    animationPlayer.Update(gameTime.ElapsedGameTime, true, Matrix.Identity);

ここにある .Update メソッドは、アニメーションが現在の方法で再生されることを保証するもので、渡された'gameTime'を使用するあらゆるものについて連続的にかつ時間内になるようにします。

このクラスのアクティブな構成要素は、以下の描画メソッドです:

public void ModelDraw(GraphicsDevice device, Vector3 cameraPosition, Vector3 cameraTarget, float farPlaneDistance)
{
    Matrix[] bones = animationPlayer.GetSkinTransforms();
    for (int i = 0; i < bones.Length; i++)
    {
        bones[i] *= 
              Matrix.CreateRotationX(Rotation.X) //Computes the rotation
            * Matrix.CreateRotationY(Rotation.Y)
            * Matrix.CreateRotationZ(Rotation.Z)
            * Matrix.CreateScale(Scale) //Applys the scale
            * Matrix.CreateWorld(Translation, Vector3.Forward, Vector3.Up); //Move the models position
    }

    float aspectRatio = (float)device.Viewport.Width /
                        (float)device.Viewport.Height;

    // Compute camera matrices.
    Matrix view = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Right);

    //Create the 3D projection for this model
    Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio,
        1.0f, farPlaneDistance);

    // Render the skinned mesh.
    foreach (ModelMesh mesh in currentModel.Meshes)
    {
        foreach (Effect effect in mesh.Effects)
        {
            effect.Parameters["Bones"].SetValue(bones);
            effect.Parameters["View"].SetValue(view);
            effect.Parameters["Projection"].SetValue(projection);
        }
        mesh.Draw();
    }
}

私たちは、このチュートリアルのためには、これを過剰に心配する必要はありません。

親ファイルから呼び出される新しいメソッドを追加し、これでプリインストールされた 'SkinnedModel'の要素を呼び出して、アニメーションを再生します。

public void PlayAnimation(String Animation)
{
    clip = skinningData.AnimationClips[Animation];
    if (clip != animationPlayer.CurrentClip)
    animationPlayer.StartClip(clip);
}

このコードに追加することで、実際のゲームプレイのロジックを拡張することもできますが(使用する魚のインスタンス変数を格納するために非常に手頃な場所なので)、今のところはシステムに必要とされる基礎の範囲を超えるので、次はモデルのレンダーとしての使用について気を配っていきます。

レンダラの使い方編集

プロジェクト内の 'Content'の下に、 'Models'という名前の新しいフォルダを作成し、魚モデルとすべての.tgaテクスチャファイルを追加します。 さて、 'References' フォルダを右クリックし、 'SkinnedModelPipeline'を追加します。 こうすると、モデルのプロパティに入って新しい 'SkinnedModelProcessor'に変更することで、モデルにふさわしいレンダラを選択することができるようになります。 それの選択ができない場合は、2つの 'SkinnedModel' プロジェクトを右クリックして 'Build'を選択することで、ビルドされていることを確認しましょう。

さて、親ファイルに戻ります。 いくつか新しいクラス変数を追加します。

ModelRenderer FishMen; //Your new Fish model
Vector3 cameraPosition; //Defines the position of the camera in the 3D space
Vector3 cameraTarget; //Defines your camera target
float farPlaneDistance = 400f; //Defines your plane distance, the higher, the less 3D 'fog' and the more is displayed

そして、アップデートメソッドに入って次の行を追加することで、それを稼働状態におきましょう

FishMen.Update(gameTime);
cameraPosition = cameraTarget = FishMen.Translation;
cameraPosition.Z += 20.0f;

at the start of the method, and in the draw method adding

FishMen.ModelDraw(device, cameraPosition, cameraTarget, farPlaneDistance);

after your

GraphicsDevice.Clear(Color.CornflowerBlue);

line.

そして最後に、 'LoadContent' メソッドの先頭に次の行を追加します。

Model currentModel; //Temporary storage for your new model

Content.RootDirectory = "Content";
currentModel = Content.Load<Model>("Models\\FishModel"); //Loads your new model, point it towards your model
FishMen = new ModelRenderer(currentModel);
FishMen.Translation = new Vector3(0f);//Move it to the centre
FishMen.PlayAnimation("Swim");//Play the default swimming animation

これでもう、アプリケーションを実行すれば、すべてが動作するはずです。