From e04fcbb9bdae8fe70ed2dce2ad13b7bee6cb7673 Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Fri, 1 May 2026 20:26:50 +0300 Subject: [PATCH] Clean up --- proj-windows/CMakeLists.txt | 4 - src/BoneAnimatedModel.cpp | 1041 ---------------------------------- src/BoneAnimatedModel.h | 103 ---- src/BoneAnimatedModelNew.cpp | 52 +- src/BoneAnimatedModelNew.h | 41 +- src/Game.cpp | 1 - src/Game.h | 1 - src/TextModel.cpp | 213 ------- src/TextModel.h | 1 - src/utils/Perlin.cpp | 73 --- src/utils/Perlin.h | 24 - 11 files changed, 91 insertions(+), 1463 deletions(-) delete mode 100644 src/BoneAnimatedModel.cpp delete mode 100644 src/BoneAnimatedModel.h delete mode 100644 src/utils/Perlin.cpp delete mode 100644 src/utils/Perlin.h diff --git a/proj-windows/CMakeLists.txt b/proj-windows/CMakeLists.txt index ea66beb..0668b01 100644 --- a/proj-windows/CMakeLists.txt +++ b/proj-windows/CMakeLists.txt @@ -32,8 +32,6 @@ add_executable(witcher001 ../src/TextModel.h ../src/AudioPlayerAsync.cpp ../src/AudioPlayerAsync.h - ../src/BoneAnimatedModel.cpp - ../src/BoneAnimatedModel.h ../src/BoneAnimatedModelNew.cpp ../src/BoneAnimatedModelNew.h ../src/render/OpenGlExtensions.cpp @@ -42,8 +40,6 @@ add_executable(witcher001 ../src/utils/Utils.h ../src/SparkEmitter.cpp ../src/SparkEmitter.h - ../src/utils/Perlin.cpp - ../src/utils/Perlin.h ../src/utils/TaskManager.cpp ../src/utils/TaskManager.h ../src/render/FrameBuffer.cpp diff --git a/src/BoneAnimatedModel.cpp b/src/BoneAnimatedModel.cpp deleted file mode 100644 index c404a00..0000000 --- a/src/BoneAnimatedModel.cpp +++ /dev/null @@ -1,1041 +0,0 @@ -#include "BoneAnimatedModel.h" -#include -#include -#include -#include -#include -#include - -namespace ZL -{ -#ifdef EMSCRIPTEN - using std::min; - using std::max; -#endif - - int getIndexByValue(const std::string& name, const std::vector& words) - { - for (int i = 0; i < words.size(); i++) - { - if (words[i] == name) - { - return i; - } - } - - - std::cout << "Bone name not found: " << name << std::endl; - throw std::runtime_error("Bone name not found: " + name); - - return -1; - } - - - void BoneSystem::LoadFromFile(const std::string& fileName, const std::string& ZIPFileName) - { - 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); - } - - std::istream& f = (!ZIPFileName.empty()) ? static_cast(zipStream) : static_cast(filestream); - - //Skip first 5 lines - std::string tempLine; - for (int i = 0; i < 5; i++) - { - std::getline(f, 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+)"); - static const std::regex pattern_boneChildren(R"(\'([^\']+)\')"); - static const std::regex pattern_bone_weight(R"(\'([^\']+)\'.*?([-]?\d+\.\d+))"); - - std::smatch match; - - int numberBones; - - if (std::regex_search(tempLine, match, pattern_count)) { - std::string number_str = match.str(); - numberBones = std::stoi(number_str); - } - else { - throw std::runtime_error("No number found in the input string."); - } - - std::vector bones; - std::vector boneNames; - std::vector boneParentNames; - std::unordered_map> boneChildren; - - bones.resize(numberBones); - boneNames.resize(numberBones); - boneParentNames.resize(numberBones); - - for (int i = 0; i < numberBones; i++) - { - std::getline(f, tempLine); - std::string boneName = tempLine.substr(6); - - boneNames[i] = boneName; - - 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; - } - - bones[i].boneStartWorld = Vector3f{ floatValues[0], floatValues[1], floatValues[2] }; - - - std::getline(f, tempLine); //skip tail - - std::getline(f, tempLine); //len - - if (std::regex_search(tempLine, match, pattern_float)) { - std::string len_str = match.str(); - bones[i].boneLength = std::stof(len_str); - } - else { - throw std::runtime_error("No number found in the input string."); - } - //---------- matrix begin - - std::getline(f, tempLine); - - b = tempLine.cbegin(); - 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; - } - - bones[i].boneMatrixWorld.data()[0] = floatValues[0]; - bones[i].boneMatrixWorld.data()[0 + 1 * 3] = floatValues[1]; - bones[i].boneMatrixWorld.data()[0 + 2 * 3] = floatValues[2]; - - - std::getline(f, tempLine); - - b = tempLine.cbegin(); - 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; - } - - bones[i].boneMatrixWorld.data()[1] = floatValues[0]; - bones[i].boneMatrixWorld.data()[1 + 1 * 3] = floatValues[1]; - bones[i].boneMatrixWorld.data()[1 + 2 * 3] = floatValues[2]; - - - std::getline(f, tempLine); - - b = tempLine.cbegin(); - 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; - } - - bones[i].boneMatrixWorld.data()[2] = floatValues[0]; - bones[i].boneMatrixWorld.data()[2 + 1 * 3] = floatValues[1]; - bones[i].boneMatrixWorld.data()[2 + 2 * 3] = floatValues[2]; - - //----------- matrix end - std::getline(f, tempLine); //parent - - if (tempLine == " Parent: None") - { - bones[i].parent = -1; - } - else - { - std::string boneParent = tempLine.substr(10); - boneParentNames[i] = boneParent; - } - - std::getline(f, tempLine); //children - - b = tempLine.cbegin(); - e = tempLine.cend(); - while (std::regex_search(b, e, match, pattern_boneChildren)) { - - boneChildren[boneName].push_back(match.str(1)); - b = match.suffix().first; - } - - } - - std::cout << "bone names count : " << boneNames.size() << std::endl; - - //Now process all the bones: - for (int i = 0; i < numberBones; i++) - { - std::string boneName = boneNames[i]; - std::string boneParent = boneParentNames[i]; - if (boneParent == "" || boneParent == "None") - { - bones[i].parent = -1; - } - else - { - bones[i].parent = getIndexByValue(boneParent, boneNames); - } - - for (int j = 0; j < boneChildren[boneName].size(); j++) - { - bones[i].children.push_back(getIndexByValue(boneChildren[boneName][j], boneNames)); - } - } - - startBones = bones; - currentBones = bones; - this->boneNames = boneNames; - - std::getline(f, tempLine); //vertice count - 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]}; - } - - - //==== process uv and normals begin - - 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::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] }; - } - - //==== process uv and normals end - - std::getline(f, tempLine); //triangle count. - //numberTriangles; //Need to check if new value is the same as was read before - - 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."); - } - - 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::getline(f, tempLine);//=== Vertex Weights === - std::vector> localVerticesBoneWeight; - localVerticesBoneWeight.resize(numberVertices); - - for (int i = 0; i < numberVertices; i++) - { - std::getline(f, tempLine); //skip Vertex 0: - std::getline(f, tempLine); //vertex group count - int boneCount; - - if (std::regex_search(tempLine, match, pattern_count)) { - std::string number_str = match.str(); - boneCount = std::stoi(number_str); - } - else { - throw std::runtime_error("No number found in the input string."); - } - - if (boneCount > MAX_BONE_COUNT) - { - throw std::runtime_error("more than 5 bones"); - } - - float sumWeights = 0; - - for (int j = 0; j < boneCount; j++) - { - std::getline(f, tempLine); //Group: 'Bone', Weight: 0.9929084181785583 - if (std::regex_search(tempLine, match, pattern_bone_weight)) { - std::string word = match.str(1); - double weight = std::stod(match.str(2)); - //std::cout << "Bone name: " << word << ", weight: " << weight << std::endl; - int boneNumber = getIndexByValue(word, boneNames); - localVerticesBoneWeight[i][j].boneIndex = boneNumber; - localVerticesBoneWeight[i][j].weight = weight; - sumWeights += weight; - } - else { - throw std::runtime_error("No match found in the input string."); - } - } - - //Normalize weights: - for (int j = 0; j < boneCount; j++) - { - localVerticesBoneWeight[i][j].weight = localVerticesBoneWeight[i][j].weight / sumWeights; - } - - } - - std::getline(f, tempLine);//=== Animation Keyframes === - std::getline(f, tempLine);//=== Bone Transforms per Keyframe === - - std::getline(f, tempLine); - int numberKeyFrames; - - if (std::regex_search(tempLine, match, pattern_count)) { - std::string number_str = match.str(); - numberKeyFrames = std::stoi(number_str); - } - else { - throw std::runtime_error("No number found in the input string."); - } - - animations.resize(1); - - animations[0].keyFrames.resize(numberKeyFrames); - - for (int i = 0; i < numberKeyFrames; i++) - { - std::getline(f, tempLine); - int numberFrame; - - if (std::regex_search(tempLine, match, pattern_count)) { - std::string number_str = match.str(); - numberFrame = std::stoi(number_str); - } - else { - throw std::runtime_error("No number found in the input string."); - } - - animations[0].keyFrames[i].frame = numberFrame; - - animations[0].keyFrames[i].bones.resize(numberBones); - - for (int j = 0; j < numberBones; j++) - { - std::getline(f, tempLine); - std::string boneName = tempLine.substr(8); - - int boneNumber = getIndexByValue(boneName, boneNames); - animations[0].keyFrames[i].bones[boneNumber] = startBones[boneNumber]; - - std::getline(f, tempLine); // Location: - - 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; - } - - animations[0].keyFrames[i].bones[boneNumber].boneStartWorld = Vector3f{ floatValues[0], floatValues[1], floatValues[2] }; - - std::getline(f, tempLine); // Rotation - std::getline(f, tempLine); // Matrix - - //=============== Matrix begin ================== - std::getline(f, tempLine); - - - b = tempLine.cbegin(); - 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; - } - - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[0] = floatValues[0]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[0 + 1 * 4] = floatValues[1]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[0 + 2 * 4] = floatValues[2]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[0 + 3 * 4] = floatValues[3]; - - std::getline(f, tempLine); - b = tempLine.cbegin(); - 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; - } - - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[1] = floatValues[0]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[1 + 1 * 4] = floatValues[1]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[1 + 2 * 4] = floatValues[2]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[1 + 3 * 4] = floatValues[3]; - - std::getline(f, tempLine); - b = tempLine.cbegin(); - 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; - } - - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2] = floatValues[0]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 1 * 4] = floatValues[1]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 2 * 4] = floatValues[2]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 3 * 4] = floatValues[3]; - std::getline(f, tempLine); - b = tempLine.cbegin(); - 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; - } - - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[3] = floatValues[0]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[3 + 1 * 4] = floatValues[1]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[3 + 2 * 4] = floatValues[2]; - animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[3 + 3 * 4] = floatValues[3]; - - //=============== Matrix end ================== - - } - - } - - // Now let's process bone weights and vertices - - for (int i = 0; i < numberTriangles; i++) - { - - mesh.PositionData.push_back(vertices[triangles[i][0]]); - mesh.PositionData.push_back(vertices[triangles[i][1]]); - mesh.PositionData.push_back(vertices[triangles[i][2]]); - - verticesBoneWeight.push_back(localVerticesBoneWeight[triangles[i][0]]); - verticesBoneWeight.push_back(localVerticesBoneWeight[triangles[i][1]]); - verticesBoneWeight.push_back(localVerticesBoneWeight[triangles[i][2]]); - - mesh.TexCoordData.push_back(uvCoords[i][0]); - mesh.TexCoordData.push_back(uvCoords[i][1]); - mesh.TexCoordData.push_back(uvCoords[i][2]); - } - - startMesh = mesh; - - - if (startBones.size() > MAX_GPU_BONES) - { - std::cout << "Warning: model has " << startBones.size() - << " bones, exceeding GPU skinning limit of " << MAX_GPU_BONES << std::endl; - //throw std::runtime_error("Too many bones for GPU skinning"); - } - } - - void BoneSystem::LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName) - { - std::vector fileData; - - if (!ZIPFileName.empty()) - { - fileData = readFileFromZIP(fileName, ZIPFileName); - } - else - { - std::ifstream f(fileName, std::ios::binary | std::ios::ate); - if (!f.is_open()) throw std::runtime_error("Failed to open binary file: " + fileName); - std::streamsize fileSize = f.tellg(); - f.seekg(0); - fileData.resize(static_cast(fileSize)); - f.read(fileData.data(), fileSize); - } - - const char* ptr = fileData.data(); - - auto readRaw = [&](void* dst, size_t n) { - std::memcpy(dst, ptr, n); - ptr += n; - }; - auto readUint32 = [&]() -> uint32_t { uint32_t v; readRaw(&v, 4); return v; }; - auto readInt32 = [&]() -> int32_t { int32_t v; readRaw(&v, 4); return v; }; - auto readFloat = [&]() -> float { float v; readRaw(&v, 4); return v; }; - auto readVec3 = [&]() -> Vector3f { return Vector3f{readFloat(), readFloat(), readFloat()}; }; - auto readVec2 = [&]() -> Vector2f { return Vector2f{readFloat(), readFloat()}; }; - - // Header - char magic[4]; - readRaw(magic, 4); - if (std::memcmp(magic, "BSAF", 4) != 0) - throw std::runtime_error("Invalid binary animation file (bad magic)"); - uint32_t version = readUint32(); - if (version != 2) - throw std::runtime_error("Unsupported binary animation file version"); - - // ---- Bones ---- - uint32_t numBones = readUint32(); - std::vector bones(numBones); - - for (uint32_t i = 0; i < numBones; i++) - { - bones[i].boneStartWorld = readVec3(); - bones[i].boneLength = readFloat(); - - // 3x3 matrix (row-major in file). - // Stored with stride-3 into Matrix4f to match the text loader. - float m[9]; - for (int j = 0; j < 9; j++) m[j] = readFloat(); - - bones[i].boneMatrixWorld = Matrix4f::Zero(); - for (int r = 0; r < 3; r++) - for (int c = 0; c < 3; c++) - bones[i].boneMatrixWorld.data()[r + c * 3] = m[r * 3 + c]; - - bones[i].parent = readInt32(); - - uint32_t numChildren = readUint32(); - bones[i].children.resize(numChildren); - for (uint32_t j = 0; j < numChildren; j++) - bones[i].children[j] = readInt32(); - } - - startBones = bones; - currentBones = bones; - - // ---- Bone names ---- - boneNames.resize(numBones); - for (uint32_t i = 0; i < numBones; i++) - { - uint32_t nameLen = readUint32(); - boneNames[i].resize(nameLen); - if (nameLen > 0) readRaw(&boneNames[i][0], nameLen); - } - - // ---- Vertices ---- - uint32_t numVertices = readUint32(); - std::vector vertices(numVertices); - for (uint32_t i = 0; i < numVertices; i++) - vertices[i] = readVec3(); - - // ---- UV Coordinates ---- - uint32_t numFaces = readUint32(); - std::vector> uvCoords(numFaces); - for (uint32_t i = 0; i < numFaces; i++) - for (int j = 0; j < 3; j++) - uvCoords[i][j] = readVec2(); - - // ---- Normals (read but not currently used by mesh) ---- - std::vector normals(numVertices); - for (uint32_t i = 0; i < numVertices; i++) - normals[i] = readVec3(); - - // ---- Triangles ---- - uint32_t numTriangles = readUint32(); - std::vector> triangles(numTriangles); - for (uint32_t i = 0; i < numTriangles; i++) - triangles[i] = { readInt32(), readInt32(), readInt32() }; - - // ---- Vertex Weights ---- - std::vector> localVerticesBoneWeight(numVertices); - for (uint32_t i = 0; i < numVertices; i++) - { - uint32_t numGroups = readUint32(); - float sumWeights = 0; - for (uint32_t j = 0; j < numGroups; j++) - { - int boneIdx = readInt32(); - float weight = readFloat(); - if (j < MAX_BONE_COUNT) - { - localVerticesBoneWeight[i][j].boneIndex = boneIdx; - localVerticesBoneWeight[i][j].weight = weight; - sumWeights += weight; - } - } - // Normalize weights - uint32_t cap = (numGroups < MAX_BONE_COUNT) ? numGroups : MAX_BONE_COUNT; - for (uint32_t j = 0; j < cap; j++) - localVerticesBoneWeight[i][j].weight /= sumWeights; - } - - // ---- Animation Keyframes ---- - uint32_t numKeyframes = readUint32(); - animations.resize(1); - animations[0].keyFrames.resize(numKeyframes); - - for (uint32_t i = 0; i < numKeyframes; i++) - { - animations[0].keyFrames[i].frame = readInt32(); - animations[0].keyFrames[i].bones.resize(numBones); - - for (uint32_t j = 0; j < numBones; j++) - { - animations[0].keyFrames[i].bones[j] = startBones[j]; - animations[0].keyFrames[i].bones[j].boneStartWorld = readVec3(); - - // 4x4 matrix (row-major in file, stored with stride-4 into Matrix4f) - float m[16]; - for (int k = 0; k < 16; k++) m[k] = readFloat(); - - for (int r = 0; r < 4; r++) - for (int c = 0; c < 4; c++) - animations[0].keyFrames[i].bones[j].boneMatrixWorld.data()[r + c * 4] = m[r * 4 + c]; - } - } - - // ---- Build per-triangle mesh (same expansion as text loader) ---- - for (uint32_t i = 0; i < numTriangles; i++) - { - mesh.PositionData.push_back(vertices[triangles[i][0]]); - mesh.PositionData.push_back(vertices[triangles[i][1]]); - mesh.PositionData.push_back(vertices[triangles[i][2]]); - - verticesBoneWeight.push_back(localVerticesBoneWeight[triangles[i][0]]); - verticesBoneWeight.push_back(localVerticesBoneWeight[triangles[i][1]]); - verticesBoneWeight.push_back(localVerticesBoneWeight[triangles[i][2]]); - - mesh.TexCoordData.push_back(uvCoords[i][0]); - mesh.TexCoordData.push_back(uvCoords[i][1]); - mesh.TexCoordData.push_back(uvCoords[i][2]); - } - - startMesh = mesh; - - if (startBones.size() > MAX_GPU_BONES) - { - std::cout << "Warning: model has " << startBones.size() - << " bones, exceeding GPU skinning limit of " << MAX_GPU_BONES << std::endl; - //throw std::runtime_error("Too many bones for GPU skinning"); - } - } - - int BoneSystem::findBoneIndex(const std::string& name) const - { - for (size_t i = 0; i < boneNames.size(); i++) - { - if (boneNames[i] == name) return static_cast(i); - } - return -1; - } - - void GpuBoneData::PrepareGpuSkinningData(const std::vector>& verticesBoneWeight) - { - size_t vertexCount = verticesBoneWeight.size(); - boneIndices0.resize(vertexCount); - boneIndices1.resize(vertexCount); - boneWeights0.resize(vertexCount); - boneWeights1.resize(vertexCount); - - for (size_t i = 0; i < vertexCount; i++) - { - boneIndices0[i] = Vector4f( - static_cast(max(0, verticesBoneWeight[i][0].boneIndex)), - static_cast(max(0, verticesBoneWeight[i][1].boneIndex)), - static_cast(max(0, verticesBoneWeight[i][2].boneIndex)), - static_cast(max(0, verticesBoneWeight[i][3].boneIndex)) - ); - boneIndices1[i] = Vector2f( - static_cast(max(0, verticesBoneWeight[i][4].boneIndex)), - static_cast(max(0, verticesBoneWeight[i][5].boneIndex)) - ); - boneWeights0[i] = Vector4f( - verticesBoneWeight[i][0].weight, - verticesBoneWeight[i][1].weight, - verticesBoneWeight[i][2].weight, - verticesBoneWeight[i][3].weight - ); - boneWeights1[i] = Vector2f( - verticesBoneWeight[i][4].weight, - verticesBoneWeight[i][5].weight - ); - } - - prepared = true; - } - - void BoneSystem::Interpolate(int frame) - { - int startingFrame = -1; - for (int i = 0; i < animations[0].keyFrames.size() - 1; i++) - { - int oldFrame = animations[0].keyFrames[i].frame; - int nextFrame = animations[0].keyFrames[i + 1].frame; - if (frame >= oldFrame && frame < nextFrame) - { - startingFrame = i; - break; - } - } - - if (startingFrame == -1) - { - std::cout << "Exception here: frame number is out of range of keyframes. Frame: " << frame << std::endl; - throw std::runtime_error("Exception here"); - } - - int modifiedFrameNumber = frame - animations[0].keyFrames[startingFrame].frame; - - int diffFrames = animations[0].keyFrames[startingFrame + 1].frame - animations[0].keyFrames[startingFrame].frame; - - float t = (modifiedFrameNumber + 0.f) / diffFrames; - - std::vector& oneFrameBones = animations[0].keyFrames[startingFrame].bones; - std::vector& nextFrameBones = animations[0].keyFrames[startingFrame+1].bones; - - std::vector skinningMatrixForEachBone; - skinningMatrixForEachBone.resize(currentBones.size()); - - - for (int i = 0; i < currentBones.size(); i++) - { - currentBones[i].boneStartWorld(0) = oneFrameBones[i].boneStartWorld(0) + t * (nextFrameBones[i].boneStartWorld(0) - oneFrameBones[i].boneStartWorld(0)); - currentBones[i].boneStartWorld(1) = oneFrameBones[i].boneStartWorld(1) + t * (nextFrameBones[i].boneStartWorld(1) - oneFrameBones[i].boneStartWorld(1)); - currentBones[i].boneStartWorld(2) = oneFrameBones[i].boneStartWorld(2) + t * (nextFrameBones[i].boneStartWorld(2) - oneFrameBones[i].boneStartWorld(2)); - - Matrix3f oneFrameBonesMatrix; - - oneFrameBonesMatrix = oneFrameBones[i].boneMatrixWorld.block<3, 3>(0, 0); - - Matrix3f nextFrameBonesMatrix; - - nextFrameBonesMatrix = nextFrameBones[i].boneMatrixWorld.block<3, 3>(0, 0); - - Eigen::Quaternionf q1 = Eigen::Quaternionf(oneFrameBonesMatrix).normalized(); - Eigen::Quaternionf q2 = Eigen::Quaternionf(nextFrameBonesMatrix).normalized(); - Eigen::Quaternionf q1_norm = q1.normalized(); - Eigen::Quaternionf q2_norm = q2.normalized(); - - Eigen::Quaternionf result = q1_norm.slerp(t, q2_norm); - - Matrix3f boneMatrixWorld3 = result.toRotationMatrix(); - - currentBones[i].boneMatrixWorld = Eigen::Matrix4f::Identity(); - - // Копируем 3x3 матрицу в верхний левый угол - currentBones[i].boneMatrixWorld.block<3, 3>(0, 0) = boneMatrixWorld3; - - // Копируем позицию в последний столбец (первые 3 элемента) - currentBones[i].boneMatrixWorld.block<3, 1>(0, 3) = currentBones[i].boneStartWorld; - - - Matrix4f currentBoneMatrixWorld4 = currentBones[i].boneMatrixWorld; - Matrix4f startBoneMatrixWorld4 = animations[0].keyFrames[0].bones[i].boneMatrixWorld; - - Matrix4f inverstedStartBoneMatrixWorld4 = startBoneMatrixWorld4.inverse(); - - skinningMatrixForEachBone[i] = currentBoneMatrixWorld4 * inverstedStartBoneMatrixWorld4; - - } - - for (int i = 0; i < mesh.PositionData.size(); i++) - { - Vector4f originalPos = { - startMesh.PositionData[i](0), - startMesh.PositionData[i](1), - startMesh.PositionData[i](2), 1.0}; - - Vector4f finalPos = Vector4f{0.f, 0.f, 0.f, 0.f}; - - bool vMoved = false; - - for (int j = 0; j < MAX_BONE_COUNT; j++) - { - if (verticesBoneWeight[i][j].weight != 0) - { - if (verticesBoneWeight[i][j].boneIndex == -1) - { - std::cout << "Exception here: bone index is -1 but weight is > 0" << std::endl; - throw std::runtime_error("Bones loaded incorrectly - bone index is -1 but weight is > 0"); - } - vMoved = true; - finalPos = finalPos + (skinningMatrixForEachBone[verticesBoneWeight[i][j].boneIndex] * originalPos) * verticesBoneWeight[i][j].weight; - - } - } - - if (!vMoved) - { - finalPos = originalPos; - } - - mesh.PositionData[i](0) = finalPos(0); - mesh.PositionData[i](1) = finalPos(1); - mesh.PositionData[i](2) = finalPos(2); - } - - } - - void GpuSkinningShaderData::prepareGpuSkinningVBOs(BoneSystem& model) { - if (gpuSkinningPrepared) - { - return; - } - - gpuBoneData.PrepareGpuSkinningData(model.verticesBoneWeight); - - // Upload bind-pose mesh (static, done once) - bindPoseMutable.AssignFrom(model.startMesh); - - auto& gpu = gpuBoneData; - - boneIndices0VBO = std::make_shared(); - glBindBuffer(GL_ARRAY_BUFFER, boneIndices0VBO->getBuffer()); - glBufferData(GL_ARRAY_BUFFER, gpu.boneIndices0.size() * sizeof(Eigen::Vector4f), - gpu.boneIndices0.data(), GL_STATIC_DRAW); - - boneIndices1VBO = std::make_shared(); - glBindBuffer(GL_ARRAY_BUFFER, boneIndices1VBO->getBuffer()); - glBufferData(GL_ARRAY_BUFFER, gpu.boneIndices1.size() * sizeof(Eigen::Vector2f), - gpu.boneIndices1.data(), GL_STATIC_DRAW); - - boneWeights0VBO = std::make_shared(); - glBindBuffer(GL_ARRAY_BUFFER, boneWeights0VBO->getBuffer()); - glBufferData(GL_ARRAY_BUFFER, gpu.boneWeights0.size() * sizeof(Eigen::Vector4f), - gpu.boneWeights0.data(), GL_STATIC_DRAW); - - boneWeights1VBO = std::make_shared(); - glBindBuffer(GL_ARRAY_BUFFER, boneWeights1VBO->getBuffer()); - glBufferData(GL_ARRAY_BUFFER, gpu.boneWeights1.size() * sizeof(Eigen::Vector2f), - gpu.boneWeights1.data(), GL_STATIC_DRAW); - - gpuSkinningPrepared = true; - } - - void GpuSkinningShaderData::RenderVBO(Renderer& renderer) - { - CheckGlError(__FILE__, __LINE__); - // Bind position and texcoord VBOs - glBindBuffer(GL_ARRAY_BUFFER, bindPoseMutable.positionVBO->getBuffer()); - renderer.VertexAttribPointer3fv("vPosition", 0, NULL); - - CheckGlError(__FILE__, __LINE__); - if (bindPoseMutable.texCoordVBO) { - glBindBuffer(GL_ARRAY_BUFFER, bindPoseMutable.texCoordVBO->getBuffer()); - renderer.VertexAttribPointer2fv("vTexCoord", 0, NULL); - CheckGlError(__FILE__, __LINE__); - } - - CheckGlError(__FILE__, __LINE__); - if (bindPoseMutable.normalVBO) { - glBindBuffer(GL_ARRAY_BUFFER, bindPoseMutable.normalVBO->getBuffer()); - renderer.VertexAttribPointer3fv("vNormal", 0, NULL); - CheckGlError(__FILE__, __LINE__); - } else { - renderer.DisableVertexAttribArray("vNormal"); - CheckGlError(__FILE__, __LINE__); - } - - CheckGlError(__FILE__, __LINE__); - // Bind bone index VBOs - glBindBuffer(GL_ARRAY_BUFFER, boneIndices0VBO->getBuffer()); - renderer.VertexAttribPointer4fv("aBoneIndices0", 0, NULL); - - CheckGlError(__FILE__, __LINE__); - - glBindBuffer(GL_ARRAY_BUFFER, boneIndices1VBO->getBuffer()); - renderer.VertexAttribPointer2fv("aBoneIndices1", 0, NULL); - - CheckGlError(__FILE__, __LINE__); - - // Bind bone weight VBOs - glBindBuffer(GL_ARRAY_BUFFER, boneWeights0VBO->getBuffer()); - renderer.VertexAttribPointer4fv("aBoneWeights0", 0, NULL); - - CheckGlError(__FILE__, __LINE__); - - glBindBuffer(GL_ARRAY_BUFFER, boneWeights1VBO->getBuffer()); - renderer.VertexAttribPointer2fv("aBoneWeights1", 0, NULL); - - CheckGlError(__FILE__, __LINE__); - - glDrawArrays(GL_TRIANGLES, 0, static_cast(bindPoseMutable.data.PositionData.size())); - - } - - void GpuSkinningShaderData::ComputeSkinningMatrices(const std::vector& startBones, const std::vector& keyFrames, int frame) - { - int startingKeyFrame = -1; - for (size_t i = 0; i < keyFrames.size() - 1; i++) - { - int oldFrame = keyFrames[i].frame; - int nextFrame = keyFrames[i + 1].frame; - if (frame >= oldFrame && frame < nextFrame) - { - startingKeyFrame = static_cast(i); - break; - } - } - - skinningMatrices.resize(startBones.size()); - - if (startingKeyFrame == -1) - { - for (auto& m : skinningMatrices) m = Matrix4f::Identity(); - return; - } - - int modifiedFrameNumber = frame - keyFrames[startingKeyFrame].frame; - int diffFrames = keyFrames[startingKeyFrame + 1].frame - keyFrames[startingKeyFrame].frame; - float t = (modifiedFrameNumber + 0.f) / diffFrames; - - const std::vector& oneFrameBones = keyFrames[startingKeyFrame].bones; - const std::vector& nextFrameBones = keyFrames[startingKeyFrame + 1].bones; - - for (size_t i = 0; i < startBones.size(); i++) - { - Vector3f interpPos; - interpPos(0) = oneFrameBones[i].boneStartWorld(0) + t * (nextFrameBones[i].boneStartWorld(0) - oneFrameBones[i].boneStartWorld(0)); - interpPos(1) = oneFrameBones[i].boneStartWorld(1) + t * (nextFrameBones[i].boneStartWorld(1) - oneFrameBones[i].boneStartWorld(1)); - interpPos(2) = oneFrameBones[i].boneStartWorld(2) + t * (nextFrameBones[i].boneStartWorld(2) - oneFrameBones[i].boneStartWorld(2)); - - Matrix3f oneFrameBonesMatrix = oneFrameBones[i].boneMatrixWorld.block<3, 3>(0, 0); - Matrix3f nextFrameBonesMatrix = nextFrameBones[i].boneMatrixWorld.block<3, 3>(0, 0); - - Eigen::Quaternionf q1 = Eigen::Quaternionf(oneFrameBonesMatrix).normalized(); - Eigen::Quaternionf q2 = Eigen::Quaternionf(nextFrameBonesMatrix).normalized(); - Eigen::Quaternionf result = q1.slerp(t, q2); - - Matrix3f boneMatrixWorld3 = result.toRotationMatrix(); - - Matrix4f currentBoneMatrixWorld4 = Eigen::Matrix4f::Identity(); - currentBoneMatrixWorld4.block<3, 3>(0, 0) = boneMatrixWorld3; - currentBoneMatrixWorld4.block<3, 1>(0, 3) = interpPos; - - Matrix4f startBoneMatrixWorld4 = keyFrames[0].bones[i].boneMatrixWorld; - Matrix4f invertedStartBoneMatrixWorld4 = startBoneMatrixWorld4.inverse(); - - skinningMatrices[i] = currentBoneMatrixWorld4 * invertedStartBoneMatrixWorld4; - } - } - - -} \ No newline at end of file diff --git a/src/BoneAnimatedModel.h b/src/BoneAnimatedModel.h deleted file mode 100644 index e821581..0000000 --- a/src/BoneAnimatedModel.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once -#include "render/Renderer.h" -#include - - -namespace ZL -{ - constexpr int MAX_BONE_COUNT = 6; - constexpr int MAX_GPU_BONES = 64; - struct Bone - { - Vector3f boneStartWorld; - float boneLength; - Matrix4f boneMatrixWorld; - - int parent; - std::vector children; - }; - - struct BoneWeight - { - int boneIndex = -1; - float weight = 0; - }; - - struct AnimationKeyFrame - { - int frame; - std::vector bones; - }; - - struct Animation - { - std::vector keyFrames; - }; - - struct GpuBoneData { - std::vector boneIndices0; // bone indices 0-3 per vertex (as float) - std::vector boneIndices1; // bone indices 4-5 per vertex - std::vector boneWeights0; // bone weights 0-3 per vertex - std::vector boneWeights1; // bone weights 4-5 per vertex - bool prepared = false; - void PrepareGpuSkinningData(const std::vector>& verticesBoneWeight); - }; - - struct BoneSystem - { - VertexDataStruct mesh; - VertexDataStruct startMesh; - std::vector> verticesBoneWeight; - - Matrix4f armatureMatrix; - - std::vector startBones; - std::vector currentBones; - std::vector boneNames; - - std::vector animations; - int startingFrame = 0; - - void LoadFromFile(const std::string& fileName, const std::string& ZIPFileName = ""); - void LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName = ""); - - void Interpolate(int frame); - - int findBoneIndex(const std::string& name) const; - - // GPU skinning: compute skinning matrices without modifying the mesh - //void ComputeSkinningMatrices(int frame, std::vector& outMatrices) const; - }; - - - struct GpuSkinningShaderData { - GpuBoneData gpuBoneData; - - // GPU skinning data (lazily initialized) - VertexRenderStruct bindPoseMutable; - std::shared_ptr boneIndices0VBO; - std::shared_ptr boneIndices1VBO; - std::shared_ptr boneWeights0VBO; - std::shared_ptr boneWeights1VBO; - bool gpuSkinningPrepared = false; - std::vector skinningMatrices; - - void prepareGpuSkinningVBOs(BoneSystem& model); - void RenderVBO(Renderer& renderer); - void ComputeSkinningMatrices(const std::vector& startBones, const std::vector& keyFrames, int frame); - }; - - struct BoneAnimationData { - BoneSystem model; - float currentFrame = 0.f; - int lastFrame = -1; - int totalFrames = 1; - - GpuSkinningShaderData gpuSkinningShaderData; - }; - - - - - -}; \ No newline at end of file diff --git a/src/BoneAnimatedModelNew.cpp b/src/BoneAnimatedModelNew.cpp index d833d9a..ef7709c 100644 --- a/src/BoneAnimatedModelNew.cpp +++ b/src/BoneAnimatedModelNew.cpp @@ -13,7 +13,21 @@ namespace ZL using std::max; #endif - extern int getIndexByValue(const std::string& name, const std::vector& words); + int getIndexByValue(const std::string& name, const std::vector& words) + { + for (int i = 0; i < words.size(); i++) + { + if (words[i] == name) + { + return i; + } + } + + std::cout << "Bone name not found: " << name << std::endl; + throw std::runtime_error("Bone name not found: " + name); + + return -1; + } static std::string trimRight(const std::string& s) { @@ -23,6 +37,42 @@ namespace ZL return s.substr(0, end); } + + void GpuBoneData::PrepareGpuSkinningData(const std::vector>& verticesBoneWeight) + { + size_t vertexCount = verticesBoneWeight.size(); + boneIndices0.resize(vertexCount); + boneIndices1.resize(vertexCount); + boneWeights0.resize(vertexCount); + boneWeights1.resize(vertexCount); + + for (size_t i = 0; i < vertexCount; i++) + { + boneIndices0[i] = Vector4f( + static_cast(max(0, verticesBoneWeight[i][0].boneIndex)), + static_cast(max(0, verticesBoneWeight[i][1].boneIndex)), + static_cast(max(0, verticesBoneWeight[i][2].boneIndex)), + static_cast(max(0, verticesBoneWeight[i][3].boneIndex)) + ); + boneIndices1[i] = Vector2f( + static_cast(max(0, verticesBoneWeight[i][4].boneIndex)), + static_cast(max(0, verticesBoneWeight[i][5].boneIndex)) + ); + boneWeights0[i] = Vector4f( + verticesBoneWeight[i][0].weight, + verticesBoneWeight[i][1].weight, + verticesBoneWeight[i][2].weight, + verticesBoneWeight[i][3].weight + ); + boneWeights1[i] = Vector2f( + verticesBoneWeight[i][4].weight, + verticesBoneWeight[i][5].weight + ); + } + + prepared = true; + } + void BoneSystemNew::LoadFromFile(const std::string& fileName, const std::string& ZIPFileName) { std::ifstream filestream; diff --git a/src/BoneAnimatedModelNew.h b/src/BoneAnimatedModelNew.h index 39de9d2..fb02635 100644 --- a/src/BoneAnimatedModelNew.h +++ b/src/BoneAnimatedModelNew.h @@ -1,9 +1,48 @@ #pragma once -#include "BoneAnimatedModel.h" +#include "render/Renderer.h" #include + namespace ZL { + constexpr int MAX_BONE_COUNT = 6; + constexpr int MAX_GPU_BONES = 64; + struct Bone + { + Eigen::Vector3f boneStartWorld; + float boneLength; + Eigen::Matrix4f boneMatrixWorld; + + int parent; + std::vector children; + }; + + struct BoneWeight + { + int boneIndex = -1; + float weight = 0; + }; + + struct AnimationKeyFrame + { + int frame; + std::vector bones; + }; + + struct Animation + { + std::vector keyFrames; + }; + + struct GpuBoneData { + std::vector boneIndices0; // bone indices 0-3 per vertex (as float) + std::vector boneIndices1; // bone indices 4-5 per vertex + std::vector boneWeights0; // bone weights 0-3 per vertex + std::vector boneWeights1; // bone weights 4-5 per vertex + bool prepared = false; + void PrepareGpuSkinningData(const std::vector>& verticesBoneWeight); + }; + struct MeshBoneData { VertexDataStruct mesh; diff --git a/src/Game.cpp b/src/Game.cpp index d0cd6a2..47cddd8 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1,6 +1,5 @@ #include "Game.h" #include "AnimatedModel.h" -#include "BoneAnimatedModel.h" #include "utils/Utils.h" #include "render/OpenGlExtensions.h" #include diff --git a/src/Game.h b/src/Game.h index 81dac78..cbde596 100644 --- a/src/Game.h +++ b/src/Game.h @@ -1,6 +1,5 @@ #pragma once #include "Character.h" -#include "BoneAnimatedModel.h" #include "render/Renderer.h" #include "Environment.h" #include "render/TextureManager.h" diff --git a/src/TextModel.cpp b/src/TextModel.cpp index 079a220..eb9becd 100644 --- a/src/TextModel.cpp +++ b/src/TextModel.cpp @@ -10,219 +10,6 @@ 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 { - std::cout << "No number found in the input string: " << tempLine << std::endl; - 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 { - std::cout << "-No number found in the input string: " << tempLine << std::endl; - 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 { - std::cout << "2 No number found in the input string: " << tempLine << std::endl; - throw std::runtime_error("2 No number found in the input string."); - } - - if (uvCount != 3) - { - std::cout << "UV count is not 3 for triangle " << i << ": " << uvCount << std::endl; - 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) - { - std::cout << "UV count is not 2: " << j << " " << floatValues.size() << std::endl; - 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.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](0) = tempVec(1); - result.PositionData[i](1) = tempVec(2); - result.PositionData[i](2) = tempVec(0); - - } - - return result; - - } - VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName) { VertexDataStruct result; diff --git a/src/TextModel.h b/src/TextModel.h index d72002e..41b88d0 100644 --- a/src/TextModel.h +++ b/src/TextModel.h @@ -6,6 +6,5 @@ namespace ZL { - VertexDataStruct LoadFromTextFile(const std::string& fileName, const std::string& ZIPFileName = ""); VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName = ""); } \ No newline at end of file diff --git a/src/utils/Perlin.cpp b/src/utils/Perlin.cpp deleted file mode 100644 index e986aa9..0000000 --- a/src/utils/Perlin.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "Perlin.h" -#include -#include -#include -#include - -namespace ZL { - - PerlinNoise::PerlinNoise() { - p.resize(256); - std::iota(p.begin(), p.end(), 0); - // Перемешиваем для случайности (можно задать seed) - std::default_random_engine engine(77777); - std::shuffle(p.begin(), p.end(), engine); - p.insert(p.end(), p.begin(), p.end()); // Дублируем для переполнения - } - - PerlinNoise::PerlinNoise(uint64_t seed) { - p.resize(256); - std::iota(p.begin(), p.end(), 0); - // Перемешиваем для случайности (используем переданный seed) - std::default_random_engine engine(static_cast(seed)); - std::shuffle(p.begin(), p.end(), engine); - p.insert(p.end(), p.begin(), p.end()); // Дублируем для переполнения - } - - float PerlinNoise::fade(float t) { return t * t * t * (t * (t * 6 - 15) + 10); } - - float PerlinNoise::lerp(float t, float a, float b) { return a + t * (b - a); } - - float PerlinNoise::grad(int hash, float x, float y, float z) { - int h = hash & 15; - float u = h < 8 ? x : y; - float v = h < 4 ? y : (h == 12 || h == 14 ? x : z); - return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); - } - - float PerlinNoise::noise(float x, float y, float z) { - int X = (int)floor(x) & 255; - int Y = (int)floor(y) & 255; - int Z = (int)floor(z) & 255; - - x -= floor(x); - y -= floor(y); - z -= floor(z); - - float u = fade(x); - float v = fade(y); - float w = fade(z); - - int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z; - int B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z; - - return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z)), - lerp(u, grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z))), - lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1), grad(p[BA + 1], x - 1, y, z - 1)), - lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1)))); - } - - float PerlinNoise::getSurfaceHeight(Eigen::Vector3f pos, float noiseCoeff) { - // Частота шума (чем больше, тем больше "холмов") - float frequency = 7.0f; - - // Получаем значение шума (обычно от -1 до 1) - float noiseValue = noise(pos(0) * frequency, pos(1) * frequency, pos(2) * frequency); - - // Масштабируем: хотим отклонение от 1.0 до 1.1 (примерно) - float height = 1.0f + (noiseValue * noiseCoeff); - - return height; - } - -} // namespace ZL \ No newline at end of file diff --git a/src/utils/Perlin.h b/src/utils/Perlin.h deleted file mode 100644 index 4135c6f..0000000 --- a/src/utils/Perlin.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace ZL { - - class PerlinNoise { - std::vector p; - public: - PerlinNoise(); - PerlinNoise(uint64_t seed); - - float fade(float t); - float lerp(float t, float a, float b); - float grad(int hash, float x, float y, float z); - - float noise(float x, float y, float z); - - float getSurfaceHeight(Eigen::Vector3f pos, float noiseCoeff); - }; - -} // namespace ZL \ No newline at end of file