|
|
|
@ -184,6 +184,13 @@ struct ViewSelectionData { |
|
|
|
viewID(id), quality(q), consistency(c) {} |
|
|
|
viewID(id), quality(q), consistency(c) {} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct VirtualFaceData { |
|
|
|
|
|
|
|
std::vector<FIndex> faceIndices; // 虚拟面对应的原始面片索引
|
|
|
|
|
|
|
|
Point3f center; // 虚拟面中心
|
|
|
|
|
|
|
|
Point3f normal; // 虚拟面法向量
|
|
|
|
|
|
|
|
float area; // 虚拟面面积
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 纹理块质量信息
|
|
|
|
// 纹理块质量信息
|
|
|
|
struct PatchQualityInfo { |
|
|
|
struct PatchQualityInfo { |
|
|
|
float averageQuality; |
|
|
|
float averageQuality; |
|
|
|
@ -566,14 +573,14 @@ public: |
|
|
|
const Mesh::VertexArr& vertices, |
|
|
|
const Mesh::VertexArr& vertices, |
|
|
|
const Mesh::FaceArr& faces, |
|
|
|
const Mesh::FaceArr& faces, |
|
|
|
const Mesh::NormalArr& faceNormals); |
|
|
|
const Mesh::NormalArr& faceNormals); |
|
|
|
void CalculateVirtualFaceProperties(VirtualFace& vf); |
|
|
|
bool CalculateVirtualFaceProperties(VirtualFace& vf); |
|
|
|
void CalculateVirtualFaceUVBounds(VirtualFace& vf); |
|
|
|
bool CalculateVirtualFaceUVBounds(VirtualFace& vf); |
|
|
|
bool AreFacesUVContinuous(FIndex fid1, FIndex fid2); |
|
|
|
bool AreFacesUVContinuous(FIndex fid1, FIndex fid2); |
|
|
|
|
|
|
|
|
|
|
|
bool ListCameraFaces(FaceDataViewArr&, float fOutlierThreshold, int nIgnoreMaskLabel, const IIndexArr& views, bool bUseVirtualFaces); |
|
|
|
bool ListCameraFaces(FaceDataViewArr&, float fOutlierThreshold, int nIgnoreMaskLabel, const IIndexArr& views, bool bUseVirtualFaces); |
|
|
|
bool CheckInvalidFaces(FaceDataViewArr& facesDatas, float fOutlierThreshold, int nIgnoreMaskLabel, const IIndexArr& _views, bool bUseVirtualFaces); |
|
|
|
bool CheckInvalidFaces(FaceDataViewArr& facesDatas, float fOutlierThreshold, int nIgnoreMaskLabel, const IIndexArr& _views, bool bUseVirtualFaces); |
|
|
|
bool IsFaceVisibleAndValid(const FaceDataArr& faceDatas, const IIndexArr& selectedCams) const; |
|
|
|
bool IsFaceVisibleAndValid(const FaceDataArr& faceDatas, const IIndexArr& selectedCams) const; |
|
|
|
|
|
|
|
std::vector<VirtualFaceData> ConvertVirtualFaceDataArrToVector(const VirtualFaceDataArr& vfDataArr); |
|
|
|
std::unordered_set<FIndex> PerformLocalDepthConsistencyCheck(DepthMap& depthMap, FaceMap& faceMap, Mesh& mesh, IIndex idxView, std::string strViewName); |
|
|
|
std::unordered_set<FIndex> PerformLocalDepthConsistencyCheck(DepthMap& depthMap, FaceMap& faceMap, Mesh& mesh, IIndex idxView, std::string strViewName); |
|
|
|
|
|
|
|
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
@ -608,6 +615,8 @@ public: |
|
|
|
unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, |
|
|
|
unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, |
|
|
|
Pixel8U colEmpty, float fSharpnessWeight, int maxTextureSize, |
|
|
|
Pixel8U colEmpty, float fSharpnessWeight, int maxTextureSize, |
|
|
|
const SEACAVE::String& baseFileName, Scene* pScene); |
|
|
|
const SEACAVE::String& baseFileName, Scene* pScene); |
|
|
|
|
|
|
|
bool ConvertVectorToVirtualFaceDataArr(const std::vector<VirtualFaceData>& src, VirtualFaceDataArr& dst); |
|
|
|
|
|
|
|
bool InitializeEmptyVirtualFaceDataArr(const VirtualFaceMap& virtualFaceMap, VirtualFaceDataArr& vfDataArr); |
|
|
|
bool SelectBestViewsForVirtualFaces(VirtualFaceMap& virtualFaceMap, |
|
|
|
bool SelectBestViewsForVirtualFaces(VirtualFaceMap& virtualFaceMap, |
|
|
|
unsigned minCommonCameras, float fOutlierThreshold, |
|
|
|
unsigned minCommonCameras, float fOutlierThreshold, |
|
|
|
float fRatioDataSmoothness, int nIgnoreMaskLabel, |
|
|
|
float fRatioDataSmoothness, int nIgnoreMaskLabel, |
|
|
|
@ -615,14 +624,6 @@ public: |
|
|
|
std::vector<std::vector<IIndex>> faceViews; |
|
|
|
std::vector<std::vector<IIndex>> faceViews; |
|
|
|
std::vector<std::vector<float>> faceViewWeights; |
|
|
|
std::vector<std::vector<float>> faceViewWeights; |
|
|
|
|
|
|
|
|
|
|
|
// 虚拟面相关数据结构
|
|
|
|
|
|
|
|
struct VirtualFaceData { |
|
|
|
|
|
|
|
std::vector<FIndex> faceIndices; // 虚拟面对应的原始面片索引
|
|
|
|
|
|
|
|
Point3f center; // 虚拟面中心
|
|
|
|
|
|
|
|
Point3f normal; // 虚拟面法向量
|
|
|
|
|
|
|
|
float area; // 虚拟面面积
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<VirtualFaceData> virtualFaceDatas; |
|
|
|
std::vector<VirtualFaceData> virtualFaceDatas; |
|
|
|
std::vector<std::vector<IIndex>> faceNeighbors; |
|
|
|
std::vector<std::vector<IIndex>> faceNeighbors; |
|
|
|
VirtualFaceGeometryArr m_virtualFaceGeometries; |
|
|
|
VirtualFaceGeometryArr m_virtualFaceGeometries; |
|
|
|
@ -1408,80 +1409,131 @@ void MeshTexture::ProcessVirtualFacesInView(const VirtualFaceMap& virtualFaceMap |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 计算虚拟面的属性
|
|
|
|
// 计算虚拟面的属性
|
|
|
|
// 计算虚拟面的属性
|
|
|
|
bool MeshTexture::CalculateVirtualFaceProperties(VirtualFace& vf) { |
|
|
|
void MeshTexture::CalculateVirtualFaceProperties(VirtualFace& vf) { |
|
|
|
|
|
|
|
if (vf.faces.empty()) { |
|
|
|
if (vf.faces.empty()) { |
|
|
|
vf.center = Point3f::ZERO; |
|
|
|
vf.center = Point3f::ZERO; |
|
|
|
vf.normal = Normal::ZERO; |
|
|
|
vf.normal = Normal::ZERO; |
|
|
|
vf.area = 0.0f; |
|
|
|
vf.area = 0.0f; |
|
|
|
return; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const Mesh::VertexArr& vertices = scene.mesh.vertices; |
|
|
|
const Mesh::VertexArr& vertices = scene.mesh.vertices; |
|
|
|
const Mesh::NormalArr& faceNormals = scene.mesh.faceNormals; |
|
|
|
const Mesh::NormalArr& faceNormals = scene.mesh.faceNormals; |
|
|
|
|
|
|
|
const size_t numFaces = scene.mesh.faces.size(); |
|
|
|
|
|
|
|
const size_t numVertices = vertices.size(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 验证输入
|
|
|
|
|
|
|
|
if (faceNormals.size() != numFaces) { |
|
|
|
|
|
|
|
DEBUG_EXTRA("WARNING: faceNormals size (%zu) doesn't match faces size (%zu)", |
|
|
|
|
|
|
|
faceNormals.size(), numFaces); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
vf.center = Point3f::ZERO; |
|
|
|
vf.center = Point3f::ZERO; |
|
|
|
vf.normal = Normal::ZERO; |
|
|
|
vf.normal = Normal::ZERO; |
|
|
|
vf.area = 0.0f; |
|
|
|
vf.area = 0.0f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int invalidFaceCount = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (FIndex faceIdx : vf.faces) { |
|
|
|
for (FIndex faceIdx : vf.faces) { |
|
|
|
const Mesh::Face& facet = faces[faceIdx]; |
|
|
|
// 检查面片索引是否有效
|
|
|
|
|
|
|
|
if (faceIdx >= numFaces) { |
|
|
|
|
|
|
|
DEBUG_EXTRA("WARNING: Invalid face index %u in CalculateVirtualFaceProperties (max: %zu)", |
|
|
|
|
|
|
|
faceIdx, numFaces - 1); |
|
|
|
|
|
|
|
invalidFaceCount++; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 计算面片中心
|
|
|
|
const Mesh::Face& facet = scene.mesh.faces[faceIdx]; |
|
|
|
Point3f faceCenter = (vertices[facet[0]] + vertices[facet[1]] + vertices[facet[2]]) / 3.0f; |
|
|
|
|
|
|
|
vf.center += faceCenter; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 累加法线
|
|
|
|
// 验证顶点索引
|
|
|
|
vf.normal += faceNormals[faceIdx]; |
|
|
|
bool verticesValid = true; |
|
|
|
|
|
|
|
for (int i = 0; i < 3; ++i) { |
|
|
|
|
|
|
|
if (facet[i] >= numVertices) { |
|
|
|
|
|
|
|
DEBUG_EXTRA("WARNING: Invalid vertex index %u in face %u (max: %zu)", |
|
|
|
|
|
|
|
facet[i], faceIdx, numVertices - 1); |
|
|
|
|
|
|
|
verticesValid = false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 计算面片面积 - 修复1:手动计算三角形面积
|
|
|
|
if (!verticesValid) { |
|
|
|
|
|
|
|
invalidFaceCount++; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算面片中心
|
|
|
|
const Point3f& v0 = vertices[facet[0]]; |
|
|
|
const Point3f& v0 = vertices[facet[0]]; |
|
|
|
const Point3f& v1 = vertices[facet[1]]; |
|
|
|
const Point3f& v1 = vertices[facet[1]]; |
|
|
|
const Point3f& v2 = vertices[facet[2]]; |
|
|
|
const Point3f& v2 = vertices[facet[2]]; |
|
|
|
|
|
|
|
|
|
|
|
// 计算三角形的两个边向量
|
|
|
|
Point3f faceCenter = (v0 + v1 + v2) / 3.0f; |
|
|
|
|
|
|
|
vf.center += faceCenter; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 累加法线
|
|
|
|
|
|
|
|
if (faceIdx < faceNormals.size()) { |
|
|
|
|
|
|
|
vf.normal += faceNormals[faceIdx]; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// 计算面片法线
|
|
|
|
|
|
|
|
Point3f edge1 = v1 - v0; |
|
|
|
|
|
|
|
Point3f edge2 = v2 - v0; |
|
|
|
|
|
|
|
Point3f normal = edge1.cross(edge2); |
|
|
|
|
|
|
|
// 归一化
|
|
|
|
|
|
|
|
float length = sqrtf(normal.dot(normal)); |
|
|
|
|
|
|
|
if (length > 0) { |
|
|
|
|
|
|
|
normal /= length; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
normal = Point3f(0, 0, 1); // 默认法线
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
vf.normal += Normal(normal); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算面片面积
|
|
|
|
Point3f edge1 = v1 - v0; |
|
|
|
Point3f edge1 = v1 - v0; |
|
|
|
Point3f edge2 = v2 - v0; |
|
|
|
Point3f edge2 = v2 - v0; |
|
|
|
|
|
|
|
|
|
|
|
// 计算叉积
|
|
|
|
Point3f crossProd = edge1.cross(edge2); |
|
|
|
Point3f crossProd( |
|
|
|
// 计算叉积的模
|
|
|
|
edge1.y * edge2.z - edge1.z * edge2.y, |
|
|
|
float crossLength = sqrtf(crossProd.dot(crossProd)); |
|
|
|
edge1.z * edge2.x - edge1.x * edge2.z, |
|
|
|
float area = crossLength * 0.5f; |
|
|
|
edge1.x * edge2.y - edge1.y * edge2.x |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算面积 = 0.5 * 叉积的模
|
|
|
|
if (area < 0) { |
|
|
|
float area = 0.5f * std::sqrt( |
|
|
|
area = -area; // 取绝对值
|
|
|
|
crossProd.x * crossProd.x + |
|
|
|
} |
|
|
|
crossProd.y * crossProd.y + |
|
|
|
|
|
|
|
crossProd.z * crossProd.z |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vf.area += area; |
|
|
|
vf.area += area; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 计算平均值
|
|
|
|
if (invalidFaceCount > 0) { |
|
|
|
vf.center /= vf.faces.size(); |
|
|
|
DEBUG_EXTRA("CalculateVirtualFaceProperties: %d invalid faces skipped", invalidFaceCount); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 修复2:手动归一化法线向量
|
|
|
|
if (vf.faces.size() - invalidFaceCount == 0) { |
|
|
|
float norm = std::sqrt( |
|
|
|
vf.center = Point3f::ZERO; |
|
|
|
vf.normal.x * vf.normal.x + |
|
|
|
vf.normal = Normal::ZERO; |
|
|
|
vf.normal.y * vf.normal.y + |
|
|
|
vf.area = 0.0f; |
|
|
|
vf.normal.z * vf.normal.z |
|
|
|
return false; |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算平均值
|
|
|
|
|
|
|
|
vf.center /= static_cast<float>(vf.faces.size() - invalidFaceCount); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 归一化法线
|
|
|
|
|
|
|
|
float norm = sqrtf(vf.normal.dot(vf.normal)); |
|
|
|
if (norm > 0) { |
|
|
|
if (norm > 0) { |
|
|
|
vf.normal.x /= norm; |
|
|
|
vf.normal /= norm; |
|
|
|
vf.normal.y /= norm; |
|
|
|
} else { |
|
|
|
vf.normal.z /= norm; |
|
|
|
vf.normal = Normal(0, 0, 1); // 默认法线
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
// 计算虚拟面的UV边界
|
|
|
|
|
|
|
|
void MeshTexture::CalculateVirtualFaceUVBounds(VirtualFace& vf) { |
|
|
|
bool MeshTexture::CalculateVirtualFaceUVBounds(VirtualFace& vf) { |
|
|
|
if (vf.faces.empty() || !scene.mesh.HasTexture()) { |
|
|
|
if (vf.faces.empty() || !scene.mesh.HasTexture()) { |
|
|
|
// 修正1: 不使用 ZERO,而是创建一个空的边界框
|
|
|
|
// 修正1: 不使用 ZERO,而是创建一个空的边界框
|
|
|
|
vf.uvBounds = AABB2f(); // 使用默认构造函数
|
|
|
|
vf.uvBounds = AABB2f(); // 使用默认构造函数
|
|
|
|
return; |
|
|
|
return false; // 返回 false
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const TexCoord* texcoords = scene.mesh.faceTexcoords.data(); |
|
|
|
const TexCoord* texcoords = scene.mesh.faceTexcoords.data(); |
|
|
|
@ -1500,6 +1552,8 @@ void MeshTexture::CalculateVirtualFaceUVBounds(VirtualFace& vf) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return !first; // 如果至少有一个UV坐标,则返回true
|
|
|
|
} |
|
|
|
} |
|
|
|
// 检查两个面片在UV空间中是否连续
|
|
|
|
// 检查两个面片在UV空间中是否连续
|
|
|
|
bool MeshTexture::AreFacesUVContinuous(FIndex fid1, FIndex fid2) { |
|
|
|
bool MeshTexture::AreFacesUVContinuous(FIndex fid1, FIndex fid2) { |
|
|
|
@ -9397,7 +9451,7 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
DEBUG_EXTRA("PointInTriangle Yes idxFace=%d", idxFace); |
|
|
|
// DEBUG_EXTRA("PointInTriangle Yes idxFace=%d", idxFace);
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -9872,7 +9926,7 @@ void MeshTexture::GenerateTextureForUV(bool bGlobalSeamLeveling, bool bLocalSeam |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
DEBUG_EXTRA("PointInTriangle Yes idxFace=%d", idxFace); |
|
|
|
// DEBUG_EXTRA("PointInTriangle Yes idxFace=%d", idxFace);
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -14816,7 +14870,7 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int |
|
|
|
// 收集所有有效视图
|
|
|
|
// 收集所有有效视图
|
|
|
|
for (const FaceData& data : vfDatas) { |
|
|
|
for (const FaceData& data : vfDatas) { |
|
|
|
if (!data.bInvalidFacesRelative) { |
|
|
|
if (!data.bInvalidFacesRelative) { |
|
|
|
// 计算视图质量权重
|
|
|
|
// 使用 FaceData 中的视图质量
|
|
|
|
float weight = data.quality; |
|
|
|
float weight = data.quality; |
|
|
|
|
|
|
|
|
|
|
|
// 添加视角与法线夹角的权重
|
|
|
|
// 添加视角与法线夹角的权重
|
|
|
|
@ -15119,10 +15173,23 @@ bool MeshTexture::GenerateTextureWithVirtualFacesInternal(bool bGlobalSeamLeveli |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 4. 生成多视图纹理图集
|
|
|
|
// 4. 计算视图和权重
|
|
|
|
// 直接调用函数,不进行类型转换
|
|
|
|
std::vector<std::vector<IIndex>> faceViews(virtualFaceMap.size()); |
|
|
|
|
|
|
|
std::vector<std::vector<float>> faceViewWeights(virtualFaceMap.size()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 这里需要获取虚拟面的最佳视图信息
|
|
|
|
|
|
|
|
// 由于虚拟面数据中没有 bestViews 成员,我们需要从其他方式获取
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 生成多视图纹理图集
|
|
|
|
|
|
|
|
// 创建一个空的 VirtualFaceDataArr,因为我们只需要虚拟面映射,不需要额外的数据
|
|
|
|
|
|
|
|
VirtualFaceDataArr emptyVfDataArr; |
|
|
|
|
|
|
|
if (!InitializeEmptyVirtualFaceDataArr(virtualFaceMap, emptyVfDataArr)) { |
|
|
|
|
|
|
|
DEBUG_EXTRA("Failed to initialize virtual face data array"); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Mesh::Image8U3Arr textures = GenerateMultiViewTextureAtlasWithVirtualFaces( |
|
|
|
Mesh::Image8U3Arr textures = GenerateMultiViewTextureAtlasWithVirtualFaces( |
|
|
|
virtualFaceMap, virtualFaceDatas, faceViews, faceViewWeights, |
|
|
|
virtualFaceMap, emptyVfDataArr, faceViews, faceViewWeights, |
|
|
|
nTextureSizeMultiple, colEmpty, fSharpnessWeight); |
|
|
|
nTextureSizeMultiple, colEmpty, fSharpnessWeight); |
|
|
|
|
|
|
|
|
|
|
|
if (textures.empty()) { |
|
|
|
if (textures.empty()) { |
|
|
|
@ -15130,10 +15197,10 @@ bool MeshTexture::GenerateTextureWithVirtualFacesInternal(bool bGlobalSeamLeveli |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 5. 存储纹理
|
|
|
|
// 6. 存储纹理
|
|
|
|
scene.mesh.texturesDiffuse.swap(textures); |
|
|
|
scene.mesh.texturesDiffuse.swap(textures); |
|
|
|
|
|
|
|
|
|
|
|
// 6. 应用UV映射
|
|
|
|
// 7. 应用UV映射
|
|
|
|
if (bGlobalSeamLeveling) { |
|
|
|
if (bGlobalSeamLeveling) { |
|
|
|
// TODO: 实现全局缝合优化
|
|
|
|
// TODO: 实现全局缝合优化
|
|
|
|
} |
|
|
|
} |
|
|
|
@ -15146,34 +15213,175 @@ bool MeshTexture::GenerateTextureWithVirtualFacesInternal(bool bGlobalSeamLeveli |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool MeshTexture::InitializeEmptyVirtualFaceDataArr(const VirtualFaceMap& virtualFaceMap, VirtualFaceDataArr& vfDataArr) { |
|
|
|
|
|
|
|
vfDataArr.clear(); // 改为小写
|
|
|
|
|
|
|
|
vfDataArr.reserve(virtualFaceMap.size()); // 改为小写
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < virtualFaceMap.size(); ++i) { |
|
|
|
|
|
|
|
FaceDataArr faceDataList; |
|
|
|
|
|
|
|
// 为每个虚拟面创建一个空的 FaceData
|
|
|
|
|
|
|
|
vfDataArr.push_back(faceDataList); // 使用 push_back
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool MeshTexture::ConvertVectorToVirtualFaceDataArr(const std::vector<VirtualFaceData>& src, VirtualFaceDataArr& dst) { |
|
|
|
|
|
|
|
dst.clear(); |
|
|
|
|
|
|
|
dst.reserve(src.size()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < src.size(); ++i) { |
|
|
|
|
|
|
|
FaceDataArr faceDataList; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建一个空的 FaceData,因为我们不需要实际的视图数据
|
|
|
|
|
|
|
|
// 视图数据会通过其他方式提供
|
|
|
|
|
|
|
|
dst.push_back(faceDataList); // 改为 push_back
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap) { |
|
|
|
bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap) { |
|
|
|
DEBUG_EXTRA("Creating virtual faces for existing UV texture mapping"); |
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查基本数据结构
|
|
|
|
|
|
|
|
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!"); |
|
|
|
|
|
|
|
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."); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (numFaceTexcoords < numFaces * 3) { |
|
|
|
|
|
|
|
DEBUG_EXTRA("ERROR: Not enough UV coordinates! Expected %zu (faces * 3), have %zu", |
|
|
|
|
|
|
|
numFaces * 3, numFaceTexcoords); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 验证面片索引
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 1. 确保网格拓扑已计算
|
|
|
|
// 1. 确保网格拓扑已计算
|
|
|
|
|
|
|
|
DEBUG_EXTRA("Computing mesh topology..."); |
|
|
|
if (scene.mesh.faceFaces.empty()) { |
|
|
|
if (scene.mesh.faceFaces.empty()) { |
|
|
|
scene.mesh.ListIncidenteFaces(); |
|
|
|
DEBUG_EXTRA(" Computing incident faces..."); |
|
|
|
scene.mesh.ListIncidenteFaceFaces(); |
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (scene.mesh.faceNormals.empty()) { |
|
|
|
if (scene.mesh.faceNormals.empty()) { |
|
|
|
scene.mesh.ComputeNormalFaces(); |
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 2. 初始化原始面片标记
|
|
|
|
|
|
|
|
const FIndex numFaces = scene.mesh.faces.size(); |
|
|
|
|
|
|
|
std::vector<bool> processedFaces(numFaces, false); |
|
|
|
std::vector<bool> processedFaces(numFaces, false); |
|
|
|
|
|
|
|
|
|
|
|
// 3. 基于曲率分割网格
|
|
|
|
// 3. 基于曲率分割网格
|
|
|
|
|
|
|
|
DEBUG_EXTRA("Segmenting mesh based on curvature..."); |
|
|
|
Mesh::FaceIdxArr regionMap; |
|
|
|
Mesh::FaceIdxArr regionMap; |
|
|
|
scene.SegmentMeshBasedOnCurvature(regionMap, 0.2f); |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} catch (const std::exception& e) { |
|
|
|
|
|
|
|
DEBUG_EXTRA("ERROR during mesh segmentation: %s", e.what()); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 4. 统计每个区域的面积
|
|
|
|
// 4. 统计每个区域的面积
|
|
|
|
|
|
|
|
DEBUG_EXTRA("Calculating region areas..."); |
|
|
|
std::unordered_map<int, float> regionAreas; |
|
|
|
std::unordered_map<int, float> regionAreas; |
|
|
|
|
|
|
|
|
|
|
|
for (FIndex fid = 0; fid < numFaces; ++fid) { |
|
|
|
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]; |
|
|
|
int region = regionMap[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]; |
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const Point3f& v0 = scene.mesh.vertices[face[0]]; |
|
|
|
const Point3f& v0 = scene.mesh.vertices[face[0]]; |
|
|
|
const Point3f& v1 = scene.mesh.vertices[face[1]]; |
|
|
|
const Point3f& v1 = scene.mesh.vertices[face[1]]; |
|
|
|
const Point3f& v2 = scene.mesh.vertices[face[2]]; |
|
|
|
const Point3f& v2 = scene.mesh.vertices[face[2]]; |
|
|
|
@ -15194,22 +15402,51 @@ bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap |
|
|
|
crossProd.z * crossProd.z |
|
|
|
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; |
|
|
|
regionAreas[region] += area; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 5. 为每个区域创建虚拟面
|
|
|
|
DEBUG_EXTRA("Region area calculation completed, found %zu regions", regionAreas.size()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 为每个区域收集面片
|
|
|
|
|
|
|
|
DEBUG_EXTRA("Grouping faces by region..."); |
|
|
|
std::unordered_map<int, std::vector<FIndex>> regionFaces; |
|
|
|
std::unordered_map<int, std::vector<FIndex>> regionFaces; |
|
|
|
for (FIndex fid = 0; fid < numFaces; ++fid) { |
|
|
|
for (FIndex fid = 0; fid < numFaces; ++fid) { |
|
|
|
regionFaces[regionMap[fid]].push_back(fid); |
|
|
|
int region = regionMap[fid]; |
|
|
|
|
|
|
|
regionFaces[region].push_back(fid); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEBUG_EXTRA("Found %zu regions with faces", regionFaces.size()); |
|
|
|
|
|
|
|
|
|
|
|
// 6. 创建虚拟面
|
|
|
|
// 6. 创建虚拟面
|
|
|
|
|
|
|
|
DEBUG_EXTRA("Creating virtual faces..."); |
|
|
|
|
|
|
|
virtualFaceMap.clear(); |
|
|
|
|
|
|
|
virtualFaceMap.reserve(regionFaces.size()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int regionCount = 0; |
|
|
|
|
|
|
|
int smallRegionCount = 0; |
|
|
|
|
|
|
|
int uvDiscontinuousCount = 0; |
|
|
|
|
|
|
|
int createdVirtualFaces = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (const auto& region : regionFaces) { |
|
|
|
for (const auto& region : regionFaces) { |
|
|
|
|
|
|
|
regionCount++; |
|
|
|
int regionID = region.first; |
|
|
|
int regionID = region.first; |
|
|
|
const std::vector<FIndex>& faceList = region.second; |
|
|
|
const std::vector<FIndex>& faceList = region.second; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (regionCount % 100 == 0) { |
|
|
|
|
|
|
|
DEBUG_EXTRA(" Processing region %d/%d (%zu faces)", regionCount, regionFaces.size(), faceList.size()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查区域面积是否足够大
|
|
|
|
// 检查区域面积是否足够大
|
|
|
|
if (regionAreas[regionID] < 0.001f) { // 面积阈值
|
|
|
|
float regionArea = regionAreas[regionID]; |
|
|
|
|
|
|
|
if (regionArea < 0.001f) { // 面积阈值
|
|
|
|
|
|
|
|
DEBUG_EXTRA(" Region %d is too small (area: %f), using individual faces", regionID, regionArea); |
|
|
|
|
|
|
|
smallRegionCount++; |
|
|
|
|
|
|
|
|
|
|
|
// 区域太小,不创建虚拟面
|
|
|
|
// 区域太小,不创建虚拟面
|
|
|
|
for (FIndex fid : faceList) { |
|
|
|
for (FIndex fid : faceList) { |
|
|
|
virtualFaceMap.push_back(VirtualFace()); |
|
|
|
virtualFaceMap.push_back(VirtualFace()); |
|
|
|
@ -15220,6 +15457,9 @@ bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap |
|
|
|
|
|
|
|
|
|
|
|
// 检查UV连续性
|
|
|
|
// 检查UV连续性
|
|
|
|
if (!CheckUVContinuity(faceList)) { |
|
|
|
if (!CheckUVContinuity(faceList)) { |
|
|
|
|
|
|
|
DEBUG_EXTRA(" Region %d has discontinuous UV, using individual faces", regionID); |
|
|
|
|
|
|
|
uvDiscontinuousCount++; |
|
|
|
|
|
|
|
|
|
|
|
// UV不连续,保持原始面片
|
|
|
|
// UV不连续,保持原始面片
|
|
|
|
for (FIndex fid : faceList) { |
|
|
|
for (FIndex fid : faceList) { |
|
|
|
virtualFaceMap.push_back(VirtualFace()); |
|
|
|
virtualFaceMap.push_back(VirtualFace()); |
|
|
|
@ -15233,17 +15473,44 @@ bool MeshTexture::CreateVirtualFacesForExistingUV(VirtualFaceMap& virtualFaceMap |
|
|
|
vf.faces = faceList; |
|
|
|
vf.faces = faceList; |
|
|
|
|
|
|
|
|
|
|
|
// 计算虚拟面的中心、法线和面积
|
|
|
|
// 计算虚拟面的中心、法线和面积
|
|
|
|
CalculateVirtualFaceProperties(vf); |
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 计算虚拟面的UV边界
|
|
|
|
// 计算虚拟面的UV边界
|
|
|
|
CalculateVirtualFaceUVBounds(vf); |
|
|
|
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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
virtualFaceMap.push_back(vf); |
|
|
|
virtualFaceMap.push_back(vf); |
|
|
|
|
|
|
|
createdVirtualFaces++; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DEBUG_EXTRA("Created %zu virtual faces (original faces: %zu)", virtualFaceMap.size(), numFaces); |
|
|
|
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(" Created virtual faces: %d", createdVirtualFaces); |
|
|
|
|
|
|
|
DEBUG_EXTRA(" Total virtual faces (including individual faces): %zu", virtualFaceMap.size()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (virtualFaceMap.empty()) { |
|
|
|
|
|
|
|
DEBUG_EXTRA("ERROR: No virtual faces created!"); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return !virtualFaceMap.empty(); |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool MeshTexture::CheckUVContinuity(const std::vector<FIndex>& faceList) { |
|
|
|
bool MeshTexture::CheckUVContinuity(const std::vector<FIndex>& faceList) { |
|
|
|
@ -15336,7 +15603,7 @@ float MeshTexture::TriangleArea( |
|
|
|
|
|
|
|
|
|
|
|
Mesh::Image8U3Arr MeshTexture::GenerateMultiViewTextureAtlasWithVirtualFaces( |
|
|
|
Mesh::Image8U3Arr MeshTexture::GenerateMultiViewTextureAtlasWithVirtualFaces( |
|
|
|
const VirtualFaceMap& virtualFaceMap, |
|
|
|
const VirtualFaceMap& virtualFaceMap, |
|
|
|
const VirtualFaceDataArr& virtualFaceDatas, // 改为 VirtualFaceDataArr
|
|
|
|
const VirtualFaceDataArr& virtualFaceDatas, // 这个参数现在不被使用,但保留以保持接口兼容
|
|
|
|
const std::vector<std::vector<IIndex>>& faceViews, |
|
|
|
const std::vector<std::vector<IIndex>>& faceViews, |
|
|
|
const std::vector<std::vector<float>>& faceViewWeights, |
|
|
|
const std::vector<std::vector<float>>& faceViewWeights, |
|
|
|
unsigned nTextureSizeMultiple, |
|
|
|
unsigned nTextureSizeMultiple, |
|
|
|
@ -15420,9 +15687,9 @@ Mesh::Image8U3Arr MeshTexture::GenerateMultiViewTextureAtlasWithVirtualFaces( |
|
|
|
if (PointInTriangle(texCoord, uvCoords[0], uvCoords[1], uvCoords[2], barycentric)) { |
|
|
|
if (PointInTriangle(texCoord, uvCoords[0], uvCoords[1], uvCoords[2], barycentric)) { |
|
|
|
// 计算3D点
|
|
|
|
// 计算3D点
|
|
|
|
const Vertex worldPoint = |
|
|
|
const Vertex worldPoint = |
|
|
|
vertices[face[0]] * barycentric.x + |
|
|
|
scene.mesh.vertices[face[0]] * barycentric.x + |
|
|
|
vertices[face[1]] * barycentric.y + |
|
|
|
scene.mesh.vertices[face[1]] * barycentric.y + |
|
|
|
vertices[face[2]] * barycentric.z; |
|
|
|
scene.mesh.vertices[face[2]] * barycentric.z; |
|
|
|
|
|
|
|
|
|
|
|
// 为每个视图采样颜色
|
|
|
|
// 为每个视图采样颜色
|
|
|
|
cv::Vec3f accumColor(0, 0, 0); |
|
|
|
cv::Vec3f accumColor(0, 0, 0); |
|
|
|
@ -18252,6 +18519,15 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
if (bUseExistingUV && !strUVMeshFileName.empty()) { |
|
|
|
|
|
|
|
VERBOSE("1faceTexcoords.size=%d, faces.size=%d", mesh.faceTexcoords.size(), mesh.faces.size() * 3); |
|
|
|
|
|
|
|
// 使用预计算UV模式
|
|
|
|
|
|
|
|
if (!mesh.Load(MAKE_PATH_SAFE(strUVMeshFileName), true)) { |
|
|
|
|
|
|
|
VERBOSE("error: cannot load mesh file with UV coordinates"); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 使用虚拟面优化策略
|
|
|
|
// 使用虚拟面优化策略
|
|
|
|
if (!texture.FaceViewSelectionWithVirtualFaces(minCommonCameras, fOutlierThreshold, fRatioDataSmoothness, nIgnoreMaskLabel, views, bUseExistingUV)) |
|
|
|
if (!texture.FaceViewSelectionWithVirtualFaces(minCommonCameras, fOutlierThreshold, fRatioDataSmoothness, nIgnoreMaskLabel, views, bUseExistingUV)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
@ -18268,13 +18544,12 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi |
|
|
|
|
|
|
|
|
|
|
|
// 处理已有UV的情况
|
|
|
|
// 处理已有UV的情况
|
|
|
|
if (bUseExistingUV && !strUVMeshFileName.empty()) { |
|
|
|
if (bUseExistingUV && !strUVMeshFileName.empty()) { |
|
|
|
VERBOSE("1faceTexcoords.size=%d, faces.size=%d", mesh.faceTexcoords.size(), mesh.faces.size() * 3); |
|
|
|
// VERBOSE("1faceTexcoords.size=%d, faces.size=%d", mesh.faceTexcoords.size(), mesh.faces.size() * 3);
|
|
|
|
|
|
|
|
// // 使用预计算UV模式
|
|
|
|
// 使用预计算UV模式
|
|
|
|
// if (!mesh.Load(MAKE_PATH_SAFE(strUVMeshFileName), true)) {
|
|
|
|
if (!mesh.Load(MAKE_PATH_SAFE(strUVMeshFileName), true)) { |
|
|
|
// VERBOSE("error: cannot load mesh file with UV coordinates");
|
|
|
|
VERBOSE("error: cannot load mesh file with UV coordinates"); |
|
|
|
// return false;
|
|
|
|
return false; |
|
|
|
// }
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VERBOSE("2faceTexcoords.size=%d, faces.size=%d", mesh.faceTexcoords.size(), mesh.faces.size() * 3); |
|
|
|
VERBOSE("2faceTexcoords.size=%d, faces.size=%d", mesh.faceTexcoords.size(), mesh.faces.size() * 3); |
|
|
|
mesh.CheckUVValid(); |
|
|
|
mesh.CheckUVValid(); |
|
|
|
|