Tag: Game Engine
The Carnot Game Engine
by Geoffrey on Mar.06, 2009, under Carnot
Discussions about Endless Skies usually go something like this:
Johannes: We need this feature. Can you code this feature??
Me: Well, it’s a bit more complicated than that, but I’ll try. Would this be ok?
Johannes: But it needs to be bigger! Much bigger! And more complex! And more realistic! And sum (-inf, +inf, BIG)!
It took all of three seconds for me to realize that no commercial engine would provide the power Johannes was looking for. I’d have to write one from scratch, specifically tailored to meet his outlandish demands. Thus, the Carnot Game Engine was born (named for the Carnot Heat Engine).
At the moment, I am putting finishing touches on how it handles static objects, and finally have something concrete to talk about. Carnot composes static objects out of a Node and a Mesh. A Node contains meta-data seen by users, and most importantly, a transformation matrix that defines the object’s position. A Mesh contains an object’s geometry. When deciding how to handle objects, I came up with three basic goals:
1) No geometry should be stored in memory more than once, regardless of how many nodes use it (example: rendering a classroom. The chair mesh should only be stored once, even if it is used by twenty chair nodes around the room).
2) In any single rendering pass, geometry should be sent to the GPU at MOST once.
3) Handling different LOD’s (levels of detail) should be automatic, and require no changes to actual geometry.
This lead to the following simplified object structure:

When a Node is loaded from a file, it has a list of LOD’s and corresponding mesh files. Carnot checks whether the mesh is already in memory, and loads it if necessary. Otherwise, it locates it in memory. Thus goal #1 is satisfied.
It then connects the Mesh to the Node for each LOD at which the Node’s geometry is stored in the mesh. The Mesh contains a list of LOD’s, each containing a list of Nodes for which the Mesh is the Node’s geometry at that LOD.
Convoluted? Yes. Memory overhead? Yes, a bit. Fast? Extremely. Let’s consider what happens when rendering a frame. Rendering is done per-mesh, as follows: If the mesh is being stored as a VBO (vertex buffer object) in video memory, it is set as the current vertex array (and how Carnot decides what to store in video memory will probably make a post of its own). Otherwise, its geometry is sent to the GPU. Then, Carnot iterates through every node pointer in the Mesh. If the Node’s current LOD is the same as its LOD in the mesh, then the OpenGL Modelview Matrix is multiplied by the Node’s matrix, and the geometry is rendered. Thus, goals #2 and #3 are is satisfied. All you have to do to change what LOD a Node is rendered at is to change one integer, and assuming that Mesh is in memory, it will automatically start rendering.
So what’s next? A few tweaks to the VBO’s, and ideally a PNG loader for textures. After that it’ll be time to hammer out a good file format, so Johannes will have something to play with, and will hopefully hector me less about my progress
~G2