I am working on game engine prototype and have the following question:
Right now my engine implementation is DirectX-bound and everything works fine.
I've got a core::Renderer class which has methods to render geometry, set shaders, lightning, etc...
Some of them are templated, some not.
class Renderer {
// ...
template <typename Geometry> RenderGeometry(shared_ptr<Geometry> geometry);
};
Let's say I want to extend the flexibility of my engine and I wan't it to work using DirectX and OpenGL. As I understand it right now, the idea is to take everything interface-specific to the base core::Renderer class, make all those calls virtual and then provide their DirectX-specific and OpenGL-specific implementation.
If my geometrical object wasn't a template, everything would look better:
class Renderer {
virtual void RenderGeometry(shared_ptr<core::Non_template_Geometry> geometry);
};
class DXRenderer {
// Here goes our custom implementation
// for DirectX-based geometry rendering
virtual void RenderGeometry(...)
};
// The same for OpenGL
The problem with the first (initial variant) is that virtual functions are not allowed to be templated.
So here comes the question - how should I solve it?
Any hacks / tricks / patterns for this situation or for template virtual functions emulation?
Use a base Geometry class:
class Geometry {
public:
virtual ~Geometry() { }
virtual void Render() = 0;
};
and have each of your Geometry-type classes derive from this base class and implement their specific rendering functionality by overriding Render.
Then, Renderer::RenderGeometry does not need to be a function template; it can simply take a pointer to the base Geometry class and call the virtual function Render.
Template is not neccessity. If you think hard about it, most of the time templates only do text-replacing and is a safer macros.
OOP was not design to rely heavily on templates, but composition and inheritance (like what James suggested)
Related
I am designing some classes for my project in C++ at the moment but I got a problem.
I want to create a camera class which holds all the needed values (e.g. transformation matrices) but the function which renders the camera should be exchangeable. This sounds like a usual case for the strategy pattern. Thus I created an interface which defines the render-function and gave the the camera class a pointer to this interface.
The problem is that the render function needs access to all the data in the camera class and therefore I gave this function a pointer to the camera class as a parameter. It looks like this:
#include "ICameraRender.h"
class Camera{
private:
ICameraRender* _cameraRender;
public:
Camera();
Camera(ICameraRender& cameraRender);
~Camera();
void renderCamera(){ _cameraRender->render(this); }
void setCameraRender(ICameraRender& cameraRender);
/..../
};
class ICameraRender{
public:
virtual ~ICameraRender(){
}
//Override me
virtual void render(Camera* camera) = 0;
};
This doesn't seem to be an elegant solution due to the liability to an infity loop (calling camera->renderCamera() in the render-function in ICameraRender). Is there a better solution to this problem?
Regards
EDIT:
I came up with another solution. Since the function which operates on the camera's data, only needs access to the data I thought I could split up the camera class itself. A class called Camera and CameraModel. The last one holds all the needed data and the first one does operations on it.
Therefore I just have to pass a pointer to CameraModel to my function:
class CameraModel{
private:
/...data.../
public:
/...setter and getter.../
};
class Camera{
private:
CameraModel* _cameraModel;
ICameraRender* _cameraRender;
public:
Camera();
Camera(ICameraRender& cameraRender);
~Camera();
void renderCamera(){ _cameraRender->render(_cameraModel); }
void setCameraRender(ICameraRender& cameraRender);
/..../
};
class ICameraRender{
public:
virtual ~ICameraRender(){
}
//Override me
virtual void render(CameraModel* cameraModel) = 0;
};
Now the render-function (which only calculates new values for the camera according to user input) does no longer have access to the renderCamera-function.
What do you think about this solution?
Regards Stan
You're right, it does seem like a bad design. :)
I don't see why a camera render needs access to a camera. I'm sure you can pass something else as parameter. The render doesn't need access to all the camera members, so you can just pass the ones it needs (and, if there's a lot of them, wrap them in a structure CameraConfig or something like that).
If the different renders need different parameters, you can make a separate hierarchy with ICameraConfig.
This is probably a great time to use Policy-based design to implement the strategy pattern, especially since you're using C++ and you're probably targeting a compiler older than 2002. (Since C++'s templating mechanism is so awesome, we can get the strategy pattern for free this way!)
First: Make your class accept the strategy/policy class (in this case, your ICameraRenderer) at a template parameter. Then, specify that you are using a certain method from that template parameter. Make calls to that method in the camera class...
Then implement your strategies as a plain old class with a render() method!
This will look something like this:
class Camera<RenderStrategy>{
using RenderStrategy::render;
/// bla bla bla
public:
void renderCamera(){ render(cameraModel); }
};
class SpiffyRender{
public:
void render(CameraModel orWhateverTheParameterIs){ // some implementation goes somewhere }
};
Whenever you want to make a camera that uses one of those policy/strategies:
// the syntax will be a bit different, my C++ chops are rusty;
// in general: you'll construct a camera object, passing in the strategy to the template parameter
auto SpiffyCamera = new Camera<SpiffyRender>();
(Since your renderer strategy doesn't have any state, that makes this approach even more favorable)
If you are changing your renderer all the time, then this pattern / approach becomes less favorable... but if you have a camera that always renders the same way, this is a slightly nicer approach. If your renderer has state, you can still use this method; but you'll want a reference to the instance inside the class, and you won't use the Using:: statement. (In general, with this, you write less boilerplate, don't need to make any assignments or allocations at runtime, and the compiler works for you)
For more about this,see: http://en.wikipedia.org/wiki/Policy-based_design
Or read Modern C++ Design... it's a great read, anyways! http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315
As an unrelated aside: You may want to look into some of the goodness that C++x11 gives you. It'll really clean up your code and make it safer. (Especially the shared/unique/etc ptr classes.)
Okay, the title is a mouthful and I think that's probably why it has been tough to find an answer through google or this site. It might just be that I don't know how to express the problem correctly but here goes:
I have a series of methods in a SimpleOpenGLRenderer class that all take a single argument that extends the Model class. So the idea is that depending on the type of model, the renderer will invoke the correct method that knows how to render it. Here is a simplified executable example based on the problem:
#include <stdio.h>
class Model {};
class Cube : public Model {};
class Sphere : public Model {};
class Renderer
{
public:
virtual void renderModel(const Model& model) = 0;
};
class SimpleOpenGLRenderer
{
public:
void renderModel(const Cube& model)
{
printf("Render the cube.\n");
}
void renderModel(const Model& model)
{
printf("Throw an exception, my renderer does not support the model type you have provided.\n");
}
void renderModel(const Sphere& model)
{
printf("Render the sphere.\n");
}
};
int
main(int argc, char** argv)
{
Cube cube;
Model& model = cube;
SimpleOpenGLRenderer renderer;
renderer.renderModel(cube);
renderer.renderModel(model);
}
The output from the example is:
Render the cube.
Throw an exception, my renderer does not support the model type you have provided.
It may seem obvious to a more seasoned C++ developer that this does not work as planned but it just doesn't make sense to me. At runtime I will not know the exact type of the Model passed to the renderer (hence the attempted overloading to resolve it). Coming from a Java background, I have used this technique before and in Java the method called will be that which best matches the runtime type of the argument. In C++ it seems to match to the compile-time type of the reference, even if that reference may end up being to a subclass that - to my mind - better matches another function.
Up until now I had taken this runtime type matching for granted. Does it simply not exist in C++ or am I going about this the wrong way? Should I be doing something differently in C++ to achieve it?
Thanks,
Gary.
Overloads in C++ are resolved at compile time, based on the static type of the argument.
There's a technique known as "double-dispatch" that might be of use:
class Model {
virtual void dispatchRender(Renderer &r) const = 0;
};
class Cube : public Model {
virtual void dispatchRender(Renderer &r) const {
r.renderModel(*this); // type of "this" is const Cube*
};
int main() {
Cube cube;
Model &model = cube;
SimpleOpenGLRenderer renderer;
cube.dispatchRender(renderer);
}
Note that the Renderer base class needs to contain all the overloads that SimpleOpenGLRenderer currently does. If you want it to be specific to SimpleOpenGLRenderer what overloads exist then you could put a Simple-specific dispatch function in Model, or you could ignore this technique and instead use dynamic_cast repeatedly in SimpleOpenGLRenderer::renderModel to test the type.
In your code, the function overloads are resolved based on the static type of the argument.
What you need probably is double-dispatch mechanism which is very close to Visitor pattern. Read these:
Double Dispatch
Visitor Pattern
For "runtime overloading" based on the dynamic type it is possible to use visitor pattern.
Your code is a good candidate of runtime type matching, if you use it. Here you are receiving Cube into Model& and passing the same simply to the renderModel(). Till now you haven't given chance to the compiler to use the runtime type. But rather relying on the static type of the object.
In 2 ways you could have used the runtime type checking. One is using dynamic_cast<> and other one is providing the interface method in Model. i.e.
class Model {
virtual void print () { printf("throw..."); } // provide an interface method
};
class Cube : public Model {
virtual void print () { print("Render cube\n"; } // implement it
};
class Sphere : public Model {
virtual void print () { print("Render sphere\n"; } // implement it
};
class SimpleOpenGLRenderer
{
public:
void renderModel(const Model& model)
{
model.print();
}
};
In C++ the resolution of which overload to call, is done at compile time.
To make the effective implementation depend on the polymorphic argument type, you need to consult that argument, i.e., call a virtual method on the argument.
I think the cleanest way to do that here is what's called the visitor pattern. Your SimpleOpenGLRenderer can call a method model.renderOn( *this ). Then Model::renderOn is either a set of overloads, one for each possible type of renderer, or it is a single virtual method that uses dynamic_cast to discover the type of renderer. In any way, it then calls back on the renderer, but now that call knows what type of renderer it is and what type itself is, and can also call a very specific rendering method, like, SimpleOpenGLRenderer::renderCube.
Cheers,
The other solutions here will do exactly what you want. But in my opinion at the cost of complexity. If your problem is exactly as described, I would suggest to change the architecture of your solution instead. Aren't the renderer trying to do the job of the model? What I see is a kind a overload generated switch sentence.
How about making the models rendering themself, perhaps by using some class offering more primitive drawing methods:
class Cube : public Model {
render(RenderTool& tool) {
tool.renderCube(); //or even more low level
}
};
class SimpleOpenGLRenderer {
public:
RenderModel(Model& model) {
model.render(renderTool);
}
private:
SomeOpenGLRenderingTool renderTool;
};
I'm making a game gui api. It will work with both Allegro and SDL. I use polymorphism for input and bitmap drawing. The issue comes with these 3 types: Bitmap, Font, and Color. SDL and Allegro are different on these. The problem is I cannot really use polymorphism here due to different return types. I wouldn't feel right to have a void* as the return type. What could I do instead so that the user could just do:
AGBitmap bmp = AGBitmap("someimage.png");
graphics->draw(bmp);
Right now my AGBitmap works with only Allegro and has an overloaded = operator and manages its memory so the user does not have to.
What could I do?
Thanks
Since there are different types, you should use template specialization.
template < typename WinManagerType >
class AGBitmap;
template<>
class AGBitmap< AlegroWinType >
{
public :
//...
AlegroBitmapType GetBitmap();
};
template<>
class AGBitmap< SdlWinType >
{
public :
//...
SdlBitmapType GetBitmap();
};
But since your question is so vague, there might be a better solution.
Sounds like an application for a Adapter Pattern.
CRTP might be useful in this scenario, provided you can abstract a common interface for the relevant concrete classes into your base class template(s).
template <class BITMAP> class MyBitmap
{
// generic bitmap interface
};
class MyAGBitmap : MyBitmap<AGBitmap>
{
};
I have the following problem in application architecture and am willing to solve it (sorry for a lot of text).
I am building a game engine prototype and I have base abstract class AbstractRenderer (I will use C++ syntax, but still the problem is general).
Assume there are some derived implementations of this renderer, let's say DirectxRenderer and OpenglRenderer.
Now, let's say that only one of these renderers (let's stick to DirectX-based) has a member called IDirect3D9Device* m_device; Obviously at this point everything is fine - m_device is used internally in DirectxRenderer and shouldn't be exposed in the abstract AbstractRenderer superclass.
I also add some abstract rendering interface, for instance IRenderable. It means simply one pure virtual method virtual void Render(AbstractRenderer* renderer) const = 0;
And this is the place where some problems start. Assume I am modelling some scene, so, this scene will probably have some geometrical objects in it.
I create abstract superclass AbstractGeometricalObject and derived DirectX-based implementation DirectxGeometricalObject. The second one would be responsible for storing pointers to DirectX-specific vertex & index buffers.
Now - the problem.
AbstractGeometricalObject should obviously derive the IRenderable interface, because it's renderable in logical terms.
If I derive my DirectxGeometricalObject from AbstractGeometricalObject, the first one should have virtual void Render(AbstractRenderer* renderer) const { ... } method in it, and that Abstract... stuff brings some troubles.
See the code for better explanation:
And for now my classes look the following way:
class AbstractGeometricalObject : public IRenderable {
virtual void Render(AbstractRenderer* renderer) const { ... }
};
class DirectxGeometricalObject : public AbstractGeometricalObject {
virtual void Render(AbstractRenderer* renderer) const {
// I think it's ok to assume that in 99 / 100 cases the renderer
// would be a valid DirectxRenderer object
// Assume that rendering a DirectxGeometricalObject requires
// the renderer to be a DirectxRenderer, but not an AbstractRenderer
// (it could utilize some DX-specific settings, class members, etc
// This means that I would have to ***downcast*** here and this seems really
// bad to me, because it means that this architecture sucks
renderer = dynamic_cast<DirectxRenderer*>(renderer);
// Use the DirectX capabilities, that's can't be taken out
// to the AbstractRenderer superclass
renderer.DirectxSpecificFoo(...);
}
I know I'm probably worrying too much, but this downcast in such a simple case means that I could be forced to make lots of downcasts if my application grows.
Definitely, I would like to avoid this, so please, could you advice me something better in design terms / point out my errors.
Thank you
This might be a situation where the template pattern (not to be confused with C++ templates) comes in handy. The public Render in the abstract class should be non-virtual, but have it call a private virtual function (e.g. DoRender). Then in the derived classes, you override DoRender instead.
Here's an article that goes into great depth describing the use of template pattern with private virtual functions.
Edit:
I started to put together an example of what I meant, and it seems like there's actually a broader flaw in the architecture. Your use of AbstractRenderer is somewhat frivolous since you're forcing each geometricalobject to be intimately aware of a particular renderer type.
Either the renderer should be able to work off the public methods of Renderables, or Renderables should be able to work off the public methods of the Renderer. Or perhaps you can give the concrete renderers a Renderable factory if there really needs to be such an intimate connection. I'm sure there are some other patterns that would fit well, too.
I don't see what your code wants to achieve. You derive Renderable objects to DirectXRenderables and OpenGLRenderables and then provide OpenGL or DirectX functionality in something derived from Renderer. A specific thing uses another specific thing so to speak.
It would seem much more reasonable to identify general rendering functions, make them pure virtual members of your abstract renderer and implement them in DirectXRenderer and OpenGLRenderer. Then a IRenderable would have a member function draw roughly like this:
void draw(const AbstractRenderer& r) {
//general stuff
r.drawLine(...);
//only possible on directX
if(DirectxRenderer rx = dynamic_cast<DirectxRenderer*>(r)) {
//...
} else {
//throw exception or do fallback rendering in case we use something else
}
}
Using templates, you could split the IRendable into two classes, one for each of the two renderer types. This is probably not the best answer, but it does avoid the need for the dynamic cast:
template <typename RendererType>
struct IRenderable {
virtual void Render(RendererType* renderer) const = 0;
}
template <typename RendererType>
class AbstractGeometricalObject : public IRenderable<RendererType> {
virtual void Render(RendererType* renderer) const { ... }
};
class DirectxGeometricalObject : public AbstractGeometricalObject<DirectxRenderer> {
// this class will now require a void Render(DirectxRenderer* renderer)
}
Use a setter to set the renderer var and cast it to the proper type in that one place.
See if the Bridge design pattern helps you: "Decouple an abstraction from its implementation so that the two can vary independently." In your example, AbstractGeometricalObject would point to an implementation, a pure virtual interface with platform-specific subclasses. The tricky part is taking the time to discover that interface.
Let's distance from compilers and consider theory. If DirectxGeometricalObject::Render expects DirectxRenderer as parameter and not any AbstractRenderer, then some other OtherGeometricalObject::Render will probably expect OtherRenderer object as parameter.
So, different implementations of AbstractGeometricalObject have different signatures of their Render methods. If they are different, then there is no purpose in defining the virtual AbstractGeometricalObject::Render.
If you declare AbstractGeometricalObject::Render(AbstractRenderer*), then you should be able to pass any renderer to any geometrical object. In your case, you can't because dynamic_cast would fail.
I want to implement a Mesh class for a CG project, but have run into some problems.
What I want to do is a Mesh class that hides implementation details (like loading to a specific API: OpenGL, DirectX, CUDA, ...) from the user. Additionally, since the Mesh class will be used in research projects, this Mesh class has to be very flexible.
class Channel {
virtual loadToAPI() = 0;
}
template <class T>
class TypedChannel : public Channel {
std::vector<T> data;
};
template <class T>
class OpenGLChannel : public TypedChannel<T> {
loadToAPI(); // implementation
};
class Mesh {
template<class T>
virtual TypedChannel<T>* createChannel() = 0; // error: no virtual template functions
std::vector<Channel*> channels;
};
class OpenGLMesh {
template<class T>
TypedChannel<T>* createChannel()
{
TypedChannel<T>* newChannel = new OpenGLChannel<T>;
channels.push_back(newChannel);
return newChannel;
};
};
For flexibility, each Mesh is really a collection of channels, like one position channel, a normal channel, etc. that describe some aspects of the mesh. A channel is a wrapper around a std::vector with some added functionality.
To hide implementation details, there is a derived class for each API (OpenGLMesh, DirectXMesh, CUDAMesh, ...) that handles API-specific code. The same goes for the Channels (OpenGLChannel, etc. that handle loading of the Channel data to the API). The Mesh acts as a factory for the Channel objects.
But here is the problem: Since the Channels are template classes, createChannel must be a template method, and template methods cannot be virtual. What I would need is something like a Factory Pattern for creating templated objects. Does anyone have advice on how something similar could be accomplished?
Thanks
It's an interesting problem, but let's discuss the compiler error first.
As the compiler said, a function cannot be both virtual and template. To understand why, just think about the implementation: most of the times, objects with virtual functions have a virtual table, which stores a pointer to each function.
For templates however, there are as many functions as combinations of type: so what should be the virtual table like ? It's impossible to tell at compilation time, and the memory layout of your class includes the virtual table and has to be decided at compilation time.
Now on to your problem.
The simplest solution would be to just write one virtual method per type, of course it can soon become tedious, so let's pretend you haven't heard that.
If Mesh is not supposed to know about the various types, then surely you don't need the function to be virtual, because who would know, given an instance of Mesh, with which type invoking the function ?
Mesh* mesh = ...;
mesh.createChannel<int>(); // has it been defined for that `Mesh` ??
On the other hand, I will suppose that OpenGLMesh does know exactly which kind of TypedChannel it will need. If so, we could use a very simple trick.
struct ChannelFactory
{
virtual ~ChannelFactory() {}
virtual Channel* createChannel() = 0;
};
template <class T>
struct TypedChannelFactory: ChannelFactory
{
};
And then:
class Mesh
{
public:
template <class T>
Channel* addChannel()
{
factories_type::const_iterator it = mFactories.find(typeid(T).name());
assert(it != mFactories.end() && "Ooops!!!" && typeid(T).name());
Channel* channel = it->second->createChannel();
mChannels.push_back(channel);
return channel;
} // addChannel
protected:
template <class T>
void registerChannelFactory(TypedChannelFactory<T>* factory)
{
mFactories.insert(std::make_pair(typeid(T).name(), factory));
} // registerChannelFactory
private:
typedef std::map < const char*, ChannelFactory* const > factories_type;
factories_type mFactories;
std::vector<Channel*> mChannels;
}; // class Mesh
It demonstrates a quite powerful idiom known as type erasure. You probably used it even before you knew the name :)
Now, you can define OpenGLMesh as:
template <class T>
struct OpenGLChannelFactory: TypedChannelFactory<T>
{
virtual Channel* createChannel() { return new OpenGLChannel<T>(); }
};
OpenGLMesh::OpenGLMesh()
{
this->registerChannelFactory(new OpenGLChannelFactory<int>());
this->registerChannelFactory(new OpenGLChannelFactory<float>());
}
And you'll use it like:
OpenGLMesh openGLMesh;
Mesh& mesh = openGLMesh;
mesh.addChannel<int>(); // fine
mesh.addChannel<float>(); // fine
mesh.addChannel<char>(); // ERROR: fire the assert... (or throw, or do nothing...)
Hope I understood what you needed :p
If you could extract factory from Mesh (introducing some ChannelFactory), then you can use templatized factory:
template <class T>
class ChannelFactory
{
public:
virtual TypedChannel<T>* createChannel() = 0;
};
Than you could derive your OpenGLMesh from ChannelFactory, , , whatever.
The only limitation of this approach is that you should know beforehand which template parameters you want use in OpenGLMesh.
Otherwise you could be interested how Boost.Any works (boost::any holds values of arbitrary type).
I'd say your whole design is broken.
virtual TypedChannel<T>* createChannel() = 0; // error: no virtual template functions
std::vector<Channel*> channels;
These two lines just don't make any sense together. Don't try to fix compiler error, think over your concepts.
To start, what exactly is your reasoning for making CreateChannel a virtual member?
To put it another way, C++ is a language known for allowing all kinds of tangled unintelligible designs. And you managed to design something that even C++ thinks is too twisted.
By channel do you mean 'spacial index'?
If you want to hide implementation details, why do you have them right in your mesh?
You want the mesh to be the same basic format, maybe templating on float, double or morton numbers in different cases. It's not the mesh that should change, just the way it gets loaded.