現状のライブラリ構成 その2

現状のライブラリ構成 - (void*)Pないと

の続きです。

テクスチャ描画周りの部分をライブラリにまとめました。

// -- dxclass.h --
#pragma once

#include <d3d9.h>
#include <d3dx9.h>

#define FVF_CUSTOM ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 ) 

// 頂点バッファ
struct CUSTOMVERTEX {  
    float x, y, z;    // 頂点座標 
    float rhw;        // 除算数 
    DWORD dwColor;    // 頂点の色 
    float u, v;        // テクスチャ座標 
};

//前方宣言
class DXClass;
class DXTexture;

// DX3Dの初期化等
class DXClass {
private:
    D3DPRESENT_PARAMETERS m_d3dpp;
    IDirect3D9* m_pd3d;
    IDirect3DDevice9* m_pd3dDevice;
    IDirect3DVertexBuffer9* m_pVertex;
    DWORD m_time;
public:
    DXClass ();
    ~DXClass ();
    bool Init(HWND hWnd);
    HRESULT DrawStart();
    void DrawEnd();
    void DrawTexture (DXTexture* pTex,RECT& rc,DWORD color,int alpha);
    DXTexture* LoadTexture(TCHAR* filename,UINT tex_widht,UINT tex_height);
    D3DPRESENT_PARAMETERS d3dpp() const;
    IDirect3D9* pd3d() const;
    IDirect3DDevice9* pd3dDevice() const;
    IDirect3DVertexBuffer9* pVertex() const;
};

// テクスチャ管理クラス
class DXTexture {
private:
    IDirect3DTexture9* m_pTex;
    UINT m_widht;
    UINT m_height;
    RECT m_uv;
    bool m_allUV;
public:
    DXTexture (IDirect3DTexture9* pTex,UINT widht,UINT height);
    ~DXTexture ();
    void SetUV(int left, int top, int right, int bottom);
    void SetUV(RECT& rc);
    RECT GetUV() const;
    void ClearUV();
    void WriteUV(CUSTOMVERTEX* v) const;
    IDirect3DTexture9* pTex() const;
};

ヘッダはこんな感じです。テクスチャを管理するクラスを作り、基本的にはこれを引き回して扱います。

テクスチャの読み込みとテクスチャの描画処理は以下のような感じになっています。

// -- dxclass.cpp --

(中略)

// テクスチャの読み込み
DXTexture* DXClass::LoadTexture (TCHAR* filename,UINT tex_widht,UINT tex_height) {
    IDirect3DTexture9* pTex;

    if( FAILED(D3DXCreateTextureFromFileEx(m_pd3dDevice, filename, tex_widht, tex_height, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_FILTER_POINT, D3DX_DEFAULT, 0, NULL, NULL, &pTex)) ){
        return NULL;
    }

    return new DXTexture(pTex,tex_widht,tex_height);
}

(中略)

// テクスチャの描画
void DXClass::DrawTexture (DXTexture* pTex,RECT& rc,DWORD color,int alpha) {
    static CUSTOMVERTEX v[4] = {
        {0.0f, 0.0f, 0.0f, 1.0f, 0xffffffff, 1.0f, 0.0f}, 
        {0.0f, 0.0f, 0.0f, 1.0f, 0xffffffff, 1.0f, 1.0f}, 
        {0.0f, 0.0f, 0.0f, 1.0f, 0xffffffff, 0.0f, 0.0f}, 
        {0.0f, 0.0f, 0.0f, 1.0f, 0xffffffff, 0.0f, 1.0f}
    };
    static HRESULT hr;
    static void *pData;

    // 表示座標の設定
    v[0].x = static_cast<float>(rc.left + rc.right);
    v[0].y = static_cast<float>(rc.top);
    v[1].x = static_cast<float>(rc.left + rc.right);
    v[1].y = static_cast<float>(rc.top + rc.bottom);
    v[2].x = static_cast<float>(rc.left);
    v[2].y = static_cast<float>(rc.top);
    v[3].x = static_cast<float>(rc.left);
    v[3].y = static_cast<float>(rc.top + rc.bottom);

    // ポリゴンのカラーと半透明の設定
    v[0].dwColor = v[1].dwColor = v[2].dwColor = v[3].dwColor = ((alpha<<24) | (color & 0xffffff));

    // テクスチャ座標の設定
    pTex->WriteUV(v);

    // テクスチャの設定
    m_pd3dDevice->SetTexture(0, pTex->pTex());

    hr = m_pVertex->Lock(0, sizeof(CUSTOMVERTEX)*4, (void**)&pData, 0);
    if(hr == D3D_OK){
        memcpy(pData, v, sizeof(CUSTOMVERTEX)*4);
        m_pVertex->Unlock();
    }
    m_pd3dDevice->SetStreamSource(0, m_pVertex, 0, sizeof(CUSTOMVERTEX));
    m_pd3dDevice->SetFVF(FVF_CUSTOM);
    m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}

DrawTextureの引数をどうするか悩みました。

本来DirectX的に、カラーとアルファブレンドがRGBAで変数一つで管理されてるので、DrawTextureの引数としてもそうしようかと思ったのですが、別々で渡せないと不便だったので分けました。

なので

((alpha<<24) | (color & 0xffffff));

こんな感じでちょっとややこしいことになってます。

colorを0xffffffで&してるのはcolorの範囲内のクセにアルファブレンドの値まで設定されてたらおかしくなるのでRGBの部分だけで切り捨てるようにしてる感じです。

まぁ事前にassertしておけばよいだけの話かもしれませんが。

// カラーはこの範囲内であるはず
assert( 0x0 <= color && color <= 0xffffff );

alphaの場合はどっちにしろ24ビットずらすので0xff以上の値がいれられてもまぁ問題はないという感じです。


さて、ちょっと復習も兼ねてるとはいえライブラリ作成にかなり時間が割かれてしまったのでそろそろ次のことをやっていかないといけないですね。

一応次回は文字列関係の勉強を予定しています。