清晰化
This commit is contained in:
1 parent
e8e3632341
commit
af1c3c0510
1 file changed
+92
-80
+92
-80
@@ -14606,10 +14606,8 @@ bool MeshTexture::SelectBestViewsForVirtualFaces(VirtualFaceMap& virtualFaceMap,
|
|||||||
m_virtualFaceGeometries.Resize(virtualFaceMap.size());
|
m_virtualFaceGeometries.Resize(virtualFaceMap.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& viewList : faceViews)
|
for (auto& viewList : faceViews) viewList.clear();
|
||||||
viewList.clear();
|
for (auto& weightList : faceViewWeights) weightList.clear();
|
||||||
for (auto& weightList : faceViewWeights)
|
|
||||||
weightList.clear();
|
|
||||||
|
|
||||||
// ===== Debug 统计 =====
|
// ===== Debug 统计 =====
|
||||||
size_t emptyCandidateViews = 0;
|
size_t emptyCandidateViews = 0;
|
||||||
@@ -14617,49 +14615,40 @@ bool MeshTexture::SelectBestViewsForVirtualFaces(VirtualFaceMap& virtualFaceMap,
|
|||||||
size_t fallbackByCenterFace = 0;
|
size_t fallbackByCenterFace = 0;
|
||||||
size_t successVF = 0;
|
size_t successVF = 0;
|
||||||
|
|
||||||
|
// ✅ 面片 → 视图 映射表
|
||||||
|
std::vector<IIndex> faceToView(scene.mesh.faces.size(), NO_ID);
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// 1. 初始视图分配
|
||||||
|
// ----------------------------------------------------------------
|
||||||
for (size_t i = 0; i < virtualFaceMap.size(); ++i) {
|
for (size_t i = 0; i < virtualFaceMap.size(); ++i) {
|
||||||
const VirtualFace& vf = virtualFaceMap[i];
|
const VirtualFace& vf = virtualFaceMap[i];
|
||||||
FIndex faceID2 = vf.faces[0];
|
if (vf.faces.empty()) continue;
|
||||||
|
|
||||||
|
FIndex faceID2 = vf.faces[0];
|
||||||
if (faceID2 >= faceNeighbors.size()) {
|
if (faceID2 >= faceNeighbors.size()) {
|
||||||
DEBUG_EXTRA("FATAL: faceID %u out of range!", faceID2);
|
DEBUG_EXTRA("FATAL: faceID %u out of range!", faceID2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (faceNeighbors[faceID2].empty()) {
|
// 收集候选视图
|
||||||
// DEBUG_EXTRA("FATAL: faceNeighbors[%u] is empty! FaceViewSelection mode error.", faceID2);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// 1. 收集每个面片的候选视图
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
std::unordered_set<IIndex> candidateViews;
|
std::unordered_set<IIndex> candidateViews;
|
||||||
std::vector<std::vector<IIndex>> faceViewCandidates(vf.faces.size());
|
for (FIndex faceID : vf.faces) {
|
||||||
|
if (faceID >= faceNeighbors.size()) continue;
|
||||||
for (size_t j = 0; j < vf.faces.size(); ++j) {
|
|
||||||
FIndex faceID = vf.faces[j];
|
|
||||||
if (faceID >= faceNeighbors.size())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (IIndex viewID : faceNeighbors[faceID]) {
|
for (IIndex viewID : faceNeighbors[faceID]) {
|
||||||
if (views.empty() || views.FindFirst(viewID) != NO_ID) {
|
if (views.empty() || views.FindFirst(viewID) != NO_ID) {
|
||||||
candidateViews.insert(viewID);
|
candidateViews.insert(viewID);
|
||||||
faceViewCandidates[j].push_back(viewID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// 2. 【终极兜底】候选视图为空 → 强制分配一个视图
|
// 2. 兜底:候选视图为空
|
||||||
// 物理遮挡不重要,逻辑可见性最重要
|
// ------------------------------------------------------------
|
||||||
//------------------------------------------------------------------
|
|
||||||
if (candidateViews.empty()) {
|
if (candidateViews.empty()) {
|
||||||
++emptyCandidateViews;
|
++emptyCandidateViews;
|
||||||
|
|
||||||
// 找一个可用的相机ID
|
|
||||||
// 优先级:views参数指定的 > 所有images中的第一个
|
|
||||||
IIndex forcedView = NO_ID;
|
IIndex forcedView = NO_ID;
|
||||||
|
|
||||||
if (!views.empty()) {
|
if (!views.empty()) {
|
||||||
forcedView = views[0];
|
forcedView = views[0];
|
||||||
} else if (!images.empty()) {
|
} else if (!images.empty()) {
|
||||||
@@ -14669,76 +14658,99 @@ bool MeshTexture::SelectBestViewsForVirtualFaces(VirtualFaceMap& virtualFaceMap,
|
|||||||
if (forcedView != NO_ID) {
|
if (forcedView != NO_ID) {
|
||||||
faceViews[i].push_back(forcedView);
|
faceViews[i].push_back(forcedView);
|
||||||
faceViewWeights[i].push_back(1.0f);
|
faceViewWeights[i].push_back(1.0f);
|
||||||
++fallbackByCenterFace;
|
|
||||||
|
|
||||||
// 降低日志级别,避免刷屏,用 DEBUG 而非 EXTRA
|
for (FIndex fid : vf.faces) {
|
||||||
// DEBUG("VF[%zu] EMPTY -> FORCED view %d (ignoring physical occlusion)",
|
if (fid < faceToView.size())
|
||||||
// i, forcedView);
|
faceToView[fid] = forcedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
++fallbackByCenterFace;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 实在没救(连images都没有),这才跳过
|
|
||||||
DEBUG_EXTRA("VF[%zu] truly hopeless: no images available", i);
|
DEBUG_EXTRA("VF[%zu] truly hopeless: no images available", i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// 3. 【关键放松】不再强求“所有面片共视”
|
// 3. 选择最佳视图(简单策略:第一个候选)
|
||||||
// 只要视图能看到任意一个面片即可
|
// ------------------------------------------------------------
|
||||||
//------------------------------------------------------------------
|
IIndex bestView = *candidateViews.begin();
|
||||||
std::vector<IIndex> usableViews(
|
|
||||||
candidateViews.begin(), candidateViews.end()
|
|
||||||
);
|
|
||||||
|
|
||||||
// (可选)按质量排序,取前 N 个
|
|
||||||
// std::sort(usableViews.begin(), usableViews.end(),
|
|
||||||
// [&](IIndex a, IIndex b) { return Quality(a) > Quality(b); });
|
|
||||||
|
|
||||||
if (usableViews.size() < minCommonCameras) {
|
|
||||||
faceViews[i] = usableViews;
|
|
||||||
} else {
|
|
||||||
// 仍尊重 minCommonCameras,但不强求共视
|
|
||||||
faceViews[i].assign(
|
|
||||||
usableViews.begin(),
|
|
||||||
usableViews.begin() + minCommonCameras
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// 4. 【二次兜底】usableViews 为空(理论上不会发生)
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
if (faceViews[i].empty()) {
|
|
||||||
++emptyCommonViews;
|
|
||||||
|
|
||||||
if (!vf.faces.empty()) {
|
|
||||||
FIndex centerFace = vf.faces[0];
|
|
||||||
if (centerFace < faceNeighbors.size() &&
|
|
||||||
!faceNeighbors[centerFace].empty()) {
|
|
||||||
|
|
||||||
IIndex bestView = faceNeighbors[centerFace][0];
|
|
||||||
faceViews[i].push_back(bestView);
|
faceViews[i].push_back(bestView);
|
||||||
faceViewWeights[i].push_back(1.0f);
|
faceViewWeights[i].push_back(1.0f);
|
||||||
|
|
||||||
DEBUG_EXTRA("VF[%zu] empty usableViews -> force view %d",
|
for (FIndex fid : vf.faces) {
|
||||||
i, bestView);
|
if (fid < faceToView.size())
|
||||||
continue;
|
faceToView[fid] = bestView;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// 5. 权重分配(均等,最稳定)
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
float weight = 1.0f / static_cast<float>(faceViews[i].size());
|
|
||||||
faceViewWeights[i].resize(faceViews[i].size(), weight);
|
|
||||||
|
|
||||||
++successVF;
|
++successVF;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// 6. Debug 汇总(非常重要)
|
// 4. 【轻量 Patch 一致性传播】
|
||||||
//--------------------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
if (scene.mesh.faceFaces.empty()) {
|
||||||
|
scene.mesh.ListIncidenteFaceFaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int PROPAGATION_ITER = 2;
|
||||||
|
for (int iter = 0; iter < PROPAGATION_ITER; ++iter) {
|
||||||
|
std::vector<IIndex> newFaceToView = faceToView;
|
||||||
|
|
||||||
|
for (FIndex fid = 0; fid < (FIndex)faceToView.size(); ++fid) {
|
||||||
|
if (faceToView[fid] == NO_ID) continue;
|
||||||
|
if (fid >= (FIndex)scene.mesh.faceFaces.size()) continue;
|
||||||
|
|
||||||
|
const Mesh::Face& neighbors = scene.mesh.faceFaces[fid];
|
||||||
|
|
||||||
|
std::unordered_map<IIndex, int> vote;
|
||||||
|
vote[faceToView[fid]] = 1;
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; ++k) {
|
||||||
|
FIndex nb = neighbors[k];
|
||||||
|
if (nb == NO_ID) continue;
|
||||||
|
if (nb < (FIndex)faceToView.size() && faceToView[nb] != NO_ID) {
|
||||||
|
vote[faceToView[nb]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IIndex majorityView = faceToView[fid];
|
||||||
|
int maxVote = 0;
|
||||||
|
for (const auto& v : vote) {
|
||||||
|
if (v.second > maxVote) {
|
||||||
|
maxVote = v.second;
|
||||||
|
majorityView = v.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxVote >= 3 && majorityView != faceToView[fid]) {
|
||||||
|
newFaceToView[fid] = majorityView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
faceToView.swap(newFaceToView);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// 5. 根据传播后的结果,更新 virtual face 的视图
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
for (size_t i = 0; i < virtualFaceMap.size(); ++i) {
|
||||||
|
const VirtualFace& vf = virtualFaceMap[i];
|
||||||
|
if (vf.faces.empty() || faceViews[i].empty()) continue;
|
||||||
|
|
||||||
|
FIndex firstFace = vf.faces[0];
|
||||||
|
if (firstFace < faceToView.size() && faceToView[firstFace] != NO_ID) {
|
||||||
|
IIndex consistentView = faceToView[firstFace];
|
||||||
|
faceViews[i] = {consistentView};
|
||||||
|
faceViewWeights[i] = {1.0f};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// 6. Debug 汇总
|
||||||
|
// ----------------------------------------------------------------
|
||||||
DEBUG_EXTRA("====== Virtual Face View Selection Summary ======");
|
DEBUG_EXTRA("====== Virtual Face View Selection Summary ======");
|
||||||
DEBUG_EXTRA("Total virtual faces : %zu", virtualFaceMap.size());
|
DEBUG_EXTRA("Total virtual faces : %zu", virtualFaceMap.size());
|
||||||
DEBUG_EXTRA("Successfully assigned : %zu", successVF);
|
DEBUG_EXTRA("Successfully assigned : %zu", successVF);
|
||||||
|
|||||||
Reference in new issue
Block a user