Terrain Editor

Info

Project Type: Godot Application

Project Timeframe: 2 Months, 2025

Sara/terrain-editor

Product Overview

A prototype for a node-based terrain editor. In my time working with game editors, I've grown to rather dislike the standard bitmap-based terrain sculpting tools. In my experience working with them to any level of detail rapidly becomes an exercise in enduring frustration. So the goal for this tool was to explore a more modular approach to terrain editing. Something that could give the user more control to create more interesting terrains, faster. To do this, I took inspiration from vector graphics, as well as CSG (Constructive Solid Geometry) modeling. Which both have one thing in common: they are "non-destructive".

Postmortem

The initial prototyping phase went really smoothly. Generating basic terrain meshes is easy enough that the first working version was down in a week or so. From there came the challenges.

In testing this with the target user group, I got some common feedback: "This should be built into the editor, having it separate makes it difficult to work with" and "I'd like to be able to see real time what's being changed."

The first one was off the table (for now) due to assignment requirements (a standalone executable). But the latter was mainly a matter of optimisation. At this point the process of generating terrains was entirely synchronous. Making it really really slow. Which was fine since I was only updating the actual terrain whenever the users stops moving things. But that stretches the iteration loop in a way that designers would rather not deal with (constantly trial-and-erroring placements of mountains can be a bit tedious). So I would have to optimise the terrain generation.

I'd intentionally designed the data and ownership rules to enable thread-safety, but not worked out an exact parallelisation strategy. As I was trying to get a working version first. So from this point on most of my time was split between implementing the UI controls, and optimising as much as I could. First optimisation was, as mentioned, basic multi-threading.

There's also more subtle option. The users did not need to see a full-detail version of the terrain, just a quick preview of what changed. So I added LOD generation, and started generating LOD models separately from each-other. Combining this with a biased task scheduler, which would prioritise faster, high LOD levels first, meant that I could freely issue rebuilds every frame. Which would process the lower detail models at a pace high enough to give immediate feedback.

From there I had enough time to think about some stretch goal features. In particular I wanted to implement "scriptable terrain". The ability for designers, using godot's existing scripting tools, design terrain generation algorithms. Which technically could be used to facilitate procedural content, but the design of the system already allowed placing mountains procedurally if one wanted to. The main goal is to "close the loop" for designers. To enable designers to prototype and implement custom terrain modifiers, in a way that is designed to avoid creating dependencies and complex code structures.

For this prototype application, I decided to implement this using godot's Expression objects. Which provide an interface for parsing and executing simple math expressions. Expressions can be passed a collection of values and objects, by name when parsed, and by value when executed, and they evaluate to some dynamically typed object (Variant). In the way I used them, they are passed the information unique to the primitive type they are attached to, and some allowed to use any static maths functions. Giving them nearly unlimited customisability.