X-FILE Loader_1

X-FILE Loader 1 で X-FILE を描画します。

プロジェクト一式を圧縮形式で提供します。
Visual Studio Express 2012 for Windows 8 で作成したプロジェクトです。
Windows 8.1 以降では動かないようなのでアップロードを廃止します。
X-FILE Loader 1 の Down Load

前田稔(Maeda Minoru)の超初心者のプログラム入門

X-FILE Loader_1

  1. DirectX9 までは、標準で X-FILE を入力する機能がサポートされていました。
    DirectX10 では、X-FILE が使えなくなった代わりに sdkmesh が使えるようになりました。
    ところが Windows8 では、このような標準モデルは存在しないようです。
    OBJ Model を Windows8 内部形式に変換して描画する以外に、モデルファイルのプログラムは見当たりません。
    OBJ Model のコンバータは OBJ Model を参照して下さい。
    そこで X-FILE を描画する専用の Loader を開発することにしました。
    一応 X-FILE Loader 1 が使えるようになったので圧縮形式で提供します。
    X-FILE を直接プロジェクトに組み込んで描画して下さい。
  2. プロジェクトには、幾つかの X-FILE のサンプルモデルが組み込まれています。
    (BOXP3.x ConePN.x gal2.x)
    圧縮ファイルを解凍して、プロジェクトを起動して下さい。
    ページ先頭の X-FILE(gal2.x) が回転しながら描画されます。
    但し、残念ながら Loader 1 ではポリゴンの色やテクスチャには対応していません。
    Loader 1 では、頂点座標と法線ベクトルのみ処理しています。
  3. X-FILE Loader_1 の仕様です。
    1. 頂点座標(Mesh)と法線ベクトル(MeshNormals)のみ処理します。
      ポリゴンの色やテクスチャには対応していません。
    2. 法線ベクトルが設定されていないモデル(X-FILE)が入力されたときは、自動的に計算します。
      DirectX9 で真っ黒に描画されてプログラマを悩ませていた Tiger.x も確認済みです。
    3. 使用できるポリゴンの形式です。
      • 三角ポリゴン(TRIANGLELIST)
      • 四角ポリゴン(TRIANGLESTRIP)
      • 五角以上のポリゴン(TRIANGLEFAN)
    4. ポリゴンは全て三角ポリゴン(TRIANGLELIST)に変換して描画します。
      五角以上のポリゴンは TRIANGLEFAN とみなされるので注意して下さい。
      幾つかのモデルを試してみたのですが、この方法がベストのようで、たいていのモデルは描画出来ると思います。
  4. Loader_1 に続いて、ポリゴンの色やテクスチャに対応した Loader を開発する予定なので、期待していて下さい。

プログラムの説明

  1. XLoader を組み込んだ制御の流れを説明します。
        System⇒.appxmanifest⇒Direct3DApp1⇒Model⇒Loader
        
  2. Direct3DApp1.App が最初に起動します。
    Direct3DApp1.App には main() 関数が定義されています。
  3. Direct3DApp1 で Model() を生成します。
    void Direct3DApp1::Initialize(CoreApplicationView^ applicationView)
    {
        applicationView->Activated +=
            ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &Direct3DApp1::OnActivated);
    
        CoreApplication::Suspending +=
            ref new EventHandler<SuspendingEventArgs^>(this, &Direct3DApp1::OnSuspending);
    
        CoreApplication::Resuming +=
            ref new EventHandler<Platform::Object^>(this, &Direct3DApp1::OnResuming);
    
        m_renderer = ref new Model();
    }
    
  4. Model() の初期化を呼び出します。
    void Direct3DApp1::SetWindow(CoreWindow^ window)
    {
        window->SizeChanged += 
            ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &Direct3DApp1::OnWindowSizeChanged);
    
        window->VisibilityChanged +=
            ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &Direct3DApp1::OnVisibilityChanged);
    
        window->Closed += 
            ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &Direct3DApp1::OnWindowClosed);
    
        window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
    
        window->PointerPressed +=
            ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &Direct3DApp1::OnPointerPressed);
    
        window->PointerMoved +=
            ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &Direct3DApp1::OnPointerMoved);
    
        m_renderer->Initialize(CoreWindow::GetForCurrentThread());
    }
    
  5. Direct3DApp1 の Run() からモデルを描画します。
    void Direct3DApp1::Run()
    {
        BasicTimer^ timer = ref new BasicTimer();
    
        while (!m_windowClosed)
        {
            if (m_windowVisible)
            {
                timer->Update();
                CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
                m_renderer->Update(timer->Total, timer->Delta);
                m_renderer->Render();
                m_renderer->Present(); // この呼び出しは、表示フレーム レートに同期されます。
            }
            else
            {
                CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
            }
        }
    }
    
  6. Model.cpp の中で で XLoader を生成します。
    Load() 関数でモデルをロードします。
    void Model::CreateDeviceResources()
    {
        Direct3DBase::CreateDeviceResources();
    
        xloader = ref new XLoader(m_d3dDevice.Get(), m_d3dContext.Get());
        xloader->Load();
           ・・・
    
  7. Render() 関数でモデルを描画します。
    void Model::Render()
    {
        const float ClearColor[4] = { 0.2f, 0.4f, 0.6f, 1.0f };
        m_d3dContext->ClearRenderTargetView(
            m_renderTargetView.Get(), ClearColor);
    
        m_d3dContext->ClearDepthStencilView(
            m_depthStencilView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
    
        m_d3dContext->OMSetRenderTargets(
            1, m_renderTargetView.GetAddressOf(), m_depthStencilView.Get());
    
        m_d3dContext->UpdateSubresource(
            m_constantBuffer.Get(), 0, NULL, &m_constantBufferData, 0, 0);
    
        m_d3dContext->VSSetConstantBuffers(0, 1, m_constantBuffer.GetAddressOf());
    
        xloader->Draw();
    }
    
  8. X-FILE はプロジェクトに直接組み込み、Load() 関数でロードします。
    void XLoader::Load()
    {
        // Reader の設定
        BasicReaderWriter^ reader = ref new BasicReaderWriter();
    
        // Read X-Model
        //Platform::Array<byte>^ buf = reader->ReadData("BOXP3.x");
        //Platform::Array<byte>^ buf = reader->ReadData("ConeP3.x");
        //Platform::Array<byte>^ buf = reader->ReadData("men4P3.x");
        //Platform::Array<byte>^ buf = reader->ReadData("BOXP4.x");
        //Platform::Array<byte>^ buf = reader->ReadData("ConePN.x");
        //Platform::Array<byte>^ buf = reader->ReadData("Tiger.x");
        Platform::Array<byte>^ buf = reader->ReadData("char.x");
    

Loader_1 の概要

  1. 簡単に X-FILE Loader_1 の概要を説明します。
    Windows8 の String は使い勝手が悪く、STL の string を使っています。 (^_^;)
    また vector もついでに STL のものを使います。
    このあたりの説明は 超初心者のプログラム入門(C/C++) を参照して下さい。
  2. X-FILE を行で切り分けて vector に格納します。
    文字コードは、もちろん Shift-JIS です。
        vector<string> VT;      // X-FILE の Vector Table(行で切り分け)
        
  3. 頂点座標と法線ベクトルの vector です。
    法線ベクトルが設定されていないモデルは、自動的に計算して設定します。
        vector<float3> VP;      // 頂点座標
        vector<float3> VN;      // 法線ベクトル
        
  4. 頂点 Index の並びと法線 Index の並びです。
        vector<int>    XVP;     // 頂点 Index の並び
        vector<int>    XVN;     // 法線 Index の並び
        
  5. ポリゴンは全て三角ポリゴンに変換するのですが、その領域です。
        vector<int>    VP3;     // 頂点 Index の並び(3角)
        vector<int>    VN3;     // 法線 Index の並び(3角)
        
  6. X-FILE Loader で使った主要な関数です。
    1. void Load();
      X-FILE を Load します。
    2. void Draw();
      Load したモデルを描画します。
    3. void Search(char *);
      Line の先頭から、key で始まる行をサーチ ⇒ Line, Col に設定
    4. void Token();
      Line, Col から次の Token を取得 ⇒ Word に設定
    5. void VP_3P();
      頂点 Index のN角ポリゴン ⇒ 3角ポリゴン
    6. void VN_3P();
      法線 Index のN角ポリゴン ⇒ 3角ポリゴン
  7. DirectX9 までは左手座標系だったのですが、Windows8のサンプルでは右手座標系になっているようです。
    DirectX9 の座標系の設定です。
        D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(0.0f, -5.0f, -30.0f),
                                    &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
                                    &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
        
    Windows8 の座標系の設定です。
        XMVECTOR eye = XMVectorSet(0.0f, 0.3f, 6.0f, 0.0f);
        XMVECTOR at = XMVectorSet(0.0f, -0.1f, 0.0f, 0.0f);
        XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
        XMStoreFloat4x4(&m_constantBufferData.view, XMMatrixTranspose(XMMatrixLookAtRH(eye, at, up)));
        XMStoreFloat4x4(&m_constantBufferData.model, 
            XMMatrixTranspose(XMMatrixRotationY(timeTotal*XM_PIDIV4) * XMMatrixRotationX(timeTotal*0.7f*XM_PIDIV4)));
    
        XMStoreFloat4x4(
            &m_constantBufferData.projection,
            XMMatrixTranspose(
                XMMatrixMultiply(
                    XMMatrixPerspectiveFovRH(
                        fovAngleY,
                        aspectRatio,
                        0.01f,
                        100.0f ),
                    XMLoadFloat4x4(&m_orientationTransform3D)
                    )
                )
            );
        
  8. X-FILE のポリゴンをそのまま描画すると、裏向きになるので「カリングモードを反転」して描画しています。
        // カリング設定
        D3D11_RASTERIZER_DESC rasterizerDesc;
        ZeroMemory( &rasterizerDesc, sizeof( D3D11_RASTERIZER_DESC ) );
        //rasterizerDesc.CullMode = D3D11_CULL_BACK;
        rasterizerDesc.CullMode = D3D11_CULL_FRONT;
        rasterizerDesc.FillMode = D3D11_FILL_SOLID;
        rasterizerDesc.DepthClipEnable = FALSE;
        rasterizerDesc.MultisampleEnable = TRUE;
        rasterizerDesc.DepthBiasClamp = 0;
        rasterizerDesc.SlopeScaledDepthBias = 0;
        DX::ThrowIfFailed(
            d3dDevice->CreateRasterizerState(
            &rasterizerDesc, &RasterizerState));
        
  9. Windows10 でリメークしたプロジェクトを XLoader Norm に掲載しています。
    XLoader Norm には XLoader.h(.cpp) のソースコードを掲載しているので併せて参照して下さい。
    Java でも X-FILE の Loader を作成しています。
    こちらの方がアニメーションにも対応した Loader で詳しく説明しています。

超初心者のプログラム入門(DirectX Store)