Mindwerks / worldengine

World generator using simulation of plates, rain shadow, erosion, etc.
MIT License
992 stars 127 forks source link

Some small Ideas to discuss #140

Closed tcld closed 8 years ago

tcld commented 9 years ago

I have been thinking about some things I noticed (this is not an "issue" but I don't know of any other place for this): Elevation maps generated by platec usually contain values between 0 and 10; although some maps go up to even 14.

Advantages I see: Imagine the elevation map being multiplied by 2000: The range between highest and lowest points of a world would be at roughly 20000 - if you translate that to meters it is pretty much as on earth, with the occasional world straying a bit further from that. Thinking back to the strange rivers I was asking for some sense of scale to decide how much a "drop" of water can achieve - using our real physical units as a metric would be a great start for that. Instead of having to combine two quite alien scales, we would have a frame of reference to help make certain decisions.

There is a function that sets elevation thresholds based on a fixed percentage of land that should be declared e.g. a 'mounain'.

Advantages: Not every world has exactly three percent mountains, but instead it depends on the seed if there are mountains and hills.

I thought it would be great if worldengine could generate higher-detail heightmaps (a pull request will show up at some point). I saw (in the README maybe?) that some other projects respectively games made use of worldengines maps already. I myself initially found worldengine looking for a program to create nice heightmaps to be used in a toy-project I was working on in Unreal Engine 4. So I dug into draw.py and the GDAL-export() and noticed that the pillow library seems to be exclusively used to write out the finished PNGs of a world - nowhere else. And I found no way to export 16 Bit grayscale images with it. (GDAL can do it, but it is a pain to install!)

Advantages: After taking a look at several libraries I found some that can handle many if not all PNG-standards and thus seem more useful than Pillow (at least when it comes to writing PNGs) - the one I tried out is this: PyPNG (https://pythonhosted.org/pypng/ - seemingly available for Python 2.3 and above) With just a small bit of work I made worldengine export proper 16 Bit heightmaps and even took a look at one in Unreal Engine 4. :) Seeing the world go 3D is nice - maybe it will prove useful to others!

I think that all of these are technically easy to realize, 1. would probably be the most complicated (depending on how much code depends on the scale of the elevation map). The benefits are there, but since those still are significant changes, I wanted to ask what you guys think about them. (The PNG-stuff will be visible in my next pull request to get an idea of it, but it could be removed).

esampson commented 9 years ago

I think that we don't really need to change the scale. As you said we can just multiply the scale by 2000 to get a close estimate as to the real world scale (or alternately multiply by .0005 if you need to convert from real world to platec). Since I suspect the results will often be renormalized if they are being imported into anything where the height is really important (such as an Unreal Engine program) the value would get altered a bit anyway.

I didn't realize that mountains were being handled purely by elevation. That should probably be addressed as a separate issue. Mountains and hills are a lot more than just elevation. They are a change in elevation over a distance. The Tibetan Plateua has an average elevation in the range of 4500 m but it is not what we should classify as mountain.

As for changing to PyPNG, assuming it doesn't cause any problems with any of the other routines I would love to have it replace pillow so that we can get a 16 bit grayscale image. If you could also include an Unreal Engine utility to view a world that would be fantastic, IMO.

tcld commented 9 years ago

Rescaling is not a big problem, that is true. I just thought about it because when I looked at hydrology.py I had no idea of the relation of the numbers with respect to each other (amount of water versus volume it can fill in the world). Had it just been meters and the rain e.g. mm/m² it would be really easy to check if the hard-coded values make sense. I will add a comment that mentions the factor of 2000, at least.

I am not sure if there is more to mountains, but the very first step is related only to elevation. And not even total elevation - every world has 3% mountains at that point. You seem to have an idea of how to handle it a little better, so if it currently is really that simplified, you should take a look at it. (generation.py, ~line 118 ;P )

As far as I know, Pillow is only imported in draw.py (clean job!) and only accessed in a single class. For my test PyPNG worked great, I already started thinking about using it for more than grayscale-images.

By the way: It was only when I looked at a 16 Bit grayscale image that I realized that you cannot notice any difference with the naked eye since monitors (and most programs) cannot differentiate more than 256 shades of gray. :P (But for exporting data without having to worry about GDAL it is great.)

(About that utitlity: It is already easy to import heightmaps and create worlds out of them. The really big deal would be something that makes use of the biome/elevation/... maps to fill in the grey world. I thought about this a while back when worldengine didn't run on my PC.^^ But it is probably not that hard to do!)

esampson commented 9 years ago

Yeah. You won't notice a difference when you are simply looking at 8 bit grayscale over 16 bit grayscale but if you are feeding the results into something like Wilbur or Fractal Terrain you can definitely see a change in the final output. I would also guess that your Unreal Engine project would show you a difference.

tcld commented 9 years ago

:D Of course it is a huge difference, I think I understand the math behind it.^^

psi29a commented 9 years ago

Scaling isn't a problem with 8-bit, it is actually best when visualizing in an image. However once you get to 16 or 32 bit.... things go wacky. The difference between points is so extreme that trying to visualize them in 3D leaves you with a spiky world.

I've done this with OpenMW (another project I'm apart of). And yes.. this was after a few days of work with GDAL. ;)

ftomassetti commented 9 years ago

The choice of using a fixed percentage for mountains is not ideal, I agree with that. However it is pretty robust: it guarantees that the world would have a reasonable distribution of the different kinds of elevation (plain, hill, mountain) and it could be used for normalization later (if in my application the mountain elevation should be 5 or 5000 for some reason I can easily rescale worlds generated by WorldEngine). I think that using absolute values to determine what is a mountain and what is not would be more correct from a theoretical point of view but it could be not so easy to achieve: we have to think about values which make sense for very different maps (for size, for number of plates, for collisions which happen during the plate tectonics phase and so on). So it could be hard to pick the right thresholds and to get decent results under different circumstances.

tcld commented 9 years ago

Well, right now it is a fixed number. If somebody were to write a small module and give it a life test, that might still be worth a try.

I wouldn't mind finding a world without mountains, or one with a lot of them. That is to be expected when creating whole worlds. :)

esampson commented 9 years ago

This all does remind me of something I've been meaning to bring up. There should probably be ways to regenerate most PNGs based off the world file.

As an example we are discussing various ways to identify areas of mountain. To the best of my knowledge there's nothing in the world file that says 'area X is mountain'. There's certain specific data such as temperature range (which is an open number not corresponding to any real world figure), humidity (likewise and open number) and elevation. If someone wants to generate a map showing mountain ranges (such as ancient_map) or ocean they could run worldengine with the altered parameters and the -w option to load an existing world file instead of completely regenerating the world.

This may cause certain issues as I believe some things like erosion look at whether an area is mountains or not so their processes will end up reflected in the final output, even if an area is later removed from being a mountain (or areas are later upgraded to mountains). However I think that it will still have value as it will allow 'fine tuning' where these behaviors have very little impact (I go from 3% mountains to 2.5% mountains then the number of misidentified areas are going to be very minimal) as well as allowing people to tweak around values until they get a map that is close to what they want (lets see what this will look like with 15% mountains) and then do a 'final render' with the new parameters, once they feel they are dialed in.

In a similar vein it might be worthwhile to see if platec (and other routines) can be tweaked so that results are more uniform regardless of size. Right now one map with a 512x512 resolution and a second map with 1024x1024 will produce very different images, I believe, even if they use the same seed. If the noise patterns were made a bit more agnostic in regard to size (and other routines were to divide the x/y distances by something such as x_width/512) this would probably allow for the generation of things such as 512x256 maps until an interesting map is spotted at which point a 4096x2048 version could be generated.

ftomassetti commented 9 years ago

I agree with you. Indeed the world file contains all the information generated for the world so it is possible to load it again. We just need to implement the operation to change it.

tcld commented 9 years ago

That last part sounds very intriguing. Platec generates completely different worlds when certain parameters change, a bit more predictability would be appreciated. It is probably hard to realize, though.

Regarding all those parameters: Maybe it would be a first step to place all constant numbers into a single file and access them as global variables (and in return make them easily editable to the user, all in one place and including a detailed description). I don't know if that is an idea that agrees with your coding-standards, though. But it could lead to generating the same world with e.g. different amounts of mountains. Which is not exactly what you suggested, but it is very similar and very easy to implement in comparison.

esampson commented 9 years ago

Yeah, placing all the constant values in a file would probably not be a bad idea. Then at the initialization of the program the values are all read and constants are set to either the value in the file or an 'override' if provided (perhaps with an additional option to read override values from a separate file since there will quite likely be a lot of them).

This way people will be able to generate less terrestrial worlds by altering ocean levels, river and mountain variables, and the variables controlling the distribution of biomes.

tcld commented 9 years ago

Nobody would try to alter the ocean_level-variable anyway. https://github.com/Mindwerks/worldengine/issues/114 https://github.com/Mindwerks/worldengine/pull/134

;P (Yes, I still plan to fix this. It could probably be decently done by removing a single line of code from one of the commits, but I hope for a better solution to randomly appear. Soon.)

tcld commented 9 years ago

Maybe this is not the best place to discuss it, but I'll try since seemingly everybody participates here anyway: Going back to the global variables mentioned above, @esampson has kind of opened a seam for that now: https://github.com/Mindwerks/worldengine/pull/162

Maybe this is a good opportunity to create a central file that stores such parameters (including elaborate explanation) so they can be changed all in one place. We might want to provide more than one default set, too, so a user can choose between "standard world" and "desert world" or something similar. Commandline overrides will still take precedent, of course. EDIT: The changed values would have to be saved to the world-file, too, right?

Now my question is: What format should such a file have (.py, .ini, .json or something like that) and where should it be placed (suggestion: settings.ini right in worldengines root folder^^). What happens to the settings after worldengine has been properly installed - if it was a compiled Python file that might not work out properly. Maybe the file itself can be passed as a parameter? worldengine --settings=settings.py --seed=5000 world

I would hold off seriously working on this until the recent PRs are processed. This would have to touch a lot of files, I assume, so time might be best spent on discussing the concept for now to then get it done in a clean sweep.