|
|
|
@ -14332,8 +14332,6 @@ bool MeshTexture::RasterizeVirtualFaces( |
|
|
|
// ✅ 拷贝到 atlas(OpenMP critical 区)
|
|
|
|
// ✅ 拷贝到 atlas(OpenMP critical 区)
|
|
|
|
#pragma omp critical |
|
|
|
#pragma omp critical |
|
|
|
{ |
|
|
|
{ |
|
|
|
const int gutter = 4; // 4像素边缘缓冲
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int y = 0; y < patchH; ++y) { |
|
|
|
for (int y = 0; y < patchH; ++y) { |
|
|
|
for (int x = 0; x < patchW; ++x) { |
|
|
|
for (int x = 0; x < patchW; ++x) { |
|
|
|
cv::Vec3b color = patch.at<cv::Vec3b>(y, x); |
|
|
|
cv::Vec3b color = patch.at<cv::Vec3b>(y, x); |
|
|
|
@ -14346,56 +14344,6 @@ bool MeshTexture::RasterizeVirtualFaces( |
|
|
|
atlasY < 0 || atlasY >= textureSize) |
|
|
|
atlasY < 0 || atlasY >= textureSize) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
// ✅ 计算当前像素的 UV 坐标
|
|
|
|
|
|
|
|
float u = (float)atlasX / (float)textureSize; |
|
|
|
|
|
|
|
float v = (float)atlasY / (float)textureSize; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ 获取三角形的三个 UV 点
|
|
|
|
|
|
|
|
const TexCoord& uv0 = scene.mesh.faceTexcoords[vf.faces[0] * 3 + 0]; |
|
|
|
|
|
|
|
const TexCoord& uv1 = scene.mesh.faceTexcoords[vf.faces[0] * 3 + 1]; |
|
|
|
|
|
|
|
const TexCoord& uv2 = scene.mesh.faceTexcoords[vf.faces[0] * 3 + 2]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ 计算点到三角形三条边的有符号距离(UV空间)
|
|
|
|
|
|
|
|
// 使用重心坐标或点到线段的距离公式
|
|
|
|
|
|
|
|
auto pointToLineDistance = [](float px, float py, |
|
|
|
|
|
|
|
float x1, float y1, |
|
|
|
|
|
|
|
float x2, float y2) -> float { |
|
|
|
|
|
|
|
float dx = x2 - x1; |
|
|
|
|
|
|
|
float dy = y2 - y1; |
|
|
|
|
|
|
|
if (dx == 0.0f && dy == 0.0f) return std::sqrt((px-x1)*(px-x1) + (py-y1)*(py-y1)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float t = ((px - x1) * dx + (py - y1) * dy) / (dx*dx + dy*dy); |
|
|
|
|
|
|
|
t = std::max(0.0f, std::min(1.0f, t)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float closestX = x1 + t * dx; |
|
|
|
|
|
|
|
float closestY = y1 + t * dy; |
|
|
|
|
|
|
|
return std::sqrt((px - closestX)*(px - closestX) + |
|
|
|
|
|
|
|
(py - closestY)*(py - closestY)); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算到三条边的距离
|
|
|
|
|
|
|
|
float d0 = pointToLineDistance(u, v, uv0.x, uv0.y, uv1.x, uv1.y); |
|
|
|
|
|
|
|
float d1 = pointToLineDistance(u, v, uv1.x, uv1.y, uv2.x, uv2.y); |
|
|
|
|
|
|
|
float d2 = pointToLineDistance(u, v, uv2.x, uv2.y, uv0.x, uv0.y); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 取最小距离作为到三角形边界的距离
|
|
|
|
|
|
|
|
float distToEdge = std::min({d0, d1, d2}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 转换为像素距离
|
|
|
|
|
|
|
|
float pixelDist = distToEdge * textureSize; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Gutter 衰减逻辑(只衰减评分,不修改颜色!)
|
|
|
|
|
|
|
|
float gutterWeight = 1.0f; |
|
|
|
|
|
|
|
if (pixelDist < gutter) { |
|
|
|
|
|
|
|
// 使用平滑衰减函数(二次曲线)
|
|
|
|
|
|
|
|
gutterWeight = (pixelDist * pixelDist) / (gutter * gutter); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 极边缘处给极低权重,但不跳过
|
|
|
|
|
|
|
|
if (pixelDist < 0.5f) { |
|
|
|
|
|
|
|
gutterWeight = 0.01f; // 极低权重,几乎不会被选中
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t idx = atlasY * textureSize + atlasX; |
|
|
|
size_t idx = atlasY * textureSize + atlasX; |
|
|
|
TexelScore& ts = m_texelScores[idx]; |
|
|
|
TexelScore& ts = m_texelScores[idx]; |
|
|
|
|
|
|
|
|
|
|
|
@ -14404,13 +14352,11 @@ bool MeshTexture::RasterizeVirtualFaces( |
|
|
|
? -1.0f |
|
|
|
? -1.0f |
|
|
|
: virtualFaceViewWeights[i][0]; |
|
|
|
: virtualFaceViewWeights[i][0]; |
|
|
|
|
|
|
|
|
|
|
|
// ✅ 只衰减评分,不修改颜色!
|
|
|
|
// ✅ 只接受更高评分的写入
|
|
|
|
float finalScore = currentScore * gutterWeight; |
|
|
|
if (currentScore > ts.score) { |
|
|
|
|
|
|
|
|
|
|
|
if (finalScore > ts.score) { |
|
|
|
|
|
|
|
atlas(atlasY, atlasX) = |
|
|
|
atlas(atlasY, atlasX) = |
|
|
|
Pixel8U{color[2], color[1], color[0]}; |
|
|
|
Pixel8U{color[2], color[1], color[0]}; |
|
|
|
ts.score = finalScore; |
|
|
|
ts.score = currentScore; |
|
|
|
ts.viewID = viewID; |
|
|
|
ts.viewID = viewID; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|