Reputation: 4085
I'm trying to find my ways in the C++ land and am increasingly confused by now. The toy application is a very basic OpenGL engine. So here's the (I guess simple) problem: I'd like to handle meshes of different vertex data, so I'd have e.g.
struct Vertex
{
Vector3f position;
}
struct VertexN : public Vertex
{
Vector3f normal;
}
Now I need a Mesh class, that holds the data and draws it. I've tried something like this:
template<class T>
class Mesh
{
public:
Mesh();
~Mesh();
void load(const T * vertices, int num);
void draw();
protected:
T * vertices_;
};
The different vertices have to be loaded and drawn differently and this can be done with template specialization.
My problem is that I like to have another class that holds instances of Mesh objects, but templated class members are obviously not allowed.
The other solution I can think of is to hold pointers to the base struct Vertex in Mesh, pass an identifier for the Vertex type used and then use switch statements in load() and draw() to allow for the different implementations.
What is the best way to accomplish this?
Any help is greatly appreciated.
Upvotes: 4
Views: 411
Reputation: 543
@bshields has a point, you need to represent vertex data in the most efficient manner, which in the case of OpenGL are Vertex Buffer Objects (VBOs): http://www.opengl.org/wiki/Vertex_Buffer_Object
Given the guidelines exposed in the link above - which go in line with what @James McNellis says about not using inheritance for your Vertex types - and the fact that both loading and drawing will probably depend on the type of vertex and the kind of input (or output) I would suggest you to apply the Strategy pattern using static polymorphism, as outlined in the answer to this other question: template strategy pattern
Upvotes: 0
Reputation: 3593
I recommend that you don't templatize your mesh class but make it capable of handling different types of vertex data. This is a common graphics problem and is addressed in DirectX with the notion of binding different "streams" of data together to draw geometry. In other words, your normals would be a different data stream than your position data. Then your mesh object becomes a container of multiple streams of data and would not be bound to a particular vertex format at compile time. I don't know OpenGL as well but I imagine there is a similar concept.
See: http://msdn.microsoft.com/en-us/library/bb147299(VS.85).aspx
Upvotes: 0
Reputation: 355147
You can use inheritance and virtual functions. For example:
class MeshBase
{
public:
virtual ~MeshBase() { }
virtual void draw() = 0;
};
template <typename T>
class Mesh : public MeshBase
{
public:
virtual void draw() { }
// ...
};
With this approach, you can store pointers to the base class MeshBase
in a container.
Ideally, you can use a pointer container, which will manage the pointers for you, or you can use a container of smart pointers (for example, a std::vector<std::shared_ptr<MeshBase> >
, if your implementation includes shared_ptr
; if not, it can be found in a number of places).
I would also recommend storing the vertices in a container in the Mesh
class, rather than using manual dynamic allocation and memory management.
Upvotes: 7