Kaos Engine
Development
I implemented this engine during my free time since I started programming. My friend Basil Fierz helped me with some subsystems like the user interface. Andreas Kägi, another friend, helped me with the implementation of support for the gcc compiler and the Direct Input subsystem.
Detailed Description
The kaos Engine is kind of a ‘Game Engine’. As most ‘Game Engines’ it is like a large collection of different libraries that are useful to create solutions for a lot of different problems. The kaos Engine consists of several parts. This section is meant to give a rough overview of all the components that make up the engine:
- First of all there is a kernel providing core functionality and an operating system abstraction. All operating system dependant functionality is provided through this core. One part of this is a virtual file system, abstracting file accesses. Another large part is the meta-system providing rather detailed reflection services. There are also some more basic things like basic data structures, smart pointers, logging and similar basic services.
- kaos Math is dedicated to provide classes and functions to solve common mathematical problems. These include vector geometry, distance computations, intersection computations and others.
- A library featuring common image representations and operations. The library provides functionality for 2d images, 3d images and cube maps. It abstracts loading image data from files and saving it back. In addition there are some common filters to convert and change images.
- The kaos UI library abstracts user interface functionality. It provides an interface which can be implemented by different back ends using the Windows API, QT or similar. kaos UI allows to create user interfaces in a platform and API independent way and supports most of the common widgets needed by modern applications.
- kaos Network provides functionality useful to create interconnected applications, for example a simple FTP client.
- Finally the kaos module provides abstractions for an audio subsystem, for different input subsystems and most important for different 3d subsystems. It also features a more or less complex mesh and 3d model implementation.
- In addition there are lots of plug-ins enhancing the functionality of the modules mentioned above.
Technical Details
- Additional Developers: Basil Fierz, Andreas Kägi
- Programming Language: C++
- Development Environment: Microsoft Visual C++ 6, Microsoft Visual Studio.NET 2003 (both no longer supported), Microsoft Visual Studio.NET 2005 and Microsoft Visual Studio.NET 2008
- Project Size: 2381 files, 218871 code lines, 98367 comment lines, 71526 blank lines, 13.8 MiB code
- Technology used: fftw, libPNG, ALUT, OpenAL, LibX, Direct3D, DirectInput
Feature List
- Operating System Independant
- Compiler Independant
- Extensive I/O Library abstracting OS dependant functionality as well as implementing a virtual file system for archive files
- Multi threading support
- Reflection system
- Network library
- Common math functionality
- An image library supporting common conversions. Image types supported are currently bmp, dds, tga, png
- Network library abstracting sockets and implementing common patterns
- Generic UI system. It abstracts the implementation details and provides an interface as easy as swing and similar libraries. The current implementation supports a Win32 backend.
- A 3d graphics API abstraction. Implemented for Direct3D 9.
- A 3d model library. Supporting common operations like keyframe animation, skinning and shadow volume extraction.
- An input system abstraction. Implemented for DirectInput.
- An audio system abstraction. Implemented using OpenAL.
- A dedicated scripting language
- Many more.
Challenges
There are several problems I faced while writing the kaos Engine. First of all the term "Game Engine" is not clearly defined. It is more like a large collection of different classes for different problems. Therefore it looks much more like e.g. the Java API although it is of course significantly smaller. On the other hand it is a significant collection of source code and quite large. Therefore it needed careful design in order to prevent messing up the code and making it impossible to maintain. In fact this is the reason I named it kaos since one of the early approaches ended in a huge mess. In the end I think it is quite nice to have an engine with now nearly 300'000 lines of code while still keeping it modular and expandable.
Screenshots
A very old screenshot. I used to program using Visual C++ 6 these times... |
||
Experiments with lighting algorithms using the Direct3D fixed function pipeline in 2005. |
||
Code Sample
The code sample is taken from the start application. The snippet I present instantiates a class and calls one of its methods. Both are determined using a configuration file.
//-----------------------------------------------------------------------------
void run_application()
{
try {
#if defined(START_FROM_ARGUMENTS)
string_t starter_class = "/ktest/TestFramework";
string_t starter_methode = "Run";
get_argumentserver()->GetArgument("kaos_starter_class", starter_class);
get_argumentserver()->GetArgument("kaos_starter_methode", starter_methode);
LOG_WRITE_L1_4(LOGSEVERITY_INFO, "main", "main",
"Calling ", starter_class, "::", starter_methode);
ObjectPtr instance = get_metaserver()->New(starter_class);
instance->MakeManaged();
if (instance.IsValid())
{
SharedPtr instance_class = instance->GetClass();
SharedPtr methode_to_call =
instance_class->GetMethod(starter_methode);
if (methode_to_call.IsValid())
{
CommandPtr command = methode_to_call->CreateCommand();
command->Reset();
methode_to_call->Call(instance, command);
}
else
{
LOG_WRITE_L1_3(LOGSEVERITY_ERROR, "kstart", "main",
"methode '", starter_methode, "' not found!\n");
}
}
else
{
LOG_WRITE_L1_3(LOGSEVERITY_ERROR, "kstart", "main",
"instanciating an object of type '", starter_class,
"' failed!\n");
}
#elif defined(START_SCRIPT)
SharedPtr startfunction =
get_metaserver()->GetFunction(
KAOS_CSTRING("/scripts/kaos/startscript"));
startfunction->Call();
#endif
}
catch (Exception& e) {
LOG_WRITE_EXCEPTION_L1(LOGSEVERITY_ERROR, "main", "main", e);
e.Handled();
}
}