mirror of
https://github.com/lubosz/overte.git
synced 2025-04-16 09:46:29 +02:00
rename binary from vhacd to vhacd-util. vhacd-util outpus obj files
This commit is contained in:
parent
034ceab4d3
commit
0d093b4921
6 changed files with 315 additions and 124 deletions
|
@ -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
|
||||
|
|
|
@ -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; i<hull.m_nPoints * 3; i++) {
|
||||
m_points_copy[ i ] = hull.m_points[ i ];
|
||||
}
|
||||
hull.m_points = m_points_copy;
|
||||
|
||||
|
||||
int *m_triangles_copy = new int[hull.m_nTriangles * 3];
|
||||
// std::copy(std::begin(hull.m_triangles), std::end(hull.m_triangles), std::begin(m_triangles_copy));
|
||||
for (unsigned int i=0; i<hull.m_nTriangles * 3; i++) {
|
||||
m_triangles_copy[ i ] = hull.m_triangles[ i ];
|
||||
}
|
||||
hull.m_triangles = m_triangles_copy;
|
||||
|
||||
|
||||
convexHulls.append(hull);
|
||||
}
|
||||
results->convexHullList.append(convexHulls);
|
||||
|
|
|
@ -21,28 +21,28 @@
|
|||
#include <FBXReader.h>
|
||||
#include <VHACD.h>
|
||||
|
||||
namespace vhacd{
|
||||
namespace vhacd {
|
||||
|
||||
typedef struct{
|
||||
typedef struct {
|
||||
int meshCount;
|
||||
QVector<int> convexHullsCountList;
|
||||
QVector<QVector<VHACD::IVHACD::ConvexHull>> convexHullList;
|
||||
}ComputeResults;
|
||||
} ComputeResults;
|
||||
|
||||
typedef struct{
|
||||
typedef struct {
|
||||
int meshCount;
|
||||
QVector<QVector<glm::vec3>> perMeshVertices;
|
||||
QVector<QVector<int>> 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
|
||||
#endif //hifi_VHACDUtil_h
|
||||
|
|
250
tools/vhacd/src/VHACDUtilApp.cpp
Normal file
250
tools/vhacd/src/VHACDUtilApp.cpp
Normal file
|
@ -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 <QCommandLineParser>
|
||||
#include <VHACD.h>
|
||||
#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<QVector<VHACD::IVHACD::ConvexHull>>& 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<VHACD::IVHACD::ConvexHull> 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<int> triangles; // array of indexes
|
||||
vector<float> 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<std::chrono::nanoseconds>(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<std::chrono::nanoseconds>(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<int> 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 <<endl;
|
||||
for (int i = 0; i < results.meshCount; i++) {
|
||||
cout << "Mesh : " << i + 1 << endl;
|
||||
QVector<VHACD::IVHACD::ConvexHull> 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() {
|
||||
}
|
28
tools/vhacd/src/VHACDUtilApp.h
Normal file
28
tools/vhacd/src/VHACDUtilApp.h
Normal file
|
@ -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 <QApplication>
|
||||
|
||||
|
||||
class VHACDUtilApp : public QCoreApplication {
|
||||
Q_OBJECT
|
||||
public:
|
||||
VHACDUtilApp(int argc, char* argv[]);
|
||||
~VHACDUtilApp();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //hifi_VHACDUtilApp_h
|
|
@ -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 <stdio.h>
|
||||
// #include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <VHACD.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "VHACDUtil.h"
|
||||
|
||||
#include "VHACDUtilApp.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace VHACD;
|
||||
|
||||
|
||||
bool writeOBJ(QString outFileName, QVector<QVector<VHACD::IVHACD::ConvexHull>>& 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<int> triangles; // array of indexes
|
||||
vector<float> 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<std::chrono::nanoseconds>(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<std::chrono::nanoseconds>(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<int> 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 <<endl;
|
||||
for (int i = 0; i < results.meshCount; i++) {
|
||||
cout << "Mesh : " << i + 1 << endl;
|
||||
QVector<VHACD::IVHACD::ConvexHull> 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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue