From: Daniel Karbach Date: Sun, 8 Mar 2015 15:49:52 +0000 (+0100) Subject: first attempt at world generation X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=f62562b0f87d571bd7b32ae2f8ca659c24e9911b;p=blank.git first attempt at world generation --- diff --git a/src/noise.cpp b/src/noise.cpp new file mode 100644 index 0000000..d192b27 --- /dev/null +++ b/src/noise.cpp @@ -0,0 +1,105 @@ +#include "noise.hpp" + +#include + + +namespace blank { + + +SimplexNoise::SimplexNoise(unsigned int seed) +: grad({ + { 1.0f, 1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f }, + { 1.0f, -1.0f, 0.0f }, + { -1.0f, -1.0f, 0.0f }, + { 1.0f, 0.0f, 1.0f }, + { -1.0f, 0.0f, 1.0f }, + { 1.0f, 0.0f, -1.0f }, + { -1.0f, 0.0f, -1.0f }, + { 0.0f, 1.0f, 1.0f }, + { 0.0f, -1.0f, 1.0f }, + { 0.0f, 1.0f, -1.0f }, + { 0.0f, -1.0f, -1.0f }, +}) { + unsigned int val = seed; + for (size_t i = 0; i < 256; ++i) { + val = 2346765 * val + 6446345; + perm[i] = val % 256; + } +} + + +float SimplexNoise::operator ()(const glm::vec3 &in) const { + float skew = (in.x + in.y + in.z) / 3.0f; + + glm::vec3 skewed(std::floor(in.x + skew), std::floor(in.y + skew), std::floor(in.z + skew)); + float tr = (skewed.x + skewed.y + skewed.z) / 6.0f; + + glm::vec3 unskewed(skewed.x - tr, skewed.y - tr, skewed.z - tr); + glm::vec3 offset[4]; + offset[0] = in - unskewed; + + glm::vec3 second, third; + + if (offset[0].x >= offset[0].y) { + if (offset[0].y >= offset[0].z) { + second = { 1.0f, 0.0f, 0.0f }; + third = { 1.0f, 1.0f, 0.0f }; + } else if (offset[0].x >= offset[0].z) { + second = { 1.0f, 0.0f, 0.0f }; + third = { 1.0f, 0.0f, 1.0f }; + } else { + second = { 0.0f, 0.0f, 1.0f }; + third = { 1.0f, 0.0f, 1.0f }; + } + } else if (offset[0].y < offset[0].z) { + second = { 0.0f, 0.0f, 1.0f }; + third = { 0.0f, 1.0f, 1.0f }; + } else if (offset[0].x < offset[0].z) { + second = { 0.0f, 1.0f, 0.0f }; + third = { 0.0f, 1.0f, 1.0f }; + } else { + second = { 0.0f, 1.0f, 0.0f }; + third = { 1.0f, 1.0f, 0.0f }; + } + + offset[1] = offset[0] - second + glm::vec3(1.0f/6.0f); + offset[2] = offset[0] - third + glm::vec3(1.0f/3.0f); + offset[3] = offset[0] - glm::vec3(0.5f); + + size_t index[3] = { + unsigned(skewed.x) % 256, + unsigned(skewed.y) % 256, + unsigned(skewed.z) % 256, + }; + size_t corner[4] = { + Perm(index[0] + Perm(index[1] + Perm(index[2]))), + Perm(index[0] + second.x + Perm(index[1] + second.y + Perm(index[2] + second.z))), + Perm(index[0] + third.x + Perm(index[1] + third.y + Perm(index[2] + third.z))), + Perm(index[0] + 1 + Perm(index[1] + 1 + Perm(index[2] + 1))), + }; + float n[4]; + float t[4]; + for (size_t i = 0; i < 4; ++i) { + t[i] = 0.6f - dot(offset[i], offset[i]); + if (t[i] < 0.0f) { + n[i] = 0.0f; + } else { + t[i] *= t[i]; + n[i] = t[i] * t[i] * dot(Grad(corner[i]), offset[i]); + } + } + + return 32.0f * (n[0] + n[1] + n[2] + n[3]); +} + + +unsigned char SimplexNoise::Perm(size_t idx) const { + return perm[idx % 256]; +} + +const glm::vec3 &SimplexNoise::Grad(size_t idx) const { + return grad[idx % 12]; +} + +} diff --git a/src/noise.hpp b/src/noise.hpp new file mode 100644 index 0000000..30bf527 --- /dev/null +++ b/src/noise.hpp @@ -0,0 +1,29 @@ +#ifndef BLANK_NOISE_HPP_ +#define BLANK_NOISE_HPP_ + +#include + + +namespace blank { + +/// (3D only) adaptation of Stefan Gustavson's SimplexNoise java class +class SimplexNoise { + +public: + explicit SimplexNoise(unsigned int seed); + + float operator ()(const glm::vec3 &) const; + +private: + unsigned char Perm(size_t idx) const; + const glm::vec3 &Grad(size_t idx) const; + +private: + unsigned char perm[256]; + glm::vec3 grad[12]; + +}; + +} + +#endif diff --git a/src/world.cpp b/src/world.cpp index aa65bef..57583e6 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -164,6 +164,8 @@ World::World() , blockShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}) , stairShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}, { 0.0f, 0.0f }) , slabShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.0f, 0.5f }}) +, blockNoise(0) +, colorNoise(1) , chunks() { blockType.Add(BlockType{ true, { 1.0f, 1.0f, 1.0f }, &blockShape }); // white block blockType.Add(BlockType{ true, { 1.0f, 1.0f, 1.0f }, &stairShape }); // white stair @@ -181,9 +183,9 @@ World::World() void World::Generate() { - for (int z = -1; z < 2; ++z) { - for (int y = -1; y < 2; ++y) { - for (int x = -1; x < 2; ++x) { + for (int z = -2; z < 3; ++z) { + for (int y = -2; y < 3; ++y) { + for (int x = -2; x < 3; ++x) { Generate(glm::vec3(x, y, z)); } } @@ -194,28 +196,26 @@ Chunk &World::Generate(const glm::vec3 &pos) { chunks.emplace_back(); Chunk &chunk = chunks.back(); chunk.Position(pos); - for (size_t i = 1; i < blockType.Size(); ++i) { - chunk.BlockAt(i) = Block(blockType[i]); - chunk.BlockAt(i + 257) = Block(blockType[i]); - chunk.BlockAt(i + 514) = Block(blockType[i]); - } - if (false) { - chunk.BlockAt(glm::vec3(0, 0, 0)) = Block(blockType[4]); - chunk.BlockAt(glm::vec3(0, 0, 1)) = Block(blockType[1]); - chunk.BlockAt(glm::vec3(1, 0, 0)) = Block(blockType[5]); - chunk.BlockAt(glm::vec3(1, 0, 1)) = Block(blockType[3]); - chunk.BlockAt(glm::vec3(2, 0, 0)) = Block(blockType[4]); - chunk.BlockAt(glm::vec3(2, 0, 1)) = Block(blockType[1]); - chunk.BlockAt(glm::vec3(3, 0, 0)) = Block(blockType[2]); - chunk.BlockAt(glm::vec3(3, 0, 1)) = Block(blockType[5]); - chunk.BlockAt(glm::vec3(2, 0, 2)) = Block(blockType[4]); - chunk.BlockAt(glm::vec3(2, 0, 3)) = Block(blockType[1]); - chunk.BlockAt(glm::vec3(3, 0, 2)) = Block(blockType[2]); - chunk.BlockAt(glm::vec3(3, 0, 3)) = Block(blockType[5]); - chunk.BlockAt(glm::vec3(1, 1, 0)) = Block(blockType[5]); - chunk.BlockAt(glm::vec3(1, 1, 1)) = Block(blockType[4]); - chunk.BlockAt(glm::vec3(2, 1, 1)) = Block(blockType[3]); - chunk.BlockAt(glm::vec3(2, 2, 1)) = Block(blockType[2]); + if (pos.x == 0 && pos.y == 0 && pos.z == 0) { + for (size_t i = 1; i < blockType.Size(); ++i) { + chunk.BlockAt(i) = Block(blockType[i]); + chunk.BlockAt(i + 257) = Block(blockType[i]); + chunk.BlockAt(i + 514) = Block(blockType[i]); + } + } else { + for (int z = 0; z < Chunk::Depth(); ++z) { + for (int y = 0; y < Chunk::Height(); ++y) { + for (int x = 0; x < Chunk::Width(); ++x) { + glm::vec3 block_pos{float(x), float(y), float(z)}; + glm::vec3 gen_pos = (pos * Chunk::Extent() + block_pos) / 64.0f; + float val = blockNoise(gen_pos); + if (val > 0.8f) { + int col_val = int((colorNoise(gen_pos) + 1.0f) * 2.0f) % 4; + chunk.BlockAt(block_pos) = Block(blockType[col_val * 3 + 1]); + } + } + } + } } chunk.Invalidate(); return chunk; diff --git a/src/world.hpp b/src/world.hpp index ebdfdf4..ce44c7c 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -3,6 +3,7 @@ #include "geometry.hpp" #include "model.hpp" +#include "noise.hpp" #include "shape.hpp" #include @@ -189,6 +190,9 @@ private: StairShape stairShape; CuboidShape slabShape; + SimplexNoise blockNoise; + SimplexNoise colorNoise; + std::list chunks; };