DrawScene.cpp

#include "StdAfx.h"
#include "DrawScene.h"


using namespace Core;
using namespace Microsoft;

using namespace System;
using namespace System::Diagnostics;


// DirectXのライブラリによる const/volatile 修飾子の使用の警告を抑制する
#pragma warning( disable : 4400 )


/// [ Constructor ]
DrawScene::DrawScene( Microsoft::DirectX::Direct3D::Device^ device ) :
    m_device( device )
{
    // 座標軸を生成する
    CreateAxisOfCoordinates();

    // 床を生成する
    CreateFloor();
}

/// [ Finalizer ]
DrawScene::!DrawScene()
{
    delete m_axisOfCoordinates;
    delete m_floor;
}


/// 座標軸を生成する
void DrawScene::CreateAxisOfCoordinates()
{
    // 頂点バッファを生成する
    m_axisOfCoordinates = gcnew DirectX::Direct3D::VertexBuffer(
        DirectX::Direct3D::CustomVertex::PositionColored::typeid,   // 頂点データを定義した構造体
        6,                                                          // 頂点数
        m_device,                                                   // デバイス
        DirectX::Direct3D::Usage::Dynamic |                         // 使用法
        DirectX::Direct3D::Usage::WriteOnly,
        DirectX::Direct3D::CustomVertex::PositionColored::Format,   // 頂点フォーマット
        DirectX::Direct3D::Pool::Default
        );

    // 頂点の生成イベントに登録する
    m_axisOfCoordinates->Created += gcnew System::EventHandler( this, &DrawScene::SetAxisOfCoordinates );

    // ... そのイベントを呼び出して 設定させる
    SetAxisOfCoordinates( m_axisOfCoordinates, nullptr );
}

/// 座標軸を設定する
void DrawScene::SetAxisOfCoordinates( System::Object^ sender, System::EventArgs^ )
{
    // 引数から目的とする型を取得する
    DirectX::Direct3D::VertexBuffer^ vertexBuffer = safe_cast< DirectX::Direct3D::VertexBuffer^ >( sender );


    // 頂点を格納する配列を生成する
    array< DirectX::Direct3D::CustomVertex::PositionColored >^ vertices
        = gcnew array< DirectX::Direct3D::CustomVertex::PositionColored >( 6 );

    const float Length = 1.2f;   // 長さ

    // ... 頂点の位置を設定する
    vertices[ 0 ].Position = DirectX::Vector3( 0.0f, 0.0f, 0.0f );
    vertices[ 1 ].Position = DirectX::Vector3( Length, 0.0f, 0.0f );

    vertices[ 2 ].Position = DirectX::Vector3( 0.0f, 0.0f, 0.0f );
    vertices[ 3 ].Position = DirectX::Vector3( 0.0f, Length, 0.0f );

    vertices[ 4 ].Position = DirectX::Vector3( 0.0f, 0.0f, 0.0f );
    vertices[ 5 ].Position = DirectX::Vector3( 0.0f, 0.0f, Length );

    // ... 頂点の色を設定する
    int red = Drawing::Color::Red.ToArgb();
    int green = Drawing::Color::Green.ToArgb();
    int blue = Drawing::Color::Blue.ToArgb();

    vertices[ 0 ].Color = red;
    vertices[ 1 ].Color = red;

    vertices[ 2 ].Color = green;
    vertices[ 3 ].Color = green;

    vertices[ 4 ].Color = blue;
    vertices[ 5 ].Color = blue;


    // 頂点データの範囲をロックして、頂点バッファ メモリへのリファレンスを取得する
    vertexBuffer->SetData( vertices, 0, DirectX::Direct3D::LockFlags::None );

    // [ Reference ]「Managed DirectX9」Tom Miller(Sams) P40
}


/// 床を生成する
void DrawScene::CreateFloor()
{
    // 頂点数を求める( 幅 / 間隔 + 1 ) x 縦横2辺 x 両端2点
    const int NumberOfVertices = ( safe_cast< int >( WidthOfFloor / DistanceOfFloorMesh ) + 1 ) * 2 * 2;

    // 頂点バッファを生成する
    m_floor = gcnew DirectX::Direct3D::VertexBuffer(
        DirectX::Direct3D::CustomVertex::PositionColored::typeid,   // 頂点データを定義した構造体
        NumberOfVertices,                                           // 頂点数
        m_device,                                                   // デバイス
        DirectX::Direct3D::Usage::Dynamic |                         // 使用法
        DirectX::Direct3D::Usage::WriteOnly,
        DirectX::Direct3D::CustomVertex::PositionColored::Format,   // 頂点フォーマット
        DirectX::Direct3D::Pool::Default
        );

    // 頂点の生成イベントに登録する
    m_floor->Created += gcnew System::EventHandler( this, &DrawScene::SetFloor );

    // ... そのイベントを呼び出して 設定させる
    SetFloor( m_floor, nullptr );
}

/// 床を設定する
void DrawScene::SetFloor( System::Object^ sender, System::EventArgs^ )
{
    // 引数から目的とする型を取得する
    DirectX::Direct3D::VertexBuffer^ vertexBuffer = safe_cast< DirectX::Direct3D::VertexBuffer^ >( sender );


    const int NumberOfSide = safe_cast< int >( WidthOfFloor / DistanceOfFloorMesh ) + 1;  // 辺の数
    const int NumberOfVertices = NumberOfSide * 2 * 2;                                    // 頂点数

    // 頂点を格納する配列を生成する
    array< DirectX::Direct3D::CustomVertex::PositionColored >^ vertices
        = gcnew array< DirectX::Direct3D::CustomVertex::PositionColored >( NumberOfVertices );

    int index = 0;

    for( int x = 0; x < NumberOfSide; x++ )
    {
        float offset = WidthOfFloor / 2.0f;
        float y = x * DistanceOfFloorMesh - offset;

        // X軸方向の線分を設定する
        vertices[ index++ ].Position = DirectX::Vector3( -offset, y, 0.0f );

        if( x == safe_cast< int >( WidthOfFloor / DistanceOfFloorMesh ) / 2 )
        {
            // 中央ならば座標軸と重なるので、原点までしか描画しない
            offset = 0.0f;
        }
        vertices[ index++ ].Position = DirectX::Vector3( +offset, y, 0.0f );
    }

    for( int y = 0; y < NumberOfSide; y++ )
    {
        float offset = WidthOfFloor / 2.0f;
        float x = y * DistanceOfFloorMesh - offset;

        // Y軸方向の線分を設定する
        vertices[ index++ ].Position = DirectX::Vector3( x, -offset, 0.0f );

        if( y == safe_cast< int >( WidthOfFloor / DistanceOfFloorMesh ) / 2 )
        {
            // 中央ならば座標軸と重なるので、原点までしか描画しない
            offset = 0.0f;
        }
        vertices[ index++ ].Position = DirectX::Vector3( x, +offset, 0.0f );
    }

    for (int i = 0; i < NumberOfVertices; i++)
    {
        // 頂点の色を設定する
        vertices[ i ].Color = Drawing::Color::Gray.ToArgb();
    }


    // 頂点データの範囲をロックして、頂点バッファ メモリへのリファレンスを取得する
    vertexBuffer->SetData( vertices, 0, DirectX::Direct3D::LockFlags::None );

    // [ Reference ]「Managed DirectX9」Tom Miller(Sams) P40
}


/// 描画する
void DrawScene::Render()
{
    // 変換行列を初期化する
    m_device->Transform->World = DirectX::Matrix::Identity;


    // 床のプリミティブ数を求める
    const int NumberOfFloorPrimitive = ( safe_cast< int >( WidthOfFloor / DistanceOfFloorMesh ) + 1 ) * 2;

    // ... 床を描画する
    RenderLine( m_floor, NumberOfFloorPrimitive );


    // 座標軸を描画する
    RenderLine( m_axisOfCoordinates, 3 );
}

/// ラインを描画する
void DrawScene::RenderLine( Microsoft::DirectX::Direct3D::VertexBuffer^ data, int primitiveCount )
{
    // ライトを無効にする
    m_device->RenderState->Lighting = false;


    // 頂点バッファを デバイスのデータ ストリームにバインドする
    m_device->SetStreamSource( 0, data, 0 );
    m_device->VertexFormat = DirectX::Direct3D::CustomVertex::PositionColored::Format; // 頂点フォーマット

    // ... レンダリングする
    m_device->DrawPrimitives(
        DirectX::Direct3D::PrimitiveType::LineList,
        0,              // 頂点の読み出し開始位置
        primitiveCount  // プリミティブの数
        );
}