AxisOfCoordinate.cpp

#include "StdAfx.h"
#include "AxisOfCoordinate.h"


using namespace Core;
using namespace Microsoft;

using namespace System;
using namespace System::Diagnostics;


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


/// [ Constructor ]
AxisOfCoordinate::AxisOfCoordinate( Microsoft::DirectX::Direct3D::Device^ device, float length ) :
    m_length( length )
{
    // ラインの 頂点バッファを生成する
    m_line = gcnew DirectX::Direct3D::VertexBuffer(
        DirectX::Direct3D::CustomVertex::PositionColored::typeid,   // 頂点データを定義した構造体
        6,                                                          // 頂点数
        device,                                                     // デバイス
        DirectX::Direct3D::Usage::Dynamic |                         // 使用法
        DirectX::Direct3D::Usage::WriteOnly,
        DirectX::Direct3D::CustomVertex::PositionColored::Format,   // 頂点フォーマット
        DirectX::Direct3D::Pool::Default
        );

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

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


    // 円錐を生成する
    m_cone = DirectX::Direct3D::Mesh::Cylinder(
        device,
        0.010f, // Z軸の負の側の面の半径
        0.000f, // Z軸の正の側の面の半径
        0.020f, // Z軸方向の円柱の長さ
        6,      // 主軸を回転軸としたスライスの数
        1       // 主軸に沿ったスタックの数
        );
}

/// [ Finalizer ]
AxisOfCoordinate::!AxisOfCoordinate()
{
    delete m_line;
    delete m_cone;
}


/// ラインを設定する
void AxisOfCoordinate::SetLine( 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 );

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

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

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

    // ... 頂点の色を設定する
    int color = Drawing::Color::Gray.ToArgb();
    vertices[ 0 ].Color = color;
    vertices[ 1 ].Color = color;

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

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

    /// @note
    /// 処理を明確にするために、ループで処理していない。


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

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


/// 描画する
void AxisOfCoordinate::Render( Microsoft::DirectX::Direct3D::Device^ device, Robotics::PositionVector^ position )
{
    // 移動する
    device->Transform->World
        = DirectX::Matrix::Translation(
            safe_cast< float >( position->X ),
            safe_cast< float >( position->Y ),
            safe_cast< float >( position->Z )
            )
        * device->Transform->World;


    // ライトを無効にする
    device->RenderState->Lighting = false;


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

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


    // 円錐を描画する
    RenderCone( device );
}

/// 円錐を描画する
void AxisOfCoordinate::RenderCone( Microsoft::DirectX::Direct3D::Device^ device )
{
    // ライトを有効にする
    device->RenderState->Lighting = true;

    // ワールド座標を保存する
    DirectX::Matrix worldMatrix = device->Transform->World;

    float rightAngle = safe_cast< float >( Math::PI / 2.0 );    // 直角


    // ----------------------------------------------
    // 色を設定する
    SetupColor( device, Drawing::Color::Red );

    // 移動と回転をする
    device->Transform->World
        = DirectX::Matrix::RotationY( rightAngle )
        * DirectX::Matrix::Translation( m_length, 0.0f, 0.0f )
        * worldMatrix;

    m_cone->DrawSubset( 0 );

    // ----------------------------------------------
    // 色を設定する
    SetupColor( device, Drawing::Color::Green );

    // 移動と回転をする
    device->Transform->World
        = DirectX::Matrix::RotationX( -rightAngle )
        * DirectX::Matrix::Translation( 0.0f, m_length, 0.0f )
        * worldMatrix;

    m_cone->DrawSubset( 0 );

    // ----------------------------------------------
    // 色を設定する
    SetupColor( device, Drawing::Color::Blue );

    // 移動と回転をする
    device->Transform->World
        = DirectX::Matrix::Translation( 0.0f, 0.0f, m_length )
        * worldMatrix;

    m_cone->DrawSubset( 0 );
}

/// 色を設定する
void AxisOfCoordinate::SetupColor( Microsoft::DirectX::Direct3D::Device^ device, System::Drawing::Color color )
{
    // マテリアルを生成する
    DirectX::Direct3D::Material material;

    material.Diffuse = color;
    material.Ambient = color;

    // ... マテリアルを設定する
    device->Material = material;
}