Device design questions

Started by
6 comments, last by nife87 15 years, 9 months ago
Hello, I would like to ask you some questions about the design of an engine and, in particular, of the device class... I know the device class should contain some pointers to the engine subsystems ( filesystem, renderer, scenemanager and so on ) to let each class access the others ... ( As it has been done in engines like irrlicht ). Ok, now I've encountered a problem in my design: if the device class should have a pointer to the Renderer class, the Renderer class has to be created by the device itself ... So i should select the correct renderer using a switch or if in the device class constructor, but i find this way too "closed" because it doesn't give me the ability to use new renderers without editing the device source code. My question is: how could i solve this problem and do we need a device ? couldn't the application class contain the pointers to the various subsystems ? ( the application class would be the device class: in this way i could create the correct renderer in my main/game classes )... How have you designed the process of initializing and selecting the correct renderer in your engine ? Thanks.. Bye :P
Advertisement
I usually take the toolbox approach to engines. I write down the dependency graph (what object needs to use what other object) and then design constructors to allow the setup of this dependency graph. Then, I perform a topological traversal of the graph to create all objects and store them where required.

For instance:

Renderer        renderer;SceneManager    scene(renderer);Filesystem      files;ResourceManager resources(files, renderer);


The responsibility of creating these is then distributed across the system, but usually crawls its way up to the entry point of the game.
Thanks for the answer ..

My problem is I don't want to do something like:

Device::Device( rendertype renderer )
{
if( renderer == RENDERDX9 ) mRenderer = new RenderDx9()
if( renderer == RENDERDX10 ) mRenderer = new RenderDx10()
}

How do you "select" the correct renderer ?
You have only two possibilities: either the code which creates the renderer determines what renderer to use, or it's told which one to use. There is no other way. If you don't want to let the device guess on its own, tell it which to create.

Note that you can pass a factory object instead of an enumeration value.
Yes, i know but...

Isn't there an elegant way to tell the engine which renderer to use ?

And should all engines have some sort of Engine/Device central class which contain all the pointers or can the pointers be contained in the Application class which the user has to derive to create the Game one ?
Quote:Original post by jwein
Yes, i know but...

Isn't there an elegant way to tell the engine which renderer to use ?


Quote:Original post by ToohrVyk
Note that you can pass a factory object instead of an enumeration value.


Quote:And should all engines have some sort of Engine/Device central class which contain all the pointers or can the pointers be contained in the Application class which the user has to derive to create the Game one ?


Mu. The pointers don't "need to be contained" anywhere. Think of the subsystems as free-standing things that you can pass around. Just because you're making "an engine" doesn't mean you need to make "an Engine" (class). Or an Application or anything else of that sort. Just make tools and let the calling code decide how to use them.
Yes, I understand but.. In this way i should link the object independently doing, for example: SceneManager *scene = new SceneManager( myRenderer ), Mesh mesh( FileSystem ) and so on..

I've seen Irrlicht has a Device class which contain pointers to the subsystems and in the constructor it initializes the various subsystems giving them access to the other ones..

Thought it could be easier to use, but i could have problems in the creation of the renderer ( i would like to avoid enum or factories to select it )..
Quote:Original post by jwein
Yes, I understand but.. In this way i should link the object independently doing, for example: SceneManager *scene = new SceneManager( myRenderer ), Mesh mesh( FileSystem ) and so on..

I've seen Irrlicht has a Device class which contain pointers to the subsystems and in the constructor it initializes the various subsystems giving them access to the other ones..

Thought it could be easier to use, but i could have problems in the creation of the renderer ( i would like to avoid enum or factories to select it )..


If you have a renderer factory/helper class that can enumerate/list/iterate the available renderers by their names and also create a specific one (again, located by its name or some sort of identifier), then you can give the user an option for choosing a renderer before or even at runtime. You should just be careful designing your dependencies in the latter case, though, as choosing a renderer runtime could provide numerous headaches if you do not design it for such replacement because of the chain of dependencies. Who (which systems) must be informed about the renderer switch, which data needs to reloaded (only textures?), and also how to avoid reloading too much unrelated data like sounds, geometry, and the like. For example, if your need to create a new resource manager (thinking of a all-data manager here) for a renderer switch, then all resources (renderer related or not) must be reloaded and is therefore quite obviously not the best solution.

My solution is to have a globally available list of available RenderSystem factories and their names from which to display and select before (via config files) or at runtime. Plugins just need to register themselves on this list when they are loaded (therefore it needs to be globally available in some way) by the use of simple LoadPlugin and UnloadPlugin functions located within the plugins. Hereafter the user is provided with an in-game option for selecting one of the available RenderSystems. Of course, it requires some careful planning when dealing with the chain of dependencies, as already stated, but it surely can be done.
IMHO I find this solution, which also resembles the way Ogre3D is doing it (perhaps you should take a look at its code), to be quite flexible and easy to implement.

[Edited by - nife87 on July 7, 2008 3:25:17 AM]

This topic is closed to new replies.

Advertisement