Чому деякі мої трикутники повернуті неправильно в LoadWater? bool World::LoadWater(const std::string& filepath)
{
    std::vector<std::string> waterData = readWaterDatFile(filepath);

    if (waterData.empty()) {
        std::cerr << "Failed to read water data or file is empty." << std::endl;
        return false;
    }

    std::cout << "Read " << waterData.size() << " lines from " << filepath << std::endl;

    std::vector<glm::vec3> vertices;
    std::vector<unsigned int> indices;
    const float EPSILON = 0.0001f; // Threshold for considering vertices as the same

    for (const auto& line : waterData) {
        if (line == "processed" || line.empty() || line[0] == '#') {
            continue;  // Skip processed, empty, or comment lines
        }

        std::istringstream iss(line);
        std::vector<float> values;
        float value;
        while (iss >> value) {
            values.push_back(value);
        }

        if (values.size() != 29) {  // 28 floats + 1 int
            std::cerr << "Invalid data line: " << line << std::endl;
            continue;
        }

        // Extract the four corners of the water quad
        std::array<glm::vec3, 4> corners;
        for (int i = 0; i < 4; ++i) {
            corners[i] = glm::vec3(values[i * 7], values[i * 7 + 1], values[i * 7 + 2]);
        }

        // Add vertices and merge if close enough
        std::array<unsigned int, 4> cornerIndices;
        for (int i = 0; i < 4; ++i) {
            bool merged = false;
            for (size_t j = 0; j < vertices.size(); ++j) {
                if (glm::distance(corners[i], vertices[j]) < EPSILON) {
                    cornerIndices[i] = j;
                    merged = true;
                    break;
                }
            }
            if (!merged) {
                vertices.push_back(corners[i]);
                cornerIndices[i] = vertices.size() - 1;
            }
        }

        // Add two triangles to form a quad
        indices.push_back(cornerIndices[0]);
        indices.push_back(cornerIndices[1]);
        indices.push_back(cornerIndices[2]);
        indices.push_back(cornerIndices[2]);
        indices.push_back(cornerIndices[1]);
        indices.push_back(cornerIndices[3]);
    }

    // Add merged vertices to the mesh
    for (const auto& vertex : vertices) {
        m_WaterWorldMesh.addVertex(vertex.x, vertex.y, vertex.z);
    }

    // Add triangles to the mesh
    for (size_t i = 0; i < indices.size(); i += 3) {
        m_WaterWorldMesh.addTriangle(indices[i], indices[i+1], indices[i+2]);
    }

    if (vertices.empty()) {
        std::cerr << "No valid water data found in the file." << std::endl;
        return false;
    }

    return true;
}. Ось приклад створення світу, де все правильно: 	for (const auto& placement : modelPlacements)
	{
		auto meshIt = meshesObjs.find(placement.ModelID);
		if (meshIt == meshesObjs.end()) continue;

		const auto& meshobj = meshIt->second;
		const glm::vec3& translation = placement.Position;
		const glm::mat4 rotationMatrix = glm::mat4_cast(placement.Rotation);

		auto applyTransform = [&](const glm::vec3& vertex) -> glm::vec3 {
			return glm::vec3(rotationMatrix * glm::vec4(vertex, 1.0f)) + translation;
		};

		for (const auto& box : meshobj.boxes) {
			glm::vec3 corners[8] = {
				{box.min.x, box.min.y, box.min.z},
				{box.max.x, box.min.y, box.min.z},
				{box.min.x, box.max.y, box.min.z},
				{box.max.x, box.max.y, box.min.z},
				{box.min.x, box.min.y, box.max.z},
				{box.max.x, box.min.y, box.max.z},
				{box.min.x, box.max.y, box.max.z},
				{box.max.x, box.max.y, box.max.z}
			};

			int v0 = m_StaticWorldMesh.getVertCount();
			for (int i = 0; i < 8; ++i) {
				glm::vec3 transformed = applyTransform(corners[i]);
				if (glm::any(glm::isnan(transformed)) || glm::any(glm::isinf(transformed))) {
					std::cerr << "Invalid transformed vertex: (" << transformed.x << ", " << transformed.y << ", " << transformed.z << ")\n";
					continue;
				}
				m_StaticWorldMesh.addVertex(transformed.x, transformed.y, transformed.z);
			}

			static const int boxIndices[] = {
				0,1,2, 1,3,2, 4,6,5, 5,6,7,
				0,2,4, 2,6,4, 1,5,3, 5,7,3,
				2,3,6, 3,7,6, 4,5,0, 5,1,0
			};

			for (int i = 0; i < 36; i += 3) {
				m_StaticWorldMesh.addTriangle(v0 + boxIndices[i], v0 + boxIndices[i + 1], v0 + boxIndices[i + 2]);
			}
		}

		for (const auto& face : meshobj.faces) {
			glm::vec3 transformed_vertices[3] = {
				applyTransform({face.a.x, face.a.y, face.a.z}),
				applyTransform({face.b.x, face.b.y, face.b.z}),
				applyTransform({face.c.x, face.c.y, face.c.z})
			};

			bool invalid = false;
			for (const auto& v : transformed_vertices) {
				if (glm::any(glm::isnan(v)) || glm::any(glm::isinf(v))) {
					invalid = true;
					break;
				}
			}

			if (invalid) {
				std::cerr << "Invalid transformed face vertex detected, skipping face.\n";
				continue;
			}

			int v0 = m_StaticWorldMesh.getVertCount();
			for (const auto& vertex : transformed_vertices) {
				m_StaticWorldMesh.addVertex(vertex.x, vertex.y, vertex.z);
			}
			m_StaticWorldMesh.addTriangle(v0, v0 + 1, v0 + 2);
		}
	}