From 78357057b6f129a5bca9b3014205c36fc1d2cb51 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 23 May 2016 14:20:25 -0700 Subject: [PATCH] return non-zero on error, add verbose option --- tools/vhacd-util/src/VHACDUtil.cpp | 70 ++++++++++++++++++--------- tools/vhacd-util/src/VHACDUtil.h | 10 +++- tools/vhacd-util/src/VHACDUtilApp.cpp | 56 +++++++++++++++------ tools/vhacd-util/src/VHACDUtilApp.h | 11 ++++- tools/vhacd-util/src/main.cpp | 2 +- 5 files changed, 107 insertions(+), 42 deletions(-) diff --git a/tools/vhacd-util/src/VHACDUtil.cpp b/tools/vhacd-util/src/VHACDUtil.cpp index c1fbc1c2a6..dcd8bdd5b6 100644 --- a/tools/vhacd-util/src/VHACDUtil.cpp +++ b/tools/vhacd-util/src/VHACDUtil.cpp @@ -28,13 +28,16 @@ void reSortFBXGeometryMeshes(FBXGeometry& geometry) { // Read all the meshes from provided FBX file bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { + if (_verbose) { + qDebug() << "reading FBX file =" << filename << "..."; + } // open the fbx file QFile fbx(filename); if (!fbx.open(QIODevice::ReadOnly)) { + qWarning() << "unable to open FBX file =" << filename; return false; } - qDebug() << "reading FBX file =" << filename << "..."; try { QByteArray fbxContents = fbx.readAll(); FBXGeometry* geom; @@ -43,14 +46,14 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { } else if (filename.toLower().endsWith(".fbx")) { geom = readFBX(fbxContents, QVariantHash(), filename); } else { - qDebug() << "unknown file extension"; + qWarning() << "unknown file extension"; return false; } result = *geom; reSortFBXGeometryMeshes(result); } catch (const QString& error) { - qDebug() << "Error reading" << filename << ":" << error; + qWarning() << "error reading" << filename << ":" << error; return false; } @@ -230,10 +233,12 @@ bool isClosedManifold(const std::vector& triangles) { return true; } -void getConvexResults(VHACD::IVHACD* convexifier, FBXMesh& resultMesh) { +void vhacd::VHACDUtil::getConvexResults(VHACD::IVHACD* convexifier, FBXMesh& resultMesh) const { // Number of hulls for this input meshPart unsigned int numHulls = convexifier->GetNConvexHulls(); - qDebug() << " hulls =" << numHulls; + if (_verbose) { + qDebug() << " hulls =" << numHulls; + } // create an output meshPart for each convex hull for (unsigned int j = 0; j < numHulls; j++) { @@ -259,9 +264,11 @@ void getConvexResults(VHACD::IVHACD* convexifier, FBXMesh& resultMesh) { resultMeshPart.triangleIndices.append(index1); resultMeshPart.triangleIndices.append(index2); } - qDebug() << " hull" << j << " vertices =" << hull.m_nPoints - << " triangles =" << hull.m_nTriangles - << " FBXMeshVertices =" << resultMesh.vertices.size(); + if (_verbose) { + qDebug() << " hull" << j << " vertices =" << hull.m_nPoints + << " triangles =" << hull.m_nTriangles + << " FBXMeshVertices =" << resultMesh.vertices.size(); + } } } @@ -273,14 +280,18 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, VHACD::IVHACD::Parameters params, FBXGeometry& result, float minimumMeshSize, float maximumMeshSize) { - qDebug() << "meshes =" << geometry.meshes.size(); + if (_verbose) { + qDebug() << "meshes =" << geometry.meshes.size(); + } // count the mesh-parts int numParts = 0; foreach (const FBXMesh& mesh, geometry.meshes) { numParts += mesh.parts.size(); } - qDebug() << "total parts =" << numParts; + if (_verbose) { + qDebug() << "total parts =" << numParts; + } VHACD::IVHACD * convexifier = VHACD::CreateVHACD(); @@ -315,9 +326,11 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, } auto numVertices = vertices.size(); - qDebug() << "mesh" << meshIndex << ": " - << " parts =" << mesh.parts.size() << " clusters =" << mesh.clusters.size() - << " vertices =" << numVertices; + if (_verbose) { + qDebug() << "mesh" << meshIndex << ": " + << " parts =" << mesh.parts.size() << " clusters =" << mesh.clusters.size() + << " vertices =" << numVertices; + } ++meshIndex; std::vector openParts; @@ -329,7 +342,9 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, // only process meshes with triangles if (triangles.size() <= 0) { - qDebug() << " skip part" << partIndex << "(zero triangles)"; + if (_verbose) { + qDebug() << " skip part" << partIndex << "(zero triangles)"; + } ++partIndex; continue; } @@ -343,13 +358,17 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, const float largestDimension = aaBox.getLargestDimension(); if (largestDimension < minimumMeshSize) { - qDebug() << " skip part" << partIndex << ": dimension =" << largestDimension << "(too small)"; + if (_verbose) { + qDebug() << " skip part" << partIndex << ": dimension =" << largestDimension << "(too small)"; + } ++partIndex; continue; } if (maximumMeshSize > 0.0f && largestDimension > maximumMeshSize) { - qDebug() << " skip part" << partIndex << ": dimension =" << largestDimension << "(too large)"; + if (_verbose) { + qDebug() << " skip part" << partIndex << ": dimension =" << largestDimension << "(too large)"; + } ++partIndex; continue; } @@ -358,18 +377,21 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, bool closed = isClosedManifold(triangles); if (closed) { unsigned int triangleCount = triangles.size() / 3; - qDebug() << " process closed part" << partIndex << ": " - << " triangles =" << triangleCount; + if (_verbose) { + qDebug() << " process closed part" << partIndex << ": " << " triangles =" << triangleCount; + } // compute approximate convex decomposition bool success = convexifier->Compute(&vertices[0].x, 3, (uint)numVertices, &triangles[0], 3, triangleCount, params); if (success) { getConvexResults(convexifier, resultMesh); - } else { + } else if (_verbose) { qDebug() << " failed to convexify"; } } else { - qDebug() << " postpone open part" << partIndex; + if (_verbose) { + qDebug() << " postpone open part" << partIndex; + } openParts.push_back(partIndex); } ++partIndex; @@ -391,14 +413,16 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, // this time we don't care if the parts are close or not unsigned int triangleCount = triangles.size() / 3; - qDebug() << " process remaining open parts =" << openParts.size() << ": " - << " triangles =" << triangleCount; + if (_verbose) { + qDebug() << " process remaining open parts =" << openParts.size() << ": " + << " triangles =" << triangleCount; + } // compute approximate convex decomposition bool success = convexifier->Compute(&vertices[0].x, 3, (uint)numVertices, &triangles[0], 3, triangleCount, params); if (success) { getConvexResults(convexifier, resultMesh); - } else { + } else if (_verbose) { qDebug() << " failed to convexify"; } } diff --git a/tools/vhacd-util/src/VHACDUtil.h b/tools/vhacd-util/src/VHACDUtil.h index 62d1779946..04e8dab92d 100644 --- a/tools/vhacd-util/src/VHACDUtil.h +++ b/tools/vhacd-util/src/VHACDUtil.h @@ -25,6 +25,8 @@ namespace vhacd { class VHACDUtil { public: + void setVerbose(bool verbose) { _verbose = verbose; } + bool loadFBX(const QString filename, FBXGeometry& result); void fattenMeshes(const FBXMesh& mesh, FBXMesh& result, @@ -35,7 +37,13 @@ namespace vhacd { VHACD::IVHACD::Parameters params, FBXGeometry& result, float minimumMeshSize, float maximumMeshSize); + + void getConvexResults(VHACD::IVHACD* convexifier, FBXMesh& resultMesh) const; + ~VHACDUtil(); + + private: + bool _verbose { false }; }; class ProgressCallback : public VHACD::IVHACD::IUserCallback { @@ -44,7 +52,7 @@ namespace vhacd { ~ProgressCallback(); // Couldn't follow coding guideline here due to virtual function declared in IUserCallback - void Update(const double overallProgress, const double stageProgress, const double operationProgress, + void Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation); }; } diff --git a/tools/vhacd-util/src/VHACDUtilApp.cpp b/tools/vhacd-util/src/VHACDUtilApp.cpp index 64d4fb3588..97b483290a 100644 --- a/tools/vhacd-util/src/VHACDUtilApp.cpp +++ b/tools/vhacd-util/src/VHACDUtilApp.cpp @@ -18,6 +18,9 @@ using namespace std; using namespace VHACD; +const int VHACD_RETURN_CODE_FAILURE_TO_READ = 1; +const int VHACD_RETURN_CODE_FAILURE_TO_WRITE = 2; +const int VHACD_RETURN_CODE_FAILURE_TO_CONVEXIFY = 3; QString formatFloat(double n) { @@ -33,14 +36,15 @@ QString formatFloat(double n) { } -bool writeOBJ(QString outFileName, FBXGeometry& geometry, bool outputCentimeters, int whichMeshPart = -1) { +bool VHACDUtilApp::writeOBJ(QString outFileName, FBXGeometry& geometry, bool outputCentimeters, int whichMeshPart) { QFile file(outFileName); if (!file.open(QIODevice::WriteOnly)) { - qDebug() << "Unable to write to " << outFileName; + qWarning() << "unable to write to" << outFileName; + _returnCode = VHACD_RETURN_CODE_FAILURE_TO_WRITE; return false; } - QTextStream out(&file); + QTextStream out(&file); if (outputCentimeters) { out << "# This file uses centimeters as units\n\n"; } @@ -105,6 +109,9 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : const QCommandLineOption helpOption = parser.addHelpOption(); + const QCommandLineOption verboseOutput("v", "verbose output"); + parser.addOption(verboseOutput); + const QCommandLineOption splitOption("split", "split input-file into one mesh per output-file"); parser.addOption(splitOption); @@ -195,8 +202,10 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : Q_UNREACHABLE(); } - bool outputCentimeters = parser.isSet(outputCentimetersOption); + bool verbose = parser.isSet(verboseOutput); + vUtil.setVerbose(verbose); + bool outputCentimeters = parser.isSet(outputCentimetersOption); bool fattenFaces = parser.isSet(fattenFacesOption); bool generateHulls = parser.isSet(generateHullsOption); bool splitModel = parser.isSet(splitOption); @@ -305,13 +314,15 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : FBXGeometry fbx; auto begin = std::chrono::high_resolution_clock::now(); if (!vUtil.loadFBX(inputFilename, fbx)){ - qDebug() << "error reading input file" << inputFilename; + _returnCode = VHACD_RETURN_CODE_FAILURE_TO_READ; return; } auto end = std::chrono::high_resolution_clock::now(); auto loadDuration = std::chrono::duration_cast(end - begin).count(); - qDebug() << "load time =" << (double)loadDuration / 1000000000.00 << "seconds"; + if (verbose) { + qDebug() << "load time =" << (double)loadDuration / 1000000000.00 << "seconds"; + } if (splitModel) { QVector infileExtensions = {"fbx", "obj"}; @@ -332,7 +343,11 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : vhacd::ProgressCallback progressCallback; //set parameters for V-HACD - params.m_callback = &progressCallback; //progress callback + if (verbose) { + params.m_callback = &progressCallback; //progress callback + } else { + params.m_callback = nullptr; + } params.m_resolution = vHacdResolution; params.m_depth = vHacdDepth; params.m_concavity = vHacdConcavity; @@ -346,12 +361,14 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : params.m_mode = 0; // 0: voxel-based (recommended), 1: tetrahedron-based params.m_maxNumVerticesPerCH = vHacdMaxVerticesPerCH; params.m_minVolumePerCH = 0.0001; // 0.0001 - params.m_logger = 0; // 0 + params.m_logger = nullptr; params.m_convexhullApproximation = true; // true params.m_oclAcceleration = true; // true //perform vhacd computation - qDebug() << "running V-HACD algorithm ..."; + if (verbose) { + qDebug() << "running V-HACD algorithm ..."; + } begin = std::chrono::high_resolution_clock::now(); FBXGeometry result; @@ -359,10 +376,15 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : end = std::chrono::high_resolution_clock::now(); auto computeDuration = std::chrono::duration_cast(end - begin).count(); - qDebug() << "run time =" << (double)computeDuration / 1000000000.00 << " seconds"; + if (verbose) { + qDebug() << "run time =" << (double)computeDuration / 1000000000.00 << " seconds"; + } if (!success) { - qDebug() << "failed to convexify model"; + if (verbose) { + qDebug() << "failed to convexify model"; + } + _returnCode = VHACD_RETURN_CODE_FAILURE_TO_CONVEXIFY; return; } @@ -377,11 +399,13 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : } } - int totalHulls = result.meshes[0].parts.size(); - qDebug() << "output file =" << outputFilename; - qDebug() << "vertices =" << totalVertices; - qDebug() << "triangles =" << totalTriangles; - qDebug() << "hulls =" << totalHulls; + if (verbose) { + int totalHulls = result.meshes[0].parts.size(); + qDebug() << "output file =" << outputFilename; + qDebug() << "vertices =" << totalVertices; + qDebug() << "triangles =" << totalTriangles; + qDebug() << "hulls =" << totalHulls; + } writeOBJ(outputFilename, result, outputCentimeters); } diff --git a/tools/vhacd-util/src/VHACDUtilApp.h b/tools/vhacd-util/src/VHACDUtilApp.h index 016b7b7b2f..9405126c65 100644 --- a/tools/vhacd-util/src/VHACDUtilApp.h +++ b/tools/vhacd-util/src/VHACDUtilApp.h @@ -15,12 +15,21 @@ #include +#include + class VHACDUtilApp : public QCoreApplication { Q_OBJECT - public: +public: VHACDUtilApp(int argc, char* argv[]); ~VHACDUtilApp(); + + bool writeOBJ(QString outFileName, FBXGeometry& geometry, bool outputCentimeters, int whichMeshPart = -1); + + int getReturnCode() const { return _returnCode; } + +private: + int _returnCode { 0 }; }; diff --git a/tools/vhacd-util/src/main.cpp b/tools/vhacd-util/src/main.cpp index 0e8d72abd3..42c9db9513 100644 --- a/tools/vhacd-util/src/main.cpp +++ b/tools/vhacd-util/src/main.cpp @@ -23,5 +23,5 @@ using namespace VHACD; int main(int argc, char * argv[]) { VHACDUtilApp app(argc, argv); - return 0; + return app.getReturnCode(); }