6
\$\begingroup\$

I'm piecing together the beginnings of an extremely basic engine which will let me draw arbitrary objects (SceneObject). I've got to the point where I'm creating a few sensible sounding classes, but as this is my first outing into game engines, I've got the feeling I'm overlooking things. I'm familiar with compartmentalising larger portions of the code so that individual sub-systems don't overly interact with each other, but I'm thinking more of the low-level stuff, starting from vertices working up.

So if I have a Vertex class, I can combine a list of those with a list of indices to make a Mesh class. How does the engine determine identical meshes for objects? Or is that left to the level designer? Once we have a Mesh, that can be contained in the SceneObject class. And a list of SceneObject can be placed into the Scene to be drawn.

Right now I'm only using OpenGL, but I'm aware that I don't want to be tying OpenGL calls right in to base classes (such as updating the vertices in the Mesh, I don't want to be calling glBufferData etc).

Are there any good resources that discuss these issues? Are there any "common" heirachies which should be used?

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

A mesh class should include more things like AABB and material info. You might even find yourself in a need to store multiple meshes in one class. Or perhaps you could need different vertex formats. It appears that you've started building your engine before your game. And that never helps. You should instead try to think of what you're realistically going to need and design with that in mind.

Tying OpenGL calls in base classes isn't bad. It just means that you won't use another API. And no one needs two APIs at the same time. If you'll find yourself in a need for multiple renderers (even though you shouldn't because you use OpenGL), it is much easier to implement the renderer as a service which the game passes data to and simply lets it sort out rendering any way it wants. But I've also succeeded in making a low-level API wrapper so that path (even though it's slightly more complicated) is a valid path to take, too, as long as feature set allows it (shader support is required for this to work).

As for common hierarchies, try something like this:

class SceneInfo {
    MeshList meshes;
    ParticleSystemList pslist;
    ...
}
class Renderer { function Render( SceneInfo* info ); }
class Game { SceneInfo info; Renderer renderer; }
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Minor quibble: "even though you shouldn't because you use OpenGL" -- not true, though it's a common misconception. There are several gaming platforms where OpenGL is not supported (or, at least, where it is not the dominant/preferred rendering API). Consoles, mainly. \$\endgroup\$ Sep 5, 2012 at 2:06
  • 3
    \$\begingroup\$ You're right. But I wouldn't expect someone making his first engine to develop it for consoles. Windows+Linux+Mac support is a big enough cross-platform development challenge if he wants that. \$\endgroup\$
    – snake5
    Sep 5, 2012 at 4:25
2
\$\begingroup\$

I am guessing your Vertex class actually represents a vertex buffer (and not a collection of thousands of Vertex objects that make up your Mesh). When I started out making a low-level rendering engine, I had a Mesh class only require exactly one IndexBuffer and VertexBuffer class, because I didn't see a need where I would have to swap index buffers with a different Mesh after the Mesh is fully built. (This terminology reflects DirectX which I was using)

The buffers were initialized with separate IndexLoader and VertexLoader classes, which inherited a base Loader class. A FileReader class read the mesh file and spit out structures used by the Loaders. In hindsight this might have been overengineering it a bit, but I wanted to keep the loading stuff separate from the rendering.

A Scene pools the Meshes for updating and rendering. SceneRenderer has a reference to a scene, it can be swapped with a different Scene if you want several rendering layers going on.

I wanted to introduce some basic culling for the scene, so I kept both an ordered list and an unordered list of Meshes for pooling. Every Mesh created goes to the ordered list first, and the unordered list keeps pointers to the ones that needed to be drawed in that frame.

Insertion time to the ordered list was linear * log n I believe, because I used string handles for the Meshes ordered to make binary search possible. This made it possible to quickly access the Meshes that need to be drawn (in log n time) and copied to the unordered list. The SceneRenderer iterates through this list in linear time when the scene is drawn.

\$\endgroup\$
2
  • \$\begingroup\$ Hi, the Vertex class is a wrapper around float[3], and I was suggesting having a list of Vertex inside the Mesh class. I've updated the question as it wasn't too clear. \$\endgroup\$ Sep 4, 2012 at 20:16
  • \$\begingroup\$ This would make more sense as a structure, then. \$\endgroup\$
    – ChrisC
    Sep 10, 2012 at 15:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .