项目作者: eobermuhlner

项目描述 :
Pure Java random generator for planets
高级语言: Java
项目地址: git://github.com/eobermuhlner/planet-generator.git
创建时间: 2016-09-20T06:24:41Z
项目社区:https://github.com/eobermuhlner/planet-generator

开源协议:MIT License

下载


planet-generator

Java library to procedurally generate earth-like planets.

The generator is pure Java without any external dependencies.

The viewer is a separate project that uses JavaFX.

Features

  • pure Java library
  • full procedural generation
  • generate different textures
  • generate terrain mesh data
  • query physical information for every point of the planet surface
  • supports biome information
  • creates impact craters
  • simple physical model for temperature, precipitation, clouds, ice, snow, …

Example Code

The following code snippets show some typical use cases.

Generate an instance of Planet

The first step to generate a planet is to define the unique random seed for the planet and
generate the basic planet data from it.

  1. PlanetGenerator planetGenerator = new PlanetGenerator();
  2. // unique seed for the planet
  3. long[] seed = new long[] { 4 };
  4. // generate planet data for unique seed
  5. PlanetData planetData = planetGenerator.createPlanetData(seed);
  6. // print some random generated planet values
  7. System.out.println("radius : " + planetData.radius + " m");
  8. System.out.println("revolutionTime : " + planetData.revolutionTime + " s");
  9. System.out.println("orbitTime : " + planetData.orbitTime + " s");
  10. // modify generated planet data if you need to fulfill special constraints
  11. planetData.baseTemperature = 290; // 290 K ~= 17 C ~= 62 F --- expect warm tropics at the equator, small polar caps
  12. // create planet according to planet data constraints
  13. Planet planet = planetGenerator.createPlanet(planetData);

The output looks like this:

  1. radius : 5137796.466254459 m
  2. revolutionTime : 59521302 s
  3. orbitTime : 40005614677 s

Query a specific point on a Planet

With the planet data generated we can now generate specific information for any point of the surface of the planet.

This is useful to know the conditions at the location of the player in a game.

  1. // specify which layers and what accuracy you need (default has all layers and good enough accuracy)
  2. PlanetGenerationContext context = planet.createDefaultContext();
  3. // generate planet at one specific point
  4. double latitudeRadians = Math.toRadians(90.0);
  5. double longitudeRadians = Math.toRadians(0.0);
  6. PlanetPoint planetPoint = planet.getPlanetPoint(latitudeRadians, longitudeRadians, context);
  7. // print some values for the specific point on the planet
  8. System.out.println("height : " + planetPoint.height + " m");
  9. System.out.println("temperature : " + planetPoint.temperature + " K");
  10. System.out.println("precipitation : " + planetPoint.precipitation);
  11. System.out.println("color : " + planetPoint.color);

The output looks like this:

  1. height : 6015.265244579083 m
  2. temperature : 271.7990658042786 K
  3. precipitation : 0.0
  4. color : (0.6295682289054663, 0.5518509754711629, 0.4010190099591988)

Create textures for a Planet

To render an entire planet we can create the necessary textures into images.

The following example creates all texture types that the framework knows about and saves them into files.

  1. // specify context and add the texture types you want to generate (we simply add all of them)
  2. PlanetGenerationContext context = planet.createDefaultContext();
  3. context.textureTypes.addAll(Arrays.asList(TextureType.values()));
  4. // generate 512 x 256 pixel textures for the entire planet
  5. Map<TextureType, TextureWriter<BufferedImage>> textures = planet.getTextures(512, 256, context, (width, height, textureType) -> new BufferedImageTextureWriter(width, height));
  6. // save the textures into png files
  7. try {
  8. for (Map.Entry<TextureType, TextureWriter<BufferedImage>> entry : textures.entrySet()) {
  9. String filename = entry.getKey().name().toLowerCase() + ".png";
  10. BufferedImage image = entry.getValue().getTexture();
  11. ImageIO.write(image, "png", new File(filename));
  12. }
  13. } catch (IOException e) {
  14. e.printStackTrace();
  15. }

The following textures where generated with the sample code above.

Surface color map:

Surface Map

Normal map:

Normal Map

Specular map:

Specular Map

Average Precipitation Map:

Average Precipitation Map

Average Temperature Map:

Average Temperature Map

The full set of example textures is here.

Create textures and height map for terrain

To render a terrain you need to generate the mesh and textures for the terrain.

The conversion of the terrain height map into a mesh depends on the 3D library you use in your renderer.
The following code snippet simply prints the values of the height map.

  1. // specify context and add the texture types you want to generate (we simply add all of them)
  2. PlanetGenerationContext context = planet.createDefaultContext();
  3. context.accuracy = 1; // meters
  4. context.textureTypes.addAll(Arrays.asList(TextureType.values()));
  5. // create terrainHeightMap to be filled
  6. DoubleMap terrainHeightMap = new DoubleMap(16, 16);
  7. // generate terrain textures and fill terrain height map for the specified area
  8. Map<TextureType, TextureWriter<BufferedImage>> textures = planet.getTextures(
  9. Math.toRadians(90.0), Math.toRadians(100.0), Math.toRadians(180.0), Math.toRadians(190.0),
  10. 64, 64, context, (width, height, textureType) -> new BufferedImageTextureWriter(width, height), terrainHeightMap);
  11. // save the textures into png files
  12. try {
  13. for (Map.Entry<TextureType, TextureWriter<BufferedImage>> entry : textures.entrySet()) {
  14. String filename = "terrain_" + entry.getKey().name().toLowerCase() + ".png";
  15. BufferedImage image = entry.getValue().getTexture();
  16. ImageIO.write(image, "png", new File(filename));
  17. }
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. }
  21. // use the terrain height map to create the 3D mesh
  22. for(int y = 0; y < terrainHeightMap.height; y++) {
  23. for (int x = 0; x < terrainHeightMap.width; x++) {
  24. if (x > 0) {
  25. System.out.print(", ");
  26. }
  27. System.out.print(terrainHeightMap.getValue(x, y));
  28. }
  29. System.out.println();
  30. }

The output looks like this:

  1. 5489.898749837851, 4471.268777925344, 4468.983375629327, 4350.646818044562, 4649.039811173835, 4102.277022713687, 3610.966842788416, 3025.767283526434, 2336.737514165431, 1883.273910496392, 1563.916787365276, 1401.429576906501, 1232.391953872694, 1098.1179502361874, 971.170228855176, 918.1472957393389
  2. 4701.42107898749, 4621.983539315942, 5601.481916916854, 6040.508911990006, 5792.126161150626, 4337.567824918225, 3227.189370439525, 2810.606457798912, 2388.3277548438646, 1775.8112997035014, 1542.8048133370557, 1317.4937295345871, 1097.1618910509796, 880.4195784505218, 725.1598352425881, 639.8835091066876
  3. 4735.97049320655, 4709.099132146011, 5314.440398093927, 6148.248928435732, 5673.96852238723, 4477.702000195767, 3298.768303500835, 2659.8442242805677, 2080.140461505328, 1709.023843990919, 1374.0575357035013, 1151.3979602021982, 944.5455144625485, 757.2690652062702, 508.16905557473456, 333.70457602977694
  4. 5325.551715553819, 5115.942863854324, 5649.121835657635, 6484.441467290666, 5320.965403440911, 4398.987988836087, 3578.8909567429664, 2417.0024246971143, 1756.5331149753774, 1357.967179500988, 1140.6441178443629, 881.532745297256, 772.9045828487397, 519.9778724764219, 296.45671775670326, 97.53588120477889
  5. 5433.510395319024, 5770.7745289228515, 6329.7465290714035, 6272.304615145475, 4942.6670193477685, 3834.6357477129395, 3299.0006258748153, 2203.7261170348365, 1595.961265505699, 1174.001214007144, 910.139679521455, 678.0264515400104, 451.0134265841343, 333.59785979978733, 162.05429510191698, 0.0
  6. 5017.988731402772, 5173.53438082652, 5424.665827607197, 6327.460451410024, 4554.1989268912685, 3620.56654234273, 2832.79863695941, 2046.0851349458617, 1472.491777219141, 1017.552307922002, 717.6108651805707, 477.79154998035756, 307.3093901945231, 136.6215066859304, 0.0, 0.0
  7. 4709.57487925033, 4526.032651940451, 4391.042942057761, 4241.32078740184, 3856.489791402785, 3255.443931561126, 2379.7313662412935, 1854.339350011488, 1329.9056721090628, 899.6985862606089, 586.8401114208509, 347.80035242662507, 196.83049901556387, 25.218009821684063, 0.0, 0.0
  8. 5363.414858681698, 4627.28659508637, 4071.47909426318, 3614.1046110418984, 3021.1042133909186, 2836.2810000520813, 2218.2686474160664, 1738.8762782897002, 1182.5195844220698, 763.7678568912006, 468.5345595229901, 274.6664124634008, 59.82482151564545, 0.0, 0.0, 0.0
  9. 4548.413703955205, 4091.4678272434676, 3873.0508442456658, 3412.4740028284095, 2888.4328559852156, 2612.5202053880957, 2076.7330375693737, 1531.8586702210005, 1009.3558023574969, 695.5595175510007, 432.0749181559995, 313.533245332811, 0.0, 0.0, 0.0, 0.0
  10. 4375.492786389766, 3892.0148708484276, 3706.364992566344, 3574.386356110005, 2887.850843594052, 2509.4510713157642, 2223.760136962791, 1696.9984204549519, 1089.2548169124575, 868.0790696075792, 496.1299243233598, 99.22034140895084, 0.0, 0.0, 0.0, 0.0
  11. 4587.539963957511, 4243.7136342571675, 3769.4715897806173, 3129.338438523483, 3252.802988534547, 3030.7313359304308, 2177.2037740380174, 1732.7958796842713, 1478.1722312062548, 851.6346802515518, 531.5189555345514, 0.0, 0.0, 0.0, 0.0, 0.0
  12. 4396.347737013605, 5066.626635938039, 3906.690585325895, 3070.1573514891506, 2835.390074881482, 2334.9812337174744, 1765.2471962030477, 1457.7398995662725, 1337.8901132145984, 820.9090682082078, 385.75380856416905, 0.0, 0.0, 0.0, 0.0, 0.0
  13. 3752.8272756544184, 4149.132621594451, 3994.616969800699, 3019.15071959706, 2239.3489934268628, 1732.358346624028, 1528.820260020564, 1087.262186793946, 726.1892559406651, 474.02742925698567, 287.00437215288, 0.0, 0.0, 0.0, 0.0, 0.0
  14. 2886.729637822723, 2910.296766750468, 3307.3954732219545, 2554.6036917349747, 1787.0023071850037, 1432.4505996767475, 1207.924309159106, 740.3354550586755, 448.5396851382302, 225.37850590913968, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
  15. 2400.2142745172378, 2228.3421107130207, 2114.166473438371, 1947.718222190556, 1612.8597756402496, 1300.431139830308, 1056.6437969661392, 693.9479640706459, 559.1918727273969, 172.62659604277724, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
  16. 2213.204457843455, 1927.4320979217619, 1752.979830529196, 1618.5553875228188, 1516.4871246154707, 1532.746970552882, 1000.0988322189642, 644.4311497084709, 618.9590170571792, 152.05721019525845, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

When you interpret these values as a 3D mesh you get the following wireframe.

Terrain Mesh

The following terrain textures where generated with the sample code above and can be used to render the mesh.
Note that the textures where generated with higher density than the terrain mesh.

Surface color map:

Terrain Surface Map

Normal map:

Terrain Normal Map

Specular map:

Terrain Specular Map

The full set of example textures is here.

JavaFX Viewer

For debugging purposes an interactive JavaFX viewer was written that allows to
see and modify many planet data values and
analyze the generated planet.

Interactive textures

Interactive textures can be clicked to show zoomed textures, point information and a height cut.

Screenshot Viewer - Textures

Animated 3D Planet

Screenshot Viewer - 3D Planet

Animated 3D Terrain 3D

The animated 3D terrain shows the same section of the planet as the zoom textures.

Screenshot Viewer - 3D Terrain

Mathematical crater models

The mathematical models used to create the craters and vulcanoes can be visualized.

Screenshot Viewer - Crater