XFile.cpp

#include "StdAfx.h"
#include "XFile.h"


using namespace Core;

using namespace Microsoft;

using namespace System;
using namespace System::Diagnostics;


/// [ Constructor ]
XFile::XFile( Microsoft::DirectX::Direct3D::Device^ device, System::String^ fileName )
{
    Debug::Assert( IO::File::Exists( fileName ), "存在するファイルである" );
    Debug::Assert( IO::Path::GetExtension( fileName ) == ".x", "Xファイルである" );


    // ファイル名をもったマテリアルを生成する
    array< DirectX::Direct3D::ExtendedMaterial >^ extendedMaterial;

    // ファイルからメッシュを生成する
    m_mesh = DirectX::Direct3D::Mesh::FromFile(
        fileName,                               // ファイル名
        DirectX::Direct3D::MeshFlags::Managed,  // オプション
        device,                                 //
        extendedMaterial                        // ファイルから読み込むための マテリアル バッファ
        );


    if( ( m_mesh->VertexFormat & DirectX::Direct3D::VertexFormats::Normal )
        != DirectX::Direct3D::VertexFormats::Normal )
    {
        // メッシュが法線情報を持たなければ、法線情報を加えたメッシュを生成する
        DirectX::Direct3D::Mesh^ tempMesh = m_mesh->Clone(
            m_mesh->Options.Value,
            m_mesh->VertexFormat | DirectX::Direct3D::VertexFormats::Normal,
            device
            );

        // ... 法線を求める
        tempMesh->ComputeNormals();

        // 新しいメッシュと置き換える
        delete m_mesh;
        m_mesh = tempMesh;

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


    if( extendedMaterial != nullptr )
    {
        int numberOfMaterial = extendedMaterial->Length;    // マテリアルの数

        if( 0 < numberOfMaterial )
        {
            // マテリアル情報が存在するならば、マテリアルとテクスチャを生成する
            m_materials = gcnew array< DirectX::Direct3D::Material >( numberOfMaterial );
            m_textures = gcnew array< DirectX::Direct3D::Texture^ >( numberOfMaterial );


            // マテリアルとテクスチャを保存する
            for( int i = 0; i < numberOfMaterial; i++ )
            {
                m_materials[ i ] = extendedMaterial[ i ].Material3D;    // マテリアル

                // ... 環境光に対する反射係数を 拡散反射係数から設定する
                m_materials[ i ].Ambient = m_materials[ i ].Diffuse;

                /// @note
                /// 環境光に対する反射係数は DirectXにより設定されない。
                /// http://www.microsoft.com/japan/msdn/directx/japan/dx9/mxd5.aspx#mxd1


                String^ textureName = extendedMaterial[ i ].TextureFilename;    // テクスチャ名

                if( ( textureName != nullptr ) && ( textureName != String::Empty ) )
                {
                    try
                    {
                        // テクスチャが存在するならば、それをファイルから読み込む
                        m_textures[ i ] = DirectX::Direct3D::TextureLoader::FromFile( device, textureName );
                    }
                    catch( DirectX::Direct3D::InvalidDataException^ e )
                    {
                        Debug::WriteLine( "テクスチャの読み込みに失敗した : " + fileName + e->Message );


                        /// @todo
                        /// ユーザーに提示するようにする。


                        // テクスチャを無効にする
                        m_textures[ i ] = nullptr;
                    }
                }
            }
        }
    }

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

/// [ Finalizer ]
XFile::!XFile()
{
    if( m_textures != nullptr )
    {
        for each( DirectX::Direct3D::Texture^ texture in m_textures )
        {
            // テクスチャを破棄する
            delete texture;
        }
    }

    // メッシュを破棄する
    delete m_mesh;
}


/// リアルな形状を描画する
void XFile::Render( Microsoft::DirectX::Direct3D::Device^ device )
{
    // ライトを有効にする
    device->RenderState->Lighting = true;

    for( int i = 0; i < m_materials->Length; i++ )
    {
        device->Material = m_materials[ i ];    // マテリアル

        // テクスチャを設定する
        device->SetTexture( 0, m_textures[ i ] );

        // ... メッシュを描画する
        m_mesh->DrawSubset( i );
    }

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