From 8c04abf9aa749af3b15bc92f517b636c9593109e Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 30 Oct 2014 16:24:35 +0100 Subject: QtBiomeVisualiser: Added a prototyping int generator flavor. This generator is easier to manipulate, since it doesn't require rewriting the sizes in the template parameters. On the other hand, it doesn't optimize so well, so it's a bit slower. --- src/Generating/ProtIntGen.h | 1008 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1008 insertions(+) create mode 100644 src/Generating/ProtIntGen.h (limited to 'src/Generating/ProtIntGen.h') diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h new file mode 100644 index 000000000..a3d10c4ef --- /dev/null +++ b/src/Generating/ProtIntGen.h @@ -0,0 +1,1008 @@ + +// ProtIntGen.h + +// Declares the prototyping integer generators - cProtIntGen class and its descendants + +/* +These classes generate 2D arrays of integers that have various interpretations. The main purpose of these +classes is to provide fast prototyping for cIntGen classes - unlike cIntGen classes, these are not +template-based and so they take care of the underlying sizes automatically. This makes them easier to chain +and re-chain, since the size parameters don't need to be adjusted after each such case. Their performance is, +however, slightly worse, which is why we use cIntGen classes in the final generator. + +Because there is no SizeX / SizeZ template param, the generators would have to either alloc memory for each +underlying generator's values, or use a maximum-size buffer. We chose the latter, to avoid memory allocation +overhead; this however means that there's (an arbitrary) limit to the size of the generated data. +*/ + + + + + +#pragma once + +// We need the biome group constants defined there: +#include "IntGen.h" + + + + + +/** Interface that all the generator classes provide. */ +class cProtIntGen +{ +protected: + /** Maximum size of the generated area. + Adjust the constant if you need larger areas, these are just so that we can use fixed-size buffers. */ + static const int m_BufferSize = 900; + +public: + + /** Type of the generic interface used for storing links to the underlying generators. */ + typedef std::shared_ptr Underlying; + + + /** Force a virtual destructor in all descendants. + Descendants contain virtual functions and are referred to via pointer-to-base, so they need a virtual destructor. */ + virtual ~cProtIntGen() {} + + /** Generates the array of specified size into a_Values, based on given min coords. */ + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) = 0; +}; + + + + + +/** Provides additional cNoise member and its helper functions. */ +class cProtIntGenWithNoise : + public cProtIntGen +{ + typedef cProtIntGen super; + +public: + cProtIntGenWithNoise(int a_Seed) : + m_Noise(a_Seed) + { + } + +protected: + cNoise m_Noise; + + /** Chooses one of a_Val1 or a_Val2, based on m_Noise and the coordinates for querying the noise. */ + int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) + { + int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; + return ((rnd & 1) == 0) ? a_Val1 : a_Val2; + } + + /** Chooses one of a_ValN, based on m_Noise and the coordinates for querying the noise. */ + int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) + { + int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; + switch (rnd % 4) + { + case 0: return a_Val1; + case 1: return a_Val2; + case 2: return a_Val3; + default: return a_Val4; + } + } +}; + + + + + + +/** Generates a 2D array of random integers in the specified range [0 .. Range). */ +class cProtIntGenChoice : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenChoice(int a_Seed, int a_Range) : + super(a_Seed), + m_Range(a_Range) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + for (int z = 0; z < a_SizeZ; z++) + { + int BaseZ = a_MinZ + z; + for (int x = 0; x < a_SizeX; x++) + { + a_Values[x + a_SizeX * z] = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7) % m_Range; + } + } // for z + } + +protected: + int m_Range; +}; + + + + + + +/** Decides between the ocean and landmass biomes. +Has a threshold (in percent) of how much land, the larger the threshold, the more land. +Generates 0 for ocean, biome group ID for landmass. */ +class cProtIntGenLandOcean : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenLandOcean(int a_Seed, int a_Threshold) : + super(a_Seed), + m_Threshold(a_Threshold) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + for (int z = 0; z < a_SizeZ; z++) + { + int BaseZ = a_MinZ + z; + for (int x = 0; x < a_SizeX; x++) + { + int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); + a_Values[x + a_SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0; + } + } + + // If the centerpoint of the world is within the area, set it to bgTemperate, always: + if ((a_MinX <= 0) && (a_MinZ <= 0) && (a_MinX + a_SizeX > 0) && (a_MinZ + a_SizeZ > 0)) + { + a_Values[-a_MinX - a_MinZ * a_SizeX] = bgTemperate; + } + } + +protected: + int m_Threshold; +}; + + + + + +class cProtIntGenZoom : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenZoom(int a_Seed, Underlying a_UnderlyingGen) : + super(a_Seed), + m_UnderlyingGen(a_UnderlyingGen) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Get the coords for the lower generator: + int lowerMinX = a_MinX >> 1; + int lowerMinZ = a_MinZ >> 1; + int lowerSizeX = a_SizeX / 2 + 2; + int lowerSizeZ = a_SizeZ / 2 + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + ASSERT(lowerSizeX > 0); + ASSERT(lowerSizeZ > 0); + + // Generate the underlying data with half the resolution: + int lowerData[m_BufferSize]; + m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerSizeX, lowerSizeZ, lowerData); + const int lowStepX = (lowerSizeX - 1) * 2; + int Cache[m_BufferSize]; + + // Discreet-interpolate the values into twice the size: + for (int z = 0; z < lowerSizeZ - 1; ++z) + { + int idx = (z * 2) * lowStepX; + int PrevZ0 = lowerData[z * lowerSizeX]; + int PrevZ1 = lowerData[(z + 1) * lowerSizeX]; + + for (int x = 0; x < lowerSizeX - 1; ++x) + { + int ValX1Z0 = lowerData[x + 1 + z * lowerSizeX]; + int ValX1Z1 = lowerData[x + 1 + (z + 1) * lowerSizeX]; + int RndX = (x + lowerMinX) * 2; + int RndZ = (z + lowerMinZ) * 2; + Cache[idx] = PrevZ0; + Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); + idx++; + Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); + Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); + idx++; + PrevZ0 = ValX1Z0; + PrevZ1 = ValX1Z1; + } + } + + // Copy from Cache into a_Values; take into account the even/odd offsets in a_Min: + for (int z = 0; z < a_SizeZ; ++z) + { + memcpy(a_Values + z * a_SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), a_SizeX * sizeof(int)); + } + } + +protected: + Underlying m_UnderlyingGen; +}; + + + + + +class cProtIntGenSmooth : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenSmooth(int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying values: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerData[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData); + + // Smooth - for each square check if the surroundings are the same, if so, expand them diagonally. + // Also get rid of single-pixel irregularities (A-B-A): + for (int z = 0; z < a_SizeZ; z++) + { + int NoiseZ = a_MinZ + z; + for (int x = 0; x < a_SizeX; x++) + { + int val = lowerData[x + 1 + (z + 1) * lowerSizeX]; + int Above = lowerData[x + 1 + z * lowerSizeX]; + int Below = lowerData[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerData[x + (z + 1) * lowerSizeX]; + int Right = lowerData[x + 2 + (z + 1) * lowerSizeX]; + + if ((Left == Right) && (Above == Below)) + { + if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) + { + val = Left; + } + else + { + val = Above; + } + } + else + { + if (Left == Right) + { + val = Left; + } + + if (Above == Below) + { + val = Above; + } + } + + a_Values[x + z * a_SizeX] = val; + } + } + } + +protected: + Underlying m_Underlying; +}; + + + + + +class cProtIntGenBeaches : + public cProtIntGen +{ + typedef cProtIntGen super; + +public: + cProtIntGenBeaches(Underlying a_Underlying) : + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Map for biome -> its beach: + static const int ToBeach[] = + { + /* biOcean */ biOcean, + /* biPlains */ biBeach, + /* biDesert */ biBeach, + /* biExtremeHills */ biStoneBeach, + /* biForest */ biBeach, + /* biTaiga */ biColdBeach, + /* biSwampland */ biSwampland, + /* biRiver */ biRiver, + /* biNether */ biNether, + /* biEnd */ biEnd, + /* biFrozenOcean */ biColdBeach, + /* biFrozenRiver */ biColdBeach, + /* biIcePlains */ biColdBeach, + /* biIceMountains */ biColdBeach, + /* biMushroomIsland */ biMushroomShore, + /* biMushroomShore */ biMushroomShore, + /* biBeach */ biBeach, + /* biDesertHills */ biBeach, + /* biForestHills */ biBeach, + /* biTaigaHills */ biColdBeach, + /* biExtremeHillsEdge */ biStoneBeach, + /* biJungle */ biBeach, + /* biJungleHills */ biBeach, + /* biJungleEdge */ biBeach, + /* biDeepOcean */ biOcean, + /* biStoneBeach */ biStoneBeach, + /* biColdBeach */ biColdBeach, + /* biBirchForest */ biBeach, + /* biBirchForestHills */ biBeach, + /* biRoofedForest */ biBeach, + /* biColdTaiga */ biColdBeach, + /* biColdTaigaHills */ biColdBeach, + /* biMegaTaiga */ biStoneBeach, + /* biMegaTaigaHills */ biStoneBeach, + /* biExtremeHillsPlus */ biStoneBeach, + /* biSavanna */ biBeach, + /* biSavannaPlateau */ biBeach, + /* biMesa */ biMesa, + /* biMesaPlateauF */ biMesa, + /* biMesaPlateau */ biMesa, + }; + + // Generate the underlying values: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); + + // Add beaches between ocean and biomes: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + int Above = lowerValues[x + 1 + z * lowerSizeX]; + int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerValues[x + (z + 1) * lowerSizeX]; + int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + if (!IsBiomeOcean(val)) + { + if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right)) + { + val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)]; + } + } + a_Values[x + z * a_SizeX] = val; + } + } + } + +protected: + Underlying m_Underlying; +}; + + + + + +/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */ +class cProtIntGenAddIslands : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + typedef std::shared_ptr Underlying; + + + cProtIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) : + super(a_Seed), + m_Threshold(a_Threshold), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + if (a_Values[x + z * a_SizeX] == bgOcean) + { + int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; + if (rnd % 100 < m_Threshold) + { + a_Values[x + z * a_SizeX] = (rnd / 100) % bgLandOceanMax; + } + } + } + } + } + +protected: + int m_Threshold; + + Underlying m_Underlying; +}; + + + + + +/** A filter that adds an edge biome group between two biome groups that need an edge between them. */ +class cProtIntGenBiomeGroupEdges : + public cProtIntGen +{ + typedef cProtIntGen super; + +public: + cProtIntGenBiomeGroupEdges(Underlying a_Underlying) : + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) + { + // Generate the underlying biome groups: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX, a_MinZ, lowerSizeX, lowerSizeZ, lowerValues); + + // Change the biomes on incompatible edges into an edge biome: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + int Above = lowerValues[x + 1 + z * lowerSizeX]; + int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerValues[x + (z + 1) * lowerSizeX]; + int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + switch (val) + { + // Desert should neighbor only oceans, desert and temperates; change to temperate when another: + case bgDesert: + { + if ( + !isDesertCompatible(Above) || + !isDesertCompatible(Below) || + !isDesertCompatible(Left) || + !isDesertCompatible(Right) + ) + { + val = bgTemperate; + } + break; + } // case bgDesert + + // Ice should not neighbor deserts; change to temperate: + case bgIce: + { + if ( + (Above == bgDesert) || + (Below == bgDesert) || + (Left == bgDesert) || + (Right == bgDesert) + ) + { + val = bgTemperate; + } + break; + } // case bgIce + + // Jungle should not neighbor Desert or Ice; change to temperate: + case bgJungle: + { + if ( + !isJungleCompatible(Above) || + !isJungleCompatible(Below) || + !isJungleCompatible(Left) || + !isJungleCompatible(Right) + ) + { + val = bgTemperate; + } + } // case bgJungle + + // Mesa should neighbor only oceans and deserts; change to desert when another: + case bgMesa: + { + if ( + !isMesaCompatible(Above) || + !isMesaCompatible(Below) || + !isMesaCompatible(Left) || + !isMesaCompatible(Right) + ) + { + val = bgDesert; + } + break; + } // case bgDesert + } + a_Values[x + z * a_SizeX] = val; + } // for x + } // for z + } + +protected: + Underlying m_Underlying; + + + inline bool isDesertCompatible(int a_BiomeGroup) + { + switch (a_BiomeGroup) + { + case bgOcean: + case bgDesert: + case bgTemperate: + case bgMesa: + { + return true; + } + default: + { + return false; + } + } + } + + inline bool isJungleCompatible(int a_BiomeGroup) + { + return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgMesa) && (a_BiomeGroup != bgIce)); + } + + inline bool isMesaCompatible(int a_BiomeGroup) + { + return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert)); + } +}; + + + + + +/** Turns biome group indices into real biomes. +For each pixel, takes its biome group and chooses a random biome from that group; replaces the value with +that biome. */ +class cProtIntGenBiomes : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenBiomes(int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Define the per-biome-group biomes: + static const int oceanBiomes[] = + { + biOcean, // biDeepOcean, + }; + + static const int desertBiomes[] = + { + biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, + }; + + static const int temperateBiomes[] = + { + biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, + }; + + static const int mountainBiomes[] = + { + biExtremeHills, biForest, biTaiga, biPlains, + }; + + static const int jungleBiomes[] = + { + biJungle, biJungle, biJungle, biForest, + }; + + static const int iceBiomes[] = + { + biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, + }; + + static const int mesaBiomes[] = + { + biMesa, biMesaPlateau, + }; + + static const cBiomesInGroups BiomesInGroups[] = + { + /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, + /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, + /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, + /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, + /* bgJungle */ { static_cast(ARRAYCOUNT(jungleBiomes)), jungleBiomes}, + /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, + /* bgMesa */ { static_cast(ARRAYCOUNT(mesaBiomes)), mesaBiomes}, + }; + + // Generate the underlying values, representing biome groups: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + + // Overwrite each biome group with a random biome from that group: + for (int z = 0; z < a_SizeZ; z++) + { + int IdxZ = z * a_SizeX; + for (int x = 0; x < a_SizeX; x++) + { + int val = a_Values[x + IdxZ]; + const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)]; + int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); + a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; + } + } + } + +protected: + + struct cBiomesInGroups + { + const int Count; + const int * Biomes; + }; + + + /** The underlying int generator */ + Underlying m_Underlying; +}; + + + + + +class cProtIntGenReplaceRandomly : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + typedef std::shared_ptr Underlying; + + + cProtIntGenReplaceRandomly(int a_From, int a_To, int a_Chance, int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_From(a_From), + m_To(a_To), + m_Chance(a_Chance), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying values: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + + // Replace some of the values: + for (int z = 0; z < a_SizeZ; z++) + { + int idxZ = z * a_SizeX; + for (int x = 0; x < a_SizeX; x++) + { + int idx = x + idxZ; + if (a_Values[idx] == m_From) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 100 < m_Chance) + { + a_Values[idx] = m_To; + } + } + } + } // for z + } + + +protected: + int m_From; + int m_To; + int m_Chance; + Underlying m_Underlying; +}; + + + + + +/** Mixer that joins together finalized biomes and rivers. +It first checks for oceans; if there's no ocean, it checks for a river. */ +class cProtIntGenMixRivers: + public cProtIntGen +{ + typedef cProtIntGen super; + +public: + cProtIntGenMixRivers(Underlying a_Biomes, Underlying a_Rivers): + m_Biomes(a_Biomes), + m_Rivers(a_Rivers) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + ASSERT(a_SizeX * a_SizeZ <= m_BufferSize); + m_Biomes->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + int riverData[m_BufferSize]; + m_Rivers->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, riverData); + + // Mix the values: + for (int z = 0; z < a_SizeZ; z++) + { + int idxZ = z * a_SizeX; + for (int x = 0; x < a_SizeX; x++) + { + int idx = x + idxZ; + if (IsBiomeOcean(a_Values[idx])) + { + // Oceans are kept without any changes + continue; + } + if (riverData[idx] != biRiver) + { + // There's no river, keep the current value + continue; + } + + // There's a river, change the output to a river or a frozen river, based on the original biome: + if (IsBiomeVeryCold((EMCSBiome)a_Values[idx])) + { + a_Values[idx] = biFrozenRiver; + } + else + { + a_Values[idx] = biRiver; + } + } // for x + } // for z + } + +protected: + Underlying m_Biomes; + Underlying m_Rivers; +}; + + + + + +/** Generates a river based on the underlying data. +This is basically an edge detector over the underlying data. The rivers are the edges where the underlying +data changes from one pixel to its neighbor. */ +class cProtIntGenRiver: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenRiver(int a_Seed, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); + + // Detect the edges: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int Above = lowerValues[x + 1 + z * lowerSizeX]; + int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerValues[x + (z + 1) * lowerSizeX]; + int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + + if ((val == Above) && (val == Below) && (val == Left) && (val == Right)) + { + val = 0; + } + else + { + val = biRiver; + } + a_Values[x + z * a_SizeX] = val; + } // for x + } // for z + } + +protected: + Underlying m_Underlying; +}; + + + + + +/** Turns some of the oceans into the specified biome. Used for mushroom and deep ocean. +The biome is only placed if at least 3 of its neighbors are ocean and only with the specified chance. */ +class cProtIntGenAddToOcean: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenAddToOcean(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying): + super(a_Seed), + m_Chance(a_Chance), + m_ToValue(a_ToValue), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); + + // Add the mushroom islands: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + if (!IsBiomeOcean(val)) + { + a_Values[x + z * a_SizeX] = val; + continue; + } + + // Count the ocean neighbors: + int Above = lowerValues[x + 1 + z * lowerSizeX]; + int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerValues[x + (z + 1) * lowerSizeX]; + int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + int NumOceanNeighbors = 0; + if (IsBiomeOcean(Above)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Below)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Left)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Right)) + { + NumOceanNeighbors += 1; + } + + // If at least 3 ocean neighbors and the chance is right, change: + if ( + (NumOceanNeighbors >= 3) && + ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance) + ) + { + a_Values[x + z * a_SizeX] = m_ToValue; + } + else + { + a_Values[x + z * a_SizeX] = val; + } + } // for x + } // for z + } + +protected: + /** Chance, in permille, of changing the biome. */ + int m_Chance; + + /** The value to change the ocean into. */ + int m_ToValue; + + Underlying m_Underlying; +}; + + + + + +/** Changes random pixels of the underlying data to the specified value. */ +class cProtIntGenSetRandomly : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenSetRandomly(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying) : + super(a_Seed), + m_Chance(a_Chance), + m_ToValue(a_ToValue), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + + // Change random pixels to bgOcean: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 1000 < m_Chance) + { + a_Values[x + z * a_SizeX] = m_ToValue; + } + } + } + } + +protected: + /** Chance, in permille, of changing each pixel. */ + int m_Chance; + + /** The value to which to set the pixel. */ + int m_ToValue; + + Underlying m_Underlying; +}; + + + + + -- cgit v1.2.3 From 13f0e93d690ef5ca96689190356b5c6c9cceb434 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 31 Oct 2014 12:52:07 +0100 Subject: GrownProt biomes: added alterations. --- src/Generating/ProtIntGen.h | 213 ++++++++++++++++++++++++++++++++------------ 1 file changed, 156 insertions(+), 57 deletions(-) (limited to 'src/Generating/ProtIntGen.h') diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h index a3d10c4ef..e2b3e592a 100644 --- a/src/Generating/ProtIntGen.h +++ b/src/Generating/ProtIntGen.h @@ -154,7 +154,7 @@ public: for (int x = 0; x < a_SizeX; x++) { int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); - a_Values[x + a_SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0; + a_Values[x + a_SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 101) % bgLandOceanMax + 1) : 0; } } @@ -410,7 +410,8 @@ protected: -/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */ +/** Generates the underlying numbers and then randomly changes some ocean group pixels into random land +group pixels, based on the predefined chance. */ class cProtIntGenAddIslands : public cProtIntGenWithNoise { @@ -420,9 +421,9 @@ public: typedef std::shared_ptr Underlying; - cProtIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) : + cProtIntGenAddIslands(int a_Seed, int a_Chance, Underlying a_Underlying) : super(a_Seed), - m_Threshold(a_Threshold), + m_Chance(a_Chance), m_Underlying(a_Underlying) { } @@ -438,9 +439,9 @@ public: if (a_Values[x + z * a_SizeX] == bgOcean) { int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; - if (rnd % 100 < m_Threshold) + if (rnd % 1000 < m_Chance) { - a_Values[x + z * a_SizeX] = (rnd / 100) % bgLandOceanMax; + a_Values[x + z * a_SizeX] = (rnd / 101) % bgLandOceanMax; } } } @@ -448,7 +449,8 @@ public: } protected: - int m_Threshold; + /** Chance of each ocean pixel being converted, in permille. */ + int m_Chance; Underlying m_Underlying; }; @@ -520,35 +522,6 @@ public: } break; } // case bgIce - - // Jungle should not neighbor Desert or Ice; change to temperate: - case bgJungle: - { - if ( - !isJungleCompatible(Above) || - !isJungleCompatible(Below) || - !isJungleCompatible(Left) || - !isJungleCompatible(Right) - ) - { - val = bgTemperate; - } - } // case bgJungle - - // Mesa should neighbor only oceans and deserts; change to desert when another: - case bgMesa: - { - if ( - !isMesaCompatible(Above) || - !isMesaCompatible(Below) || - !isMesaCompatible(Left) || - !isMesaCompatible(Right) - ) - { - val = bgDesert; - } - break; - } // case bgDesert } a_Values[x + z * a_SizeX] = val; } // for x @@ -566,7 +539,6 @@ protected: case bgOcean: case bgDesert: case bgTemperate: - case bgMesa: { return true; } @@ -576,16 +548,6 @@ protected: } } } - - inline bool isJungleCompatible(int a_BiomeGroup) - { - return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgMesa) && (a_BiomeGroup != bgIce)); - } - - inline bool isMesaCompatible(int a_BiomeGroup) - { - return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert)); - } }; @@ -616,24 +578,40 @@ public: biOcean, // biDeepOcean, }; + // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately) + static const int rareOceanBiomes[] = + { + biOcean, + }; + static const int desertBiomes[] = { biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, }; + static const int rareDesertBiomes[] = + { + biMesaPlateau, biMesaPlateauF, + }; + static const int temperateBiomes[] = { biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, }; + static const int rareTemperateBiomes[] = + { + biJungle, // Jungle is not strictly temperate, but let's piggyback it here + }; + static const int mountainBiomes[] = { biExtremeHills, biForest, biTaiga, biPlains, }; - static const int jungleBiomes[] = + static const int rareMountainBiomes[] = { - biJungle, biJungle, biJungle, biForest, + biMegaTaiga, }; static const int iceBiomes[] = @@ -641,33 +619,44 @@ public: biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const int mesaBiomes[] = + // Same as iceBiomes, there's no rare ice biome + static const int rareIceBiomes[] = { - biMesa, biMesaPlateau, + biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const cBiomesInGroups BiomesInGroups[] = + static const cBiomesInGroups biomesInGroups[] = { /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, - /* bgJungle */ { static_cast(ARRAYCOUNT(jungleBiomes)), jungleBiomes}, /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, - /* bgMesa */ { static_cast(ARRAYCOUNT(mesaBiomes)), mesaBiomes}, + }; + + static const cBiomesInGroups rareBiomesInGroups[] = + { + /* bgOcean */ { static_cast(ARRAYCOUNT(rareOceanBiomes)), rareOceanBiomes}, + /* bgDesert */ { static_cast(ARRAYCOUNT(rareDesertBiomes)), rareDesertBiomes}, + /* bgTemperate */ { static_cast(ARRAYCOUNT(rareTemperateBiomes)), rareTemperateBiomes}, + /* bgMountains */ { static_cast(ARRAYCOUNT(rareMountainBiomes)), rareMountainBiomes}, + /* bgIce */ { static_cast(ARRAYCOUNT(rareIceBiomes)), rareIceBiomes}, }; // Generate the underlying values, representing biome groups: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); // Overwrite each biome group with a random biome from that group: + // Take care of the bgfRare flag for (int z = 0; z < a_SizeZ; z++) { int IdxZ = z * a_SizeX; for (int x = 0; x < a_SizeX; x++) { int val = a_Values[x + IdxZ]; - const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)]; + const cBiomesInGroups & Biomes = (val > bgfRare) ? + rareBiomesInGroups[(val & (bgfRare - 1)) % ARRAYCOUNT(rareBiomesInGroups)] : + biomesInGroups[val % ARRAYCOUNT(biomesInGroups)]; int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; } @@ -700,7 +689,7 @@ public: typedef std::shared_ptr Underlying; - cProtIntGenReplaceRandomly(int a_From, int a_To, int a_Chance, int a_Seed, Underlying a_Underlying) : + cProtIntGenReplaceRandomly(int a_Seed, int a_From, int a_To, int a_Chance, Underlying a_Underlying) : super(a_Seed), m_From(a_From), m_To(a_To), @@ -725,7 +714,7 @@ public: if (a_Values[idx] == m_From) { int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; - if (rnd % 100 < m_Chance) + if (rnd % 1000 < m_Chance) { a_Values[idx] = m_To; } @@ -1006,3 +995,113 @@ protected: + +/** Adds a "rare" flag to random biome groups, based on the given chance. */ +class cProtIntGenRareBiomeGroups: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenRareBiomeGroups(int a_Seed, int a_Chance, Underlying a_Underlying): + super(a_Seed), + m_Chance(a_Chance), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + + // Change some of the biome groups into rare biome groups: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 1000 < m_Chance) + { + int idx = x + a_SizeX * z; + a_Values[idx] = a_Values[idx] | bgfRare; + } + } + } + } + +protected: + /** Chance, in permille, of changing each pixel into the rare biome group. */ + int m_Chance; + + /** The underlying generator. */ + Underlying m_Underlying; +}; + + + + + +/** Changes biomes in the parent data into their alternate verions ("M" variants), in such places that +have their alterations set. */ +class cProtIntGenAlternateBiomes: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenAlternateBiomes(int a_Seed, Underlying a_Alterations, Underlying a_BaseBiomes): + super(a_Seed), + m_Alterations(a_Alterations), + m_BaseBiomes(a_BaseBiomes) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the base biomes and the alterations: + m_BaseBiomes->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + int alterations[m_BufferSize]; + m_Alterations->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, alterations); + + // Change the biomes into their alternate versions: + int len = a_SizeX * a_SizeZ; + for (int idx = 0; idx < len; ++idx) + { + if (alterations[idx] == 0) + { + // No change + continue; + } + + // Change to alternate biomes: + int val = a_Values[idx]; + switch (val) + { + case biBirchForest: val = biBirchForest; break; + case biDesert: val = biDesertHills; break; + case biExtremeHills: val = biExtremeHillsPlus; break; + case biForest: val = biForestHills; break; + case biIcePlains: val = biIceMountains; break; + case biJungle: val = biJungleHills; break; + case biMegaTaiga: val = biMegaTaigaHills; break; + case biMesaPlateau: val = biMesa; break; + case biPlains: val = biForest; break; + case biRoofedForest: val = biPlains; break; + case biSavanna: val = biSavannaPlateau; break; + case biTaiga: val = biTaigaHills; break; + } + a_Values[idx] = val; + } // for idx - a_Values[] + } + +protected: + Underlying m_Alterations; + Underlying m_BaseBiomes; +}; + + + + -- cgit v1.2.3 From 4873890cfbb0c1a2ede464c44ffb58bfe4a1c1cd Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 1 Nov 2014 16:37:56 +0100 Subject: GrownProt biome gen: Added biome edges. --- src/Generating/ProtIntGen.h | 159 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) (limited to 'src/Generating/ProtIntGen.h') diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h index e2b3e592a..c523d9d52 100644 --- a/src/Generating/ProtIntGen.h +++ b/src/Generating/ProtIntGen.h @@ -1088,6 +1088,7 @@ public: case biJungle: val = biJungleHills; break; case biMegaTaiga: val = biMegaTaigaHills; break; case biMesaPlateau: val = biMesa; break; + case biMesaPlateauF: val = biMesa; break; case biPlains: val = biForest; break; case biRoofedForest: val = biPlains; break; case biSavanna: val = biSavannaPlateau; break; @@ -1105,3 +1106,161 @@ protected: + +/** Adds an edge between two specifically incompatible biomes, such as mesa and forest. */ +class cProtIntGenBiomeEdges: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenBiomeEdges(int a_Seed, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying biomes: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); + + // Convert incompatible edges into neutral biomes: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int biome = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + int above = lowerValues[x + 1 + z * lowerSizeX]; + int below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int left = lowerValues[x + (z + 1) * lowerSizeX]; + int right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + + switch (biome) + { + case biDesert: + case biDesertM: + case biDesertHills: + { + if ( + IsBiomeVeryCold(static_cast(above)) || + IsBiomeVeryCold(static_cast(below)) || + IsBiomeVeryCold(static_cast(left)) || + IsBiomeVeryCold(static_cast(right)) + ) + { + biome = biPlains; + } + break; + } // case biDesert + + case biMesaPlateau: + case biMesaPlateauF: + case biMesaPlateauFM: + case biMesaPlateauM: + { + if ( + !isMesaCompatible(above) || + !isMesaCompatible(below) || + !isMesaCompatible(left) || + !isMesaCompatible(right) + ) + { + biome = biDesert; + } + break; + } // Mesa biomes + + case biJungle: + case biJungleM: + { + if ( + !isJungleCompatible(above) || + !isJungleCompatible(below) || + !isJungleCompatible(left) || + !isJungleCompatible(right) + ) + { + biome = (biome == biJungle) ? biJungleEdge : biJungleEdgeM; + } + break; + } // Jungle biomes + + case biSwampland: + case biSwamplandM: + { + if ( + IsBiomeNoDownfall(static_cast(above)) || + IsBiomeNoDownfall(static_cast(below)) || + IsBiomeNoDownfall(static_cast(left)) || + IsBiomeNoDownfall(static_cast(right)) + ) + { + biome = biPlains; + } + break; + } // Swampland biomes + } // switch (biome) + + a_Values[x + z * a_SizeX] = biome; + } // for x + } // for z + } + + +protected: + Underlying m_Underlying; + + + bool isMesaCompatible(int a_Biome) + { + switch (a_Biome) + { + case biDesert: + case biMesa: + case biMesaBryce: + case biMesaPlateau: + case biMesaPlateauF: + case biMesaPlateauFM: + case biMesaPlateauM: + case biOcean: + case biDeepOcean: + { + return true; + } + default: + { + return false; + } + } + } + + + bool isJungleCompatible(int a_Biome) + { + switch (a_Biome) + { + case biJungle: + case biJungleM: + case biJungleEdge: + case biJungleEdgeM: + case biJungleHills: + { + return true; + } + default: + { + return false; + } + } + } +}; + + + + -- cgit v1.2.3 From d868346491cf35ea9d52d60786904b0552d9d67c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 1 Nov 2014 21:01:33 +0100 Subject: GrownProt: Added the rest of rare and M biomes. --- src/Generating/ProtIntGen.h | 94 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 13 deletions(-) (limited to 'src/Generating/ProtIntGen.h') diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h index c523d9d52..9c3eb36cc 100644 --- a/src/Generating/ProtIntGen.h +++ b/src/Generating/ProtIntGen.h @@ -1080,19 +1080,21 @@ public: int val = a_Values[idx]; switch (val) { - case biBirchForest: val = biBirchForest; break; - case biDesert: val = biDesertHills; break; - case biExtremeHills: val = biExtremeHillsPlus; break; - case biForest: val = biForestHills; break; - case biIcePlains: val = biIceMountains; break; - case biJungle: val = biJungleHills; break; - case biMegaTaiga: val = biMegaTaigaHills; break; - case biMesaPlateau: val = biMesa; break; - case biMesaPlateauF: val = biMesa; break; - case biPlains: val = biForest; break; - case biRoofedForest: val = biPlains; break; - case biSavanna: val = biSavannaPlateau; break; - case biTaiga: val = biTaigaHills; break; + case biBirchForest: val = biBirchForest; break; + case biDesert: val = biDesertHills; break; + case biExtremeHills: val = biExtremeHillsPlus; break; + case biForest: val = biForestHills; break; + case biIcePlains: val = biIceMountains; break; + case biJungle: val = biJungleHills; break; + case biMegaTaiga: val = biMegaTaigaHills; break; + case biMesaPlateau: val = biMesa; break; + case biMesaPlateauF: val = biMesa; break; + case biMesaPlateauM: val = biMesa; break; + case biMesaPlateauFM: val = biMesa; break; + case biPlains: val = biForest; break; + case biRoofedForest: val = biPlains; break; + case biSavanna: val = biSavannaPlateau; break; + case biTaiga: val = biTaigaHills; break; } a_Values[idx] = val; } // for idx - a_Values[] @@ -1264,3 +1266,69 @@ protected: + +class cProtIntGenMBiomes: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenMBiomes(int a_Seed, Underlying a_Alteration, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying), + m_Alteration(a_Alteration) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying biomes and the alterations: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + int alterations[m_BufferSize]; + m_Alteration->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, alterations); + + // Wherever alterations are nonzero, change into alternate biome, if available: + int len = a_SizeX * a_SizeZ; + for (int idx = 0; idx < len; ++idx) + { + if (alterations[idx] == 0) + { + continue; + } + + // Ice spikes biome was removed from here, because it was generated way too often + switch (a_Values[idx]) + { + case biPlains: a_Values[idx] = biSunflowerPlains; break; + case biDesert: a_Values[idx] = biDesertM; break; + case biExtremeHills: a_Values[idx] = biExtremeHillsM; break; + case biForest: a_Values[idx] = biFlowerForest; break; + case biTaiga: a_Values[idx] = biTaigaM; break; + case biSwampland: a_Values[idx] = biSwamplandM; break; + case biJungle: a_Values[idx] = biJungleM; break; + case biJungleEdge: a_Values[idx] = biJungleEdgeM; break; + case biBirchForest: a_Values[idx] = biBirchForestM; break; + case biBirchForestHills: a_Values[idx] = biBirchForestHillsM; break; + case biRoofedForest: a_Values[idx] = biRoofedForestM; break; + case biColdTaiga: a_Values[idx] = biColdTaigaM; break; + case biMegaSpruceTaiga: a_Values[idx] = biMegaSpruceTaiga; break; + case biMegaSpruceTaigaHills: a_Values[idx] = biMegaSpruceTaigaHills; break; + case biExtremeHillsPlus: a_Values[idx] = biExtremeHillsPlusM; break; + case biSavanna: a_Values[idx] = biSavannaM; break; + case biSavannaPlateau: a_Values[idx] = biSavannaPlateauM; break; + case biMesa: a_Values[idx] = biMesaBryce; break; + case biMesaPlateauF: a_Values[idx] = biMesaPlateauFM; break; + case biMesaPlateau: a_Values[idx] = biMesaBryce; break; + } + } // for idx - a_Values[] / alterations[] + } + +protected: + Underlying m_Underlying; + Underlying m_Alteration; +}; + + + + -- cgit v1.2.3 From d5b6353493868ac14b277155f398bd87f08c484c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 2 Nov 2014 16:36:59 +0100 Subject: Grown biomes: Unified with GrownProt biomes. Also fixed a Zoom filter randomness. --- src/Generating/ProtIntGen.h | 83 +++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 33 deletions(-) (limited to 'src/Generating/ProtIntGen.h') diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h index 9c3eb36cc..73ed27096 100644 --- a/src/Generating/ProtIntGen.h +++ b/src/Generating/ProtIntGen.h @@ -70,14 +70,14 @@ protected: cNoise m_Noise; /** Chooses one of a_Val1 or a_Val2, based on m_Noise and the coordinates for querying the noise. */ - int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) + int chooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) { int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; return ((rnd & 1) == 0) ? a_Val1 : a_Val2; } /** Chooses one of a_ValN, based on m_Noise and the coordinates for querying the noise. */ - int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) + int chooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) { int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; switch (rnd % 4) @@ -173,6 +173,9 @@ protected: +/** Zooms the underlying value array to twice the size. Uses random-neighbor for the pixels in-between. +This means that the zoome out image is randomly distorted. Applying zoom several times provides all +the distortion that the generators need. */ class cProtIntGenZoom : public cProtIntGenWithNoise { @@ -201,7 +204,7 @@ public: int lowerData[m_BufferSize]; m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerSizeX, lowerSizeZ, lowerData); const int lowStepX = (lowerSizeX - 1) * 2; - int Cache[m_BufferSize]; + int cache[m_BufferSize]; // Discreet-interpolate the values into twice the size: for (int z = 0; z < lowerSizeZ - 1; ++z) @@ -216,12 +219,11 @@ public: int ValX1Z1 = lowerData[x + 1 + (z + 1) * lowerSizeX]; int RndX = (x + lowerMinX) * 2; int RndZ = (z + lowerMinZ) * 2; - Cache[idx] = PrevZ0; - Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); - idx++; - Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); - Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); - idx++; + cache[idx] = PrevZ0; + cache[idx + lowStepX] = super::chooseRandomOne(RndX, RndZ + 1, PrevZ0, PrevZ1); + cache[idx + 1] = super::chooseRandomOne(RndX, RndZ - 1, PrevZ0, ValX1Z0); + cache[idx + 1 + lowStepX] = super::chooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); + idx += 2; PrevZ0 = ValX1Z0; PrevZ1 = ValX1Z1; } @@ -230,7 +232,7 @@ public: // Copy from Cache into a_Values; take into account the even/odd offsets in a_Min: for (int z = 0; z < a_SizeZ; ++z) { - memcpy(a_Values + z * a_SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), a_SizeX * sizeof(int)); + memcpy(a_Values + z * a_SizeX, cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), a_SizeX * sizeof(int)); } } @@ -242,6 +244,8 @@ protected: +/** Smoothes out some artifacts generated by the zooming - mostly single-pixel values. +Compares each pixel to its neighbors and if the neighbors are equal, changes the pixel to their value. */ class cProtIntGenSmooth : public cProtIntGenWithNoise { @@ -272,32 +276,32 @@ public: for (int x = 0; x < a_SizeX; x++) { int val = lowerData[x + 1 + (z + 1) * lowerSizeX]; - int Above = lowerData[x + 1 + z * lowerSizeX]; - int Below = lowerData[x + 1 + (z + 2) * lowerSizeX]; - int Left = lowerData[x + (z + 1) * lowerSizeX]; - int Right = lowerData[x + 2 + (z + 1) * lowerSizeX]; + int above = lowerData[x + 1 + z * lowerSizeX]; + int below = lowerData[x + 1 + (z + 2) * lowerSizeX]; + int left = lowerData[x + (z + 1) * lowerSizeX]; + int right = lowerData[x + 2 + (z + 1) * lowerSizeX]; - if ((Left == Right) && (Above == Below)) + if ((left == right) && (above == below)) { if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) { - val = Left; + val = left; } else { - val = Above; + val = above; } } else { - if (Left == Right) + if (left == right) { - val = Left; + val = left; } - if (Above == Below) + if (above == below) { - val = Above; + val = above; } } @@ -314,6 +318,7 @@ protected: +/** Converts land biomes at the edge of an ocean into the respective beach biome. */ class cProtIntGenBeaches : public cProtIntGen { @@ -386,14 +391,15 @@ public: for (int x = 0; x < a_SizeX; x++) { int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; - int Above = lowerValues[x + 1 + z * lowerSizeX]; - int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; - int Left = lowerValues[x + (z + 1) * lowerSizeX]; - int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + int above = lowerValues[x + 1 + z * lowerSizeX]; + int below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int left = lowerValues[x + (z + 1) * lowerSizeX]; + int right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; if (!IsBiomeOcean(val)) { - if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right)) + if (IsBiomeOcean(above) || IsBiomeOcean(below) || IsBiomeOcean(left) || IsBiomeOcean(right)) { + // First convert the value to a regular biome (drop the M flag), then modulo by our biome count: val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)]; } } @@ -411,7 +417,7 @@ protected: /** Generates the underlying numbers and then randomly changes some ocean group pixels into random land -group pixels, based on the predefined chance. */ +biome group pixels, based on the predefined chance. */ class cProtIntGenAddIslands : public cProtIntGenWithNoise { @@ -441,7 +447,7 @@ public: int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; if (rnd % 1000 < m_Chance) { - a_Values[x + z * a_SizeX] = (rnd / 101) % bgLandOceanMax; + a_Values[x + z * a_SizeX] = (rnd / 1003) % bgLandOceanMax; } } } @@ -575,7 +581,7 @@ public: // Define the per-biome-group biomes: static const int oceanBiomes[] = { - biOcean, // biDeepOcean, + biOcean, // biDeepOcean, }; // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately) @@ -680,6 +686,7 @@ protected: +/** Randomly replaces pixels of one value to another value, using the given chance. */ class cProtIntGenReplaceRandomly : public cProtIntGenWithNoise { @@ -725,9 +732,15 @@ public: protected: + /** The original value to be replaced. */ int m_From; + + /** The destination value to which to replace. */ int m_To; + + /** Chance, in permille, of replacing the value. */ int m_Chance; + Underlying m_Underlying; }; @@ -736,7 +749,9 @@ protected: /** Mixer that joins together finalized biomes and rivers. -It first checks for oceans; if there's no ocean, it checks for a river. */ +It first checks for oceans, if there is an ocean in the Biomes, it keeps the ocean. +If there's no ocean, it checks Rivers for a river, if there is a river, it uses the Biomes to select either +regular river or frozen river, based on the biome. */ class cProtIntGenMixRivers: public cProtIntGen { @@ -1043,8 +1058,8 @@ protected: -/** Changes biomes in the parent data into their alternate verions ("M" variants), in such places that -have their alterations set. */ +/** Changes biomes in the parent data into an alternate versions (usually "hill" variants), in such places +that have their alterations set. */ class cProtIntGenAlternateBiomes: public cProtIntGenWithNoise { @@ -1080,7 +1095,7 @@ public: int val = a_Values[idx]; switch (val) { - case biBirchForest: val = biBirchForest; break; + case biBirchForest: val = biBirchForestHills; break; case biDesert: val = biDesertHills; break; case biExtremeHills: val = biExtremeHillsPlus; break; case biForest: val = biForestHills; break; @@ -1267,6 +1282,8 @@ protected: +/** Changes biomes in the parent data into their alternate versions ("M" variants), in such places that +have their alterations set. */ class cProtIntGenMBiomes: public cProtIntGenWithNoise { -- cgit v1.2.3