Skip to content

Instantly share code, notes, and snippets.

@atrus6
Created November 18, 2015 06:01
Show Gist options
  • Save atrus6/f6a25dfa97a1e2807d0c to your computer and use it in GitHub Desktop.
Save atrus6/f6a25dfa97a1e2807d0c to your computer and use it in GitHub Desktop.
Complex Planetary Surface in libnoise for java
import libnoiseforjava.NoiseGen;
import libnoiseforjava.module.*;
import libnoiseforjava.util.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
public class Terra {
/*
These constants determine the terrain of the grid, boundaries and size.
*/
//Southernmost coordinate of the grid.
private final double SOUTH_COORD = -90;
//Northernmost coordinate of teh grid.
private final double NORTH_COORD = 90;
//Westernmost coordinate of the grid.
private final double WEST_COORD = -180;
//Easternmost coordinate of the grid.
private final double EAST_COORD = 180;
//Width of the elevation grid, in points.
private final int GRID_WIDTH = 4096;
//Height of the elevation grid, in points.
private final int GRID_HEIGHT = 2048;
//Planet seed. Change this to generate a different planet.
private final int CUR_SEED = 0x209ecfbe;
//Circumference of the planet, in meters.
private final double PLANET_CIRCUMFERENCE = 44236800;
//Minimum elevation of the planet, in meters. This value is approximate.
private final double MIN_ELEV = -18192;
//Maximum elevation of the planet, in meters. This value is approximate.
private final double MAX_ELEV = 8192;
//Frequency of the planet's continents. Higher frequency produces smaller, more numerous continents.
//This value is measured in radians.
private final double CONTINENT_FREQUENCY = 1;
//Lacunarity of the planets continents. Changing this value produces slightly different continents.
//For best results, this value should be random, but close to 2.
private final double CONTINENT_LACUNARITY = 2.208984375;
//Lacunarity of the planets mountains. Changing this value produces slightly different mountains.
//For best results, this value should be random, but close to 2.
private final double MOUNTAIN_LACUNARITY = 2.142578125;
//Lacunarity of the planets hills. Changing this value produces slightly different hills.
//For best results, this value should be random, but close to 2.
private final double HILLS_LACUNARITY = 2.162109375;
//Lacunarity of the planets plains. Changing this value produces slightly different plains.
//For best results, this vluae should be random, but close to 2.
private final double PLAINS_LACUNARITY = 2.314453125;
//lacunarity of the planets badlands. Changing this value produces slightly different badlands.
//For best results, this value should be random, but close to 2.
private final double BADLANDS_LACUNARITY = 2.212890625;
//Specifies the twisitness of mountains.
private final double MOUNTAINS_TWIST = 1;
//Specifies the twistiness of hills.
private final double HILLS_TWIST = 1;
//Specifies the twisitness of badlands;
private final double BADLANDS_TWIST = 1;
//Specifies the planets sea level. This value must be between 1.0 and -1.0
private final double SEA_LEVEL = -100;
//Specifies the level on the planet in which continential shelves appear. This value must be between 1 and -1,
// and less than SEA_LEVEL.
private final double SHELF_LEVEL = -100.375;
//Determines the amount of mountainous terrain that appears on the planet. Values range from 0 (no mountains) to
// 1 (all terrain is covered in mountains). Mountainous terrain will overlap hilly terrain. Because badlands cover
// any terrain, setting MOUNTAINS_AMOUNT may not completely cover the terrain in mountains.
private final double MOUNTAINS_AMOUNT = 0.5;
//Determins the amount of hilly terrain that appears on the planet. Values range from 0 (no hills) to 1 (all
// terrain is covered in hills). This value must be less than MOUNTAINS_AMOUNT. Because mountains and badlands
// overlap hilly terrain, setting HILLS_AMOUNT to 1 may not completely cover the terrain in hills.
private final double HILLS_AMOUNT = (1.0 + MOUNTAINS_AMOUNT) / 2;
//Determins the amount of badlands terrain that appears on the planet. Values range from 0 (no badlands) to 1
// (all terrain is badlands). Badlands terrain will overlap any other terrain.
private final double BADLANDS_AMOUNT = 0.03125;
//Offset to apply to terrain type definition. Low values ( < 1) cause the rough areas to appear only at high
// elevations. High values ( > 2 ) cause the rough areas to appear at any elevation. The percentage of rough
// areas on the planet are independent of this value.
private final double TERRAIN_OFFSET = 1;
//Specifies the amount of glaciation of the mountains. This value should be close to 1, and greater than 1.
private final double MOUNTAIN_GLACIATION = 1.375;
//Scaling to apply to the base continent elevaitons, in planetary units.
private final double CONTINENT_HEIGHT_SCALE = (1 - SEA_LEVEL) / 4;
//Maximum depth of rivers, in planetary units.
private final double RIVER_DEPTH = 0.0234375;
//The final planet.
Cached finalPlanet;
public Terra() throws Exception {
//
// Module Group: Continent definition.
//
/*
Module subgroup: base continent definition (7 noise modules)
This subgroup roughly defines the positions and base elevation of the planets continents.
The "base elevation" is the elevation of the terrain before any features are placed.
-1 represents the lowest elevation, 1 represents the highest elevation.
*/
Cached baseContinentDef = baseContinentDef();
/*
Module subgroup: continent definition (5 noise modules)
This subgroup warps the output values from the base-continent-definition subgroup, producting more
realistic terrain.
Warping the base continent definition produces lumpier terrain with cliffs and rifts.
*/
Cached continentDef = continentDef(baseContinentDef);
//
// Module Group: Terrain type definition
//
/*
Module subgroup: terrain type definition
This subgroup defines the position of terrain types on the planet.
Terrains include, in order of increasing roughenss: plains, hills and mountains.
This subgroups output should be based on the output value from the continentDef subgroup module. Roughter terrain
mainly appears at higher elevations.
-1 represents the smoothest terrain types (plains and underwater)
1 represents the roughest terrain types (mountains)
*/
Cached terrainTypeDef = terrainTypeDef(continentDef);
//
// Module Group: Mountainous terrain
//
/*
Module Subgroup: mountain base definition
This subgroup generates the base-mountain elevations. Other subgroups will add the ridges and low areas to the
base elevations.
-1 represents low mountainous terrain and 1 represents high mountainous terrain.
*/
Cached mountainBaseDef = mountainBaseDef();
/*
Module Subgroup: High mountainous terrain
This subgroup generates high mountain terrain that appears at high elevations within the mountain ranges.
-1 represents the lowest elevations and 1 represents the highest elevations.
*/
Cached mountainousHigh = mountainousHigh();
/*
Module Subgroup: Low mountainous terrain
This subgroup generates low mountainous terrain that appears at low elevations that appears within the river
valleys.
-1 represents the lowest elevations and 1 represents the highest elevations.
*/
Cached mountainousLow = mountainousLow();
/*
Module Subgroup: Mountainous terrain
This subgroup generates the final mountainous terrain by combining the high-mountainous-terrain module with
the low-mountainous-terrain.
-1 represents the lowest elevations and 1 represents the highest elevations.
*/
Cached mountainousTerrain = mountainousTerrain(mountainousLow, mountainousHigh, mountainBaseDef);
//
// Module Group: Hilly Terrain
//
/*
Module subgroup hilly terrain.
This subgroup represents the hilly terrain.
-1 represents the lowest elevations 1 represents the highest elevations.
*/
Cached hillyTerrain = hillyTerrain();
//
// Module group: Plains Terrain
//
/*
Module subgroup: plains terrain
This subgroups represents the plains terrain.
Because this subgroup will eventually be flattened considerably, the types and combinations of noise modules
that generate the plains are not really that important; they only need to "look" interesting.
-1 represents the lowest elevations, 1 represents the highest elevations.
*/
Cached plainsTerrain = plainsTerrain();
//
// Module Group: Badlands terrain
//
/*
Module subgroup: badlands sand
This group represents the sandy terrain of the badlands.
-1 represents the lowest elevations, 1 represents the highest elevations.
*/
Cached badlandsSand = badlandsSand();
/*
Module subgroup: badlands cliffs.
This group generates the cliffs for the badlands.
-1 represents the lowest elevations, 1 represents the highest elevations.
*/
Cached badlandsCliffs = badlandsCliffs();
/*
Module subgroup: badlands terrain
Generates the final badlands terrain.
Using a scale/bias module, the badlands sand is flattened considerably, then the sand elevations are lowered
to about -1.0. The maximum value from the flattened sand module and the cliff module contributes to the final
elevation. This causes sand to appear at low elevations since the sand is slightly higher than the cliff base.
-1 represents the lowest elevations, 1 represents the highest elevations.
*/
Cached badlandsTerrain = badlandsTerrain(badlandsSand, badlandsCliffs);
//
// Module group: River positions
//
/*
Module subgroup: River positions
This subgroup generates the river positions
-1 represents the lowest elevations, 1 represents the highest elevations.
*/
Cached riverPositions = riverPositions();
//
// Module group: Scaled mountainous terrain
//
// This subgroup scales the output value from the mountainous-terrain group so that it can be added
// to the elevation defined by the continent-definition group.
//
// This subgroup scales the output values such that it is almost always positive. This is done so that a
// negative elevation does not get applied to the continent-definition group, preventing parts of that group
// from having negative terrain features "stamped" into it.
//
// The output values from this module is measured in planetary elevation units (-1 for the lowest underwater
// trenches, 1 for the highest mountain peaks.
Cached scaledMountainousTerrain = scaledMountainousTerrain(mountainousTerrain);
//
// Module group: Scaled hilly terrain
//
// This subgroup scales the output value from the hilly-terrain group so that it can be added to the elevation
// defined by the continent-definition group. The scaling amount applied to the hills is one half of the
// scaling amount applied to the scaled-mountainous-terrain group.
//
// This subgroup scales the output value such that it is almost always positive. This is done so that a
// negative elevation does not get applied to the continent-definition group, preventing parts of that group
// from having negative terrain featuers "stamped" into it.
Cached scaledHillyTerrain = scaledHillyTerrain(hillyTerrain);
//
// Module group: Scaled plains terrain
//
// This subgroup scales the output value from the plains-terrain group so that it can be added to the elevation
// defined by the continent-definition group.
//
// This subgroup scales the output value such that it is almost always positive. This is done so that a
// negative elevation does not get applied to the continent-definition group, preventing parts of that group
// from having negative terrain features "stamped" into it.
Cached scaledPlainsTerrain = scaledPlainsTerrain(plainsTerrain);
//
// Module group: Scaled badlands terrain
//
// This subgroup scales the output value from the badlands-terrain group so that it can be added to the elevation
// defined by the continent-definition group.
//
// This subgroup scales the output value such that it is almost always positive. This is done so that a
// negative elevation does not get applied to the continent-definition group, preventing parts of that group
// from having negative terrain features "stamped" into it.
Cached scaledBadlandsTerrain = scaledBadlandsTerrain(badlandsTerrain);
//
// Module Group: Final Planet
//
/*
Module Subgroup: Continental Shelf
This module subgroup creates the continental shelves.
*/
Cached continentalShelf = continentalShelf(continentDef);
/*
Module Subgroup: Base Continent Elevations
The subgroup creates the base elevations of the continents, before terrain features are added.
*/
Cached baseContinentElev = baseContinentElev(continentDef, continentalShelf);
/*
Module Subgroup: Continents with plains
This subgroup applies the scaled-plains-terrain subgroup to the base-continent-elevation subgroup
*/
Cached continentsWithPlains = continentsWithPlains(baseContinentElev, scaledPlainsTerrain);
/*
Module Subgroup: Continents with hills
This subgroup applies the scaled-hilly-terrain to the continents-with-plains subgroup.
*/
Cached continentsWithHills = continentsWithHills(baseContinentElev, continentsWithPlains, scaledHillyTerrain, terrainTypeDef);
/*
Module Subgroup: Continents with mountains
This subgroup applies the scaled-mountainous-terrain subgroup to the continents-with-hills subgroup.
*/
Cached continentsWithMountains = continentsWithMountains(baseContinentElev, continentsWithHills, scaledMountainousTerrain, terrainTypeDef, continentDef);
/*
Module Subgroup: Continents with badlands
This subgroup applies the scaled-badlands-terrain subgroup the the continents-with-mountains subgroup.
*/
Cached continentsWithBadlands = continentsWithBadlands(baseContinentElev, scaledBadlandsTerrain, continentsWithMountains);
/*
Module Subgroup: Continents with Rivers
This subgroup applies the river-positions group to the continents-with-badlands subgroup.
*/
Cached continentsWithRivers = continentsWithRivers(riverPositions, continentsWithBadlands);
/*
Module Subgroup: Unscaled final planet.
*/
Cached unscaledFinalPlanet = new Cached(continentsWithRivers);
/*
Module subgroup: Final Planet
*/
ScaleBias finalPlanet_sb = new ScaleBias(unscaledFinalPlanet);
finalPlanet_sb.setScale((MAX_ELEV - MIN_ELEV) / 2.0);
finalPlanet_sb.setBias(MIN_ELEV + ((MAX_ELEV - MIN_ELEV) / 2.0));
finalPlanet = new Cached(finalPlanet_sb);
}
private Cached baseContinentDef() throws Exception {
// 1. [Continent Module] This Perlin-noise module generates the continents. This noise module
// generates the continents. This noise module has a high number of octaves so the detail is visible
// at high zoom levels.
Perlin baseContinentDef_pe0 = new Perlin();
baseContinentDef_pe0.setSeed(CUR_SEED);
baseContinentDef_pe0.setFrequency(CONTINENT_FREQUENCY);
baseContinentDef_pe0.setPersistence(0.5);
baseContinentDef_pe0.setLacunarity(CONTINENT_LACUNARITY);
baseContinentDef_pe0.setOctaveCount(14);
baseContinentDef_pe0.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_STD);
// 2. [Continent-with-ranges module] Next, a curve module modifies the output value from the coninent module
// so that high values appear near sea level. This defines the position of the mountain ranges.
Curve baseContinentDef_cu = new Curve(baseContinentDef_pe0); //TODO Possible error location.
baseContinentDef_cu.addControlPoint(-2.0000 + SEA_LEVEL, -1.625 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(-1.0000 + SEA_LEVEL, -1.375 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(0.0000 + SEA_LEVEL, -0.375 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(0.0625 + SEA_LEVEL, 0.125 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(0.1250 + SEA_LEVEL, 0.250 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(0.2500 + SEA_LEVEL, 1.000 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(0.5000 + SEA_LEVEL, 0.250 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(0.7500 + SEA_LEVEL, 0.250 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(1.0000 + SEA_LEVEL, 0.500 + SEA_LEVEL);
baseContinentDef_cu.addControlPoint(2.0000 + SEA_LEVEL, 0.500 + SEA_LEVEL);
// 3. [Carver Module] This higher-frequency Perlin-noise module will be used by subsequent noise modules
// to carve out chunks from the mountain ranges within the continent-with-ranges module so that the mountain
// ranges will not be completely impassible.
Perlin baseContinentDef_pe1 = new Perlin();
baseContinentDef_pe1.setSeed(CUR_SEED + 1);
baseContinentDef_pe1.setFrequency(CONTINENT_FREQUENCY * 4.34375);
baseContinentDef_pe1.setPersistence(0.5);
baseContinentDef_pe1.setLacunarity(CONTINENT_LACUNARITY);
baseContinentDef_pe1.setOctaveCount(11);
baseContinentDef_pe1.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_STD);
// 4. [Scaled-carver module] This scale-bias modules scales the output value from the carver module
// so that it is usually near 1. This is required for step 5.
ScaleBias baseContinentDef_sb = new ScaleBias(baseContinentDef_pe1);
baseContinentDef_sb.setScale(0.375);
baseContinentDef_sb.setBias(0.625);
// 5. [Carved-continent module] This minimum-value module carves out chunks from the continent-with-ranges
// module. It does this by ensuring that only the minimum of the output values from the scaled-carver module
// the the continent-with-ranges module contribute to the output value of this subgroup. Most of the time,
// the minimum-value module will select the output value from the continent-with-ranges module since the output
// from the scaled-carver module is usually near 1. Occassionally, the output value from the scaled-carver module
// will be less than the output value from continent-with-ranges module, so in this case, the output from the
// scaled carver module is selected.
Min baseContinentDef_mi = new Min(baseContinentDef_sb, baseContinentDef_cu);
// 6. [Clamped-continent module] Finally a clamp module modified the carved-continent module so that the output
// values are between -1 and 1.
Clamp baseContinentDef_cl = new Clamp(baseContinentDef_mi);
baseContinentDef_cl.setBounds(-1, 1);
// 7. [Base-continent-definition subgroup] Caches the output from the clamped-continent module.
return new Cached(baseContinentDef_cl);
}
private Cached continentDef(Cached baseContinentDef) throws Exception {
// 1. [Course-turbulence module] This turbulence module warps the output value from the base-continent subgroup
// adding some course detail to it.
Turbulence continentDef_tu0 = new Turbulence(baseContinentDef);
continentDef_tu0.setSeed(CUR_SEED + 10);
continentDef_tu0.setFrequency(CONTINENT_FREQUENCY * 15.25);
continentDef_tu0.setPower(CONTINENT_FREQUENCY / 113.75);
continentDef_tu0.setRoughness(13);
// 2. [Intermediate-turbulence module] This turbulence module warps the output value from the course-turbulence
// module. The turbulence has a higher frequency, but lower power, than the course-turbulence module, adding
// some intermediate detail to it.
Turbulence continentDef_tu1 = new Turbulence(continentDef_tu0);
continentDef_tu1.setSeed(CUR_SEED + 11);
continentDef_tu1.setFrequency(CONTINENT_FREQUENCY * 47.25);
continentDef_tu1.setPower(CONTINENT_FREQUENCY / 433.75);
continentDef_tu1.setRoughness(12);
// 3. [Warped-base-continent-definition module] This turbulence module warps the output value from the
// intermediate-turbulence module. This turbulence has a higher frequency, but lower power, than the
// intermediate-turbulence module, adding some fine detail to it.
Turbulence continentDef_tu2 = new Turbulence(continentDef_tu1);
continentDef_tu2.setSeed(CUR_SEED + 12);
continentDef_tu2.setFrequency(CONTINENT_FREQUENCY * 95.25);
continentDef_tu2.setPower(CONTINENT_FREQUENCY / 1019.75);
continentDef_tu2.setRoughness(11);
// 4. [Select-turbulence module] At this stage, the turbulence is applied to the entire base-continent-definition
// subgroup, producing some very rugged, unrealistic coastlines. This selector module selects the output values
// from the (unwarped) base-continent-definition subgroup and the warped-base-continent-definition module, based
// on the output value from the (unwarped) base-continent-definition subgroup. The selection boundry is near sea
// level and has a relativly smooth transition. In effect, only the higher areas of the base-continent-definition
// subgroup get warped; the underwater and coastal areas remain uneffected.
Select continentDef_se = new Select(baseContinentDef, continentDef_tu2, baseContinentDef);
continentDef_se.setBounds(SEA_LEVEL - 0.0375, SEA_LEVEL + 1000.0375);
continentDef_se.setEdgeFalloff(0.0625);
// 5. [continent-definition subgroup] Caches the output.
return new Cached(continentDef_se);
}
private Cached terrainTypeDef(Cached continentDef) throws Exception {
// 1. [Warped-continent module] This turbulence slightly warps the output value from the continent-definition
// group. This prevents the rougher terrain from exclusivly appearing at higher elevations. Rough areas may now
// appear in the ocean, creating rocky islands and fjords.
Turbulence terrainTypeDef_tu = new Turbulence(continentDef);
terrainTypeDef_tu.setSeed(CUR_SEED + 20);
terrainTypeDef_tu.setFrequency(CONTINENT_FREQUENCY * 18.125);
terrainTypeDef_tu.setPower(CONTINENT_FREQUENCY / 20.59375 * TERRAIN_OFFSET);
terrainTypeDef_tu.setRoughness(3);
// 2. [Roughness-probability-shift module] This terracing module sharpens the edges of the warped-continent
// module near sea level and lowers the slope towards the higher elevation areas. This shrinks the areas in
// which rough terrain appears, increasing the "rarity" of rough terrain.
Terrace terrainTypeDef_te = new Terrace(terrainTypeDef_tu);
terrainTypeDef_te.addControlPoint(-1);
terrainTypeDef_te.addControlPoint(SHELF_LEVEL + SEA_LEVEL / 2);
terrainTypeDef_te.addControlPoint(1);
// 3. Returns the cached output.
return new Cached(terrainTypeDef_te);
}
private Cached mountainBaseDef() throws Exception {
// 1. This ridged-multifractal-noise module generates the mountain ridges.
RidgedMulti mountainBaseDef_rm0 = new RidgedMulti();
mountainBaseDef_rm0.setSeed(CUR_SEED + 30);
mountainBaseDef_rm0.setFrequency(1723);
mountainBaseDef_rm0.setLacunarity(MOUNTAIN_LACUNARITY);
mountainBaseDef_rm0.setOctaveCount(4);
mountainBaseDef_rm0.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_STD);
// 2. [Scaled-mountain-ridge module] Next, a scale bias module scaled the output value from the mountain-ridge
// module so that it's not too high. The reason for this is thtat another subgroup adds actual mountainous
// terrain to the ridges.
ScaleBias mountainBaseDef_sb0 = new ScaleBias(mountainBaseDef_rm0);
mountainBaseDef_sb0.setScale(0.5);
mountainBaseDef_sb0.setBias(0.375);
// 3. [River-valley module] This ridge-multifractal-noise module generates the river valleys. It has a much
// lower frequency than the mountain-ridge module so that more mountain ridges will remain outside of the
// valleys. Note that this noise module generates ridged-multifractal noise using only one octave; this
// information will be important in the next step.
RidgedMulti mountainBaseDef_rm1 = new RidgedMulti();
mountainBaseDef_rm1.setSeed(CUR_SEED + 31);
mountainBaseDef_rm1.setFrequency(367);
mountainBaseDef_rm1.setLacunarity(MOUNTAIN_LACUNARITY);
mountainBaseDef_rm1.setOctaveCount(1);
mountainBaseDef_rm1.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 4. [Scaled-river-valley module] Next, a scale/bias module applies a scaling factor of -2 to the river-valley
// module. This stretches the possible elevation values because one-octave ridged-multifractal noise has a lower
// range of output values then multi-octave ridged-multifractal noise. The negative scaling factor inverts the
// range of the output value, turning the ridges from the river-valley module into the valleys.
ScaleBias mountainBaseDef_sb1 = new ScaleBias(mountainBaseDef_rm1);
mountainBaseDef_sb1.setScale(-2);
mountainBaseDef_sb1.setBias(-0.5);
// 5. [Low-flat module] This low constant value is used by step 6.
Const mountainBaseDef_co = new Const();
mountainBaseDef_co.setConstValue(-1);
// 6. [Mountain-and-valleys module] This blender module merges the scaled-mountain-ridge module and the
// scaled-river-valley module together. It cause the low-lying area of the terrain to become smooth, and
// causes the high-lying areas of the terrain to contain ridges. To do this, it uses the scaled-river-valley
// module as the control module, causing the low-flat module to appear in the lower areas and causing the
// scaled-mountain-ridges to appear in the high areas.
Blend mountainBaseDef_bl = new Blend(mountainBaseDef_co, mountainBaseDef_sb0, mountainBaseDef_sb1);
// 7. [Course-turbulence module] This turbulence module warps the output value from the mountain-and-valleys
// module, adding some course detain to it.
Turbulence mountainBaseDef_tu0 = new Turbulence(mountainBaseDef_bl);
mountainBaseDef_tu0.setSeed(CUR_SEED + 32);
mountainBaseDef_tu0.setFrequency(1337);
mountainBaseDef_tu0.setPower(1.0 / 6730.0 * MOUNTAINS_TWIST);
mountainBaseDef_tu0.setRoughness(6);
// 8. [Warped-mountains-and-valleys module] This turbulence module warps the output value from the
// course-turbulence module/ This turbulence has a higher frequency, but lower power, than the course-turbulence
// module, adding some detail to it.
Turbulence mountainBaseDef_tu1 = new Turbulence(mountainBaseDef_tu0);
mountainBaseDef_tu1.setSeed(CUR_SEED + 33);
mountainBaseDef_tu1.setFrequency(21221);
mountainBaseDef_tu1.setPower(1.0 / 120157.0 * MOUNTAINS_TWIST);
mountainBaseDef_tu1.setRoughness(6);
// 9. [Mountain-base-definition subgroup] Cached output
return new Cached(mountainBaseDef_tu1);
}
private Cached mountainousHigh() throws Exception {
// 1. [Mountain-basis-0 module] This ridged-multifractal module, along with the mountain-basis-1 module
// generates the individual mountains.
RidgedMulti mountainousHigh_rm0 = new RidgedMulti();
mountainousHigh_rm0.setSeed(CUR_SEED + 40);
mountainousHigh_rm0.setFrequency(2371);
mountainousHigh_rm0.setLacunarity(MOUNTAIN_LACUNARITY);
mountainousHigh_rm0.setOctaveCount(3);
mountainousHigh_rm0.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 2. [Mountain-basis-1 module] This ridged-multifractal module, alone with the mountain-basis-0 module
// generates the individual mountains.
RidgedMulti mountainousHigh_rm1 = new RidgedMulti();
mountainousHigh_rm1.setSeed(CUR_SEED + 41);
mountainousHigh_rm1.setFrequency(2341);
mountainousHigh_rm1.setLacunarity(MOUNTAIN_LACUNARITY);
mountainousHigh_rm1.setOctaveCount(3);
mountainousHigh_rm1.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 3. [High-mountains module] Next, a maximum value module causes more mountains to appear at the expense of
// valleys. It does this by ensuring that only the maximum of the output values from the two ridged-multifractal
// modules contribute to the output value of this group.
Max mountainousHigh_ma = new Max(mountainousHigh_rm0, mountainousHigh_rm1);
// 4. [Warped-high-mountains module] This turbulence module warps the output value from the high-mountains
// module, adding some detail to it.
Turbulence mountainousHigh_tu = new Turbulence(mountainousHigh_ma);
mountainousHigh_tu.setSeed(CUR_SEED + 42);
mountainousHigh_tu.setFrequency(31511);
mountainousHigh_tu.setPower(1.0 / 180371.0 * MOUNTAINS_TWIST);
mountainousHigh_tu.setRoughness(4);
// 5. [High-mountainous-terrain subgroup] Cached values of the output.
return new Cached(mountainousHigh_tu);
}
private Cached mountainousLow() throws Exception {
// 1. [Lowland-basis-0 module] This ridged-multifractal module, along with lowland-basis-1, produces the
// low mountainous terrain.
RidgedMulti mountainousLow_rm0 = new RidgedMulti();
mountainousLow_rm0.setSeed(CUR_SEED + 50);
mountainousLow_rm0.setFrequency(1381);
mountainousLow_rm0.setLacunarity(MOUNTAIN_LACUNARITY);
mountainousLow_rm0.setOctaveCount(8);
mountainousLow_rm0.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 2. [Lowland-basis-1 module] This ridged-multifractal module, along with lowland-basis-0, produces the
// low mountainous terrain.
RidgedMulti mountainousLow_rm1 = new RidgedMulti();
mountainousLow_rm1.setSeed(CUR_SEED + 51);
mountainousLow_rm1.setFrequency(1427);
mountainousLow_rm1.setLacunarity(MOUNTAIN_LACUNARITY);
mountainousLow_rm1.setOctaveCount(8);
mountainousLow_rm1.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 3. [Low-mountainous-terrain module] This multiplications module combines the output values from the two
// ridged-multifractal-noise modules. This causes the following to appear in the terrain:
//
// - Cracks appear when two negative values are multiplies together.
// - Flat areas when a negative and a positive value are multiplied together.
// - Ridges appear when two positive values are mulitiplied together.
Multiply mountainousLow_mu = new Multiply(mountainousLow_rm0, mountainousLow_rm1);
// 4. [Low-mountainous-terrain subgroup] Cached output of the values.
return new Cached(mountainousLow_mu);
}
private Cached mountainousTerrain(Cached mountainousLow, Cached mountainousHigh, Cached mountainousBaseDef) throws Exception{
// 1. [Scaled-low-mountainous-terrain module] First, this scale/bias module scales the output value from
// the low-mountainous-terrain module to a very low value and biases it towards -1. This results in the low
// mountainous areas becoming more-or-less flat with little variation. This will also result in the low
// mountainous areas appearing in the lowest elevations in this subgroup.
ScaleBias mountainousTerrain_sb0 = new ScaleBias(mountainousLow);
mountainousTerrain_sb0.setScale(0.03125);
mountainousTerrain_sb0.setBias(-0.96875);
// 2. [Scaled-high-mountainous-terrain module] Next, this scale/bias module scales the output value of the
// high-mountainous-terrain module to 1/4th of its initial values and biases it so that it's output is
// usually positive.
ScaleBias mountainousTerrain_sb1 = new ScaleBias(mountainousHigh);
mountainousTerrain_sb1.setScale(0.25);
mountainousTerrain_sb1.setBias(0.25);
// 3. [Added-mountainous-terrain module] This addition module adds the output values from the
// scaled-high-mountainous-terrain module to the output value from the mountain-base-definition subgroup.
// Mountains now appear all over the terrain.
Add mountainousTerrain_ad = new Add(mountainousTerrain_sb1, mountainousBaseDef);
// 4. [Combined-mountainous-terrain module] Note that at this point, the entire terrain is covered in high
// mountainous terrain, even at the low elevations. To make sure the mountains only appear at higher elevations,
// this selector module causes low mountainous terrain to appear at the low elevations (within the valleys)
// and the high mountainous to appear at the high elevations (within the ridges). To do this, this noise module
// selects the output values from the added-high-mountainous-terrain module if the output value from the
// mountain-base-definition subgroup is higher than a set amount. Otherwise, this noise module selects the
// output value from the scaled-high-mountainous-terrain module.
Select mountainousTerrain_se = new Select(mountainousTerrain_sb0, mountainousTerrain_ad, mountainousBaseDef);
mountainousTerrain_se.setBounds(-0.5, 999.5);
mountainousTerrain_se.setEdgeFalloff(0.5);
// 5. [Scaled-mountainous-terrain module] This scale/bias slightly reduces the range of the output value from
// the combined-mountainous-terrain module, slightly reducing the height of the mountain peaks.
ScaleBias mountainousTerrain_sb2 = new ScaleBias(mountainousTerrain_se);
mountainousTerrain_sb2.setScale(0.8);
mountainousTerrain_sb2.setBias(0.0);
// 6. [Glacaiated-mountainous-terrain module] This exponential-curve module applies an exponential curve to the
// output value from the scaled-mountainous-terrain module. This causes the slope of the mountains to smoothly
// increase towards higher elevations, as if a glacier grinded out those mountains. This exponential curve
// module expects the output value to range from -1 to 1.
Exponent mountainousTerrain_ex = new Exponent(mountainousTerrain_sb2);
mountainousTerrain_ex.setExponent(MOUNTAIN_GLACIATION);
// 7. [mountainous-terrain module] Caches the output.
return new Cached(mountainousTerrain_ex);
}
private Cached hillyTerrain() throws Exception {
// 1. [Hills module] This billow-noise module generates the hills.
Billow hillyTerrain_bi = new Billow();
hillyTerrain_bi.setSeed(CUR_SEED + 60);
hillyTerrain_bi.setFrequency(1663);
hillyTerrain_bi.setPersistence(0.5);
hillyTerrain_bi.setLacunarity(HILLS_LACUNARITY);
hillyTerrain_bi.setOctaveCount(6);
hillyTerrain_bi.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 2. [Scaled-hills module] Next, a scale/bias module scales the output value from the hills module so that
// the hilltops are not too high. The reason for this is that the hills are eventually added to the river
// valleys. (see below)
ScaleBias hillyTerrain_sb0 = new ScaleBias(hillyTerrain_bi);
hillyTerrain_sb0.setScale(0.5);
hillyTerrain_sb0.setBias(0.5);
// 3. [River-valley module] This ridged-multifractal-noise module generates the river valleys. It has a much
// lower frequency so that more hills will appear between the valleys. Note that this ridged-multifractal module
// generates noise using only a single octave; this information will be important in the next step.
RidgedMulti hillyTerrain_rm = new RidgedMulti();
hillyTerrain_rm.setSeed(CUR_SEED + 61);
hillyTerrain_rm.setFrequency(367.5);
hillyTerrain_rm.setLacunarity(HILLS_LACUNARITY);
hillyTerrain_rm.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
hillyTerrain_rm.setOctaveCount(1);
// 4. [Scaled-river-valley module] Next a scale/bias module applies a scaling factor of -2 to the output value
// from the river-valley module. This stretches the possible elevation values because one-octave
// ridged-multifractal noise has a lower range of output values than multiple-octave ridge-multifractal noise.
// The negative scaling factor inverts the range of the output value, turning the ridges into valleys.
ScaleBias hillyTerrain_sb1 = new ScaleBias(hillyTerrain_rm);
hillyTerrain_sb1.setScale(-2);
hillyTerrain_sb1.setBias(-0.5);
// 5. [Low-flat module] This low constant value is used by step 6.
Const hillyTerrain_co = new Const();
hillyTerrain_co.setConstValue(-1);
// 6. [Hills-and-valleys module] This blender module merges the scaled-hills module and the
// scaled-river-valley module together. It causes the low-lying areas of the terrain to become smooth, and
// causes the high-lying areas of the terrain to contain hills. To do this, it uses the scaled-hills module
// as the control module, causing the low-flat module to appear in the lower areas and the scaled-river-valley
// module to appear in the higher areas.
Blend hillyTerrain_bl = new Blend(hillyTerrain_co, hillyTerrain_sb1, hillyTerrain_sb0);
// 7. [Scaled-hills-and-valleys module] This scale/bias module slightly reduces the range of the output value
// from the hills-and-valleys module, decreasing the heights of the hilltops.
ScaleBias hillyTerrain_sb2 = new ScaleBias(hillyTerrain_bl);
hillyTerrain_sb2.setScale(0.75);
hillyTerrain_sb2.setBias(-0.25);
// 8. [Increased-slope-hilly-terrain module] To increase the hill slopes at higher elevations, this
// exponential-curve module applies an exponential curve to the output value of the scaled-hills-and-valleys
// module. This exponential-curve modules expects the input value to range from -1 to 1.
Exponent hillyTerrain_ex = new Exponent(hillyTerrain_sb2);
hillyTerrain_ex.setExponent(1.375);
// 9. [Coarse-turbulence module] This turbulence module warps the output value from the
// increased-slope-hilly-terrain module, adding some coarse detail to it.
Turbulence hillyTerrain_tu0 = new Turbulence(hillyTerrain_ex);
hillyTerrain_tu0.setSeed(CUR_SEED + 62);
hillyTerrain_tu0.setFrequency(1531);
hillyTerrain_tu0.setPower(1.0 / 16921.0 * HILLS_TWIST);
hillyTerrain_tu0.setRoughness(4);
// 10. [Warped-hilly-terrain module] This turbulence modules warps the output value from the coarse-turbulence
// module. This turbulence has a higher frequency, but a lower power, then the coarse-turbulence module, adding
// some fine detail to it.
Turbulence hillyTerrain_tu1 = new Turbulence(hillyTerrain_tu0);
hillyTerrain_tu1.setSeed(CUR_SEED + 63);
hillyTerrain_tu1.setFrequency(21617.0);
hillyTerrain_tu1.setPower(1.0 / 117529 * HILLS_TWIST);
hillyTerrain_tu1.setRoughness(6);
// 11. [Hilly-terrain subgroup] Caches the output
return new Cached(hillyTerrain_tu1);
}
private Cached plainsTerrain() throws Exception {
// 1. [Plains-basis-0] This billow-noise module, along with the plains-basis-1 module, produces the plains.
Billow plainsTerrain_bi0 = new Billow();
plainsTerrain_bi0.setSeed(CUR_SEED + 70);
plainsTerrain_bi0.setFrequency(1097.5);
plainsTerrain_bi0.setPersistence(0.5);
plainsTerrain_bi0.setLacunarity(PLAINS_LACUNARITY);
plainsTerrain_bi0.setOctaveCount(8);
plainsTerrain_bi0.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 2. [Positive-plains-basis-0 module] This scale/bias module makes the output value from the plains-basis-0
// module positive since this output value will be multiplied together with positive-plains-basis-1 module.
ScaleBias plainsTerrain_sb0 = new ScaleBias(plainsTerrain_bi0);
plainsTerrain_sb0.setScale(0.5);
plainsTerrain_sb0.setBias(0.5);
// 3. [Plains-basis-1] This billow-noise module, along with the plains-basis-0 module, produces the plains.
Billow plainsTerrain_bi1 = new Billow();
plainsTerrain_bi1.setSeed(CUR_SEED + 71);
plainsTerrain_bi1.setFrequency(1319);
plainsTerrain_bi1.setPersistence(0.5);
plainsTerrain_bi1.setLacunarity(PLAINS_LACUNARITY);
plainsTerrain_bi1.setOctaveCount(8);
plainsTerrain_bi1.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 4. [Positive-plains-basis-1 module] This scale/bias modules makes the output value from the plains-basis-1
// module positive since this output values will be multiplied together with positive-plains-basis-0 module.
ScaleBias plainsTerrain_sb1 = new ScaleBias(plainsTerrain_bi1);
plainsTerrain_sb1.setScale(0.5);
plainsTerrain_sb1.setBias(0.5);
// 5. [Combined-plains-basis module] This multiplication module combines the two plains noise modules together.
Multiply plainsTerrain_mu = new Multiply(plainsTerrain_sb0, plainsTerrain_sb1);
// 6. [Rescaled-plains-basis module] This scale/bias module maps the output value that ranges from 0 to 1 back
// to a value that ranges from -1 to 1
ScaleBias plainsTerrain_sb2 = new ScaleBias(plainsTerrain_mu);
plainsTerrain_sb2.setScale(2);
plainsTerrain_sb2.setBias(-1);
// 7. [Plains-terrain group] Caches the output value
return new Cached(plainsTerrain_sb2);
}
private Cached badlandsSand() throws Exception {
// 1. [Sand-dunes module] This ridged-multifractal-noise module generates sand dunes. This
// ridged-multifractal-noise is generated with one octave, which make very smooth dunes.
RidgedMulti badlandsSand_rm = new RidgedMulti();
badlandsSand_rm.setSeed(CUR_SEED + 80);
badlandsSand_rm.setFrequency(6163.5);
badlandsSand_rm.setLacunarity(BADLANDS_LACUNARITY);
badlandsSand_rm.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
badlandsSand_rm.setOctaveCount(1);
// 2. [Scaled-sand-dunes module] This scale/bias module shrinks the dune height by a small amount. This is
// necessary so that subsequent modules can add some detail to the dunes.
ScaleBias badlandsSand_sb0 = new ScaleBias(badlandsSand_rm);
badlandsSand_sb0.setScale(0.875);
badlandsSand_sb0.setBias(0);
// 3. [Dune-detail module] This noise module uses Voronoi polygons to generate the detail to add to the dunes.
// By enabling the distance alogorithm, small plygonal pits are generated; the edges of the pits are joined
// to the edges of nearby pits.
Voronoi badlandsSand_vo = new Voronoi();
badlandsSand_vo.setSeed(CUR_SEED + 81);
badlandsSand_vo.setFrequency(16183.25);
badlandsSand_vo.setDisplacement(0);
badlandsSand_vo.enableDistance(true);
// 4. [Scaled-dune-detail module] This scale/bias modules shrinks the dune details by a large amount. This is
// necessary so that the subsequent noise modules in this subgroup can add this detail to the sand-dunes module.
ScaleBias badlandsSand_sb1 = new ScaleBias(badlandsSand_vo);
badlandsSand_sb1.setScale(0.25);
badlandsSand_sb1.setBias(0.25);
// 5. [Dunes-with-detail module] This addition modules combines the scaled-sand-dunes module with the
// scaled-dune-detail module.
Add badlandsSand_ad = new Add(badlandsSand_sb0, badlandsSand_sb1);
// 6. Cached output
return new Cached(badlandsSand_ad);
}
private Cached badlandsCliffs() throws Exception{
// 1. [Cliff-basis module] This Perlin-noise module generates some coherent noise that will be used to
// generate the cliffs.
Perlin badlandsCliffs_pe = new Perlin();
badlandsCliffs_pe.setSeed(CUR_SEED + 90);
badlandsCliffs_pe.setFrequency(CONTINENT_FREQUENCY * 839);
badlandsCliffs_pe.setPersistence(0.5);
badlandsCliffs_pe.setLacunarity(BADLANDS_LACUNARITY);
badlandsCliffs_pe.setOctaveCount(6);
badlandsCliffs_pe.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_STD);
// 2. [Cliff-shaping-module] Next, this curve module applies a curve to the output value from the cliff-basis
// module. This curve is initially very shallow, but then its slope increases sharply. At the highest elevations
// the curve becomes very flat again. The produces the sterotypical Utah-style desert cliffs.
Curve badlandsCliffs_cu = new Curve(badlandsCliffs_pe);
badlandsCliffs_cu.addControlPoint(-2.0000, -2.0000);
badlandsCliffs_cu.addControlPoint(-1.0000, -1.2500);
badlandsCliffs_cu.addControlPoint(-0.0000, -0.7500);
badlandsCliffs_cu.addControlPoint(0.5000, -0.2500);
badlandsCliffs_cu.addControlPoint(0.6250, 0.8750);
badlandsCliffs_cu.addControlPoint(0.7500, 1.0000);
badlandsCliffs_cu.addControlPoint(2.0000, 1.2500);
// 3. [Clamped-cliffs module] This clamping module makes the tops of cliffs very flat by clamping the output of
// the cliff-shaping value.
Clamp badlandsCliffs_cl = new Clamp(badlandsCliffs_cu);
badlandsCliffs_cl.setBounds(-999.125, 0.875);
// 4. [Terraced-cliffs module] Next, this terracing module applies some terraces to the clamped-cliffs module
// in the lower elevations before the sharp cliff transitions.
Terrace badlandsCliffs_te = new Terrace(badlandsCliffs_cl);
badlandsCliffs_te.addControlPoint(-1.0000);
badlandsCliffs_te.addControlPoint(-0.8750);
badlandsCliffs_te.addControlPoint(-0.7500);
badlandsCliffs_te.addControlPoint(-0.5000);
badlandsCliffs_te.addControlPoint(0.0000);
badlandsCliffs_te.addControlPoint(1.0000);
// 5. [Coarse-turbulence module] This turbulence module warps the output from the terraced-cliffs module,
// allowing some coarse detail to it.
Turbulence badlandsCliffs_tu0 = new Turbulence(badlandsCliffs_te);
badlandsCliffs_tu0.setSeed(CUR_SEED + 91);
badlandsCliffs_tu0.setFrequency(16111);
badlandsCliffs_tu0.setPower(1.0 / 141539.0 * BADLANDS_TWIST);
badlandsCliffs_tu0.setRoughness(3);
// 6. [Warped-cliffs module] This turbulence module warps the output from coarse-turbulence module. This
// turbulence has a higher frequency, but lower power, than coarse-turbulence module, adding some fine
// detail to it.
Turbulence badlandsCliffs_tu1 = new Turbulence(badlandsCliffs_tu0);
badlandsCliffs_tu1.setSeed(CUR_SEED + 92);
badlandsCliffs_tu1.setFrequency(36107);
badlandsCliffs_tu1.setPower(1.0 / 211543.0 * BADLANDS_TWIST);
badlandsCliffs_tu1.setRoughness(3);
// 7 Cached output
return new Cached(badlandsCliffs_tu1);
}
private Cached badlandsTerrain(Cached badlandsSand, Cached badlandsCliffs) throws Exception {
// 1. [Scaled-sand-dunes module] This scale/bias module considerably flattens the output value from the
// badlands-sand subgroup and lowers this value to near -1
ScaleBias badlandsTerrain_sb0 = new ScaleBias(badlandsSand);
badlandsTerrain_sb0.setScale(0.25);
badlandsTerrain_sb0.setBias(-0.75);
// 2. [Dunes-and-cliffs module] This maximum value module causes the dunes to appear in the low areas and
// the cliffs to appear in the high areas. It does this by selecting the maximum of the output values from
// the scaled-sand-dunes and the badlands-cliffs modules.
Max badlandsTerrain_ma = new Max(badlandsTerrain_sb0, badlandsCliffs);
// 3. Cached output
return new Cached(badlandsTerrain_ma);
}
private Cached riverPositions() throws Exception {
// 1. [large-river-basis module] This ridged-multifractal-noise module creates the large, deep rivers.
RidgedMulti riverPositions_rm0 = new RidgedMulti();
riverPositions_rm0.setSeed(CUR_SEED + 100);
riverPositions_rm0.setFrequency(18.75);
riverPositions_rm0.setLacunarity(CONTINENT_LACUNARITY);
riverPositions_rm0.setOctaveCount(1);
riverPositions_rm0.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 2. [Large-river-curve module] This curve module applies a curve to the output value from the
// large-river-basis module so that the ridges become inverted. This creates rivers. This curve
// also compresses the edge of the rivers, producing a sharp transistion from the land to the river bottom.
Curve riverPositions_cu0 = new Curve(riverPositions_rm0);
riverPositions_cu0.addControlPoint(-2.000, 2.000);
riverPositions_cu0.addControlPoint(-1.000, 1.000);
riverPositions_cu0.addControlPoint(-0.125, 0.875);
riverPositions_cu0.addControlPoint(0.000, -1.000);
riverPositions_cu0.addControlPoint(1.000, -1.500);
riverPositions_cu0.addControlPoint(2.000, -2.000);
// 3. [Small-river-basis module] This ridged-multifractal-nosie module creates the small, shallow rivers.
RidgedMulti riverPositions_rm1 = new RidgedMulti();
riverPositions_rm1.setSeed(CUR_SEED + 101);
riverPositions_rm1.setFrequency(43.25);
riverPositions_rm1.setLacunarity(CONTINENT_LACUNARITY);
riverPositions_rm1.setOctaveCount(1);
riverPositions_rm1.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 4. [Small-river-curve module] This curve modules applies a curve to the output value from the
// small-river-basis module so that the ridges become inverted. This creates the rivers. This curve
// also compresses the edge of the rivers, producing a sharp transition from the land to the river bottom.
Curve riverPositions_cu1 = new Curve(riverPositions_rm1);
riverPositions_cu1.addControlPoint(-2.000, 2.0000);
riverPositions_cu1.addControlPoint(-1.000, 1.5000);
riverPositions_cu1.addControlPoint(-0.125, 1.4375);
riverPositions_cu1.addControlPoint(0.000, 0.5000);
riverPositions_cu1.addControlPoint(1.000, 0.2500);
riverPositions_cu1.addControlPoint(2.000, 0.0000);
// 5. [combined-rivers module] This minimum value module causes the small river to cut into the large rivers.
// It does this by selecting the minimum output values from the large-river-curve module and the
// smll-river-curve module.
Min riverPositions_mi = new Min(riverPositions_cu0, riverPositions_cu1);
// 6. [Warped-rivers module] This turbulence module warps the output values from the combined-rivers module
// which twists the rivers. The high roughness produces less-smooth rivers.
Turbulence riverPositions_tu = new Turbulence(riverPositions_mi);
riverPositions_tu.setSeed(CUR_SEED + 102);
riverPositions_tu.setFrequency(9.25);
riverPositions_tu.setPower(1.0 / 57.75);
riverPositions_tu.setRoughness(6);
// 7. Cached output
return new Cached(riverPositions_tu);
}
private Cached scaledMountainousTerrain(Cached mountainousTerrain) throws Exception {
// 1. [Base-scaled-mountainous-terrain module] This scale/bias module scales the output value from the
// mountainout-terrain module so that the output value is measured in planetary elevation units.
ScaleBias scaledMountainousTerrain_sb0 = new ScaleBias(mountainousTerrain);
scaledMountainousTerrain_sb0.setScale(0.125);
scaledMountainousTerrain_sb0.setBias(0.125);
// 2. [base-peak-modulation module] At this stage, most mountain peaks have roughly the same elevation. This
// Perlin-noise module generates some random values that will be used by subsequent noise modules to randomly
// change the elevations of the mountain peaks.
Perlin scaledMountainousTerrain_pe = new Perlin();
scaledMountainousTerrain_pe.setSeed(CUR_SEED + 110);
scaledMountainousTerrain_pe.setFrequency(14.5);
scaledMountainousTerrain_pe.setPersistence(0.5);
scaledMountainousTerrain_pe.setLacunarity(MOUNTAIN_LACUNARITY);
scaledMountainousTerrain_pe.setOctaveCount(6);
scaledMountainousTerrain_pe.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_STD);
// 3. [Peak-modulation module] This exponential-curve module applies an exponential curve to the output value
// from the base-peak-modulation module. This produces a small number of high values and a much larger number of
// low values. This means there will be a few peaks with much higher elevations then the majority of the peaks,
// making the terrain features more varied.
Exponent scaledMountainousTerrain_ex = new Exponent(scaledMountainousTerrain_pe);
scaledMountainousTerrain_ex.setExponent(1.25);
// 4. [Scaled-peak-modulation module] This scale/bias module modifies the range of the output value from the
// peak-modulation module so that it can be used as the modulator for the peak-height-multiplier module.
// It is important that this output value is not much lower than 1.
ScaleBias scaledMountainousTerrain_sb1 = new ScaleBias(scaledMountainousTerrain_ex);
scaledMountainousTerrain_sb1.setScale(0.25);
scaledMountainousTerrain_sb1.setBias(1);
// 5. [Peak-height-multiplier module] This multiplier module modulates the heights of the mountain peaks from
// the base-scaled-mountainous-terrain module using the output value from the scaled-peak-modulation module.
Multiply scaledMountainousTerrain_mu = new Multiply(scaledMountainousTerrain_sb0, scaledMountainousTerrain_sb1);
// 6. Cached output
return new Cached(scaledMountainousTerrain_mu);
}
private Cached scaledHillyTerrain(Cached hillyTerrain) throws Exception {
// 1. [base-scaled-hilly-terrain module] This scale/bias module scales the output from hilly-terrain group so
// that this output value is measured in planetary units.
ScaleBias scaledHillyTerrain_sb0 = new ScaleBias(hillyTerrain);
// 2. [base-hilltop-modulation module] At this stage, most hilltops have roughly the same elevation. This
// Perlin-noise module generates some random values that will be used by subsequent noise modules to randomly
// change the elevations of the hilltops.
Perlin scaledHillyTerrain_pe = new Perlin();
scaledHillyTerrain_pe.setSeed(CUR_SEED + 120);
scaledHillyTerrain_pe.setFrequency(13.5);
scaledHillyTerrain_pe.setPersistence(0.5);
scaledHillyTerrain_pe.setLacunarity(HILLS_LACUNARITY);
scaledHillyTerrain_pe.setOctaveCount(6);
scaledHillyTerrain_pe.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_STD);
// 3. [Hilltop-modulation module] This exponential-curve module applies an exponential curve to the output
// value from the base-hilltop-modulation module. This produces a small number of high values and a much larger
// number of low values. This means there will be a few hilltops with much higher elevations, making the
// terrain features more varied.
Exponent scaledHillyTerrain_ex = new Exponent(scaledHillyTerrain_pe);
scaledHillyTerrain_ex.setExponent(1.25);
// 4. [scaled-hilltop-modulation module] This scale/bias module modifies the range of the output value from
// hilltop-modulation module so that it can be used as the modulator for the hilltop-height-multiplier module.
// It is important that this output value is not much lower than 1.
ScaleBias scaledHillyTerrain_sb1 = new ScaleBias(scaledHillyTerrain_ex);
scaledHillyTerrain_sb1.setScale(0.5);
scaledHillyTerrain_sb1.setBias(1.5);
// 5. [Hilltop-height-multiplier module] This multiplier module modulates the heights of the hilltops from the
// base-scaled-hilly-terrain module using the output value from scaled-hilltop-modulation module.
Multiply scaledHillyTerrain_mu = new Multiply(scaledHillyTerrain_sb0, scaledHillyTerrain_sb1);
// 6. Cached output.
return new Cached(scaledHillyTerrain_mu);
}
private Cached scaledPlainsTerrain(Cached plainsTerrain) throws Exception {
// 1. [Scaled-plains-terrain module] This scale/bias module greatly flattens the output value from plains
// terrain. This output value is measured in planetary units.
ScaleBias scaledPlainsTerrain_sb = new ScaleBias(plainsTerrain);
scaledPlainsTerrain_sb.setScale(0.00390625);
scaledPlainsTerrain_sb.setBias(0.0078125);
// 2. Cached output
return new Cached(scaledPlainsTerrain_sb);
}
private Cached scaledBadlandsTerrain(Cached badlandsTerrain) throws Exception {
// 1. [Scaled-badlands-terrain module] This scale/bias module scales the output value from badlands-terrain
// so that it is measure in planetary elevation units.
ScaleBias scaledBadlandsTerrain_sb = new ScaleBias(badlandsTerrain);
scaledBadlandsTerrain_sb.setScale(0.0625);
scaledBadlandsTerrain_sb.setScale(0.0625);
// 2. Cached output
return new Cached(scaledBadlandsTerrain_sb);
}
private Cached continentalShelf(Cached continentDef) throws Exception {
// 1. [Shelf-creator module] This terracing module applies a terracing curve to the continent-definition
// group at the specified shelf level. This terrace becomes the continental shelf. Note that this terracing
// module also places another terrace below the continental shelf near -1. The bottom of this terrace is
// defined as the bottom of the ocean; subsequent modules will later add oceanic trenches to the bottom of the
// ocean.
Terrace continentalShelf_te = new Terrace(continentDef);
continentalShelf_te.addControlPoint (-1.0);
continentalShelf_te.addControlPoint (-0.75);
continentalShelf_te.addControlPoint (SHELF_LEVEL);
continentalShelf_te.addControlPoint (1.0);
// 2. [Oceanic-trench-basis module] This ridged-multifractal-noise module generates some coherent noise that
// will be used to generate the oceanic trenches. The ridged represent the bottoms of the trenchs.
RidgedMulti continentalShelf_rm = new RidgedMulti();
continentalShelf_rm.setSeed(CUR_SEED + 130);
continentalShelf_rm.setFrequency(CONTINENT_FREQUENCY * 4.375);
continentalShelf_rm.setLacunarity(CONTINENT_LACUNARITY);
continentalShelf_rm.setOctaveCount(16);
continentalShelf_rm.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_BEST);
// 3. [Oceanic-trench module] The scale/bias module inverts the ridges from the oceanic-trench-basis module
// so that the ridges become trenches. This noise module reduces the depth of the ridges so that they are
// scaled in planetary elevation units.
ScaleBias continentalShelf_sb= new ScaleBias(continentalShelf_rm);
continentalShelf_sb.setScale(-0.125);
continentalShelf_sb.setBias(-0.125);
// 4. [Clamped-sea-bottom module] This clamping modules clamps the output values from the shelf creator module
// so that its possible range is from the bottom of the ocean to the sea level. This is done because this
// subgroup is only concerned with the oceans.
Clamp continentalShelf_cl = new Clamp(continentalShelf_te);
continentalShelf_cl.setBounds(-0.75, SEA_LEVEL);
// 5. [Shelf-and-trenches module] This module adds the oceanic trenches to the clamped-sea-bottom module.
Add continentalShelf_ad = new Add(continentalShelf_sb, continentalShelf_cl);
// 6. Cached output.
return new Cached(continentalShelf_ad);
}
private Cached baseContinentElev(Cached continentDef, Cached continentalShelf) throws Exception {
// 1. [base-scaled-continent-elevations module] This scale/bias module scales the output value from the
// continent-definition group so that it is measured in planetary elevation units.
ScaleBias baseContinentElev_sb = new ScaleBias(continentDef);
baseContinentElev_sb.setScale(CONTINENT_HEIGHT_SCALE);
baseContinentElev_sb.setBias(0);
// 2. [base-continent-with-oceans module] This selector module applies the elevations of the continental
// shelves to the base elevations of the continent.
Select baseContinentElev_se = new Select(baseContinentElev_sb, continentalShelf, continentDef);
baseContinentElev_se.setBounds(SHELF_LEVEL - 1000, SHELF_LEVEL);
baseContinentElev_se.setEdgeFalloff(0.03125);
// 3. Cached output
return new Cached(baseContinentElev_se);
}
private Cached continentsWithPlains(Cached baseContinentElev, Cached scaledPlainsTerrain) throws Exception {
// 1. [Continents-with-plains module] This addition module adds the scaled-plains-terrain to the
// base-continent-elevation subgroup.
Add continentsWithPlains_ad = new Add(baseContinentElev, scaledPlainsTerrain);
// 2. Cached output
return new Cached(continentsWithPlains_ad);
}
private Cached continentsWithHills(Cached baseContinentElev, Cached continentsWithPlains, Cached scaledHillyTerrain, Cached terrainTypeDef) throws Exception {
// 1. [Continents-with-hills module] This addition module adds the scaled-hilly-terrain to the
// base-continent-elevations subgroup.
Add continentsWithHills_ad = new Add(baseContinentElev, scaledHillyTerrain);
// 2. [Select-high-elevations module] This selector module ensures that hills only appear at higher elevations.
// It does this by selecting the output value from the continent-with-hills module if the corresponding output
// value from the terrain-type-definition group is above a certain value. Otherwise it selects the output value
// from continents-with-plains module.
Select continentsWithHills_se = new Select(continentsWithPlains, continentsWithHills_ad, terrainTypeDef);
continentsWithHills_se.setBounds(1.0 - HILLS_AMOUNT, 1001.0 - HILLS_AMOUNT);
continentsWithHills_se.setEdgeFalloff(0.25);
// 3. Cached output
return new Cached(continentsWithHills_se);
}
private Cached continentsWithMountains(Cached baseContinentElev, Cached continentsWithHills, Cached scaledMountainousTerrain, Cached terrainTypeDef, Cached continentDef) throws Exception {
// 1. [Continents-and-mountains module] This addition module adds the scaled-mountainous-terrain module to the
// base-continent-elevations subgroup.
Add continentsWithMountains_ad0 = new Add(scaledMountainousTerrain, baseContinentElev);
// 2. [Increase-mountain-heights module] The curve module applies a curve to the output value from the
// continent-definition group. This modified output value is used by a subsequent noise module to add
// additional height to the mountains based on the current continent elevation. The higher the continent
// elevation, the higher the mountains.
Curve continentsWithMountains_cu = new Curve(continentDef);
continentsWithMountains_cu.addControlPoint(-1.0, -0.0625);
continentsWithMountains_cu.addControlPoint(0.0, 0.0000);
continentsWithMountains_cu.addControlPoint(1.0 - MOUNTAINS_AMOUNT, 0.0625);
continentsWithMountains_cu.addControlPoint(1.0, 0.2500);
// 3. [Add-increased-mountain-heights module] This addition module adds the increased-mountain-heights module
// to the continents-and-mountains module. The highest continent elevations now have the highest mountains.
Add continentsWithMountains_ad1 = new Add(continentsWithMountains_cu, continentsWithMountains_ad0);
// 4. [Select-high-elevations module] This selector module ensures that mountains only appear at higher
// elevations. It does this by selecting the output value from the continents-with-mountains module if the
// corresponding output value from the terrain-type-definition group is above a certain value. Otherwise,
// it selects the output value from the continents-with-hills group. Note that the continents-with-hills group
// contains the plains terrain.
Select continentsWithMountains_se = new Select(continentsWithHills, continentsWithMountains_ad1, terrainTypeDef);
continentsWithMountains_se.setBounds(1.0 -MOUNTAINS_AMOUNT, 1001.0 - MOUNTAINS_AMOUNT);
continentsWithMountains_se.setEdgeFalloff(0.25);
// 5. Cached output
return new Cached(continentsWithMountains_se);
}
private Cached continentsWithBadlands(Cached baseContinentElev, Cached scaledBadlandsTerrain, Cached continentsWithMountains) throws Exception {
// 1. [Badlands-positions module] The Perlin-noise module generates some random noise, which is used by
// subsequent noise modules to specify the locations of the badlands.
Perlin continentsWithBadlands_pe = new Perlin();
continentsWithBadlands_pe.setSeed(CUR_SEED + 140);
continentsWithBadlands_pe.setFrequency(16.5);
continentsWithBadlands_pe.setPersistence(0.5);
continentsWithBadlands_pe.setLacunarity(CONTINENT_LACUNARITY);
continentsWithBadlands_pe.setOctaveCount(2);
continentsWithBadlands_pe.setNoiseQuality(NoiseGen.NoiseQuality.QUALITY_STD);
// 2. [continents-and-badlands module] This addition module adds the scaled-badlands-terrain module to
// the base-continent-elevation subgroup.
Add continentsWithBadlands_ad = new Add(scaledBadlandsTerrain, baseContinentElev);
// 3. [Select-badlands-positions module] The selector module places badlands at random spots on the continents
// based on the Perlin-noise generate by badlands-positions-module. To do this, it selects the output value
// from the continents-and-badlands module if the corresponding output value from the badlands-positions module
// is greater than a specified value. Otherwise, this selector module selects the output value from the
// continents-and-mountains. There is also a wide transition between these two modules so that the badlands
// can blend into the rest of the terrain on the continents.
Select continentsWithBadlands_se = new Select(continentsWithMountains, continentsWithBadlands_ad, continentsWithBadlands_pe);
continentsWithBadlands_se.setBounds(1.0 - BADLANDS_AMOUNT, 1001.0 - BADLANDS_AMOUNT);
continentsWithBadlands_se.setEdgeFalloff(0.25);
// 4. [Apply-badlands module] This maximum value module causes the badlands to "poke out" from the rest of the
// terrain. It does this by ensuring that only the maximum of the output values from the
// continents-with-mountains subgroup and the select-badlands-positions module contribute to the output value
// of this subgroup. One side effect of this process is that badlands do not appear in mountainous terrain.
Max continentsWithBadlands_ma = new Max(continentsWithMountains, continentsWithBadlands_se);
// 5. Cached output
return new Cached(continentsWithBadlands_ma);
}
private Cached continentsWithRivers(Cached riverPositions, Cached continentsWithBadlands) throws Exception {
// 1. [Scaled-rivers module] This scale/bias module scales the output value from the river-positions group
// so that it is measured in planetary elevations units and is negative; this is required for step 2.
ScaleBias continentsWithRivers_sb = new ScaleBias(riverPositions);
continentsWithRivers_sb.setScale(RIVER_DEPTH / 2.0);
continentsWithRivers_sb.setBias(-RIVER_DEPTH / 2.0);
// 2. [Add-rivers-to-continents module] This addition module adds the rivers to the continents-with-badlands
// group. Because the scaled-rivers module only adds a negative value, the scaled-rivers module carves the
// rivers out of the terrain.
Add continentsWithRivers_ad = new Add(continentsWithRivers_sb, continentsWithBadlands);
// 3. [Blended-rivers-to-continents module] This selector module outputs deep rivers near sea level and
// shallower rivers in higher terrain. It does this by selecting the output value from the
// continents-with-badlands subgroup if the corresponding output value from the continents subgroup is far from
// sea level. Otherwise, this selector module selects the output value from the add-rivers-to-continents module.
Select continentsWithRivers_se = new Select(continentsWithBadlands, continentsWithRivers_ad, continentsWithBadlands);
continentsWithRivers_se.setBounds(SEA_LEVEL, CONTINENT_HEIGHT_SCALE + SEA_LEVEL);
continentsWithRivers_se.setEdgeFalloff(CONTINENT_HEIGHT_SCALE - SEA_LEVEL);
// 4. Cached output
return new Cached(continentsWithRivers_se);
}
public static void main(String args[]) {
try {
Terra t = new Terra();
NoiseMapBuilderSphere planet = new NoiseMapBuilderSphere();
NoiseMap elevGrid = new NoiseMap((int)t.GRID_WIDTH, (int)t.GRID_HEIGHT);
planet.setBounds(t.SOUTH_COORD, t.NORTH_COORD, t.WEST_COORD, t.EAST_COORD);
planet.setDestSize(t.GRID_WIDTH, t.GRID_HEIGHT);
planet.setSourceModule(t.finalPlanet);
planet.setDestNoiseMap(elevGrid);
planet.build();
// Calculate the spatial resolution of the elevation grid, in meters.
// Assume that the spatial resolution is the same in both the x and y
// directions. This is needed by the Terragen file writer.
double degExtent = t.EAST_COORD - t.WEST_COORD;
double gridExtent = (double)t.GRID_WIDTH;
double metersPerDegree = (t.PLANET_CIRCUMFERENCE / 360.0);
double resInMeters = (degExtent / gridExtent) * metersPerDegree;
// Calculate the sea level, in meters.
double seaLevelInMeters = (((t.SEA_LEVEL + 1.0) / 2.0) * (t.MAX_ELEV - t.MIN_ELEV)) + t.MIN_ELEV;
ImageCafe destImage = new ImageCafe(t.GRID_WIDTH, t.GRID_HEIGHT);
RendererImage imageRenderer = new RendererImage();
imageRenderer.setSourceNoiseMap(elevGrid);
imageRenderer.setDestImage(destImage);
imageRenderer.clearGradient();
imageRenderer.addGradientPoint (-16384.0 + seaLevelInMeters, new Color(0, 0, 0, 255));
imageRenderer.addGradientPoint(-256 + seaLevelInMeters, new Color( 6, 58, 127, 255));
imageRenderer.addGradientPoint(-1.0 + seaLevelInMeters, new Color( 14, 112, 192, 255));
imageRenderer.addGradientPoint(0.0 + seaLevelInMeters, new Color( 70, 120, 60, 255));
imageRenderer.addGradientPoint(1024.0 + seaLevelInMeters, new Color(110, 140, 75, 255));
imageRenderer.addGradientPoint(2048.0 + seaLevelInMeters, new Color(160, 140, 111, 255));
imageRenderer.addGradientPoint(3072.0 + seaLevelInMeters, new Color(184, 163, 141, 255));
imageRenderer.addGradientPoint(4096.0 + seaLevelInMeters, new Color(255, 255, 255, 255));
imageRenderer.addGradientPoint(6144.0 + seaLevelInMeters, new Color(128, 255, 255, 255));
imageRenderer.addGradientPoint(16384.0 + seaLevelInMeters, new Color( 0, 0, 255, 255));
imageRenderer.enableLight(true);
imageRenderer.setLightContrast(1.0 / resInMeters);
imageRenderer.setLightIntensity(2.0);
imageRenderer.setLightElev(45.0);
imageRenderer.setLightAzimuth(135.0);
imageRenderer.render();
BufferedImage output = new BufferedImage(t.GRID_WIDTH, t.GRID_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
for(int x = 0; x < destImage.getWidth(); x++) {
for(int y = 0; y < destImage.getHeight(); y++) {
int red = destImage.getValue(x, y).getRed();
int blue = destImage.getValue(x, y).getBlue();
int green = destImage.getValue(x, y).getGreen();
int alpha = destImage.getValue(x, y).getAlpha();
int abgr = alpha;
abgr = (abgr << 8) + blue;
abgr = (abgr << 8) + green;
abgr = (abgr << 8) + red;
output.setRGB(x, y, abgr);
}
}
ImageIO.write(output, "PNG", new File("my_planet.png"));
} catch(Exception e) {
e.printStackTrace();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment