X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;ds=sidebyside;f=src%2Fworld%2Fworld.cpp;h=25723ba81c052f21e7fbeda023518817fdb2c42f;hb=2e761a60d1717297b7e308ef1b66e2a81319fdff;hp=eba12eab25ef4c334b329e0b50081c4ca2953ae1;hpb=33346e9a5c58e92e4d7cc7cb542cf5abb7ffeb25;p=tacos.git diff --git a/src/world/world.cpp b/src/world/world.cpp index eba12ea..25723ba 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -1,8 +1,78 @@ +#include "Cursor.hpp" #include "Floor.hpp" namespace tacos { +Cursor::Cursor() +: vao(0) +, buffers{0} +, size(3) +, offset(0.1f) +, mode(HIDDEN) { + glGenVertexArrays(1, &vao); + glGenBuffers(2, buffers); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, 0, sizeof(Attributes), reinterpret_cast(offsetof(Attributes, position))); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); + glBindVertexArray(0); +} + +Cursor::~Cursor() { + glDeleteBuffers(2, buffers); + glDeleteVertexArrays(1, &vao); +} + +void Cursor::Hide() noexcept { + mode = HIDDEN; +} + +void Cursor::FloorTile(const Floor &floor, int tile_x, int tile_z) { + // TODO: only update if changed + mode = FLOOR; + + int x_begin = glm::clamp(tile_x, 0, floor.Width() - size); + int x_end = x_begin + size; + int z_begin = glm::clamp(tile_z, 0, floor.Depth() - size); + int z_end = z_begin + size; + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); + glBufferData(GL_ARRAY_BUFFER, size * size * sizeof(Attributes), nullptr, GL_DYNAMIC_DRAW); + Attributes *attrib = reinterpret_cast(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)); + for (int z = z_begin, index = 0; z < z_end; ++z) { + for (int x = x_begin; x < x_end; ++x, ++index) { + attrib[index].position = glm::vec3(x, floor.GetElevation(x, z) + offset, z); + } + } + glUnmapBuffer(GL_ARRAY_BUFFER); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (size - 1) * (size - 1) * 6, nullptr, GL_DYNAMIC_DRAW); + unsigned char *element = reinterpret_cast(glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY)); + for (int z = 0, index = 0; z < size - 1; ++z) { + for (int x = 0; x < size - 1; ++x, ++index) { + element[index * 6 + 0] = (z + 0) * size + (x + 0); + element[index * 6 + 1] = (z + 0) * size + (x + 1); + element[index * 6 + 2] = (z + 1) * size + (x + 0); + element[index * 6 + 3] = (z + 0) * size + (x + 1); + element[index * 6 + 4] = (z + 1) * size + (x + 1); + element[index * 6 + 5] = (z + 1) * size + (x + 0); + } + } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + glBindVertexArray(0); +} + +void Cursor::Draw() const noexcept { + glBindVertexArray(vao); + glDrawElements(GL_TRIANGLES, (size - 1) * (size - 1) * 6, GL_UNSIGNED_BYTE, nullptr); +} + + constexpr int Floor::VAO_DIVISOR; Floor::Floor(int w, int d) @@ -140,4 +210,21 @@ void Floor::DrawVAO(int vao_x, int vao_z) const noexcept { glDrawElements(GL_TRIANGLES, NumTiles(vao_x, vao_z) * 6, GL_UNSIGNED_SHORT, nullptr); } +bool Floor::Intersection(const Ray &ray, glm::vec3 &point) { + // TODO: this tests for Y=0 plane intersection, change to respect heightmap + if (std::abs(ray.direction.y) < std::numeric_limits::epsilon()) { + // ray parallel to plane + return false; + } + float factor = ray.origin.y / ray.direction.y; + if (factor > 0.0f) { + // intersection "behind" the ray + return false; + } + point.x = ray.origin.x - (ray.direction.x * factor); + point.y = 0.0f; + point.z = ray.origin.z - (ray.direction.z * factor); + return point.x >= 0.0f && point.x <= float(width) && point.z >= 0.0f && point.z <= float(depth); +} + }