summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dgn-proclayouts.cc
diff options
context:
space:
mode:
authorPete Hurst <pete@streamuniverse.tv>2013-03-22 03:35:07 +0000
committerPete Hurst <pete@streamuniverse.tv>2013-04-09 12:24:52 +0100
commit104d96d01f927a7702dba091c2c27725d97fd790 (patch)
tree10f9a9b99cc29dc6e1cefae13f8746348bba80a8 /crawl-ref/source/dgn-proclayouts.cc
parent95c5a40c70f2cf92857960f27bb60cc9dac88066 (diff)
downloadcrawl-ref-104d96d01f927a7702dba091c2c27725d97fd790.tar.gz
crawl-ref-104d96d01f927a7702dba091c2c27725d97fd790.zip
Abyssal Underworld layout
Diffstat (limited to 'crawl-ref/source/dgn-proclayouts.cc')
-rw-r--r--crawl-ref/source/dgn-proclayouts.cc176
1 files changed, 61 insertions, 115 deletions
diff --git a/crawl-ref/source/dgn-proclayouts.cc b/crawl-ref/source/dgn-proclayouts.cc
index ec0e40d933..542ed7940b 100644
--- a/crawl-ref/source/dgn-proclayouts.cc
+++ b/crawl-ref/source/dgn-proclayouts.cc
@@ -283,7 +283,7 @@ ForestLayout::operator()(const coord_def &p, const uint32_t offset) const
{
dungeon_feature_type feat = DNGN_FLOOR;
- const static WorleyFunction base(0.16,0.16,0.5,0,0,0);
+ const static WorleyFunction base(0.32,0.4,0.5,0,0,0);
const static WorleyFunction offx(0.6,0.6,0.2,854.3,123.4,0.0);
const static WorleyFunction offy(0.6,0.6,0.2,123.2,3623.51,0.0);
const static WorleyDistortFunction tfunc(base,offx,2.0,offy,1.5);
@@ -318,6 +318,7 @@ ForestLayout::operator()(const coord_def &p, const uint32_t offset) const
return ProceduralSample(p, feat, offset + 1); // Delta is always 1 because the layout will be clamped
}
+// An expansive underworld containing seas, rivers, lakes, forests, cities, mountains, and perhaps more...
ProceduralSample
ClampLayout::operator()(const coord_def &p, const uint32_t offset) const
{
@@ -353,90 +354,43 @@ CityLayout::operator()(const coord_def &p, const uint32_t offset) const
ProceduralSample
PlainsLayout::operator()(const coord_def &p, const uint32_t offset) const
OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
+UnderworldLayout::operator()(const coord_def &p, const uint32_t offset) const
{
- // Wetness gives us features like water, and optimal wetness is required for plants.
- double wet_xoff = 3463.128;
- double wet_yoff = -3737.987;
- double wet_xmul = 0.5;
- double wet_ymul = 0.5;
- double wet_dmul = 3;
- double wet_doff = 0;
- double wet_oct = 2;
-
- // Height
- double height_xoff = 7.543;
- double height_yoff = 2.123;
- double height_xmul = 0.3; // 0.2; // Setting muls to 10 produces very dense terrain variation and looks cool
- double height_ymul = 0.3;// 0.2;
- double height_dmul = 1;
- double height_doff = 0;
- double height_oct = 4; // 4;
+ // Define various environmental functions based on noise. These factors
+ // combine to determine what terrain gets drawn at a given coordinate.
+ // Wetness gives us features like water, and optimal wetness will be required for plants
+ const static SimplexFunction func_wet(0.5,0.5,3.0,3463.128,-3737.987,0,2);
+ // Terrain height gives us mountains, rivers, ocean
+ const static SimplexFunction func_height(0.3,0.3,1.0,7.543,2.123,0,4);
// Temperament. Plants struggle to grow in extreme temperatures, and we only see lava in hot places.
- double hot_xoff = 111.612;
- double hot_yoff = 11.243;
- double hot_xmul = 0.1;
- double hot_ymul = 0.1;
- double hot_dmul = 2;
- double hot_doff = 0;
- double hot_oct = 1;
-
- // Citification; areas with a high settle factor will tend to feature "man"-made architecture
- double city_xoff = 2.732;
- double city_yoff = 22.43;
- double city_xmul = 0.2; // 0.4 , 0.4
- double city_ymul = 0.2;
- double city_dmul = 1;
- double city_doff = 0;
- double city_oct = 1;
-
- // Gentrification; some cities are richer than others, for now this will just affect wall types
- // but it could be interesting to make architecture more complex and regular in rich areas too,
- // as well as influencing features like statues, fountains, plants, even monsters/loot
- double rich_xoff = 9.543;
- double rich_yoff = 5.543;
- double rich_xmul = 0.05;
- double rich_ymul = 0.05;
- double rich_dmul = 1;
- double rich_doff = 0;
- double rich_oct = 1;
-
- // to create lots of lines everywhere that can often be perpendicular to other features; for creating bridges, dividing walls
- double lateral_xoff = 2000.543;
- double lateral_yoff = 1414.823;
- double lateral_xmul = 4;
- double lateral_ymul = 4;
- double lateral_dmul = 1;
- double lateral_doff = 0;
- double lateral_oct = 2;
-
- // jitter needs to be completely random everywhere, so this can be used instead of normal random methods:
+ const static SimplexFunction func_hot(0.1,0.1,2.0,111.612,11.243,0,1);
+ // Citification; areas with a high settle factor will tend to feature "man"-made architecture
+ // TODO: Citi/gentrification could use a worley layer instead (or a mix) to have better geometry
+ // and stop things like wall types suddenly changing halfway through a city.
+ const static SimplexFunction func_city(0.2,0.2,1.0,2.732,22.43,0,1);
+ // Gentrification; some cities are richer than others, this affects wall types
+ // but we can also choose what features to build inside the cities, influencing
+ // features like statues, fountains, plants, regularness, and even monsters/loot
+ const static SimplexFunction func_rich(0.05,0.05,1,9.543,5.543,0,1);
+
+ // To create lots of lines everywhere that can often be perpendicular to other#
+ // features; for creating bridges, dividing walls
+ // const static SimplexFunction func_lateral(4,4,1,2000.543,1414.823,0,2);
+ const static WorleyFunction func_lateral(2,2,1,2000.543,1414.823,0);
+
+ // Jitter needs to be completely random everywhere, so this can be used instead of normal random methods:
// if (jitter < (chance_in_1)) { ... }
- double jitter_xoff = 1123.543;
- double jitter_yoff = 2451.143;
- double jitter_xmul = 10;
- double jitter_ymul = 10;
- double jitter_dmul = 0.5;
- double jitter_doff = 0;
- double jitter_oct = 5;
-
- // Based on the various perlin layers, determine environmental parameters at the current spot
- // printf ("Abyss: %d %d", p.x, p.y);
- double wet = _perlin(p, offset, wet_xmul, wet_xoff, wet_ymul, wet_yoff, wet_dmul, wet_doff, wet_oct);
- double height = _perlin(p, offset, height_xmul, height_xoff, height_ymul, height_yoff, height_dmul, height_doff, height_oct);
-
- // Note: worley noise with x,y multiplied by something below 10 (maybe about 8) produces similar density to Perlin.
- /*
- worley::noise_datum n = worley::noise(hx, hy, hz);
- double height = n.distance[0] - 1.0;
- double other = n.distance[1] - 1.0;
- */
- //printf ("X: %d, Y: %d, HX: %f, HY: %f, HZ: %f, Height: %f, Other: %f\n", p.x, p.y, hx, hy, hz, height, other);
- double hot = _perlin(p, offset, hot_xmul, hot_xoff, hot_ymul, hot_yoff, hot_dmul, hot_doff, hot_oct);
- double city = _perlin(p, offset, city_xmul, city_xoff, city_ymul, city_yoff, city_dmul, city_doff, city_oct);
- double rich = _perlin(p, offset, rich_xmul, rich_xoff, rich_ymul, rich_yoff, rich_dmul, rich_doff, rich_oct);
- double lateral = _perlin(p, offset, lateral_xmul, lateral_xoff, lateral_ymul, lateral_yoff, lateral_dmul, lateral_doff, lateral_oct);
- double jitter = _perlin(p, offset, jitter_xmul, jitter_xoff, jitter_ymul, jitter_yoff, jitter_dmul, jitter_doff, jitter_oct);
+ const static SimplexFunction func_jitter(10,10,0.5,1123.543,2451.143,0,5);
+
+ // Compute all our environment factors at the current spot
+ double wet = func_wet(p, offset);
+ double height = func_height(p, offset);
+ double hot = func_hot(p, offset);
+ double city = func_city(p, offset);
+ double rich = func_rich(p, offset);
+ double lateral = func_lateral(p, offset);
+ double jitter = func_jitter(p, offset);
// TODO: The abyss doesn't support all of these yet but would be nice if:
// * Clusters of plants around water edge
@@ -447,9 +401,16 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
// * Pave areas within city
// * Borrow some easing functions from somewhere to better control how features vary across bounaries
// * Look at surrounding squares to determine gradients - will help with lateral features and also e.g. growing plants on sunlit mountainsides...
+ // * Use some lateral wetness to try and join mountain streams up to rivers...
+ // * Petrified trees and other fun stuff in extreme temperatures
+ // * Cities - Make the decor more interesting, and choose fountain types based on wetness
+ // * Cities - Pave floor within wall limit
+ // * Cities - might sometimes want to modify the terrain based on what was here before the city.
+ // e.g. if the city was built on water then there should be fountains, with lava we get furnaces, etc.
- // TODO: Rather than basing all the factors purely on the perlin layers, we should combine some factors; e.g. cities thrive best at optimal combinations
- // of wet, height and hot, so the city factor could be based on how close to optimum those three are...
+ // * Rather than basing all the factors purely on separate perlin layers,
+ // could combine some factors; e.g. cities thrive best at optimal combinations
+ // of wet, height and hot, so the city/rich factor could be based on how close to optimum those three are...
// Factors controlling how the environment is mapped to terrain
/*
@@ -464,16 +425,16 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
double mountain_top_height = 0.95;
// Default feature
dungeon_feature_type feat = DNGN_FLOOR;
- // printf ("Height: %f, Wet: %f", height,wet);
// Lakes and rivers
- /* height with a mul of 10 looked really nice with:
+ /* TODO: height with a mul of 10 looked really nice with:
if (height<0.5)
feat = DNGN_SHALLOW_WATER;
if (height<0.3)
feat = DNGN_DEEP_WATER;
if (height>0.8)
- feat = DNGN_ROCK_WALL; */
+ feat = DNGN_ROCK_WALL;
+ (but I should implement that as a separate layout) */
if (height < water_depth)
feat = DNGN_SHALLOW_WATER;
if (height < water_deep_depth)
@@ -509,13 +470,12 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
// Forest
bool enable_forest = true;
// Forests fill an important gap in the middling height gap between water and mountainous regions
- double forest_start_height = 0.4; // 0.3,0.7
- double forest_end_height = 0.6;
+ double forest_start_height = 0.43; // 0.3,0.7
+ double forest_end_height = 0.57;
if (enable_forest)
{
// A narrow river running through the middle of forresty heights at good wetness levels
- // TODO: Use some lateral wetness to try and join mountain streams up to rivers...
bool is_river = (abs(height-0.5) < (wet/10.0));
if (is_river)
feat = DNGN_SHALLOW_WATER;
@@ -531,8 +491,6 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
* _optimum_range(wet, 0.5, 0.8)
* _optimum_range(hot, 0.4, 0.6);
- // TODO: Petrified trees and other fun stuff in extreme temperatures
-
// Forest should now be 1.0 in the center of the range, 0.0 at the end
if (jitter < (forest * 0.7))
{
@@ -560,7 +518,6 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
if (enable_city && city >= city_outer_limit) {
// feat = DNGN_FLOOR;
-
dungeon_feature_type city_wall = DNGN_ROCK_WALL;
if (rich > 0.5) city_wall = DNGN_STONE_WALL;
else if (rich > 0.75) city_wall = DNGN_METAL_WALL;
@@ -583,8 +540,6 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
if (city >= city_wall_limit)
{
// Within outer wall reset all terrain to floor.
- // TODO: We might sometimes want to modify the terrain based on what was here before the city.
- // e.g. if the city was built on water then there should be fountains, with lava we get furnaces, etc.
feat = DNGN_FLOOR;
if (city < (city_wall_limit + city_wall_width))
@@ -600,7 +555,6 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
if (city < (city_inner_wall_limit + city_wall_width))
feat = city_wall;
// Decide on what decor we want within the inner walls
- // TODO: Make the decor more interesting, and choose fountain types based on wetness
else if (jitter > 0.9)
{
if (rich>0.8)
@@ -612,8 +566,6 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
else
feat = DNGN_STONE_ARCH;
}
-
- // TOOD: Pave coords within wall limit
}
}
}
@@ -623,22 +575,6 @@ OverworldLayout::operator()(const coord_def &p, const uint32_t offset) const
return ProceduralSample(p, feat, offset + delta);
}
-worley::noise_datum NoiseLayout::_worley(const coord_def &p, const uint32_t offset, const double xmul, const double xoff, const double ymul,const double yoff, const double zmul,const double zoff, const int oct) const
-{
- double hx = ((double)p.x * (double)0.8 + xoff) * xmul;
- double hy = ((double)p.y * (double)0.8 + yoff) * ymul;
- double hz = ((double)offset * (double)0.008 + zoff) * zmul; // Was offset/80, maybe should change faster than this
- return worley::noise(hx, hy, hz);
-}
-
-double NoiseLayout::_perlin(const coord_def &p, const uint32_t offset, const double xmul, const double xoff, const double ymul,const double yoff, const double zmul,const double zoff, const int oct) const
-{
- double hx = ((double)p.x / (double)10 + xoff) * xmul;
- double hy = ((double)p.y / (double)10 + yoff) * ymul;
- double hz = ((double)offset / (double)1000 + zoff) * zmul;
- return perlin::fBM(hx, hy, hz, oct) / 2.0 + 0.5;
-}
-
double NoiseLayout::_optimum_range(const double val, const double rstart, const double rend) const
{
double mid = (rstart + rend) / 2.0;
@@ -663,15 +599,25 @@ double ProceduralFunction::operator()(double x, double y, double z) const
return 0;
}
+double SimplexFunction::operator()(const coord_def &p, const uint32_t offset) const
+{
+ return SimplexFunction::operator()(p.x,p.y,offset);
+}
+
double SimplexFunction::operator()(double x, double y, double z) const
{
double hx = (x / (double)10 + seed_x) * scale_x;
double hy = (y / (double)10 + seed_y) * scale_y;
- double hz = (z / (double)1000 + seed_z) * scale_z;
+ double hz = (z / (double)2000 + seed_z) * scale_z;
// Use octaval simplex and scale into a 0..1 range
return perlin::fBM(hx, hy, hz, octaves) / 2.0 + 0.5;
}
+double WorleyFunction::operator()(const coord_def &p, const uint32_t offset) const
+{
+ return WorleyFunction::operator()(p.x,p.y,offset);
+}
+
double WorleyFunction::operator()(double x, double y, double z) const
{
worley::noise_datum d = this->datum(x,y,z);
@@ -682,7 +628,7 @@ worley::noise_datum WorleyFunction::datum(double x, double y, double z) const
{
double hx = (x * (double)0.8 + seed_x) * scale_x;
double hy = (y * (double)0.8 + seed_y) * scale_y;
- double hz = (z * (double)0.008 + seed_z) * scale_z; // Was z/80, maybe should change faster than this
+ double hz = (z * (double)0.004 + seed_z) * scale_z;
return worley::noise(hx, hy, hz);
}