XLoader Norm

Windows10 の XLoader で「頂点+法線」のモデルを描画します。

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

XLoader Norm Model

  1. Win10 XLoader をベースに「頂点+法線」で構成される X-FILE を描画します。
    頂点データの形式は Win10 XLoader と同じなので、シェーダ関係のファイルはそのまま使います。
    自動生成したプロジェクトは「頂点+カラー」なのでシェーダーを入れ替えて下さい。
    シェーダーは Win10 Shader で説明しています。
    また Model Class はさわる必要が無いので、修正するのは XLoader.h と XLoader.cpp だけです。
      System⇒App.cpp⇒App1Main⇒Model⇒XLoader
    
  2. X Model から Box_4PNorm.x, gal2.x をダウンロードしてプロジェクトに組み込んで下さい。
    X-FILE は「頂点+法線」で構成されるモデルなら何でも良いので適当に調達して来ても構いません。
    組み込んだ X-FILE を右クリックしてコンテンツを True に設定して下さい。
    モデルの描画が大きすぎる(または小さすぎる)ときは Model Class のカメラで調整して下さい。
    組み込んだ X-FILE のソースを取得するのに BasicReaderWriter.h(.cpp) を使います。
    Windows10 DirectX Library を参照してプロジェクトに加えて下さい。
  3. XLoader.h のソースコードです。
    X-FILE を解析してモデルを作成して描画するための関数や領域を定義します。
    float3 は "BasicMath.h" で定義されています。
    Debug() 関数を組み込んでいますが、プログラムが完成すると不要です。
    vector<string> VT; に X-FILE のソースを行で切り分けて格納します。
    vector<float3> m_pos; が頂点座標の配列です。
    vector<float3> m_norm; が法線ベクトルの配列です。
    m_idxP; は頂点 Index の並びで m_idxN; は法線 Index の並びです。
    m_idxP3; m_idxN3; は三角ポリゴンに変換したときの Index の並びです。
    三角以上のポリゴンは三角ポリゴンに変換して描画されます。
    #pragma once
    
    #include "..\Common\DeviceResources.h"
    #include "..\Common\StepTimer.h"
    #include "ShaderStructures.h"
    #include "BasicReaderWriter.h"
    #include <vector>
    
    using namespace Platform;
    using namespace std;
    
    namespace App1
    {
        class XLoader
        {
        public:
            XLoader(const std::shared_ptr<DX::DeviceResources>& deviceResources);
            void Load();
            void Draw(ModelViewProjectionConstantBuffer);
            void Release();
    
        private:
            std::shared_ptr<DX::DeviceResources> m_deviceResources;
    
            Microsoft::WRL::ComPtr<ID3D11InputLayout>   m_inputLayout;
            Microsoft::WRL::ComPtr<ID3D11Buffer>        m_vertexBuffer;
            Microsoft::WRL::ComPtr<ID3D11Buffer>        m_indexBuffer;
            Microsoft::WRL::ComPtr<ID3D11VertexShader>  m_vertexShader;
            Microsoft::WRL::ComPtr<ID3D11PixelShader>   m_pixelShader;
            Microsoft::WRL::ComPtr<ID3D11Buffer>        m_constantBuffer;
    
            uint32  m_indexCount;
            bool    m_loadingComplete;
    
            Microsoft::WRL::ComPtr<ID3D11SamplerState>  m_sampler;
    
            ID3D11RasterizerState  *m_RasterizerState;
            vector<string>  VT;                 //X-FILE を行で切り分け
            int             VT_size;            //VT の大きさ
            vector<float3>  m_pos;              // 頂点座標
            vector<float3>  m_norm;             // 法線ベクトル
            vector<unsigned short> m_idxP;      // 頂点 Index の並び(角付)
            vector<unsigned short> m_idxN;      // 法線 Index の並び(角付)
            vector<unsigned short> m_idxP3;     // 頂点 Index(3P) の並び
            vector<unsigned short> m_idxN3;     // 法線 Index(3P) の並び
            int     m_Line, m_Col, m_Top;
            string  Word;
    
            bool Setfloat3(char *key, vector<float3> *f3);
            bool SetShort(vector<unsigned short> *val);
            void PX_P3(vector<unsigned short> PX, vector<unsigned short> *P3);
            void ComputeNorm(VertexPosition *Vertices, int siz);
            bool Search(char *);
            void Token();
        };
    }
    
  4. XLoader.cpp のソースコードです。
    X-FILE を解析してモデルを作成して描画します。
    Load() 関数で X Model を取得して解析します。
    Draw() 関数でモデルを描画します。
    X-FILE を解析する全ソースコードは Windows10 X_FILE や Windows10 Load_X Class を参照して下さい。
        //★ XFILE の解析
        int     num;
        int     pt,pw;
        byte    wk;
    
        BasicReaderWriter^ reader = ref new BasicReaderWriter();
        //Platform::Array<byte>^ buf = reader->ReadData("Box_4PNorm.x");
        Platform::Array<byte>^ buf = reader->ReadData("gal2.x");
    }
    
    // モデルを描画
    void XLoader::Draw(ModelViewProjectionConstantBuffer BuffData)
    {
        if (!m_loadingComplete)
        {   return; }
    
        auto context = m_deviceResources->GetD3DDeviceContext();
        ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
        context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
    
        context->UpdateSubresource(
            m_constantBuffer.Get(),
            0, NULL, &BuffData, 0, 0 );
    
        UINT stride = sizeof(VertexPosition);
        UINT offset = 0;
        context->IASetVertexBuffers(
            0, 1,
            m_vertexBuffer.GetAddressOf(),
            &stride, &offset);
    
        context->IASetIndexBuffer(
            m_indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0 );
    
        context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
        context->IASetInputLayout(m_inputLayout.Get());
        context->RSSetState(m_RasterizerState);
    
        context->VSSetShader(m_vertexShader.Get(), nullptr, 0);
    
        context->VSSetConstantBuffers(
            0, 1, m_constantBuffer.GetAddressOf() );
    
        context->PSSetShader(m_pixelShader.Get(), nullptr, 0);
    
        context->PSSetSamplers(0, 1, m_sampler.GetAddressOf());
    
        // オブジェクトを描画します。
        context->DrawIndexed(m_indexCount, 0, 0);
    }
    
  5. このプロジェクトは X-FILE Loader_1 をリメークしたものです。
    説明不足な点は、こちらも併せて参照して下さい。
    Win10 NormModel でも X-FILE の Norm Model を組み込んで描画しています。

X-FILE 名を渡す

  1. Load() 関数にパラメータを持たせて X-FILE 名を渡すと意味不明のエラーメッセージが表示されて動きませんでしたが、ようやく動かす方法を見つけました。
    XLoader.h でパラメータを持たせた Load() 関数を宣言して下さい。
    str が X-FILE の名前です。
        void Load(Platform::String ^str);
    
  2. Load() 関数の定義です。
    受け取った str を xfile に保存して、この名前でロードします。
    // Load X-FILE
    void XLoader::Load(Platform::String ^str)
    {
        static String ^xfile = str;
    
        ・・・
    
        BasicReaderWriter^ reader = ref new BasicReaderWriter();
        Platform::Array<byte>^ buf = reader->ReadData(xfile);
    
  3. Model.cpp から Load() 関数の呼び出し方は次のようになります。
    "gal2.x", "Box_4PNorm.x" 等は事前にプロジェクトのフォルダーに格納しておいて下さい。
    void Model::CreateDeviceDependentResources()
    {
        xloader = std::unique_ptr<XLoader>(new XLoader(m_deviceResources));
        xloader->Load("gal2.x");
        //xloader->Load("Box_4PNorm.x");
    }  
    
  4. 不思議なことに、このページを更新するためにプログラムを検証中に str を直接指定しても動くことを確認しました。
    これが出来ないから苦労していたのですが、どうなっているのでしょう? (^_^;)
    どこかで私がミスっていた?
    自動的にシステムが更新されてエラーが修復された?
    // Load X-FILE
    void XLoader::Load(Platform::String ^str)
    {
        BasicReaderWriter^ reader = ref new BasicReaderWriter();
        Platform::Array<byte>^ buf = reader->ReadData(str);
    

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