From 29388cf341e00f722be4fa44c0533019452a969d Mon Sep 17 00:00:00 2001 From: hesuicong Date: Thu, 14 May 2026 16:51:45 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E8=BF=87=E7=BC=96=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- libs/MVS/SceneTexture.cpp | 228 +++++++++++++++++++++++++------------- 2 files changed, 151 insertions(+), 79 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f11638..6214f1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,7 @@ ENDIF() PROJECT(OpenMVS) SET(ENV_PYTHON_PATH "/home/algo/.conda/envs/py310_pyt210/lib/python3.10/site-packages") -SET(ENV_MVS_PATH "/home/algo/Documents/openMVS/openMVS/libs/MVS") +SET(ENV_MVS_PATH "/home/algo/Documents/openMVS/openMVS.ManualUV/libs/MVS") CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/build/Templates/ConfigEnv.h.in" diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 76f3f67..9e90589 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -670,6 +670,10 @@ public: 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); @@ -14922,19 +14926,55 @@ bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap m_virtualFaceMapCached = true; return true; } +// 检查面片的UV是否有效 +bool MeshTexture::IsFaceUVValid(FIndex fid) const { + if (fid >= scene.mesh.faces.size()) { + return false; + } + + if (scene.mesh.faceTexcoords.size() <= fid * 3 + 2) { + 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)) { + return false; + } + } + + 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; +// 获取面片的UV中心 +TexCoord MeshTexture::GetFaceUVCenter(FIndex fid) const { + TexCoord center(0, 0); + + if (!IsFaceUVValid(fid)) { + return center; + } + + for (int i = 0; i < 3; ++i) { + const TexCoord& uv = scene.mesh.faceTexcoords[fid * 3 + i]; + center.x += uv.x; + center.y += uv.y; } + 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; - size_t validFaces = 0; + int validFaces = 0; for (FIndex fid : vf.faces) { if (fid >= scene.mesh.faces.size()) { @@ -14943,14 +14983,19 @@ void MeshTexture::CalculateVirtualFacePropertiesSafe(VirtualFace& vf) { 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()) { - // 跳过无效的面 - goto skip_face; + validVertices = false; + break; } } + if (!validVertices) { + continue; // 跳过无效的面 + } + // 计算面中心 Point3f faceCenter(0, 0, 0); for (int i = 0; i < 3; ++i) { @@ -14966,11 +15011,16 @@ void MeshTexture::CalculateVirtualFacePropertiesSafe(VirtualFace& vf) { Point3f edge1 = v1 - v0; Point3f edge2 = v2 - v0; Point3f faceNormal = edge1.cross(edge2); - float faceArea = faceNormal.norm(); - if (faceArea > 0) { + // 计算法向量的长度 + float faceAreaSq = faceNormal.dot(faceNormal); + + if (faceAreaSq > 0) { + float faceArea = sqrt(faceAreaSq); + + // 归一化法向量 faceNormal /= faceArea; - faceArea *= 0.5f; + faceArea *= 0.5f; // 三角形面积是平行四边形的一半 // 加权平均 centerSum += faceCenter * faceArea; @@ -14978,14 +15028,20 @@ void MeshTexture::CalculateVirtualFacePropertiesSafe(VirtualFace& vf) { areaSum += faceArea; validFaces++; } - - skip_face: - continue; } if (validFaces > 0 && areaSum > 0) { vf.center = centerSum / areaSum; - vf.normal = normalSum.normalized(); + + // 手动计算法向量长度并归一化 + float normalLengthSq = normalSum.dot(normalSum); + if (normalLengthSq > 0) { + float normalLength = sqrt(normalLengthSq); + vf.normal = normalSum / normalLength; + } else { + vf.normal = Point3f(0, 0, 1); // 默认法向量 + } + vf.area = areaSum; } else { vf.center = Point3f(0, 0, 0); @@ -14995,37 +15051,45 @@ void MeshTexture::CalculateVirtualFacePropertiesSafe(VirtualFace& vf) { } void MeshTexture::CalculateVirtualFaceUVBoundsSafe(VirtualFace& vf) { - if (vf.faces.empty()) { - vf.uvBounds.ptMin = TexCoord(0, 0); - vf.uvBounds.ptMax = TexCoord(1, 1); - return; - } + vf.uvBounds.ptMin = TexCoord(FLT_MAX, FLT_MAX); + vf.uvBounds.ptMax = TexCoord(-FLT_MAX, -FLT_MAX); + + bool hasValidUV = false; - bool first = true; for (FIndex fid : vf.faces) { - if (fid * 3 + 2 >= scene.mesh.faceTexcoords.size()) { - continue; // 跳过无效索引 + if (!IsFaceUVValid(fid)) { + 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 - } + // 处理UV环绕 + TexCoord wrappedUV = uv; - if (first) { - vf.uvBounds.ptMin = uv; - vf.uvBounds.ptMax = uv; - first = false; - } else { - vf.uvBounds.Insert(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 (first) { - // 没有有效的UV + if (!hasValidUV) { vf.uvBounds.ptMin = TexCoord(0, 0); vf.uvBounds.ptMax = TexCoord(1, 1); } @@ -15157,9 +15221,11 @@ bool MeshTexture::CreateVirtualFacesForExistingUVImpl(VirtualFaceMap& virtualFac VirtualFace vf; vf.faces.reserve(end - start); - vf.faces.insert(vf.faces.end(), - cell.begin() + start, - cell.begin() + end); + + // 修复:使用循环添加,因为 cList 没有接受迭代器的 insert 方法 + for (size_t idx = start; idx < end; ++idx) { + vf.faces.push_back(cell[idx]); + } // 计算属性 CalculateVirtualFacePropertiesSafe(vf); @@ -15169,7 +15235,12 @@ bool MeshTexture::CreateVirtualFacesForExistingUVImpl(VirtualFaceMap& virtualFac } } else { VirtualFace vf; - vf.faces = cell; // 复制 + vf.faces.reserve(cellSize); + + // 修复:使用循环添加 + for (FIndex fid : cell) { + vf.faces.push_back(fid); + } // 计算属性 CalculateVirtualFacePropertiesSafe(vf); @@ -15193,43 +15264,44 @@ bool MeshTexture::CreateVirtualFacesForExistingUVImpl(VirtualFaceMap& virtualFac 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("计算虚拟面统计时发生未知异常"); - } + + 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; }