mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 10:02:13 +02:00
return non-zero on error, add verbose option
This commit is contained in:
parent
7d7c991447
commit
78357057b6
5 changed files with 107 additions and 42 deletions
|
@ -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<int>& 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<int> 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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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<std::chrono::nanoseconds>(end - begin).count();
|
||||
|
||||
qDebug() << "load time =" << (double)loadDuration / 1000000000.00 << "seconds";
|
||||
if (verbose) {
|
||||
qDebug() << "load time =" << (double)loadDuration / 1000000000.00 << "seconds";
|
||||
}
|
||||
|
||||
if (splitModel) {
|
||||
QVector<QString> 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<std::chrono::nanoseconds>(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);
|
||||
}
|
||||
|
|
|
@ -15,12 +15,21 @@
|
|||
|
||||
#include <QApplication>
|
||||
|
||||
#include <FBXReader.h>
|
||||
|
||||
|
||||
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 };
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -23,5 +23,5 @@ using namespace VHACD;
|
|||
|
||||
int main(int argc, char * argv[]) {
|
||||
VHACDUtilApp app(argc, argv);
|
||||
return 0;
|
||||
return app.getReturnCode();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue