Fix #105164: Blender exits when QuadriFlow solver fails

Replace calls to exit(..) with an error return value.
This commit is contained in:
Campbell Barton
2025-01-22 19:17:20 +11:00
parent 16f728cfe5
commit 46724ca841
7 changed files with 182 additions and 16 deletions

View File

@@ -375,6 +375,88 @@ index ab4a01c..a77f7ae 100644
};
class NetworkSimplexFlowHelper : public MaxFlowHelper {
diff --git a/extern/quadriflow/src/main.cpp b/extern/quadriflow/src/main.cpp
index 18bc4063c42..63c9e61b8c9 100644
--- a/extern/quadriflow/src/main.cpp
+++ b/extern/quadriflow/src/main.cpp
@@ -110,7 +110,10 @@ int main(int argc, char** argv) {
printf("Use %lf seconds\n", (t2 - t1) * 1e-3);
t1 = GetCurrentTime64();
printf("Solve index map...\n");
- field.ComputeIndexMap();
+ if (!field.ComputeIndexMap()) {
+ fprintf(stderr, "Failed to solve result, exiting!\n");
+ return 1;
+ }
t2 = GetCurrentTime64();
printf("Indexmap Use %lf seconds\n", (t2 - t1) * 1e-3);
printf("Writing the file...\n");
diff --git a/extern/quadriflow/src/parametrizer.cpp b/extern/quadriflow/src/parametrizer.cpp
index b85383566c9..3dbdc386eca 100644
--- a/extern/quadriflow/src/parametrizer.cpp
+++ b/extern/quadriflow/src/parametrizer.cpp
@@ -18,7 +18,7 @@
namespace qflow {
-void Parametrizer::ComputeIndexMap(int with_scale) {
+bool Parametrizer::ComputeIndexMap(int with_scale) {
// build edge info
auto& V = hierarchy.mV[0];
auto& F = hierarchy.mF;
@@ -80,9 +80,12 @@ void Parametrizer::ComputeIndexMap(int with_scale) {
#ifdef LOG_OUTPUT
printf("subdivide...\n");
#endif
- subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
- edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges,
- singularities, 1);
+ if (!subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
+ edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges,
+ singularities, 1))
+ {
+ return false;
+ }
allow_changes.clear();
allow_changes.resize(edge_diff.size() * 2, 1);
@@ -99,9 +102,12 @@ void Parametrizer::ComputeIndexMap(int with_scale) {
int t1 = GetCurrentTime64();
#endif
FixFlipHierarchy();
- subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
+ if (!subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges,
- singularities, 1);
+ singularities, 1))
+ {
+ return false;
+ }
FixFlipSat();
#ifdef LOG_OUTPUT
@@ -242,6 +248,7 @@ void Parametrizer::ComputeIndexMap(int with_scale) {
// E2E_compact,
// V, N, Q, O, F, V2E, hierarchy.mE2E, disajoint_tree,
// hierarchy.mScale, false);
+ return true;
}
} // namespace qflow
diff --git a/extern/quadriflow/src/parametrizer.hpp b/extern/quadriflow/src/parametrizer.hpp
index 1f4a02be6c2..9703ebbfff6 100644
--- a/extern/quadriflow/src/parametrizer.hpp
+++ b/extern/quadriflow/src/parametrizer.hpp
@@ -54,7 +54,8 @@ class Parametrizer {
void ComputePositionSingularities();
// Integer Grid Map Pipeline
- void ComputeIndexMap(int with_scale = 0);
+ // Return false when the solver fails.
+ bool ComputeIndexMap(int with_scale = 0);
void BuildEdgeInfo();
void ComputeMaxFlow();
void MarkInteger();
diff --git a/extern/quadriflow/src/post-solver.cpp b/extern/quadriflow/src/post-solver.cpp
index 6027ddd..ccefd15 100644
--- a/extern/quadriflow/src/post-solver.cpp
@@ -389,3 +471,71 @@ index 6027ddd..ccefd15 100644
#include <cmath>
#include <cstdio>
#include <string>
diff --git a/extern/quadriflow/src/subdivide.cpp b/extern/quadriflow/src/subdivide.cpp
index c408bbc6394..babff96ccb4 100644
--- a/extern/quadriflow/src/subdivide.cpp
+++ b/extern/quadriflow/src/subdivide.cpp
@@ -145,7 +145,7 @@ void subdivide(MatrixXi &F, MatrixXd &V, VectorXd& rho, VectorXi &V2E, VectorXi
E2E.conservativeResize(nF * 3);
}
-void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
+bool subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold,
std::vector<Vector2i> &edge_diff, std::vector<DEdge> &edge_values,
std::vector<Vector3i> &face_edgeOrients, std::vector<Vector3i> &face_edgeIds,
@@ -500,17 +500,18 @@ void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, Matr
for (int j = 0; j < 3; ++j) {
auto diff = edge_diff[face_edgeIds[i][j]];
if (abs(diff[0]) > 1 || abs(diff[1]) > 1) {
- printf("wrong init %d %d!\n", face_edgeIds[i][j], i * 3 + j);
- exit(0);
+ fprintf(stderr, "wrong init %d %d!\n", face_edgeIds[i][j], i * 3 + j);
+ return false;
}
}
}
for (int i = 0; i < edge_diff.size(); ++i) {
if (abs(edge_diff[i][0]) > 1 || abs(edge_diff[i][1]) > 1) {
- printf("wrong...\n");
- exit(0);
+ fprintf(stderr, "wrong...\n");
+ return false;
}
}
+ return true;
}
} // namespace qflow
diff --git a/extern/quadriflow/src/subdivide.hpp b/extern/quadriflow/src/subdivide.hpp
index a93c58ac2a7..8c682b6d9f2 100644
--- a/extern/quadriflow/src/subdivide.hpp
+++ b/extern/quadriflow/src/subdivide.hpp
@@ -9,7 +9,8 @@ namespace qflow {
void subdivide(MatrixXi &F, MatrixXd &V, VectorXd& rho, VectorXi &V2E, VectorXi &E2E, VectorXi &boundary,
VectorXi &nonmanifold, double maxLength);
-void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
+// Return false when solving fails.
+bool subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold,
std::vector<Vector2i> &edge_diff, std::vector<DEdge> &edge_values,
std::vector<Vector3i> &face_edgeOrients, std::vector<Vector3i> &face_edgeIds,
diff --git a/intern/quadriflow/quadriflow_capi.cpp b/intern/quadriflow/quadriflow_capi.cpp
index fad604f679a..014ac2a5613 100644
--- a/intern/quadriflow/quadriflow_capi.cpp
+++ b/intern/quadriflow/quadriflow_capi.cpp
@@ -190,8 +190,11 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
return;
}
- /* Compute the final quad geomtry using a maxflow solver */
- field.ComputeIndexMap();
+ /* Compute the final quad geometry using a maxflow solver */
+ if (!field.ComputeIndexMap()) {
+ /* Error computing the result. */
+ return;
+ }
if (check_if_canceled(0.9f, update_cb, update_cb_data)) {
return;

View File

@@ -110,7 +110,10 @@ int main(int argc, char** argv) {
printf("Use %lf seconds\n", (t2 - t1) * 1e-3);
t1 = GetCurrentTime64();
printf("Solve index map...\n");
field.ComputeIndexMap();
if (!field.ComputeIndexMap()) {
fprintf(stderr, "Failed to solve result, exiting!\n");
return 1;
}
t2 = GetCurrentTime64();
printf("Indexmap Use %lf seconds\n", (t2 - t1) * 1e-3);
printf("Writing the file...\n");

View File

@@ -18,7 +18,7 @@
namespace qflow {
void Parametrizer::ComputeIndexMap(int with_scale) {
bool Parametrizer::ComputeIndexMap(int with_scale) {
// build edge info
auto& V = hierarchy.mV[0];
auto& F = hierarchy.mF;
@@ -80,9 +80,12 @@ void Parametrizer::ComputeIndexMap(int with_scale) {
#ifdef LOG_OUTPUT
printf("subdivide...\n");
#endif
subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges,
singularities, 1);
if (!subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges,
singularities, 1))
{
return false;
}
allow_changes.clear();
allow_changes.resize(edge_diff.size() * 2, 1);
@@ -99,9 +102,12 @@ void Parametrizer::ComputeIndexMap(int with_scale) {
int t1 = GetCurrentTime64();
#endif
FixFlipHierarchy();
subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
if (!subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges,
singularities, 1);
singularities, 1))
{
return false;
}
FixFlipSat();
#ifdef LOG_OUTPUT
@@ -242,6 +248,7 @@ void Parametrizer::ComputeIndexMap(int with_scale) {
// E2E_compact,
// V, N, Q, O, F, V2E, hierarchy.mE2E, disajoint_tree,
// hierarchy.mScale, false);
return true;
}
} // namespace qflow

View File

@@ -54,7 +54,8 @@ class Parametrizer {
void ComputePositionSingularities();
// Integer Grid Map Pipeline
void ComputeIndexMap(int with_scale = 0);
// Return false when the solver fails.
bool ComputeIndexMap(int with_scale = 0);
void BuildEdgeInfo();
void ComputeMaxFlow();
void MarkInteger();

View File

@@ -145,7 +145,7 @@ void subdivide(MatrixXi &F, MatrixXd &V, VectorXd& rho, VectorXi &V2E, VectorXi
E2E.conservativeResize(nF * 3);
}
void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
bool subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold,
std::vector<Vector2i> &edge_diff, std::vector<DEdge> &edge_values,
std::vector<Vector3i> &face_edgeOrients, std::vector<Vector3i> &face_edgeIds,
@@ -500,17 +500,18 @@ void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, Matr
for (int j = 0; j < 3; ++j) {
auto diff = edge_diff[face_edgeIds[i][j]];
if (abs(diff[0]) > 1 || abs(diff[1]) > 1) {
printf("wrong init %d %d!\n", face_edgeIds[i][j], i * 3 + j);
exit(0);
fprintf(stderr, "wrong init %d %d!\n", face_edgeIds[i][j], i * 3 + j);
return false;
}
}
}
for (int i = 0; i < edge_diff.size(); ++i) {
if (abs(edge_diff[i][0]) > 1 || abs(edge_diff[i][1]) > 1) {
printf("wrong...\n");
exit(0);
fprintf(stderr, "wrong...\n");
return false;
}
}
return true;
}
} // namespace qflow

View File

@@ -9,7 +9,8 @@ namespace qflow {
void subdivide(MatrixXi &F, MatrixXd &V, VectorXd& rho, VectorXi &V2E, VectorXi &E2E, VectorXi &boundary,
VectorXi &nonmanifold, double maxLength);
void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
// Return false when solving fails.
bool subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold,
std::vector<Vector2i> &edge_diff, std::vector<DEdge> &edge_values,
std::vector<Vector3i> &face_edgeOrients, std::vector<Vector3i> &face_edgeIds,

View File

@@ -190,8 +190,11 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
return;
}
/* Compute the final quad geomtry using a maxflow solver */
field.ComputeIndexMap();
/* Compute the final quad geometry using a maxflow solver */
if (!field.ComputeIndexMap()) {
/* Error computing the result. */
return;
}
if (check_if_canceled(0.9f, update_cb, update_cb_data)) {
return;