ToyMaker Game Engine 0.0.2
ToyMaker is a game engine developed and maintained by Zoheb Shujauddin.
Loading...
Searching...
No Matches
ToyMaker

About

ToyMaker is an open source, extensible, single-threaded 3D game engine written in C++ on top of SDL3 and OpenGL. Scene data is described in JSON and managed through a combination of ECS and scene tree APIs. Demo projects using ToyMaker have been compiled successfully for Windows and Linux.

ToyMaker is currently in very early alpha; all APIs seen here today are subject to change until an eventual 1.0 release. It also doesn't yet feature a level editor.

Examples

Fill Container 1

Fill Container 2

Fill Container 3

Examples/FillContainer – shows spheres spawning at a steady rate filling an invisible container, with several collision checks and corrections taking place every frame.

Triple Pendulum

Examples/TriplePendulum – shows set of granular single degree of freedom position constraints being used to model the behaviour of a hinge joint in a triple pendulum.

Slope Friction

Examples/SlopeFriction – demos friction forces causing a moving block to slow and come to a stop sliding down a gentle incline.

Many Lights

Examples/ManyLights – scene containing 441 point lights and 441 models (2 meshes each) rendered with instancing for both.

One One Collision

Examples/LeftRightCollision – shows single one-to-one collision between two spheres.

Interactive Center Text

Examples/CenterText – demo featuring clickable text that spins on interaction.

Features

  • Rendering using Blinn-Phong lighting in a fixed deferred shading pipeline.
  • Scene data organized and updated via the engine's own single-threaded Entity-Component-System implementation.
  • Extensible resource loading, tracking, and serialization through ToyMaker's Resource Database
  • Scene management through its scene-tree style API with JSON serialization. Additionally supports:
    • Multiple viewports through ToyMaker::ViewportNode, where each viewport may share its parent's ECS "World" or create one of its own.
    • Object-oriented, component based application logic scripting, a la many popular engines, through ToyMaker Aspects
  • Input abstraction, management, and serialization via the engine's input system.
    • Input events are buffered on receipt, and only sent to listeners when the input's timestamp matches the simulation window currently being processed by the engine. This ensures that user inputs are processed predictably even during update compute lags.
Note
Currently requires knowledge of SDL's input event definitions to set bindings correctly.
  • Observer pattern implementation in the form of ToyMaker Signals, allowing decoupling of event data publishers and consumers.
  • A spatial query system using octrees for fast retrieval of scene entities based on spatial parameters (e.g., ray casts, bounding volume collisions, etc.)
  • A physics system using an implementation of Extended Position-Based Dynamics(XPBD) with support for collisions between capsules, spheres, and cuboids.
    • In addition to the spatial query system's octree, it uses Sweep and Prune to accelerate broad phase collision checks per physics substep.

Motivation

I spent 2023-2024 studying C++, OpenGL, SDL, and 3D graphics by following the tutorials on learncpp, Lazy Foo, and Learn OpenGL among others. I used my learnings to write Game of Ur, then split this engine out from it. The goal now is to take this as far as I can while learning as much as I can along the way.

Documentation

See raynmetal/game-of-ur's toymaker-fork tag which holds the commit history leading up to the splitting of the engine project from the game project.

Documentation for the engine is available on this project's github pages.

Open, ongoing, and completed tasks and issues are tracked on this project's Trello board.

Building & Running

Requirements

This project uses CMake for its build system, so make sure to have that installed.

On your platform, download the following packages and place them somewhere discoverable by your compiler toolchain. This project has been successfully compiled with MinGW-w64 on Windows, and clang on Linux.

  • SDL3 – For abstracting away platform specific tasks, like requesting a window for the application.
  • SDL3 Image – For loading of images in various formats.
  • SDL3 TTF – For loading and rendering fonts.
  • GLEW – For exposing OpenGL functionality available on this platform.
  • Nlohmann JSON – For serialization/deserialization of data to and from JSON.
  • GLM – For linear algebra functions resembling those in GLSL, and for quaternion math.
  • Assimp – For importing assets of various kinds, mainly 3D models.
  • Doctest – For building and running tests.

If you'd like to generate and tinker with the documentation generated for the project, also install Doxygen.

Presets

The project is bundled with a few CMake presets used with cmake --preset ${PRESET}

  • Examples_FullBuild_Release – Compiles all example projects under Examples/ and the ToyMaker library, with optimizations enabled and debug symbols disabled.
  • Library_Release – Compiles only the engine library using sources found in ToyMaker_Main/ and ToyMaker_Builtins/, with optimizations enabled and debug symbols disabled.
  • Examples_AppBuild_Release – Compiles a release version of the projects under Examples/, linking them to ToyMaker binaries already installed in the local system.

Replacing Release with Debug in any of the above enables the generation of debug symbols and suppresses many compiler optimizations.

Building

First, clone this repository.

git clone https://github.com/raynmetal/toymaker.git
# OR, using ssh
git clone git@github.com:raynmetal/toymaker.git

Create a directory for storing files generated during the build process. The instructions here assume that the build directory is ../toymaker_build/ relative to the project root.

# on Linux and Mac
mkdir toymaker_build

Enter the project directory and generate the build configuration using CMake. The instructions here use the FullBuild_Examples preset (see the Presets section), that generates binaries both for the ToyMaker library as well as the example projects under Examples/.

Important
For now, the toymaker_configure_executable CMake script picks up created and removed data files (JSON scene descriptions, images, models, etc.) only when this command is run.

Be sure to rerun it whenever making such a change if you use ToyMaker in a project of your own, or when attempting to modify any of the examples.
cd toymaker
cmake --preset Examples_FullBuild_Debug -B ../toymaker_build

Finally head over to the project directory and actually build the project.

cd ../toymaker_build
cmake --build .

Running Examples

Starting in the build directory root, navigate to the directory containing the demo you would like to run (say, FillContainer).

cd Examples/FillContainer

Then simply run the generated executable (likely prefixed with Example_).

./Example_FillContainer
Warning
This command will not work if you try running it while in a different directory from the executable, as in:

toymaker_build/Examples/FillContainer/Example_FillContainer


Running the above will lead to an immediate crash, as the program won't be able to find the data files it expects to find in the directory where the command was invoked. This is an issue and will be addressed in a future update.

Running Tests

Tests are compiled along with the rest of the library when ToyMaker is itself the project being built (as opposed to when it is a vendored library in another project). The test sources are found under tests/ under the project root.

To run them, go to the root of the build directory, then invoke:

tests/TestDriver

ToyMaker uses Doctest for testing. See instructions there to learn how to run tests selectively, or with options besides the default.

Contributing

I'm not planning to accept contributions to this project any time soon. Feel free to fork it and make it your own, though!

LICENSE

raynmetal/toymaker is distributed under the terms of the MIT License.

This program makes extensive use of the following libraries: