DirectX Lib

Windows10 DirectX Library

Windows10 DirectX で汎用的に使用するクラス(関数)のソースコードです。
ページのあちらこちらに重複して掲載されているソースコードをまとめます。

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

DirectX Library Index

Debug Message

  1. OutputDebugString は windows.h で定義されています。
    OutputDebugString を単独で使用する場合です。
        OutputDebugString(L"Debug Message");    
        OutputDebugString(L"★Test Debug Message\n");    
    
  2. String^ msg を[カッコで囲って]改行を付加して印字します。
    void Load_X::Debug(String^ msg)
    {   String^ str = "**[" + msg + "]\n";
        OutputDebugString(str->Data());
    }
    
  3. メッセージと共に int 型の値を印字します。
    void Load_OBJ::Debug(LPWSTR msg, int val)
    {
        wchar_t str[80];
        swprintf(str, 80, L"%s: %d\r\n", msg, val);
        OutputDebugString(str);
    }
    
  4. float3 の値を(かっこで囲って)印字します。
    void Load_OBJ::Debug(float3 f3)
    {
        String^ str = ref new Platform::String(L"float3(");
        str += f3.x.ToString();
        str += "f , ";
        str += f3.y.ToString();
        str += "f , ";
        str += f3.z.ToString();
        str += "f), \r\n";
        OutputDebugString(str->Data());
    }
    
  5. Shift-JIS の文字列を先頭から最大 1000 文字を印字します。
    void Load_OBJ::Debug(char *str)
    {   WCHAR   wk[1000];
        MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,str,-1,wk,1000);
        OutputDebugString(wk);
        OutputDebugString(L"\r\n");
    }
    
  6. Array<byte>^ の先頭から最大 10000 文字を印字します。
    void DirectXPage::Model_Text(Array<byte>^ buf)
    {
        char    *wp;
        WCHAR   wk[10000];
        wp = (char *)&buf[0];
        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, wp, -1, wk, 10000);
        OutputDebugString(wk);
    }
    
  7. vector 配列で渡された unsigned short を印字します。
    void Load_OBJ::Debug(vector<unsigned short> val)
    {
        String^ str = ref new String(L"short[");
        str += val.size().ToString();
        str += L"]:";
        for (unsigned i = 0; i < val.size(); i++)
        {
            str += val[i].ToString();
            str += " ";
        }
        str += "\r\n";
        OutputDebugString(str->Data());
    }
    

MyCamera Class

  1. MyCamera.h で定義されている代表的な領域です。
        DirectX::XMVECTOR   m_eye = { 0.0f, 0.7f, 1.5f, 0.0f };
        DirectX::XMVECTOR   m_at = { 0.0f, -0.1f, 0.0f, 0.0f };
        DirectX::XMVECTOR   m_up = { 0.0f, 1.0f, 0.0f, 0.0f };
    
        DirectX::XMFLOAT4X4 m_projection;
        DirectX::XMFLOAT4X4 m_view;
        DirectX::XMFLOAT4X4 m_model;
    
  2. Projection() 関数です。
    // m_projection を設定します
    void MyCamera::Projection()
    {
        Size outputSize = m_deviceResources->GetOutputSize();
        float aspectRatio = outputSize.Width / outputSize.Height;
        float fovAngleY = 70.0f * XM_PI / 180.0f;
        if (aspectRatio < 1.0f)
        {   fovAngleY *= 2.0f;  }
        XMMATRIX perspectiveMatrix = XMMatrixPerspectiveFovRH(
        fovAngleY, aspectRatio, 0.01f, 100.0f);
    
        XMFLOAT4X4 orientation = m_deviceResources->GetOrientationTransform3D();
        XMMATRIX orientationMatrix = XMLoadFloat4x4(&orientation);
        XMStoreFloat4x4(&m_projection, XMMatrixTranspose(perspectiveMatrix * orientationMatrix));
    }
    
  3. Camera() 関数です。
    // m_view を設定します
    void MyCamera::Camera(XMVECTOR eye, XMVECTOR at, XMVECTOR up)
    {   m_eye = eye;
        m_at = at;
        m_up = up;
        XMStoreFloat4x4(&m_view, XMMatrixTranspose(XMMatrixLookAtRH(m_eye, m_at, m_up)));
    }
    
  4. Model() 関数です。
    // Model を回転する
    void MyCamera::Model(float rx, float ry, float rz)
    {   XMMATRIX    mat;
        mat = XMMatrixRotationX(rx) * XMMatrixRotationY(ry) * XMMatrixRotationX(rz);
        XMStoreFloat4x4(&m_model, mat);
    }
    
  5. View() 関数です。
    // カメラを回転する
    void MyCamera::View(float dx, float dy, float dz)
    {   XMMATRIX    view, mat;
        view = XMMatrixTranspose(XMMatrixLookAtRH(m_eye, m_at, m_up));
        mat = XMMatrixRotationRollPitchYaw(dy, dx, dz);
        XMStoreFloat4x4(&m_view, mat * view);
    }
    

Load_OBJ Class

  1. Load_OBJ.h で定義されている代表的な領域です。
        std::string str;            // OBJ Model ソースコード
        vector<string>  VT;         // 行(\n)で切り分け
        int             VT_size;    // VT の大きさ
        vector<string>  TK;         // VT[m_pt] の行をトークンで切り分け
    
        vector<float3>  m_pos;      // 頂点座標
        vector<uint16>  m_idxP;     // 頂点 Index の並び(角付)
        vector<uint16>  m_idxP3;    // 頂点 Index(3P) の並び
    
        vector<VertexPosition>  m_Vertex;
        vector<uint16>          m_Index;
    
  2. f3() 関数です。
    struct float3
    {
        float   x;
        float   y;
        float   z;
    };
    
    float3 Load_OBJ::f3(float x, float y, float z)
    {
        float3 wf3;
        wf3.x = x;
        wf3.y = y;
        wf3.z = z;
        return wf3;
    }
    
  3. CreateModel() 関数です。
    m_Vertex, m_Index を参照してモデルを生成します。
    m_Vertex には頂点データの形式(pos+norm+tex+color)に合わせたモデル情報が格納されています。
    // Model を作成
    void Load_OBJ::CreateModel(
        ID3D11Buffer **vertexBuffer,
        ID3D11Buffer **indexBuffer,
        uint32 *indexCount)
    {
        // 法線ベクトルの計算
        ComputeNorm(m_Vertex.data(), m_Vertex.size());
    
        *indexCount = m_Index.size();
        // メッシュを生成
        D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
        vertexBufferData.pSysMem = m_Vertex.data();
        vertexBufferData.SysMemPitch = 0;
        vertexBufferData.SysMemSlicePitch = 0;
        CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(VertexPosition)*(*indexCount), D3D11_BIND_VERTEX_BUFFER);
        DX::ThrowIfFailed(
            m_deviceResources->GetD3DDevice()->CreateBuffer(
                &vertexBufferDesc, &vertexBufferData, vertexBuffer));
    
        // インデックスを生成
        D3D11_SUBRESOURCE_DATA indexBufferData = {0};
        indexBufferData.pSysMem = m_Index.data();
        indexBufferData.SysMemPitch = 0;
        indexBufferData.SysMemSlicePitch = 0;
        CD3D11_BUFFER_DESC indexBufferDesc(sizeof(uint16)*(*indexCount), D3D11_BIND_INDEX_BUFFER);
        DX::ThrowIfFailed(
            m_deviceResources->GetD3DDevice()->CreateBuffer(
                &indexBufferDesc, &indexBufferData, indexBuffer));
    
        // 領域の解放
        m_Vertex.clear();
        m_Index.clear();
    
        // カリング設定
        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(
            m_deviceResources->GetD3DDevice()->CreateRasterizerState(
                &rasterizerDesc, &m_RasterizerState));
    }
    
  4. Token() 関数です。
    // VT[m_pt]⇒st をトークンで切り分けて TK に格納
    void Load_OBJ::Token(string st)
    {
        uint32 pt, wk;
    
        TK.clear();
        for (pt = 0; pt<st.length(); )
        {
            wk = st.find_first_not_of(" ,;", pt);
            if (st[wk] == '\r' || st[wk] == '\n')   return;
            pt = wk;
            wk = st.find_first_of(" ,;\r\n", pt);
            if (wk > pt)
            {
                Word = Word.assign(st, pt, wk-pt);
                TK.push_back(Word);
                pt = wk;
            }
            else    pt++;
        }
    }
    
  5. PX_P3() 関数です。
    多角形ポリゴンを3角形ポリゴンに変換します。
    // 多角形ポリゴン ⇒ 3角ポリゴン
    void Load_OBJ::PX_P3(vector<uint16> PX, vector<uint16> *P3)
    {
        int    i, j, num, pn;
        num = PX.size();
        for (i = 0; i<num; )
        {
            pn = (int)PX[i];
            i++;
            switch (pn)
            {
            case 3:     //TRIANGLESTRIP 3
                P3->push_back(PX[i]);
                P3->push_back(PX[i + 1]);
                P3->push_back(PX[i + 2]);
                break;
            case 4:     //TRIANGLESTRIP 4
                P3->push_back(PX[i]);
                P3->push_back(PX[i + 1]);
                P3->push_back(PX[i + 2]);
                P3->push_back(PX[i]);
                P3->push_back(PX[i + 2]);
                P3->push_back(PX[i + 3]);
                break;
            default:
                for (j = 0; j <= pn - 3; j++)
                {
                    P3->push_back(PX[i]);
                    P3->push_back(PX[i + 1]);
                    P3->push_back(PX[i + 2]);
                }
                break;
            }
            i += pn;
        }
    }
    
  6. ComputeNorm() 関数です。
    // 法線ベクトルの計算
    void Load_OBJ::ComputeNorm(VertexPosition *vtx, int siz)
    {
        for (int i = 0; i<siz; i += 3)
        {
            float ax = vtx[i + 2].pos.x - vtx[i + 1].pos.x;
            float ay = vtx[i + 2].pos.y - vtx[i + 1].pos.y;
            float az = vtx[i + 2].pos.z - vtx[i + 1].pos.z;
            float bx = vtx[i + 0].pos.x - vtx[i + 1].pos.x;
            float by = vtx[i + 0].pos.y - vtx[i + 1].pos.y;
            float bz = vtx[i + 0].pos.z - vtx[i + 1].pos.z;
    
            float nx = ay * bz - az * by;
            float ny = az * bx - ax * bz;
            float nz = ax * by - ay * bx;
    
            vtx[i + 0].norm.x = nx;
            vtx[i + 0].norm.y = ny;
            vtx[i + 0].norm.z = nz;
            vtx[i + 1].norm = vtx[i + 0].norm;
            vtx[i + 2].norm = vtx[i + 0].norm;
        }
    }
    
  7. SetCullMode() 関数です。
    // カリングの設定
    void Load_OBJ:: SetCullMode()
    {
        auto context = m_deviceResources->GetD3DDeviceContext();
        context->RSSetState(m_RasterizerState);
    }
    

X-FILE Class

  1. X-FILE の解析に使用される代表的な領域です。
    XMFLOAT3 と float3 は共に3次元座標の構造体ですが、直接代入することは出来ないようです。
        vector<string>  VT;                 //X-FILE を行で切り分け
        int             VT_size;            //VT の大きさ
        vector<DirectX::XMFLOAT3> m_pos;    // 頂点座標
        vector<DirectX::XMFLOAT3> 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;
    
  2. Search() 関数です。
    見つけた行を m_Line に設定します。
    // m_Line から key で始まる行をサーチ
    bool Search(char *key)
    {
        for (; m_Line<VT_size - 1; m_Line++)
        {
            m_Col = VT[m_Line].find(key);
            if (m_Col != -1)    return true;
        }
        return false;
    }
    
  3. Token() 関数です。
    m_Line, m_Col は次の位置に設定されます。
    // m_Line, m_Col から次の Token を取得 ⇒ Word に設定
    void Token()
    {
        int wk;
        Word = "";
        for (; m_Line<VT_size - 1; m_Line++)
        {
            wk = VT[m_Line].find_first_not_of(" ,;{}\r\n", m_Col);
            m_Col = wk;
            wk = VT[m_Line].find_first_of(" ,;}\r\n", m_Col);
            if (wk>m_Col)
            {
                Word = Word.assign(VT[m_Line], m_Col, wk - m_Col);
                m_Col = wk + 1;
                return;
            }
            m_Col = 0;
        }
    }
    
  4. LineToken() 関数です。
    Token() 関数は次の行に進みますが、m_Line の行だけ検索します。
    // Line, Col から次の Token を取得 ⇒ Word に設定(Line 行だけ検索)
    bool LineToken()
    {
        int wk;
        Word= "";
        if (m_Col>=(int)VT[m_Line].size())  return false;
        wk= VT[m_Line].find_first_not_of(" ,;{}\r\n", m_Col);
        m_Col= wk;
        wk= VT[m_Line].find_first_of(" ,;}\r\n", m_Col);
        if (wk>m_Col)
        {   Word= Word.assign(VT[m_Line], m_Col, wk-m_Col);
            m_Col= wk + 1;
            return true;
        }
        return false;
    }
    
  5. SetXMFLOAT3() 関数です。
    XMFLOAT3 と float3 は共に3次元座標の構造体です。
    // *key を検索して f3 に三次元座標を設定
    bool SetXMFLOAT3(char *key, vector<DirectX::XMFLOAT3> *f3)
    {
        int     num,i;
        float   x, y, z;
        DirectX::XMFLOAT3 wf3;
    
        if (Search(key)==false)
        {
            OutputDebugString(L"Keyword Not found\r\n");
            return false;
        }
    
        m_Line++;
        m_Col = 0;
        Token();
        num = atoi((char *)Word.data());
        if (num<3)
        {
            OutputDebugString(L"Mesh Vertex Error\r\n");
            return false;
        }
    
        // 頂点座標を f3 に設定
        for (i = 0; i<num; i++)
        {
            Token();
            x = (float)atof((char *)Word.data());
            Token();
            y = (float)atof((char *)Word.data());
            Token();
            z = (float)atof((char *)Word.data());
            wf3 = XMFLOAT3(x, y, z);
            f3->push_back(wf3);
        }
        return true;
    }
    
  6. SetXMFLOAT2() 関数です。
    // *key を検索して f2 に二次元座標を設定
    bool SetXMFLOAT2(char *key, vector<XMFLOAT2> *f2)
    {
        int     num,i;
        float   x, y;
        XMFLOAT2 wf2;
    
        if (Search(key)==false)
        {
            OutputDebugString(L"Keyword Not found\r\n");
            return false;
        }
    
        m_Line++;
        m_Col = 0;
        Token();
        num = atoi((char *)Word.data());
        if (num<3)
        {
            OutputDebugString(L"Mesh Vertex Error\r\n");
            return false;
        }
    
        // 頂点座標を f2 に設定
        for (i = 0; i<num; i++)
        {
            Token();
            x = (float)atof((char *)Word.data());
            Token();
            y = (float)atof((char *)Word.data());
            wf2 = XMFLOAT2(x, y);
            f2->push_back(wf2);
        }
        return true;
    }
    
  7. SetShort() 関数です。
    // 現在の位置(m_Line, m_Col)から Index を val に格納する
    bool SetShort(vector<unsigned short> *val)
    {
        int i,j,cn,num;
        unsigned short wk;
    
        Token();
        num= atoi((char *)Word.data());
        if (num<3)
        {   OutputDebugString(L"Index Count Error\r\n");
            return false;
        }
        for(i=0; i<num; i++)
        {
            Token();
            cn= atoi((char *)Word.data());
            val->push_back(cn);
            for(j=0; j<cn; j++)
            {
                Token();
                wk = atoi((char *)Word.data());
                val->push_back(wk);
            }
        }
        return true;
    }
    
  8. PX_P3() 関数です。
    // N角ポリゴン ⇒ 3角ポリゴン
    void PX_P3(vector<unsigned short> PX, vector<unsigned short> *P3)
    {
        int    i, j, num, pn;
        num = PX.size();
        for (i = 0; i<num; )
        {
            pn = (int)PX[i];
            i++;
            switch (pn)
            {
            case 3:     //TRIANGLESTRIP 3
                P3->push_back(PX[i]);
                P3->push_back(PX[i + 1]);
                P3->push_back(PX[i + 2]);
                break;
            case 4:     //TRIANGLESTRIP 4
                P3->push_back(PX[i]);
                P3->push_back(PX[i + 1]);
                P3->push_back(PX[i + 2]);
                P3->push_back(PX[i]);
                P3->push_back(PX[i + 2]);
                P3->push_back(PX[i + 3]);
                break;
            default:
                for (j = 0; j <= pn - 3; j++)
                {
                    P3->push_back(PX[i]);
                    P3->push_back(PX[i + 1]);
                    P3->push_back(PX[i + 2]);
                }
                break;
            }
            i += pn;
        }
    }
    
  9. ComputeNorm() 関数です。
    // 法線ベクトルの計算
    void ComputeNorm(VertexPosition *Vertices, int siz)
    {
        for (int i = 0; i<siz; i += 3)
        {
            float ax = Vertices[i + 2].pos.x - Vertices[i + 1].pos.x;
            float ay = Vertices[i + 2].pos.y - Vertices[i + 1].pos.y;
            float az = Vertices[i + 2].pos.z - Vertices[i + 1].pos.z;
            float bx = Vertices[i + 0].pos.x - Vertices[i + 1].pos.x;
            float by = Vertices[i + 0].pos.y - Vertices[i + 1].pos.y;
            float bz = Vertices[i + 0].pos.z - Vertices[i + 1].pos.z;
    
            float nx = ay * bz - az * by;
            float ny = az * bx - ax * bz;
            float nz = ax * by - ay * bx;
    
            Vertices[i + 0].norm = XMFLOAT3(nx, ny, nz);
            Vertices[i + 1].norm = XMFLOAT3(nx, ny, nz);
            Vertices[i + 2].norm = XMFLOAT3(nx, ny, nz);
        }
    }
    

BasicReaderWriter Class

  1. BasicReaderWriter.h です。
    //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
    //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
    //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    //// PARTICULAR PURPOSE.
    ////
    //// Copyright (c) Microsoft Corporation. All rights reserved
    
    #pragma once
    
    #include <ppltasks.h>
    
    // A simple reader/writer class that provides support for reading and writing
    // files on disk. Provides synchronous and asynchronous methods.
    ref class BasicReaderWriter
    {
    private:
        Windows::Storage::StorageFolder^ m_location;
    
    internal:
        BasicReaderWriter();
        BasicReaderWriter(
            _In_ Windows::Storage::StorageFolder^ folder
            );
    
        Platform::Array<byte>^ ReadData(
            _In_ Platform::String^ filename
            );
    
        concurrency::task<Platform::Array<byte>^> ReadDataAsync(
            _In_ Platform::String^ filename
            );
    
        uint32 WriteData(
            _In_ Platform::String^ filename,
            _In_ const Platform::Array<byte>^ fileData
            );
    
        concurrency::task<void> WriteDataAsync(
            _In_ Platform::String^ filename,
            _In_ const Platform::Array<byte>^ fileData
            );
    };
    
  2. BasicReaderWriter.cpp です。
    ファイルが見つからないときの名前を OutputDebugString で印字しています。
    //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
    //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
    //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    //// PARTICULAR PURPOSE.
    ////
    //// Copyright (c) Microsoft Corporation. All rights reserved
    
    #include "pch.h"
    #include "BasicReaderWriter.h"
    
    using namespace Microsoft::WRL;
    using namespace Windows::Storage;
    using namespace Windows::Storage::FileProperties;
    using namespace Windows::Storage::Streams;
    using namespace Windows::Foundation;
    using namespace Windows::ApplicationModel;
    using namespace concurrency;
    
    BasicReaderWriter::BasicReaderWriter()
    {
        m_location = Package::Current->InstalledLocation;
    }
    
    BasicReaderWriter::BasicReaderWriter(
        _In_ Windows::Storage::StorageFolder^ folder
        )
    {
        m_location = folder;
        Platform::String^ path = m_location->Path;
        if (path->Length() == 0)
        {
            // Applications are not permitted to access certain
            // folders, such as the Documents folder, using this
            // code path.  In such cases, the Path property for
            // the folder will be an empty string.
            throw ref new Platform::FailureException();
        }
    }
    
    Platform::Array<byte>^ BasicReaderWriter::ReadData(
        _In_ Platform::String^ filename
        )
    {
        CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0};
        extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
        extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
        extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN;
        extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
        extendedParams.lpSecurityAttributes = nullptr;
        extendedParams.hTemplateFile = nullptr;
    
        Wrappers::FileHandle file(
            CreateFile2(
                filename->Data(),
                GENERIC_READ,
                FILE_SHARE_READ,
                OPEN_EXISTING,
                &extendedParams
                )
            );
        if (file.Get() == INVALID_HANDLE_VALUE)
        {
            Platform::String^ str = "***[" + filename + "]\n";
            OutputDebugString(str->Data());
            throw ref new Platform::FailureException();
        }
    
        FILE_STANDARD_INFO fileInfo = {0};
        if (!GetFileInformationByHandleEx(
            file.Get(),
            FileStandardInfo,
            &fileInfo,
            sizeof(fileInfo)
            ))
        {
            throw ref new Platform::FailureException();
        }
    
        if (fileInfo.EndOfFile.HighPart != 0)
        {
            throw ref new Platform::OutOfMemoryException();
        }
    
        Platform::Array<byte>^ fileData = ref new Platform::Array<byte>(fileInfo.EndOfFile.LowPart);
    
        if (!ReadFile(
            file.Get(),
            fileData->Data,
            fileData->Length,
            nullptr,
            nullptr
            ))
        {
            throw ref new Platform::FailureException();
        }
    
        return fileData;
    }
    
    task<Platform::Array<byte>^> BasicReaderWriter::ReadDataAsync(
        _In_ Platform::String^ filename
        )
    {
        return task<StorageFile^>(m_location->GetFileAsync(filename)).then([=](StorageFile^ file)
        {
            return FileIO::ReadBufferAsync(file);
        }).then([=](IBuffer^ buffer)
        {
            auto fileData = ref new Platform::Array<byte>(buffer->Length);
            DataReader::FromBuffer(buffer)->ReadBytes(fileData);
            return fileData;
        });
    }
    
    uint32 BasicReaderWriter::WriteData(
        _In_ Platform::String^ filename,
        _In_ const Platform::Array<byte>^ fileData
        )
    {
        CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0};
        extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
        extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
        extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN;
        extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
        extendedParams.lpSecurityAttributes = nullptr;
        extendedParams.hTemplateFile = nullptr;
    
        Wrappers::FileHandle file(
            CreateFile2(
                filename->Data(),
                GENERIC_WRITE,
                0,
                CREATE_ALWAYS,
                &extendedParams
                )
            );
        if (file.Get() == INVALID_HANDLE_VALUE)
        {
            throw ref new Platform::FailureException();
        }
    
        DWORD numBytesWritten;
        if (
            !WriteFile(
                file.Get(),
                fileData->Data,
                fileData->Length,
                &numBytesWritten,
                nullptr
                ) ||
            numBytesWritten != fileData->Length
            )
        {
            throw ref new Platform::FailureException();
        }
    
        return numBytesWritten;
    }
    
    task<void> BasicReaderWriter::WriteDataAsync(
        _In_ Platform::String^ filename,
        _In_ const Platform::Array<byte>^ fileData
        )
    {
        return task<StorageFile^>(m_location->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting)).then([=](StorageFile^ file)
        {
            FileIO::WriteBytesAsync(file, fileData);
        });
    }
    

TextureLoader Class

  1. TextureLoader.h です。
    File Picker からテクスチャを選択できるように次の関数を追加しました。
        void LoadTexture(
            _In_ Platform::Array<byte>^ tex,
            _In_ Platform::String^ filename,
            _Out_opt_ ID3D11Texture2D** texture,
            _Out_opt_ ID3D11ShaderResourceView** textureView
            );
    
    /***************************************************/
    /* TextureLoader Class Header File  Ver-2  前田 稔 */
    /***************************************************/
    #pragma once
    #include "BasicReaderWriter.h"
    
    ref class TextureLoader
    {
    internal:
        TextureLoader(
            _In_ ID3D11Device* d3dDevice,
            _In_opt_ IWICImagingFactory2* wicFactory = nullptr
            );
    
        void LoadTexture(
            _In_ Platform::String^ filename,
            _Out_opt_ ID3D11Texture2D** texture,
            _Out_opt_ ID3D11ShaderResourceView** textureView
            );
    
        void LoadTexture(
            _In_ Platform::Array<byte>^ tex,
            _In_ Platform::String^ filename,
            _Out_opt_ ID3D11Texture2D** texture,
            _Out_opt_ ID3D11ShaderResourceView** textureView
            );
    
        concurrency::task<void> LoadTextureAsync(
            _In_ Platform::String^ filename,
            _Out_opt_ ID3D11Texture2D** texture,
            _Out_opt_ ID3D11ShaderResourceView** textureView
            );
    
    private:
        Microsoft::WRL::ComPtr<ID3D11Device> m_d3dDevice;
        Microsoft::WRL::ComPtr<IWICImagingFactory2> m_wicFactory;
        BasicReaderWriter^ m_basicReaderWriter;
    
        void CreateTexture(
            _In_reads_bytes_(dataSize) byte* data,
            _In_ uint32 dataSize,
            _Out_opt_ ID3D11Texture2D** texture,
            _Out_opt_ ID3D11ShaderResourceView** textureView,
            _In_opt_ Platform::String^ debugName
            );
    };
    
  2. TextureLoader.cpp です。
    /****************************************************/
    /* TextureLoader Class Program File  Ver-2  前田 稔 */
    /****************************************************/
    #include "pch.h"
    #include "TextureLoader.h"
    #include "..\Common\DirectXHelper.h"
    
    using namespace Microsoft::WRL;
    using namespace std;
    using namespace concurrency;
    
    TextureLoader::TextureLoader(
        _In_ ID3D11Device* d3dDevice,
        _In_opt_ IWICImagingFactory2* wicFactory
        ) :
        m_d3dDevice(d3dDevice),
        m_wicFactory(wicFactory)
    {
        // Create a new BasicReaderWriter to do raw file I/O.
        m_basicReaderWriter = ref new BasicReaderWriter();
    }
    
    void TextureLoader::CreateTexture(
        _In_reads_bytes_(dataSize) byte* data,
        _In_ uint32 dataSize,
        _Out_opt_ ID3D11Texture2D** texture,
        _Out_opt_ ID3D11ShaderResourceView** textureView,
        _In_opt_ Platform::String^ debugName
        )
    {
        ComPtr<ID3D11ShaderResourceView> shaderResourceView;
        ComPtr<ID3D11Texture2D> texture2D;
        if (m_wicFactory.Get() == nullptr)
        {
            // A WIC factory object is required in order to load texture
            // assets stored in non-DDS formats.  If TextureLoader was not
            // initialized with one, create one as needed.
            DX::ThrowIfFailed(
                CoCreateInstance(
                    CLSID_WICImagingFactory,
                    nullptr,
                    CLSCTX_INPROC_SERVER,
                    IID_PPV_ARGS(&m_wicFactory)
                    )
                );
        }
    
        ComPtr<IWICStream> stream;
        DX::ThrowIfFailed(
            m_wicFactory->CreateStream(&stream)
            );
    
        DX::ThrowIfFailed(
            stream->InitializeFromMemory(
                data,
                dataSize
                )
            );
    
        ComPtr<IWICBitmapDecoder> bitmapDecoder;
        DX::ThrowIfFailed(
            m_wicFactory->CreateDecoderFromStream(
                stream.Get(),
                nullptr,
                WICDecodeMetadataCacheOnDemand,
                &bitmapDecoder
                )
            );
    
        ComPtr<IWICBitmapFrameDecode> bitmapFrame;
        DX::ThrowIfFailed(
            bitmapDecoder->GetFrame(0, &bitmapFrame)
            );
    
        ComPtr<IWICFormatConverter> formatConverter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&formatConverter)
            );
    
        DX::ThrowIfFailed(
            formatConverter->Initialize(
                bitmapFrame.Get(),
                GUID_WICPixelFormat32bppPBGRA,
                WICBitmapDitherTypeNone,
                nullptr,
                0.0,
                WICBitmapPaletteTypeCustom
                )
            );
    
        uint32 width;
        uint32 height;
        DX::ThrowIfFailed(
            bitmapFrame->GetSize(&width, &height)
            );
    
        std::unique_ptr<byte[]> bitmapPixels(new byte[width * height * 4]);
        DX::ThrowIfFailed(
            formatConverter->CopyPixels(
                nullptr,
                width * 4,
                width * height * 4,
                bitmapPixels.get()
                )
            );
    
        D3D11_SUBRESOURCE_DATA initialData;
        ZeroMemory(&initialData, sizeof(initialData));
        initialData.pSysMem = bitmapPixels.get();
        initialData.SysMemPitch = width * 4;
        initialData.SysMemSlicePitch = 0;
    
        CD3D11_TEXTURE2D_DESC textureDesc(
            DXGI_FORMAT_B8G8R8A8_UNORM,
            width,
            height,
            1,
            1
            );
    
        DX::ThrowIfFailed(
            m_d3dDevice->CreateTexture2D(
                &textureDesc,
                &initialData,
                &texture2D
                )
            );
    
        if (textureView != nullptr)
        {
            CD3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc(
                texture2D.Get(),
                D3D11_SRV_DIMENSION_TEXTURE2D
                );
    
            DX::ThrowIfFailed(
                m_d3dDevice->CreateShaderResourceView(
                    texture2D.Get(),
                    &shaderResourceViewDesc,
                    &shaderResourceView
                    )
                );
        }
    
        if (texture != nullptr)
        {
            *texture = texture2D.Detach();
        }
        if (textureView != nullptr)
        {
            *textureView = shaderResourceView.Detach();
        }
    }
    
    void TextureLoader::LoadTexture(
        _In_ Platform::String^ filename,
        _Out_opt_ ID3D11Texture2D** texture,
        _Out_opt_ ID3D11ShaderResourceView** textureView
        )
    {
        Platform::Array<byte>^ textureData = m_basicReaderWriter->ReadData(filename);
    
        CreateTexture(
            textureData->Data,
            textureData->Length,
            texture,
            textureView,
            filename
            );
    }
    
    void TextureLoader::LoadTexture(
        _In_ Platform::Array<byte>^ textureData,
        _In_ Platform::String^ filename,
        _Out_opt_ ID3D11Texture2D** texture,
        _Out_opt_ ID3D11ShaderResourceView** textureView
        )
    {
        CreateTexture(
            textureData->Data,
            textureData->Length,
            texture,
            textureView,
            filename
            );
    }
    
    task<void> TextureLoader::LoadTextureAsync(
        _In_ Platform::String^ filename,
        _Out_opt_ ID3D11Texture2D** texture,
        _Out_opt_ ID3D11ShaderResourceView** textureView
        )
    {
        return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array<byte>^ textureData)
        {
            CreateTexture(
                textureData->Data,
                textureData->Length,
                texture,
                textureView,
                filename
                );
        });
    }
    

BasicMath

  1. BasicMath.h です。
    //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
    //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
    //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    //// PARTICULAR PURPOSE.
    ////
    //// Copyright (c) Microsoft Corporation. All rights reserved
    
    #pragma once
    
    #define _USE_MATH_DEFINES
    #include <math.h>
    
    // This header defines math and matrix helper functions and structures used 
    // by DirectX SDK samples.
    
    // Common Constants
    
    #define PI_F 3.1415927f
    
    // Template Vector & Matrix Classes
    
    template <class T> struct Vector2
    {
        union
        {
            struct
            {
                T x;
                T y;
            };
            struct
            {
                T r;
                T g;
            };
            struct
            {
                T u;
                T v;
            };
        };
    
        T& operator[](unsigned int index)
        {
            return static_cast<T*>(this)[index];
        }
    
        Vector2(T _x = 0, T _y = 0) : x(_x), y(_y) { }
    };
    
    template <class T> struct Vector3
    {
        union
        {
            struct
            {
                T x;
                T y;
                T z;
            };
            struct
            {
                T r;
                T g;
                T b;
            };
            struct
            {
                T u;
                T v;
                T w;
            };
        };
    
        T& operator[](unsigned int index)
        {
            return static_cast<T*>(this)[index];
        }
    
        Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z) { }
    };
    
    template <class T> struct Vector4
    {
        union
        {
            struct
            {
                T x;
                T y;
                T z;
                T w;
            };
            struct
            {
                T r;
                T g;
                T b;
                T a;
            };
        };
    
        T& operator[](unsigned int index)
        {
            return static_cast<T*>(this)[index];
        }
    
        Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0) : x(_x), y(_y), z(_z), w(_w) { }
    };
    
    template <class T> struct Matrix4x4
    {
        union
        {
            struct
            {
                T _11; T _12; T _13; T _14;
                T _21; T _22; T _23; T _24;
                T _31; T _32; T _33; T _34;
                T _41; T _42; T _43; T _44;
            };
            struct
            {
                T _m00; T _m01; T _m02; T _m03;
                T _m10; T _m11; T _m12; T _m13;
                T _m20; T _m21; T _m22; T _m23;
                T _m30; T _m31; T _m32; T _m33;
            };
        };
    
        Matrix4x4(T value = 0)
        {
            _11 = _12 = _13 = _14 = value;
            _21 = _22 = _23 = _24 = value;
            _31 = _32 = _33 = _34 = value;
            _41 = _42 = _43 = _44 = value;
        }
    
        Matrix4x4(
            T i11, T i12, T i13, T i14,
            T i21, T i22, T i23, T i24,
            T i31, T i32, T i33, T i34,
            T i41, T i42, T i43, T i44
            )
        {
            _11 = i11; _12 = i12; _13 = i13; _14 = i14;
            _21 = i21; _22 = i22; _23 = i23; _24 = i24;
            _31 = i31; _32 = i32; _33 = i33; _34 = i34;
            _41 = i41; _42 = i42; _43 = i43; _44 = i44;
        }
    
        T* operator[](unsigned int index)
        {
            return &(reinterpret_cast<T*>(this)[index*4]);
        }
    };
    
    // Template Vector Operations
    
    template <class T>
    T dot(Vector2<T> a, Vector2<T> b)
    {
        return a.x * b.x + a.y * b.y;
    }
    
    template <class T>
    T dot(Vector3<T> a, Vector3<T> b)
    {
        return a.x * b.x + a.y * b.y + a.z * b.z;
    }
    
    template <class T>
    T dot(Vector4<T> a, Vector4<T> b)
    {
        return a.x * b.x + a.y * b.y + a.z * b.z + a.w + b.w;
    }
    
    template <class T>
    T length(Vector2<T> a)
    {
        return sqrt(a.x * a.x + a.y * a.y);
    }
    
    template <class T>
    T length(Vector3<T> a)
    {
        return sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
    }
    
    template <class T>
    T length(Vector4<T> a)
    {
        return sqrt(a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w);
    }
    
    template <class T>
    Vector3<T> cross(Vector3<T> a, Vector3<T> b)
    {
        return Vector3<T>((a.y*b.z)-(a.z*b.y), (a.z*b.x)-(a.x*b.z), (a.x*b.y)-(a.y*b.x));
    }
    
    template <class T>
    Vector2<T> normalize(Vector2<T> a)
    {
        T len = length(a);
        return Vector2<T>(a.x / len, a.y / len);
    }
    
    template <class T>
    Vector3<T> normalize(Vector3<T> a)
    {
        T len = length(a);
        return Vector3<T>(a.x / len, a.y / len, a.z / len);
    }
    
    template <class T>
    Vector4<T> normalize(Vector4<T> a)
    {
        T len = length(a);
        return Vector4<T>(a.x / len, a.y / len, a.z / len, a.w / len);
    }
    
    // Template Vector Operators
    
    template <class T>
    Vector2<T> operator-(Vector2<T> a, Vector2<T> b)
    {
        return Vector2<T>(a.x - b.x, a.y - b.y);
    }
    
    template <class T>
    Vector2<T> operator-(Vector2<T> a)
    {
        return Vector2<T>(-a.x, -a.y);
    }
    
    template <class T>
    Vector3<T> operator-(Vector3<T> a, Vector3<T> b)
    {
        return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
    }
    
    template <class T>
    Vector3<T> operator-(Vector3<T> a)
    {
        return Vector3<T>(-a.x, -a.y, -a.z);
    }
    
    template <class T>
    Vector4<T> operator-(Vector4<T> a, Vector4<T> b)
    {
        return Vector4<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
    }
    
    template <class T>
    Vector4<T> operator-(Vector4<T> a)
    {
        return Vector4<T>(-a.x, -a.y, -a.z, -a.w);
    }
    
    template <class T>
    Vector2<T> operator+(Vector2<T> a, Vector2<T> b)
    {
        return Vector2<T>(a.x + b.x, a.y + b.y);
    }
    
    template <class T>
    Vector3<T> operator+(Vector3<T> a, Vector3<T> b)
    {
        return Vector3<T>(a.x + b.x, a.y + b.y, a.z + b.z);
    }
    
    template <class T>
    Vector4<T> operator+(Vector4<T> a, Vector4<T> b)
    {
        return Vector4<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
    }
    
    template <class T>
    Vector2<T> operator*(Vector2<T> a, T s)
    {
        return Vector2<T>(a.x * s, a.y * s);
    }
    
    template <class T>
    Vector2<T> operator*(T s, Vector2<T> a)
    {
        return a * s;
    }
    
    template <class T>
    Vector2<T> operator*(Vector2<T> a, Vector2<T> b)
    {
        return Vector2<T>(a.x * b.x, a.y * b.y);
    }
    
    template <class T>
    Vector2<T> operator/(Vector2<T> a, T s)
    {
        return Vector2<T>(a.x / s, a.y / s);
    }
    
    template <class T>
    Vector3<T> operator*(Vector3<T> a, T s)
    {
        return Vector3<T>(a.x * s, a.y * s, a.z * s);
    }
    
    template <class T>
    Vector3<T> operator*(T s, Vector3<T> a)
    {
        return a * s;
    }
    
    template <class T>
    Vector3<T> operator*(Vector3<T> a, Vector3<T> b)
    {
        return Vector3<T>(a.x * b.x, a.y * b.y, a.z * b.z);
    }
    
    template <class T>
    Vector3<T> operator/(Vector3<T> a, T s)
    {
        return Vector3<T>(a.x / s, a.y / s, a.z / s);
    }
    
    template <class T>
    Vector4<T> operator*(Vector4<T> a, T s)
    {
        return Vector4<T>(a.x * s, a.y * s, a.z * s, a.w * s);
    }
    
    template <class T>
    Vector4<T> operator*(T s, Vector4<T> a)
    {
        return a * s;
    }
    
    template <class T>
    Vector4<T> operator*(Vector4<T> a, Vector4<T> b)
    {
        return Vector4<T>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
    }
    
    template <class T>
    Vector4<T> operator/(Vector4<T> a, T s)
    {
        return Vector4<T>(a.x / s, a.y / s, a.z / s, a.w / s);
    }
    
    
    
    // Template Matrix Operations
    
    template <class T>
    Matrix4x4<T> transpose(Matrix4x4<T> m)
    {
        return Matrix4x4<T>(
            m._11, m._21, m._31, m._41,
            m_.12, m._22, m._32, m._42,
            m._13, m._23, m._33, m._43,
            m._14, m._24, m._34, m._44
            );
    }
    
    template <class T>
    Matrix4x4<T> mul(Matrix4x4<T> m1, Matrix4x4<T> m2)
    {
        Matrix4x4<T> mOut;
    
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                for (int k = 0; k < 4; k++)
                {
                    mOut[i][j] += m1[i][k] * m2[k][j];
                }
            }
        }
    
        return mOut;
    }
    
    // Common HLSL-compatible vector typedefs
    
    typedef unsigned int uint;
    
    typedef Vector2<float> float2;
    typedef Vector3<float> float3;
    typedef Vector4<float> float4;
    
    typedef Matrix4x4<float> float4x4;
    
    // Standard Matrix Intializers
    
    inline float4x4 identity()
    {
        float4x4 mOut;
    
        mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
        mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f;
        mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f;
        mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
    
        return mOut;
    }
    
    inline float4x4 translation(float x, float y, float z)
    {
        float4x4 mOut;
    
        mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = x;
        mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = y;
        mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = z;
        mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
    
        return mOut;
    }
    
    inline float4x4 scale(float x, float y, float z)
    {
        float4x4 mOut;
    
        mOut._11 = x;    mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
        mOut._21 = 0.0f; mOut._22 = y;    mOut._23 = 0.0f; mOut._24 = 0.0f;
        mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = z;    mOut._34 = 0.0f;
        mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
    
        return mOut;
    }
    
    inline float4x4 rotationX(float degreeX)
    {
        float angleInRadians = degreeX * (PI_F / 180.0f);
    
        float sinAngle = sinf(angleInRadians);
        float cosAngle = cosf(angleInRadians);
    
        float4x4 mOut;
    
        mOut._11 = 1.0f; mOut._12 = 0.0f;     mOut._13 = 0.0f;      mOut._14 = 0.0f;
        mOut._21 = 0.0f; mOut._22 = cosAngle; mOut._23 = -sinAngle; mOut._24 = 0.0f;
        mOut._31 = 0.0f; mOut._32 = sinAngle; mOut._33 = cosAngle;  mOut._34 = 0.0f;
        mOut._41 = 0.0f; mOut._42 = 0.0f;     mOut._43 = 0.0f;      mOut._44 = 1.0f;
    
        return mOut;
    }
    
    inline float4x4 rotationY(float degreeY)
    {
        float angleInRadians = degreeY * (PI_F / 180.0f);
    
        float sinAngle = sinf(angleInRadians);
        float cosAngle = cosf(angleInRadians);
    
        float4x4 mOut;
    
        mOut._11 = cosAngle;  mOut._12 = 0.0f; mOut._13 = sinAngle; mOut._14 = 0.0f;
        mOut._21 = 0.0f;      mOut._22 = 1.0f; mOut._23 = 0.0f;     mOut._24 = 0.0f;
        mOut._31 = -sinAngle; mOut._32 = 0.0f; mOut._33 = cosAngle; mOut._34 = 0.0f;
        mOut._41 = 0.0f;      mOut._42 = 0.0f; mOut._43 = 0.0f;     mOut._44 = 1.0f;
    
        return mOut;
    }
    
    inline float4x4 rotationZ(float degreeZ)
    {
        float angleInRadians = degreeZ * (PI_F / 180.0f);
    
        float sinAngle = sinf(angleInRadians);
        float cosAngle = cosf(angleInRadians);
    
        float4x4 mOut;
    
        mOut._11 = cosAngle; mOut._12 = -sinAngle; mOut._13 = 0.0f; mOut._14 = 0.0f;
        mOut._21 = sinAngle; mOut._22 = cosAngle;  mOut._23 = 0.0f; mOut._24 = 0.0f;
        mOut._31 = 0.0f;     mOut._32 = 0.0f;      mOut._33 = 1.0f; mOut._34 = 0.0f;
        mOut._41 = 0.0f;     mOut._42 = 0.0f;      mOut._43 = 0.0f; mOut._44 = 1.0f;
    
        return mOut;
    }
    
    // 3D Rotation matrix for an arbitrary axis specified by x, y and z
    inline float4x4 rotationArbitrary(float3 axis, float degree)
    {
        axis = normalize(axis);
    
        float angleInRadians = degree * (PI_F / 180.0f);
    
        float sinAngle = sinf(angleInRadians);
        float cosAngle = cosf(angleInRadians);
        float oneMinusCosAngle = 1 - cosAngle;
    
        float4x4 mOut;
    
        mOut._11 = 1.0f + oneMinusCosAngle * (axis.x * axis.x - 1.0f);
        mOut._12 = axis.z * sinAngle + oneMinusCosAngle * axis.x * axis.y;
        mOut._13 = -axis.y * sinAngle + oneMinusCosAngle * axis.x * axis.z;
        mOut._41 = 0.0f;
    
        mOut._21 = -axis.z * sinAngle + oneMinusCosAngle * axis.y * axis.x;
        mOut._22 = 1.0f + oneMinusCosAngle * (axis.y * axis.y - 1.0f);
        mOut._23 = axis.x * sinAngle + oneMinusCosAngle * axis.y * axis.z;
        mOut._24 = 0.0f;
    
        mOut._31 = axis.y * sinAngle + oneMinusCosAngle * axis.z * axis.x;
        mOut._32 = -axis.x * sinAngle + oneMinusCosAngle * axis.z * axis.y;
        mOut._33 = 1.0f + oneMinusCosAngle * (axis.z * axis.z - 1.0f);
        mOut._34 = 0.0f;
    
        mOut._41 = 0.0f;
        mOut._42 = 0.0f;
        mOut._43 = 0.0f;
        mOut._44 = 1.0f;
    
        return mOut;
    }
    

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