The many faces of Janus

When I typed in that title I wasn’t intentionally alluding to Janus, the Roman god. But it’s cool nonetheless.

I’ve been developing Janus for seven or so years, and I’ve faced, time and time again, the difficulty in presenting the Janus in a way that satisfies me – because I think it’s a good concept, it makes it even more difficult.

In my previous post about Dynamic Mesh Combining, and my recent re-vamping PSAT rendering I’ve been reminded of how cool coding ventures (from my point of view) have been dwarfed up by the pressure to promote Janus as a mainstream product, which presents the difficulty of consolidating the features that make up Janus into something that most LW users can understand and appreciate. And thus, I laboured two weeks on writing and creating an overview in the hopes that I have explained in a little bit better this time.

But this didn’t change the fact that there are a lot of stuff in Janus that’s difficult to present. On one hand you have For Loops, and on another you have Dynamic Mesh Combining; there is PSAT rendering, plugin support, buffers support, the proxy system, search-and-replace functionality (in object replacement, and throughout the system), the script system, the offline method, etc. Then you have these strange little terms like ‘composite command types’, which, if you were a Janus user, would make more sense – though it is most probable that even Janus users don’t touch it.

It’s though I’ve put in so much functionality that I wanted to have because I didn’t want to run another script to do it for me. One may venture to consolidate these features into a superlative blurb that it has ‘everything’. It doesn’t have everything, but it has a whole lot that no one knows about.

For Loops in Janus

In the recent 1.7 release of Janus I’ve implemented For Loops, which is a way to get a looping construct in the Janus context. It’s rather interesting, and it all came because a prospective (Janus) client emailed me one day asking me if it was possible to procedurally tell Janus to replace objects in a specific directory. There was none at the time, and the solution to that was to either to create render passes dynamically via definition files, or use composite command types. He was happy enough for such a solution. But for my part I felt things could be done better: it was still not procedural insofar as the generation of the data strings was external to Janus: what I wanted to do was get something procedural so that extra scripting was not necessary to do these sort of things.

Enter For Loops, which are represented as subcommands. For Loops tell Janus to ‘recycle’ the render pass (similar to what composite command types already do). In For Loop ‘recycling’ the render pass is internally duplicated; this duplicate passes through a string filter and replaces variable names which are a specific subset for the given For Loop. This contextualises the data that is being accessed; if the loop is around a directory, for example, then you can’t use the variable to get file line information, etc. However, being a construct, they do share some data, such as the iterator; perhaps more can be added in the future.

The prospective client didn’t end up getting Janus, though, as it often happens. But the great thing about it is his question sparked a good idea in my brain. It may also have been through my exposure with Houdini and its Wedge ROP that I’ve implemented it the way I have. These emails from prospecting clients was the root of another less-known feature of Janus called Dynamic Mesh Combining, which combines two or more mesh items into one and it does so during breakout so that the master scene is not modified in any way. Dynamic Mesh Combining came because a person asked me how to prevent shadows from being cast by separate shadow catcher. The only solution to his specific problem was to combine all of his shadow catching objects into one and then turn the Self Shadow render flag off. Because combining meshes is a tedious task, why not implement it?

Janus 1.7

I’ve just released Janus 1.7 which is a major update since a long time.

This cycle started when Mikael Burman, a Technical Supervisor working at Ubisoft Massive looked for a feature where Janus could break out passes without loading the scene in. Well, as it turns out, more than seven years ago, I was wishing that very same feature. Back then, however, the engine wasn’t mature enough; there were too many things to address, and the feature itself was a daunting task which, I had thought then, required an extended development. This feature was called the ‘offline method’; offline denotes that the scene file is not loaded into memory, but that the file will be parsed directly by Janus without pre-processing. I don’t know if this is Janus’s claim to fame (because Janus is not really that popular), but I  don’t know of any other render layer offering that can do that.

Had I attempted to do this back when I wanted it to, I very much think it would have taken me at least three times longer to do, and the coding wouldn’t probably be as clean that I could build a lot of future development on top of it. I credit the relatively slow and deliberate updates that led up to 1.6 with the robust base that I built the offline method on.

Janus’s breakout engine has two processing phases. The first phase is scene pre-processing, which prepares all objects for scene parsing; in this phase the items are ‘tagged’ with their own particular settings based on final evaluation of that pass. Key Layout functions are employed here which help in exporting shader-based overrides, and other peculiar tools such as mesh combine (combining separate meshes into one object during breakout).

The second phase is scene parsing, which opens the scene file and starts parsing the scene out, line-by-line, looking for keywords and tags, and dumping it to another scene – the breakout scene – with the data modified.

In the offline method, the second phase was generally left untouched, except perhaps for some additions to new tags that were related to the offline method that needed to be considered. It was actually the first phase that was particular different. In fact, the engine’s first phase is, for the most part, bypassed when the offline method is being used. Some of the code was still used, of course, because I couldn’t possibly think of changing the main ‘trunk’ procedures. I changed some of the called functions to imitate what was already going on in the ‘online’ method.

But this didn’t change the very base limitation of not being able to deal with shader-based overrides and dynamic mesh combination. Of course, these are actually possible, but it entails a lot more work. While I have some functions designed to write shader-based overrides directly into .lwos, my suite is not comprehensive enough for what is required. And dynamic mesh combination is a bit further away from my reach because I don’t have any code pertaining to handling .lwo mesh data.

I’m not sure if it’s worth the time, as well.

Lastly, there are still some things that can be addressed in the offline method. One disclaimed limitation is the fact that once you create your groupings in Janus, you cannot change them when the scene is unloaded, and the user is working in the offline method. This is because the groupings have been tagged into the items, and this used the parenting information from Layout to get those items tagged correctly. Perhaps there is a way to re-assemble the hierarchy internally when the the file is loaded as offline so that groupings can be changed around. It is a bag of bugs, I’m sure, but maybe it can be done on the side.

At any rate, I’m still busy with other things non-technical in nature. Truth be told, at this point I’m just more eager to use Janus for the stuff I’m doing than coding it.