Sign in to follow this  
  • entries
    455
  • comments
    639
  • views
    422583

Resource Manager Design Part 4

Sign in to follow this  

89 views

So, after a few days thinking about the problem I decided to sit down and bang out some code, as sometimes you can scribble and think about things a little too much [wink]

As mentioned before, the system is decomposed into 4 parts;

  • The texture object to be returned
  • The image loader
  • The API uploader
  • The backend storage


Based on this I attacked the problem one class at a time.
The Imageloader for example, in this instance based off GTL, defines an imageType type so that calling code knows what it returns, and a LoadData() function todo the loading.
gtlLoader.hpp

// GTL Based loader policy class
#include
namespace TextureManagerLib
{
class GTLLoader
{
public:
typedef GameTextureLoader::ImagePtr imageType;
protected:
imageType loadData(std::string &filename)
{
return GameTextureLoader::LoadTextureSafe(filename);
}

private:
};

}




The API uploader takes the object returned by the above, using a template to adjust its self so it can call it and uploads the texture to the texture store backend and returns an API specific handle to it (the only bit about this I don't like), which is also typedef'd so the calling code knows what it returns.

OpenGLUpload.hpp

// OpenGL Image Upload Policy

#include
namespace TextureManagerLib
{
class OpenGLUploader
{
public:
typedef GLuint UploaderType;
protected:
template<class T>
UploaderType uploadImage(T img)
{
GLuint tex;
glGenTextures(1,&tex);
glBindTexture(GL_TEXTURE_2D,tex);

if(img->getColourDepth() == 32)
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,img->getWidth(),img->getHeight(),0,GL_RGBA,GL_UNSIGNED_BYTE,img->getDataPtr());
else
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB8,img->getWidth(),img->getHeight(),0,GL_BGR,GL_UNSIGNED_BYTE,img->getDataPtr());

return tex;
}

private:
};

}




The backing store is responcible for checking if we already have this object in memory, retrieving said object to allow it to be returned if so and storing a new object of that type. It can optionally handle clean up.
The class typedefs the type it stores and the type the library should return, the storetype needs to be constructable from the return type.

mapWeakStorage.hpp

// Storage policy using a vector of weak pointers

#include
#include
#include
#include

namespace TextureManagerLib
{
template<class T>
class mapWeakStorage
{
public:
typedef typename boost::shared_ptr returnType;
typedef typename boost::weak_ptr storeType;

protected:
bool checkStored(std::string &filename)
{
texturemap_t::iterator it = texturemap.find(filename);
if(it != texturemap.end())
if(returnType tmp = it->second.lock())
return true;

return false;
}

returnType retieveStored(std::string &filename)
{
texturemap_t::iterator it = texturemap.find(filename);
return it->second.lock();
}

void store(std::string &filename, returnType val)
{
texturemap.insert(std::make_pair(filename,storeType(val)));
}
public:
void clearUp()
{
for(texturemap_t::iterator it = texturemap.begin(); it != texturemap.end();)
{
if(it->second.lock())
++it;
else
texturemap.erase(it++);
}
}


private:
typedef std::map texturemap_t;
texturemap_t texturemap;
};
}




Finally, the texture manager class its self, which uses the functions provided by the classes todo its work.

textureManagerLib.hpp

#ifndef TEXTUREMANAGERLIB_HPP
#define TEXTUREMANAGERLIB_HPP
namespace TextureManagerLib
{
template<class T, class Loader = GTLLoader, class Uploader = OpenGLUploader, class Storage = mapWeakStorage >
class TextureManager : public Loader, public Uploader, public Storage
{
public:
TextureManager(){};
~TextureManager(){};
typename Storage::returnType Load(std::string &filename)
{
if(checkStored(filename))
return retieveStored(filename);

typename Loader::imageType img = loadData(filename);
typename Uploader::UploaderType handle = uploadImage(img);
typename Storage::returnType rtn(new T(handle));
store(filename,rtn);
return rtn;
}
protected:
private:
};

}
#endif




The policy classes define all their 'internal' functions as protected so that the interface to the outside world isn't cluttered with all their stuff, however for extensions, such as cleanUp(), and typedefs the defintions are left public as they are required (I'm having second thoughts about the typedefs as not all will be required to be viewable to the outside world.

So, thats how it currently stands, a few more tweaks for this generation might be worth while, such as passing objects by reference and pointers and smart pointers by value, but I'll look into that tomorrow I think.

The fact that the user supplied class needs to know how to construct its self from the type returned by the API Uploader bothers me slightly as well, I'll ponder on that some more.

Anyways, the classes in use is as follows;
textureManagerLib.cpp

// A texture management library tester

#include "gtlLoader.hpp"
#include "OpenGLUpload.hpp"
#include "mapWeakStorage.hpp"
#include "textureManagerLib.hpp"

void TestFunc(std::string &file)
{
typedef TextureManagerLib::TextureManager texturemgr;

texturemgr tex;

texturemgr::returnType handle = tex.Load(file);
}




That all compiles fine [smile]

So, tada, policeies [grin]
Questions?
Comments?
Sign in to follow this  


1 Comment


Recommended Comments

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now