| Assimp | Used for reading 3D models |
| Dear ImGui | Used for 2D GUI |
| GLAD | Used for loading OpenGL extensions |
| GLFW | Used for OpenGL initialization and management |
| GLM | Used for linear algebra math |
| GoogleTest | Used for unit testing |
| OpenGL | Used for 3D rendering |
| STB | Used for reading image files |
Various wireframe rendering techniques exist, each more/less different; efficient; modern than others.
The current architecture allows devs to implement their own model loader via the ModelLoaderImpl interface, in which they choose how each mesh's triangles layout is made (triangles, strips, fans). This would have potentially required different ways of handling that in shaders. For simplicity, the traditional global polygon mode (glPolygonMode) is used.
The main loop frame rate is capped at the primary monitor's refresh rate. For example, if your primary monitor's refresh rate is 144 Hz, the main loop will run approximately 144 ticks in 1 second. However, because frame rate can still fluctuate, a fixed timestep with an accumulator is also used when computing camera movement, model transform and animation to ensure a fixed number of ticks per second. This timer's frequency is also set to the primary monitor's refresh rate.
A fixed-size circular queue was developed for the dev messages system. It is implemented similarly to what's explained here. This data structure was needed for efficiently adding and popping messages to the dev messages queue in O(1).
The interface to use for all model loaders. It has 2 methods:
- LoadModel
- LoadAnimation
virtual bool LoadModel(
const std::string& file_path,
const ProgramBindings& program_bindings,
TextureStore& texture_store,
Model& out_model
) = 0;Parameters:
| Parameter | Description |
|---|---|
| file_path | The model's file path |
| program_bindings | The OpenGL program bindings singleton |
| texture_store | The texture store singleton |
| out_model | The output model |
Return value:
trueif the model was successfully loadedfalseotherwise
virtual bool LoadAnimation(
const std::string& original_model_file_path,
size_t animation_index,
Animation& out_animation
) Parameters:
| Parameter | Description |
|---|---|
| original_model_file_path | The original model's file path |
| animation_index | Zero-based index of the animation. 0 = first animation, 1 = second animation, etc. |
| out_animation | The output animation |
Return value:
trueif the animation was successfully loadedfalseotherwise- Default:
false
Implements ModelLoaderImpl. Uses Assimp to read a model file and creates each mesh, texture and animation.
Note: For embedded textures, it currently always assumes each texture's pixel format is
GL_BGRAand sets the OpenGL internal format toGL_RGBA8.
Note: It currently only supports linear interpolation when reading animations.
Implements ModelLoaderImpl. Builds a 3D cube made of 6 meshes (1 mesh per face), each with 3 skins. No skeletal animations.