I have some quite complex, virtual objects hierarchy that represents all the elements in 3D Engine as abstract classes (interfaces).
For example, I have Renderable
which parent is Sizeable
(with getSize()
method). Sizeable
inherits from Positionable
(with getPosition()
) etc.
That structure is fine and logic (e.g. 3D Model is Renderable
, bone of skeleton for skinning is Sizeable
, and the Camera is only Positionable
).
There is also one "uber-class", Engine3D
.
My aim is:
I have to write the "implementation" for that "graphic things" (module). It will be DirectX "implementation". The aim: the programmer that uses my "implementation" can switch to other fast and simple (which implementation he uses is almost transparent to him).
I would like to keep it that way:
//choosing module "implementation" ("implementation" mentioned here only)
Engine3D * engine = new MyEngine3D();
Renderable * model = engine->createModel(...);
//line above will return MyRenderable class in fact,
//but user (programmer) will treat it as Renderable
Why I want to create "own" versions of Renderable
and all others? Because they will share some "implementation"-specific data (pointers for DirectX structures etc.).
My problem is:
But that way, I would create a "mirror" - a copy of the original module's objects hierarchy with My
in front of each class name. Moreover, MyRenderable
would have to inherit both from Renderable
(to overwide render()
) and MySizeable
(to get the DirectX matrices etc.).
And that involves the virtual inheritance and really complicates the structure.
I'm speaking mainly about avoiding virtual multi-inheritance (just multi-inheritance is fine, I guess).
You should definitely avoid a strong coupling of object hierarchy and rendering implementation. My suggestion would be to move all the DirectX specific code to a class outside of your object hierarchy, for example an IRenderer
interface together with a DirectXRenderer
implementation. Add a reference or pointer to IRenderer
to all the classes which have to draw something (Renderable
, etc). All object classes must use your own implementations of matrices etc. to keep them independent from the data structures of the actual rendering backend.