From 42f6d9c84c5f9e4a594725679d97a69d36acdc90 Mon Sep 17 00:00:00 2001 From: hesuicong Date: Thu, 14 May 2026 09:06:37 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=96=E8=AF=91=E4=B8=8D=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/MVS/SceneTexture.cpp | 1113 ++++++++++++++++++++----------------- 1 file changed, 593 insertions(+), 520 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index ea1b65e..76f3f67 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -593,6 +593,9 @@ public: void CreateVirtualFaces4(const FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, Mesh::FaceIdxArr& mapFaceToVirtualFace, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f); void CreateVirtualFaces5(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f) const; bool CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector& isVirtualFace, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f) const; + bool CreateVirtualFaces61(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, + VirtualFaceIdxsArr& virtualFaces, std::vector& isVirtualFace, + unsigned minCommonCameras, float thMaxNormalDeviation) const; bool CreateVirtualFaces7(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector& isVirtualFace, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f) const; IIndexArr SelectBestViews(const FaceDataArr& faceDatas, FIndex fid, unsigned minCommonCameras, float ratioAngleToQuality) const; IIndexArr SelectBestView(const FaceDataArr& faceDatas, FIndex fid, unsigned minCommonCameras, float ratioAngleToQuality) const; @@ -605,16 +608,16 @@ public: bool ShouldMergeVirtualFace(const MeshTexture::FaceDataViewArr& facesDatas, const Mesh::FaceIdxArr& currentVirtualFace, FIndex candidateFace, unsigned minCommonCameras); bool FaceViewSelectionWithVirtualFaces(unsigned minCommonCameras, float fOutlierThreshold, float fRatioDataSmoothness, int nIgnoreMaskLabel, - const IIndexArr& views, bool bUseExistingUV); + const IIndexArr& views, bool bUseExistingUV, VirtualFaceMap* pVirtualFaceMap); bool GenerateTextureWithVirtualFaces(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, float fSharpnessWeight, int maxTextureSize, - const SEACAVE::String& baseFileName, bool bOriginFaceview, Scene* pScene); + const SEACAVE::String& baseFileName, bool bOriginFaceview, Scene* pScene, VirtualFaceMap* pVirtualFaceMap); bool GenerateTextureWithVirtualFacesInternal(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, float fSharpnessWeight, int maxTextureSize, - const SEACAVE::String& baseFileName, Scene* pScene); + const SEACAVE::String& baseFileName, Scene* pScene, VirtualFaceMap* pVirtualFaceMap); bool ConvertVectorToVirtualFaceDataArr(const std::vector& src, VirtualFaceDataArr& dst); bool InitializeEmptyVirtualFaceDataArr(const VirtualFaceMap& virtualFaceMap, VirtualFaceDataArr& vfDataArr); bool SelectBestViewsForVirtualFaces(VirtualFaceMap& virtualFaceMap, @@ -628,6 +631,9 @@ public: std::vector> faceNeighbors; VirtualFaceGeometryArr m_virtualFaceGeometries; + mutable VirtualFaceMap m_cachedVirtualFaceMap; + mutable bool m_virtualFaceMapCached = false; + uint32_t FindNearestPatchForFaces(const std::vector& faceIndices); void FixIsolatedComponents(); void ReinitializeSeamData(); @@ -658,8 +664,13 @@ public: ); bool TextureWithExistingUVVirtualFaces(const IIndexArr& views, int nIgnoreMaskLabel, float fOutlierThreshold, unsigned nTextureSizeMultiple, - Pixel8U colEmpty, float fSharpnessWeight); + Pixel8U colEmpty, float fSharpnessWeight, VirtualFaceMap* pVirtualFaceMap); + void AnalyzeUVDistribution(); bool CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap); + bool CreateVirtualFacesForExistingUVImpl(VirtualFaceMap& virtualFaceMap); + void CalculateVirtualFaceUVBoundsSafe(VirtualFace& vf); + void CalculateVirtualFacePropertiesSafe(VirtualFace& vf); + bool CheckUVContinuityForRegion(const std::vector& faceList); bool CheckUVContinuityForRegion(const MVS::Mesh::FaceIdxArr& faceList); bool CheckUVContinuity(const std::vector& faceList); @@ -1538,141 +1549,65 @@ bool MeshTexture::CalculateVirtualFaceProperties(VirtualFace& vf) { } bool MeshTexture::CalculateVirtualFaceUVBounds(VirtualFace& vf) { - 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; + // if (!scene.mesh.HasTexture() || scene.mesh.faceTexcoords.empty()) { + // vf.uvBounds = AABB2f(); + // return false; + // } - DEBUG_EXTRA("CalculateVirtualFaceUVBounds: Processing %zu faces", vf.faces.size()); + bool first = true; + AABB2f bounds; - 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()); + for (FIndex faceIdx : vf.faces) { + if (faceIdx * 3 + 2 >= 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++; + const TexCoord& uv = scene.mesh.faceTexcoords[faceIdx * 3 + i]; - // 检查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) { - DEBUG_EXTRA("CalculateVirtualFaceUVBounds: Setting initial bounds with UV[%d] = (%.6f, %.6f)", - i, uv.x, uv.y); - vf.uvBounds.ptMin = uv; - vf.uvBounds.ptMax = uv; + bounds.ptMin = uv; + bounds.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()); - } + bounds.Insert(uv); } } } 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(); + vf.uvBounds = bounds; + float width = bounds.ptMax.x() - bounds.ptMin.x(); + float height = bounds.ptMax.y() - bounds.ptMin.y(); + float area = width * height; - 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); - } + // 记录统计信息 + if (area < 1e-6f) { + DEBUG_EXTRA("虚拟面UV面积: %.6e (尺寸: %.6f x %.6f), 面片数: %zu", + area, width, height, vf.faces.size()); + } return true; } // 检查两个面片在UV空间中是否连续 bool MeshTexture::AreFacesUVContinuous(FIndex fid1, FIndex fid2) { - if (!scene.mesh.HasTexture()) { - return false; - } + // if (!scene.mesh.HasTexture()) { + // return false; + // } const TexCoord* uv1 = &scene.mesh.faceTexcoords[fid1 * 3]; const TexCoord* uv2 = &scene.mesh.faceTexcoords[fid2 * 3]; @@ -4595,6 +4530,120 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA return true; } +bool MeshTexture::CreateVirtualFaces61(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, + VirtualFaceIdxsArr& virtualFaces, std::vector& isVirtualFace, + unsigned minCommonCameras, float thMaxNormalDeviation) const +{ + if (meshCurvatures.empty()) { + ComputeFaceCurvatures(); + } + + const float cosMaxNormalDeviation(COS(FD2R(thMaxNormalDeviation))); + Mesh::FaceIdxArr remainingFaces(faces.size()); + std::iota(remainingFaces.begin(), remainingFaces.end(), 0); + std::vector selectedFaces(faces.size(), false); + cQueue currentVirtualFaceQueue; + std::unordered_set queuedFaces; + + do { + const FIndex startPos = RAND() % remainingFaces.size(); + const FIndex virtualFaceCenterFaceID = remainingFaces[startPos]; + + const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID]; + const FaceDataArr& centerFaceDatas = facesDatas[virtualFaceCenterFaceID]; + + // 选择公共相机 + IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, + minCommonCameras, 0.67f); + + Mesh::FaceIdxArr virtualFace; + FaceDataArr virtualFaceDatas; + + if (centerFaceDatas.empty()) { + // 处理没有视图的情况 + virtualFace.emplace_back(virtualFaceCenterFaceID); + selectedFaces[virtualFaceCenterFaceID] = true; + const auto posToErase = remainingFaces.FindFirst(virtualFaceCenterFaceID); + ASSERT(posToErase != Mesh::FaceIdxArr::NO_INDEX); + remainingFaces.RemoveAtMove(posToErase); + } else { + currentVirtualFaceQueue.AddTail(virtualFaceCenterFaceID); + queuedFaces.clear(); + + do { + const FIndex currentFaceId = currentVirtualFaceQueue.GetHead(); + currentVirtualFaceQueue.PopHead(); + + // 检查法线夹角 + const Normal& faceNormal = scene.mesh.faceNormals[currentFaceId]; + const float cosFaceToCenter(ComputeAngleN(normalCenter.ptr(), faceNormal.ptr())); + if (cosFaceToCenter < cosMaxNormalDeviation) + continue; + + // 检查当前面是否被所有选定相机看到 + if (!IsFaceVisible(facesDatas[currentFaceId], selectedCams)) + continue; + + // 移除剩余面并添加到虚拟面 + const auto posToErase = remainingFaces.FindFirst(currentFaceId); + ASSERT(posToErase != Mesh::FaceIdxArr::NO_INDEX); + remainingFaces.RemoveAtMove(posToErase); + selectedFaces[currentFaceId] = true; + virtualFace.push_back(currentFaceId); + + // 添加邻居到队列 + const Mesh::FaceFaces& ffaces = faceFaces[currentFaceId]; + for (int i = 0; i < 3; ++i) { + const FIndex fIdx = ffaces[i]; + if (fIdx == NO_ID) + continue; + if (!selectedFaces[fIdx] && queuedFaces.find(fIdx) == queuedFaces.end()) { + currentVirtualFaceQueue.AddTail(fIdx); + queuedFaces.emplace(fIdx); + } + } + } while (!currentVirtualFaceQueue.IsEmpty()); + + // 计算虚拟面的质量 + for (IIndex idxView: selectedCams) { + FaceData& virtualFaceData = virtualFaceDatas.emplace_back(); + virtualFaceData.quality = 0; + virtualFaceData.idxView = idxView; + #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA + virtualFaceData.color = Point3f::ZERO; + #endif + + unsigned processedFaces = 0; + for (FIndex fid : virtualFace) { + const FaceDataArr& faceDatas = facesDatas[fid]; + for (const FaceData& faceData: faceDatas) { + if (faceData.idxView == idxView) { + virtualFaceData.quality += faceData.quality; + #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA + virtualFaceData.color += faceData.color; + #endif + ++processedFaces; + break; + } + } + } + + if (processedFaces > 0) { + virtualFaceData.quality /= processedFaces; + #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA + virtualFaceData.color /= processedFaces; + #endif + } + } + } + + virtualFacesDatas.emplace_back(std::move(virtualFaceDatas)); + virtualFaces.emplace_back(std::move(virtualFace)); + } while (!remainingFaces.empty()); + + return true; +} + bool MeshTexture::CreateVirtualFaces7(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector& isVirtualFace, unsigned minCommonCameras, float thMaxNormalDeviation) const { if (meshCurvatures.empty()) { @@ -14331,7 +14380,7 @@ void MeshTexture::FillTextureHoles(std::vector& textures, Pixel8U colE bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int nIgnoreMaskLabel, float fOutlierThreshold, unsigned nTextureSizeMultiple, - Pixel8U colEmpty, float fSharpnessWeight) + Pixel8U colEmpty, float fSharpnessWeight, VirtualFaceMap* pVirtualFaceMap) { DEBUG_EXTRA("TextureWithExistingUVVirtualFaces with multi-view blending"); TD_TIMER_START(); @@ -14351,16 +14400,14 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int // 2. 创建虚拟面 DEBUG_EXTRA("Creating virtual faces for existing UV texture mapping..."); VirtualFaceMap virtualFaceMap; - if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { - DEBUG_EXTRA("Failed to create virtual faces, falling back to original faces"); - // 回退到原始面片 - virtualFaceMap.clear(); - for (FIndex fid = 0; fid < faces.size(); ++fid) { - virtualFaceMap.push_back(VirtualFace()); - VirtualFace& vf = virtualFaceMap.back(); - vf.faces.push_back(fid); - } - } + if (pVirtualFaceMap) { + virtualFaceMap = *pVirtualFaceMap; // 使用传入的虚拟面 + } else { + if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { + DEBUG_EXTRA("Failed to create virtual faces for existing UV"); + return false; + } + } DEBUG_EXTRA("Created %zu virtual faces (original faces: %zu)", virtualFaceMap.size(), faces.size()); @@ -14481,18 +14528,21 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int bool MeshTexture::FaceViewSelectionWithVirtualFaces(unsigned minCommonCameras, float fOutlierThreshold, float fRatioDataSmoothness, int nIgnoreMaskLabel, - const IIndexArr& views, bool bUseExistingUV) + const IIndexArr& views, bool bUseExistingUV, VirtualFaceMap* pVirtualFaceMap) { DEBUG_EXTRA("Performing face view selection with virtual faces (bUseExistingUV=%d)", bUseExistingUV); if (bUseExistingUV) { // 使用现有UV的虚拟面选择策略 VirtualFaceMap virtualFaceMap; - if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { - DEBUG_EXTRA("Failed to create virtual faces for existing UV"); - return false; + if (pVirtualFaceMap) { + virtualFaceMap = *pVirtualFaceMap; // 使用传入的虚拟面 + } else { + if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { + DEBUG_EXTRA("Failed to create virtual faces for existing UV"); + return false; + } } - DEBUG_EXTRA("Created %zu virtual faces", virtualFaceMap.size()); // 为虚拟面选择最佳视图 @@ -14512,7 +14562,7 @@ bool MeshTexture::FaceViewSelectionWithVirtualFaces(unsigned minCommonCameras, f bool MeshTexture::GenerateTextureWithVirtualFaces(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, float fSharpnessWeight, int maxTextureSize, - const SEACAVE::String& baseFileName, bool bOriginFaceview, Scene* pScene) + const SEACAVE::String& baseFileName, bool bOriginFaceview, Scene* pScene, VirtualFaceMap* pVirtualFaceMap) { DEBUG_EXTRA("Generating texture with virtual faces (bOriginFaceview=%d)", bOriginFaceview); @@ -14528,7 +14578,7 @@ bool MeshTexture::GenerateTextureWithVirtualFaces(bool bGlobalSeamLeveling, bool return GenerateTextureWithVirtualFacesInternal(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, colEmpty, fSharpnessWeight, maxTextureSize, - baseFileName, pScene); + baseFileName, pScene, pVirtualFaceMap); } } @@ -14653,7 +14703,7 @@ bool MeshTexture::SelectBestViewsForVirtualFaces(VirtualFaceMap& virtualFaceMap, bool MeshTexture::GenerateTextureWithVirtualFacesInternal(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, float fSharpnessWeight, int maxTextureSize, - const SEACAVE::String& baseFileName, Scene* pScene) + const SEACAVE::String& baseFileName, Scene* pScene, VirtualFaceMap* pVirtualFaceMap) { DEBUG_EXTRA("Generating texture with virtual faces internal method"); @@ -14678,11 +14728,14 @@ bool MeshTexture::GenerateTextureWithVirtualFacesInternal(bool bGlobalSeamLeveli // 2. 创建虚拟面 VirtualFaceMap virtualFaceMap; - if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { - DEBUG_EXTRA("Failed to create virtual faces"); - return false; - } - + if (pVirtualFaceMap) { + virtualFaceMap = *pVirtualFaceMap; // 使用传入的虚拟面 + } else { + if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { + DEBUG_EXTRA("Failed to create virtual faces for existing UV"); + return false; + } + } // 3. 为虚拟面选择最佳视图 if (!SelectBestViewsForVirtualFaces(virtualFaceMap, 1, 0.0f, 1.0f, -1, IIndexArr())) { DEBUG_EXTRA("Failed to select best views for virtual faces"); @@ -14756,459 +14809,427 @@ bool MeshTexture::ConvertVectorToVirtualFaceDataArr(const std::vector uvGrid(gridSize * gridSize, 0); + + for (size_t i = 0; i < numUVs; ++i) { + const TexCoord& uv = scene.mesh.faceTexcoords[i]; + + int x = static_cast(uv.x * gridSize); + int y = static_cast(uv.y * gridSize); + + if (x >= 0 && x < gridSize && y >= 0 && y < gridSize) { + uvGrid[y * gridSize + x]++; + } } - size_t numFaces = scene.mesh.faces.size(); - if (scene.mesh.faceTexcoords.size() < numFaces * 3) { - DEBUG_EXTRA("ERROR: Not enough UV coordinates!"); - return false; + // 统计非空网格数量 + int nonEmptyCells = 0; + int maxDensity = 0; + int totalDensity = 0; + + for (int count : uvGrid) { + if (count > 0) { + nonEmptyCells++; + maxDensity = std::max(maxDensity, count); + totalDensity += count; + } } - // 检查法线数组 - if (scene.mesh.faceNormals.empty()) { - DEBUG_EXTRA("WARNING: faceNormals is empty, computing..."); - scene.mesh.ComputeNormalFaces(); + DEBUG_EXTRA("UV分布统计:"); + DEBUG_EXTRA(" - UV网格使用率: %d/%d (%.1f%%)", + nonEmptyCells, gridSize * gridSize, + 100.0f * nonEmptyCells / (gridSize * gridSize)); + DEBUG_EXTRA(" - 最大密度: %d (一个网格中的最大UV数量)", maxDensity); + DEBUG_EXTRA(" - 平均密度: %.1f (每个非空网格的平均UV数量)", + (float)totalDensity / nonEmptyCells); + + // 检查UV重叠情况 + int overlappingUVs = 0; + for (int count : uvGrid) { + if (count > 1) { + overlappingUVs += count; + } } - if (scene.mesh.faceNormals.size() != numFaces) { - DEBUG_EXTRA("ERROR: faceNormals size mismatch!"); - return false; + DEBUG_EXTRA(" - UV重叠情况: %d 个UV坐标在网格中重叠", overlappingUVs); + + // 检查每个面片的UV分布 + int degenerateFaces = 0; + for (FIndex fid = 0; fid < numFaces && fid < 100; ++fid) { // 只检查前100个面片 + if (fid * 3 + 2 >= numUVs) { + continue; + } + + const TexCoord& uv0 = scene.mesh.faceTexcoords[fid * 3]; + const TexCoord& uv1 = scene.mesh.faceTexcoords[fid * 3 + 1]; + const TexCoord& uv2 = scene.mesh.faceTexcoords[fid * 3 + 2]; + + // 计算UV三角形的面积 + float area = 0.5f * std::abs( + (uv1.x - uv0.x) * (uv2.y - uv0.y) - + (uv2.x - uv0.x) * (uv1.y - uv0.y) + ); + + if (area < 1e-8f) { + degenerateFaces++; + if (degenerateFaces < 5) { + DEBUG_EXTRA("面片 %u 的UV面积过小: %.6e (UVs: (%.3f,%.3f), (%.3f,%.3f), (%.3f,%.3f))", + fid, area, uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y); + } + } } - // 检查面-面邻接关系 - if (scene.mesh.faceFaces.empty()) { - DEBUG_EXTRA("Computing face adjacency..."); - scene.mesh.ListIncidenteFaces(); - scene.mesh.ListIncidenteFaceFaces(); + if (degenerateFaces > 0) { + DEBUG_EXTRA(" - 退化面片数量: %d (UV面积过小)", degenerateFaces); + } +} + +bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap) { + // 如果已有缓存,直接使用 + if (m_virtualFaceMapCached) { + virtualFaceMap = m_cachedVirtualFaceMap; + return true; + } + + // 否则重新创建 + if (!CreateVirtualFacesForExistingUVImpl(virtualFaceMap)) { + return false; + } + + // 缓存结果 + m_cachedVirtualFaceMap = virtualFaceMap; + m_virtualFaceMapCached = true; + return true; +} + +void MeshTexture::CalculateVirtualFacePropertiesSafe(VirtualFace& vf) { + if (vf.faces.empty()) { + vf.center = Point3f(0, 0, 0); + vf.normal = Point3f(0, 0, 1); + vf.area = 0.0f; + return; } - if (scene.mesh.faceFaces.size() != numFaces) { - DEBUG_EXTRA("ERROR: faceFaces size mismatch!"); - return false; + Point3f centerSum(0, 0, 0); + Point3f normalSum(0, 0, 0); + float areaSum = 0.0f; + size_t validFaces = 0; + + for (FIndex fid : vf.faces) { + if (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()) { + // 跳过无效的面 + goto skip_face; + } + } + + // 计算面中心 + Point3f faceCenter(0, 0, 0); + for (int i = 0; i < 3; ++i) { + faceCenter += scene.mesh.vertices[face[i]]; + } + faceCenter /= 3.0f; + + // 计算面面积和法线 + 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; + Point3f faceNormal = edge1.cross(edge2); + float faceArea = faceNormal.norm(); + + if (faceArea > 0) { + faceNormal /= faceArea; + faceArea *= 0.5f; + + // 加权平均 + centerSum += faceCenter * faceArea; + normalSum += faceNormal * faceArea; + areaSum += faceArea; + validFaces++; + } + + skip_face: + continue; } - // 1. 基于曲率分割网格 - DEBUG_EXTRA("Segmenting mesh based on curvature..."); - Mesh::FaceIdxArr regionMap; + if (validFaces > 0 && areaSum > 0) { + vf.center = centerSum / areaSum; + vf.normal = normalSum.normalized(); + vf.area = areaSum; + } else { + vf.center = Point3f(0, 0, 0); + vf.normal = Point3f(0, 0, 1); + vf.area = 0.0f; + } +} + +void MeshTexture::CalculateVirtualFaceUVBoundsSafe(VirtualFace& vf) { + if (vf.faces.empty()) { + vf.uvBounds.ptMin = TexCoord(0, 0); + vf.uvBounds.ptMax = TexCoord(1, 1); + return; + } - // 使用更大的曲率阈值以获得更大的区域 - scene.SegmentMeshBasedOnCurvature(regionMap, 0.5f); + bool first = true; + for (FIndex fid : vf.faces) { + if (fid * 3 + 2 >= scene.mesh.faceTexcoords.size()) { + continue; // 跳过无效索引 + } + + for (int i = 0; i < 3; ++i) { + const TexCoord& uv = scene.mesh.faceTexcoords[fid * 3 + i]; + + if (!std::isfinite(uv.x) || !std::isfinite(uv.y)) { + continue; // 跳过无效UV + } + + if (first) { + vf.uvBounds.ptMin = uv; + vf.uvBounds.ptMax = uv; + first = false; + } else { + vf.uvBounds.Insert(uv); + } + } + } - DEBUG_EXTRA("Region map computed, size: %zu", regionMap.size()); + if (first) { + // 没有有效的UV + vf.uvBounds.ptMin = TexCoord(0, 0); + vf.uvBounds.ptMax = TexCoord(1, 1); + } +} + +bool MeshTexture::CreateVirtualFacesForExistingUVImpl(VirtualFaceMap& virtualFaceMap) { + DEBUG_EXTRA("=== 创建现有UV映射的虚拟面 ==="); - if (regionMap.empty()) { - DEBUG_EXTRA("ERROR: regionMap is empty!"); + if (scene.mesh.faceTexcoords.empty()) { + DEBUG_EXTRA("错误: 网格没有UV坐标数据"); return false; } - if (regionMap.size() != numFaces) { - DEBUG_EXTRA("ERROR: regionMap size doesn't match number of faces"); + const size_t numFaces = scene.mesh.faces.size(); + + // 检查数据一致性 + if (scene.mesh.faceTexcoords.size() != numFaces * 3) { + DEBUG_EXTRA("错误: UV坐标数量不匹配 (面片数: %zu, UV坐标数: %zu)", + numFaces, scene.mesh.faceTexcoords.size()); return false; } - // 检查区域映射的有效性 - int minRegion = INT_MAX, maxRegion = INT_MIN; + DEBUG_EXTRA("开始UV聚类,面片数: %zu", numFaces); + + // 使用简单的哈希聚类 + const int gridSize = 32; + std::vector> grid(gridSize * gridSize); + + // 预分配内存 + size_t totalValidFaces = 0; 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; + if (IsFaceUVValid(fid)) { + totalValidFaces++; } - int region = regionMap[fid]; - if (region < minRegion) minRegion = region; - if (region > maxRegion) maxRegion = region; } - DEBUG_EXTRA("Region map: min=%d, max=%d", minRegion, maxRegion); - // 3. 统计区域信息 - std::unordered_map> regionFaces; - std::unordered_map regionAreas; + // 为每个网格预分配内存 + size_t avgPerCell = totalValidFaces / (gridSize * gridSize) + 1; + for (auto& cell : grid) { + cell.reserve(avgPerCell); + } + + // 分配面片到网格 + DEBUG_EXTRA("创建面片到UV网格的映射 (网格大小: %dx%d)...", gridSize, gridSize); + + AABB2f uvBounds; + bool hasBounds = false; for (FIndex fid = 0; fid < numFaces; ++fid) { - int region = regionMap[fid]; - regionFaces[region].push_back(fid); + if (!IsFaceUVValid(fid)) { + continue; + } - // 计算面片面积 - const Mesh::Face& face = scene.mesh.faces[fid]; + TexCoord center = GetFaceUVCenter(fid); - // 检查顶点索引是否有效 - 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; + // 更新UV边界 + if (!hasBounds) { + uvBounds.ptMin = center; + uvBounds.ptMax = center; + hasBounds = true; + } else { + uvBounds.Insert(center); } - const Point3f& v0 = scene.mesh.vertices[face[0]]; - const Point3f& v1 = scene.mesh.vertices[face[1]]; - const Point3f& v2 = scene.mesh.vertices[face[2]]; + // 确保在[0,1)范围内 + float u = center.x - floor(center.x); + float v = center.y - floor(center.y); + if (u < 0) u += 1.0f; + if (v < 0) v += 1.0f; - Point3f edge1 = v1 - v0; - Point3f edge2 = v2 - v0; + int gridX = static_cast(u * gridSize); + int gridY = static_cast(v * gridSize); - Point3f crossProd( - edge1.y * edge2.z - edge1.z * edge2.y, - edge1.z * edge2.x - edge1.x * edge2.z, - edge1.x * edge2.y - edge1.y * edge2.x - ); + // 边界检查 + gridX = std::max(0, std::min(gridX, gridSize - 1)); + gridY = std::max(0, std::min(gridY, gridSize - 1)); - float area = 0.5f * std::sqrt( - crossProd.x * crossProd.x + - crossProd.y * crossProd.y + - crossProd.z * crossProd.z - ); + int cellIdx = gridY * gridSize + gridX; + if (cellIdx >= 0 && cellIdx < static_cast(grid.size())) { + grid[cellIdx].push_back(fid); + } - regionAreas[region] += area; + if (fid % 200000 == 0 && fid > 0) { + DEBUG_EXTRA("已处理 %u/%zu 个面片", fid, numFaces); + } } - DEBUG_EXTRA("Found %zu regions", regionFaces.size()); + DEBUG_EXTRA("UV中心点分布范围: min(%.6f, %.6f) max(%.6f, %.6f)", + uvBounds.ptMin.x(), uvBounds.ptMin.y(), + uvBounds.ptMax.x(), uvBounds.ptMax.y()); - // 检查regionAreas是否计算正确 - for (const auto& entry : regionAreas) { - DEBUG_EXTRA("Region %d: area=%.6f, faces=%zu", - entry.first, entry.second, regionFaces[entry.first].size()); + // 创建虚拟面 + DEBUG_EXTRA("创建虚拟面..."); + + // 先计算非空网格数 + size_t nonEmptyCells = 0; + for (const auto& cell : grid) { + if (!cell.empty()) { + nonEmptyCells++; + } } - // 4. 创建虚拟面 - std::vector processedFaces(numFaces, false); - virtualFaceMap.clear(); - virtualFaceMap.reserve(numFaces); // 每个面单独处理 + virtualFaceMap.reserve(nonEmptyCells); - int createdVirtualFaces = 0; - int smallRegions = 0; - int uvDiscontinuousRegions = 0; + size_t totalFacesInClusters = 0; + size_t maxClusterSize = 0; + size_t minClusterSize = SIZE_MAX; - // 参数设置 - 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) { - int regionID = region.first; - const std::vector& faceList = region.second; - - DEBUG_EXTRA("Processing region %d with %zu faces", regionID, faceList.size()); - - // 检查区域面积 - float regionArea = regionAreas[regionID]; - - // 小区域:直接为每个面单独创建虚拟面 - if (regionArea < minRegionArea) { - DEBUG_EXTRA(" Small region (area=%.6f < %.6f), creating individual faces", - regionArea, minRegionArea); - smallRegions++; - - for (FIndex fid : faceList) { - // 添加调试代码 - // 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); + for (int i = 0; i < static_cast(grid.size()); ++i) { + const auto& cell = grid[i]; + if (cell.empty()) { continue; } - // 大区域:正常处理 - DEBUG_EXTRA(" Large region (area=%.6f), using region growing", regionArea); + size_t cellSize = cell.size(); + totalFacesInClusters += cellSize; + maxClusterSize = std::max(maxClusterSize, cellSize); + minClusterSize = std::min(minClusterSize, cellSize); - // 创建虚拟面列表 - std::vector regionVirtualFaces; - - // 遍历区域中的每个面片 - for (FIndex seedFace : faceList) { - // 添加调试代码 - // DEBUG_EXTRA("Processing seed face %u for virtual face creation", seedFace); - - // 检查面片数据 - 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 (cellSize > 1000) { + size_t numParts = (cellSize + 999) / 1000; // 向上取整 - 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(); + for (size_t part = 0; part < numParts; ++part) { + size_t start = part * 1000; + size_t end = std::min((part + 1) * 1000, cellSize); - // 获取相邻面片 - if (currentFace >= scene.mesh.faceFaces.size()) { - continue; - } + if (start >= end) continue; - const Mesh::FaceFaces& neighbors = scene.mesh.faceFaces[currentFace]; + VirtualFace vf; + vf.faces.reserve(end - start); + vf.faces.insert(vf.faces.end(), + cell.begin() + start, + cell.begin() + end); - 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); - } + // 计算属性 + CalculateVirtualFacePropertiesSafe(vf); + CalculateVirtualFaceUVBoundsSafe(vf); + + virtualFaceMap.push_back(std::move(vf)); } + } else { + VirtualFace vf; + vf.faces = cell; // 复制 - // 将虚拟面添加到区域虚拟面列表 - regionVirtualFaces.push_back(vf); + // 计算属性 + CalculateVirtualFacePropertiesSafe(vf); + CalculateVirtualFaceUVBoundsSafe(vf); - // 标记面片为已处理 - for (FIndex fid : vf.faces) { - if (fid < processedFaces.size()) { - processedFaces[fid] = true; - } - } - } - - // 将区域虚拟面添加到全局虚拟面列表 - for (const auto& vf : regionVirtualFaces) { - virtualFaceMap.push_back(vf); - } - - 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++; - } - unprocessedCount++; + virtualFaceMap.push_back(std::move(vf)); } } - if (unprocessedCount > 0) { - DEBUG_EXTRA(" Processed %d unassigned faces", unprocessedCount); - } + DEBUG_EXTRA("UV网格聚类完成,创建了 %zu 个UV簇", nonEmptyCells); + DEBUG_EXTRA("簇大小统计: 最小=%zu, 最大=%zu, 平均=%.1f", + minClusterSize, maxClusterSize, + static_cast(totalFacesInClusters) / nonEmptyCells); - DEBUG_EXTRA("Virtual face creation completed:"); - 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); - - // 统计合并比例 - 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); + DEBUG_EXTRA("虚拟面创建完成:"); + DEBUG_EXTRA(" - 总共创建的虚拟面数量: %zu", virtualFaceMap.size()); + DEBUG_EXTRA(" - 包含在虚拟面中的面片数: %zu", totalFacesInClusters); + DEBUG_EXTRA(" - 未处理的面片数: %zu", numFaces - totalFacesInClusters); if (virtualFaceMap.empty()) { - DEBUG_EXTRA("ERROR: No virtual faces created!"); + DEBUG_EXTRA("警告: 没有创建任何虚拟面"); return false; } - + + try { + size_t minFaces = SIZE_MAX, maxFaces = 0, totalFaces = 0; + float minArea = FLT_MAX, maxArea = 0.0f, totalArea = 0.0f; + + for (const VirtualFace& vf : virtualFaceMap) { + size_t numFacesInVF = vf.faces.size(); + minFaces = std::min(minFaces, numFacesInVF); + maxFaces = std::max(maxFaces, numFacesInVF); + totalFaces += numFacesInVF; + + if (vf.uvBounds.ptMax.x() >= vf.uvBounds.ptMin.x() && + vf.uvBounds.ptMax.y() >= vf.uvBounds.ptMin.y()) { + float width = vf.uvBounds.ptMax.x() - vf.uvBounds.ptMin.x(); + float height = vf.uvBounds.ptMax.y() - vf.uvBounds.ptMin.y(); + float area = width * height; + minArea = std::min(minArea, area); + maxArea = std::max(maxArea, area); + totalArea += area; + } else { + DEBUG_EXTRA("警告: 虚拟面UV边界无效"); + } + } + + DEBUG_EXTRA("虚拟面统计:"); + DEBUG_EXTRA(" - 每个虚拟面的面片数: 最小=%zu, 最大=%zu, 平均=%.1f", + minFaces, maxFaces, static_cast(totalFaces) / virtualFaceMap.size()); + + if (virtualFaceMap.size() > 0) { + DEBUG_EXTRA(" - 每个虚拟面的UV面积: 最小=%.6e, 最大=%.6e, 平均=%.6e", + minArea, maxArea, totalArea / virtualFaceMap.size()); + } + } catch (const std::exception& e) { + DEBUG_EXTRA("计算虚拟面统计时发生异常: %s", e.what()); + } catch (...) { + DEBUG_EXTRA("计算虚拟面统计时发生未知异常"); + } return true; } @@ -18240,6 +18261,8 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi } #endif + MeshTexture::VirtualFaceMap virtualFaceMap; + // assign the best view to each face { TD_TIMER_STARTD(); @@ -18260,8 +18283,58 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi } } + // 在LoadUV后添加UV坐标检查 + DEBUG_EXTRA("=== UV坐标质量检查 ==="); + DEBUG_EXTRA("UV坐标数量: %zu", mesh.faceTexcoords.size()); + DEBUG_EXTRA("面片数量: %zu", mesh.faces.size()); + + if (bUseExistingUV && !strUVMeshFileName.empty()) { + if (!texture.CreateVirtualFacesForExistingUV(virtualFaceMap)) { + DEBUG_EXTRA("Failed to create virtual faces"); + return false; + } + } + + if (mesh.faceTexcoords.size() >= 3) { + // 检查UV坐标范围 + AABB2f globalUVBounds; + bool firstUV = true; + int invalidCount = 0; + + for (size_t i = 0; i < mesh.faceTexcoords.size(); ++i) { + const TexCoord& uv = mesh.faceTexcoords[i]; + + if (!std::isfinite(uv.x) || !std::isfinite(uv.y)) { + invalidCount++; + continue; + } + + if (firstUV) { + globalUVBounds.ptMin = uv; + globalUVBounds.ptMax = uv; + firstUV = false; + } else { + globalUVBounds.Insert(uv); + } + } + + float uvWidth = globalUVBounds.ptMax.x() - globalUVBounds.ptMin.x(); + float uvHeight = globalUVBounds.ptMax.y() - globalUVBounds.ptMin.y(); + + DEBUG_EXTRA("全局UV边界: min(%.6f, %.6f) max(%.6f, %.6f)", + globalUVBounds.ptMin.x(), globalUVBounds.ptMin.y(), + globalUVBounds.ptMax.x(), globalUVBounds.ptMax.y()); + DEBUG_EXTRA("全局UV尺寸: %.6f x %.6f", uvWidth, uvHeight); + DEBUG_EXTRA("全局UV面积: %.6f", uvWidth * uvHeight); + DEBUG_EXTRA("无效UV坐标: %d", invalidCount); + + if (uvWidth < 0.01f || uvHeight < 0.01f) { + DEBUG_EXTRA("警告: UV坐标范围过小,可能导致纹理模糊!"); + } + } + // 使用虚拟面优化策略 - if (!texture.FaceViewSelectionWithVirtualFaces(minCommonCameras, fOutlierThreshold, fRatioDataSmoothness, nIgnoreMaskLabel, views, bUseExistingUV)) + if (!texture.FaceViewSelectionWithVirtualFaces(minCommonCameras, fOutlierThreshold, fRatioDataSmoothness, nIgnoreMaskLabel, views, bUseExistingUV, &virtualFaceMap)) return false; DEBUG_EXTRA("Virtual face view selection completed: %u faces (%s)", mesh.faces.size(), TD_TIMER_GET_FMT().c_str()); @@ -18293,7 +18366,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi } // 使用虚拟面优化的纹理生成 - if (!texture.TextureWithExistingUVVirtualFaces(views, nIgnoreMaskLabel, fOutlierThreshold, nTextureSizeMultiple, colEmpty, fSharpnessWeight)){ + if (!texture.TextureWithExistingUVVirtualFaces(views, nIgnoreMaskLabel, fOutlierThreshold, nTextureSizeMultiple, colEmpty, fSharpnessWeight, &virtualFaceMap)){ return false; } return true; @@ -18303,7 +18376,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi { TD_TIMER_STARTD(); if (!texture.GenerateTextureWithVirtualFaces(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, - colEmpty, fSharpnessWeight, maxTextureSize, baseFileName, bOriginFaceview, this)) + colEmpty, fSharpnessWeight, maxTextureSize, baseFileName, bOriginFaceview, this, &virtualFaceMap)) { return false; }