From 0d093b4921b5ae7e8dfcc6afc0924093eb8ac2f5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 5 Mar 2015 15:38:55 -0800 Subject: [PATCH] rename binary from vhacd to vhacd-util. vhacd-util outpus obj files --- tools/vhacd/CMakeLists.txt | 4 +- tools/vhacd/src/VHACDUtil.cpp | 22 +++ tools/vhacd/src/VHACDUtil.h | 16 +- tools/vhacd/src/VHACDUtilApp.cpp | 250 +++++++++++++++++++++++++++++++ tools/vhacd/src/VHACDUtilApp.h | 28 ++++ tools/vhacd/src/main.cpp | 119 +-------------- 6 files changed, 315 insertions(+), 124 deletions(-) create mode 100644 tools/vhacd/src/VHACDUtilApp.cpp create mode 100644 tools/vhacd/src/VHACDUtilApp.h diff --git a/tools/vhacd/CMakeLists.txt b/tools/vhacd/CMakeLists.txt index 31a7f7c8e2..f003b685e0 100644 --- a/tools/vhacd/CMakeLists.txt +++ b/tools/vhacd/CMakeLists.txt @@ -1,5 +1,5 @@ -set(TARGET_NAME vhacd) -setup_hifi_project() +set(TARGET_NAME vhacd-util) +setup_hifi_project(Core Widgets) link_hifi_libraries(shared model fbx gpu networking octree) #find_package(VHACD REQUIRED) done in CMakeList.txt in parent directory diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp index 0f72032af1..caa213572b 100644 --- a/tools/vhacd/src/VHACDUtil.cpp +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -13,6 +13,11 @@ #include "VHACDUtil.h" + + + + + //Read all the meshes from provided FBX file bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *results) { @@ -82,6 +87,23 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD for (unsigned int j = 0; j < nConvexHulls; j++){ VHACD::IVHACD::ConvexHull hull; interfaceVHACD->GetConvexHull(j, hull); + + double *m_points_copy = new double[hull.m_nPoints * 3]; + // std::copy(std::begin(hull.m_points), std::end(hull.m_points), std::begin(m_points_copy)); + for (unsigned int i=0; iconvexHullList.append(convexHulls); diff --git a/tools/vhacd/src/VHACDUtil.h b/tools/vhacd/src/VHACDUtil.h index b87ba07ff0..ce1c157025 100644 --- a/tools/vhacd/src/VHACDUtil.h +++ b/tools/vhacd/src/VHACDUtil.h @@ -21,28 +21,28 @@ #include #include -namespace vhacd{ +namespace vhacd { - typedef struct{ + typedef struct { int meshCount; QVector convexHullsCountList; QVector> convexHullList; - }ComputeResults; + } ComputeResults; - typedef struct{ + typedef struct { int meshCount; QVector> perMeshVertices; QVector> perMeshTriangleIndices; - }LoadFBXResults; + } LoadFBXResults; - class VHACDUtil{ + class VHACDUtil { public: bool loadFBX(const QString filename, vhacd::LoadFBXResults *results); bool computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, vhacd::ComputeResults *results)const; ~VHACDUtil(); }; - class ProgressCallback : public VHACD::IVHACD::IUserCallback{ + class ProgressCallback : public VHACD::IVHACD::IUserCallback { public: ProgressCallback(void); ~ProgressCallback(); @@ -52,4 +52,4 @@ namespace vhacd{ const char * const stage, const char * const operation); }; } -#endif //hifi_VHACDUtil_h \ No newline at end of file +#endif //hifi_VHACDUtil_h diff --git a/tools/vhacd/src/VHACDUtilApp.cpp b/tools/vhacd/src/VHACDUtilApp.cpp new file mode 100644 index 0000000000..d4b0f48766 --- /dev/null +++ b/tools/vhacd/src/VHACDUtilApp.cpp @@ -0,0 +1,250 @@ +// +// VHACDUtil.h +// tools/vhacd/src +// +// Created by Seth Alves on 3/5/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include "VHACDUtilApp.h" +#include "VHACDUtil.h" + +using namespace std; +using namespace VHACD; + + + +QString formatFloat(double n) { + // limit precision to 6, but don't output trailing zeros. + QString s = QString::number(n, 'f', 6); + while (s.endsWith("0")) { + s.remove(s.size() - 1, 1); + } + if (s.endsWith(".")) { + s.remove(s.size() - 1, 1); + } + return s; +} + + +bool writeOBJ(QString outFileName, QVector>& convexHullList, bool outputOneMesh) { + QFile file(outFileName); + if (!file.open(QIODevice::WriteOnly)) { + qDebug() << "Unable to write to " << outFileName; + return false; + } + + QTextStream out(&file); + + + if (convexHullList.size() != 1) { + qDebug() << "unexpected number of meshes --" << convexHullList.size(); + exit(1); + } + + QVector hulls = convexHullList[0]; + + + if (outputOneMesh) { + foreach (VHACD::IVHACD::ConvexHull hull, hulls) { + for (unsigned int i = 0; i < hull.m_nPoints; i++) { + out << "v "; + out << formatFloat(hull.m_points[i*3]) << " "; + out << formatFloat(hull.m_points[i*3+1]) << " "; + out << formatFloat(hull.m_points[i*3+2]) << " 1\n"; + } + } + + unsigned int pointStartOffset = 0; + foreach (VHACD::IVHACD::ConvexHull hull, hulls) { + for (unsigned int i = 0; i < hull.m_nTriangles; i++) { + out << "f "; + out << hull.m_triangles[i*3] + 1 + pointStartOffset << " "; + out << hull.m_triangles[i*3+1] + 1 + pointStartOffset << " "; + out << hull.m_triangles[i*3+2] + 1 + pointStartOffset << "\n"; + } + pointStartOffset += hull.m_nPoints; + } + } else { + unsigned int nth = 0; + foreach (VHACD::IVHACD::ConvexHull hull, hulls) { + out << "o hull-" << nth++ << "\n"; + for (unsigned int i = 0; i < hull.m_nPoints; i++) { + out << "v "; + out << formatFloat(hull.m_points[i*3]) << " "; + out << formatFloat(hull.m_points[i*3+1]) << " "; + out << formatFloat(hull.m_points[i*3+2]) << " 1\n"; + } + for (unsigned int i = 0; i < hull.m_nTriangles; i++) { + out << "f "; + out << hull.m_triangles[i*3] + 1 << " "; + out << hull.m_triangles[i*3+1] + 1 << " "; + out << hull.m_triangles[i*3+2] + 1 << "\n"; + } + out << "\n"; + } + } + + return true; +} + + + + +VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : + QCoreApplication(argc, argv) +{ + vector triangles; // array of indexes + vector points; // array of coordinates + vhacd::VHACDUtil vUtil; + vhacd::LoadFBXResults fbx; //mesh data from loaded fbx file + vhacd::ComputeResults results; // results after computing vhacd + VHACD::IVHACD::Parameters params; + vhacd::ProgressCallback pCallBack; + + + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity Object Decomposer"); + parser.addHelpOption(); + + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption outputOneMeshOption("1", "output hulls as single mesh"); + parser.addOption(outputOneMeshOption); + + const QCommandLineOption inputFilenameOption("i", "input file", "filename.fbx"); + parser.addOption(inputFilenameOption); + + const QCommandLineOption outputFilenameOption("o", "output file", "filename.obj"); + parser.addOption(outputFilenameOption); + + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + Q_UNREACHABLE(); + } + + + bool outputOneMesh = parser.isSet(outputOneMeshOption); + + QString inputFilename; + // check for an assignment pool passed on the command line or in the config + if (parser.isSet(inputFilenameOption)) { + inputFilename = parser.value(inputFilenameOption); + } + + QString outputFilename; + // check for an assignment pool passed on the command line or in the config + if (parser.isSet(outputFilenameOption)) { + outputFilename = parser.value(outputFilenameOption); + } + + + if (inputFilename == "") { + cerr << "input filename is required."; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (outputFilename == "") { + cerr << "output filename is required."; + parser.showHelp(); + Q_UNREACHABLE(); + } + + + //set parameters for V-HACD + params.m_callback = &pCallBack; //progress callback + params.m_resolution = 100000; // 100000 + params.m_depth = 20; // 20 + params.m_concavity = 0.001; // 0.001 + params.m_delta = 0.01; // 0.05 + params.m_planeDownsampling = 4; // 4 + params.m_convexhullDownsampling = 4; // 4 + params.m_alpha = 0.05; // 0.05 // controls the bias toward clipping along symmetry planes + params.m_beta = 0.05; // 0.05 + params.m_gamma = 0.0005; // 0.0005 + params.m_pca = 0; // 0 enable/disable normalizing the mesh before applying the convex decomposition + params.m_mode = 0; // 0: voxel-based (recommended), 1: tetrahedron-based + params.m_maxNumVerticesPerCH = 64; // 64 + params.m_minVolumePerCH = 0.00001; // 0.0001 + params.m_callback = 0; // 0 + params.m_logger = 0; // 0 + params.m_convexhullApproximation = true; // true + params.m_oclAcceleration = true; // true + + + + // load the mesh + + auto begin = std::chrono::high_resolution_clock::now(); + if (!vUtil.loadFBX(inputFilename, &fbx)){ + cout << "Error in opening FBX file...."; + } + auto end = std::chrono::high_resolution_clock::now(); + auto loadDuration = std::chrono::duration_cast(end - begin).count(); + + //perform vhacd computation + begin = std::chrono::high_resolution_clock::now(); + + + if (!vUtil.computeVHACD(&fbx, params, &results)){ + cout << "Compute Failed..."; + } + end = std::chrono::high_resolution_clock::now(); + auto computeDuration = std::chrono::duration_cast(end - begin).count(); + + int totalVertices = 0; + for (int i = 0; i < fbx.meshCount; i++){ + totalVertices += fbx.perMeshVertices.at(i).count(); + } + + int totalTriangles = 0; + for (int i = 0; i < fbx.meshCount; i++){ + totalTriangles += fbx.perMeshTriangleIndices.at(i).count(); + } + + int totalHulls = 0; + QVector hullCounts = results.convexHullsCountList; + for (int i = 0; i < results.meshCount; i++){ + totalHulls += hullCounts.at(i); + } + cout << endl << "Summary of V-HACD Computation..................." << endl; + cout << "File Path : " << inputFilename.toStdString() << endl; + cout << "Number Of Meshes : " << fbx.meshCount << endl; + cout << "Processed Meshes : " << results.meshCount << endl; + cout << "Total vertices : " << totalVertices << endl; + cout << "Total Triangles : " << totalTriangles << endl; + cout << "Total Convex Hulls : " << totalHulls << endl; + cout << "Total FBX load time: " << (double)loadDuration / 1000000000.00 << " seconds" << endl; + cout << "V-HACD Compute time: " << (double)computeDuration / 1000000000.00 << " seconds" << endl; + cout << endl << "Summary per convex hull ........................" << endl < chList = results.convexHullList.at(i); + cout << "\t" << "Number Of Hulls : " << chList.count() << endl; + + for (int j = 0; j < results.convexHullList.at(i).count(); j++){ + cout << "\tHUll : " << j + 1 << endl; + cout << "\t\tNumber Of Points : " << chList.at(j).m_nPoints << endl; + cout << "\t\tNumber Of Triangles : " << chList.at(j).m_nTriangles << endl; + } + } + + writeOBJ(outputFilename, results.convexHullList, outputOneMesh); +} + +VHACDUtilApp::~VHACDUtilApp() { +} diff --git a/tools/vhacd/src/VHACDUtilApp.h b/tools/vhacd/src/VHACDUtilApp.h new file mode 100644 index 0000000000..016b7b7b2f --- /dev/null +++ b/tools/vhacd/src/VHACDUtilApp.h @@ -0,0 +1,28 @@ +// +// VHACDUtil.h +// tools/vhacd/src +// +// Created by Seth Alves on 3/5/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#ifndef hifi_VHACDUtilApp_h +#define hifi_VHACDUtilApp_h + +#include + + +class VHACDUtilApp : public QCoreApplication { + Q_OBJECT + public: + VHACDUtilApp(int argc, char* argv[]); + ~VHACDUtilApp(); +}; + + + +#endif //hifi_VHACDUtilApp_h diff --git a/tools/vhacd/src/main.cpp b/tools/vhacd/src/main.cpp index 530f4ad648..0e8d72abd3 100644 --- a/tools/vhacd/src/main.cpp +++ b/tools/vhacd/src/main.cpp @@ -8,129 +8,20 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -#include +// #include #include #include #include #include #include -#include "VHACDUtil.h" + +#include "VHACDUtilApp.h" using namespace std; using namespace VHACD; -bool writeOBJ(QString outFileName, QVector>& convexHullList) { - QFile file(outFileName); - if (!file.open(QIODevice::WriteOnly)) { - qDebug() << "Unable to write to " << outFileName; - return false; - } - - QTextStream out(&file); - - out << "testing\n"; - - return true; -} - - -int main(int argc, char * argv[]){ - vector triangles; // array of indexes - vector points; // array of coordinates - vhacd::VHACDUtil vUtil; - vhacd::LoadFBXResults fbx; //mesh data from loaded fbx file - vhacd::ComputeResults results; // results after computing vhacd - VHACD::IVHACD::Parameters params; - vhacd::ProgressCallback pCallBack; - if (argc < 3) { - cout << argv[0] << " input-file.fbx output-file.obj\n"; - return 1; - } - string inputFilename(argv[1]); - if (inputFilename.empty()) { - cout << "please provide a FBX file as first argument\n"; - return 1; - } - string outputFilename(argv[2]); - if (outputFilename.empty()) { - cout << "please provide a OBJ file as second argument\n"; - return 1; - } - - QString inFileName = QString::fromStdString(inputFilename); - QString outFileName = QString::fromStdString(outputFilename); - - //set parameters for V-HACD - params.m_callback = &pCallBack; //progress callback - params.m_resolution = 50000; - params.m_depth = 10; - params.m_concavity = 0.003; - params.m_alpha = 0.05; // controls the bias toward clipping along symmetry planes - params.m_pca = 1; // enable/disable normalizing the mesh before applying the convex decomposition - params.m_mode = 1; // 0: voxel - based approximate convex decomposition, 1 : tetrahedron - based approximate convex decomposition - params.m_maxNumVerticesPerCH = 128; - params.m_minVolumePerCH = 0.0001; // controls the adaptive sampling of the generated convex - hulls - - // load the mesh - - auto begin = std::chrono::high_resolution_clock::now(); - if (!vUtil.loadFBX(inFileName, &fbx)){ - cout << "Error in opening FBX file...."; - return 1; - } - auto end = std::chrono::high_resolution_clock::now(); - auto loadDuration = std::chrono::duration_cast(end - begin).count(); - - //perform vhacd computation - begin = std::chrono::high_resolution_clock::now(); - if (!vUtil.computeVHACD(&fbx, params, &results)){ - cout << "Compute Failed..."; - return 1; - } - end = std::chrono::high_resolution_clock::now(); - auto computeDuration = std::chrono::duration_cast(end - begin).count(); - - int totalVertices = 0; - for (int i = 0; i < fbx.meshCount; i++){ - totalVertices += fbx.perMeshVertices.at(i).count(); - } - - int totalTriangles = 0; - for (int i = 0; i < fbx.meshCount; i++){ - totalTriangles += fbx.perMeshTriangleIndices.at(i).count(); - } - - int totalHulls = 0; - QVector hullCounts = results.convexHullsCountList; - for (int i = 0; i < results.meshCount; i++){ - totalHulls += hullCounts.at(i); - } - cout << endl << "Summary of V-HACD Computation..................." << endl; - cout << "File Path : " << inFileName.toStdString() << endl; - cout << "Number Of Meshes : " << fbx.meshCount << endl; - cout << "Processed Meshes : " << results.meshCount << endl; - cout << "Total vertices : " << totalVertices << endl; - cout << "Total Triangles : " << totalTriangles << endl; - cout << "Total Convex Hulls : " << totalHulls << endl; - cout << "Total FBX load time: " << (double)loadDuration / 1000000000.00 << " seconds" << endl; - cout << "V-HACD Compute time: " << (double)computeDuration / 1000000000.00 << " seconds" << endl; - cout << endl << "Summary per convex hull ........................" << endl < chList = results.convexHullList.at(i); - cout << "\t" << "Number Of Hulls : " << chList.count() << endl; - - for (int j = 0; j < results.convexHullList.at(i).count(); j++){ - cout << "\tHUll : " << j + 1 << endl; - cout << "\t\tNumber Of Points : " << chList.at(j).m_nPoints << endl; - cout << "\t\tNumber Of Triangles : " << chList.at(j).m_nTriangles << endl; - } - } - - - writeOBJ(outFileName, results.convexHullList); - - +int main(int argc, char * argv[]) { + VHACDUtilApp app(argc, argv); return 0; }