I want to use OpenGL as graphics of my project. But I really want to do it in a good style. How can I declare a member function "draw()" for each class to call it within OpenGL display function?
For example, I want something like this:
class Triangle
{
public:
void draw()
{
gl开发者_如何学JAVABegin(GL_TRIANGLES);
...
glEnd();
}
};
Well, it also depends on how much time you have and what is required. Your approach is not bad, a little old-fashioned, though. Modern OpenGL uses shaders, but I this is not covered by your (school?) project, I guess. For that purpose, and for starters, your approach should be completely OK.
Besides shaders, if you wanted to progress a little further, you could also go in the direction of using more generic polygon objects, simply storing a list of vertices and combine that with a separate 'Renderer' class that would be capable of rendering polygons, consisting of triangles. The code would look like this:
renderer.draw(triangle);
Of course, a polygon can have some additional attributes like color, texture, transparency, etc. You can have some more specific polygon classes like TriangleStrip
, TriangleFan
, etc., also. Then all you need to do is to write a generic draw()
method in your OpenGL Renderer
that will be able to set all the states and push the vertices to rendering pipeline.
When I was working on my PhD, I wrote a simulator which did what you wanted to do. Just remember that even though your code may look object oriented, the OpenGL engine still renders things sequentially. Also, the sequential nature of matrix algrebra, which is under the hood in OpenGL, is sometimes not in the same order as you would logically think (when do I translate, when do I draw, when do I rotate, etc.?).
Remember LOGO back in the old days? It had a turtle, which was a pen, and you moved the turtle around and it would draw lines. If the pen was down, it drew, if the pen was up, it did not. That is how my mindset was when I worked on this program. I would start the "turtle" at a familiar coordinate (0, 0, 0), and use the math to translate it (move it around to the center of the object I want to draw), then call the draw() methods you are trying to write to draw my shape based on the relative coordinate system where the "turtle" is, not from absolute (0, 0, 0). Then I would move, the turtle, draw, etc. Hope that helps...
No, it won't work like this. The problem is that the GLUT Display function is exactly one function. So if you wanted to draw a bunch of triangles, you could still only register one of their draw() functions to be the GLUT display function. (Besides, pointers to member functions in C++ are a hard topic as well).
So as suggested above, go for a dedicated Renderer class. This class would know about all drawable objects in your application.
class Renderer {
std::list<Drawable> _objects;
public:
drawAllObjects() {
// iterate through _objects and call the respective draw() functions
}
};
Your GLUT display function would then be a static function that calls drawAllObjects() on a (global or not) renderer object.
Ah, good old immediate-mode OpenGL. :) That routine there looks fine.
I would probably make the 'draw' method virtual, though, and inherit from a 'Drawable' base type that specifies the methods such classes have.
精彩评论