#include "Mesh.h" #include #include #include Mesh::Mesh(ShaderProgram* shader, std::size_t size) : GLObject(shader), _size(size), _xs(size), _ys(size), _normals(2*size*size) { _vertexCount = _size*_size; _indexCount = (_size - 1)*(_size - 1)*6; _vertices = std::make_unique(_vertexCount); _indices = std::make_unique(_indexCount); } Mesh::~Mesh() { } void Mesh::generateVertices() const { for(std::size_t j = 0; j < _size; ++j) { for (std::size_t i = 0; i < _size; ++i) { size_t idx = j*_size + i; _vertices[idx].x = (float)i/_size - 0.5f; _vertices[idx].y = (float)j/_size - 0.5f; _vertices[idx].z = 0.f; _vertices[idx].nx = 0.f; _vertices[idx].ny = 0.f; _vertices[idx].nz = 0.f; } } } inline size_t Mesh::normalIndex(size_t x, size_t y) const { return 2*(x + y*_size); } void Mesh::updateVertices() const { for(std::size_t j = 0; j < _size; ++j) { for(std::size_t i = 0; i < _size; ++i) { std::size_t idx = j*_size + i; _vertices[idx].z = heightMap(i, j); } } // 1. Calc normals for all triangles _normals.clear(); for(std::size_t j = 0; j < _size; ++j) { for(std::size_t i = 0; i < _size; ++i) { float x = _xs[i], x2 = _xs[i + 1]; float y = _ys[j], y2 = _ys[j + 1]; glm::vec3 p1(x, y, _vertices[j*(_size - 1) + i].z); glm::vec3 p2(x2, y, _vertices[j*(_size - 1) + i + 1].z); glm::vec3 p3(x, y2, _vertices[(j + 1)*(_size - 1) + i].z); glm::vec3 p4(x2, y2, _vertices[(j + 1)*(_size - 1) + i + 1].z); glm::vec3 v1 = p1 - p3; glm::vec3 v2 = p2 - p3; glm::vec3 v3 = p4 - p3; glm::vec3 norm1 = glm::cross(v2, v1); glm::vec3 norm2 = glm::cross(v3, v2); _normals.emplace_back(norm1); _normals.emplace_back(norm2); } } // 2. Calc normals for all vertices based on precalculated normals for triangles // Normal of vertex is an average of normals of adjacent triangles for(std::size_t j = 0; j < _size; ++j) { for (std::size_t i = 0; i < _size; ++i) { glm::vec3 normal; size_t idx1 = normalIndex(i - 1, j - 1); for(size_t k = idx1; k < idx1 + 3; ++k) { if(k >= 0) { normal += _normals[k]; } } size_t idx2 = normalIndex(i - 1, j); for(size_t k = idx2; k < idx2 + 3; ++k) { if(k >= 0) { normal += _normals[k]; } } size_t idx = j*(_size - 1) + i; _vertices[idx].nx = normal.x; _vertices[idx].ny = normal.y; _vertices[idx].nz = normal.z; } } } void Mesh::generateIndices() const { GLuint u = (GLuint)_size, v = (GLuint)_size; for (unsigned i = 0; i < (u - 1); i++) for (unsigned j = 0; j < (v - 1); j++) { GLuint indexa = j*(u - 1) + i; GLuint indexb = j*u + i; _indices[indexa*6 + 0] = indexb; _indices[indexa*6 + 1] = indexb + 1 + u; _indices[indexa*6 + 2] = indexb + 1; _indices[indexa*6 + 3] = indexb; _indices[indexa*6 + 4] = indexb + u; _indices[indexa*6 + 5] = indexb + u + 1; } }