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