Back in 2023 I was spending a lot of time in the Outer Wilds community, having just completed the masterpiece of a game. In the game, you uncover the secrets of the Nomai, a species long dead, by using your translator tool to read their long forgotten and recently re-learned language.

A wall with curves of Nomai text written on it. The translator tool is equipped and translates one of the segments.

This language works a lot like modern conversation threads, and is written in curves, each attached to a previous conversation piece. Each piece is usually written by a different author. In the game, their language is not real and cannot be interpreted outside the translator tool. The community, however, has created multiple writing systems that mimic the look of the system found in game.

A photo of a paper with the original instructions on how to write and read their interpretation of the Nomai text.

One such writing system was created by a Reddit user named 36CornDogs, who created a phonetic writing system that visually mimicked the in-game Nomai spirals. It used a phonetic translation method where words were converted based on how they sound rather than a direct alphabet substitution. In my opinion, the design was visually much nicer than others I've seen so far. Seeing how I had also just watched the incredible video "The beauty of Bezier curves", I took this as an opportunity to automate the process of generating such curves, so anyone could generate their own messages.

It took me a while to understand all the rules and special cases, but I eventually got it. I jumped right into it and spent about a weekend building the parser and the rendering engine. The pipeline operates in several distinct sequential phases, which I will illustrate below.

First, the input text is split into phonemes using the CMU Pronouncing Dictionary. If a word does not exist in the dictionary the system splits it up into sub-tokens and combines them back together. These phonemes are then mapped to specific Nomai shapes like lines, bends, squares, and hexagons. I created these shapes individually, so that I could create some visual variety, and to be able to define valid attachment points to other shapes, which will become relevant later.

All of the different shapes that can be drawn by the renderer, for the different phonemes supported in the system.

I will be using the text I have 3287 apples but I wish I had 3288. My friend has an extra apple you can have. to illustrate this. It has two sentences, meaning each sentence will become an individual curve later that will be combined at the end. These are the phonemes that are created from this input:

AY1 | HH, AE1, V | AE1, P, AH0, L, Z | B, AH1, T | AY1 | W, IH1, SH | AY1 | HH, AE1, D
M, AY1 | F, R, EH1, N, D | HH, AE1, Z | HH, AH0, Z | AE1, N | AH0, N | EH1, K, S, T, R, AH0 | AE1, P, AH0, L | Y, UW1 | K, AE1, N | K, AH0, N | HH, AE1, V

I created a manual mapping table using which these inputs are converted into the ones that the writing system supports.

ay | h, aah, v | aah, p, uh, l, z | b, uh, t | ay | w, ih, sh | ay | h, aah, d | m, ay
f, r, eh, n, d | h, aah, z | aah, n | eh, k, s, t, r, uh | aah, p, uh, l | y, oo | k, aah, n | h, aah, v

Because Corn's system for Nomai writing is not drawn linearly, but rather branches out across up to three different lanes, the logic will then arrange these shapes into a branching node tree structure. A single word dot can have three lines coming out of it representing a consonant, a vowel, and a number.

ROOT [V W]
  V [ay => SQUARE SQUARE SQUARE_SQUARE]

  ROOT [C]
    C [h => HEXAGON HEXAGON HEXAGON_HEXAGON]
      V [aah => SQUARE LINE LINE_SQUARE]
      C [v => HEXAGON_HEXAGON]

        ROOT [V C N]
          V [aah => SQUARE LINE LINE_SQUARE]
          N [3 => OCTAGON_OCTAGON]
            N [2 => HEXAGON_HEXAGON]
...

To make the distribution and mathematical transformations later simpler, the algorithm first draws all the letter shapes in a straight line on a regular grid.

Step one of the rendering process showing the shapes laid out in a straight line on a grid with three lanes.

Only after the spacing is calculated does the system pick a Bezier curve from a set of pre-defined curves depending on the length of the text. The curve is used to span a coordinate system which translates the straight shapes onto the spiral. I always found this to be a mathematically very beautiful operation.

Step two showing the shapes transformed and mapped onto a curved Bezier coordinate system.

Now comes connecting the letter symbols. Since the space can get pretty tight on a spiral layout, the connecting lines easily intersect with other shapes which ruins the aesthetic. I implemented several algorithms to either find a clean connection point by shortest distance, and later a brute force approach for the collision detection and prevention.

Step three is connecting the individual symbols on the curved line.

If it detects an overlap it simply discards the image and reruns all previous steps up to ten times with a different random seed. It then evaluates the iterations and picks the image with the cleanest layout. The same process happens again with the remaining sentence. The algorithm then finds a fitting spot to attach the next curve to, and will rotate it a bit to make it look like in the game.

The final steps handle the composite styling. Using pure Java AWT graphics the image is overlaid with copies of itself that have been recolored, dilated, and blurred to create a glowing effect. It is then placed onto a pre-defined background like the Quantum Moon or a Nomai ruin wall.

Step 4 is to apply some thickness to the writing. Step 5 is to add a nice glow effect to finish the writing off.
The final generated Nomai text placed onto a rocky wall background.

And there we go! Your own Nomai text in six simple steps. You can try out all of this by checking out the instructions on the repository. I made them so clear that anyone can follow them, even with no programming knowledge.

The best way to share this tool with the community was to build a Reddit bot, so that I could create an interactive post on which people could try this out. Users could comment their desired text and background style and the bot would reply with a translated image. I hosted the bot locally on my PC and it took about five seconds to generate a single image. Over fifty people tried it out in the subreddit requesting everything from lore quotes to personal messages. I kept the bot online for two or three days before shutting it down because I did not want my machine running indefinitely. It was a pretty big success for the project and brought a lot of joy to the people who interacted with it.

A screenshot of the Reddit bot automatically replying to a user with a generated Nomai translation for 'I hope you won’t mind if I think of you as a friend'.

This project remains one of my most popular repositories on GitHub. People all over the world still star the repository and use the tool for their own projects or other use-cases, such as just recently where a Reddit user posted about their Outer Wilds themed birthday. They used the generator to write a custom Nomai message as part of the gift, which is just so nice to see.