From 82c019ee491b3bc187ebc608e92f25b5d3554990 Mon Sep 17 00:00:00 2001 From: hesuicong Date: Wed, 13 May 2026 14:07:15 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=96=E8=AF=91=E9=80=9A=E8=BF=87=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E7=94=9F=E6=88=90=E7=BA=B9=E7=90=86=EF=BC=8C?= =?UTF-8?q?=E4=BD=86=E6=98=AF=E8=BF=98=E6=98=AF=E6=A8=A1=E7=B3=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/MVS/SceneTexture.cpp | 686 ++++++++++++++++++++++++++++---------- 1 file changed, 509 insertions(+), 177 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index e183d82..ea1b65e 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -660,6 +660,8 @@ public: float fOutlierThreshold, unsigned nTextureSizeMultiple, Pixel8U colEmpty, float fSharpnessWeight); bool CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap); + bool CheckUVContinuityForRegion(const std::vector& faceList); + bool CheckUVContinuityForRegion(const MVS::Mesh::FaceIdxArr& faceList); bool CheckUVContinuity(const std::vector& faceList); Mesh::Image8U3Arr GenerateMultiViewTextureAtlasWithVirtualFaces( const VirtualFaceMap& virtualFaceMap, @@ -1411,9 +1413,18 @@ bool MeshTexture::CalculateVirtualFaceProperties(VirtualFace& vf) { vf.center = Point3f::ZERO; vf.normal = Normal::ZERO; vf.area = 0.0f; + + DEBUG_EXTRA("ERROR: Virtual face has no faces"); return false; } + for (FIndex fid : vf.faces) { + if (fid >= scene.mesh.faces.size()) { + DEBUG_EXTRA("ERROR: Face index %u out of bounds in virtual face", fid); + return false; + } + } + const Mesh::VertexArr& vertices = scene.mesh.vertices; const Mesh::NormalArr& faceNormals = scene.mesh.faceNormals; const size_t numFaces = scene.mesh.faces.size(); @@ -1527,31 +1538,136 @@ bool MeshTexture::CalculateVirtualFaceProperties(VirtualFace& vf) { } bool MeshTexture::CalculateVirtualFaceUVBounds(VirtualFace& vf) { - if (vf.faces.empty() || !scene.mesh.HasTexture()) { - // 修正1: 不使用 ZERO,而是创建一个空的边界框 + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: Starting for virtual face with %zu faces", vf.faces.size()); + + if (vf.faces.empty()) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: ERROR - Virtual face has no faces"); vf.uvBounds = AABB2f(); // 使用默认构造函数 return false; // 返回 false } + // if (!scene.mesh.HasTexture()) { + // DEBUG_EXTRA("CalculateVirtualFaceUVBounds: ERROR - Mesh has no texture"); + // vf.uvBounds = AABB2f(); // 使用默认构造函数 + // return false; // 返回 false + // } + + if (scene.mesh.faceTexcoords.empty()) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: ERROR - No texture coordinates in mesh"); + vf.uvBounds = AABB2f(); + return false; + } + const TexCoord* texcoords = scene.mesh.faceTexcoords.data(); bool first = true; + int uv_count = 0; - for (FIndex faceIdx : vf.faces) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: Processing %zu faces", vf.faces.size()); + + for (size_t idx = 0; idx < vf.faces.size(); ++idx) { + FIndex faceIdx = vf.faces[idx]; + + // 检查面片索引是否有效 + if (faceIdx >= scene.mesh.faces.size()) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: ERROR - Face index %u out of bounds (max=%zu)", + faceIdx, scene.mesh.faces.size()); + continue; + } + + // 检查UV坐标索引是否有效 + size_t base_uv_idx = faceIdx * 3; + if (base_uv_idx + 2 >= scene.mesh.faceTexcoords.size()) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: ERROR - Face %u has insufficient UV coordinates (base_idx=%zu, total_uvs=%zu)", + faceIdx, base_uv_idx, scene.mesh.faceTexcoords.size()); + continue; + } + + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: Processing face %u (index %zu/%zu)", + faceIdx, idx + 1, vf.faces.size()); + for (int i = 0; i < 3; ++i) { const TexCoord& uv = texcoords[faceIdx * 3 + i]; + uv_count++; + + // 检查UV值是否有效 - 注意:对于Eigen向量,使用x()和y()函数访问分量 + if (!std::isfinite(uv.x) || !std::isfinite(uv.y)) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: WARNING - Face %u UV[%d] = (%.6f, %.6f) contains NaN or Inf", + faceIdx, i, uv.x, uv.y); + continue; + } + + // 检查UV值是否在合理范围内 + if (uv.x < -100.0f || uv.x > 100.0f || uv.y < -100.0f || uv.y > 100.0f) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: WARNING - Face %u UV[%d] = (%.6f, %.6f) is out of expected range [-100, 100]", + faceIdx, i, uv.x, uv.y); + } + if (first) { - // 修正2: 使用 ptMin 和 ptMax + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: Setting initial bounds with UV[%d] = (%.6f, %.6f)", + i, uv.x, uv.y); vf.uvBounds.ptMin = uv; vf.uvBounds.ptMax = uv; first = false; } else { + // 记录扩展前的边界 + Point2f oldMin = vf.uvBounds.ptMin; + Point2f oldMax = vf.uvBounds.ptMax; + vf.uvBounds.Insert(uv); + + // 检查边界是否发生变化 + if (oldMin.x != vf.uvBounds.ptMin.x() || + oldMin.y != vf.uvBounds.ptMin.y() || + oldMax.x != vf.uvBounds.ptMax.x() || + oldMax.y != vf.uvBounds.ptMax.y()){ + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: UV[%d] = (%.6f, %.6f) expanded bounds: min(%.6f,%.6f)->max(%.6f,%.6f)", + i, uv.x, uv.y, + oldMin.x, oldMin.y, + vf.uvBounds.ptMax.x(), vf.uvBounds.ptMax.y()); + } } } } - return !first; // 如果至少有一个UV坐标,则返回true + if (first) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: ERROR - No valid UV coordinates found for virtual face"); + vf.uvBounds = AABB2f(); + return false; + } + + // 计算UV边界尺寸 - 修正:AABB2f没有GetWidth和GetHeight,需要手动计算 + float uv_width = vf.uvBounds.ptMax.x() - vf.uvBounds.ptMin.x(); + float uv_height = vf.uvBounds.ptMax.y() - vf.uvBounds.ptMin.y(); + + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: Completed successfully"); + DEBUG_EXTRA(" - Processed %zu faces", vf.faces.size()); + DEBUG_EXTRA(" - Valid UV coordinates: %d", uv_count); + // 修正:使用x()和y()函数而不是直接访问成员 + DEBUG_EXTRA(" - UV bounds: min(%.6f, %.6f) max(%.6f, %.6f)", + vf.uvBounds.ptMin.x(), vf.uvBounds.ptMin.y(), + vf.uvBounds.ptMax.x(), vf.uvBounds.ptMax.y()); + DEBUG_EXTRA(" - UV size: %.6f x %.6f (width x height)", uv_width, uv_height); + DEBUG_EXTRA(" - UV area: %.6f", uv_width * uv_height); + + // 检查UV边界是否合理 + if (uv_width <= 0.0f || uv_height <= 0.0f) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: WARNING - Invalid UV dimensions: %.6f x %.6f", + uv_width, uv_height); + } + + if (uv_width > 10.0f || uv_height > 10.0f) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: WARNING - UV bounds unusually large: %.6f x %.6f", + uv_width, uv_height); + } + + if (uv_width * uv_height < 1e-10f) { + DEBUG_EXTRA("CalculateVirtualFaceUVBounds: WARNING - UV area extremely small: %.6e", + uv_width * uv_height); + } + + return true; } + // 检查两个面片在UV空间中是否连续 bool MeshTexture::AreFacesUVContinuous(FIndex fid1, FIndex fid2) { if (!scene.mesh.HasTexture()) { @@ -14643,150 +14759,101 @@ bool MeshTexture::ConvertVectorToVirtualFaceDataArr(const std::vector(10)); ++i) { // 使用static_cast - const Mesh::Face& face = scene.mesh.faces[i]; - bool valid = true; - for (int j = 0; j < 3; ++j) { - if (face[j] >= numVertices) { - DEBUG_EXTRA("ERROR: Face %zu has invalid vertex index %u (max: %zu)", - i, face[j], numVertices - 1); - valid = false; - } - } - if (valid) { - DEBUG_EXTRA("Face %zu: vertices [%u, %u, %u] - OK", - i, face[0], face[1], face[2]); - } - } - - // 验证UV坐标索引 - if (numFaceTexcoords > 0) { - DEBUG_EXTRA("Validating UV coordinate indices..."); - if (numFaceTexcoords < numFaces * 3) { - DEBUG_EXTRA("ERROR: Not enough UV coordinates! Expected %zu, have %zu", - numFaces * 3, numFaceTexcoords); - return false; - } + if (scene.mesh.faceNormals.size() != numFaces) { + DEBUG_EXTRA("ERROR: faceNormals size mismatch!"); + return false; } - // 1. 确保网格拓扑已计算 - DEBUG_EXTRA("Computing mesh topology..."); + // 检查面-面邻接关系 if (scene.mesh.faceFaces.empty()) { - DEBUG_EXTRA(" Computing incident faces..."); - try { - scene.mesh.ListIncidenteFaces(); - scene.mesh.ListIncidenteFaceFaces(); - DEBUG_EXTRA(" Done computing incident faces"); - } catch (const std::exception& e) { - DEBUG_EXTRA(" ERROR computing incident faces: %s", e.what()); - return false; - } + DEBUG_EXTRA("Computing face adjacency..."); + scene.mesh.ListIncidenteFaces(); + scene.mesh.ListIncidenteFaceFaces(); } - if (scene.mesh.faceNormals.empty()) { - DEBUG_EXTRA(" Computing face normals..."); - try { - scene.mesh.ComputeNormalFaces(); - DEBUG_EXTRA(" Done computing face normals"); - } catch (const std::exception& e) { - DEBUG_EXTRA(" ERROR computing face normals: %s", e.what()); - return false; - } + if (scene.mesh.faceFaces.size() != numFaces) { + DEBUG_EXTRA("ERROR: faceFaces size mismatch!"); + return false; } - std::vector processedFaces(numFaces, false); - - // 3. 基于曲率分割网格 + // 1. 基于曲率分割网格 DEBUG_EXTRA("Segmenting mesh based on curvature..."); Mesh::FaceIdxArr regionMap; - try { - scene.SegmentMeshBasedOnCurvature(regionMap, 0.2f); - DEBUG_EXTRA("Mesh segmentation completed, regionMap size: %zu", regionMap.size()); - - if (regionMap.size() != numFaces) { - DEBUG_EXTRA("ERROR: regionMap size (%zu) doesn't match number of faces (%u)", - regionMap.size(), numFaces); + // 使用更大的曲率阈值以获得更大的区域 + scene.SegmentMeshBasedOnCurvature(regionMap, 0.5f); + + DEBUG_EXTRA("Region map computed, size: %zu", regionMap.size()); + + if (regionMap.empty()) { + DEBUG_EXTRA("ERROR: regionMap is empty!"); + return false; + } + + if (regionMap.size() != numFaces) { + DEBUG_EXTRA("ERROR: regionMap size doesn't match number of faces"); + return false; + } + + // 检查区域映射的有效性 + int minRegion = INT_MAX, maxRegion = INT_MIN; + for (FIndex fid = 0; fid < numFaces; ++fid) { + if (fid >= regionMap.size()) { + DEBUG_EXTRA("ERROR: regionMap index out of bounds: %u >= %zu", fid, regionMap.size()); return false; } - } catch (const std::exception& e) { - DEBUG_EXTRA("ERROR during mesh segmentation: %s", e.what()); - return false; + int region = regionMap[fid]; + if (region < minRegion) minRegion = region; + if (region > maxRegion) maxRegion = region; } + DEBUG_EXTRA("Region map: min=%d, max=%d", minRegion, maxRegion); - // 4. 统计每个区域的面积 - DEBUG_EXTRA("Calculating region areas..."); + // 3. 统计区域信息 + std::unordered_map> regionFaces; std::unordered_map regionAreas; for (FIndex fid = 0; fid < numFaces; ++fid) { - if (fid % 10000 == 0 && fid > 0) { - DEBUG_EXTRA(" Processed %u/%u faces", fid, numFaces); - } - int region = regionMap[fid]; + regionFaces[region].push_back(fid); - // 验证面片索引 - if (fid >= scene.mesh.faces.size()) { - DEBUG_EXTRA("ERROR: Face index %u out of bounds (mesh has %zu faces)", - fid, scene.mesh.faces.size()); - continue; - } - + // 计算面片面积 const Mesh::Face& face = scene.mesh.faces[fid]; - // 验证顶点索引 - for (int i = 0; i < 3; ++i) { - if (face[i] >= scene.mesh.vertices.size()) { - DEBUG_EXTRA("ERROR: Vertex index %u out of bounds in face %u (mesh has %zu vertices)", - face[i], fid, scene.mesh.vertices.size()); - continue; - } + // 检查顶点索引是否有效 + if (face[0] >= scene.mesh.vertices.size() || + face[1] >= scene.mesh.vertices.size() || + face[2] >= scene.mesh.vertices.size()) { + DEBUG_EXTRA("WARNING: Face %u has invalid vertex indices, skipping area calculation", fid); + continue; } const Point3f& v0 = scene.mesh.vertices[face[0]]; const Point3f& v1 = scene.mesh.vertices[face[1]]; const Point3f& v2 = scene.mesh.vertices[face[2]]; - // 计算三角形面积 Point3f edge1 = v1 - v0; Point3f edge2 = v2 - v0; @@ -14802,108 +14869,340 @@ bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap crossProd.z * crossProd.z ); - if (area < 0) { - DEBUG_EXTRA("WARNING: Negative area calculated for face %u: %f", fid, area); - area = 0.0f; - } - regionAreas[region] += area; } - DEBUG_EXTRA("Region area calculation completed, found %zu regions", regionAreas.size()); + DEBUG_EXTRA("Found %zu regions", regionFaces.size()); - // 5. 为每个区域收集面片 - DEBUG_EXTRA("Grouping faces by region..."); - std::unordered_map> regionFaces; - for (FIndex fid = 0; fid < numFaces; ++fid) { - int region = regionMap[fid]; - regionFaces[region].push_back(fid); + // 检查regionAreas是否计算正确 + for (const auto& entry : regionAreas) { + DEBUG_EXTRA("Region %d: area=%.6f, faces=%zu", + entry.first, entry.second, regionFaces[entry.first].size()); } - DEBUG_EXTRA("Found %zu regions with faces", regionFaces.size()); - - // 6. 创建虚拟面 - DEBUG_EXTRA("Creating virtual faces..."); + // 4. 创建虚拟面 + std::vector processedFaces(numFaces, false); virtualFaceMap.clear(); - virtualFaceMap.reserve(regionFaces.size()); + virtualFaceMap.reserve(numFaces); // 每个面单独处理 - int regionCount = 0; - int smallRegionCount = 0; - int uvDiscontinuousCount = 0; int createdVirtualFaces = 0; + int smallRegions = 0; + int uvDiscontinuousRegions = 0; + + // 参数设置 + const float thMaxNormalDeviation = 30.0f; // 法线最大偏差角度 + const float cosMaxNormalDeviation = cos(FD2R(thMaxNormalDeviation)); + const float maxUVSize = 1.0f; // UV边界最大尺寸 + const float minRegionArea = 0.01f; // 最小区域面积 + // 遍历每个区域 for (const auto& region : regionFaces) { - regionCount++; int regionID = region.first; const std::vector& faceList = region.second; - if (regionCount % 100 == 0) { - DEBUG_EXTRA(" Processing region %d/%d (%zu faces)", regionCount, regionFaces.size(), faceList.size()); - } + DEBUG_EXTRA("Processing region %d with %zu faces", regionID, faceList.size()); - // 检查区域面积是否足够大 + // 检查区域面积 float regionArea = regionAreas[regionID]; - if (regionArea < 0.001f) { // 面积阈值 - DEBUG_EXTRA(" Region %d is too small (area: %f), using individual faces", regionID, regionArea); - smallRegionCount++; + + // 小区域:直接为每个面单独创建虚拟面 + if (regionArea < minRegionArea) { + DEBUG_EXTRA(" Small region (area=%.6f < %.6f), creating individual faces", + regionArea, minRegionArea); + smallRegions++; - // 区域太小,不创建虚拟面 for (FIndex fid : faceList) { - virtualFaceMap.push_back(VirtualFace()); - virtualFaceMap.back().faces.push_back(fid); + // 添加调试代码 + // DEBUG_EXTRA("Processing face %u for virtual face creation", fid); + + // 检查面片数据 + if (fid >= scene.mesh.faces.size()) { + DEBUG_EXTRA("ERROR: Face index %u out of bounds (max=%zu)", fid, scene.mesh.faces.size()); + continue; + } + + // 检查顶点索引 + const Mesh::Face& face = scene.mesh.faces[fid]; + if (face[0] >= scene.mesh.vertices.size() || + face[1] >= scene.mesh.vertices.size() || + face[2] >= scene.mesh.vertices.size()) { + DEBUG_EXTRA("ERROR: Face %u has invalid vertex indices: %u, %u, %u", + fid, face[0], face[1], face[2]); + continue; + } + + // 检查法线 + if (fid >= scene.mesh.faceNormals.size()) { + DEBUG_EXTRA("ERROR: Face %u has no normal data", fid); + continue; + } + + // 检查UV坐标 + if (fid * 3 + 2 >= scene.mesh.faceTexcoords.size()) { + DEBUG_EXTRA("ERROR: Face %u has insufficient UV coordinates", fid); + continue; + } + // 调试代码结束 + + if (fid >= scene.mesh.faces.size()) { + DEBUG_EXTRA(" WARNING: Invalid face index %u, skipping", fid); + continue; + } + + VirtualFace singleFace; + singleFace.faces.push_back(fid); + + // 计算单个面的属性 + if (CalculateVirtualFaceProperties(singleFace) && + CalculateVirtualFaceUVBounds(singleFace)) { + virtualFaceMap.push_back(singleFace); + createdVirtualFaces++; + } else { + // DEBUG_EXTRA(" WARNING: Failed to create virtual face for face %u", fid); + } + + if (fid < processedFaces.size()) { + processedFaces[fid] = true; + } } + DEBUG_EXTRA(" Created %d virtual faces for small region %d", createdVirtualFaces, regionID); continue; } - // 检查UV连续性 - if (!CheckUVContinuity(faceList)) { - DEBUG_EXTRA(" Region %d has discontinuous UV, using individual faces", regionID); - uvDiscontinuousCount++; + // 大区域:正常处理 + DEBUG_EXTRA(" Large region (area=%.6f), using region growing", regionArea); + + // 创建虚拟面列表 + std::vector regionVirtualFaces; + + // 遍历区域中的每个面片 + for (FIndex seedFace : faceList) { + // 添加调试代码 + // DEBUG_EXTRA("Processing seed face %u for virtual face creation", seedFace); - // UV不连续,保持原始面片 - for (FIndex fid : faceList) { - virtualFaceMap.push_back(VirtualFace()); - virtualFaceMap.back().faces.push_back(fid); + // 检查面片数据 + if (seedFace >= scene.mesh.faces.size()) { + DEBUG_EXTRA("ERROR: Seed face index %u out of bounds (max=%zu)", seedFace, scene.mesh.faces.size()); + continue; + } + + // 检查顶点索引 + const Mesh::Face& face = scene.mesh.faces[seedFace]; + if (face[0] >= scene.mesh.vertices.size() || + face[1] >= scene.mesh.vertices.size() || + face[2] >= scene.mesh.vertices.size()) { + DEBUG_EXTRA("ERROR: Seed face %u has invalid vertex indices: %u, %u, %u", + seedFace, face[0], face[1], face[2]); + continue; + } + + // 检查法线 + if (seedFace >= scene.mesh.faceNormals.size()) { + DEBUG_EXTRA("ERROR: Seed face %u has no normal data", seedFace); + continue; + } + + // 检查UV坐标 + if (seedFace * 3 + 2 >= scene.mesh.faceTexcoords.size()) { + DEBUG_EXTRA("ERROR: Seed face %u has insufficient UV coordinates", seedFace); + continue; + } + // 调试代码结束 + + if (seedFace >= scene.mesh.faces.size()) { + DEBUG_EXTRA(" WARNING: Invalid seed face index %u, skipping", seedFace); + continue; + } + + // 检查面片是否已处理 + if (seedFace < processedFaces.size() && processedFaces[seedFace]) { + continue; + } + + // 创建新的虚拟面 + VirtualFace vf; + vf.faces.push_back(seedFace); + + // 计算虚拟面属性 + if (!CalculateVirtualFaceProperties(vf) || !CalculateVirtualFaceUVBounds(vf)) { + // DEBUG_EXTRA(" WARNING: Failed to calculate properties for seed face %u", seedFace); + continue; + } + + // 区域增长队列 + std::queue faceQueue; + faceQueue.push(seedFace); + std::unordered_set inQueue; + inQueue.insert(seedFace); + + while (!faceQueue.empty()) { + FIndex currentFace = faceQueue.front(); + faceQueue.pop(); + + // 获取相邻面片 + if (currentFace >= scene.mesh.faceFaces.size()) { + continue; + } + + const Mesh::FaceFaces& neighbors = scene.mesh.faceFaces[currentFace]; + + for (int i = 0; i < 3; ++i) { + FIndex neighborFace = neighbors[i]; + if (neighborFace == NO_ID) continue; + + if (neighborFace >= scene.mesh.faces.size()) { + continue; + } + + // 检查邻居是否在同一区域 + bool inSameRegion = false; + for (FIndex fid : faceList) { + if (fid == neighborFace) { + inSameRegion = true; + break; + } + } + if (!inSameRegion) continue; + + // 检查邻居是否已处理 + if (neighborFace < processedFaces.size() && processedFaces[neighborFace]) { + continue; + } + + // 检查是否已在队列中 + if (inQueue.find(neighborFace) != inQueue.end()) continue; + + // 检查邻居是否已在当前虚拟面中 + bool alreadyInVirtual = false; + for (FIndex fid : vf.faces) { + if (fid == neighborFace) { + alreadyInVirtual = true; + break; + } + } + if (alreadyInVirtual) continue; + + // 1. 检查法线相似性 + FIndex firstFace = vf.faces[0]; + if (firstFace >= scene.mesh.faceNormals.size() || + neighborFace >= scene.mesh.faceNormals.size()) { + continue; + } + + const Normal& seedNormal = scene.mesh.faceNormals[firstFace]; + const Normal& neighborNormal = scene.mesh.faceNormals[neighborFace]; + + float cosAngle = seedNormal.dot(neighborNormal); + if (cosAngle < cosMaxNormalDeviation) continue; + + // 2. 临时添加面片检查UV连续性 + MVS::Mesh::FaceIdxArr tempFaces = vf.faces; + tempFaces.push_back(neighborFace); + + if (!CheckUVContinuityForRegion(tempFaces)) continue; + + // 3. 检查UV边界 + AABB2f tempBounds = vf.uvBounds; + + // 扩展UV边界 + for (int k = 0; k < 3; ++k) { + size_t uvIndex = neighborFace * 3 + k; + if (uvIndex >= scene.mesh.faceTexcoords.size()) { + break; + } + + const Point2f& uv = scene.mesh.faceTexcoords[uvIndex]; + + float minX = tempBounds.ptMin.x(); + float minY = tempBounds.ptMin.y(); + float maxX = tempBounds.ptMax.x(); + float maxY = tempBounds.ptMax.y(); + + if (uv.x < minX) minX = uv.x; + if (uv.y < minY) minY = uv.y; + if (uv.x > maxX) maxX = uv.x; + if (uv.y > maxY) maxY = uv.y; + + // 检查UV边界尺寸 + if (maxX - minX > maxUVSize || maxY - minY > maxUVSize) { + break; // UV边界过大,跳过 + } + + tempBounds.ptMin.x() = minX; + tempBounds.ptMin.y() = minY; + tempBounds.ptMax.x() = maxX; + tempBounds.ptMax.y() = maxY; + } + + // 所有检查通过,添加面片到虚拟面 + vf.faces.push_back(neighborFace); + vf.uvBounds = tempBounds; + + // 重新计算虚拟面属性 + if (!CalculateVirtualFaceProperties(vf)) { + vf.faces.pop_back(); // 移除添加的面片 + continue; + } + + // 添加到队列继续扩展 + faceQueue.push(neighborFace); + inQueue.insert(neighborFace); + } + } + + // 将虚拟面添加到区域虚拟面列表 + regionVirtualFaces.push_back(vf); + + // 标记面片为已处理 + for (FIndex fid : vf.faces) { + if (fid < processedFaces.size()) { + processedFaces[fid] = true; + } } - continue; } - // 创建虚拟面 - VirtualFace vf; - vf.faces = faceList; - - // 计算虚拟面的中心、法线和面积 - if (!CalculateVirtualFaceProperties(vf)) { - DEBUG_EXTRA(" Failed to calculate properties for virtual face in region %d", regionID); - // 计算失败,回退到原始面片 - for (FIndex fid : faceList) { - virtualFaceMap.push_back(VirtualFace()); - virtualFaceMap.back().faces.push_back(fid); - } - continue; + // 将区域虚拟面添加到全局虚拟面列表 + for (const auto& vf : regionVirtualFaces) { + virtualFaceMap.push_back(vf); } - // 计算虚拟面的UV边界 - if (!CalculateVirtualFaceUVBounds(vf)) { - DEBUG_EXTRA(" Failed to calculate UV bounds for virtual face in region %d", regionID); - // 计算失败,回退到原始面片 - for (FIndex fid : faceList) { - virtualFaceMap.push_back(VirtualFace()); - virtualFaceMap.back().faces.push_back(fid); + createdVirtualFaces += regionVirtualFaces.size(); + DEBUG_EXTRA(" Region %d: created %zu virtual faces", regionID, regionVirtualFaces.size()); + } + + // 处理未包含在区域中的面片 + int unprocessedCount = 0; + for (FIndex fid = 0; fid < numFaces; ++fid) { + if (!processedFaces[fid]) { + VirtualFace singleFace; + singleFace.faces.push_back(fid); + if (CalculateVirtualFaceProperties(singleFace) && + CalculateVirtualFaceUVBounds(singleFace)) { + virtualFaceMap.push_back(singleFace); + createdVirtualFaces++; } - continue; + unprocessedCount++; } - - virtualFaceMap.push_back(vf); - createdVirtualFaces++; + } + + if (unprocessedCount > 0) { + DEBUG_EXTRA(" Processed %d unassigned faces", unprocessedCount); } DEBUG_EXTRA("Virtual face creation completed:"); - DEBUG_EXTRA(" Total regions: %zu", regionFaces.size()); - DEBUG_EXTRA(" Small regions (area < 0.001): %d", smallRegionCount); - DEBUG_EXTRA(" UV discontinuous regions: %d", uvDiscontinuousCount); + DEBUG_EXTRA(" Total faces: %zu", numFaces); + DEBUG_EXTRA(" Total virtual faces: %zu", virtualFaceMap.size()); + DEBUG_EXTRA(" Small regions (< %.3f): %d", minRegionArea, smallRegions); DEBUG_EXTRA(" Created virtual faces: %d", createdVirtualFaces); - DEBUG_EXTRA(" Total virtual faces (including individual faces): %zu", virtualFaceMap.size()); + + // 统计合并比例 + size_t totalFacesInVirtual = 0; + for (const auto& vf : virtualFaceMap) { + totalFacesInVirtual += vf.faces.size(); + } + + float mergeRatio = (float)totalFacesInVirtual / (numFaces * 1.0f); + DEBUG_EXTRA(" Average faces per virtual face: %.2f", mergeRatio); if (virtualFaceMap.empty()) { DEBUG_EXTRA("ERROR: No virtual faces created!"); @@ -14913,6 +15212,39 @@ bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap return true; } +bool MeshTexture::CheckUVContinuityForRegion(const std::vector& faceList) { + if (faceList.size() <= 1) return true; + + // 检查UV是否在合理范围内 + for (FIndex fid : faceList) { + for (int i = 0; i < 3; ++i) { + const Point2f& uv = scene.mesh.faceTexcoords[fid * 3 + i]; + if (std::isnan(uv.x) || std::isnan(uv.y) || + std::isinf(uv.x) || std::isinf(uv.y)) { + return false; + } + } + } + + return true; +} + +bool MeshTexture::CheckUVContinuityForRegion(const MVS::Mesh::FaceIdxArr& faceList) { + if (faceList.size() <= 1) return true; + + for (FIndex fid : faceList) { + for (int i = 0; i < 3; ++i) { + const Point2f& uv = scene.mesh.faceTexcoords[fid * 3 + i]; + if (std::isnan(uv.x) || std::isnan(uv.y) || + std::isinf(uv.x) || std::isinf(uv.y)) { + return false; + } + } + } + + return true; +} + bool MeshTexture::CheckUVContinuity(const std::vector& faceList) { if (faceList.empty()) return false; @@ -17145,7 +17477,7 @@ bool MeshTexture::ValidateProjection(const Vertex& worldPoint, // 3. 设置误差阈值 if (reprojectionError > maxReprojectionError) { - DEBUG_EXTRA("重投影误差过大: %.3f像素,跳过该采样点", reprojectionError); + // DEBUG_EXTRA("重投影误差过大: %.3f像素,跳过该采样点", reprojectionError); return false; }