--- /dev/null
+#ifndef TACOS_WORLD_FLOOR_HPP_
+#define TACOS_WORLD_FLOOR_HPP_
+
+#include <vector>
+#include <GL/glew.h>
+#include <glm/glm.hpp>
+
+
+namespace tacos {
+
+class Floor {
+
+public:
+ /// width and depth in vertices, so will have one less
+ /// in each dimension in tiles
+ Floor(int width, int depth);
+ ~Floor() noexcept;
+
+ Floor(const Floor &) = delete;
+ Floor &operator =(const Floor &) = delete;
+
+ static constexpr int VAO_DIVISOR = 32;
+
+ int Width() const noexcept { return width; }
+ int Depth() const noexcept { return depth; }
+
+ int VAOWidth() const noexcept { return vao_width; }
+ int VAODepth() const noexcept { return vao_depth; }
+
+ glm::vec3 VAOPosition(int vao_x, int vao_z) const noexcept {
+ return glm::vec3(float(vao_x * VAO_DIVISOR), 0.0f, float(vao_z * VAO_DIVISOR));
+ }
+ void DrawVAO(int vao_x, int vao_z) const noexcept;
+
+ void SetElevation(int x, int z, float e) noexcept {
+ elevation[z * width + x] = e;
+ }
+ float GetElevation(int x, int z) const noexcept {
+ return elevation[z * width + x];
+ }
+ float ClampedElevation(int x, int z) const noexcept {
+ return GetElevation(glm::clamp(x, 0, width), glm::clamp(z, 0, depth));
+ }
+ glm::vec3 GetNormal(int x, int z) const noexcept;
+
+ void GenerateVertices();
+
+private:
+ void SetupVAO(int which, GLuint element_buffer, int vertex_count) noexcept;
+ void FillElementBuffer(GLuint which, int tile_width, int tile_depth);
+ void FillAttribBuffer(int vao_x, int vao_z);
+ glm::ivec2 Tiles(int vao_x, int vao_z) const noexcept;
+ int NumTiles(int vao_x, int vao_z) const noexcept;
+ int NumVertices(int vao_x, int vao_z) const noexcept;
+
+private:
+ int width;
+ int depth;
+ std::vector<float> elevation;
+
+ int tile_width;
+ int tile_depth;
+ int unclean_width;
+ int unclean_depth;
+ int vao_width;
+ int vao_depth;
+ std::vector<GLuint> vaos;
+ // index of general element buffer
+ int general_elements;
+ // index of unclean width element buffer, if any
+ int unclean_width_elements;
+ // index of unclean depth element buffer, if any
+ int unclean_depth_elements;
+ // index of unclean corner element buffer, if any
+ int unclean_corner_elements;
+ std::vector<GLuint> buffers;
+
+ struct Attributes {
+ glm::vec3 position;
+ glm::vec3 normal;
+ };
+
+};
+
+}
+
+#endif