Streaming World – Part 1

For the last week or so, I’ve been knuckling down on creating a fully streaming overworld in Daggerfall Tools for Unity. If you’re not sure what I aim to accomplish, here’s a brief overview of how I want this to work from the Unity Editor.

  1. Setup DaggerfallUnity singleton as normal.
  2. Add prefab StreamingWorld into scene hierarchy.
  3. Add prefab PlayerAdvanced into scene hierarchy.
  4. Set player virtual position in PlayerGPS and virtual time in WorldTime.
  5. Hit Play and explore entire Illiac Bay, entering any building, any dungeon, and experiencing full day/night cycle with climate and seasons.

In many ways, I’m already very close to this goal. The tools have procedural loading of cities and dungeons, virtual time and space, climates and seasons, day and night, interiors and exteriors, and more. What’s missing is a full terrain setup and intelligent loading/unloading of blocks as player traverses the world.

You can probably imagine what a huge job this is. While I am working very quickly towards this goal, it will be another 3-4 weeks before it all comes together in a state that I’m happy with. To maintain regular updates over that time, I will split news on my progress over multiple articles.

In this first article, let’s take a look at Daggerfall’s height map and how it translates into useful terrain.

Similar to the 1000×500 maps found in POLITIC.PAK and CLIMATE.PAK, Daggerfall also stores a 1000×500 elevation map in WOODS.WLD. Here’s a grayscale dump of that data (click for full size).

HeightmapFull

You can also see a nice false-colour version of this map here.

Like most height maps, dark areas are low elevations (values of 2 or less are water) and bright areas are high elevations. Daggerfall also stores a noise map in WOODS.WLD, which I’m not going to talk about as I plan to use a better method of noise generation.

To better understand the scale of this data, here is a zoomed-in 10×8 sample grabbed from along the northern coastline (I have brightened image so individual points are easier to make out). Each of the below squares represents a single “map pixel”, equivalent to one full-sized city like Daggerfall or Wayrest. If you measure the time it takes to cross from one side of Wayrest to the other, it would take 10x that amount of time to cross the below sample west-to-east.

HeightmapZoomOriginal

Once the scale is understood, it becomes apparent there’s not much height data here considering the actual size of terrain represented. This is why Daggerfall’s terrain is mostly flat. It’s stretching a single height sample over a huge area then modulating that with a little noise. Sometimes you can fluke a nice bit of terrain, but it’s very rare. On the whole, the overworld in Daggerfall is very flat and bland.

To improve this situation, there needs to exist more data in between height samples above. This new data must be quick to sample, use very little memory, and create a continuous grade between samples with plenty of interesting variety. To accomplish this, I am combining a few basic techniques.

The first problem to solve is the rate of elevation change between map pixels. It’s incredibly boring to have a huge flat area abruptly stepping up or down into yet another huge flat area. Our baseline needs to be a nice continuous elevation change from sample-to-sample.

I have added a new API method called GetHeightBilinear(). This quickly samples any point in the 1000×500 map with any number of bilinear interpolations between samples. The result is a much smoother overworld full of curves as each height sample blends into the next.

Below is the same zoomed-in terrain sample using bilinear interpolation to create additional sample points across the surface.

HeightmapZoomWithBilinear

If written out to a full-size image, this would be 128000×64000 pixels, enough to create a reasonably detailed overworld at the same grid resolution found in RMB blocks. New sample points are created on the fly from existing data, and it doesn’t require any additional memory.

There’s still a problem however. Despite having nice continuous samples, the terrain is still quite boring. The next technique is to add some noise and break things up a little. I’m using a fast simplex noise generator to create small variations at ground level. Below is an example of noise overlayed with interpolated heightmap.

HeightmapZoomWithBilinearNoise

You won’t see it in the thumbnail, but if you click through to full-size image you will see small whorls of coherent noise added to the height data. Compare this with the blocky first image, and you can see just how much fine data has been mathematically inserted. This can be scaled to any grid resolution and tweaked as required.

Of course, this is just the beginning. The next step is to create real terrain chunks from this data and tune noise generation towards interesting-looking terrain based on climate data.

Before wrapping up, I will leave you with the following image of a small patch of terrain (equivalent to 2×2 RMB blocks, or 1/4 the size of a full city. I have noise turned up to show the kind of deformations possible.

TerrainChunks

 

Over the course of the next few weeks, I will continue building on this foundation, adding better texturing, cities, and climates into the mix.

Posted in Daggerfall Tools for Unity, Technical Content.

9 Comments

  1. Wasn’t expecting such a great feature for sure hehe !! I’m not exactly sure how its gonna work with the cities and stuff but I’m trusting you on this one. Your tutorial never fail me 🙂

    Do you realise than you’ve show us more progress in 1 month than DaggerXL in a whole year(probably more) !!!

    Also just out of curiosity, can we use another height map different than Illiac bay?

  2. It will all make sense once you see it in action. 🙂 The StreamingWorld prefab takes care of building the scene at runtime and laying out nearby cities based on the player’s virtual position in PlayerGPS. The terrain classes automatically place RMB ground tiles underneath cities where needed and procedural terrain everywhere else.

    You could replace the height map easily enough, but the streaming world stuff will still use the same climate data and city positions as Daggerfall. What I need to do is add support for overriding the various maps (climate, height, politic, etc.) and adjust city locations. I do want to add support for changing up the streaming classes, but not sure the best way to do this yet. I’ll keep thinking about this as everything progresses.

  3. Just remember that you are designing a tool. It will be up to the tool user to implement certain features. Just don’t get bogged down by too many features.

    For example, if I was to use your tool or make a Daggerfall like clone, a streaming world would not be a feature I am interested in. I think Arena style world travel would be more beneficial. Let’s all be honest that Daggerfall’s world outside of dungeons and cities was more of a gimmick. The only time I actually went walking in the world was the time I got brain fever and fast travel would kill me. I spent an hour walking to the nearest city only to find out they did not have a temple or mages guild.

    (FYI: My character did survive because I realized that I had transport spell, aka mark/recall, and my mark was set at the Mages guild in Daggerfall. I remember laughing so hard when I realized that.)

  4. I hear what you’re saying and promise not to get bogged down. I believe this is an essential feature or I would not allocate my valuable time for development.

    Keep in mind, a throwaway feature for some will be critical to others. And love it or hate it, a streaming overworld was part of Daggerfall. I agree it wasn’t particularly well implemented, but I need to provide at minimum a scaffold of this feature for others to build on.

    In any case, we’re only talking about a few weeks of work to get where I want it. Not much time in the scheme of things. 🙂

  5. just to give a different opinion i want to mention that i am really looking forward to the streaming world component since it will be a necessity for the stuff i plan to fiddle around with based on the dafferfall tools for unity 😉

  6. I think Interkarma is doing right. Impelemting game features is not on him, but bringing the whole world of Daggerfall to Unity is the right way, because futurer developers who arent so skilled in getting old data to work and just want reimplement a clone can profit a lot if the even get the world and dont need to create it on their own.

  7. Eric pretty much nailed it. My first pass is to get the world up and running, with only light gameplay. That way developers of all skill levels have an almost complete Daggerfall framework to build their own gameplay into.

    Once the world is up and running, I will start iterating over toolset, adding more stuff to API and fleshing out the lighter features.

    I am also open to suggestions. If there’s some Daggerfall data you really want to get at that isn’t currently in the API, let me know about it and I will do what I can to get it in. For example, reading quest data is well understood, but it’s not in the API yet.

  8. Quest sounds pretty cool but I am worried that is a to big deal to provide a working Quest API. We need to be able to call several methodes of other classes like from player or NPCs which arent providet yet. The other way it could be realised is converting them in a human readable format and create a Quest Markup Language.

    Maybe there are better posibilities I havent thought of and I am very excited of the outcome once its time for talking about quests.

Comments are closed.