About 3 years ago, I started my journey of building a procedural, graph-based terrain generator - Vista - for Unity engine. The development went well with the first release on March 1, 2022.
Up until today, the asset has gathered thousands of users love to use it in every of their projects and share their ideas on Discord. Many of them asked me if I can expand the scope of Vista to support other development platforms such as Unreal or Godot?
Hmm, why not? Let's do it!
Define the scope of the terrain generator
Many of you have known that there is only one person behind Pinwheel Studio, it's me. At least it's true at the moment I write this post.
It is critical to choose an achievable scope for the project to be successful. After lots of thinking, I decided to make Vista 2 as:
A standalone app for Windows (Mac & Linux are on the list for future)
Can be easily integrated with popular 3D softwares (Unity, Unreal, Godot, Blender, etc.)
Select the technologies
Since it is a 3D terrain generator software, I use C++ and DirectX 11 to build its core & editor.
This is a real challenge for me! After years of working with Unity & C#, I forgot nearly everything about C++. My knowledge about "real DirectX" is also an empty page.
Anyway, I'm getting used to them really quick :)
For someone who's curious, here's the Youtube channel where I learnt from.
What we have so far?
The development has been started for a while before this post. Because I'm building the foundation of the whole project in the long run, I've done many complete "destroy & rebuild" to do things the correct way from the beginning!
The app was built in Visual Studio 2019, where it is splitted into 3 main projects:
Vista Runtime: contains core components that handle logical graph creation & execution.
Vista Editor: provide intuitive user interface for graph authoring & files.
Vista Tests: Unit testing to ensure the highest code quality as possible.
There are also other side projects that aid the development process, we will discuss about them in latter posts.
The core runtime is packed into a single DLL that will be loaded when the app starts.
Most of the code was ported from the C# version, not a big deal.
But, we've got a problem!
The fact that softwares can be built with different version of C++ compilers, that can have different ways of handling data layout & structure. This incompatibility can lead to data corruption, making the DLL unusable.
For example: if we load the DLL from Unreal editor and call a function from it, it may fail because we can't guarantee that Unreal & the DLL are built using the same compiler.
This is not a problem with the Vista Editor because it is in the same solution with its runtime, which mean they are built with the same compiler version.
To tackle that, I only export a set of free functions in C-style naming (extern "C"), with their signatures only use raw pointers and primitive types (remove all namespaces and user defined types from the interface). This will enable maximum compatibility between platforms.
The Vista Editor provides graphical user interface for graph editing and preview, as well as handling file system, here's how it looks like:
The initial layout is similar to the current version of Vista asset, but now you can reposition/dock subwindows the way you want. It's truly your workspace now.
I don't write the GUI code entirely, but instead use a library called Dear ImGUI. It's a single pass immediate GUI library written in C++ that supports many platforms, including Win32 and DirectX. Bravo to the author! 👏
In addition to the main window, I also have a console to output debug information:
Perhaps this console will be removed in the final product. Information will be displayed somewhere in the main window instead.
To ensure the highest code quality and detect bugs early when the development goes further, I use Google Test library for the app:
I'm already a fan of unit tests because of its benefits:
I can quickly setup the environment to run a function without messing with GUI, this can save me lots of time!
I can verify that a change in one place won't break anything in other places.
I can evaluate the clarity of my API design (function signatures, return type, error handling, etc.)
And many more...
And that's the start of a new journey in my career. Unfamiliar environment, unfamiliar technologies, unfamiliar methodologies, a complete new chapter!
But I think the hardest part are not those "unfamiliar things" above, but your "will" and "dedication" for the job. I've won 50% of the game because after years, I finally step out of my confort zone with Unity and keep pushing myself to the new skies.
I hope this can be your inspiration to kick start your own journey!