]> git.localhorst.tv Git - tacos.git/blobdiff - src/world/world.cpp
mouse cursor mockup
[tacos.git] / src / world / world.cpp
index eba12eab25ef4c334b329e0b50081c4ca2953ae1..25723ba81c052f21e7fbeda023518817fdb2c42f 100644 (file)
@@ -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<const void *>(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<Attributes *>(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<unsigned char *>(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<float>::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);
+}
+
 }