0
\$\begingroup\$

I'm fairly new to procedural terrain generation. I know that to generate terrain you would use different calculations with the x and y axis (also z if you have one).

But what if you want to generated random terrain on a 2D world that loops around itself? By that I mean a world in which you enter the right side upon leaving the left side (or the other way around). It should also be generated on the fly and not all at once.

One solution I can think of is to just generate ocean along the border, but that is not what I'm looking for. I also seem to remember that Civilization generated such types of worlds, but I'm not quite sure how that worked, it's been quite some time since I played that game.

So how exactly can one generate such a continuous world?

\$\endgroup\$
  • 3
    \$\begingroup\$ Here: jgallant.com/… \$\endgroup\$ – jgallant Aug 31 '16 at 13:47
  • \$\begingroup\$ @Jon: Seems like that is what I wanted. I t would be great if you could explain the relevant pieces in an answer. \$\endgroup\$ – Matthias Schreiber Sep 1 '16 at 6:26
4
\$\begingroup\$

As mentioned in the comment, I figured what you required was wrappable noise. With wrappable noise, you can generate seamless textures and game worlds. You are probably familiar with generating 2D noise already.

What you need to do is sample 3 dimensional noise instead. Instead of sampling a rectangular shaped noise pattern, you are going to sample a cylindrical shaped pattern in 3D space.

enter image description here

The image above is what we will be doing. The idea is that you can cut this cylinder lengthwise at any point, and unroll it, and then use this as your map data. This will effectively wrap your noise around on 1 axis.

In order to do this, sample your noise data like so:

for (var x = 0; x < Width; x++) {
    for (var y = 0; y < Height; y++) {

        // Sample noise at smaller intervals
        float s = x / (float)Width;
        float t = y / (float)Height;

        // Calculate our 3D coordinates
        float nx = Mathf.Cos (s * 2 * Mathf.PI) / (2 * Mathf.PI);
        float ny = Mathf.Sin (s * 2 * Mathf.PI) / (2 * Mathf.PI);
        float nz = t;

        // sample noise at coordinate
        float heightValue = (float)HeightMap.Get (nx, ny, nz);

        // save noise value to a noise map
        mapData.Data [x, y] = heightValue;
    }
}

If you convert this map data into a texture it would wrap on the x-axis and would look something like:

enter image description here

More information can be found here.

\$\endgroup\$
  • \$\begingroup\$ Thank you, that explains it pretty much to the point. I'm still a little confused about how it works exactly, but I think I can figure it out from here on. \$\endgroup\$ – Matthias Schreiber Sep 1 '16 at 16:28
0
\$\begingroup\$

For generating the terrain in chunks, you should look into... well, chunks. An interesting example of that would be the McRegion format that was eventually pulled into Minecraft. You can read a bit about it here: https://bukkit.org/threads/is-it-worth-looking-at-the-mcregion-files.35713/

As to the other part, it depends on what you want the world to look like. You say cylindrical, but I suspect that you don't mean that the world is actually a cylinder. However, if you do mean cylinder, or even sphere, then the best bet would be to generate the world as a flat plane and wrap it. But since you mention 2D, I'll assume that you mean that maxX becomes minX and maxY becomes minY as you move across the edge. In that case, so long as your terrain creation takes that into account (there's isn't a sudden cliff on the edge of one that prevents two-way movement across the border), then it also depends on your engine. You could do this with trick cameras and some scripts that cover your boundaries, making sure it loads the chunk from the other side and "teleports" your character between coordinates, but the camera makes it look smooth.

\$\endgroup\$
  • \$\begingroup\$ Well, I didn't downvote your answer, but I guess I know why it got downvoted. My question was how to make a map that loops around itself (so yes, maxX is to the left of minX, same with Y). It has nothing to do with chunks nor does it have to do with cameras, but with JIT-generated terrain. \$\endgroup\$ – Matthias Schreiber Sep 1 '16 at 6:20
  • \$\begingroup\$ Um, actually not the same with Y, because then it would essentially be an impossible 3D object. I was explicitly asking for a cylinder, maxX + 1 = minX. Even if it would be a sphere then you would do something like maxY + 1 = abs(maxY - (amount_of_pixel_horizontal_on_maxY / 2)) # (or something like that) \$\endgroup\$ – Matthias Schreiber Sep 1 '16 at 6:33
  • 1
    \$\begingroup\$ Not impossible — a torus (doughnut) has this property. The inside is a little smaller than the outside, but this is a reasonably small distortion factor if the torus is a large thin ring. You can cut its surface into a roughly rectangular sheet, whose sides and top/bottom seam together in the wrapping manner you describe. \$\endgroup\$ – DMGregory Sep 1 '16 at 12:30
  • 1
    \$\begingroup\$ @MatthiasSchreiber - the chunks was in response to " It should also be generated on the fly and not all at once", so I was offering a note on that. Also, you said cylinder (which is a 3D shape) but specified a 2D map. When you create a 2D representation of a 3D shape, you will inherently get distortion (look at flat maps of Earth, save the Dymaxion map, they aren't perfect representations). A torus would have the same effect. \$\endgroup\$ – Jesse Williams Sep 1 '16 at 12:34
  • 1
    \$\begingroup\$ @JesseWilliams: I see how my question could be misunderstood, I was trying to explain it in a few different ways to get my idea across. Technically, yes, it is not a cylinder, what I meant was basically a 2D map which has been glued together on two sides. I still don't see how chunks should solve my question though, because chunks still need to connect seamlessly. Also, while I see what you mean with the camera, it has nothing to do with the generation itself, but with the process of displaying it later on (which wasn't my question). \$\endgroup\$ – Matthias Schreiber Sep 1 '16 at 16:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.