diff --git a/include/Model.h b/include/Model.h index 159d1c8..946dd34 100644 --- a/include/Model.h +++ b/include/Model.h @@ -11,6 +11,7 @@ #define DEFAULT_MTL_DIR "./" class GrouptedModel loadOBJtoGroupted(const char* filename, const char* mtl_directory = DEFAULT_MTL_DIR, const char* texture_directory = DEFAULT_MTL_DIR); +void calc_tb(const GLuint* indices, const int indices_count, const glm::vec3* verteces, const glm::vec2* texCords, glm::vec3* tangent, glm::vec3* bitangent); struct Material { diff --git a/src/Model.cpp b/src/Model.cpp index fa22579..8e03e71 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -274,6 +274,47 @@ inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) { hash_combine(seed, rest...); } +// Расчет касательных и бикасательных векторов +void calc_tb(const GLuint* indices, const int indices_count, const glm::vec3* verteces, const glm::vec2* texCords, glm::vec3* tangent, glm::vec3* bitangent) +{ + glm::vec2 dTex1, dTex2; // Разница по текстурным координатам + glm::vec3 dPos1, dPos2; // Разница по координатам вершин + float f; // Разность произведений + glm::vec3 tmp; // Для вычислений вектора + + for (int i = 0; i < indices_count; i+=3) + { + // Разности векторов + dTex1 = texCords[indices[i+1]] - texCords[indices[i]]; + dTex2 = texCords[indices[i+2]] - texCords[indices[i]]; + dPos1 = verteces[indices[i+1]] - verteces[indices[i]]; + dPos2 = verteces[indices[i+2]] - verteces[indices[i]]; + f = dTex1.x * dTex2.y - dTex2.x * dTex1.y; + + // Покомпонентное вычисление касательного вектора + tmp.x = (dTex2.y * dPos1.x - dTex1.y * dPos2.x) / f; + tmp.y = (dTex2.y * dPos1.y - dTex1.y * dPos2.y) / f; + tmp.z = (dTex2.y * dPos1.z - dTex1.y * dPos2.z) / f; + // Нормируем значение + tmp = glm::normalize(tmp); + // Добавим вектор в контейнер + tangent[indices[i ]] = tmp; // Для каждого индекса полигона + tangent[indices[i+1]] = tmp; // значение вектора + tangent[indices[i+2]] = tmp; // одинаковое + + // Покомпонентное вычисление бикасательного вектора + tmp.x = (-dTex2.x * dPos1.x + dTex1.x * dPos2.x) / f; + tmp.y = (-dTex2.x * dPos1.y + dTex1.x * dPos2.y) / f; + tmp.z = (-dTex2.x * dPos1.z + dTex1.x * dPos2.z) / f; + // Нормируем значение + tmp = glm::normalize(tmp); + // Добавим вектор в контейнер + bitangent[indices[i ]] = tmp; // Для каждого индекса полигона + bitangent[indices[i+1]] = tmp; // значение вектора + bitangent[indices[i+2]] = tmp; // одинаковое + } +} + GrouptedModel loadOBJtoGroupted(const char* filename, const char* mtl_directory, const char* texture_directory) { GrouptedModel result; @@ -296,6 +337,7 @@ GrouptedModel loadOBJtoGroupted(const char* filename, const char* mtl_directory, std::vector verteces; // вершины std::vector normals; // нормали std::vector texCords; // текстурные координаты + std::vector tangent, bitangent; // касательный и бикасательный веткоры size_t hash; // Для уникальных вершин std::map uniqueVerteces; // словарь для уникальных вершин: ключ - хеш, значение - индекс вершины @@ -362,10 +404,18 @@ GrouptedModel loadOBJtoGroupted(const char* filename, const char* mtl_directory, + // Изменим размер массивов + tangent.resize(verteces.size()); + bitangent.resize(verteces.size()); + // Расчет касательных и бикасательных векторов + calc_tb(indices.data(), indices.size(), verteces.data(), texCords.data(), tangent.data(), bitangent.data()); + // Загрузка в буферы model.load_verteces (&verteces[0], verteces.size()); model.load_normals (&normals[0], normals.size()); model.load_texCoords(&texCords[0], texCords.size()); + model.load_tangent(&tangent[0], tangent.size()); + model.load_bitangent(&bitangent[0], bitangent.size()); // Загрузка индексного буфера model.load_indices (&indices[0], indices.size());