April Development Update!

Most of my focus is to get Sojour ported to 64 bit and running on a .net 10 platform.

If I pull this off, you get extra performance and I will get access to additional tools that will allow me to do things with Sojour that I have always wanted to do!

The big hold up has been Ionian, Sojour’s custom graphics engine. I wrote it a long time ago for another project of mine called Ancient Armies. It’s not a bad engine, but it is 32 bit and it can only render to one window at a time.

A few posts back I showed off some of my work with Dorian – Ionian’s replacement.

What was probably not made too clear, is that it was a POC:

The original POC! Best viewed on You-Tube to see it in 4k!

What’s a POC?

A POC is a Proof Of Concept. The idea being that for complex tasks – like a graphics engine – you knock up a quick and dirty system purely as a learning exercise. That way when you work on the real thing, you will have a lot more relevant experience under your belt.

The key point of a POC is that you learn what you need to learn, de-risk what needs de-risking and then you effectively throw it away. The lessons learned are then applied to creation of the full enterprise system.

For the last month or so I have been doing just this – working on the real Dorian Engine and not the POC.

The actual engine is way more powerful, expressive and scalable when compared to the POC. It doesn’t look as good – at least not yet – simply because it is at an earlier point in its life cycle.

The biggest difference between Dorian and the POC is that Dorian uses an enterprise grade architecture known as ECS (Entities, Components & Systems).

I think it would be fair to say that ECS takes a bit of getting used to. However, it is massively scalable, simple to use and expressive in ways that are only limited by your own imagination.

I should probably warn you that the next section of this post is going to take the geek factor up to 100! Those of a nervous disposition might well want to bail out about now 😊 (I need to go technical in order to show you the main highlights of Dorian’s ECS system.)

Dorian is now at a point where its architecture is all in place – all I need to do is keep adding features to it – which the new architecture makes exceedingly easy to do.

Here is a short video of me testing three different cameras all pointed at the same world using Dorian. Each window is showing exactly the same thing but from three different perspectives.

This is the real Dorian engine in action. You can see me showing off dynamic window resizing and me trying my best to upset the chase camera, but to no avail! Still work in progress! Best viewed on You-Tube to see it in 4k. (It’s a little dark and flat because YouTube converted a HDR recording to an SDR recording!)

What the video shows are three dynamically resizable windows (Ionian in Sojour can only render to a single window) where each window is pointed at the same world. Dorian allows a lot of flexibility here. You could for example have a few windows rendering world number 1 and another few rendering world number 2 and so forth.

The left hand pane in the video shows the cubes’ actual movement because the camera is not moving. The ones on the right show things from the perspective of the treasure chest cube – one is a follow camera, the other is a first person camera.

In a standard engine like Ionian, coding the animation of all the cubes and the advanced camera behaviours such as the chase camera would have been quite difficult. But, with Dorian’s ECS system it is almost trivial.

What is ECS precisely?

It’s a system where you have Entities and that these entities can represent anything – cameras, models, sound, AI, animations, environments – absolutely anything you can think of.

The key concept of ECS is that they are all treated the same.

The way it works is that the entities are just an Id and that’s it!

Id’s alone don’t do much. However, ECS allows you to dynamically attach (or detach) Components to any entity and these components contain just data. The idea being that if your entity needs to store some specific data, you just attach the appropriate component to it that can store that specific data.

Ok, so you now have entities with data. How is that useful?

Well, the next thing you can do is attach or detach behavioural tags to an entity. Systems within Dorian look out for these tags and operate on the entities that have them using the data stored in the attached components. (I told you we were getting technical!)

This makes the engine very simple to use and incredibly expressive. If you want something to behave in a certain way, just attach the appropriate tag! And that’s it. Very, very simple, but very very powerful.

I don’t normally show my code because it is closed source, but I will make an exception here so that you can see how clean and easy Dorian is to work with – please bear in mind these are very early days!

First up initialisation:

This is how you initialise Dorian – Pretty simple – even for a multi-window, multi-world app!

Dorian is incredibly flexible. Rather than offering a fixed rendering pipeline, it allows the caller to precisely define their own rendering pipeline and they can create as many as they need – though in this example I use the same pipeline for all three windows.

This means that developers can precisely pick what they need to go into their pipeline and they can precisely order it how they want. They can even add their own custom pipeline systems – they are not constrained by what Dorian provides.

It’s flexible in that if I wanted reflections for instance, I could just dynamically add a ReflectionsCubeMapRenderPass and the whole thing would just work!

The other thing Dorian provides that neither Ionian nor the POC offer are simulation (not shown) and animation pipelines. Both of these run independently of the rendering pipelines and are just as configurable:

Setting up an animation pipeline and making camera 2 follow the treasure cube!

The code above sets up an animation pipeline precisely the way I want it.

One of the features I added to it is the ability to process ‘Follow’ behaviour – that is to have one entity follow another. I do this by adding a FollowTarget system to the animation pipeline.

This system will be querying Dorian’s ECS system for the relevant entities and then it will act upon them.

For camera 2, we use the FollowTarget system by attaching a ‘Follow’ component to the camera. I have attached this component to the camera as I want the camera to obtain the additional parameters it needs to allow it to follow another entity (the camera itself is an entity)

Finally, the last line adds a behavioural tag to the camera which invokes the follow system for this camera.

That’s it! That’s all the coder has to do to make any entity in Dorian follow any other entity, no matter how complex the movements. It makes the system incredibly easy to use.

If you want the camera to stop following, just remove the tag. You could even change what it’s following and do all of this dynamically.

The beauty of the system is that each entity can have as many behaviours as you want and that these behaviours can be dynamically attached or detached whenever you want and that the same behaviours can be applied to any entity.

For example, you could pretty much use the same code to make one model follow another…

Here is another example of Dorian’s ECS system in action:

A few lines of code to completely animate a cube!

Here we have another entity, this time the cube you see floating in the demo with the big smiley face.

Once more, we attach a data component to give the entity (the smiley cube) the additional parameters it needs to support animations.

Next, we tag it with the IsAnimatedSinsoidally tag to make it rotate and move. That is all I need to do!

If I want the cube to stop moving I remove the tag.

To top it off, that particular animation is a custom one that I added as a developer using Dorian (as opposed to being the developer coding Dorian).

Dorian allows you to add custom Systems, Tags and Components, so you are not limited by what Dorian can do out of the box.

Dorian is an entity based system, so I could just as easily tag a camera with the same tag as above and have the camera automatically move around like the cube! No additional code required.

It’s this feature that makes Dorian so expressive and so powerful.

Finally, one more code example, but this time it is a structural connection:

Three lines of code to create a camera and turn it into a first person camera.

Dorian allows you to connect (or disconnect) any entity to any other entity! Here it happens to be a camera to a cube model, but that’s just a coincidence.

I could have, for example, connected one of the cubes to another cube! (everything in Dorian is an entity) If that other cube was the parent, the cube we just connected would automatically move along with it. That is the expressive power of Dorian.

Dorian also features its own querying system to allow a developer to easily get at any type of entity that they want.

For example, maybe they want Dorian to return all entities with a Follow component, marked with an IsFollowing behavioural flag and that is in possession of the matrices and vectors to position it in space. This is all you would need to do:

Dorian’s query system in action!

It is an odd architecture to work with until you get used to it.

For example in Ionian and in the POC you had an actual camera class, whereas Dorian doesn’t have cameras. It just has entities that happen to have a camera tag and a world transform component attached to it and that’s it. Together this dynamic composition makes a camera – along with the associated system to operate on its data.

I know this post won’t make a lot sense to most people, but hopefully it gets across two things:

Firstly, I’m still hard at work!

And secondly, that what I’m creating – Dorian – is something of an architectural marvel. It will be the jewel in Sojour’s crown.

Dorian will allow Sojour to have multiple map panes open and visible at the same time. You could even use it to send a ‘players’ map to another monitor when using Sojour as a GM assistant.

The possibilities are endless!

That’s enough from me.

Have Fun!

RobP

Sojour 1.2.155.0 has been released!

I’ll start by saying that this is NOT the custom folders release. Work is still ongoing for that release, but I do have a video of it in action!

Instead, this release is focused on bug fixing and maintenance that addresses the following issues:

RPG-396 When Sojour crashes (on load), we should not be overwriting the main save files: This is an important one. I have had 3 reports over the last year of customer’s save games being corrupted.

When I examined their saved games, it looked like the save files had become partial save files. I finally traced a potential use-case where this can occur…

There are occasions where Sojour could crash during loading resulting in incomplete data being resident in memory. The global exception handler would then try and save that data resulting in partially complete saved files.

This will no longer happen. In addition, I have changed the code for closing down Sojour post crash so that it more reliably closes its process down.

RPG-397 Sojour shouldn’t crash if there are missing data directories on load. A week or two back I had a customer report that their Sojour game was crashing during loading and there was nothing they could do.

On investigation, I discovered that some of the customer’s data folders were missing. This upset Sojour and caused it to crash.

Sojour is now a lot more tolerant with regard to missing folders or data. In addition, if a crash is detected whilst loading, Sojour will now offer the option to pick a different data directory, restore from a back up, or simply exit:

The new exception handler for failed loading! (Click the image to see a larger version)

RPG-399 Sojour crashing when dragging character to map with journal open. This was an odd one in that the investigation had found some corrupt internal data within the customer’s save file which, alas, I hadn’t been able to reproduce.

This corrupt data was centred around token characteristics. All token characteristics code has now been updated to be more fault tolerant.

RPG-400 Adding or editing a map-link with no campaign selected crashes Sojour. Sojour used to use the assets browser to get the current campaign or ruleset. The flaw with this approach is that if a user selects a different campaign, or no campaign at all, it can lead to Sojour having problems.

This code has been entirely re-written and all places that used to rely on the assets browser for the active ruleset or campaign, no longer do so, and instead, use the updated code.

RPG-401 Adding or editing a map-link when the map is set to show all, doesn’t show them! This is a minor issue where adding or editing a map-link would result it in not respecting the current map’s Show Map Links option. This has now been fixed!

Work has been slowed down a little by the fact that Sojour currently has three work streams associated with it:

The three main work streams / branches!

Having three streams of parallel work means that any issues I find in one of them has to be merged into the others. This is normally pretty easy using my source control system.

However, the fly in the ointment is that the Custom Folders branch sports a radically different UI architecture from the other two branches, which means that some fixes have to be hand coded as opposed to merged!

Normally I try to work on one thing at a time, but I soon realised that if I stayed on the calendar work, my customers would see very little new from me as that work is such a large undertaking.

Custom folders sprung up as a result of many customer requests and of seeing Lord Gwydion struggle with his data during the live streams. As with most things software related, I had thought it would be a quick and easy update, but it has turned out to be a little more complex. Hopefully the video above will provide ample evidence that we are headed the right way.

Finally we have the main branch where all the hot-fixes and high priority changes go.

My end game is to get back to one branch again, but this is predicated on me delivering the Mk2 Calendar and Custom Folders functionality! 🙂

That’s it for this post!

Have Fun!

RobP