Simulant 21.12 Released!

Happy New Year!

Another quarter has gone, and that means it's time for another tagged release of SImulant! A lot has happened over the last 3 months, mainly driven by the development of the Driving Strikers Holiday Edition Dreamcast game demo that has been developed by the main Simulant contributors.

So onto what's new in this release!!

Core API Restructure

The way the core of Simulant has been structured until now has been quite messy due to the way the engine unexpectedly developed over time. Specifically, objects and properties that would logically be at the Application level, belonged to the Window - the Window class had multiple unrelated responsibilities and it was a big code smell.

In 21.12 this has all changed!

  • time_keeper, shared_assets, vfs, idle, sound_driver, stats, and frame started/finished signals are now found under the Application
  • Stage management (e.g. new_stage()) is now handled by the Scene class template

This is a much cleaner structure and the Window class is now only responsible for things like event handling and functionality related to the window itself.

New UI Widgets!

New UI

Alongside a huge cleanup with how widgets are rendered and sized, we've introduced two MVP widgets that make the UI system much more powerful:

  • Frame - this widget is a container widget that you can pack child widgets into, either in a left-to-right, or top-to-bottom orientation.
  • Keyboard - this widget is an onscreen keyboard that you can create to gather input from a player when a physical keyboard isn't available.

Both widgets are a first-pass iteration, and have some rough edges that will be ironed out before the next release.

Better UI Theming

We've introduced a new default UI theme in this release. The bold blue has been toned down and widgets by default have a dark theme. We've also cleaned up the UI theming so that you can create a new look just by providing new background, foreground, text, and highlight colours.

Physics Updates

We've updated our copy of Bounce to the latest upstream version, and there have been a number of performance improvements in our wrapper code. Also we've introduced new functions to RigidBody as well as a new KinematicBody class!

Improved Font Loading

TTF fonts are now used by default over .FNT fonts. You can specify a default font and size in the AppConfig for your application and Simulant will use that for UI widgets, and panels. You can now override fonts easily per-widget by calling Widget::set_font() and this will use an internal font cache to make sure that fonts are only loaded when necessary.

Upgraded OpenAL for Dreamcast

ALdc, our Dreamcast OpenAL implementation, has been upgraded. This provides working, low-CPU positional audio when running on the Dreamcast platform!

Bug Fixes

There have been a vast number of big fixes and improvements over the last 3 months - too many to list! The focus on the next quarter will be to continue to improve the widget framework and we'll start tentatively looking towards adding networking support to the engine!

A New Simulant Game: Tunnels!

Happy Halloween!

As a Halloween surprise two members of the Simulant team, Luke Benstead & David Reichelt, have been working on a mini Halloween Dreamcast demo called "Tunnels"!

It is available for you to download on the itch.io page.

What is it?

Tunnels is a mini-demo of the Simulant engine. It's been written over the past three weeks as a demonstration of what Simulant allows you to do in very little time. Both Luke and David have day jobs, and this has been developed in their spare time - probably an hour a day each at most - and a good majority of that time was spent improving Simulant itself!

Along the way flaws were discovered in Simulant and many were fixed, others will be fixed later. Some planned features were dropped due to limited time, but may reappear at some point. In the future we'll use Tunnels as a test bed for new Simulant features, and as a regression test.

What made the cut?

Tunnels demonstrates a number of features - that possibly have never been in a Dreamcast homebrew game before:

  • A full real-time physics simulation. The entire world is being powered by the "Bounce" real-time physics engine.
  • Skeletal animation. The enemy in the game is a fully skeletal animated mesh.
  • 3D positional sound. The game uses ALdc - our custom OpenAL implementation for true 3D audio.

What didn't make it?

There were a number of features that were unfortunately dropped due to time constraints:

  • Item drops. The original idea of the game was to start with no weapons, and have to scavenge things from the tunnels. Hopefully we'll restore this functionality at some point.
  • Particles. Testing exposed a performance issue with the Simulant particle system on Dreamcast. Once this has been addressed we'll restore particles to the demo.

What was fixed?

Many issues were fixed in Simulant, including:

  • A brand-new memory efficient Wavefront OBJ loader was built, from scratch!
  • Many issues were fixed in the Milkshape3D model loader.
  • Skeletal animation was heavily optimised, particularly for the Dreamcast.
  • Added a new 'KinematicBody' class to the physics engine
  • Added many new features to the RigidBody class
  • Fixed issues with flipped controller axis between PC and DC
  • Fixed bilinear filtering with mipmaps on the Dreamcast
  • Added a new raycast API
  • Fixed an issue where Sounds wouldn't be released
  • Added support for DC triggers, and the 2nd analog stick (if a controller is ever released with one!)

Known Problems

  • Sound popping. This is a problem with ALdc that we didn't manage to solve in time.
  • Memory issues. The game appears to "leak" memory between tries. We're looking into it.
  • Low frame rate. On Dreamcast, the framerate hovers between 20-25 FPS, we hope to increase this to a constant 30+ FPS.
  • Monster movement issues. When comparing between PC and DC, the enemy seems to move away from you on DC, whereas on PC it very much attacks! There seems to be a subtle bug/difference in the physics between PC and DC (possibly frame-rate related).
  • Pressing Start kills the game. This was an oversight in the release, it will be fixed in a future version.
  • Slow loading time. This is because we're using the .obj file format for model loading - and it's not a particularly efficient way of loading a scene.

Credits

Special thanks go to the following people!

  • mrneo240 - for packaging the CDI image nicely for us
  • Psionic for the spider model
  • 3DModelsCC0 for the crowbar model
  • FreeSound and OpenGameArt for various CC0 licensed bits

Simulant 21.09 Released!

It's a couple of days later than expected, but I'm happy to announce the 21.09 release of Simulant!

Swirling Blades Image

There are a couple of big features in this release, and the usual scattering of smaller features, bug fixes and improvements. Here are some of the highlights.

The MeshInstancer Stage Node

Up until now there are have primarily been two methods of displaying loaded mesh in your game scene, these are:

  • Actor - a fully dynamic stage node that allows behaviours, multiple levels of detail, and an array of other features. To support all this, Actors are very memory-intensive.
  • Geom - a completely static stage node, attached meshes are compiled on construction. Usually used for level geometry.

There are times though when you need some middle ground: you want to spawn multiple instances of the same mesh, but you don't want to have to take the overhead of creating an Actor for each one. And that's where MeshInstancer comes in!

The new MeshInstancer stage node is a fully dynamic stage node (it can be moved, have behaviours etc.) but when instantiated with a mesh, it doesn't immediately render anything. Once you have created a MeshInstancer you can then spawn multiple instances of the mesh over and over again at relative positions around the MeshInstancer. The mesh instances that are created use very little memory, and are incredibly fast to render. MeshInstancers are ideal for spawning things like foliage, trees, rocks etc.

In 21.09 we have implemented a first-pass at the MeshInstancer, but in following releases we intend to add levels of detail like actors, and much more - while ensuring that things remain fast and light.

A Stream-based JSON Parser

Up until now Simulant bundled in Jsonic, which is a very small JSON library and this was used for parsing material and particle script files, among other things. It wasn't a publically advertised API though so unless you went digging around the Simulant codebase you wouldn't know about it.

Jsonic (and many other JSON parsers) suffered a flaw though that was catastrophic for low-memory environments like the Dreamcast: it would load the entire JSON file into RAM.

Simulant 21.09 now includes a custom public JSON parsing API which uses an underlying file stream to move around the file data. This allows minimal memory usage even with massive files and it's resulted in much lower memory usage when loading materials and particle scripts.

Faster UI Widgets

UI widgets have been cleaned up, many bugs have been fixed, and they are much more performant. This is the result of increased user testing and feedback on the UI subsystem. Newlines in text are now also handled correctly without causing a crash which had been a long-standing bug.

The UI subsystem is still very much a work in progress, and we welcome testers and contributors to help build it out into a first class part of the engine.

Miscellaneous Improvements

There have been a number of bug fixes and improvements including:

  • The Simulant test suite now uses far less memory
  • A performance issue and potential memory leak in the physics subsystem has been fixed
  • We've continued our drive to factor out C++ exceptions where they aren't necessary, using smlt::optional<T> returns instead
  • The SmoothFollow behaviour has received some improvements, including the ability to pause and resume following
  • Console logging now uses ANSI colours for INFO, WARN, and ERROR levels
  • You can now force a texture file extension when loading 3D models - this is useful to force a platform-specific texture format (e.g. .dtex on Dreamcast) even if the model file specifies say, a .png
  • GLdc has been updated and this has received a lot of performance improvements recently

Simulant Needs You!

Simulant has come a long way over the last few years, but to really fulfill its potential it needs more people to get involved! If you've ever wanted to write a game, give it a try! If you're a developer and you want to add new features and improvements, get stuck in!

Special thanks again to everyone on the Simulant Discord - particularly @freakdave you continues to be our number one contributor and tester!

Simulant 21.06 Released!

Unfortunately a little later than scheduled, I'm happy to announce the release of Simulant 21.06!

Due to me moving home it's a little less feature packed than some releases, but, there's still plenty to see! Without further ado, here's the new shiny!

Support for VQ Compressed Texture Formats

The Dreamcast natively supports a kind of texture compression called VQ compression. It's a remarkably memory efficient way of supplying texture data. Of course, other platforms don't natively support VQ compression in hardware so that makes it tricky to support in a cross-platform way.

In 21.06 we've added support for .dtex files which is the output format of the excellent texconv utility. When loading .dtex files, VQ compressed formats are loaded directly to hardware on the Dreamcast, but decompressed in software on other platforms! This allows you to ship a single compressed image format for use everywhere, with the caveat that decompression will hit loading times (and of course, memory) on non-Dreamcast platforms.

Introduction of the Path Type

Up until now, Simulant has been using the unicode type to deal with file paths. However, paths are not always valid unicode and so should not be stored in a unicode type. Instead Simulant now uses a new Path type that is based on std::string. This will behave more correctly, and also be more efficient.

VertexData and IndexData can now be Shared

Previously each Mesh got its own VertexData instance, and each SubMesh got its own IndexData. This could potentially be very wasteful. Now you can pass a VertexDataPtr or IndexDataPtr during Mesh or SubMesh creation respectively and these can be shared across multiple meshes/submeshes.

Doxygen Documentation Generation

We now have an automated Doxygen build process that generates up-to-date API documentation which you will always be able to find here.

get_platform() is now Global

Previously information on the platform an app was running on was available via the window property. This made little sense, as by definition the platform is global state.

Now in addition to get_app() which was added in the last release, there is now a global get_platform() function that returns a Platform* so you can query information about the system (e.g. how much memory is available etc.)

Materials now Contain Fog Properties

Up until now you could enable fog in some capacity on the stage, this API has been removed in favour of fog being a Material-level property as it should always have been. The additional properties are:

  • s_fog_mode
  • s_fog_density
  • s_fog_start
  • s_fog_end
  • s_fog_colour

Revamped Texture Formats

Texture formats previously didn't allow for different component orders (e.g. BGRA) and some formats were ambiguous. These problems have now been rectified with better texture format naming.

Improvements to Skyboxes

You can now pass TextureFlags when loading skyboxes to have full control over the kind of filtering etc. that takes place.

Added StageNode::link_position

It's a common case that you'd like a stage node to "follow" another node, but without any kind of hierarchical re-parenting. For example, once you've created a skybox, you'd probably like it to stay positioned around your camera. Previously you could use node parenting and the (brittle) StageNode::lock_rotation function, but this has now been replaced with link_position e.g.

skybox->link_position(camera);

To unlink you simply pass nullptr to link_position

Better Sound Buffer Size Calculation

Previously sounds used a constant buffer size, but this could mean that high quality audio could suffer from drop-outs. Now the buffer size is calculated based on the bitrate of the audio.

Renaming of Sound Classes

A little bit of API clean up. Source is now named AudioSource, and SourceInstance is now called PlayingSound. This makes the API much clearer.


That's it! There's the usual scattering of bug fixes and small features but 21.06 is a big leap forward in just a few months!

Simulant 21.03 Released!

It's the end of the first quarter of 2021, and that means another Simulant release!

After the fairly quiet release in December, the time we have a feature packed version for all you lovely game developers!

Cave Demo

Initial PSP Support

It's always been the intention to support as many platforms post-Dreamcast as possible, and supporting the PSP really is a no-brainer when it has such an active homebrew community. 21.03 includes the first steps towards full-featured support for the PSP. PSP builds are running on CI, and some demos are successfully running. There's plenty more to do though, so if you're in the PSP community and want to make PSP support first-class then please get involved!

Huge Reduction in Memory Usage

Stage node memory usage has been reduced by 33% on average, sometimes this can be much more. The node pool is now shared across all stages (which reduces wasted space when using multiple stages) and larger stage node types (e.g. Widgets) have been refactored so that stage node types are approximately equally sized (again, reducing wastage).

Faster Materials, and More Memory Savings

The Material system has been re-written under the hood to reduce memory usage. Material property values are now only stored if they differ from the default material definition, effectively now Materials and MaterialPasses are a delta-diff from the base material which greatly saves memory.

In addition to this, property types are no longer stored in a Variant (which would greatly waste memory, a boolean property would take the same space as a 4x4 matrix!), and Material property accesses have been optimised to improve performance.

Faster .fnt Loading

.FNT font loading has been refactored to be blazingly fast. Previously loading fonts would stall the Dreamcast for a second or two, but now it's near instantaneous!

Input Improvements

You can now check if an input axis was activated or deactivated during the last frame by calling input->axis_was_pressed("...") or input->axis_was_released("..."). This removes some of the boilerplate needed when doing one-off checks for in-game menus, or weapons firing etc.

Improved Fullscreen and Resolution Handling

Simulant now uses SDL's desktop scaling flags if supported. Also the platform classes have gained a native_resolution() function which will tell you what the native resolution of the platform is.

Upgraded Bounce Physics

Simulant is now using the last Bounce physics engine available before it was taken offline. The Simulant community is now maintaining a fork of the project in its community GitLab group, which will be used to fix bugs etc. going forward.

Textures can now be "Flushed" to the Renderer

Previously texture uploads would always happen just before the render pipeline was processed - this was problematic if you were loading a lot of textures into RAM in a single frame. Now textures have a "flush" method which will force the renderer to upload the texture to VRAM and free the memory (if that's the configuration).

Default Textures and Texture Map Toggling

All built-in texture map properties now have a default texture, this differs depending on which map property it is, diffuse_map for example has an all-white texture. This creates consistency across renderers when accessing textures that haven't been explicitly bound.

Also, the s_texturing_enabled material property has been changed to s_textures_enabled and is now a bitmask of enabled texture maps, so you can for example turn on diffuse_map and light_map, but leave normal_map disabled etc.

Threading Fixes

There have been a lot of fixes to the threading subsystem. The Dreamcast platform no-longer uses pthread and instead uses native threading primitives.

Logging Improvements

The old L_ prefixed logging macros have been replaced by S_ prefixed macros which take printf style variadic arguments, placeholders still follow the {0}, {1} format.

Logging in release mode no longer outputs the file and line of the logging statement.

Audio Memory Improvements

Streaming .OGG files no longer maintains the whole file in memory, and instead a persistent file buffer is used.

Special Thanks

Huge thanks to all the contributors this quarter, but particularly to @freakdave who has contributed the most beautiful demo to the samples folder (seen above). Thank you!

Simulant 20.12 Released!

Happy Holidays!

For an early Christmas present, I've just tagged version 20.12 of the Simulant game engine!

It's been a pretty quiet release cycle - there's been a lot going on in the world recently! However, there are still some really neat changes in this release!

Better Coroutines

Coroutines landed a while back, but the API for using them was clunky and unfamiliar. In 20.12 we've added familiarly-named functions to manage coroutines: cr_async, cr_await and cr_yield.

cr_async also now returns a CRPromise<T> which has a convenient then() method for triggering events once the coroutine has completed. This is great for scheduling game logic to run sequentially, and is a bit more elegant than using idle tasks.

Better MS3D Support

MS3D support landed in 20.09, but it wasn't fully compatible with the Dreamcast port and caused unaligned read crashes if you tried to use it there. This has now been fixed and MS3D models can be used on the Dreamcast.

Scene Management Improvements

Firstly, scene management function names have been cleaned up. You can now preload a scene, before activation or, you can preload_in_background to do so in a coroutine. Utilizing the .then() pattern can allow you to preload in the background, then activate a scene once done - which is great for loading screens.

On top of that preload, preload_in_background, and activate accept arbitrary variadic arguments which are accessible in your scene's load method. This allows you to have one scene class, but pass flags to it on activation to alter its state. For example, you could pass the filename to a level file, or enable an "arcade" mode etc.

Bug fixes

There have also been an array of bug fixes, including numerous sound bugs (including fixing garbled stereo sound) and problems with frustum culling!

Simulant 20.09 Released!

We've just tagged the first ever stable release of Simulant: 20.09!

Today marks the start of a regular release cadence for the Simulant project. We'll aim to release Simulant every 3 months. Disruptive changes will be merged at the start of the 3 month period so that by the time of release things should have stablised nicely.

So what's new in Simulant 20.09?

Improved Skeletal Animation!

skeletal animation

The previous alpha release introduced Skeletal Animation. Simulant 20.09 brings manual manipulation of skeletal actors! Want your character to turn its head to follow a target? Now you can simply find the joint you want to manipulate, and go for it!

New Dreamcast Audio API

Previously Simulant used ALdc 1.0. This was an OpenAL implementation for the Dreamcast that did all mixing on the main SH4 processor, before sending audio over to the AICA sound processor.

Not only was this slow and wasteful, but there were a number of bugs that were never resolved. In preparation for Simulant 20.09 the Simulant team has reimplemented ALdc from scratch. Leveraging the AICA directly, and its 64 available channels to provide faster and better audio.

ALdc will continue to improve and gain functionality over the next few months!

Better "alias" API

In the previous Simulant release, you could give assets a name during construction by using the _with_alias suffixed methods. This was a very cumbersome API, and increased the number of methods on the AssetManager unnecessarily.

You can now set the name of an Asset or StageNode using it's set_name(name) method. And if you want to do so inline with construction you can use new_X()->set_name_and_get(name); which returns the object itself.

Finding nodes and assets by name is also much more straightforward. Simply use the find_X(name) methods which can be found on the AssetManager and Stage.

New StageNode::destroy_after Method

Quite often you want to destroy a stage node after a delay. For example, your game might have a missile object that should destroy itself if it's still alive after a number of seconds. This behaviour is now simple! All stage nodes now have a destroy_after(Seconds) method, so now you can fire and forget!

New .ms3d Blender Plugin

As Simulant .ms3d support was being added, we became aware that the .ms3d import/export plugin in Blender had stopped working in recent versions and had been removed from the community plugin tree. To help developers (until Simulant supports a more modern skeletal format) we've written a brand new .ms3d export plugin for Blender.

You can find the plugin in the Simulant project on GitLab.

Bug Fixes and Minor Features!

Along with those new features there are a number of bug fixes and minor changes, including:

  • Fixed a typo in the joystick button enumeration (Thanks @freakdave!)
  • Fixed .equals vs == problem when setting positions, scaling, and rotation
  • Fixed issues with object pooling
  • Made MS3D loading more resilient
  • Fixed a bug where the free list in the object pool would break
  • Added a new_submesh_as_capsule method
  • Added more operator overloads for the Degrees class (thanks @freakdave!)
  • Fixed a number of sound issues
  • Fixed depth issues on UI widgets

What's next?

Things that are lined up for next release include:

  • A complete restructure of the core engine API
  • An upgrade to the Bounce physics engine
  • More audio and performance improvements

Have fun!

Simulant Alpha 4 Released

I just missed tagging Alpha 4 by the end of June, which would've continued the 6 monthly release cycle that I'd organically fallen into. This was largely because I've been pushing some final bug fixes into the release to make it so much better!

And what a release it is, a total of 51 merge requests were merged this cycle! Let's see what they bring!

Skeletal Animation

Skeletal animation has been a glaring missing feature in Simulant for years, but now it's here and ready to go! The first skeletal mesh file format that Simulant supports is Milkshape 3D, but in the next few releases I plan to bring more new formats into the mix.

MS3D Model

Mesh objects that support skeletal animation support both pre-defined animations through the existing KeyFrameAnimated interface, and also manual joint manipulation through the new skeleton API.

Disable Culling Per-Node

Previously there was a poorly implemented flag for disabling culling of actors. Now, you can disable all spatial culling of any stage node by setting its is_cullable property. This is useful for debugging, or if you know that a node will always be visible it can lead to small performance improvements.

Better and Faster Memory Pooling

StageNode pooling was rewritten for Alpha 3, but the resulting code had some deficiencies, particularly around iteration and insertion performance. The next iteration of that pooling has arrived in Alpha 4, bringing huge speed improvements.

Utility Functions for Heightmaps

When loading heightmap meshes from texture data, Simulant has always provided information about the way the heightmap was generated via the stored TerrainData object. TerrainData has gained utility functions to get the exact height at a world coordinate, and to give you the triangle indexes at a world coordinate. These are super useful for placing things on your terrain, or performing ray-intersections.

Additionally, you can now pass a TexturePtr to new_mesh_from_heightmap instead of a file which is great if you're generating the heightmap procedurally.

Coroutines

Simulant now has a basic implementation of Coroutines, and all mutexes throughout the codebase have been removed. Not only do Coroutines provide a simpler model of concurrency, and reduced complexity of the entire codebase, but they've improved performance.

None of the Simulant API is now threadsafe, and Coroutines should be used for all concurrency.

New Threading API

Although Simulant isn't threadsafe, that doesn't mean you won't need threads at all. Simulant now provides a consistent and clean threading API for all platforms for you to use in your own code. This is an alternative to C++'s std::thread which has spotty (or non-existent) implementations on older compilers.

Loads of Bug Fixes and Minor Features

Too many to mention, but here are the hightlights

  • Fixed a bug where particle systems would live longer than they should
  • Fixed bugs in particle system updating
  • CylindricalBillboard and SphericalBillboard behaviours were added
  • Removed usages of deque and stack which hurt performance
  • Simplified the texture API
  • Added a new container for faster render queue insertion and iteration
  • Fix alignment issues in optional<T> that could cause a crash
  • Improved Octree and Quadtree performance by pre-calculating child node indexes
  • Allowed positioning and rotating of Geom's on construction
  • Vertex colours are now loaded from Wavefront .obj files
  • Capped deltatime to avoid spiraling
  • Added support for texture matrix manipulation
  • Improved performance of material properties
  • Improved the performance of the Frustum partitioner
  • Improved the performance of UI widget rendering
  • Widgets can now have render priorities
  • Added custom iterators throughout the codebase
  • Improved the performance of index iteration
  • Removed Window backgrounds which were confusing and brittle
  • Fixed crashes in MD2 loading
  • Renamed RenderSequence to Compositor
  • Improved OSX compatibility
  • Added "force" to digital inputs on virtual axises
  • Fixed parent_is_stage method

... and many many more!

Special Thanks

Special thanks go to Charlotte Koch and David Reichelt for their contributions this cycle!

Simulant Alpha 3 Released

It's been 6 months since the last Alpha release of Simulant and it's now time for another! In fact this 6 monthly cycle has become an unintentional habit that I may as well continue!

So what's new since last time?

Well first let's look at the stats:

 382 files changed, 12986 insertions(+), 7013 deletions(-)

That's a fair amount of code churn! Lots of deletions, lots more insertions, so what to do they add up to?

  • Memory management for manual objects has moved to an improved pool system to reduce allocations and improve performance
  • Brand new hierarchical material property system
  • More consistent object management APIs
  • Added a gprof compatible sampling profiler to the Dreamcast build
  • Made Octree depth configurable in the Geom culler
  • Reduced memory usage of Geoms
  • Added a loose Quadree Geom culler
  • Improved render queue performance
  • Improved render queue ordering sequence
  • Made "nameable" objects consistently use std::string for names, rather than unicode for reduced memory usage
  • Added iterator classes for better and faster iteration of Simulant containers
  • Moved to a new default vertex structure for better Dreamcast performance
  • Update to latest GLdc on the Dreamcast
  • UI widget rendering has been refactored for performance
  • Added support for loading .wav audio files
  • Implemented 3D positional audio
  • Allow setting pitch, gain and reference distance for sound sources
  • Conditionally generate mipmaps on the Dreamcast when possible
  • Improved the performance of MD2 animations
  • Renamed "ask_owner_for_destruction" to "destroy"
  • Standardised on "clean_up" rather than "cleanup" across the API
  • Fixed bugs with shininess in .obj model loading
  • Started moving to a transactional API for asset manipulation
  • Allow linking Pipelines to Scenes
  • Fix wrong RAM usage being displayed in Windows
  • Add a RAM usage graph to the stats panel
  • Huge refactor of particle systems
  • Allow specifying multiple materials for a mesh and selecting them per-Actor (multiple skins)
  • Various controller mapping fixes
  • Roll back to an earlier glibc on the automated builds for more portability
  • Added support for integer packed normals
  • Added support for unsigned byte vertex colours
  • Added more utility functions (e.g. smoothstep)
  • Allow controlling blending when loading meshes from file
  • Improved the speed of font loading
  • Improved the built-in font files
  • Improved the performance of applying staged writes to the partitioner
  • Switched to the frustum partitioner by default (spatial hash is still experimental)
  • Build a debug release of Simulant for the Dreamcast on CI
  • Fixed issues with Camera::unproject
  • Many many other bug fixes and performance enhancements!

Massive massive thanks to @freakdave for his great contributions to this release. And also a shout out to @HaydenKow for generally being a great mentor, and everyone else on the Simulant Discord for generally being awesome!

Introducing Simulant

Merry Christmas! The festive season seems like a good time for an announcement, so here we go!

I'm pleased to announce the Alpha release of the Simulant Game Engine - a new open-source project to bring modern game development flows to older platforms.

Simulant is a portable general-purpose game engine, written in C++. It's aim is to allow writing games for older 3D consoles like the SEGA Dreamcast, as well as modern platforms such as Windows, Linux and Android.

Simulant is built to let you get a game up and running fast! The API is designed to be easy-to-use and to read so that even novice C++ developers can build games and experiment. The simulant command line tool lets you set up a scaffold project, and build, package and test for multiple platforms with a few simple commands.

Simulant requires using Linux as a development OS, but uses cross-compilers and Docker to build your game for other platforms.

The development of Simulant as led to the development of GLdc, a brand new OpenGL implementation for the SEGA Dreamcast, and the fledgling ALdc which hopes to bring OpenAL compatibility to the same platform.

Simulant comes with a bunch of features:

  • Multiple renderers (OpenGL 1.1 and OpenGL 2.1)
  • High-level Scene management
  • Powerful material system, supporting GLSL on GL 2.x
  • Hierarchical scene building
  • Scriptable particle system (custom JSON format)
  • Support for loading .obj and .md2 meshes, as well as Tiled .tmx files
  • Complex configurable rendering pipeline
  • Easy-to-use API
  • Automatic memory management of game assets
  • Automatic level-of-detail mesh selection
  • Combination Spatial hash and Octree based culling systems
  • Built-in realistic Newtonian physics engine
  • Entity behaviour component system
  • UI widget rendering system
  • Built-in helpers for scrollable backgrounds, skyboxes and animated sprites
  • OpenAL powered audio
  • There's probably more I've forgotten...

And if that isn't enough, the whole thing is controllable from a simple command-line management command, which allows you to bootstrap projects, build them for multiple platforms, run unit tests, and package your game for Linux (flatpak) and Dreamcast (.CDI). Windows installer support is coming soon!

You don't even have to compile the game engine yourself, just install the management command and it will download pre-compiled game engine libraries which are generated automatically via a complex build system!

Simulant is built to support multiple OpenGL renderers. Currently there are OpenGL 1.1 and OpenGL 2.1 renderers and a GLES 2 renderer will happen soon. As for platforms:

  • Linux: Packaging needs work. Working Flatpak packages are built with the "package" command though.
  • Windows: Executables are buildable using the built-in cross-compiling, there is no installer generation (packaging) yet, although when it lands it will use NSIS. If you want to compile manually + natively on Windows, then building on VC++ should work, it may require some minor patches.
  • Android: An Android build has worked in the past, a long time ago, but it bitrotted away. It's about 80% restored, but doesn't work yet
  • OSX: TravisCI is building for OSX on the GitHub mirror, although it's not being used for anything except checking that nothing broke. You'll have to build OSX projects manually on OSX itself for now.
  • Dreamcast: Builds and generates a bootable .cdi image. Romdisk support is high priority, as is VMU file loading/saving.

Getting Started

Providing you have a Linux installation available (preferably Fedora 28 or 29), getting up and running should be easy. Head on over to the tutorial!

Status

Simulant is currently at Alpha stage. This means the codebase is unstable, and the API is subject to change. If you're using Simulant to build a game, make sure you update frequently, and file bugs and submit patches to help improve things.

Keep an eye on the Simulant Discord chat, and issue tracker.

Get Involved!

Simulant has so far been pretty much a one-man project, for it to reach its potential it needs other contributors. If you want to help out, hit the Discord group and come join the community! Here are some useful links for getting started!

And if you don't have the time to contribute, but want to support my work then my patreon is here

Caveats

Simulant is very much under development, so pay attention to the following caveats:

  • Nothing is stable. APIs will change!
  • The Dreamcast support is currently missing audio, this is work in progress
  • The Dreamcast port is missing built-in support for VMU storage, rom disks and CD audio. You can use native KallistiOS SDK for some of this functionality
  • Work is ongoing to support texconv's texture format for Dreamcast native textures
  • Baseline memory usage is still higher than I'd like
  • The material system is due to change soon to be switched for a more readable JSON based system.
  • The current default OpenGL 2.x shader has a bug which overbrightens some models
  • Thread-safety is a bit hit and miss
  • Some of the APIs are a first-pass and have bugs or inconsistencies
  • On the GL 2.x renderer, render batching (performance) needs improving

Licensing

Simulant is released under the LGPL (with patches accepted under dual LGPL+MIT licensing), there are a number of reasons for this, but it does mean that:

  • If you make and distribute changes to Simulant, you must make those changes available under the LGPL.
  • If your game statically links to Simulant, you must release your app's source code under an LGPL compatible license, or buy a commercial license for Simulant.

For more information, take a look at the licensing page