From 664d7c6700ccc4f71a2df9a5af4bee5591fb2d20 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 26 Jan 2021 21:17:37 +0000 Subject: Generate some random terrain with a water layer --- game/terrain.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- game/terrain.h | 2 ++ 2 files changed, 68 insertions(+), 5 deletions(-) (limited to 'game') diff --git a/game/terrain.cpp b/game/terrain.cpp index 85a6d32..27fdc1c 100644 --- a/game/terrain.cpp +++ b/game/terrain.cpp @@ -2,32 +2,40 @@ #include "gfx/models/texture.h" #include #include +#include #include #include #include #include #include +#include -constexpr auto size {255}; // Vertices +constexpr auto size {241}; // Vertices +constexpr auto offset {(size - 1) / 2}; constexpr auto verticesCount = size * size; constexpr auto tilesCount = (size - 1) * (size - 1); constexpr auto trianglesCount = tilesCount * 2; constexpr auto indicesCount = trianglesCount * 3; constexpr auto resolution = 10; // Grid size +constexpr auto extent = offset * resolution; Terrain::Terrain() : - m_vertexArrayObject {}, m_vertexArrayBuffers {}, texture {Texture::cachedTexture.get("res/bricks.jpg")} + m_vertexArrayObject {}, m_vertexArrayBuffers {}, texture {Texture::cachedTexture.get("res/terrain.png")} { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + vertices.reserve(verticesCount + 4); vertices.resize(verticesCount, {{}, {}, {}}); - indices.reserve(indicesCount); + indices.reserve(indicesCount + 6); // Initial coordinates for (auto z = 0; z < size; z += 1) { for (auto x = 0; x < size; x += 1) { auto & vertex = vertices[x + (z * size)]; - vertex.pos = {resolution * x, -1, resolution * z}; + vertex.pos = {resolution * (x - offset), -1.5, resolution * (z - offset)}; vertex.normal = {0, 1, 0}; - vertex.texCoord = {x % 2, z % 2}; + vertex.texCoord = {(x % 2) / 2.01, (z % 2) / 2.01}; } } // Indices @@ -41,6 +49,53 @@ Terrain::Terrain() : indices.push_back((x + 1) + ((z + 1) * size)); } } + // Add hills + std::mt19937 gen(std::random_device {}()); + std::uniform_int_distribution<> rpos(2, size - 2); + std::uniform_int_distribution<> rsize(10, 20); + std::uniform_int_distribution<> rheight(1, 3); + for (int h = 0; h < 500;) { + const glm::ivec2 hpos {rpos(gen), rpos(gen)}; + const glm::ivec2 hsize {rsize(gen), rsize(gen)}; + if (const auto lim1 = hpos - hsize; lim1.x > 0 && lim1.y > 0) { + if (const auto lim2 = hpos + hsize; lim2.x < size && lim2.y < size) { + auto height {rheight(gen)}; + const glm::ivec2 hsizesqrd {hsize.x * hsize.x, hsize.y * hsize.y}; + for (auto z = lim1.y; z < lim2.y; z += 1) { + for (auto x = lim1.x; x < lim2.x; x += 1) { + const auto dist {hpos - glm::ivec2 {x, z}}; + const glm::ivec2 distsqrd {dist.x * dist.x, dist.y * dist.y}; + if ((pow(x - hpos.x, 2) / pow(hsize.x, 2)) + (pow(z - hpos.y, 2) / pow(hsize.y, 2)) <= 1.0) { + auto & vertex = vertices[x + (z * size)]; + vertex.pos.y += height; + } + } + } + h += 1; + } + } + } + // Normals + for (auto z = 1; z < size - 1; z += 1) { + for (auto x = 1; x < size - 1; x += 1) { + const auto a = v(x - 1, z).pos; + const auto b = v(x, z - 1).pos; + const auto c = v(x + 1, z).pos; + const auto d = v(x, z + 1).pos; + v(x, z).normal = -glm::normalize(glm::cross(c - a, d - b)); + } + } + // Add water + vertices.emplace_back(glm::vec3 {-extent, 0, -extent}, glm::vec2 {0.5, 0.0}, glm::vec3 {0, 1, 0}); + vertices.emplace_back(glm::vec3 {-extent, 0, extent}, glm::vec2 {0.5, 0.5}, glm::vec3 {0, 1, 0}); + vertices.emplace_back(glm::vec3 {extent, 0, extent}, glm::vec2 {1, 0.5}, glm::vec3 {0, 1, 0}); + vertices.emplace_back(glm::vec3 {extent, 0, -extent}, glm::vec2 {1, 0.0}, glm::vec3 {0, 1, 0}); + indices.push_back(verticesCount); + indices.push_back(verticesCount + 1); + indices.push_back(verticesCount + 2); + indices.push_back(verticesCount); + indices.push_back(verticesCount + 2); + indices.push_back(verticesCount + 3); glGenVertexArrays(1, &m_vertexArrayObject); glBindVertexArray(m_vertexArrayObject); @@ -65,6 +120,12 @@ Terrain::Terrain() : glBindVertexArray(0); } +Vertex & +Terrain::v(unsigned int x, unsigned int z) +{ + return vertices[x + (z * size)]; +} + Terrain::~Terrain() { glDeleteBuffers(NUM_BUFFERS, m_vertexArrayBuffers.data()); diff --git a/game/terrain.h b/game/terrain.h index 4db99c5..c039730 100644 --- a/game/terrain.h +++ b/game/terrain.h @@ -27,6 +27,8 @@ public: private: static constexpr unsigned int NUM_BUFFERS {4}; + Vertex & v(unsigned int, unsigned int); + GLuint m_vertexArrayObject; std::array m_vertexArrayBuffers; std::vector vertices; -- cgit v1.2.3