G-Engine #9: Quaternions

Way back in G-Engine #4, we rendered a triangle, and there was much rejoicing. Since then, the posts in this series have primarily focused on implementing mathematical constructs in code. This point is the final math pre-requisite before we can move on to more interesting things.

Think of a game engine as its own little universe: at first, there is nothing - the void. Concepts such as time, position, and orientation don’t exist yet. Suddenly, the game loop and delta time introduces the concept of time. With vectors, we can convey positions, directions, and distances. Slowly, our universe takes shape and we can convey important concepts in code.

But what about rotations? Vectors can store position, direction, and scale data, but they are not effective structures for 3D rotations. We need some other option to convey rotations in code.

One structure that is very effective for 3D rotations is the Quaternion. Much-maligned for their apparant complexity, Quaternions allow us to efficiently store and use 3D rotation data. In this post, we’ll explore why we use quaternions, what they are, how to perform common operations with them, and finally I’ll provide some tips for writing your own Quaternion class.

[Read More]

G-Engine #8: Matrices

Matrices are vital tools for 3D rendering. Graphics libraries expect you to use matrices to represent positions, rotations, and scales of 3D objects. Furthermore, matrices provide a convenient/effective mechanism for representing hierarchies of 3D objects and coordinate systems.

This post will briefly explain what matrices are, explain commonly used operations for 3D game development, and provide tips for writing matrix classes for your game engine.

[Read More]

G-Engine #7: Vectors

We have added a basic math library to the 3D engine, but we’re still missing several fundamental mathematical building blocks to move forward and build full-fledged 3D environments. In particular, I want to implement Vectors, Matrices, and Quaternions. This post will cover Vectors, which enable the engine to represent important spacial concepts such as “position” and “direction”.

[Read More]

G-Engine #6: Math Library

After my post about rendering basics, I had a fairly underwhelming final result: a single triangle being rendered in 3D. But it’s progress! My next goals are to do two seemingly simple things: move the virtual “camera” around my 3D environment to view the triangle from different perspectives, and move the triangle itself to different locations in 3D space.

If we were just writing some graphics library sample code, achieving those two goals would not be too tricky. However, I want to avoid using too many graphics library convenience methods (to avoid “lock in” to a particular graphics library) and I want to be laying the groundwork for 3D world features I’ll want in the future like translation/rotation/scale of objects and parenting.

One of the first things I need to address is my lack of math library. This post will explore a basic useful math library for a 3D game engine. Future posts will build upon this math library core to add support for 3D vector math, matrices, quaternions, and more!

[Read More]

G-Engine #5: GK3 Assets Overview

Previous posts in this series have focused on the technical aspects of getting the G-Engine up and running. For this post, I’m going to take a short break from writing engine code to instead analyze how GK3 is built. It’ll be important to understand this as I move forward and try to recreate it.

As a data-driven game, GK3 makes heavy use of various custom data and file formats. I’ll refer to each piece of data as an asset.

A key challenge in this project is understanding what the different asset types are, how they relate to one another, how to parse and load them into memory, and how to make use of them at runtime in a meaningful way. The developers would have documented all this, but much of that is unavailable to me - time for some detective work!

This post focuses on those first two questions: what are the different asset types, and how do they relate to one another? We’ll take a look at the various assets, what they do, and the web of relationships between them.

[Read More]

G-Engine #4: Basic 3D Rendering

In the last G-Engine post, we got the game loop and frame “delta time” calculations working. We’ve now got a blank, empty game window - yay? Despite the unimpressive result, we’ve got a beating heart under the hood: an update loop being called at roughly 60 frames per second.

Empty windows are no fun, so my next goal is to get something - anything - rendering in the game window. Graphics are a vital and exciting part of any game, and rendering can give us vital visual feedback as we move on to implementing and debugging 3D object placement, cameras, rotations, and data loading for 3D meshes and animations.

This post will focus on rendering a single triangle on screen. Though the result is simple, we’ll cover a lot of ground towards building a 3D rendering system that will be extended and enhanced as we move forward.

[Read More]

G-Engine #3: Game Loop

In my last G-Engine post, I did some setup work and finally got a basic OS window appearing that could be moved around, minimized/maximized, and closed. Good start!

In this post, we’ll do a bit more planning, and then we’ll structure our code into a high-level class (GEngine) that’ll be more conducive to building an engine than just shoving everything into the main function. We’ll also implement our “delta time” calculations, which will be critical for updating the state of our game as we move forward.

[Read More]

G-Engine #2: Project Setup

The previous post introduced the G-Engine project. So here we are, ready to build a 3D game engine! This post walks through some early decisions, starting from absolutely nothing to having just an empty application window that can be moved around and closed.

This is not the most exciting end result, but there are plenty of important decisions to be made before we dig into actually writing game engine code.

[Read More]

Insert, Push, and Emplace

Standard C++ containers (or collections) are essential tools. Some, like vector, queue, deque, and stack are list-like: elements are accessed by position. Others, such as map or set, are more associative in nature: elements are accessed by a key.

To add an object to a vector, you can call insert or push_back. Stacks and queues both allow you to add elements using push. Map allows insertions with insert or using the [ ] operator.

In C++11 and beyond, all these containers have new functions that seem to behave similarly to the above methods: emplace, emplace_back, and emplace_front.

Which begs the question: what’s the difference between these different methods of adding items to collections?

[Read More]