FireStorm Engine
FireStorm is my own experimental C++ game engine, inspired by Unreal Engine. Source codes are not yet available.
It is currently in an early stage with only a few functional modules. It is absolutely not intended to be ready for production, other engines are more advanced and more efficient (like Unreal).
FireStorm is designed around 3 concepts: Ease of use, Optimization and Modularity.
Ease of use
Build System
FireStorm is written in C++ and use CMake as build system. CMake very good tool for C++ programmers, despite obvious drawbacks (Weird syntax !!!). Meson is a good alternative, with a really good syntax but without the possibility to create its own functions (Meson developers explain that this would make the language "Turing-complete").
Handling dependencies
FireStorm Engine use Conan to manage dependencies. Conan is a C++ dependency manager written in Python. It is a good tool because it is "project-centric" (each project has is own dependency list) unlike VCPKG which is "system-centric". Conan allows the user to avoid installing dependencies himself. It also allows the user to have an excellent integration with CMake and to be able to create his own packages (the main defect of Hunter and VCPKG). It also has an huge list of officially supported libraries.
Code generation and metadata
FireStorm use C++ reflection. Since C++ lacks such a feature, I had to create a code generator to easily
complete classes with reflection. This kind of process is widely used, for example by Unreal Engine or Qt. It
works similarly to Unreal Header Tool. It permits to choose the elements able to use reflection with generate
useless code. It uses macro like UHT: FIRECLASS
, FIRESTRUCT
,
FIREENUM
, FIREPARAM
, FIREPROPERTY
et FIREFUNCTION
.
Here is an example of use to make a reflective class :
namespace firestorm
{
FIRECLASS(Abstract, DisplayName = "Actor")
class AActor : public FFireObject
{
...
FIREPROPERTY(EditAnywhere, Help = "Actor velocity")
float Speed = 10.0f;
FIREFUNCTION(Getter = "Speed")
void SetSpeed(float InSpeed);
...
};
}
Reflection macros use a DSL close to that of Unreal Engine. However, the FireStorm's DSL is strict,
case-sensitive and extensible. For example, With Unreal, UCLASS(DisplayName = "Actor")
and
UCLASS(DisplayName = Actor)
are same. With FireStorm, absence of quotation marks
(SECLASS(DisplayName = Actor)
) is considered as a syntax error by design.
FHT (FireStorm Header Tool) implementation use Clang libraries for parsing C++ code.It permits to use
more C++ features than UHT like namespaces. This tool retrieves classes, structures, enumerations, attributes,
methods and parameters marked with C++ annotations (cad [[annotate("...")]]
) and parses the
annotation string with a lexer/parser build with Flex and Bison.
FireStorm Header Tool is extensible. Each engine and game module can add specifiers and generate code. For
example, an RPC module can add RpcClient
, RpcClient
et RpcBoth
specifiers.
Manage assets
FireStorm Engine has two terms for designing assets.
- "Asset" refers to the files created by the user with another software (like Blender or Photoshop) and imported into the engine.
- "Ressource" refers to the files imported by the engine. They are created by the engine transformed from the assets. They are therefore internal assets.
The asset import process is very similar to Unity import process. The user must place the assets in the Content folder. He must then import them manually (via a tool in the interface). The engine will then associate a meta file to each asset. The meta file allows the engine to transform an asset into a resource. This meta file contains the ID of the resource and various import parameters (these parameters vary depending on the type of asset being imported). Each time an imported asset is modified, the engine automatically converts the asset into a resource.
Asset & data management follows those rules:
- Assets must be easy to handle and transfer. For example, like Unity does, where each asset is referenced by a guid in a meta file.
- Assets must be stored raw. One should not have to re-import an asset in an internal format manually each time it is changed. The best way to do this is like Unity: a meta file containing the import parameters is associated with each asset. The combination of the two allows you to create the asset in a format used by the engine.
- Data files must be easily modifiable. This is one of Unreal's main concerns for me. If a binary file is corrupted, it is often impossible to repair it. In a text format, it is possible to modify the data manually.
- Data files must be easily readable. Because I use Git, it's painful to manage a Unity project with, just because the scene files use bloated YAML.
- The engine must be error-sensitive.
Optimization
Scene compilation
During compilation, the scenes initially structured in XML format are transformed into C++ code. This will then be compiled into a shared library. This method should allow a faster loading of the scenes. However, the performance of this method is purely theoretical.
File system
FireStorm uses CFS. For more information about CFS, see here.
Modularity
Module architecture
FireStorm is split in several parts:
- Runtime Core module contains essentials classes like containers, module loader, etc...
- Runtime modules contains others parts of the engine(rendering, physics, input, gameplay base, etc...).
- Editor Core module contains essential editor features like main windows. It designed with Qt. The editor allows you to create levels and manage assets in the same way as Unity and Unreal.
- Editor modules contains plugins, tools and extensions for the editor.
- Some external tools like shader compiler, FHT, etc...
Most of the modules use delayed loading. The engine is responsible for loading module dependencies.