v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
26
source/game/terrain/StarCacheSelector.cpp
Normal file
26
source/game/terrain/StarCacheSelector.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "StarCacheSelector.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const CacheSelector::Name = "cache";
|
||||
|
||||
CacheSelector::CacheSelector(
|
||||
Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
auto sourceConfig = config.get("source");
|
||||
String sourceType = sourceConfig.getString("type");
|
||||
uint64_t seedBias = sourceConfig.getUInt("seedBias", 0);
|
||||
TerrainSelectorParameters sourceParameters = parameters;
|
||||
sourceParameters.seed += seedBias;
|
||||
m_source = database->createSelectorType(type, sourceConfig, sourceParameters);
|
||||
|
||||
m_cache.setMaxSize(config.getUInt("lruCacheSize", 20000));
|
||||
}
|
||||
|
||||
float CacheSelector::get(int x, int y) const {
|
||||
return m_cache.get(Vec2I(x, y), [this](Vec2I const& key) {
|
||||
return m_source->get(key[0], key[1]);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
23
source/game/terrain/StarCacheSelector.hpp
Normal file
23
source/game/terrain/StarCacheSelector.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef STAR_CACHE_SELECTOR_HPP
|
||||
#define STAR_CACHE_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
#include "StarLruCache.hpp"
|
||||
#include "StarVector.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct CacheSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
CacheSelector(Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
TerrainSelectorConstPtr m_source;
|
||||
mutable HashLruCache<Vec2I, float> m_cache;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
16
source/game/terrain/StarConstantSelector.cpp
Normal file
16
source/game/terrain/StarConstantSelector.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "StarConstantSelector.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const ConstantSelector::Name = "constant";
|
||||
|
||||
ConstantSelector::ConstantSelector(Json const& config, TerrainSelectorParameters const& parameters)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
m_value = config.getFloat("value");
|
||||
}
|
||||
|
||||
float ConstantSelector::get(int, int) const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
}
|
20
source/game/terrain/StarConstantSelector.hpp
Normal file
20
source/game/terrain/StarConstantSelector.hpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef STAR_SOLID_SELECTOR_HPP
|
||||
#define STAR_SOLID_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct ConstantSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
ConstantSelector(Json const& config, TerrainSelectorParameters const& parameters);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
float m_value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
69
source/game/terrain/StarDisplacementSelector.cpp
Normal file
69
source/game/terrain/StarDisplacementSelector.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include "StarDisplacementSelector.hpp"
|
||||
#include "StarRandom.hpp"
|
||||
#include "StarJsonExtra.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const DisplacementSelector::Name = "displacement";
|
||||
|
||||
DisplacementSelector::DisplacementSelector(
|
||||
Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
RandomSource random(parameters.seed);
|
||||
|
||||
auto xType = PerlinTypeNames.getLeft(config.getString("xType"));
|
||||
auto xOctaves = config.getFloat("xOctaves");
|
||||
auto xFreq = config.getFloat("xFreq");
|
||||
auto xAmp = config.getFloat("xAmp");
|
||||
auto xBias = config.getFloat("xBias", 0.0f);
|
||||
auto xAlpha = config.getFloat("xAlpha", 2.0f);
|
||||
auto xBeta = config.getFloat("xBeta", 2.0f);
|
||||
|
||||
xDisplacementFunction = PerlinF(xType, xOctaves, xFreq, xAmp, xBias, xAlpha, xBeta, random.randu64());
|
||||
|
||||
auto yType = PerlinTypeNames.getLeft(config.getString("yType"));
|
||||
auto yOctaves = config.getFloat("yOctaves");
|
||||
auto yFreq = config.getFloat("yFreq");
|
||||
auto yAmp = config.getFloat("yAmp");
|
||||
auto yBias = config.getFloat("yBias", 0.0f);
|
||||
auto yAlpha = config.getFloat("yAlpha", 2.0f);
|
||||
auto yBeta = config.getFloat("yBeta", 2.0f);
|
||||
|
||||
yDisplacementFunction = PerlinF(yType, yOctaves, yFreq, yAmp, yBias, yAlpha, yBeta, random.randu64());
|
||||
|
||||
xXInfluence = config.getFloat("xXInfluence", 1.0f);
|
||||
xYInfluence = config.getFloat("xYInfluence", 1.0f);
|
||||
yXInfluence = config.getFloat("yXInfluence", 1.0f);
|
||||
yYInfluence = config.getFloat("yYInfluence", 1.0f);
|
||||
|
||||
yClamp = config.contains("yClamp");
|
||||
if (yClamp) {
|
||||
yClampRange = jsonToVec2F(config.get("yClamp"));
|
||||
yClampSmoothing = config.getFloat("yClampSmoothing", 0);
|
||||
}
|
||||
|
||||
auto sourceConfig = config.get("source");
|
||||
String sourceType = sourceConfig.getString("type");
|
||||
m_source = database->createSelectorType(sourceType, sourceConfig, parameters);
|
||||
}
|
||||
|
||||
float DisplacementSelector::get(int x, int y) const {
|
||||
auto x_ = x + xDisplacementFunction.get(x * xXInfluence, y * xYInfluence);
|
||||
auto y_ = y + clampY(yDisplacementFunction.get(x * yXInfluence, y * yYInfluence));
|
||||
return m_source->get(x_, y_);
|
||||
}
|
||||
|
||||
float DisplacementSelector::clampY(float v) const {
|
||||
if (!yClamp)
|
||||
return v;
|
||||
if (yClampSmoothing == 0)
|
||||
return clamp(v, yClampRange[0], yClampRange[1]);
|
||||
|
||||
return 0.2f * (clamp(v - yClampSmoothing, yClampRange[0], yClampRange[1])
|
||||
+ clamp(v - 0.5f * yClampSmoothing, yClampRange[0], yClampRange[1])
|
||||
+ clamp(v, yClampRange[0], yClampRange[1])
|
||||
+ clamp(v + 0.5f * yClampSmoothing, yClampRange[0], yClampRange[1])
|
||||
+ clamp(v + yClampSmoothing, yClampRange[0], yClampRange[1]));
|
||||
}
|
||||
|
||||
}
|
37
source/game/terrain/StarDisplacementSelector.hpp
Normal file
37
source/game/terrain/StarDisplacementSelector.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef STAR_DISPLACEMENT_SELECTOR_HPP
|
||||
#define STAR_DISPLACEMENT_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
#include "StarPerlin.hpp"
|
||||
#include "StarVector.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct DisplacementSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
DisplacementSelector(
|
||||
Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
PerlinF xDisplacementFunction;
|
||||
PerlinF yDisplacementFunction;
|
||||
|
||||
float xXInfluence;
|
||||
float xYInfluence;
|
||||
float yXInfluence;
|
||||
float yYInfluence;
|
||||
|
||||
bool yClamp;
|
||||
Vec2F yClampRange;
|
||||
float yClampSmoothing;
|
||||
|
||||
float clampY(float v) const;
|
||||
|
||||
TerrainSelectorConstPtr m_source;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
18
source/game/terrain/StarFlatSurfaceSelector.cpp
Normal file
18
source/game/terrain/StarFlatSurfaceSelector.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include "StarFlatSurfaceSelector.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const FlatSurfaceSelector::Name = "flatSurface";
|
||||
|
||||
FlatSurfaceSelector::FlatSurfaceSelector(Json const& config, TerrainSelectorParameters const& parameters)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
surfaceLevel = parameters.baseHeight;
|
||||
adjustment = config.getFloat("adjustment", 0);
|
||||
flip = config.getBool("flip", false) ? -1 : 1;
|
||||
}
|
||||
|
||||
float FlatSurfaceSelector::get(int, int y) const {
|
||||
return flip * (surfaceLevel - (y - adjustment));
|
||||
}
|
||||
|
||||
}
|
22
source/game/terrain/StarFlatSurfaceSelector.hpp
Normal file
22
source/game/terrain/StarFlatSurfaceSelector.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef STAR_FLAT_SURFACE_SELECTOR_HPP
|
||||
#define STAR_FLAT_SURFACE_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct FlatSurfaceSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
FlatSurfaceSelector(Json const& config, TerrainSelectorParameters const& parameters);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
float surfaceLevel;
|
||||
float adjustment;
|
||||
float flip;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
50
source/game/terrain/StarIslandSurfaceSelector.cpp
Normal file
50
source/game/terrain/StarIslandSurfaceSelector.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include "StarIslandSurfaceSelector.hpp"
|
||||
#include "StarGameTypes.hpp"
|
||||
#include "StarRandom.hpp"
|
||||
#include "StarJsonExtra.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const IslandSurfaceSelector::Name = "islandSurface";
|
||||
|
||||
IslandSurfaceSelector::IslandSurfaceSelector(Json const& config, TerrainSelectorParameters const& parameters)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
layerBaseHeight = parameters.baseHeight;
|
||||
worldWidth = parameters.worldWidth;
|
||||
|
||||
islandElevation = config.getFloat("islandElevation");
|
||||
islandTaperPoint = config.getFloat("islandTaperPoint");
|
||||
|
||||
islandHeight = PerlinF(config.getObject("islandHeight"), staticRandomU64(parameters.seed, parameters.baseHeight, "islandHeight"));
|
||||
islandDepth = PerlinF(config.getObject("islandDepth"), staticRandomU64(parameters.seed, parameters.baseHeight, "islandDepth"));
|
||||
islandDecision = PerlinF(config.getObject("islandDecision"), staticRandomU64(parameters.seed, parameters.baseHeight, "islandDecision"));
|
||||
}
|
||||
|
||||
IslandColumn IslandSurfaceSelector::generateColumn(int x) const {
|
||||
float noiseAngle = 2 * Constants::pi * x / worldWidth;
|
||||
float noiseX = (std::cos(noiseAngle) * worldWidth) / (2 * Constants::pi);
|
||||
float noiseY = (std::sin(noiseAngle) * worldWidth) / (2 * Constants::pi);
|
||||
|
||||
IslandColumn newCol;
|
||||
float thisIslandDecision = islandDecision.get(noiseX, noiseY);
|
||||
if (thisIslandDecision > 0) {
|
||||
float taperFactor = thisIslandDecision < islandTaperPoint ? std::sin((0.5 * Constants::pi * thisIslandDecision) / islandTaperPoint) : 1.0f;
|
||||
newCol.topLevel = islandElevation + layerBaseHeight + taperFactor * islandHeight.get(noiseX, noiseY);
|
||||
newCol.bottomLevel = islandElevation + layerBaseHeight - taperFactor * islandDepth.get(noiseX, noiseY);
|
||||
} else {
|
||||
newCol.topLevel = layerBaseHeight;
|
||||
newCol.bottomLevel = layerBaseHeight;
|
||||
}
|
||||
|
||||
return newCol;
|
||||
}
|
||||
|
||||
float IslandSurfaceSelector::get(int x, int y) const {
|
||||
auto col = columnCache.get(x, [=](int x) {
|
||||
return IslandSurfaceSelector::generateColumn(x);
|
||||
});
|
||||
|
||||
return (col.topLevel - col.bottomLevel) / 2 - abs((col.topLevel + col.bottomLevel) / 2 - y);
|
||||
}
|
||||
|
||||
}
|
39
source/game/terrain/StarIslandSurfaceSelector.hpp
Normal file
39
source/game/terrain/StarIslandSurfaceSelector.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef STAR_ISLAND_SURFACE_SELECTOR_HPP
|
||||
#define STAR_ISLAND_SURFACE_SELECTOR_HPP
|
||||
|
||||
#include "StarLruCache.hpp"
|
||||
#include "StarPerlin.hpp"
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct IslandColumn {
|
||||
float topLevel;
|
||||
float bottomLevel;
|
||||
};
|
||||
|
||||
struct IslandSurfaceSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
IslandSurfaceSelector(Json const& config, TerrainSelectorParameters const& parameters);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
IslandColumn generateColumn(int x) const;
|
||||
|
||||
mutable HashLruCache<int, IslandColumn> columnCache;
|
||||
|
||||
PerlinF islandHeight;
|
||||
PerlinF islandDepth;
|
||||
PerlinF islandDecision;
|
||||
|
||||
float islandTaperPoint;
|
||||
float islandElevation;
|
||||
|
||||
float layerBaseHeight;
|
||||
int worldWidth;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
114
source/game/terrain/StarKarstCave.cpp
Normal file
114
source/game/terrain/StarKarstCave.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
#include "StarKarstCave.hpp"
|
||||
#include "StarJsonExtra.hpp"
|
||||
#include "StarRandom.hpp"
|
||||
#include "StarInterpolation.hpp"
|
||||
#include "StarGameTypes.hpp"
|
||||
#include "StarLogging.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const KarstCaveSelector::Name = "karstcave";
|
||||
|
||||
KarstCaveSelector::KarstCaveSelector(Json const& config, TerrainSelectorParameters const& parameters)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
m_sectorSize = config.getUInt("sectorSize", 64);
|
||||
m_layerResolution = config.getInt("layerResolution");
|
||||
m_layerDensity = config.getFloat("layerDensity");
|
||||
m_bufferHeight = config.getInt("bufferHeight");
|
||||
m_caveTaperPoint = config.getFloat("caveTaperPoint");
|
||||
|
||||
m_caveDecisionPerlinConfig = config.get("caveDecision");
|
||||
m_layerHeightVariationPerlinConfig = config.get("layerHeightVariation");
|
||||
m_caveHeightVariationPerlinConfig = config.get("caveHeightVariation");
|
||||
m_caveFloorVariationPerlinConfig = config.get("caveFloorVariation");
|
||||
|
||||
m_worldWidth = parameters.worldWidth;
|
||||
m_seed = parameters.seed;
|
||||
|
||||
m_layerPerlinsCache.setMaxSize(config.getUInt("layerPerlinsCacheSize", 16));
|
||||
m_sectorCache.setMaxSize(config.getUInt("sectorCacheSize", 16));
|
||||
}
|
||||
|
||||
float KarstCaveSelector::get(int x, int y) const {
|
||||
Vec2I key = Vec2I(x - pmod(x, m_sectorSize), y - pmod(y, m_sectorSize));
|
||||
return m_sectorCache.get(key, [=](Vec2I const& key) {
|
||||
return Sector(this, key);
|
||||
}).get(x, y);
|
||||
}
|
||||
|
||||
KarstCaveSelector::Sector::Sector(KarstCaveSelector const* parent, Vec2I sector)
|
||||
: parent(parent), sector(sector), values(square(parent->m_sectorSize)) {
|
||||
|
||||
m_maxValue = 0;
|
||||
|
||||
for (int y = sector[1] - parent->m_bufferHeight; y < sector[1] + parent->m_sectorSize + parent->m_bufferHeight; y++) {
|
||||
float layerChance = parent->m_layerDensity * parent->m_layerResolution;
|
||||
// determine whether this layer has caves
|
||||
if (y % parent->m_layerResolution == 0 && staticRandomFloat(parent->m_seed, y) <= layerChance) {
|
||||
LayerPerlins const& layerPerlins = parent->layerPerlins(y);
|
||||
|
||||
// carve out cave layer
|
||||
for (int x = sector[0]; x < sector[0] + parent->m_sectorSize; x++) {
|
||||
// use wrapping noise
|
||||
float noiseAngle = 2 * Constants::pi * x / parent->m_worldWidth;
|
||||
float noiseX = (std::cos(noiseAngle) * parent->m_worldWidth) / (2 * Constants::pi);
|
||||
float noiseY = (std::sin(noiseAngle) * parent->m_worldWidth) / (2 * Constants::pi);
|
||||
|
||||
// determine where caves be at
|
||||
float isThereACaveHere = layerPerlins.caveDecision.get(noiseX, noiseY);
|
||||
if (isThereACaveHere > 0) {
|
||||
float taperFactor = isThereACaveHere < parent->m_caveTaperPoint
|
||||
? std::sin((0.5 * Constants::pi * isThereACaveHere) / parent->m_caveTaperPoint)
|
||||
: 1.0f;
|
||||
|
||||
int baseY = y + layerPerlins.layerHeightVariation.get(noiseX, noiseY);
|
||||
int ceilingY = baseY + layerPerlins.caveHeightVariation.get(noiseX, noiseY) * taperFactor;
|
||||
int floorY = baseY + layerPerlins.caveFloorVariation.get(noiseX, noiseY) * taperFactor;
|
||||
float halfHeight = abs(ceilingY - floorY + 1) / 2.0f;
|
||||
float midpointY = (floorY + ceilingY) / 2.0f;
|
||||
|
||||
m_maxValue = max(m_maxValue, halfHeight);
|
||||
|
||||
for (int pointY = floorY; pointY < ceilingY; pointY++)
|
||||
if (inside(x, pointY))
|
||||
set(x, pointY, max(get(x, pointY), halfHeight - abs(midpointY - pointY)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float KarstCaveSelector::Sector::get(int x, int y) {
|
||||
auto val = values[(x - sector[0]) + parent->m_sectorSize * (y - sector[1])];
|
||||
if (val > 0)
|
||||
return val;
|
||||
else
|
||||
return -m_maxValue;
|
||||
}
|
||||
|
||||
bool KarstCaveSelector::Sector::inside(int x, int y) {
|
||||
int x_ = x - sector[0];
|
||||
if (x_ < 0 || x_ >= parent->m_sectorSize)
|
||||
return false;
|
||||
int y_ = y - sector[1];
|
||||
if (y_ < 0 || y_ >= parent->m_sectorSize)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void KarstCaveSelector::Sector::set(int x, int y, float value) {
|
||||
values[(x - sector[0]) + parent->m_sectorSize * (y - sector[1])] = value;
|
||||
}
|
||||
|
||||
KarstCaveSelector::LayerPerlins const& KarstCaveSelector::layerPerlins(int y) const {
|
||||
return m_layerPerlinsCache.get(y, [this](int y) {
|
||||
return LayerPerlins{
|
||||
PerlinF(m_caveDecisionPerlinConfig, staticRandomU64(y, m_seed, "CaveDecision")),
|
||||
PerlinF(m_layerHeightVariationPerlinConfig, staticRandomU64(y, m_seed, "LayerHeightVariation")),
|
||||
PerlinF(m_caveHeightVariationPerlinConfig, staticRandomU64(y, m_seed, "CaveHeightVariation")),
|
||||
PerlinF(m_caveFloorVariationPerlinConfig, staticRandomU64(y, m_seed, "CaveFloorVariation"))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
}
|
64
source/game/terrain/StarKarstCave.hpp
Normal file
64
source/game/terrain/StarKarstCave.hpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#ifndef STAR_KARST_CAVE_HPP
|
||||
#define STAR_KARST_CAVE_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
#include "StarLruCache.hpp"
|
||||
#include "StarVector.hpp"
|
||||
#include "StarPerlin.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
class KarstCaveSelector : public TerrainSelector {
|
||||
public:
|
||||
static char const* const Name;
|
||||
|
||||
KarstCaveSelector(Json const& config, TerrainSelectorParameters const& parameters);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
private:
|
||||
struct LayerPerlins {
|
||||
PerlinF caveDecision;
|
||||
PerlinF layerHeightVariation;
|
||||
PerlinF caveHeightVariation;
|
||||
PerlinF caveFloorVariation;
|
||||
};
|
||||
|
||||
struct Sector {
|
||||
Sector(KarstCaveSelector const* parent, Vec2I sector);
|
||||
|
||||
float get(int x, int y);
|
||||
|
||||
bool inside(int x, int y);
|
||||
void set(int x, int y, float value);
|
||||
|
||||
KarstCaveSelector const* parent;
|
||||
Vec2I sector;
|
||||
List<float> values;
|
||||
|
||||
float m_maxValue;
|
||||
};
|
||||
|
||||
LayerPerlins const& layerPerlins(int y) const;
|
||||
|
||||
int m_sectorSize;
|
||||
int m_layerResolution;
|
||||
float m_layerDensity;
|
||||
int m_bufferHeight;
|
||||
float m_caveTaperPoint;
|
||||
|
||||
Json m_caveDecisionPerlinConfig;
|
||||
Json m_layerHeightVariationPerlinConfig;
|
||||
Json m_caveHeightVariationPerlinConfig;
|
||||
Json m_caveFloorVariationPerlinConfig;
|
||||
|
||||
int m_worldWidth;
|
||||
uint64_t m_seed;
|
||||
|
||||
mutable HashLruCache<int, LayerPerlins> m_layerPerlinsCache;
|
||||
mutable HashLruCache<Vec2I, Sector> m_sectorCache;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
source/game/terrain/StarMaxSelector.cpp
Normal file
27
source/game/terrain/StarMaxSelector.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include "StarMaxSelector.hpp"
|
||||
#include "StarMathCommon.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const MaxSelector::Name = "max";
|
||||
|
||||
MaxSelector::MaxSelector(
|
||||
Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
for (auto const& sourceConfig : config.getArray("sources")) {
|
||||
String sourceType = sourceConfig.getString("type");
|
||||
uint64_t seedBias = sourceConfig.getUInt("seedBias", 0);
|
||||
TerrainSelectorParameters sourceParameters = parameters;
|
||||
sourceParameters.seed += seedBias;
|
||||
m_sources.append(database->createSelectorType(sourceType, sourceConfig, sourceParameters));
|
||||
}
|
||||
}
|
||||
|
||||
float MaxSelector::get(int x, int y) const {
|
||||
float value = lowest<float>();
|
||||
for (auto const& source : m_sources)
|
||||
value = max(value, source->get(x, y));
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
20
source/game/terrain/StarMaxSelector.hpp
Normal file
20
source/game/terrain/StarMaxSelector.hpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef STAR_MAX_SELECTOR_HPP
|
||||
#define STAR_MAX_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct MaxSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
MaxSelector(Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
List<TerrainSelectorConstPtr> m_sources;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
32
source/game/terrain/StarMinMaxSelector.cpp
Normal file
32
source/game/terrain/StarMinMaxSelector.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "StarMinMaxSelector.hpp"
|
||||
#include "StarMathCommon.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const MinMaxSelector::Name = "minmax";
|
||||
|
||||
MinMaxSelector::MinMaxSelector(
|
||||
Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
for (auto const& sourceConfig : config.getArray("sources")) {
|
||||
String sourceType = sourceConfig.getString("type");
|
||||
uint64_t seedBias = sourceConfig.getUInt("seedBias", 0);
|
||||
TerrainSelectorParameters sourceParameters = parameters;
|
||||
sourceParameters.seed += seedBias;
|
||||
m_sources.append(database->createSelectorType(sourceType, sourceConfig, sourceParameters));
|
||||
}
|
||||
}
|
||||
|
||||
float MinMaxSelector::get(int x, int y) const {
|
||||
float value = 0.0f;
|
||||
for (auto const& source : m_sources) {
|
||||
float srcVal = source->get(x, y);
|
||||
if (value > 0 || srcVal > 0)
|
||||
value = max(value, srcVal);
|
||||
else
|
||||
value = min(value, srcVal);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
20
source/game/terrain/StarMinMaxSelector.hpp
Normal file
20
source/game/terrain/StarMinMaxSelector.hpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef STAR_MIN_MAX_SELECTOR_HPP
|
||||
#define STAR_MIN_MAX_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct MinMaxSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
MinMaxSelector(Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
List<TerrainSelectorConstPtr> m_sources;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
29
source/game/terrain/StarMixSelector.cpp
Normal file
29
source/game/terrain/StarMixSelector.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include "StarMixSelector.hpp"
|
||||
#include "StarInterpolation.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const MixSelector::Name = "mix";
|
||||
|
||||
MixSelector::MixSelector(Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
auto readSource = [&](Json const& sourceConfig) {
|
||||
String type = sourceConfig.getString("type");
|
||||
return database->createSelectorType(type, sourceConfig, parameters);
|
||||
};
|
||||
|
||||
m_mixSource = readSource(config.get("mixSource"));
|
||||
m_aSource = readSource(config.get("aSource"));
|
||||
m_bSource = readSource(config.get("bSource"));
|
||||
}
|
||||
|
||||
float MixSelector::get(int x, int y) const {
|
||||
auto f = clamp(m_mixSource->get(x, y), -1.0f, 1.0f);
|
||||
if (f == -1)
|
||||
return m_aSource->get(x, y);
|
||||
if (f == 1)
|
||||
return m_bSource->get(x, y);
|
||||
return lerp(f * 0.5f + 0.5f, m_aSource->get(x, y), m_bSource->get(x, y));
|
||||
}
|
||||
|
||||
}
|
22
source/game/terrain/StarMixSelector.hpp
Normal file
22
source/game/terrain/StarMixSelector.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef STAR_MIX_SELECTOR_HPP
|
||||
#define STAR_MIX_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct MixSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
MixSelector(Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
TerrainSelectorConstPtr m_mixSource;
|
||||
TerrainSelectorConstPtr m_aSource;
|
||||
TerrainSelectorConstPtr m_bSource;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
30
source/game/terrain/StarPerlinSelector.cpp
Normal file
30
source/game/terrain/StarPerlinSelector.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "StarPerlinSelector.hpp"
|
||||
#include "StarRandom.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const PerlinSelector::Name = "perlin";
|
||||
|
||||
PerlinSelector::PerlinSelector(Json const& config, TerrainSelectorParameters const& parameters)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
RandomSource random(parameters.seed);
|
||||
|
||||
auto type = PerlinTypeNames.getLeft(config.getString("function"));
|
||||
auto octaves = config.getFloat("octaves");
|
||||
auto freq = config.getFloat("freq");
|
||||
auto amp = config.getFloat("amp");
|
||||
auto bias = config.getFloat("bias", 0.0f);
|
||||
auto alpha = config.getFloat("alpha", 2.0f);
|
||||
auto beta = config.getFloat("beta", 2.0f);
|
||||
|
||||
function = PerlinF(type, octaves, freq, amp, bias, alpha, beta, random.randu64());
|
||||
|
||||
xInfluence = config.getFloat("xInfluence", 1.0f);
|
||||
yInfluence = config.getFloat("yInfluence", 1.0f);
|
||||
}
|
||||
|
||||
float PerlinSelector::get(int x, int y) const {
|
||||
return function.get(x * xInfluence, y * yInfluence);
|
||||
}
|
||||
|
||||
}
|
24
source/game/terrain/StarPerlinSelector.hpp
Normal file
24
source/game/terrain/StarPerlinSelector.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef STAR_PERLIN_SELECTOR_HPP
|
||||
#define STAR_PERLIN_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
#include "StarPerlin.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct PerlinSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
PerlinSelector(Json const& config, TerrainSelectorParameters const& parameters);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
PerlinF function;
|
||||
|
||||
float xInfluence;
|
||||
float yInfluence;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
35
source/game/terrain/StarRidgeBlocksSelector.cpp
Normal file
35
source/game/terrain/StarRidgeBlocksSelector.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "StarRidgeBlocksSelector.hpp"
|
||||
#include "StarRandom.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const RidgeBlocksSelector::Name = "ridgeblocks";
|
||||
|
||||
RidgeBlocksSelector::RidgeBlocksSelector(Json const& config, TerrainSelectorParameters const& parameters)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
commonality = parameters.commonality;
|
||||
|
||||
amplitude = config.getFloat("amplitude");
|
||||
frequency = config.getFloat("frequency");
|
||||
bias = config.getFloat("bias");
|
||||
|
||||
noiseAmplitude = config.getFloat("noiseAmplitude");
|
||||
noiseFrequency = config.getFloat("noiseFrequency");
|
||||
|
||||
RandomSource random(parameters.seed);
|
||||
ridgePerlin1 = PerlinF(PerlinType::RidgedMulti, 2, frequency, amplitude, 0, 2.0f, 2.0f, random.randu64());
|
||||
ridgePerlin2 = PerlinF(PerlinType::RidgedMulti, 2, frequency, amplitude, 0, 2.0f, 2.0f, random.randu64());
|
||||
noisePerlin = PerlinF(1, noiseFrequency, noiseAmplitude, 0, 1.0f, 2.0f, random.randu64());
|
||||
}
|
||||
|
||||
float RidgeBlocksSelector::get(int x, int y) const {
|
||||
if (commonality <= 0.0f) {
|
||||
return 0.0f;
|
||||
} else {
|
||||
x += noisePerlin.get(x, y);
|
||||
y += noisePerlin.get(y, x);
|
||||
return (ridgePerlin1.get(x, y) - ridgePerlin2.get(x, y)) * commonality + bias;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
32
source/game/terrain/StarRidgeBlocksSelector.hpp
Normal file
32
source/game/terrain/StarRidgeBlocksSelector.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef STAR_RIDGE_BLOCKS_SELECTOR_HPP
|
||||
#define STAR_RIDGE_BLOCKS_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
#include "StarPerlin.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct RidgeBlocksSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
RidgeBlocksSelector(Json const& config, TerrainSelectorParameters const& parameters);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
float commonality;
|
||||
|
||||
float amplitude;
|
||||
float frequency;
|
||||
float bias;
|
||||
|
||||
float noiseAmplitude;
|
||||
float noiseFrequency;
|
||||
|
||||
PerlinF ridgePerlin1;
|
||||
PerlinF ridgePerlin2;
|
||||
PerlinF noisePerlin;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
source/game/terrain/StarRotateSelector.cpp
Normal file
27
source/game/terrain/StarRotateSelector.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include "StarRotateSelector.hpp"
|
||||
#include "StarRandom.hpp"
|
||||
#include "StarJsonExtra.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const RotateSelector::Name = "rotate";
|
||||
|
||||
RotateSelector::RotateSelector(
|
||||
Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
RandomSource random(parameters.seed);
|
||||
|
||||
rotation = config.getFloat("rotation");
|
||||
rotationCenter = Vec2F(parameters.worldWidth / 2, 0);
|
||||
|
||||
auto sourceConfig = config.get("source");
|
||||
String sourceType = sourceConfig.getString("type");
|
||||
m_source = database->createSelectorType(sourceType, sourceConfig, parameters);
|
||||
}
|
||||
|
||||
float RotateSelector::get(int x, int y) const {
|
||||
auto pos = (Vec2F(x, y) - rotationCenter).rotate(rotation) + rotationCenter;
|
||||
return m_source->get(pos[0], pos[1]);
|
||||
}
|
||||
|
||||
}
|
24
source/game/terrain/StarRotateSelector.hpp
Normal file
24
source/game/terrain/StarRotateSelector.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef STAR_ROTATE_SELECTOR_HPP
|
||||
#define STAR_ROTATE_SELECTOR_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
#include "StarVector.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
struct RotateSelector : TerrainSelector {
|
||||
static char const* const Name;
|
||||
|
||||
RotateSelector(Json const& config, TerrainSelectorParameters const& parameters, TerrainDatabase const* database);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
float rotation;
|
||||
Vec2F rotationCenter;
|
||||
|
||||
TerrainSelectorConstPtr m_source;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
157
source/game/terrain/StarWormCave.cpp
Normal file
157
source/game/terrain/StarWormCave.cpp
Normal file
|
@ -0,0 +1,157 @@
|
|||
#include "StarWormCave.hpp"
|
||||
#include "StarJsonExtra.hpp"
|
||||
#include "StarRandom.hpp"
|
||||
#include "StarInterpolation.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* const WormCaveSelector::Name = "wormcave";
|
||||
|
||||
WormCaveSector::WormCaveSector(int sectorSize, Vec2I sector, Json const& config, size_t seed, float commonality)
|
||||
: m_sectorSize(sectorSize), m_sector(sector), m_values(sectorSize * sectorSize) {
|
||||
struct Worm {
|
||||
Vec2F pos;
|
||||
float angle;
|
||||
float goalAngle;
|
||||
float size;
|
||||
float length;
|
||||
float goalLength;
|
||||
};
|
||||
List<Worm> worms;
|
||||
|
||||
Vec2F numberOfWormsPerSectorRange = jsonToVec2F(config.get("numberOfWormsPerSectorRange"));
|
||||
Vec2F wormSizeRange = jsonToVec2F(config.get("wormSizeRange"));
|
||||
Vec2F wormLengthRange = jsonToVec2F(config.get("wormLengthRange"));
|
||||
float wormTaperDistance = config.getFloat("wormTaperDistance");
|
||||
Vec2F wormAngleRange = jsonToVec2F(config.get("wormAngleRange"));
|
||||
float wormTurnChance = config.getFloat("wormTurnChance");
|
||||
float wormTurnRate = config.getFloat("wormTurnRate");
|
||||
|
||||
float wormSpeed = config.getFloat("wormSpeed", 1);
|
||||
|
||||
float twoPi = Constants::pi * 2;
|
||||
|
||||
m_maxValue = wormSizeRange[1] / 2;
|
||||
|
||||
// determine worms for the neighbouring sectors
|
||||
int sectorRadius = m_sectorSize * config.getInt("sectorRadius");
|
||||
for (int x = sector[0] - sectorRadius; x <= sector[0] + sectorRadius; x += m_sectorSize)
|
||||
for (int y = sector[1] - sectorRadius; y <= sector[1] + sectorRadius; y += m_sectorSize) {
|
||||
RandomSource rs(staticRandomU64(x, y, seed));
|
||||
float numberOfWorms = rs.randf(numberOfWormsPerSectorRange[0], numberOfWormsPerSectorRange[1]) * commonality;
|
||||
int intNumberOfWorms = (int)numberOfWorms;
|
||||
if (rs.randf() < (numberOfWorms - intNumberOfWorms))
|
||||
intNumberOfWorms++;
|
||||
for (int n = 0; n < intNumberOfWorms; ++n) {
|
||||
Worm worm;
|
||||
worm.pos = Vec2F(x, y) + Vec2F(rs.randf(0, m_sectorSize), rs.randf(0, m_sectorSize));
|
||||
worm.angle = rs.randf(wormAngleRange[0], wormAngleRange[1]);
|
||||
worm.goalAngle = rs.randf(wormAngleRange[0], wormAngleRange[1]);
|
||||
worm.size = rs.randf(wormSizeRange[0], wormSizeRange[1]) * commonality;
|
||||
worm.length = 0;
|
||||
worm.goalLength = rs.randf(wormLengthRange[0], wormLengthRange[1]) * commonality;
|
||||
worms.append(worm);
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
bool idle = true;
|
||||
|
||||
for (auto& worm : worms) {
|
||||
if (worm.length >= worm.goalLength)
|
||||
continue;
|
||||
|
||||
idle = false;
|
||||
|
||||
// taper size
|
||||
float wormRadius = worm.size / 2;
|
||||
float taperFactor = 1.0f;
|
||||
if (worm.length < wormTaperDistance)
|
||||
taperFactor = std::sin(0.5 * Constants::pi * worm.length / wormTaperDistance);
|
||||
else if (worm.goalLength - worm.length < wormTaperDistance)
|
||||
taperFactor = std::sin(0.5 * Constants::pi * (worm.goalLength - worm.length) / wormTaperDistance);
|
||||
wormRadius *= taperFactor;
|
||||
|
||||
// carve out worm area
|
||||
int size = ceil(wormRadius);
|
||||
for (float dx = -size; dx <= size; dx += 1)
|
||||
for (float dy = -size; dy <= size; dy += 1) {
|
||||
float m = sqrt((dx * dx) + (dy * dy));
|
||||
if (m <= wormRadius) {
|
||||
int x = floor(dx + worm.pos[0]);
|
||||
int y = floor(dy + worm.pos[1]);
|
||||
if (inside(x, y)) {
|
||||
float v = get(x, y);
|
||||
set(x, y, max(v, wormRadius - m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move the worm, slowing down a bit as we reach the ends to reduce
|
||||
// stutter
|
||||
float thisSpeed = max(0.75f, wormSpeed * taperFactor);
|
||||
worm.pos += Vec2F::withAngle(worm.angle) * thisSpeed;
|
||||
worm.length += thisSpeed;
|
||||
|
||||
// maybe set new goal angle
|
||||
if (staticRandomFloat(worm.pos[0], worm.pos[1], seed, 1) < wormTurnChance * thisSpeed) {
|
||||
worm.goalAngle = pfmod(
|
||||
staticRandomFloatRange(wormAngleRange[0], wormAngleRange[1], worm.pos[0], worm.pos[1], seed, 2), twoPi);
|
||||
}
|
||||
|
||||
if (worm.angle != worm.goalAngle) {
|
||||
// turn the worm toward goal angle
|
||||
float angleDiff = worm.goalAngle - worm.angle;
|
||||
|
||||
// stop if we're close enough
|
||||
if (abs(angleDiff) < wormTurnRate * thisSpeed)
|
||||
worm.angle = worm.goalAngle;
|
||||
else {
|
||||
// turn the shortest angular distance
|
||||
if (abs(angleDiff) > twoPi)
|
||||
angleDiff = -angleDiff;
|
||||
worm.angle = pfmod(worm.angle + copysign(wormTurnRate * thisSpeed, angleDiff), twoPi);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (idle)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float WormCaveSector::get(int x, int y) {
|
||||
auto val = m_values[(x - m_sector[0]) + m_sectorSize * (y - m_sector[1])];
|
||||
if (val > 0)
|
||||
return val;
|
||||
else
|
||||
return -m_maxValue;
|
||||
}
|
||||
|
||||
bool WormCaveSector::inside(int x, int y) {
|
||||
int x_ = x - m_sector[0];
|
||||
if (x_ < 0 || x_ >= m_sectorSize)
|
||||
return false;
|
||||
int y_ = y - m_sector[1];
|
||||
if (y_ < 0 || y_ >= m_sectorSize)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WormCaveSector::set(int x, int y, float value) {
|
||||
m_values[(x - m_sector[0]) + m_sectorSize * (y - m_sector[1])] = value;
|
||||
}
|
||||
|
||||
WormCaveSelector::WormCaveSelector(Json const& config, TerrainSelectorParameters const& parameters)
|
||||
: TerrainSelector(Name, config, parameters) {
|
||||
m_sectorSize = config.getUInt("sectorSize", 64);
|
||||
m_cache.setMaxSize(config.getUInt("lruCacheSize", 16));
|
||||
}
|
||||
|
||||
float WormCaveSelector::get(int x, int y) const {
|
||||
Vec2I sector = Vec2I(x - pmod(x, m_sectorSize), y - pmod(y, m_sectorSize));
|
||||
return m_cache.get(sector, [=](Vec2I const& sector) {
|
||||
return WormCaveSector(m_sectorSize, sector, config, parameters.seed, parameters.commonality);
|
||||
}).get(x, y);
|
||||
}
|
||||
|
||||
}
|
42
source/game/terrain/StarWormCave.hpp
Normal file
42
source/game/terrain/StarWormCave.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef STAR_WORM_CAVE_HPP
|
||||
#define STAR_WORM_CAVE_HPP
|
||||
|
||||
#include "StarTerrainDatabase.hpp"
|
||||
#include "StarLruCache.hpp"
|
||||
#include "StarVector.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
class WormCaveSector {
|
||||
public:
|
||||
WormCaveSector(int sectorSize, Vec2I sector, Json const& config, size_t seed, float commonality);
|
||||
|
||||
float get(int x, int y);
|
||||
|
||||
private:
|
||||
bool inside(int x, int y);
|
||||
void set(int x, int y, float value);
|
||||
|
||||
int m_sectorSize;
|
||||
Vec2I m_sector;
|
||||
List<float> m_values;
|
||||
|
||||
float m_maxValue;
|
||||
};
|
||||
|
||||
class WormCaveSelector : public TerrainSelector {
|
||||
public:
|
||||
static char const* const Name;
|
||||
|
||||
WormCaveSelector(Json const& config, TerrainSelectorParameters const& parameters);
|
||||
|
||||
float get(int x, int y) const override;
|
||||
|
||||
private:
|
||||
int m_sectorSize;
|
||||
mutable HashLruCache<Vec2I, WormCaveSector> m_cache;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue