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.


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!