December 2020
They say there is no prouder moment for a parent than when their child takes the first steps. Behold!
First 3D avatar in Nim.
This scene was the sum of two new modules: (1) the physics engine and (2) an entity component system (ECS). The first module established gravity in the scene, allowing the avatar to "fall" to the floor. The second module enabled navigation using the mouse.
The physics module wrapped AMD's FEMFX library which was a newly opensourced project at the time. I considered going with Nvidia's PhysX library initially, but after much research I concluded that I should go with a smaller library that could be easily contributed to if I ever needed to add a custom feature.
The ECS implementation -- dubbed SECS for Simple ECS -- was inspired by skypjack's amazing series on ECS. I had made the decision to create a pure Nim implementation instead of wrapping his library to better take advantage of Nim's language features.
It was during the development of SECS that I conceptualized the engine's "implicit event system". The idea was that user-defined systems should be able to notify each other of mutations to components without explicitly invoking any callback functions.
To illustrate, take two systems defined in the files inputs.nim
and players.nim
. An "event" in this context is the mutation of a component handled by a system, e.g. a Position
component handled by the inputs
system. This event could be seen by another system that also handles the Position
component -- e.g. the players
system -- simply by defining a callback onMutate
with a Position
parameter.
# inputs.nim: system of inputs
proc onUpdate() =
inputEntity.position = canvas.get3DMouseCoords() # get mouse coordinates
# players.nim: system of players
proc onMutate(position) = # automatically called from 'inputs.nim'
playerEntity.position = position # move player to new location
The implementation of ECS in the engine allowed me to scale its functionality by enabling loose coupling between subsystems such as physics and rendering.
It seemed that all that was needed from this point on was to implement the other core subsystems of the engine.