#include "TextModel.h" #include #include #include #include #include namespace ZL { VertexDataStruct LoadFromTextFile(const std::string& fileName, const std::string& ZIPFileName) { VertexDataStruct result; std::ifstream filestream; std::istringstream zipStream; if (!ZIPFileName.empty()) { std::vector fileData = readFileFromZIP(fileName, ZIPFileName); std::string fileContents(fileData.begin(), fileData.end()); zipStream.str(fileContents); } else { filestream.open(fileName); } // Создаем ссылку f на нужный поток – после этого код ниже остается без изменений std::istream& f = (!ZIPFileName.empty()) ? static_cast(zipStream) : static_cast(filestream); //Skip first 5 lines std::string tempLine; std::getline(f, tempLine); static const std::regex pattern_count(R"(\d+)"); static const std::regex pattern_float(R"([-]?\d+\.\d+)"); static const std::regex pattern_int(R"([-]?\d+)"); std::smatch match; int numberVertices; if (std::regex_search(tempLine, match, pattern_count)) { std::string number_str = match.str(); numberVertices = std::stoi(number_str); } else { throw std::runtime_error("No number found in the input string."); } std::vector vertices; vertices.resize(numberVertices); for (int i = 0; i < numberVertices; i++) { std::getline(f, tempLine); std::vector floatValues; auto b = tempLine.cbegin(); auto e = tempLine.cend(); while (std::regex_search(b, e, match, pattern_float)) { floatValues.push_back(std::stof(match.str())); b = match.suffix().first; } vertices[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] }; } std::cout << "UV Coordinates" << std::endl; std::getline(f, tempLine); //===UV Coordinates: std::getline(f, tempLine); //triangle count int numberTriangles; if (std::regex_search(tempLine, match, pattern_count)) { std::string number_str = match.str(); numberTriangles = std::stoi(number_str); } else { throw std::runtime_error("No number found in the input string."); } // Now process UVs std::vector> uvCoords; uvCoords.resize(numberTriangles); for (int i = 0; i < numberTriangles; i++) { std::getline(f, tempLine); //Face 0 int uvCount; std::getline(f, tempLine); if (std::regex_search(tempLine, match, pattern_count)) { std::string number_str = match.str(); uvCount = std::stoi(number_str); } else { throw std::runtime_error("No number found in the input string."); } if (uvCount != 3) { throw std::runtime_error("more than 3 uvs"); } std::vector floatValues; for (int j = 0; j < 3; j++) { std::getline(f, tempLine); //UV auto b = tempLine.cbegin(); auto e = tempLine.cend(); floatValues.clear(); while (std::regex_search(b, e, match, pattern_float)) { floatValues.push_back(std::stof(match.str())); b = match.suffix().first; } if (floatValues.size() != 2) { throw std::runtime_error("more than 2 uvs---"); } uvCoords[i][j] = Vector2f{ floatValues[0],floatValues[1] }; } } std::cout << "Normals go" << std::endl; std::getline(f, tempLine); //===Normals: std::vector normals; normals.resize(numberVertices); for (int i = 0; i < numberVertices; i++) { std::getline(f, tempLine); std::vector floatValues; auto b = tempLine.cbegin(); auto e = tempLine.cend(); while (std::regex_search(b, e, match, pattern_float)) { floatValues.push_back(std::stof(match.str())); b = match.suffix().first; } normals[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] }; } std::cout << "Triangles go:" << std::endl; std::getline(f, tempLine); //===Triangles: 3974 std::vector> triangles; triangles.resize(numberTriangles); for (int i = 0; i < numberTriangles; i++) { std::getline(f, tempLine); std::vector intValues; auto b = tempLine.cbegin(); auto e = tempLine.cend(); while (std::regex_search(b, e, match, pattern_int)) { intValues.push_back(std::stoi(match.str())); b = match.suffix().first; } triangles[i] = { intValues[0], intValues[1], intValues[2] }; } std::cout << "Process vertices" << std::endl; // Now let's process vertices for (int i = 0; i < numberTriangles; i++) { result.PositionData.push_back(vertices[triangles[i][0]]); result.PositionData.push_back(vertices[triangles[i][1]]); result.PositionData.push_back(vertices[triangles[i][2]]); /* result.NormalData.push_back(normals[triangles[i][0]]); result.NormalData.push_back(normals[triangles[i][1]]); result.NormalData.push_back(normals[triangles[i][2]]); */ result.TexCoordData.push_back(uvCoords[i][0]); result.TexCoordData.push_back(uvCoords[i][1]); result.TexCoordData.push_back(uvCoords[i][2]); } //Swap from Blender format to OpenGL format for (int i = 0; i < result.PositionData.size(); i++) { Vector3f tempVec = result.PositionData[i]; result.PositionData[i].v[0] = tempVec.v[1]; result.PositionData[i].v[1] = tempVec.v[2]; result.PositionData[i].v[2] = tempVec.v[0]; /* tempVec = result.NormalData[i]; result.NormalData[i].v[0] = tempVec.v[1]; result.NormalData[i].v[1] = tempVec.v[2]; result.NormalData[i].v[2] = tempVec.v[0];*/ } return result; } VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName) { VertexDataStruct result; std::ifstream filestream; std::istringstream zipStream; // --- 1. Открытие потока (без изменений) --- if (!ZIPFileName.empty()) { std::vector fileData = readFileFromZIP(fileName, ZIPFileName); std::string fileContents(fileData.begin(), fileData.end()); zipStream.str(fileContents); } else { filestream.open(fileName); if (!filestream.is_open()) { throw std::runtime_error("Failed to open file: " + fileName); } } std::istream& f = (!ZIPFileName.empty()) ? static_cast(zipStream) : static_cast(filestream); std::string tempLine; std::smatch match; // Обновленные регулярки // pattern_float стал чуть надежнее для чисел вида "0" или "-1" без точки, если вдруг Python округлит до int static const std::regex pattern_count(R"(\d+)"); static const std::regex pattern_float(R"([-]?\d+(\.\d+)?)"); static const std::regex pattern_int(R"([-]?\d+)"); // --- 2. Парсинг Вершин (Pos + Norm + UV) --- // Ищем заголовок ===Vertices while (std::getline(f, tempLine)) { if (tempLine.find("===Vertices") != std::string::npos) break; } int numberVertices = 0; if (std::regex_search(tempLine, match, pattern_count)) { numberVertices = std::stoi(match.str()); } else { throw std::runtime_error("Vertices header not found or invalid."); } // Временные буферы для хранения "уникальных" вершин перед разверткой по индексам std::vector tempPositions(numberVertices); std::vector tempNormals(numberVertices); std::vector tempUVs(numberVertices); for (int i = 0; i < numberVertices; i++) { std::getline(f, tempLine); // Строка вида: V 0: Pos(x, y, z) Norm(x, y, z) UV(u, v) std::vector floatValues; floatValues.reserve(8); // Ожидаем ровно 8 чисел (3 pos + 3 norm + 2 uv) auto b = tempLine.cbegin(); auto e = tempLine.cend(); while (std::regex_search(b, e, match, pattern_float)) { floatValues.push_back(std::stof(match.str())); b = match.suffix().first; } // Проверка целостности строки (ID вершины regex может поймать первым, но нас интересуют данные) // Обычно ID идет первым (0), потом 3+3+2 float. Итого 9 чисел, если считать ID. // Ваш Python пишет "V 0:", regex поймает 0. Потом 8 флоатов. // Если regex ловит ID вершины как float (что вероятно), нам нужно смещение. // ID - floatValues[0] // Pos - [1], [2], [3] // Norm - [4], [5], [6] // UV - [7], [8] if (floatValues.size() < 9) { throw std::runtime_error("Malformed vertex line at index " + std::to_string(i)); } tempPositions[i] = Vector3f{ floatValues[1], floatValues[2], floatValues[3] }; tempNormals[i] = Vector3f{ floatValues[4], floatValues[5], floatValues[6] }; tempUVs[i] = Vector2f{ floatValues[7], floatValues[8] }; } // --- 3. Парсинг Треугольников (Индексов) --- // Пропускаем пустые строки до заголовка треугольников while (std::getline(f, tempLine)) { if (tempLine.find("===Triangles") != std::string::npos) break; } int numberTriangles = 0; if (std::regex_search(tempLine, match, pattern_count)) { numberTriangles = std::stoi(match.str()); } else { throw std::runtime_error("Triangles header not found."); } // Резервируем память в result, чтобы избежать лишних аллокаций result.PositionData.reserve(numberTriangles * 3); result.NormalData.reserve(numberTriangles * 3); result.TexCoordData.reserve(numberTriangles * 3); for (int i = 0; i < numberTriangles; i++) { std::getline(f, tempLine); // Строка вида: Tri: 0 1 2 std::vector indices; indices.reserve(3); auto b = tempLine.cbegin(); auto e = tempLine.cend(); while (std::regex_search(b, e, match, pattern_int)) { indices.push_back(std::stoi(match.str())); b = match.suffix().first; } if (indices.size() != 3) { throw std::runtime_error("Malformed triangle line at index " + std::to_string(i)); } // --- 4. Заполнение VertexDataStruct (Flattening) --- // Берем данные из временных буферов по индексам и кладем в итоговый массив for (int k = 0; k < 3; k++) { int idx = indices[k]; result.PositionData.push_back(tempPositions[idx]); result.NormalData.push_back(tempNormals[idx]); result.TexCoordData.push_back(tempUVs[idx]); } } // --- 5. Конвертация координат (Blender -> OpenGL/Engine) --- // Сохраняем вашу логику смены осей: X->Z, Y->X, Z->Y for (size_t i = 0; i < result.PositionData.size(); i++) { Vector3f originalPos = result.PositionData[i]; result.PositionData[i].v[0] = originalPos.v[1]; // New X = Old Y result.PositionData[i].v[1] = originalPos.v[2]; // New Y = Old Z result.PositionData[i].v[2] = originalPos.v[0]; // New Z = Old X Vector3f originalNorm = result.NormalData[i]; result.NormalData[i].v[0] = originalNorm.v[1]; result.NormalData[i].v[1] = originalNorm.v[2]; result.NormalData[i].v[2] = originalNorm.v[0]; } std::cout << "Model loaded: " << numberVertices << " verts, " << numberTriangles << " tris." << std::endl; return result; } }