3D Engine – Basic Concepts

August 29, 2008

As you probably know by now, I’m making an indie 3D engine, and last time I talked aboutthe abstraction layer for accessing the 3D hardware. This time, I’m going to talk a bit about the basic concepts of the higher level engine, touching on things like meshes, materials and the scene graph.

It’s always difficult to judge what level to start at when discussing these matters. Some people know a lot about 3D already, others might be beginners… and considering how poorly defined the terminology is in the field of game development, misunderstandings are not uncommon. So, I’ll skim through the very basic stuff as well, just to make sure we’re on the same page.

renderer_triangle_mesh

This figure shows a triangle and part of a mesh. A triangle is made up of three points (called vertices), and if you draw a line from one vertex to another, you get what is called an edge. The area contained by three connected edges is the actual triangle. In a 3D engine, everything is made up of triangles, and if you need more complex shapes, you always build them by combining triangles. This is because 3D hardware works with triangles, and all a 3D graphics card really does, is provide a way of drawing lots and lots of triangles really really fast (the more modern cards can do it in a very flexible way, usingprogrammable shaders, but it still comes down to drawing triangles).

There’s no definitive name for a collection of triangles, but I’ve chosen to call it a mesh. In the above figure, you can see that a mesh is made up of a bunch of vertices and triangles connecting them. It would be possible to define a mesh in terms of a long list of vertex triplets, but as some vertices are shared between several triangles, that would mean that we waste a lot of memory by duplicating data (as you will see later on, a vertex can be quite large, as it contains not only a position, but also color, normal  and texture coordinate information). The common solution for this is to specify all the vertices in one big list (called a vertex buffer) and when specifying the triangles, to use the index of a vertex instead of the full vertex. So a triangle would be defined with three simple index values rather than three complex vertex structures. If you look at the platform abstraction layer I defined last time, you’ll see that there’s functionality for creating vertex and index buffers, as well as a Render method which allows us to specify which vertices and indices to use from the specified buffers.

renderer_meshdefinition

So, the way I define a mesh, is as a collection of vertices and indices, along with a material,as pictured in the above figure. This means that all the triangles in a mesh are rendered using the same material, and it also means that it’s not possible to move one part of a mesh in relation to the other parts (for example, spinning the wheels on a car). This means that some models will need to be made up of several meshes, but that’s fine – we can deal with that. But it also means that a mesh can be rendered in one go.

Few models are simple enough to be made up of only one mesh. You often want to use different textures on different parts of the character, or you might want parts of the model to be able to move independently of the others (like the wheels on the car). The way we’ll be making that possibile, is to create a hierarchy, or tree structure, of nodes.

renderer_nodedefinition

In the above figure, you will see the contents of a node. Each node has a name, which will be useful to identify the different parts of a model, and it also has a transform, which is a description of the nodes position and rotation relative to its parent node. A node might have any number of child nodes, which can be either nodes themselves, or meshes (as defined earlier).

There are some nice things about structuring things this way, as we will see later on. A model will be defined as just a node, and the entire scene (everything we render) will also be just a node. To add a model to the scene, we just add the models node as a child to the scene node. If we have a model of a car, and a model of a driver we want to attach to it, we would just add the driver model as a child node to the car model, and the car model as a child node to the scene.

More on this next time, when I will talk a bit more about how we go from these basic concepts to actually rendering it using the platform abstraction layer. And if anything is a bit unclear, just post your questions as a comment and I’ll do my best to clarify.

Leave a Reply