feat: add mixCoord and replaceable
This commit is contained in:
1 parent
cf7321610c
commit
477bdd67e7
1 file changed
+159
@@ -0,0 +1,159 @@
|
|||||||
|
#include "vf/NetherGen.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
uint32_t mixCoord(uint32_t seed, int gx, int gy, int gz) {
|
||||||
|
uint64_t h = 1469598103934665603ull;
|
||||||
|
auto mix = [&h](uint32_t v) {
|
||||||
|
h ^= v;
|
||||||
|
h *= 1099511628211ull;
|
||||||
|
};
|
||||||
|
mix(seed);
|
||||||
|
mix(static_cast<uint32_t>(gx));
|
||||||
|
mix(static_cast<uint32_t>(gy));
|
||||||
|
mix(static_cast<uint32_t>(gz));
|
||||||
|
h ^= h >> 33;
|
||||||
|
return static_cast<uint32_t>(h ^ (h >> 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool replaceable(Block block) {
|
||||||
|
return block == Block::Air || block == Block::Lava;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
NetherGenerator::NetherGenerator() : NetherGenerator(Params{}) {}
|
||||||
|
|
||||||
|
NetherGenerator::NetherGenerator(const Params& netherParams)
|
||||||
|
: params(netherParams),
|
||||||
|
floorNoise(netherParams.seed ^ 0x4e455448u),
|
||||||
|
ceilingNoise(netherParams.seed ^ 0x524f4f46u),
|
||||||
|
caveNoise(netherParams.seed ^ 0x43415645u),
|
||||||
|
blobNoise(netherParams.seed ^ 0x424c4f42u),
|
||||||
|
oreNoise(netherParams.seed ^ 0x5155415au),
|
||||||
|
biomeNoise(netherParams.seed ^ 0x42494f4du) {}
|
||||||
|
|
||||||
|
NetherBiome NetherGenerator::biomeAt(int gx, int gz) const {
|
||||||
|
float f = params.biomeFrequency;
|
||||||
|
float heat = biomeNoise.simplex2D(gx * f, gz * f);
|
||||||
|
float damp = biomeNoise.simplex2D(gx * f * 1.7f + 91.3f, gz * f * 1.7f - 44.7f);
|
||||||
|
|
||||||
|
if (damp < -0.30f) return NetherBiome::SoulSandValley;
|
||||||
|
if (heat > 0.34f) return NetherBiome::BasaltDeltas;
|
||||||
|
if (damp > 0.26f) return NetherBiome::CrimsonForest;
|
||||||
|
return NetherBiome::NetherWastes;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetherColumn NetherGenerator::columnAt(int gx, int gz) const {
|
||||||
|
NetherColumn column;
|
||||||
|
column.biome = biomeAt(gx, gz);
|
||||||
|
column.lavaLevel = params.lavaLevel;
|
||||||
|
|
||||||
|
float ff = params.floorFrequency;
|
||||||
|
float broad = floorNoise.fbm2D(gx * ff, gz * ff, 4, 2.0f, 0.5f);
|
||||||
|
float rough = floorNoise.noise2D(gx * ff * 3.1f + 17.0f, gz * ff * 3.1f - 9.0f);
|
||||||
|
|
||||||
|
int floorCentre = params.lavaLevel + 3;
|
||||||
|
float amplitude = 12.0f;
|
||||||
|
switch (column.biome) {
|
||||||
|
case NetherBiome::SoulSandValley:
|
||||||
|
floorCentre -= 8;
|
||||||
|
amplitude = 15.0f;
|
||||||
|
break;
|
||||||
|
case NetherBiome::BasaltDeltas:
|
||||||
|
floorCentre -= 3;
|
||||||
|
amplitude = 9.0f;
|
||||||
|
break;
|
||||||
|
case NetherBiome::CrimsonForest:
|
||||||
|
floorCentre += 4;
|
||||||
|
amplitude = 8.0f;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float shaped = broad * 0.78f + rough * 0.22f;
|
||||||
|
column.floorHeight = floorCentre + static_cast<int>(std::lround(shaped * amplitude));
|
||||||
|
|
||||||
|
float cf = params.ceilingFrequency;
|
||||||
|
float roof = ceilingNoise.fbm2D(gx * cf, gz * cf, 3, 2.0f, 0.5f);
|
||||||
|
column.ceilingHeight = params.ceilingY - params.roofThickness +
|
||||||
|
static_cast<int>(std::lround(roof * 7.0f));
|
||||||
|
|
||||||
|
int lowest = params.floorY + params.bedrockThickness + 1;
|
||||||
|
int highest = params.ceilingY - params.bedrockThickness - 2;
|
||||||
|
if (column.floorHeight < lowest) column.floorHeight = lowest;
|
||||||
|
if (column.floorHeight > highest - 12) column.floorHeight = highest - 12;
|
||||||
|
if (column.ceilingHeight > highest) column.ceilingHeight = highest;
|
||||||
|
if (column.ceilingHeight < column.floorHeight + 10) column.ceilingHeight = column.floorHeight + 10;
|
||||||
|
|
||||||
|
column.drowned = column.floorHeight < params.lavaLevel;
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetherGenerator::isCarved(int gx, int gy, int gz) const {
|
||||||
|
float f = params.caveFrequency;
|
||||||
|
float first = 1.0f - std::fabs(caveNoise.noise3D(gx * f, gy * f * 1.9f, gz * f));
|
||||||
|
float second = 1.0f - std::fabs(caveNoise.noise3D(gx * f + 41.3f, gy * f * 1.9f - 17.9f,
|
||||||
|
gz * f + 23.1f));
|
||||||
|
return first > params.caveThreshold && second > params.caveThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetherGenerator::isBlob(int gx, int gy, int gz) const {
|
||||||
|
float broad = blobNoise.noise3D(gx * 0.026f, gy * 0.019f, gz * 0.026f);
|
||||||
|
float detail = blobNoise.noise3D(gx * 0.056f + 7.3f, gy * 0.048f - 3.1f, gz * 0.056f + 2.7f);
|
||||||
|
return broad + detail * 0.42f > params.blobThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetherGenerator::isBedrock(int gx, int gy, int gz) const {
|
||||||
|
if (gy == params.floorY || gy == params.ceilingY - 1) return true;
|
||||||
|
|
||||||
|
int fromFloor = gy - params.floorY;
|
||||||
|
int fromCeiling = params.ceilingY - 1 - gy;
|
||||||
|
int band = -1;
|
||||||
|
if (fromFloor > 0 && fromFloor < params.bedrockThickness) band = fromFloor;
|
||||||
|
else if (fromCeiling > 0 && fromCeiling < params.bedrockThickness) band = fromCeiling;
|
||||||
|
if (band < 0) return false;
|
||||||
|
|
||||||
|
uint32_t roll = mixCoord(params.seed ^ 0x42454452u, gx, gy, gz);
|
||||||
|
return static_cast<int>(roll % static_cast<uint32_t>(params.bedrockThickness)) >= band;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block NetherGenerator::topFor(NetherBiome biome) const {
|
||||||
|
switch (biome) {
|
||||||
|
case NetherBiome::SoulSandValley: return Block::SoulSand;
|
||||||
|
case NetherBiome::BasaltDeltas: return Block::Basalt;
|
||||||
|
case NetherBiome::CrimsonForest: return Block::Moss;
|
||||||
|
default: return Block::Netherrack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Block NetherGenerator::fillerFor(NetherBiome biome) const {
|
||||||
|
switch (biome) {
|
||||||
|
case NetherBiome::SoulSandValley: return Block::SoulSoil;
|
||||||
|
case NetherBiome::BasaltDeltas: return Block::Blackstone;
|
||||||
|
default: return Block::Netherrack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Block NetherGenerator::blockAt(const NetherColumn& column, int gx, int gy, int gz) const {
|
||||||
|
if (gy < params.floorY || gy >= params.ceilingY) return Block::Air;
|
||||||
|
if (isBedrock(gx, gy, gz)) return Block::Bedrock;
|
||||||
|
|
||||||
|
bool inMass = gy <= column.floorHeight || gy >= column.ceilingHeight;
|
||||||
|
bool solid = inMass || isBlob(gx, gy, gz);
|
||||||
|
if (solid && isCarved(gx, gy, gz)) solid = false;
|
||||||
|
if (!solid) return gy <= params.lavaLevel ? Block::Lava : Block::Air;
|
||||||
|
|
||||||
|
Block material = Block::Netherrack;
|
||||||
|
if (gy <= column.floorHeight) {
|
||||||
|
int depth = column.floorHeight - gy;
|
||||||
|
if (depth == 0) material = topFor(column.biome);
|
||||||
|
else if (depth <= 3) material = fillerFor(column.biome);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user