|
|
|
|
@ -670,6 +670,10 @@ public:
@@ -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<FIndex>& faceList); |
|
|
|
|
bool CheckUVContinuityForRegion(const MVS::Mesh::FaceIdxArr& faceList); |
|
|
|
|
@ -14922,19 +14926,55 @@ bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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
@@ -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
@@ -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
@@ -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<float>(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<float>(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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|