ページ 11

C++ DirectX リソース二重ロード防止

Posted: 2016年12月14日(水) 00:53
by roxas710
今DirextXでゲームを作っているのですが、困ったことがあります。
メッシュをロードする際に、同じリソースを多重ロード防止する方法を
教えて頂だきたいです。

Aメッシュ Bメッシュ 2つともCというテクスチャをロードする際に
同じテクスチャをロードしないようにしたいのですが、
最適な方法はないでしょうか?

Re: C++ DirectX リソース二重ロード防止

Posted: 2016年12月14日(水) 08:32
by C6b14
例えば下記の様な事でしょうか。
01.あらかじめ用意されたテクスチャのみを指定できるようにする
02.使用するすべてのテクスチャを別にリストアップしておき、その中からメッシュに使うテクスチャを選び出す
03.すべてのテクスチャを納めた1枚の大きなテクスチャの必要な部分だけを切り出してくる
04.テクスチャを一括して管理するクラスにロードを任せる。このクラスは同じテクスチャを重複してロードするように指示されても、既に読み込まれているテクスチャを返す。
[04の件として]
(テクスチャデータへのポインタの型を仮に LPTEXTURE とします。なので、そのままでは動きません。適当に書き換えてください。テクスチャ以外のデータに使う場合もちょっと変えるだけです)[コード例は古いですよ]

コード:

#include <windows.h>
#include <stdlib.h> //_fullpath()
#include <limits.h> //CHAR_BIT,UCHAR_MAX
#include <map>
#include 他にも必要なヘッダファイル

class CTextureManager{
protected:
    //ファイルパスの32bitCRCをキーにテクスチャを管理する
    std::map<unsigned int,LPTEXTURE> TextureManagerMap;
public:
    CTextureManager();
    virtual ~CTextureManager();
    virtual void Clear();    //管理しているすべてのテクスチャを放棄
    virtual bool Load(LPTEXTURE&,const char*); //テクスチャのロード
};

//*******************
//*    CRC計算部    *
//*******************

#define CRCPOLY 0x04C11DB7UL
    /* x^{32}+x^{26}+x^{23}+x^{22}+x^{16}+x^{12}+x^{11]+
       x^{10}+x^8+x^7+x^5+x^4+x^2+x^1+1 */

//CRCテーブル
static unsigned long crctable[UCHAR_MAX + 1];

//CRCテーブルの初期化;一度だけ呼べばよい
void MakeCRCTable()
{
    unsigned int i, j;
    unsigned long r;

    for(i = 0; i <= UCHAR_MAX; i++) {
        r = (unsigned long)i << (32 - CHAR_BIT);
        for(j = 0; j < CHAR_BIT; j++)
            if(r & 0x80000000UL) r = (r << 1) ^ CRCPOLY;
            else r <<= 1;
        crctable[i] = r & 0xFFFFFFFFUL;
    }
}

unsigned long CalcCRC32(int n, const BYTE c[])
{
    unsigned long r;

    r = 0xFFFFFFFFUL;
    while (--n >= 0)
        r = (r << CHAR_BIT) ^ crctable[(byte)(r >> (32 - CHAR_BIT)) ^ *c++];
    return ~r & 0xFFFFFFFFUL;
}



CTextureManager::CTextureManager()
{
    MakeCRCTable();
}


CTextureManager::~CTextureManager()
{
    Clear();
}


//テクスチャをロードする。
//テクスチャの読み込みに失敗した場合のみfalseを返す
//trueが返れば必ず有効なテクスチャが与えられると考えて良い
bool CTextureManager::Load(LPTEXTURE &Texture,const char *filename){
    //*********************
    //*   絶対パス取得    *
    //*********************
    //ファイル名が指定されていなければロードは失敗
    if(NULL==filename[0]){
        return false;
    }

    char Full[_MAX_PATH];    //絶対パス取得用バッファ
    if(NULL==_fullpath( Full, filename, _MAX_PATH)){
        //絶対パス取得失敗
        return false;
    }

    //*********************
    //*   重複チェック    *
    //*********************
    unsigned int key_crc=CalcCRC32(strlen(Full)*sizeof(char),(BYTE*)Full);

    std::pair<std::map<unsigned int,LPTEXTURE>::iterator,bool> p;

    p=TextureManagerMap.insert(std::pair<unsigned int,LPTEXTURE>(key_crc,NULL));

    //mapに挿入してみる。
    //失敗すれば、既に同じキーが登録されているということ。
    if(!p.second){
        //既に登録されているテクスチャのポインタを引数に設定して終了
        Texture=(*p.first).second;
        return true;
    }

    //挿入に成功すれば、新しくデータを読み込む必要がある
    //ここではLoadTextureが第一引数にファイル名、
    //第二引数にLPTEXTUREへのポインタをとり、ロードに失敗すればfalseを返す関数であるとする
    if(!LoadTexture(Full,&(*p.first).second)){
        //ファイルロードに失敗
        return false;
    }
    Texture=(*p.first).second;
    return true;
}

void CTextureManager::Clear()
{
    //アンロード
    std::map<unsigned int,LPTEXTURE>::iterator ite=TextureManagerMap.begin();
    std::map<unsigned int,LPTEXTURE>::iterator end=TextureManagerMap.end();

    for(;ite!=end;ite++){
        //ここではUnloadTextureは引数にLPTEXTUREをとり、
        //テクスチャをメモリからアンロードする関数であるとする
        UnloadTexture((*ite).second);
    }

    //クリア
    TextureManagerMap.clear();
}

Re: C++ DirectX リソース二重ロード防止

Posted: 2016年12月15日(木) 11:55
by roxas710
回答ありがとうございます!
試してみます。