Skip to main content
gamedev.net
🔒 Locked

C++ Object oriented question

Started by dracan 8 replies 1.7k views
Original Post
dracan
dracan
My background is in C, but I have just started coding a 3dengine at home in C++ as a learning project. I understand C++ quite well, but just haven't had that much OO programming experience yet. Basically I want my 3d engine to be able to work with many different APIs - for example, DirectX, OGL, XBox360, etc. If we take for example, my generic texture class (CTexture). I want this to just contain generic code, and be linked to my api specific classes (CDirectXTexture, COGLTexture, etc). I sort of want all my api specific classes to inherit from the generic CTexture class, and then use polymorphism to call the platform specific functions. The problem is that would involve me greating my textures like this ... CTexture *texture = new CDirectXTexture; However, as I'll be creating textures in various places in the code, and I don't want this to explicitly refer to an api specific class - then I actually want to do this ... CTexture *texture = new CTexture; Where texture actually gets created as a CDirectXTexture. Is this possible? Maybe via overriding the new operator or something like that? Or is there a better way of setting out my classes? Which platform I'm compiling for will either be passed into the compiler as a #define, or will be a flag somewhere in code. Cheers, - Dan
torakka
torakka
class device3d
{
public:
virtual texture* createTexture(...) = 0;
};

Then depending on what kind of device you have you can create a mathing texture, internally the code might look something like this:

texture* deviced3d::createTexture(...)
{
textured3d* tex = new textured3d(...);
// ...
return tex;
}

There are other possibilities but that fits my framework so I advice on that method as the first choise. ;-)
swordfish
swordfish
Yes, it is possible.

I can't tell you exactly how off-hand, but take a look at the WildMagic engine (source viewable online) and see how it handles OpenGL-DirectX, Windows-Linux-Mac, float-double, etc.

For a specific example, look at the Renderer classes. Basically there is a base 'Renderer' class, which has Wm3Dx9Renderer and Wm3OpenGLRenderer subclassed from it, each class handling API specific functionality. Then the class Wm3Application, with subclasses Wm3AglApplication and Wm3Dx9Application implement the API specific Renderer class - and on the front-end, the developer does not have to worry about API specific tasks. Beautifully done I must say.

There are probably less complex examples out there.
http://blog.protonovus.com/
dracan
dracan
Quote:
Original post by torakka
class device3d
{
public:
virtual texture* createTexture(...) = 0;
};

Then depending on what kind of device you have you can create a mathing texture, internally the code might look something like this:

texture* deviced3d::createTexture(...)
{
textured3d* tex = new textured3d(...);
// ...
return tex;
}

There are other possibilities but that fits my framework so I advice on that method as the first choise. ;-)


Thanks for your reply. That might actually fit my engine quite well. I've already got a CGraphicSystem class, which is the base class of CDirectXSystem, COGLSystem, etc. This is actually created by the app-side using ...

CGraphicSystem *graphic_system = new CDirectXSystem;

As this only gets created once, I don't mind this being api specific. Infact, I'll probably have this as the appside's way of choosing what API to use.

So like you say - if I then did ...

graphic_system.create_texture ();

then that would automatically call CDirectXSystem::create_texture () due to polymorphism.

Although, one problem is that currently the engine-side doesn't have access to this graphic_system variable. I'm sure I can rearrange some stuff so that it does though.

- Dan
dracan
dracan
Quote:
Original post by swordfish
Yes, it is possible.

I can't tell you exactly how off-hand, but take a look at the WildMagic engine (source viewable online) and see how it handles OpenGL-DirectX, Windows-Linux-Mac, float-double, etc.

For a specific example, look at the Renderer classes. Basically there is a base 'Renderer' class, which has Wm3Dx9Renderer and Wm3OpenGLRenderer subclassed from it, each class handling API specific functionality. Then the class Wm3Application, with subclasses Wm3AglApplication and Wm3Dx9Application implement the API specific Renderer class - and on the front-end, the developer does not have to worry about API specific tasks. Beautifully done I must say.

There are probably less complex examples out there.


That sound interesting. I've not got time to look at it now - but I'll download it tomorrow and check it out!

Thanks for the link!
- Dan
DadleFish
DadleFish
You may want to look into a design pattern called "Abstract Factory". Generally speaking, a factory is a design pattern for creating objects just the way you want it, using a base class and derived classes. You can also use templates here. Consider the following example:

class BaseClass{public:     virtual int SomeFunction() = 0;};class DerivedClassA : public BaseClass{public:     virtual int SomeFunction() { cout << "A" << endl; }};class DerivedClassB : public BaseClass{public:     virtual int SomeFunction() { cout << "B" << endl; }};template <class T>class Factory{public:     BaseClass *CreateClass() { return new T(); }};typedef Factory<DerivedClassA> FactoryForClassA;typedef Factory<DerivedClassB> FactoryForClassB;int main(){    FactoryForClassA aFactory;    FactoryForClassB bFactory;    BaseClass *obj = aFactory.CreateClass();    .....    return 0;}


Now some remarks. First, this example should be enhanced by "ReleaseClass" as well, because the user doesn't necessarily knows how the instance was created. This also means that you actually have control over the management of the instances; For example, you could opt to pre-allocate a pool of textures rather than using the rather slow OS new and delete operators.

The factory template class itself could inherit from a base class that will obscure even further the whole process. In my engine, for example, my "factory" is a Renderer base class, which in turn is inherited by OpenGLRenderer and DirectX9Renderer. The application creates an instance of Renderer* in the beginning, and it is used afterwards as needed.

Good luck!
Dubito, Cogito ergo sum.
swordfish
swordfish
I believe the patterns described above are those that the WildMagic engine uses. And by the way, the source for the engine is viewable online for quick reference.
http://blog.protonovus.com/
Ex777
Ex777
The factory meathod is perfect for what your trying to do, I'd advise using it aswell.
joanusdmentia
joanusdmentia
And here's a page full of useful design patterns.
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The nly verdict is vengeance; a vendett o

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.