|
|
|
|
@ -14279,60 +14279,48 @@ bool MeshTexture::RasterizeVirtualFaces(
@@ -14279,60 +14279,48 @@ bool MeshTexture::RasterizeVirtualFaces(
|
|
|
|
|
if (!PointInTriangle(texCoord, uv[0], uv[1], uv[2], bary)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
// ✅ 透视校正插值
|
|
|
|
|
// 计算插值后的1/z
|
|
|
|
|
float invZ = bary.x / vertexDepths[0] + |
|
|
|
|
// ✅ 透视校正插值(double 精度)
|
|
|
|
|
double invZ = bary.x / vertexDepths[0] + |
|
|
|
|
bary.y / vertexDepths[1] + |
|
|
|
|
bary.z / vertexDepths[2]; |
|
|
|
|
if (invZ <= 0.0f) continue; |
|
|
|
|
|
|
|
|
|
float depth = 1.0f / invZ; // 校正后的深度
|
|
|
|
|
|
|
|
|
|
// ✅ 透视校正的世界坐标
|
|
|
|
|
Point3f P( |
|
|
|
|
(verts[0]->x * bary.x / vertexDepths[0] + |
|
|
|
|
verts[1]->x * bary.y / vertexDepths[1] + |
|
|
|
|
verts[2]->x * bary.z / vertexDepths[2]) * depth, |
|
|
|
|
(verts[0]->y * bary.x / vertexDepths[0] + |
|
|
|
|
verts[1]->y * bary.y / vertexDepths[1] + |
|
|
|
|
verts[2]->y * bary.z / vertexDepths[2]) * depth, |
|
|
|
|
(verts[0]->z * bary.x / vertexDepths[0] + |
|
|
|
|
verts[1]->z * bary.y / vertexDepths[1] + |
|
|
|
|
verts[2]->z * bary.z / vertexDepths[2]) * depth |
|
|
|
|
); |
|
|
|
|
if (invZ <= 0.0) continue; |
|
|
|
|
|
|
|
|
|
// ✅ 正确的深度测试:只保留更近的像素
|
|
|
|
|
if (depth <= 0.0f) continue; |
|
|
|
|
// ✅ 校正后的重心坐标
|
|
|
|
|
double u0 = (bary.x / vertexDepths[0]) / invZ; |
|
|
|
|
double u1 = (bary.y / vertexDepths[1]) / invZ; |
|
|
|
|
double u2 = (bary.z / vertexDepths[2]) / invZ; |
|
|
|
|
|
|
|
|
|
// ✅ 透视校正的世界坐标(double)
|
|
|
|
|
Point3d P_double( |
|
|
|
|
(verts[0]->x * bary.x / vertexDepths[0] + |
|
|
|
|
verts[1]->x * bary.y / vertexDepths[1] + |
|
|
|
|
verts[2]->x * bary.z / vertexDepths[2]) / invZ, |
|
|
|
|
(verts[0]->y * bary.x / vertexDepths[0] + |
|
|
|
|
verts[1]->y * bary.y / vertexDepths[1] + |
|
|
|
|
verts[2]->y * bary.z / vertexDepths[2]) / invZ, |
|
|
|
|
(verts[0]->z * bary.x / vertexDepths[0] + |
|
|
|
|
verts[1]->z * bary.y / vertexDepths[1] + |
|
|
|
|
verts[2]->z * bary.z / vertexDepths[2]) / invZ |
|
|
|
|
verts[0]->x * u0 + verts[1]->x * u1 + verts[2]->x * u2, |
|
|
|
|
verts[0]->y * u0 + verts[1]->y * u1 + verts[2]->y * u2, |
|
|
|
|
verts[0]->z * u0 + verts[1]->z * u1 + verts[2]->z * u2 |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
Point2f imgPt = cam.ProjectPoint(P_double); |
|
|
|
|
// ✅ 正确的投影(double → float)
|
|
|
|
|
Point2d imgPtDouble = cam.ProjectPoint(P_double); |
|
|
|
|
Point2f imgPt(static_cast<float>(imgPtDouble.x), |
|
|
|
|
static_cast<float>(imgPtDouble.y)); |
|
|
|
|
|
|
|
|
|
// 边界检查
|
|
|
|
|
// ✅ 边界检查
|
|
|
|
|
if (imgPt.x < 0.5f || imgPt.y < 0.5f || |
|
|
|
|
imgPt.x >= srcW - 0.5f || imgPt.y >= srcH - 0.5f) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
// ✅ 双线性采样(关键!)
|
|
|
|
|
// ✅ 双线性采样
|
|
|
|
|
Color color = BilinearSample(srcImg.image, imgPt); |
|
|
|
|
if (color[0] < 0 || color[1] < 0 || color[2] < 0) continue; |
|
|
|
|
|
|
|
|
|
// ✅ 单一临界区:原子更新深度和颜色
|
|
|
|
|
// ✅ 深度测试(float 缓冲,double 比较)
|
|
|
|
|
float depthFloat = static_cast<float>(1.0 / invZ); |
|
|
|
|
|
|
|
|
|
#pragma omp critical |
|
|
|
|
{ |
|
|
|
|
if (depth < depthBuffer(y, x)) { |
|
|
|
|
depthBuffer(y, x) = depth; |
|
|
|
|
colorBuffer(y, x) = cv::Vec3f(color[0], color[1], color[2]); // BGR->RGB
|
|
|
|
|
if (depthFloat < depthBuffer(y, x)) { |
|
|
|
|
depthBuffer(y, x) = depthFloat; |
|
|
|
|
colorBuffer(y, x) = cv::Vec3f( |
|
|
|
|
color[0], color[1], color[2] |
|
|
|
|
); |
|
|
|
|
validBuffer(y, x) = 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|