diff --git a/Application/Block.h b/Application/Block.h index 9fd8974..beac8de 100644 --- a/Application/Block.h +++ b/Application/Block.h @@ -11,6 +11,7 @@ enum class BlockType : std::uint32_t Dirt, Stone, Grass, + Sand, EndEnum }; diff --git a/Application/Chunk.cpp b/Application/Chunk.cpp index a0ec1d2..4fcad54 100644 --- a/Application/Chunk.cpp +++ b/Application/Chunk.cpp @@ -9,10 +9,11 @@ constexpr Scop::Vec2ui ATLAS_SIZE = { 64, 64 }; constexpr Scop::Vec2f SPRITE_UNIT = Scop::Vec2f(SPRITE_SIZE) / Scop::Vec2f(ATLAS_SIZE); constexpr std::array, BlocksCount> BLOCKS_TO_ATLAS = { - std::array{ Scop::Vec2ui{ 0, 0 } }, // Air - std::array{ Scop::Vec2ui{ 0, 0 } }, // Dirt - std::array{ Scop::Vec2ui{ 1, 0 } }, // Stone + std::array{ Scop::Vec2ui{ 0, 0 }, Scop::Vec2ui{ 0, 0 }, Scop::Vec2ui{ 0, 0 } }, // Air + std::array{ Scop::Vec2ui{ 0, 0 }, Scop::Vec2ui{ 0, 0 }, Scop::Vec2ui{ 0, 0 } }, // Dirt + std::array{ Scop::Vec2ui{ 1, 0 }, Scop::Vec2ui{ 1, 0 }, Scop::Vec2ui{ 1, 0 } }, // Stone std::array{ Scop::Vec2ui{ 2, 0 }, Scop::Vec2ui{ 0, 0 }, Scop::Vec2ui{ 3, 0 } }, // Grass + std::array{ Scop::Vec2ui{ 0, 1 }, Scop::Vec2ui{ 0, 1 }, Scop::Vec2ui{ 0, 1 } }, // Sand }; enum class Side : std::uint8_t diff --git a/Application/Noise.cpp b/Application/Noise.cpp index ef578ec..f882739 100644 --- a/Application/Noise.cpp +++ b/Application/Noise.cpp @@ -2,25 +2,25 @@ #include #include #include -#include + +constexpr float HEIGHT_COEFF = 255.0f; Noise::Noise(const std::uint32_t seed, float frequency, float amplitude, int octaves, float lacunarity, float persistance): seed(std::mt19937(seed)), frequency(frequency), amplitude(amplitude), octaves(octaves), lacunarity(lacunarity), persistance(persistance) { - if (amplitude > 1.0f || amplitude < -1.0f) - { - throw std::invalid_argument("Amplitude value must be in [-1;1]"); - } + if(amplitude > 1.0f || amplitude < -1.0f) + Scop::FatalError("Amplitude value must be in [-1;1]"); + InitPermutation(); } -void Noise::InitPermutation(void) +void Noise::InitPermutation() { std::array permutations; - for (int i = 0; i < 256; ++i) + for(int i = 0; i < 256; ++i) permutations[i] = i; std::shuffle(permutations.begin(), permutations.end(), seed); - for (int i = 0; i < 256; ++i) + for(int i = 0; i < 256; ++i) { this->perms[i] = permutations[i]; this->perms[i + 256] = permutations[i]; @@ -29,37 +29,31 @@ void Noise::InitPermutation(void) [[nodiscard]] const float Noise::fade(float t) noexcept { - return t * t * t * (t * (t * 6 - 15) + 10); } -[[nodiscard]] const float Noise::lerp(float a, float b, float t) noexcept -{ - return (a + t * (b - a)); -} - const float Noise::Perlin2D(float x, float y) noexcept { - int xi = (int)floor(x) & 255; - int yi = (int)floor(y) & 255; + int xi = static_cast(floor(x)) & 255; + int yi = static_cast(floor(y)) & 255; - float xf = x - floor(x); - float yf = y - floor(y); + float xf = x - floor(x); + float yf = y - floor(y); - float u = fade(xf); - float v = fade(yf); + float u = fade(xf); + float v = fade(yf); - int aa = perms[perms[xi] + yi]; - int ab = perms[perms[xi] + yi + 1]; - int ba = perms[perms[xi + 1] + yi]; - int bb = perms[perms[xi + 1] + yi + 1]; + int aa = perms[perms[xi] + yi]; + int ab = perms[perms[xi] + yi + 1]; + int ba = perms[perms[xi + 1] + yi]; + int bb = perms[perms[xi + 1] + yi + 1]; - float x1 = lerp(grad2D(aa, xf, yf), - grad2D(ba, xf - 1, yf), u); - float x2 = lerp(grad2D(ab, xf, yf - 1), - grad2D(bb, xf - 1, yf - 1), u); + float x1 = std::lerp(grad2D(aa, xf, yf), + grad2D(ba, xf - 1, yf), u); + float x2 = std::lerp(grad2D(ab, xf, yf - 1), + grad2D(bb, xf - 1, yf - 1), u); - return ((lerp(x1, x2, v) + 1.0f) / 2.0f); + return ((std::lerp(x1, x2, v) + 1.0f) / 2.0f); } const int Noise::ApplyPerlin2DParameters(float x, float y) noexcept // Wrapper to apply various mumbo jumbo to get a very worldlike generation @@ -69,7 +63,8 @@ const int Noise::ApplyPerlin2DParameters(float x, float y) noexcept // Wrapper t float tmp_amp = amplitude; float maxValue = 0.0f; - for (int i = 0; i < this->octaves; ++i) { + for(int i = 0; i < this->octaves; ++i) + { total += Perlin2D(x * tmp_freq, y * tmp_freq) * tmp_amp; maxValue += tmp_amp; tmp_amp *= persistance; @@ -77,33 +72,31 @@ const int Noise::ApplyPerlin2DParameters(float x, float y) noexcept // Wrapper t } float normalized = total / maxValue; normalized = std::clamp(normalized, 0.0f, 1.0f); - return static_cast(normalized * 255.0f); + return static_cast(normalized * HEIGHT_COEFF); } [[nodiscard]] const int Noise::Perlin2D(int x, int y) noexcept { // Wrapper to unnormalise input and output - float scaledX = static_cast(x) * frequency; - float scaledY = static_cast(y) * frequency; - return floor(ApplyPerlin2DParameters(scaledX, scaledY)); + float scaledX = static_cast(x) * frequency; + float scaledY = static_cast(y) * frequency; + return floor(ApplyPerlin2DParameters(scaledX, scaledY)); } - - [[nodiscard]] const float Noise::grad2D(int hash, float x, float y) noexcept { - int h = hash & 7; // 8 directions - float u = h < 4 ? x : y; - float v = h < 4 ? y : x; + int h = hash & 7; // 8 directions + float u = h < 4 ? x : y; + float v = h < 4 ? y : x; - return ((h & 1) ? -u : u) + ((h & 2) ? -v : v); + return ((h & 1) ? -u : u) + ((h & 2) ? -v : v); } [[nodiscard]] const float Noise::grad(int hash, float x, float y, float z) noexcept { - int h = hash & 15; // 16 directions possibles - float u = h < 8 ? x : y; - float v = h < 4 ? y : (h == 12 || h == 14 ? x : z); - return ((h & 1) ? -u : u) + ((h & 2) ? -v : v); + int h = hash & 15; // 16 directions possibles + float u = h < 8 ? x : y; + float v = h < 4 ? y : (h == 12 || h == 14 ? x : z); + return ((h & 1) ? -u : u) + ((h & 2) ? -v : v); } @@ -139,19 +132,19 @@ const int Noise::ApplyPerlin2DParameters(float x, float y) noexcept // Wrapper t int bbb = perms[perms[perms[xi + 1] + yi + 1] + zi + 1]; float x1, x2, y1, y2; - x1 = lerp(grad(aaa, xf, yf, zf), + x1 = std::lerp(grad(aaa, xf, yf, zf), grad(baa, xf - 1, yf, zf), u); - x2 = lerp(grad(aba, xf, yf - 1, zf), + x2 = std::lerp(grad(aba, xf, yf - 1, zf), grad(bba, xf - 1, yf - 1, zf), u); - y1 = lerp(x1, x2, v); + y1 = std::lerp(x1, x2, v); - x1 = lerp(grad(aab, xf, yf, zf - 1), + x1 = std::lerp(grad(aab, xf, yf, zf - 1), grad(bab, xf - 1, yf, zf - 1), u); - x2 = lerp(grad(abb, xf, yf - 1, zf - 1), + x2 = std::lerp(grad(abb, xf, yf - 1, zf - 1), grad(bbb, xf - 1, yf - 1, zf - 1), u); - y2 = lerp(x1, x2, v); + y2 = std::lerp(x1, x2, v); - return ((lerp(y1, y2, w) + 1.0f) / 2.0f) * amplitude; + return ((std::lerp(y1, y2, w) + 1.0f) / 2.0f) * amplitude; } [[nodiscard]] const int Noise::ApplyPerlin3DParameters(float x, float y, float z) noexcept @@ -161,28 +154,26 @@ const int Noise::ApplyPerlin2DParameters(float x, float y) noexcept // Wrapper t float tmp_amp = amplitude; float maxValue = 0.0f; - for (int i = 0; i < this->octaves; ++i) { - total += Perlin3D(x * tmp_freq, y * tmp_freq, z * tmp_freq) * tmp_amp; - maxValue += tmp_amp; + for(int i = 0; i < this->octaves; ++i) + { + total += Perlin3D(x * tmp_freq, y * tmp_freq, z * tmp_freq) * tmp_amp; + maxValue += tmp_amp; tmp_amp *= persistance; - tmp_freq *= lacunarity; - } + tmp_freq *= lacunarity; + } float normalized = total / maxValue; normalized = std::clamp(normalized, 0.0f, 1.0f); - return static_cast(normalized * 255.0f); + return static_cast(normalized * HEIGHT_COEFF); } - [[nodiscard]] std::array Noise::GetHeight(Scop::Vec2i pos) { std::array data; std::memset(data.data(), static_cast(BlockType::Air), data.size() * sizeof(std::uint32_t)); - //std::uint32_t height = std::abs(std::sin((float)pos.x / 20.0f) * std::cos((float)pos.y / 20.0f) * 60.0f) + 1; std::uint32_t height = Perlin2D(pos.x, pos.y); - // Must not exceed CHUNK_SIZE.y for(std::uint32_t y = 0; y < std::min(height, CHUNK_SIZE.y); y++) { if(y > std::min(height, CHUNK_SIZE.y) - 2) diff --git a/Application/Noise.h b/Application/Noise.h index c4241df..5db264c 100644 --- a/Application/Noise.h +++ b/Application/Noise.h @@ -35,7 +35,6 @@ class Noise [[nodiscard]] const int ApplyPerlin3DParameters(float x, float y, float z) noexcept; [[nodiscard]] const float fade(float t) noexcept; - [[nodiscard]] const float lerp(float a, float b, float t) noexcept; [[nodiscard]] const float grad2D(int hash, float x, float y) noexcept; [[nodiscard]] const float grad(int hash, float x, float y, float z) noexcept; }; diff --git a/Resources/atlas.bmp b/Resources/atlas.bmp index 957a63e..ead6259 100644 Binary files a/Resources/atlas.bmp and b/Resources/atlas.bmp differ