From 56ad2c49cbd365b75a04c447c2d42437d9d4e158 Mon Sep 17 00:00:00 2001 From: hesuicong Date: Thu, 23 Jul 2026 09:43:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/MVS/SceneTexture.cpp | 137 +++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 77 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index cfc9951..73efd70 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -18717,99 +18717,82 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi } #endif - // assign the best view to each face + // ========== 视图选择总入口 ========== { TD_TIMER_STARTD(); - if (bOriginFaceview) - { - // 使用原始面片视图选择 + if (bOriginFaceview) { + // 1. 原始面片模式 if (!texture.FaceViewSelection(minCommonCameras, fOutlierThreshold, fRatioDataSmoothness, nIgnoreMaskLabel, views)) return false; - } - else - { - if (bUseExistingUV && !strUVMeshFileName.empty()) { - VERBOSE("1faceTexcoords.size=%d, faces.size=%d", mesh.faceTexcoords.size(), mesh.faces.size() * 3); - // 使用预计算UV模式 - if (!mesh.Load(MAKE_PATH_SAFE(strUVMeshFileName), true)) { - VERBOSE("error: cannot load mesh file with UV coordinates"); - return false; - } - } - - // 使用虚拟面优化策略 - if (!texture.FaceViewSelectionWithVirtualFaces(minCommonCameras, fOutlierThreshold, fRatioDataSmoothness, nIgnoreMaskLabel, views, bUseExistingUV)) - return false; + } else if (bUseExistingUV && !strUVMeshFileName.empty()) { + // 2. 已有UV专用模式(只走这里,不要后面的重复分支) + VERBOSE("faceTexcoords.size=%d, faces.size=%d", mesh.faceTexcoords.size(), mesh.faces.size() * 3); - DEBUG_EXTRA("Virtual face view selection completed: %u faces (%s)", mesh.faces.size(), TD_TIMER_GET_FMT().c_str()); - } - DEBUG_EXTRA("Assigning the best view to each face completed: %u faces (%s)", mesh.faces.size(), TD_TIMER_GET_FMT().c_str()); - } - - // 检查UV有效性 - // mesh.CheckUVValid(); - - DEBUG_EXTRA("TextureMesh bUseExistingUV=%d, UVMeshFile=%s", bUseExistingUV, strUVMeshFileName.c_str()); - - // 处理已有UV的情况 - if (bUseExistingUV && !strUVMeshFileName.empty()) { - MeshTexture texture(*this, nResolutionLevel, nMinResolution); + // 加载带UV的mesh + if (!mesh.Load(MAKE_PATH_SAFE(strUVMeshFileName), true)) { + VERBOSE("error: cannot load mesh file with UV coordinates"); + return false; + } - // ✅ 只用“纯可见性”,绝不碰 FaceViewSelection - if (!texture.ComputePureFaceVisibility( - fOutlierThreshold, - nIgnoreMaskLabel, - views)) { - return false; - } + // 纯可见性计算(初始化faceNeighbors) + if (!texture.ComputePureFaceVisibility(fOutlierThreshold, nIgnoreMaskLabel, views)) { + // ❗ 兜底:如果ComputePureFaceVisibility没初始化faceNeighbors,手动填充 + if (texture.faceNeighbors.empty()) { + texture.faceNeighbors.resize(mesh.faces.size()); + for (FIndex fid = 0; fid < (FIndex)mesh.faces.size(); ++fid) { + if (!views.empty()) { + texture.faceNeighbors[fid].insert(texture.faceNeighbors[fid].end(), views.begin(), views.end()); + } else { + for (IIndex vid = 0; vid < (IIndex)images.size(); ++vid) + texture.faceNeighbors[fid].push_back(vid); + } + } + DEBUG_EXTRA("Forced fill faceNeighbors for %zu faces", mesh.faces.size()); + } + return false; + } - // ✅ 现在 faces 没动过,faceNeighbors 是对齐的 - MeshTexture::VirtualFaceMap virtualFaceMap; - if (!texture.CreateVirtualFacesForExistingUV(virtualFaceMap)) { - return false; - } + // 创建虚拟面(1:1映射) + MeshTexture::VirtualFaceMap virtualFaceMap; + if (!texture.CreateVirtualFacesForExistingUV(virtualFaceMap)) return false; - if (!texture.SelectBestViewsForVirtualFaces( - virtualFaceMap, - 1, // 单视图就够了 - fOutlierThreshold, - fRatioDataSmoothness, - nIgnoreMaskLabel, - views)) { - return false; - } + // 选最佳视图(带patch一致性) + if (!texture.SelectBestViewsForVirtualFaces( + virtualFaceMap, 1, fOutlierThreshold, fRatioDataSmoothness, nIgnoreMaskLabel, views)) + return false; - // 直接光栅化 - Mesh::Image8U3Arr textures; - if (!texture.RasterizeVirtualFaces( - virtualFaceMap, - texture.faceViews, - texture.faceViewWeights, - nTextureSizeMultiple, - colEmpty, - textures)) { - return false; - } + // 直接光栅化(不需要生成图集) + Mesh::Image8U3Arr textures; + if (!texture.RasterizeVirtualFaces( + virtualFaceMap, texture.faceViews, texture.faceViewWeights, + nTextureSizeMultiple, colEmpty, textures)) + return false; - mesh.texturesDiffuse = std::move(textures); - return true; - } + mesh.texturesDiffuse = std::move(textures); + DEBUG_EXTRA("Existing UV texturing completed: %u faces (%s)", mesh.faces.size(), TD_TIMER_GET_FMT().c_str()); + return true; // 直接返回,不走后面的图集逻辑 + } else { + // 3. 通用虚拟面模式(无预计算UV) + if (!texture.FaceViewSelectionWithVirtualFaces( + minCommonCameras, fOutlierThreshold, fRatioDataSmoothness, + nIgnoreMaskLabel, views, bUseExistingUV)) + return false; + DEBUG_EXTRA("Virtual face view selection completed: %u faces (%s)", mesh.faces.size(), TD_TIMER_GET_FMT().c_str()); + } + DEBUG_EXTRA("Assigning the best view to each face completed: %u faces (%s)", mesh.faces.size(), TD_TIMER_GET_FMT().c_str()); + } - // generate the texture image and atlas + // ========== 非UV模式:生成纹理图集 ========== { TD_TIMER_STARTD(); - if (!texture.GenerateTextureWithVirtualFaces(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, - colEmpty, fSharpnessWeight, maxTextureSize, baseFileName, bOriginFaceview, this)) - { + if (!texture.GenerateTextureWithVirtualFaces( + bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, + colEmpty, fSharpnessWeight, maxTextureSize, baseFileName, bOriginFaceview, this)) return false; - } - DEBUG_EXTRA("Generating texture atlas and image completed: %u patches, %u image size, %u textures (%s)", - texture.texturePatches.size(), mesh.texturesDiffuse[0].width(), mesh.texturesDiffuse.size(), TD_TIMER_GET_FMT().c_str()); + DEBUG_EXTRA("Generating texture atlas completed: %u textures (%s)", + mesh.texturesDiffuse.size(), TD_TIMER_GET_FMT().c_str()); } - // 最终UV检查 - // mesh.CheckUVValid(); - return true; } // TextureMesh