Sign in to follow this  
dotproduct

Filereaders

Recommended Posts

dotproduct    180
I'm about to design and write the file input system for my engine. I want to support at least .3ds and .obj for now, and make it easy to add more file formats later. I'll probably have a base class "Filereader", and subclasses (e.g. 3dsReader, OBJReader, etc...) My question is: how can I make it possible to add new file format classes without having to add anything to existing code? Some sort of plugin system I guess (not necessarily dynamically loaded).

Share this post


Link to post
Share on other sites
MaulingMonkey    1730
The best way to deal with this depends on your class layout. Here's one way I might do it:

std::map< std::string , boost::shared_ptr< model_loader > > model_loaders;

struct model_loader
{
virtual void load( model_data & model , const std::string & file ) = 0;
};

struct 3ds_model_loader
{
virtual void load( model_data & model , const std::string & file )
{
std::ifstream ifs( file.c_str() );
ifs >> model._____;
ifs >> model._____;
ifs >> model._____;
}
};

struct obj_model_loader
{
virtual void load( model_data & model , const std::string & file )
{
std::ifstream ifs( file.c_str() );
ifs >> model._____;
ifs >> model._____;
ifs >> model._____;
}
};

void init( void )
{
model_loaders["3ds"] = new 3ds_model_loader;
model_loaders["obj"] = new obj_model_loader;
}

void load_model( model_data & model , const std::string & file )
{
model_loaders[ extension( file ) ]->load( model , file );
}

Share this post


Link to post
Share on other sites
Cygon    1219
Combine the factory pattern with the chain-of-responsibility (CHOR) pattern. All your readers need to be derived from a common base class, which should look like this:

class Reader {
public:
virtual ~Reader() {}

virtual auto_ptr<Model> read(FileStream &fs) = 0;
virtual bool canRead(FileStream &fs) const = 0;
};


Then write a class to where all available readers are registered and which queries the readers, one by one, whether they can load a given stream using their canRead() method:

class ReaderManager {
public:
void addReader(...) { ... }

auto_ptr<Model> read(FileStream &fs) {
for(
ReaderMap::const_iterator ReaderIt = m_Readers.begin();
ReaderIt != m_Readers.end(); ++ReaderIt
) {
if(ReaderIt->canRead(fs)) {
return ReaderIt->read(fs9;
}
}
}
};


This is the basic approach on how I would do it, of course this can be made more effective by providing various hints to the canRead() method like the file's extension (if available), the first 4 bytes of the file or anything else you might think that helps the reader implementation classes.

-Markus-

Share this post


Link to post
Share on other sites

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

Sign in to follow this