2009/1/20 Na-7
 

技術資料一覧に戻る

 

立体地形モデルの作成と高さの取得

注意 この資料は、筆者が自らの経験を記録したものであり、他人に勧めるものではありません。

この資料を参考として行った行為がいかなる結果になろうとも、筆者は責任を負いませんので予めご承知おきください。

 

 

◎使用ツール

ツール名 入手元
XNA3.0(XNA GameStudio 3.0:ゲーム開発用フレームワーク) http://msdn.microsoft.com/ja-jp/xna/default.aspx
HeightmapCollision.Zip(XNA2.0用公式サンプル、変換ウィザードを利用するとXNA3.0でも使用可能) http://creators.xna.com/en-US/sample/collision3dheightmap

 

◎概要

XNA公式サンプル「HeightmapCollision」を利用して、立体地形モデルの作成と、特定座標の高さを取得 する。

(HeightmapCollisionの内容解析はブログを参照)

 

 

◎全体の流れ

1.グレースケールマップを用意する

2.新規プロジェクトを作成する

3.コンテントパイプラインをコピーして組み込む

4.グレースケールマップを登録する

5.テクスチャファイルをコピーする

6.新規クラスを作成する

7.HeightMapInfoクラスをコピーする

8.コンテントパイプラインを書き換える

9.地形作成機能の呼び出し

10.高さ取得機能の呼び出し

 

 

◎「1.グレースケールマップを用意する」について

グレースケールマップとは、高さを白から黒までの明暗だけで表現した画像のこと。

HeightmapCollisionでは、白い部分が高く、黒い部分が低い地形となる。

(例:HeightmapCollisionの中のterrain.bmp)

グレースケールマップは、各種CGツールや地図ビュワーなどを利用して作成すること。

 

 

◎「2.新規プロジェクトを作成する。」の詳細手順

1.「ファイル」→「新しいプロジェクト」

2.「新しいプロジェクト」ダイアログで「プロジェクト名」を変更し「OK」

 

 

◎「3.コンテントパイプラインをコピーして組み込む」の詳細手順

※今回はコンテントパイプラインの一部を書き換える必要があるため、元のソースを直接追加せずに、新規プロジェクトにコピーしてから組み込む。
※(プロジェクトの「追加」はリンク状態となるため、コードを書き換えると元のソースも変更される)

1.HeightmapCollisionの「HeightmapCollisionPipeline」フォルダを、新規プロジェクトフォルダの直下にコピーする

2.ソリューションエクスプローラのソリューション名で右クリック→「追加」→「既存のプロジェクト」

3.先にコピーした「HeightmapCollisionPipeline」の中の「HeightmapCollisionPipeline.csproj」を選択し「開く」

4.XNA3.0の人は、ここでVisualStudio変換ウィザードが起動する(HeightmapCollisionはXNA2.0用であるため)
    通常はそのまま「完了」ボタンを押すと正常に変換される

5.ソリューションエクスプローラの新規プロジェクト名-Content-参照設定で右クリック→「参照の追加」

6.「参照の追加」ダイアログの「プロジェクト」タブ→「HeightmapCollisionPipeline」を選択し「OK」

 

 

◎「4.グレースケールマップを登録する」の詳細手順

1.ソリューションエクスプローラの新規プロジェクト名-Contentで右クリック→「追加」→「既存の項目」

2.「既存項目の追加」ダイアログでグレースケールマップを選択し「追加」

3.ソリューションエクスプローラの新規プロジェクト名-Content-グレースケールマップを選択

4.プロパティウィンドウの「Content Processor」を「TerrainProcessor」に変更
    (「TerrainProcessor」が選択肢に表示されない場合は、一度ビルドすると表示される)

5.必要に応じて、他のプロパティ(「Terrain Texture」など)を変更
    (後で変更することも可能)

 

 

◎「5.テクスチャファイルをコピーする」の詳細手順

1.HeightmapCollisionの「HeightmapCollision\Content\rocks.bmp」ファイルを、新規プロジェクトのContentフォルダにコピーする

※このテクスチャファイルは後で差し替え可能

 

 

◎「6.新規クラスを作成する」の詳細手順

1.ソリューションエクスプローラの新規プロジェクト名で右クリック→「追加」→「クラス」

2.「新しい項目の追加」ダイアログで「ファイル名」を「HeightMapInfo.cs」と変更し「追加」

 

 

◎「7.HeightMapInfoクラスをコピーする」の詳細手順

1.公式サンプルHeightmapCollisionのHeightMapInfo.csを開き、「編集」→「すべて選択」

2.コードを全て選択した状態で「編集」→「コピー」

3.新規プロジェクトのHeightMapInfo.cs(新規クラス)を開き、「編集」→「すべて選択」

4.コードを全て選択した状態で「編集」→「貼り付け」(全コードを上書き貼り付け)

5.新規プロジェクトのGame1.csの上部にある namespace 名が新規プロジェクト名となっていることを確認する

6.新規プロジェクトのHeightMapInfo.csの上部にある namespace 名を新規プロジェクト名に書き換える

 

 

◎「8.コンテントパイプラインを書き換える」の詳細手順

1.新規プロジェクトに組み込んだHeightMapInfoContent.csを以下のように書き換える

※プロジェクト名が「NewProject」の場合の例
※(NewProjectと記述した4箇所を各々のプロジェクト名に置き換えること)

public override string GetRuntimeType(TargetPlatform targetPlatform)
{
   
return "NewProject.HeightMapInfo, " +
        "NewProject, Version=1.0.0.0, Culture=neutral";
}

public override string GetRuntimeReader(TargetPlatform targetPlatform)
{
   
return "NewProject.HeightMapInfoReader, " +
        "NewProject, Version=1.0.0.0, Culture=neutral";
}

※以上で公式サンプル HeightmapCollision の組み込みは完了

 

 

◎「9.地形作成機能の呼び出し」のサンプルコード

public class Game1 : Microsoft.Xna.Framework.Game
{
    〜

    // 地形モデルの宣言
    Model terrain;

    // 地形情報クラスの宣言
   
HeightMapInfo heightMapInfo;

    // ビュー座標変換行列の宣言
   
Matrix viewMatrix;

    // 射影変換行列の宣言
   
Matrix projectionMatrix;

    〜

    protected override void Initialize()
    {

        〜

        float aspectRatio = graphics.GraphicsDevice.Viewport.Width /
        (
float)graphics.GraphicsDevice.Viewport.Height;

        // 射影変換行列
   
    projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
       
MathHelper.ToRadians(45.0f), aspectRatio, 1f, 10000);

        // ビュー座標変換行列
   
    viewMatrix = Matrix.CreateLookAt(
   
        new Vector3(0, 200, 500), // カメラ位置
   
        new Vector3(0, 0, 0), // カメラ注視点
       
    new Vector3(0, 1, 0) // カメラ上方向
       
    );

        〜

    }

 

    protected override void LoadContent()
    {

        〜

        // 地形モデルの呼び出し
        terrain = Content.Load<Model>("terrain");

        // 地形情報クラスの呼び出し
        heightMapInfo = terrain.Tag as HeightMapInfo;

        if (heightMapInfo == null)
        {
           
string message = "The terrain model did not have a HeightMapInfo " +
           
"object attached. Are you sure you are using the " +
           
"TerrainProcessor?";
           
throw new InvalidOperationException(message);
        }

        〜

    }

    protected override void Draw(GameTime gameTime)
    {

        〜

        // 地形モデルの表示
       
foreach (ModelMesh mesh in terrain.Meshes)
        {
           
foreach (BasicEffect effect in mesh.Effects)
            {
                effect.World =
Matrix.Identity;
                effect.View = viewMatrix;
                effect.Projection = projectionMatrix;

                // ライト有効
                effect.EnableDefaultLighting();
                // ピクセル単位のライト有効
                effect.PreferPerPixelLighting = true;
            }
            mesh.Draw();
        }

        〜

    }
}

 

 

◎「10.高さ取得機能の呼び出し」のサンプルコード

    protected override void Update(GameTime gameTime)
    {

        〜

        float height = heightMapInfo.GetHeight(new Vector3(10, 0, 30));
       
Console.WriteLine("座標(10,30)の高さ:" + height.ToString());

        〜

    }

※コンソール出力した文字列は、デバッグ実行後に「表示」→「出力」で出力ウィンドゥに表示される

 

inserted by FC2 system