Map Generator 3.0 - Please Critique!

Thanks! I will see if I can make sense of that math when I have some time/energy.

As for a Dymaxion Map, can you tile it with hexagons? And once in cubeoctohedron form how do you project that out to a sphere?

Given that my data structure is tied to my rectangular offset hex map, converting that system to handle dymaxion is probably not going to happen. Unfortunately my brain has limits… :stuck_out_tongue:

Of course I never thought I would turn this map into a globe in the first place so who knows! :slight_smile:

The math for the conversion is super easy despite the mathematical notation making it look complex.

It’s basically just radius and your secondary coordinate, phi standing in for x and y respectively.

If all you have are x/y coordinates (say a plane, or a cube) then you want to convert into r and phi like this:


r = sqrt(x^2 + y^2)

radius = square root of x-square + y-squared


phi = atan2(y, x)

phi is the result of atan2 with y and x passed

Then it gives the definition of atan2 (which we don’t care about, since every game engine ever includes the specific atan version we need).

If you have r and phi already, it’s even easier to get an x/y out:



x = r cos phi
y = r sin phi


So you should be able to just keep it as a plane like normal, then just fit 5 other planes filled with hexes into a cube, then tessellate the cube geometry by adding vertices and connecting them. The only issue then would be the corner points of the cube - they’d likely have a wrong hex. But compared to literally any other plane -> spherical projection, it’s way way less distortion both in area and distance.

Using this method, you wouldn’t change any of your data structures dealing with x/y at all, and instead simply project for the rendering/placement of the hexes (so when you set the position, calculate r and phi, then plug those in as the x/y respectively). You’d also be able to leave querying functionality alone and run it through the same conversion before doing the normal work.


Now, that said, you could do it totally differently. Instead of using x/y at all and messing around with the planar projection, map all your hexes in polar coordinates from the beginning (e.g., arbitrarily specify radius and phi, then calculate the tiling in r and phi as you would x and y normally). Theoretically you could literally just replace your x/y based code with r/phi based code.

You might even be able to leave it all the same and simply replace the bits where it actually spawns stuff to deal with the projection.

Edit: Hit me up on the Launcher chat if you need help with this projection stuff. I’d be happy to help where I can.

Thanks, that is a lot more intelligible, though I am still going to need some time and brain energy to jump back into that. I will definitely hit you up if I start to work on that(this weekend or next maybe). :slight_smile:

It is kind of funny, but I just jumped back into normal blueprint mode for the first time in maybe 2 months(felt like forever). Working logic in blueprint is like a soothing balm for my brain compared to trying to work out sphere projection math. :stuck_out_tongue:

When I mentioned distortion, I am not sure I meant it quite in the same way you are referring. So the data structure, the neighbor checking, really everything, is setup to handle this map as a big rectangle of specific dimensions(height/length divisible by 10). The entire top/bottom row of the rectangle is polar. The distortion I really refer to is the fact that the arctic circle is essentially the same circumference as the equator. This is more a problem with the foundation of the generator than the projection method.

So yeah, I could probably still use a rectangle with the dimaxion map, but the current logic structure of the generator would require a complete retool and that probably isn’t going to happen. I think I would just add 12 pentagons to the thing if I were to go that route. :stuck_out_tongue:

The Break Vector is the hit location on the sphere. The Atan2, COS, and SIN are in Radians? Is this even close to correct? (it is way off in tests)

Beginning to work out a system where the map is updated and moves around the player as the pan around. This is primarily for world wrap. had brought this up almost a year ago, but at the time I didn’t need the option and it seemed extremely complicated. Well now I do need the option… and it is still extremely complicated. :stuck_out_tongue: So laying it out here in post helps me focus my thoughts, and maybe if I am lucky someone will have some good advice. :slight_smile:

So in order to move an instance, I need to know it’s index. Each Add Instance tied to a single variable keeps a running tally of how many instances it has spawned, which each instance is referenced to. So I will need to store a separate array of these indexes, per type of mesh/material in the world. As of right now, there are 23 base tile types, of which there may be 5 or more mesh/material variations for each. So 100+ separate arrays storing instance index information, just for basic terrain. Maybe another couple hundred for units, cities, resources, etc, etc.

The basic scenario:
Player Camera moves 1 tile to the North. 1 row of tiles on the South edge need to be moved and/or replicated to the North Edge. Based on player position, we can do a small bit of math to find the indexes of the bottom row tiles. Then we can work out their new vectors and store that in an temp array.

In order to reduce the number of main map array checks to the absolute minimum, we are going to need a giant struct array:

Parent Stuct Array: Will have a member for each category of item that needs moved (Terrain, Forest, Resource, Unit, Tile Damage, Tile Improvement, River pieces(could be 3-6 per tile edge), City, Territory Info, etc.).
Member Struct Arrays: Contain the Mesh Instance Type and Instance Index. Rivers and similar members could also have additional required information.

We need to access the main struct array for each tile to be moved to find out what Mesh Instance Array each of those items belong to, as well as it’s Instance Index number, plus any other information that may be needed for certain edge cases like rivers. Then, we have to use the first piece of information to hit an Enum for the proper Mesh Instance Array, and then the second piece of information to update the transform of the tile.

So in short, worst case scenario is a 100% explored, 100% land, ultra huge 400 tile wide map:

X400

  1. Small bit of math. (To determine Tile Index to be moved)
  2. Get from Struct Array - Array Size 80,000 (To determine Mesh Instance Type, Instance Index, and other required information)
    — 2.1+ Information from Struct Array is run through switches, branches, etc to determine what is moving and what additional information needs to be worked.
  3. Small bit of math. (To determine new vectors)
  4. Transform Update multiplied by the number of items on the tile(could be 15+ items to a single tile).

Only thing I am really worried about is accessing that many arrays, that often. As fast as the player can pan across the map, that is how often this has to be done. I will probably try and spread this operation across a tick if necessary.

Teleporting using the minimap will be a whole different beast, but it can be expected in most such games that that might take a second or two to load on huge maps.

Thank you for reminding me why I dropped out of college… Math… <shudder> :slight_smile:

J^2

It seems right to me. It should kind of just work.

What’s the input/output look like?

Edit: Though keep in mind if you do it on a single plane, you won’t get a sphere, just a curved section. You’ll need 6 planes forming a cube to make a proper sphere.

No doubt! :stuck_out_tongue:

The input is the vector on the surface of the sphere. I am not sure this is the input that it wants… isn’t r and phi in radians/degrees or something?

Output is like .5, .6 compared to say 300, 400.

Fantastic thread! Very interesting read. Do the tectonics effect the mountain generation? I was also thinking that you could base erosion on player activity ( settlements, movement and so on ) it may be difficult but weather could also be a factor in that. Would it be difficult to generate visualization for sea floors or for weather patterns? I think a meta-system like weather would make this project even more outstanding. Your project has given me some great leads on research for my own project and I’m most impressed that you’ve done so much with blueprints alone.

It’s my understanding that you can use Vector fields to effect GPU particle flow. Would you by chance know if those vector fields can be adjusted at runtime?

Again. Thanks for the great devlog. I’ll keep my eye on… oh wait… there are many more pages. ha!

Great work at any rate!

Thanks! :slight_smile:

Yeah there are 2 types of tectonic plate boundary, divergent(Think Atlantic Ocean), and Convergent. There are 4 types of Convergent Boundary; Andes, Rockies, Himalayas, and Island Chain(think of the area from Japan to Australia).

Erosion is a bit too long of a process for the physical and time scales of the game. Players will be able to level hills and mountains at some point though(Industrial/Modern era), and maybe even build them(post Modern Era).

For visualization of the sea floor, the current plans are to make the ocean out of 1 giant water plane, make it somewhat transparent, and then place seafloor tiles under that plane. Brighter coastal tiles, darker mid-ocean seafloor tiles, maybe some underwater volcanoes, vents, ridges, etc. I plan to make sea floor colonization a super late game ability.

The only time I will probably simulate weather patterns visually will be for hurricanes and other game affecting weather disasters, and maybe when you zoom out for a full planet view I could bring the clouds into view.

What kind of project do you have in mind? Always interested in seeing more turn based projects and any project with lots of procedural action. :slight_smile:

I don’t know anything about the particle system, but it would make sense that you could.

Great work btw, one of it’s kind! I only read the first 2 pages or so, but here are some questions:

  • Is this available for me to download from you for reference?
  • How did you implement the Voronoi Diagram into your project? How did you use the math?
  • It looks like you didn’t use Voronoi for the oceans, what did you use?

I am working on a game kind of like The Blockheads, and some of this information could be useful for this game and more importantly future games. I plan on making a generated world hunting 3D game, and could use some of this info for Biomes and such. Anyways, great work!

Been working with J.J. Franzen on updating my **** poor art to something more respectable. Hopefully have a good screen or two to show off this week. :slight_smile:

Currently working on splitting the generator up into smaller, more manageable bits. Also implemented Perforce source control, which was honestly more tedious than it really should be… why are we still using command line in this century? :stuck_out_tongue:

Thanks!

Sorry, the generator is not available for download. But hopefully I can point you in the right direction when you have questions. :slight_smile:

Here is the math for Voronoi:


You may or may not need world wrap, so you should be able to skip the 2 commented sections after the branch if you don’t need wrap.

Basically you just need to determine your seed vectors, put them into an array, and then for each tile you are checking compare the current tile with each of the seeds. Or, figure out how to optimize it so you don’t need to check against all the seeds. Maybe you only need to check for seeds within 3-6 tiles of the current tile? That is one way I optimized things.

The oceans also use Voronoi. The thing about the generator is that there is layer upon layer of Voronoi. The tectonic plates have 2 levels of voronoi. Then the land/water is a voronoi on top of that. Then climate on top of that, etc. Some of the oceans have their own voronoi tectonic plate, and other oceans fill in between continental plates. Most of the generator is really about intelligent placement of the seeds using tectonics, climate, etc.

Looking forward to seeing how this will look with J.J’s meshes. How are you splitting the blueprint up to make it more manageable? What sort of blueprints are you using? I’m working on splitting up my blueprint myself, as I might hold the doubtful honor of second largest blueprint contained within a single graph. Personally I’m using a combination of my placed grid manager, my level blueprint, camera actor, game mode and pawns.

Haha. How big is your blueprint now? Did you notice an increase in file size with 4.7? My MapGen BP was 20-26MB in 4.6, and in 4.7 it ballooned to 88MB somehow. Even the portions I break off are far bigger than they would have been before. I am assuming this has something to do with the circular dependency fixes, but who knows what else could have beefed it up.

Just using empty actor BP’s for the new pieces. Their key info variables are exposed on spawn and set by the main BP. First thing I split off was the actual instance spawning section so that J.J could work in it without being weighed down by the rest. Right now I am working to push the map update functions(such as when I click the map to turn on overlays, remove forest, etc) from the main bp into the SpawnBP.

Also breaking things by function; tectonics(already separated, but still in testing), landmass creation, climate, river, etc.

The main BP will act as the gateway and holder of all information, and is now named MapState.

Yeah, the same thing happened to me when I updated to 4.7. My main grid manager blueprint went from 4 to 18 MB, admittedly with quite a few additions, but that’s still more than quadrupled in size. What other reasons do you have for splitting up the blueprint than making it easier for J.J. to work with? For me it’s mainly so I won’t replace all changes users have made each time I make a new patch. I’m doing something similar to you in keeping the grid manager as a gateway and holder of info. I’m considering moving most of the functions to a function library.

Compile time, save time, and general reaction time of the map generator blueprint is pretty bad at this size. It honestly slows the whole workflow down and I should have split it up long ago. That, and it makes for one very large single point of failure if it gets corrupted.

Since Epic fixed circular dependency issues in 4.7 it did remove one potential problem from the breakup.

Makes sense. Compile times aren’t that bad in my case, but if they were four times as long it would be pretty annoying. The point about corruption is a good one. I’m sure Epic weighed the pros and cons before fixing circular dependency. I’ll miss the small file sizes, though.

Yeah, I am not making a mobile game so I don’t really care if blueprints are a little bigger. Of course, I may have a different opinion on that when I try and spawn 80K data blueprints into the world, so we will see how that goes… :stuck_out_tongue:

Made a lot of progress visually. Thanks to J.J. Franzen for all the help! :slight_smile:

Still a lot of work to do such as input the rest of the hill/mountain meshes, rotate them randomly, etc. Here is a current screen:

Using Hierarchical Instanced Meshes for the trees in that screen, but it didn’t seem to do anything for performance. Hopefully Epic updates the docs soon for them if they haven’t already.

Other than that, I completed work on splitting up the giant generator blueprint. It used to be 90MB, and it is now 4MB. :slight_smile: Most of the new blueprints are 10-20MB with one at 30MB. Definitely helps on the compile times when you only need to work in one area.

Also integrated the entire project into Perforce, and that was seriously far more tedious than it should have been(command line, really?). But, now that it is working it is pretty great.

One of the things I will work on going forward will be implementing a proper random stream system. Need to figure out a way to randomized the stream for every tile, but tie it all to a single stream seed that can be set in the map creation screen. Recent tests didn’t go so well.

Quite a few other areas of the generator need optimization, especially the river system.

And I still need to work out a good way to wrap the world that doesn’t involve spawning 3-7 maps, but that will depend on a few other things that have to be worked out first.

The only thing visually missing is a toggle for night mode showing shadow side with city lights. Maybe someday. :slight_smile: Heh, maybe I should throw a procedural moon in the sky for the hell of it too. :smiley:

Going to put the collision sphere trace on tick so we can get mouse-over working. Once that is up and running, then fine tuning the trace accuracy should be much easier.