From d95c2fc8ff8a9d390b8cd22a645a305795c8847a Mon Sep 17 00:00:00 2001 From: hesuicong Date: Fri, 10 Jul 2026 16:53:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=95=E5=83=8F=E7=B4=A0=E9=87=87=E6=A0=B7?= =?UTF-8?q?=E6=B8=85=E6=99=B0=E5=8C=96=E4=B8=AD=E9=97=B4=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/MVS/SceneTexture.cpp | 1142 ++++++++++++++----------------------- 1 file changed, 426 insertions(+), 716 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 9e90589..80ec372 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -593,9 +593,6 @@ 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; @@ -608,16 +605,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, VirtualFaceMap* pVirtualFaceMap); + const IIndexArr& views, bool bUseExistingUV); bool GenerateTextureWithVirtualFaces(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, float fSharpnessWeight, int maxTextureSize, - const SEACAVE::String& baseFileName, bool bOriginFaceview, Scene* pScene, VirtualFaceMap* pVirtualFaceMap); + const SEACAVE::String& baseFileName, bool bOriginFaceview, Scene* pScene); bool GenerateTextureWithVirtualFacesInternal(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, float fSharpnessWeight, int maxTextureSize, - const SEACAVE::String& baseFileName, Scene* pScene, VirtualFaceMap* pVirtualFaceMap); + const SEACAVE::String& baseFileName, Scene* pScene); bool ConvertVectorToVirtualFaceDataArr(const std::vector& src, VirtualFaceDataArr& dst); bool InitializeEmptyVirtualFaceDataArr(const VirtualFaceMap& virtualFaceMap, VirtualFaceDataArr& vfDataArr); bool SelectBestViewsForVirtualFaces(VirtualFaceMap& virtualFaceMap, @@ -631,8 +628,18 @@ public: std::vector> faceNeighbors; VirtualFaceGeometryArr m_virtualFaceGeometries; - mutable VirtualFaceMap m_cachedVirtualFaceMap; - mutable bool m_virtualFaceMapCached = false; + inline Point3f NormalizePoint3(Point3f& p) + { + const float l = std::sqrt( + p.x * p.x + + p.y * p.y + + p.z * p.z + ); + if (l > FLT_EPSILON) + p *= 1.0f / l; + + return p; + } uint32_t FindNearestPatchForFaces(const std::vector& faceIndices); void FixIsolatedComponents(); @@ -664,20 +671,28 @@ public: ); bool TextureWithExistingUVVirtualFaces(const IIndexArr& views, int nIgnoreMaskLabel, float fOutlierThreshold, unsigned nTextureSizeMultiple, - Pixel8U colEmpty, float fSharpnessWeight, VirtualFaceMap* pVirtualFaceMap); - void AnalyzeUVDistribution(); + Pixel8U colEmpty, float fSharpnessWeight); bool CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap); - bool CreateVirtualFacesForExistingUVImpl(VirtualFaceMap& virtualFaceMap); - void CalculateVirtualFaceUVBoundsSafe(VirtualFace& vf); - void CalculateVirtualFacePropertiesSafe(VirtualFace& vf); - bool IsFaceUVValid(FIndex fid) const; - - // 获取面片的UV中心 - TexCoord GetFaceUVCenter(FIndex fid) const; - - bool CheckUVContinuityForRegion(const std::vector& faceList); - bool CheckUVContinuityForRegion(const MVS::Mesh::FaceIdxArr& faceList); bool CheckUVContinuity(const std::vector& faceList); + + struct TexelViewInfo { + IIndex best_view_id; // 最佳视图ID + float best_weight; // 最佳权重 + Point2f best_proj; // 最佳投影坐标 + std::vector candidate_views; // 候选视图列表 + }; + + bool SelectBestViewForTexel(const Point3f& worldPos, + const Normal& normal, + const std::vector& candidateViews, + const std::vector& viewWeights, + TexelViewInfo& result); + + float CalculateViewScale(const Camera& cam, const Point3d& pos); + + bool GetWorldPositionAndNormal(const Point2f& texCoord, + Point3f& worldPos, Normal& normal, FIndex& faceID); + Mesh::Image8U3Arr GenerateMultiViewTextureAtlasWithVirtualFaces( const VirtualFaceMap& virtualFaceMap, const VirtualFaceDataArr& virtualFaceDatas, // 改为 VirtualFaceDataArr @@ -1428,18 +1443,9 @@ 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(); @@ -1553,65 +1559,36 @@ bool MeshTexture::CalculateVirtualFaceProperties(VirtualFace& vf) { } bool MeshTexture::CalculateVirtualFaceUVBounds(VirtualFace& vf) { - if (vf.faces.empty()) { - vf.uvBounds = AABB2f(); - return false; + if (vf.faces.empty() || !scene.mesh.HasTexture()) { + // 修正1: 不使用 ZERO,而是创建一个空的边界框 + vf.uvBounds = AABB2f(); // 使用默认构造函数 + return false; // 返回 false } - // if (!scene.mesh.HasTexture() || scene.mesh.faceTexcoords.empty()) { - // vf.uvBounds = AABB2f(); - // return false; - // } - + const TexCoord* texcoords = scene.mesh.faceTexcoords.data(); bool first = true; - AABB2f bounds; for (FIndex faceIdx : vf.faces) { - if (faceIdx * 3 + 2 >= scene.mesh.faceTexcoords.size()) { - continue; - } - for (int i = 0; i < 3; ++i) { - const TexCoord& uv = scene.mesh.faceTexcoords[faceIdx * 3 + i]; - - if (!std::isfinite(uv.x) || !std::isfinite(uv.y)) { - continue; - } - + const TexCoord& uv = texcoords[faceIdx * 3 + i]; if (first) { - bounds.ptMin = uv; - bounds.ptMax = uv; + // 修正2: 使用 ptMin 和 ptMax + vf.uvBounds.ptMin = uv; + vf.uvBounds.ptMax = uv; first = false; } else { - bounds.Insert(uv); + vf.uvBounds.Insert(uv); } } } - if (first) { - vf.uvBounds = AABB2f(); - return false; - } - - vf.uvBounds = bounds; - float width = bounds.ptMax.x() - bounds.ptMin.x(); - float height = bounds.ptMax.y() - bounds.ptMin.y(); - float area = width * height; - - // 记录统计信息 - if (area < 1e-6f) { - DEBUG_EXTRA("虚拟面UV面积: %.6e (尺寸: %.6f x %.6f), 面片数: %zu", - area, width, height, vf.faces.size()); - } - - return true; + return !first; // 如果至少有一个UV坐标,则返回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]; @@ -4534,120 +4511,6 @@ 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()) { @@ -14384,7 +14247,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, VirtualFaceMap* pVirtualFaceMap) + Pixel8U colEmpty, float fSharpnessWeight) { DEBUG_EXTRA("TextureWithExistingUVVirtualFaces with multi-view blending"); TD_TIMER_START(); @@ -14404,14 +14267,16 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int // 2. 创建虚拟面 DEBUG_EXTRA("Creating virtual faces for existing UV texture mapping..."); VirtualFaceMap virtualFaceMap; - if (pVirtualFaceMap) { - virtualFaceMap = *pVirtualFaceMap; // 使用传入的虚拟面 - } else { - if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { - DEBUG_EXTRA("Failed to create virtual faces for existing UV"); - return false; - } - } + 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); + } + } DEBUG_EXTRA("Created %zu virtual faces (original faces: %zu)", virtualFaceMap.size(), faces.size()); @@ -14532,21 +14397,18 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int bool MeshTexture::FaceViewSelectionWithVirtualFaces(unsigned minCommonCameras, float fOutlierThreshold, float fRatioDataSmoothness, int nIgnoreMaskLabel, - const IIndexArr& views, bool bUseExistingUV, VirtualFaceMap* pVirtualFaceMap) + const IIndexArr& views, bool bUseExistingUV) { DEBUG_EXTRA("Performing face view selection with virtual faces (bUseExistingUV=%d)", bUseExistingUV); if (bUseExistingUV) { // 使用现有UV的虚拟面选择策略 VirtualFaceMap virtualFaceMap; - if (pVirtualFaceMap) { - virtualFaceMap = *pVirtualFaceMap; // 使用传入的虚拟面 - } else { - if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { - DEBUG_EXTRA("Failed to create virtual faces for existing UV"); - return false; - } + if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { + DEBUG_EXTRA("Failed to create virtual faces for existing UV"); + return false; } + DEBUG_EXTRA("Created %zu virtual faces", virtualFaceMap.size()); // 为虚拟面选择最佳视图 @@ -14566,7 +14428,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, VirtualFaceMap* pVirtualFaceMap) + const SEACAVE::String& baseFileName, bool bOriginFaceview, Scene* pScene) { DEBUG_EXTRA("Generating texture with virtual faces (bOriginFaceview=%d)", bOriginFaceview); @@ -14582,7 +14444,7 @@ bool MeshTexture::GenerateTextureWithVirtualFaces(bool bGlobalSeamLeveling, bool return GenerateTextureWithVirtualFacesInternal(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, colEmpty, fSharpnessWeight, maxTextureSize, - baseFileName, pScene, pVirtualFaceMap); + baseFileName, pScene); } } @@ -14707,7 +14569,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, VirtualFaceMap* pVirtualFaceMap) + const SEACAVE::String& baseFileName, Scene* pScene) { DEBUG_EXTRA("Generating texture with virtual faces internal method"); @@ -14732,14 +14594,11 @@ bool MeshTexture::GenerateTextureWithVirtualFacesInternal(bool bGlobalSeamLeveli // 2. 创建虚拟面 VirtualFaceMap virtualFaceMap; - if (pVirtualFaceMap) { - virtualFaceMap = *pVirtualFaceMap; // 使用传入的虚拟面 - } else { - if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { - DEBUG_EXTRA("Failed to create virtual faces for existing UV"); - return false; - } - } + if (!CreateVirtualFacesForExistingUV(virtualFaceMap)) { + DEBUG_EXTRA("Failed to create virtual faces"); + return false; + } + // 3. 为虚拟面选择最佳视图 if (!SelectBestViewsForVirtualFaces(virtualFaceMap, 1, 0.0f, 1.0f, -1, IIndexArr())) { DEBUG_EXTRA("Failed to select best views for virtual faces"); @@ -14813,526 +14672,274 @@ 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]++; - } + if (scene.mesh.vertices.empty()) { + DEBUG_EXTRA("ERROR: Mesh has no vertices!"); + 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; - } - } + // 验证faces数组的大小 + size_t numFaces = scene.mesh.faces.size(); + size_t numVertices = scene.mesh.vertices.size(); + size_t numFaceTexcoords = scene.mesh.faceTexcoords.size(); - 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); + DEBUG_EXTRA("Number of faces: %zu", numFaces); + DEBUG_EXTRA("Number of vertices: %zu", numVertices); + DEBUG_EXTRA("Number of texture coordinates: %zu", numFaceTexcoords); - // 检查UV重叠情况 - int overlappingUVs = 0; - for (int count : uvGrid) { - if (count > 1) { - overlappingUVs += count; - } + // 关键检查:必须有纹理坐标才能使用此方法 + if (numFaceTexcoords == 0) { + DEBUG_EXTRA("ERROR: Mesh has no texture coordinates. Cannot create virtual faces for existing UV."); + return false; } - DEBUG_EXTRA(" - UV重叠情况: %d 个UV坐标在网格中重叠", overlappingUVs); + if (numFaceTexcoords < numFaces * 3) { + DEBUG_EXTRA("ERROR: Not enough UV coordinates! Expected %zu (faces * 3), have %zu", + numFaces * 3, numFaceTexcoords); + return false; + } - // 检查每个面片的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); + // 验证面片索引 + DEBUG_EXTRA("Validating face indices..."); + for (size_t i = 0; i < std::min(numFaces, static_cast(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 (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; + if (valid) { + DEBUG_EXTRA("Face %zu: vertices [%u, %u, %u] - OK", + i, face[0], face[1], face[2]); + } } - - // 缓存结果 - m_cachedVirtualFaceMap = virtualFaceMap; - m_virtualFaceMapCached = true; - return true; -} -// 检查面片的UV是否有效 -bool MeshTexture::IsFaceUVValid(FIndex fid) const { - if (fid >= scene.mesh.faces.size()) { - return false; + + // 验证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.faceTexcoords.size() <= fid * 3 + 2) { - 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; + } } - // 检查UV坐标是否有效(非NaN、有限值) - for (int i = 0; i < 3; ++i) { - const TexCoord& uv = scene.mesh.faceTexcoords[fid * 3 + i]; - if (std::isnan(uv.x) || std::isnan(uv.y) || - !std::isfinite(uv.x) || !std::isfinite(uv.y)) { + 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; } } - return true; -} - -// 获取面片的UV中心 -TexCoord MeshTexture::GetFaceUVCenter(FIndex fid) const { - TexCoord center(0, 0); + std::vector processedFaces(numFaces, false); - if (!IsFaceUVValid(fid)) { - return center; - } + // 3. 基于曲率分割网格 + DEBUG_EXTRA("Segmenting mesh based on curvature..."); + Mesh::FaceIdxArr regionMap; - for (int i = 0; i < 3; ++i) { - const TexCoord& uv = scene.mesh.faceTexcoords[fid * 3 + i]; - center.x += uv.x; - center.y += uv.y; + 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); + return false; + } + } catch (const std::exception& e) { + DEBUG_EXTRA("ERROR during mesh segmentation: %s", e.what()); + return false; } - center.x /= 3.0f; - center.y /= 3.0f; - - return center; -} - -// 计算虚拟面的属性(安全版本) -void MeshTexture::CalculateVirtualFacePropertiesSafe(VirtualFace& vf) { - // 与之前的 CalculateVirtualFaceProperties 类似,但更安全 - Point3f centerSum(0, 0, 0); - Point3f normalSum(0, 0, 0); - float areaSum = 0.0f; - int validFaces = 0; + // 4. 统计每个区域的面积 + DEBUG_EXTRA("Calculating region areas..."); + std::unordered_map regionAreas; - for (FIndex fid : vf.faces) { + 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]; + + // 验证面片索引 if (fid >= scene.mesh.faces.size()) { - continue; // 跳过无效索引 + 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]; - // 检查顶点索引是否有效 - bool validVertices = true; + // 验证顶点索引 for (int i = 0; i < 3; ++i) { if (face[i] >= scene.mesh.vertices.size()) { - validVertices = false; - break; + 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 (!validVertices) { - continue; // 跳过无效的面 - } - - // 计算面中心 - 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 faceAreaSq = faceNormal.dot(faceNormal); - if (faceAreaSq > 0) { - float faceArea = sqrt(faceAreaSq); - - // 归一化法向量 - faceNormal /= faceArea; - faceArea *= 0.5f; // 三角形面积是平行四边形的一半 - - // 加权平均 - centerSum += faceCenter * faceArea; - normalSum += faceNormal * faceArea; - areaSum += faceArea; - validFaces++; - } - } - - if (validFaces > 0 && areaSum > 0) { - vf.center = centerSum / areaSum; + 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 + ); - // 手动计算法向量长度并归一化 - float normalLengthSq = normalSum.dot(normalSum); - if (normalLengthSq > 0) { - float normalLength = sqrt(normalLengthSq); - vf.normal = normalSum / normalLength; - } else { - vf.normal = Point3f(0, 0, 1); // 默认法向量 - } + float area = 0.5f * std::sqrt( + crossProd.x * crossProd.x + + crossProd.y * crossProd.y + + crossProd.z * crossProd.z + ); - 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) { - vf.uvBounds.ptMin = TexCoord(FLT_MAX, FLT_MAX); - vf.uvBounds.ptMax = TexCoord(-FLT_MAX, -FLT_MAX); - - bool hasValidUV = false; - - for (FIndex fid : vf.faces) { - if (!IsFaceUVValid(fid)) { - continue; + if (area < 0) { + DEBUG_EXTRA("WARNING: Negative area calculated for face %u: %f", fid, area); + area = 0.0f; } - for (int i = 0; i < 3; ++i) { - const TexCoord& uv = scene.mesh.faceTexcoords[fid * 3 + i]; - - // 处理UV环绕 - TexCoord wrappedUV = uv; - - // 使用 .x() 和 .y() 函数访问和修改分量 - float u = wrappedUV.x - floor(wrappedUV.x); - float v = wrappedUV.y - floor(wrappedUV.y); - if (u < 0) u += 1.0f; - if (v < 0) v += 1.0f; - - // 使用 .x() 和 .y() 函数设置值 - wrappedUV.x = u; - wrappedUV.y = v; - - // 更新最小边界 - vf.uvBounds.ptMin.x() = std::min(vf.uvBounds.ptMin.x(), wrappedUV.x); - vf.uvBounds.ptMin.y() = std::min(vf.uvBounds.ptMin.y(), wrappedUV.y); - - // 更新最大边界 - vf.uvBounds.ptMax.x() = std::max(vf.uvBounds.ptMax.x(), wrappedUV.x); - vf.uvBounds.ptMax.y() = std::max(vf.uvBounds.ptMax.y(), wrappedUV.y); - - hasValidUV = true; - } - } - - if (!hasValidUV) { - vf.uvBounds.ptMin = TexCoord(0, 0); - vf.uvBounds.ptMax = TexCoord(1, 1); - } -} - -bool MeshTexture::CreateVirtualFacesForExistingUVImpl(VirtualFaceMap& virtualFaceMap) { - DEBUG_EXTRA("=== 创建现有UV映射的虚拟面 ==="); - - if (scene.mesh.faceTexcoords.empty()) { - DEBUG_EXTRA("错误: 网格没有UV坐标数据"); - return false; - } - - 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; + regionAreas[region] += area; } - DEBUG_EXTRA("开始UV聚类,面片数: %zu", numFaces); + DEBUG_EXTRA("Region area calculation completed, found %zu regions", regionAreas.size()); - // 使用简单的哈希聚类 - const int gridSize = 32; - std::vector> grid(gridSize * gridSize); - - // 预分配内存 - size_t totalValidFaces = 0; + // 5. 为每个区域收集面片 + DEBUG_EXTRA("Grouping faces by region..."); + std::unordered_map> regionFaces; for (FIndex fid = 0; fid < numFaces; ++fid) { - if (IsFaceUVValid(fid)) { - totalValidFaces++; - } + int region = regionMap[fid]; + regionFaces[region].push_back(fid); } - // 为每个网格预分配内存 - size_t avgPerCell = totalValidFaces / (gridSize * gridSize) + 1; - for (auto& cell : grid) { - cell.reserve(avgPerCell); - } + DEBUG_EXTRA("Found %zu regions with faces", regionFaces.size()); - // 分配面片到网格 - DEBUG_EXTRA("创建面片到UV网格的映射 (网格大小: %dx%d)...", gridSize, gridSize); + // 6. 创建虚拟面 + DEBUG_EXTRA("Creating virtual faces..."); + virtualFaceMap.clear(); + virtualFaceMap.reserve(regionFaces.size()); - AABB2f uvBounds; - bool hasBounds = false; + int regionCount = 0; + int smallRegionCount = 0; + int uvDiscontinuousCount = 0; + int createdVirtualFaces = 0; - for (FIndex fid = 0; fid < numFaces; ++fid) { - if (!IsFaceUVValid(fid)) { - continue; - } + for (const auto& region : regionFaces) { + regionCount++; + int regionID = region.first; + const std::vector& faceList = region.second; - TexCoord center = GetFaceUVCenter(fid); - - // 更新UV边界 - if (!hasBounds) { - uvBounds.ptMin = center; - uvBounds.ptMax = center; - hasBounds = true; - } else { - uvBounds.Insert(center); + if (regionCount % 100 == 0) { + DEBUG_EXTRA(" Processing region %d/%d (%zu faces)", regionCount, regionFaces.size(), faceList.size()); } - // 确保在[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; - - int gridX = static_cast(u * gridSize); - int gridY = static_cast(v * gridSize); - - // 边界检查 - gridX = std::max(0, std::min(gridX, gridSize - 1)); - gridY = std::max(0, std::min(gridY, gridSize - 1)); - - int cellIdx = gridY * gridSize + gridX; - if (cellIdx >= 0 && cellIdx < static_cast(grid.size())) { - grid[cellIdx].push_back(fid); - } - - if (fid % 200000 == 0 && fid > 0) { - DEBUG_EXTRA("已处理 %u/%zu 个面片", fid, numFaces); - } - } - - DEBUG_EXTRA("UV中心点分布范围: min(%.6f, %.6f) max(%.6f, %.6f)", - uvBounds.ptMin.x(), uvBounds.ptMin.y(), - uvBounds.ptMax.x(), uvBounds.ptMax.y()); - - // 创建虚拟面 - DEBUG_EXTRA("创建虚拟面..."); - - // 先计算非空网格数 - size_t nonEmptyCells = 0; - for (const auto& cell : grid) { - if (!cell.empty()) { - nonEmptyCells++; - } - } - - virtualFaceMap.reserve(nonEmptyCells); - - size_t totalFacesInClusters = 0; - size_t maxClusterSize = 0; - size_t minClusterSize = SIZE_MAX; - - for (int i = 0; i < static_cast(grid.size()); ++i) { - const auto& cell = grid[i]; - if (cell.empty()) { - continue; - } - - size_t cellSize = cell.size(); - totalFacesInClusters += cellSize; - maxClusterSize = std::max(maxClusterSize, cellSize); - minClusterSize = std::min(minClusterSize, cellSize); - - // 如果簇太大,分割成多个虚拟面 - if (cellSize > 1000) { - size_t numParts = (cellSize + 999) / 1000; // 向上取整 + // 检查区域面积是否足够大 + float regionArea = regionAreas[regionID]; + if (regionArea < 0.001f) { // 面积阈值 + DEBUG_EXTRA(" Region %d is too small (area: %f), using individual faces", regionID, regionArea); + smallRegionCount++; - for (size_t part = 0; part < numParts; ++part) { - size_t start = part * 1000; - size_t end = std::min((part + 1) * 1000, cellSize); - - if (start >= end) continue; - - VirtualFace vf; - vf.faces.reserve(end - start); - - // 修复:使用循环添加,因为 cList 没有接受迭代器的 insert 方法 - for (size_t idx = start; idx < end; ++idx) { - vf.faces.push_back(cell[idx]); - } - - // 计算属性 - CalculateVirtualFacePropertiesSafe(vf); - CalculateVirtualFaceUVBoundsSafe(vf); - - virtualFaceMap.push_back(std::move(vf)); - } - } else { - VirtualFace vf; - vf.faces.reserve(cellSize); - - // 修复:使用循环添加 - for (FIndex fid : cell) { - vf.faces.push_back(fid); + // 区域太小,不创建虚拟面 + for (FIndex fid : faceList) { + virtualFaceMap.push_back(VirtualFace()); + virtualFaceMap.back().faces.push_back(fid); } - - // 计算属性 - CalculateVirtualFacePropertiesSafe(vf); - CalculateVirtualFaceUVBoundsSafe(vf); - - virtualFaceMap.push_back(std::move(vf)); + continue; } - } - - DEBUG_EXTRA("UV网格聚类完成,创建了 %zu 个UV簇", nonEmptyCells); - DEBUG_EXTRA("簇大小统计: 最小=%zu, 最大=%zu, 平均=%.1f", - minClusterSize, maxClusterSize, - static_cast(totalFacesInClusters) / nonEmptyCells); - - DEBUG_EXTRA("虚拟面创建完成:"); - DEBUG_EXTRA(" - 总共创建的虚拟面数量: %zu", virtualFaceMap.size()); - DEBUG_EXTRA(" - 包含在虚拟面中的面片数: %zu", totalFacesInClusters); - DEBUG_EXTRA(" - 未处理的面片数: %zu", numFaces - totalFacesInClusters); - - if (virtualFaceMap.empty()) { - 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; + + // 检查UV连续性 + if (!CheckUVContinuity(faceList)) { + DEBUG_EXTRA(" Region %d has discontinuous UV, using individual faces", regionID); + uvDiscontinuousCount++; - 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边界无效"); + // UV不连续,保持原始面片 + for (FIndex fid : faceList) { + virtualFaceMap.push_back(VirtualFace()); + virtualFaceMap.back().faces.push_back(fid); } + continue; } - DEBUG_EXTRA("虚拟面统计:"); - DEBUG_EXTRA(" - 每个虚拟面的面片数: 最小=%zu, 最大=%zu, 平均=%.1f", - minFaces, maxFaces, static_cast(totalFaces) / virtualFaceMap.size()); + // 创建虚拟面 + VirtualFace vf; + vf.faces = faceList; - if (virtualFaceMap.size() > 0) { - DEBUG_EXTRA(" - 每个虚拟面的UV面积: 最小=%.6e, 最大=%.6e, 平均=%.6e", - minArea, maxArea, totalArea / virtualFaceMap.size()); + // 计算虚拟面的中心、法线和面积 + 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; } - } catch (const std::exception& e) { - DEBUG_EXTRA("计算虚拟面统计时发生异常: %s", e.what()); - } catch (...) { - DEBUG_EXTRA("计算虚拟面统计时发生未知异常"); - } - - 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; + + // 计算虚拟面的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); } + continue; } + + virtualFaceMap.push_back(vf); + createdVirtualFaces++; } - return true; -} - -bool MeshTexture::CheckUVContinuityForRegion(const MVS::Mesh::FaceIdxArr& faceList) { - if (faceList.size() <= 1) return true; + 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(" Created virtual faces: %d", createdVirtualFaces); + DEBUG_EXTRA(" Total virtual faces (including individual faces): %zu", virtualFaceMap.size()); - 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; - } - } + if (virtualFaceMap.empty()) { + DEBUG_EXTRA("ERROR: No virtual faces created!"); + return false; } return true; @@ -15426,6 +15033,125 @@ float MeshTexture::TriangleArea( ); } +bool MeshTexture::GetWorldPositionAndNormal( + const Point2f& texCoord, + Point3f& worldPos, + Normal& normal, + FIndex& faceID) +{ + const auto& faces = scene.mesh.faces; + const auto& uvs = scene.mesh.faceTexcoords; + const auto& verts = scene.mesh.vertices; + const auto& norms = scene.mesh.faceNormals; + + const size_t numFaces = faces.size(); + + // 遍历所有面片(可优化为 UV atlas 分区索引) + for (FIndex fid = 0; fid < numFaces; ++fid) { + const TexCoord& uv0 = uvs[fid * 3 + 0]; + const TexCoord& uv1 = uvs[fid * 3 + 1]; + const TexCoord& uv2 = uvs[fid * 3 + 2]; + + // 重心坐标 + Point3f bary; + if (!PointInTriangle(texCoord, uv0, uv1, uv2, bary)) + continue; + + // 命中面片 + faceID = fid; + + const Mesh::Face& f = faces[fid]; + + // 插值世界坐标 + worldPos = + verts[f[0]] * bary.x + + verts[f[1]] * bary.y + + verts[f[2]] * bary.z; + + // 法线选择策略(⚠️这里是关键) + if (!norms.empty() && fid < norms.size()) { + // ✅ 使用面法线(RC 风格,避免法线混合带来的模糊) + normal = norms[fid]; + } else { + // fallback:叉乘计算 + const Point3f& v0 = verts[f[0]]; + const Point3f& v1 = verts[f[1]]; + const Point3f& v2 = verts[f[2]]; + Point3f faceNormal = (v1 - v0).cross(v2 - v0); + normal = NormalizePoint3(faceNormal); + } + + return true; + } + //*/ + + return false; +} + +// 计算视图缩放因子 +float MeshTexture::CalculateViewScale(const Camera& cam, const Point3d& pos) { + // ✅ 全部使用 double + Point2d proj = cam.ProjectPointP(pos); + // Point2d proj_dx = cam.ProjectPointP(pos + Point3d(0.01, 0.0, 0.0)); + // Point2d proj_dy = cam.ProjectPointP(pos + Point3d(0.0, 0.01, 0.0)); + + // const double pixelArea = std::abs( + // (proj_dx.x - proj.x) * (proj_dy.y - proj.y) - + // (proj_dx.y - proj.y) * (proj_dy.x - proj.x) + // ); + + // // ✅ 返回尺度权重 + // return static_cast(std::min(1.0, pixelArea / 4.0)); + return 0.0f; +} + +bool MeshTexture::SelectBestViewForTexel(const Point3f& worldPos, + const Normal& normal, + const std::vector& candidateViews, + const std::vector& viewWeights, + TexelViewInfo& result) { + result.best_weight = -1.0f; + + for (size_t i = 0; i < candidateViews.size(); ++i) { + const IIndex viewId = candidateViews[i]; + const Image& img = images[viewId]; + + // 1. 投影验证 + Point2f proj = ProjectPointWithAutoCorrection(img.camera, worldPos, img); + if (!ValidateProjection(worldPos, img, proj) || + !img.image.isInside(proj) || + !img.camera.IsInFront(worldPos)) { + continue; + } + + // 2. 计算视角权重(关键:使用真实视角角度) + Point3f camCenter( + static_cast(img.camera.C.x), + static_cast(img.camera.C.y), + static_cast(img.camera.C.z) + ); + + Point3f viewDir = camCenter - worldPos; + + viewDir = NormalizePoint3(viewDir); + float cosAngle = normal.dot(viewDir); + + // 3. 计算尺度权重(避免远处视图的模糊) + float scale = CalculateViewScale(img.camera, worldPos); + + // 4. 综合评分 + float score = viewWeights[i] * cosAngle * scale; + + if (score > result.best_weight) { + result.best_weight = score; + result.best_view_id = viewId; + result.best_proj = proj; + } + } + + return result.best_weight > 0.1f; +} + Mesh::Image8U3Arr MeshTexture::GenerateMultiViewTextureAtlasWithVirtualFaces( const VirtualFaceMap& virtualFaceMap, const VirtualFaceDataArr& virtualFaceDatas, // 这个参数现在不被使用,但保留以保持接口兼容 @@ -15507,6 +15233,7 @@ Mesh::Image8U3Arr MeshTexture::GenerateMultiViewTextureAtlasWithVirtualFaces( for (int x = startX; x <= endX; ++x) { const Point2f texCoord((float)x / textureSize, (float)y / textureSize); + /* // 计算重心坐标 Point3f barycentric; if (PointInTriangle(texCoord, uvCoords[0], uvCoords[1], uvCoords[2], barycentric)) { @@ -15557,6 +15284,39 @@ Mesh::Image8U3Arr MeshTexture::GenerateMultiViewTextureAtlasWithVirtualFaces( pointColors.push_back(accumColor); } } + //*/ + + //* + // 获取3D位置和法线 + Point3f worldPos; + Normal normal; + FIndex faceID; + if (!GetWorldPositionAndNormal(texCoord, worldPos, normal, faceID)) continue; + + // 查找虚拟面 + if (idxVF >= faceViews.size()) continue; + + // 1. 逐像素选图(关键!) + TexelViewInfo viewInfo; + if (!SelectBestViewForTexel(worldPos, normal, + faceViews[idxVF], + faceViewWeights[idxVF], + viewInfo)) { + continue; + } + + // // 2. 自适应纹素密度 + // int adaptiveSize = GetAdaptiveTexelSize(worldPos, + // faceViews[idxVF], + // textureSize); + + // // 3. 从最佳视图采样(使用双三次插值保持清晰度) + // const Image& bestImg = images[viewInfo.best_view_id]; + // Pixel8U color = SampleImageBicubic(bestImg.image, viewInfo.best_proj); + + // // 存储结果 + // textureAtlas(y, x) = color; + //*/ } } @@ -15629,6 +15389,7 @@ Mesh::Image8U3Arr MeshTexture::GenerateMultiViewTextureAtlasWithVirtualFaces( } } + //* // 6. 应用权重归一化 DEBUG_EXTRA("Applying weight normalization for virtual faces"); for (int y = 0; y < textureSize; ++y) { @@ -15651,6 +15412,7 @@ Mesh::Image8U3Arr MeshTexture::GenerateMultiViewTextureAtlasWithVirtualFaces( } } } + //*/ // 7. 填充缝隙和未采样区域 DEBUG_EXTRA("Filling gaps in texture atlas for virtual faces"); @@ -17570,7 +17332,7 @@ bool MeshTexture::ValidateProjection(const Vertex& worldPoint, // 3. 设置误差阈值 if (reprojectionError > maxReprojectionError) { - // DEBUG_EXTRA("重投影误差过大: %.3f像素,跳过该采样点", reprojectionError); + DEBUG_EXTRA("重投影误差过大: %.3f像素,跳过该采样点", reprojectionError); return false; } @@ -18333,8 +18095,6 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi } #endif - MeshTexture::VirtualFaceMap virtualFaceMap; - // assign the best view to each face { TD_TIMER_STARTD(); @@ -18355,58 +18115,8 @@ 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, &virtualFaceMap)) + 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()); @@ -18438,7 +18148,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi } // 使用虚拟面优化的纹理生成 - if (!texture.TextureWithExistingUVVirtualFaces(views, nIgnoreMaskLabel, fOutlierThreshold, nTextureSizeMultiple, colEmpty, fSharpnessWeight, &virtualFaceMap)){ + if (!texture.TextureWithExistingUVVirtualFaces(views, nIgnoreMaskLabel, fOutlierThreshold, nTextureSizeMultiple, colEmpty, fSharpnessWeight)){ return false; } return true; @@ -18448,7 +18158,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, &virtualFaceMap)) + colEmpty, fSharpnessWeight, maxTextureSize, baseFileName, bOriginFaceview, this)) { return false; }