From 48592782149ef9694b492226de286ca13daf6eb3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 11:17:25 -0700 Subject: [PATCH 01/16] get rid of point/tri bounce structures in favor of FBXGeometry --- tools/vhacd/src/VHACDUtil.cpp | 356 +++++++++++++++---------------- tools/vhacd/src/VHACDUtil.h | 31 +-- tools/vhacd/src/VHACDUtilApp.cpp | 81 +++---- 3 files changed, 216 insertions(+), 252 deletions(-) diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp index 804a3562c6..8f41f67ad0 100644 --- a/tools/vhacd/src/VHACDUtil.cpp +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -14,7 +14,7 @@ //Read all the meshes from provided FBX file -bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *results) { +bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { // open the fbx file QFile fbx(filename); @@ -25,174 +25,116 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *re QByteArray fbxContents = fbx.readAll(); - - FBXGeometry geometry; - if (filename.toLower().endsWith(".obj")) { - geometry = readOBJ(fbxContents, QVariantHash()); + result = readOBJ(fbxContents, QVariantHash()); } else if (filename.toLower().endsWith(".fbx")) { - geometry = readFBX(fbxContents, QVariantHash()); + result = readFBX(fbxContents, QVariantHash()); } else { qDebug() << "unknown file extension"; return false; } - - std::cout << "-------------------\n"; - foreach (const FBXMesh& mesh, geometry.meshes) { - foreach (const FBXMeshPart &meshPart, mesh.parts) { - std::cout << meshPart.triangleIndices.size() << " "; - } - } - std::cout << "\n"; - - - //results->meshCount = geometry.meshes.count(); - // qDebug() << "read in" << geometry.meshes.count() << "meshes"; - - int count = 0; - foreach(FBXMesh mesh, geometry.meshes) { - //get vertices for each mesh - // QVector vertices = mesh.vertices; - - - QVector vertices; - foreach (glm::vec3 vertex, mesh.vertices) { - vertices.append(glm::vec3(mesh.modelTransform * glm::vec4(vertex, 1.0f))); - } - - // get the triangle indices for each mesh - QVector triangles; - foreach(FBXMeshPart meshPart, mesh.parts){ - QVector indices = meshPart.triangleIndices; - triangles += indices; - - unsigned int quadCount = meshPart.quadIndices.size() / 4; - for (unsigned int i = 0; i < quadCount; i++) { - unsigned int p0Index = meshPart.quadIndices[i * 4]; - unsigned int p1Index = meshPart.quadIndices[i * 4 + 1]; - unsigned int p2Index = meshPart.quadIndices[i * 4 + 2]; - unsigned int p3Index = meshPart.quadIndices[i * 4 + 3]; - // split each quad into two triangles - triangles.append(p0Index); - triangles.append(p1Index); - triangles.append(p2Index); - triangles.append(p0Index); - triangles.append(p2Index); - triangles.append(p3Index); - } - } - - // only read meshes with triangles - if (triangles.count() <= 0){ - continue; - } - - AABox aaBox; - foreach (glm::vec3 p, vertices) { - aaBox += p; - } - - results->perMeshVertices.append(vertices); - results->perMeshTriangleIndices.append(triangles); - results->perMeshLargestDimension.append(aaBox.getLargestDimension()); - count++; - } - - results->meshCount = count; return true; } -void vhacd::VHACDUtil::combineMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const { - float largestDimension = 0; - int indexStart = 0; +// void vhacd::VHACDUtil::combineMeshes(FBXGeometryvhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const { +// float largestDimension = 0; +// int indexStart = 0; - QVector emptyVertices; - QVector emptyTriangles; - results->perMeshVertices.append(emptyVertices); - results->perMeshTriangleIndices.append(emptyTriangles); - results->perMeshLargestDimension.append(largestDimension); +// QVector emptyVertices; +// QVector emptyTriangles; +// results->perMeshVertices.append(emptyVertices); +// results->perMeshTriangleIndices.append(emptyTriangles); +// results->perMeshLargestDimension.append(largestDimension); - for (int i = 0; i < meshes->meshCount; i++) { - QVector vertices = meshes->perMeshVertices.at(i); - QVector triangles = meshes->perMeshTriangleIndices.at(i); - const float largestDimension = meshes->perMeshLargestDimension.at(i); +// for (int i = 0; i < meshes->meshCount; i++) { +// QVector vertices = meshes->perMeshVertices.at(i); +// QVector triangles = meshes->perMeshTriangleIndices.at(i); +// const float largestDimension = meshes->perMeshLargestDimension.at(i); - for (int j = 0; j < triangles.size(); j++) { - triangles[ j ] += indexStart; - } - indexStart += vertices.size(); +// for (int j = 0; j < triangles.size(); j++) { +// triangles[ j ] += indexStart; +// } +// indexStart += vertices.size(); - results->perMeshVertices[0] << vertices; - results->perMeshTriangleIndices[0] << triangles; - if (results->perMeshLargestDimension[0] < largestDimension) { - results->perMeshLargestDimension[0] = largestDimension; - } - } +// results->perMeshVertices[0] << vertices; +// results->perMeshTriangleIndices[0] << triangles; +// if (results->perMeshLargestDimension[0] < largestDimension) { +// results->perMeshLargestDimension[0] = largestDimension; +// } +// } - results->meshCount = 1; -} +// results->meshCount = 1; +// } -void vhacd::VHACDUtil::fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const { +// void vhacd::VHACDUtil::fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const { - for (int i = 0; i < meshes->meshCount; i++) { - QVector vertices = meshes->perMeshVertices.at(i); - QVector triangles = meshes->perMeshTriangleIndices.at(i); - const float largestDimension = meshes->perMeshLargestDimension.at(i); +// for (int i = 0; i < meshes->meshCount; i++) { +// QVector vertices = meshes->perMeshVertices.at(i); +// QVector triangles = meshes->perMeshTriangleIndices.at(i); +// const float largestDimension = meshes->perMeshLargestDimension.at(i); - results->perMeshVertices.append(vertices); - results->perMeshTriangleIndices.append(triangles); - results->perMeshLargestDimension.append(largestDimension); +// results->perMeshVertices.append(vertices); +// results->perMeshTriangleIndices.append(triangles); +// results->perMeshLargestDimension.append(largestDimension); - for (int j = 0; j < triangles.size(); j += 3) { - auto p0 = vertices[triangles[j]]; - auto p1 = vertices[triangles[j+1]]; - auto p2 = vertices[triangles[j+2]]; +// for (int j = 0; j < triangles.size(); j += 3) { +// auto p0 = vertices[triangles[j]]; +// auto p1 = vertices[triangles[j+1]]; +// auto p2 = vertices[triangles[j+2]]; - auto d0 = p1 - p0; - auto d1 = p2 - p0; +// auto d0 = p1 - p0; +// auto d1 = p2 - p0; - auto cp = glm::cross(d0, d1); - cp = -2.0f * glm::normalize(cp); +// auto cp = glm::cross(d0, d1); +// cp = -2.0f * glm::normalize(cp); - auto p3 = p0 + cp; +// auto p3 = p0 + cp; - auto n = results->perMeshVertices.size(); - results->perMeshVertices[i] << p3; +// auto n = results->perMeshVertices.size(); +// results->perMeshVertices[i] << p3; - results->perMeshTriangleIndices[i] << triangles[j] << n << triangles[j + 1]; - results->perMeshTriangleIndices[i] << triangles[j + 1] << n << triangles[j + 2]; - results->perMeshTriangleIndices[i] << triangles[j + 2] << n << triangles[j]; - } +// results->perMeshTriangleIndices[i] << triangles[j] << n << triangles[j + 1]; +// results->perMeshTriangleIndices[i] << triangles[j + 1] << n << triangles[j + 2]; +// results->perMeshTriangleIndices[i] << triangles[j + 2] << n << triangles[j]; +// } - results->meshCount++; - } -} +// results->meshCount++; +// } +// } -bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *inMeshes, VHACD::IVHACD::Parameters params, - vhacd::ComputeResults *results, - int startMeshIndex, int endMeshIndex, float minimumMeshSize, - bool fattenFaces) const { +bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, + VHACD::IVHACD::Parameters params, + FBXGeometry& result, + int startMeshIndex, + int endMeshIndex, float minimumMeshSize, + bool fattenFaces) { - vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults; + // vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults; // combineMeshes(inMeshes, meshes); // vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults; - if (fattenFaces) { - fattenMeshes(inMeshes, meshes); - } else { - meshes = inMeshes; + // if (fattenFaces) { + // fattenMeshes(inMeshes, meshes); + // } else { + // meshes = inMeshes; + // } + + + // count the mesh-parts + QVector meshParts; + int meshCount = 0; + foreach (FBXMesh mesh, geometry.meshes) { + meshCount += mesh.parts.size(); } VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD(); - int meshCount = meshes->meshCount; - int count = 0; if (startMeshIndex < 0) { startMeshIndex = 0; @@ -201,66 +143,119 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *inMeshes, VHACD::IVHA endMeshIndex = meshCount; } - for (int i = 0; i < meshCount; i++) { - std::cout << meshes->perMeshTriangleIndices.at(i).size() << " "; - } - std::cout << "\n"; + // for (int i = 0; i < meshCount; i++) { + // std::cout << meshes->perMeshTriangleIndices.at(i).size() << " "; + // } + // std::cout << "\n"; std::cout << "Performing V-HACD computation on " << endMeshIndex - startMeshIndex << " meshes ..... " << std::endl; - for (int i = startMeshIndex; i < endMeshIndex; i++){ - qDebug() << "--------------------"; - std::vector vertices = meshes->perMeshVertices.at(i).toStdVector(); - std::vector triangles = meshes->perMeshTriangleIndices.at(i).toStdVector(); - int nPoints = (unsigned int)vertices.size(); - int nTriangles = (unsigned int)triangles.size() / 3; - const float largestDimension = meshes->perMeshLargestDimension.at(i); + result.meshExtents.reset(); + result.meshes.append(FBXMesh()); + FBXMesh &resultMesh = result.meshes.last(); - qDebug() << "Mesh " << i << " -- " << nPoints << " points, " << nTriangles << " triangles, " - << "size =" << largestDimension; + int count = 0; + foreach (const FBXMesh& mesh, geometry.meshes) { + foreach (const FBXMeshPart &meshPart, mesh.parts) { + qDebug() << "--------------------"; + std::vector vertices = mesh.vertices.toStdVector(); + std::vector triangles = meshPart.triangleIndices.toStdVector(); - if (largestDimension < minimumMeshSize /* || largestDimension > 1000 */) { - qDebug() << " Skipping..."; - continue; - } - // compute approximate convex decomposition - bool res = interfaceVHACD->Compute(&vertices[0].x, 3, nPoints, &triangles[0], 3, nTriangles, params); - if (!res){ - qDebug() << "V-HACD computation failed for Mesh : " << i; - continue; - } - count++; //For counting number of successfull computations - - //Number of hulls for the mesh - unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); - results->convexHullsCountList.append(nConvexHulls); - - //get all the convex hulls for this mesh - QVector convexHulls; - 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); - } //end of for loop - results->meshCount = count; + // only process meshes with triangles + if (triangles.size() <= 0) { + continue; + } + + int nPoints = vertices.size(); + const float largestDimension = aaBox.getLargestDimension(); + + qDebug() << "Mesh " << count << " -- " << nPoints << " points, " << triangleCount << " triangles, " + << "size =" << largestDimension; + + if (largestDimension < minimumMeshSize /* || largestDimension > 1000 */) { + qDebug() << " Skipping..."; + continue; + } + + // compute approximate convex decomposition + bool res = interfaceVHACD->Compute(&vertices[0].x, 3, nPoints, &triangles[0], 3, triangleCount, params); + if (!res){ + qDebug() << "V-HACD computation failed for Mesh : " << count; + continue; + } + + // Number of hulls for this input meshPart + unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); + + // create an output meshPart for each convex hull + for (unsigned int j = 0; j < nConvexHulls; j++) { + VHACD::IVHACD::ConvexHull hull; + interfaceVHACD->GetConvexHull(j, hull); + // each convex-hull is a mesh-part + resultMesh.parts.append(FBXMeshPart()); + FBXMeshPart &resultMeshPart = resultMesh.parts.last(); + + int hullIndexStart = resultMesh.vertices.size(); + + qDebug() << "j =" << j << "points =" << hull.m_nPoints << "tris =" << hull.m_nTriangles; + + for (unsigned int i = 0; i < hull.m_nPoints; i++) { + float x = hull.m_points[i * 3]; + float y = hull.m_points[i * 3 + 1]; + float z = hull.m_points[i * 3 + 2]; + resultMesh.vertices.append(glm::vec3(x, y, z)); + } + + for (unsigned int i = 0; i < hull.m_nTriangles; i++) { + int index0 = hull.m_triangles[i * 3] + hullIndexStart; + int index1 = hull.m_triangles[i * 3 + 1] + hullIndexStart; + int index2 = hull.m_triangles[i * 3 + 2] + hullIndexStart; + resultMeshPart.triangleIndices.append(index0); + resultMeshPart.triangleIndices.append(index1); + resultMeshPart.triangleIndices.append(index2); + } + } + + count++; + } + } //release memory interfaceVHACD->Clean(); @@ -272,7 +267,6 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *inMeshes, VHACD::IVHA else{ return false; } - } vhacd::VHACDUtil:: ~VHACDUtil(){ diff --git a/tools/vhacd/src/VHACDUtil.h b/tools/vhacd/src/VHACDUtil.h index 1239afe2e5..37031a2f7b 100644 --- a/tools/vhacd/src/VHACDUtil.h +++ b/tools/vhacd/src/VHACDUtil.h @@ -23,28 +23,17 @@ #include namespace vhacd { - - typedef struct { - int meshCount; - QVector convexHullsCountList; - QVector> convexHullList; - } ComputeResults; - - typedef struct { - int meshCount; - QVector> perMeshVertices; - QVector> perMeshTriangleIndices; - QVector perMeshLargestDimension; - } LoadFBXResults; - class VHACDUtil { public: - bool loadFBX(const QString filename, vhacd::LoadFBXResults *results); - void combineMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const; - void fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const; - bool computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, - vhacd::ComputeResults *results, int startMeshIndex, int endMeshIndex, float minimumMeshSize, - bool fattenFaces) const; + bool loadFBX(const QString filename, FBXGeometry& result); + // void combineMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const; + // void fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const; + bool computeVHACD(FBXGeometry& geometry, + VHACD::IVHACD::Parameters params, + FBXGeometry& result, + int startMeshIndex, int endMeshIndex, + float minimumMeshSize, + bool fattenFaces); ~VHACDUtil(); }; @@ -53,7 +42,7 @@ namespace vhacd { ProgressCallback(void); ~ProgressCallback(); - //Couldn't follow coding guideline here due to virtual function declared in IUserCallback + // Couldn't follow coding guideline here due to virtual function declared in IUserCallback void Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation); }; diff --git a/tools/vhacd/src/VHACDUtilApp.cpp b/tools/vhacd/src/VHACDUtilApp.cpp index a572f49b80..e179a3c758 100644 --- a/tools/vhacd/src/VHACDUtilApp.cpp +++ b/tools/vhacd/src/VHACDUtilApp.cpp @@ -32,7 +32,7 @@ QString formatFloat(double n) { } -bool writeOBJ(QString outFileName, QVector>& meshList, bool outputOneMesh) { +bool writeOBJ(QString outFileName, FBXGeometry& geometry) { QFile file(outFileName); if (!file.open(QIODevice::WriteOnly)) { qDebug() << "Unable to write to " << outFileName; @@ -41,26 +41,25 @@ bool writeOBJ(QString outFileName, QVector>& QTextStream out(&file); - unsigned int pointStartOffset = 0; + unsigned int nth = 0; + foreach (const FBXMesh& mesh, geometry.meshes) { + for (int i = 0; i < mesh.vertices.size(); i++) { + out << "v "; + out << formatFloat(mesh.vertices[i][0]) << " "; + out << formatFloat(mesh.vertices[i][1]) << " "; + out << formatFloat(mesh.vertices[i][2]) << "\n"; + } - foreach (QVector hulls, meshList) { - unsigned int nth = 0; - foreach (VHACD::IVHACD::ConvexHull hull, hulls) { + foreach (const FBXMeshPart &meshPart, mesh.parts) { out << "g 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]) << "\n"; - } - for (unsigned int i = 0; i < hull.m_nTriangles; i++) { + int triangleCount = meshPart.triangleIndices.size() / 3; + for (int i = 0; i < triangleCount; 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"; + out << meshPart.triangleIndices[i*3] + 1 << " "; + out << meshPart.triangleIndices[i*3+1] + 1 << " "; + out << meshPart.triangleIndices[i*3+2] + 1 << "\n"; } out << "\n"; - pointStartOffset += hull.m_nPoints; } } @@ -76,8 +75,6 @@ VHACDUtilApp::VHACDUtilApp(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; @@ -89,9 +86,6 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : const QCommandLineOption helpOption = parser.addHelpOption(); - const QCommandLineOption outputOneMeshOption("1", "output hulls as single mesh"); - parser.addOption(outputOneMeshOption); - const QCommandLineOption fattenFacesOption("f", "fatten faces"); parser.addOption(fattenFacesOption); @@ -132,7 +126,6 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : } bool fattenFaces = parser.isSet(fattenFacesOption); - bool outputOneMesh = parser.isSet(outputOneMeshOption); QString inputFilename; if (parser.isSet(inputFilenameOption)) { @@ -211,8 +204,9 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : // load the mesh + FBXGeometry fbx; auto begin = std::chrono::high_resolution_clock::now(); - if (!vUtil.loadFBX(inputFilename, &fbx)){ + if (!vUtil.loadFBX(inputFilename, fbx)){ cout << "Error in opening FBX file...."; } auto end = std::chrono::high_resolution_clock::now(); @@ -221,50 +215,37 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : //perform vhacd computation begin = std::chrono::high_resolution_clock::now(); - if (!vUtil.computeVHACD(&fbx, params, &results, startMeshIndex, endMeshIndex, minimumMeshSize, fattenFaces)) { + FBXGeometry result; + if (!vUtil.computeVHACD(fbx, params, result, startMeshIndex, endMeshIndex, minimumMeshSize, fattenFaces)) { 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 totalMeshParts = 0; + foreach (const FBXMesh& mesh, result.meshes) { + totalVertices += mesh.vertices.size(); + foreach (const FBXMeshPart &meshPart, mesh.parts) { + totalTriangles += meshPart.triangleIndices.size() / 3; + // each quad was made into two triangles + totalTriangles += 2 * meshPart.quadIndices.size() / 4; + totalMeshParts++; + } } - int totalHulls = 0; - QVector hullCounts = results.convexHullsCountList; - for (int i = 0; i < results.meshCount; i++){ - totalHulls += hullCounts.at(i); - } + int totalHulls = result.meshes[0].parts.size(); 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 << "Number Of Meshes : " << totalMeshParts << 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); + writeOBJ(outputFilename, result); } VHACDUtilApp::~VHACDUtilApp() { From c035de4e73a10256a3f9c56e805103f09493d80c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 11:38:54 -0700 Subject: [PATCH 02/16] cleanups --- tools/vhacd/src/VHACDUtil.cpp | 77 +++++++---------------------------- 1 file changed, 15 insertions(+), 62 deletions(-) diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp index 8f41f67ad0..eab9a25b2c 100644 --- a/tools/vhacd/src/VHACDUtil.cpp +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -13,7 +13,7 @@ #include "VHACDUtil.h" -//Read all the meshes from provided FBX file +// Read all the meshes from provided FBX file bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { // open the fbx file @@ -38,37 +38,6 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { } -// void vhacd::VHACDUtil::combineMeshes(FBXGeometryvhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const { -// float largestDimension = 0; -// int indexStart = 0; - -// QVector emptyVertices; -// QVector emptyTriangles; -// results->perMeshVertices.append(emptyVertices); -// results->perMeshTriangleIndices.append(emptyTriangles); -// results->perMeshLargestDimension.append(largestDimension); - -// for (int i = 0; i < meshes->meshCount; i++) { -// QVector vertices = meshes->perMeshVertices.at(i); -// QVector triangles = meshes->perMeshTriangleIndices.at(i); -// const float largestDimension = meshes->perMeshLargestDimension.at(i); - -// for (int j = 0; j < triangles.size(); j++) { -// triangles[ j ] += indexStart; -// } -// indexStart += vertices.size(); - -// results->perMeshVertices[0] << vertices; -// results->perMeshTriangleIndices[0] << triangles; -// if (results->perMeshLargestDimension[0] < largestDimension) { -// results->perMeshLargestDimension[0] = largestDimension; -// } -// } - -// results->meshCount = 1; -// } - - // void vhacd::VHACDUtil::fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const { // for (int i = 0; i < meshes->meshCount; i++) { @@ -113,19 +82,6 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, int startMeshIndex, int endMeshIndex, float minimumMeshSize, bool fattenFaces) { - - // vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults; - // combineMeshes(inMeshes, meshes); - - // vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults; - - // if (fattenFaces) { - // fattenMeshes(inMeshes, meshes); - // } else { - // meshes = inMeshes; - // } - - // count the mesh-parts QVector meshParts; int meshCount = 0; @@ -133,7 +89,6 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, meshCount += mesh.parts.size(); } - VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD(); if (startMeshIndex < 0) { @@ -143,12 +98,6 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, endMeshIndex = meshCount; } - // for (int i = 0; i < meshCount; i++) { - // std::cout << meshes->perMeshTriangleIndices.at(i).size() << " "; - // } - // std::cout << "\n"; - - std::cout << "Performing V-HACD computation on " << endMeshIndex - startMeshIndex << " meshes ..... " << std::endl; result.meshExtents.reset(); @@ -200,6 +149,8 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, // only process meshes with triangles if (triangles.size() <= 0) { + qDebug() << " Skipping (no triangles)..."; + count++; continue; } @@ -210,7 +161,8 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, << "size =" << largestDimension; if (largestDimension < minimumMeshSize /* || largestDimension > 1000 */) { - qDebug() << " Skipping..."; + qDebug() << " Skipping (too small)..."; + count++; continue; } @@ -218,6 +170,7 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, bool res = interfaceVHACD->Compute(&vertices[0].x, 3, nPoints, &triangles[0], 3, triangleCount, params); if (!res){ qDebug() << "V-HACD computation failed for Mesh : " << count; + count++; continue; } @@ -228,14 +181,11 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, for (unsigned int j = 0; j < nConvexHulls; j++) { VHACD::IVHACD::ConvexHull hull; interfaceVHACD->GetConvexHull(j, hull); - // each convex-hull is a mesh-part + resultMesh.parts.append(FBXMeshPart()); FBXMeshPart &resultMeshPart = resultMesh.parts.last(); int hullIndexStart = resultMesh.vertices.size(); - - qDebug() << "j =" << j << "points =" << hull.m_nPoints << "tris =" << hull.m_nTriangles; - for (unsigned int i = 0; i < hull.m_nPoints; i++) { float x = hull.m_points[i * 3]; float y = hull.m_points[i * 3 + 1]; @@ -274,8 +224,11 @@ vhacd::VHACDUtil:: ~VHACDUtil(){ } //ProgressClaback implementation -void vhacd::ProgressCallback::Update(const double overallProgress, const double stageProgress, const double operationProgress, - const char * const stage, const char * const operation){ +void vhacd::ProgressCallback::Update(const double overallProgress, + const double stageProgress, + const double operationProgress, + const char* const stage, + const char* const operation) { int progress = (int)(overallProgress + 0.5); if (progress < 10){ @@ -287,9 +240,9 @@ void vhacd::ProgressCallback::Update(const double overallProgress, const double std::cout << progress << "%"; - if (progress >= 100){ - std::cout << std::endl; - } + if (progress >= 100){ + std::cout << std::endl; + } } vhacd::ProgressCallback::ProgressCallback(void){} From 79b1a6aeb0e40f92d7e92a0c1e3150fc9f108d82 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 17:45:47 -0700 Subject: [PATCH 03/16] comma key toggles rendering of collision hulls --- interface/src/Application.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7bab72ff0d..4f67a45ad8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -164,6 +164,8 @@ const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::D const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js"; +bool renderCollisionHulls = false; + #ifdef Q_OS_WIN class MyNativeEventFilter : public QAbstractNativeEventFilter { public: @@ -1181,6 +1183,10 @@ void Application::keyPressEvent(QKeyEvent* event) { break; } + case Qt::Key_Comma: { + renderCollisionHulls = !renderCollisionHulls; + } + default: event->ignore(); break; @@ -2976,7 +2982,11 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs PerformanceTimer perfTimer("entities"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... entities..."); - _entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderSide); + if (renderCollisionHulls) { + _entities.render(RenderArgs::DEBUG_RENDER_MODE, renderSide); + } else { + _entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderSide); + } } // render JS/scriptable overlays From 81200bb2a0843263dfb4a0efca7ff40f2e4ea89a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 17:49:01 -0700 Subject: [PATCH 04/16] save collision hull scaling in model --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 2353a20e7d..f76a514b92 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -393,6 +393,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { // collision model's extents). glm::vec3 scale = _dimensions / renderGeometry.getUnscaledMeshExtents().size(); + // save the scale we've used into the model for when we want to render the collision hulls + _model->setCollisionGeometryScale(scale); // multiply each point by scale before handing the point-set off to the physics engine for (int i = 0; i < _points.size(); i++) { From 420424a5eea430d1724b28f9a6047859f1f74c16 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 17:49:49 -0700 Subject: [PATCH 05/16] make it possible to sort meshes into the same order they appear in the model file --- libraries/fbx/src/FBXReader.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 1cd3bba73a..1073bc5c31 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -819,8 +819,9 @@ void appendIndex(MeshData& data, QVector& indices, int index) { } } -ExtractedMesh extractMesh(const FBXNode& object) { +ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { MeshData data; + data.extracted.mesh.meshIndex = meshIndex++; QVector materials; QVector textures; foreach (const FBXNode& child, object.children) { @@ -1261,6 +1262,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, float unitScaleFactor = 1.0f; glm::vec3 ambientColor; QString hifiGlobalNodeID; + unsigned int meshIndex = 0; foreach (const FBXNode& child, node.children) { if (child.name == "FBXHeaderExtension") { @@ -1305,7 +1307,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, foreach (const FBXNode& object, child.children) { if (object.name == "Geometry") { if (object.properties.at(2) == "Mesh") { - meshes.insert(getID(object.properties), extractMesh(object)); + meshes.insert(getID(object.properties), extractMesh(object, meshIndex)); } else { // object.properties.at(2) == "Shape" ExtractedBlendshape extracted = { getID(object.properties), extractBlendshape(object) }; blendshapes.append(extracted); @@ -1440,7 +1442,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else if (subobject.name == "Vertices") { // it's a mesh as well as a model mesh = &meshes[getID(object.properties)]; - *mesh = extractMesh(object); + *mesh = extractMesh(object, meshIndex); } else if (subobject.name == "Shape") { ExtractedBlendshape blendshape = { subobject.properties.at(0).toString(), @@ -1980,7 +1982,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, // see if any materials have texture children bool materialsHaveTextures = checkMaterialsHaveTextures(materials, textureFilenames, childMap); - + for (QHash::iterator it = meshes.begin(); it != meshes.end(); it++) { ExtractedMesh& extracted = it.value(); From 36cd69c38a9aa845a6bdbe9c0cc6b2847e1cad34 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 17:50:20 -0700 Subject: [PATCH 06/16] new member variable to remember the order in which meshes appeared in the model file --- libraries/fbx/src/FBXReader.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 6cb6b19c05..d1576bc02a 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -152,6 +152,8 @@ public: bool hasSpecularTexture() const; bool hasEmissiveTexture() const; + + unsigned int meshIndex; // the order the meshes appeared in the object file }; /// A single animation frame extracted from an FBX document. From 00449ef7c0ff25df1588f31259d5d6e54b6d519c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 17:50:35 -0700 Subject: [PATCH 07/16] new member variable to remember the order in which meshes appeared in the model file --- libraries/fbx/src/OBJReader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 7e71ba07f7..f7b5a3b10d 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -343,6 +343,7 @@ FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) { } FBXMesh &mesh = geometry.meshes[0]; + mesh.meshIndex = 0; // if we got a hint about units, scale all the points if (scaleGuess != 1.0f) { From 8940ba0c2aeb681c03765faad6c91f2e5fb2c9f3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 17:52:18 -0700 Subject: [PATCH 08/16] new member variables related to rendering collision hulls --- libraries/render-utils/src/Model.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 299853ec9d..e582e4018e 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -91,7 +91,7 @@ public: void reset(); virtual void simulate(float deltaTime, bool fullUpdate = true); - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, DEBUG_RENDER_MODE }; bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); @@ -111,6 +111,7 @@ public: // Set the model to use for collisions Q_INVOKABLE void setCollisionModelURL(const QUrl& url); const QUrl& getCollisionURL() const { return _collisionUrl; } + void setCollisionGeometryScale(glm::vec3 newScale) { _collisionGeometryScale = newScale; } /// Sets the distance parameter used for LOD computations. void setLODDistance(float distance) { _lodDistance = distance; } @@ -295,6 +296,7 @@ private: float _nextLODHysteresis; QSharedPointer _collisionGeometry; + QSharedPointer _saveNonCollisionGeometry; float _pupilDilation; QVector _blendshapeCoefficients; @@ -479,6 +481,8 @@ private: static AbstractViewStateInterface* _viewState; + bool _renderCollisionHull; + glm::vec3 _collisionGeometryScale; }; Q_DECLARE_METATYPE(QPointer) From bfab522ee747117983800971b702db513e72fe51 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 17:52:30 -0700 Subject: [PATCH 09/16] debuging render mode --- libraries/shared/src/RenderArgs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index e447472fee..c7386f9f6b 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -17,7 +17,7 @@ class OctreeRenderer; class RenderArgs { public: - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, DEBUG_RENDER_MODE }; enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT }; OctreeRenderer* _renderer; From 06b38615d5b7d6123c9e787ec850b029526efeba Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 17:53:33 -0700 Subject: [PATCH 10/16] sort meshes into the order they appeared in the model file so that start and end arguments mean something usefil --- tools/vhacd/src/VHACDUtil.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp index eab9a25b2c..9f20e5e706 100644 --- a/tools/vhacd/src/VHACDUtil.cpp +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -13,6 +13,16 @@ #include "VHACDUtil.h" +// FBXReader jumbles the order of the meshes by reading them back out of a hashtable. This will put +// them back in the order in which they appeared in the file. +bool FBXGeometryLessThan(const FBXMesh& e1, const FBXMesh& e2) { + return e1.meshIndex < e2.meshIndex; +} +void reSortFBXGeometryMeshes(FBXGeometry& geometry) { + qSort(geometry.meshes.begin(), geometry.meshes.end(), FBXGeometryLessThan); +} + + // Read all the meshes from provided FBX file bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { @@ -34,10 +44,13 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { return false; } + reSortFBXGeometryMeshes(result); + return true; } + // void vhacd::VHACDUtil::fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const { // for (int i = 0; i < meshes->meshCount; i++) { @@ -85,9 +98,6 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, // count the mesh-parts QVector meshParts; int meshCount = 0; - foreach (FBXMesh mesh, geometry.meshes) { - meshCount += mesh.parts.size(); - } VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD(); @@ -106,9 +116,22 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, int count = 0; foreach (const FBXMesh& mesh, geometry.meshes) { + + // each mesh has its own transform to move it to model-space + std::vector vertices; + foreach (glm::vec3 vertex, mesh.vertices) { + vertices.push_back(glm::vec3(mesh.modelTransform * glm::vec4(vertex, 1.0f))); + } + foreach (const FBXMeshPart &meshPart, mesh.parts) { + + if (count < startMeshIndex || count >= endMeshIndex) { + count ++; + continue; + } + qDebug() << "--------------------"; - std::vector vertices = mesh.vertices.toStdVector(); + std::vector triangles = meshPart.triangleIndices.toStdVector(); AABox aaBox; From 78af7f900e3d48dd9da599ab4df1fd379e3dafaa Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 18:23:25 -0700 Subject: [PATCH 11/16] don't need _collisionGeometryScale --- libraries/render-utils/src/Model.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index e582e4018e..5dbd0b03c2 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -111,7 +111,6 @@ public: // Set the model to use for collisions Q_INVOKABLE void setCollisionModelURL(const QUrl& url); const QUrl& getCollisionURL() const { return _collisionUrl; } - void setCollisionGeometryScale(glm::vec3 newScale) { _collisionGeometryScale = newScale; } /// Sets the distance parameter used for LOD computations. void setLODDistance(float distance) { _lodDistance = distance; } @@ -482,7 +481,6 @@ private: static AbstractViewStateInterface* _viewState; bool _renderCollisionHull; - glm::vec3 _collisionGeometryScale; }; Q_DECLARE_METATYPE(QPointer) From 997f7251c7993e51d064b20f8f3554f769d35f32 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 18:23:43 -0700 Subject: [PATCH 12/16] dont need _collisionGeometryScale --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f76a514b92..bf5ce62ff8 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -393,9 +393,6 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { // collision model's extents). glm::vec3 scale = _dimensions / renderGeometry.getUnscaledMeshExtents().size(); - // save the scale we've used into the model for when we want to render the collision hulls - _model->setCollisionGeometryScale(scale); - // multiply each point by scale before handing the point-set off to the physics engine for (int i = 0; i < _points.size(); i++) { for (int j = 0; j < _points[i].size(); j++) { From eb78fa0f85012c09d18c7dfc0c0cd69cfddc9f4d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 1 Apr 2015 18:24:25 -0700 Subject: [PATCH 13/16] if switching to the mode where collision hulls are drawn, updateGeometry and simulate --- libraries/render-utils/src/Model.cpp | 40 ++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index e9cfdaf345..69052da443 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -82,7 +82,8 @@ Model::Model(QObject* parent) : _appliedBlendNumber(0), _calculatedMeshBoxesValid(false), _calculatedMeshTrianglesValid(false), - _meshGroupsKnown(false) { + _meshGroupsKnown(false), + _renderCollisionHull(false) { // we may have been created in the network thread, but we live in the main thread if (_viewState) { @@ -712,13 +713,13 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { { GLenum buffers[3]; int bufferCount = 0; - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE || mode == DEBUG_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; } - if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE || mode == DEBUG_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; } - if (mode == DEFAULT_RENDER_MODE) { + if (mode == DEFAULT_RENDER_MODE || mode == DEBUG_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; } GLBATCH(glDrawBuffers)(bufferCount, buffers); @@ -777,7 +778,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDrawBuffers)(bufferCount, buffers); } - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE || mode == DEBUG_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args, true); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args, true); @@ -1778,13 +1779,13 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { { GLenum buffers[3]; int bufferCount = 0; - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE || mode == DEBUG_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; } - if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE || mode == DEBUG_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; } - if (mode == DEFAULT_RENDER_MODE) { + if (mode == DEFAULT_RENDER_MODE || mode == DEBUG_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; } GLBATCH(glDrawBuffers)(bufferCount, buffers); @@ -1843,7 +1844,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { GLBATCH(glDrawBuffers)(bufferCount, buffers); } - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE || mode == DEBUG_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); @@ -1919,6 +1920,22 @@ bool Model::renderInScene(float alpha, RenderArgs* args) { if (_meshStates.isEmpty()) { return false; } + + if (args->_renderMode == RenderArgs::DEBUG_RENDER_MODE && _renderCollisionHull == false) { + qDebug() << "turning collision hull rendering on"; + _renderCollisionHull = true; + _nextGeometry = _collisionGeometry; + _saveNonCollisionGeometry = _geometry; + updateGeometry(); + simulate(0.0, true); + } else if (args->_renderMode != RenderArgs::DEBUG_RENDER_MODE && _renderCollisionHull == true) { + qDebug() << "turning collision hull rendering off"; + _renderCollisionHull = false; + _nextGeometry = _saveNonCollisionGeometry; + updateGeometry(); + simulate(0.0, true); + } + renderSetup(args); _modelsInScene.push_back(this); return true; @@ -2402,8 +2419,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } -int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - Locations* locations, SkinLocations* skinLocations, bool forceRenderMeshes) { +int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, + float alphaThreshold, RenderArgs* args, Locations* locations, SkinLocations* skinLocations, + bool forceRenderMeshes) { PROFILE_RANGE(__FUNCTION__); auto textureCache = DependencyManager::get(); From 57a4f3abe33101a56227b139ba73fba14c7b6e51 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 2 Apr 2015 06:57:27 -0700 Subject: [PATCH 14/16] clear _saveNonCollisionGeometry when it's not needed, remove some debug prints --- libraries/render-utils/src/Model.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 69052da443..d04972ebee 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1922,16 +1922,17 @@ bool Model::renderInScene(float alpha, RenderArgs* args) { } if (args->_renderMode == RenderArgs::DEBUG_RENDER_MODE && _renderCollisionHull == false) { - qDebug() << "turning collision hull rendering on"; + // turning collision hull rendering on _renderCollisionHull = true; _nextGeometry = _collisionGeometry; _saveNonCollisionGeometry = _geometry; updateGeometry(); simulate(0.0, true); } else if (args->_renderMode != RenderArgs::DEBUG_RENDER_MODE && _renderCollisionHull == true) { - qDebug() << "turning collision hull rendering off"; + // turning collision hull rendering off _renderCollisionHull = false; _nextGeometry = _saveNonCollisionGeometry; + _saveNonCollisionGeometry.clear(); updateGeometry(); simulate(0.0, true); } From 17f110172f56e4b8fec3f8f9dbac62502e23c053 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 2 Apr 2015 06:57:47 -0700 Subject: [PATCH 15/16] more command-line flags for v-hacd parameters --- tools/vhacd/src/VHACDUtilApp.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/tools/vhacd/src/VHACDUtilApp.cpp b/tools/vhacd/src/VHACDUtilApp.cpp index e179a3c758..98fbb342c5 100644 --- a/tools/vhacd/src/VHACDUtilApp.cpp +++ b/tools/vhacd/src/VHACDUtilApp.cpp @@ -101,18 +101,29 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : const QCommandLineOption endMeshIndexOption("e", "end-mesh index", "0"); parser.addOption(endMeshIndexOption); - const QCommandLineOption minimumMeshSizeOption("m", "minimum mesh size to consider", "0"); + const QCommandLineOption minimumMeshSizeOption("m", "minimum mesh (diagonal) size to consider", "0"); parser.addOption(minimumMeshSizeOption); - const QCommandLineOption vHacdResolutionOption("resolution", "v-hacd resolution", "100000"); + const QCommandLineOption vHacdResolutionOption("resolution", "Maximum number of voxels generated during the " + "voxelization stage (range=10,000-16,000,000)", "100000"); parser.addOption(vHacdResolutionOption); - const QCommandLineOption vHacdDepthOption("depth", "v-hacd depth", "20"); + const QCommandLineOption vHacdDepthOption("depth", "Maximum number of clipping stages. During each split stage, parts " + "with a concavity higher than the user defined threshold are clipped " + "according the \"best\" clipping plane (range=1-32)", "20"); parser.addOption(vHacdDepthOption); - const QCommandLineOption vHacdDeltaOption("delta", "v-hacd delta", "0.05"); + const QCommandLineOption vHacdDeltaOption("delta", "Controls the bias toward maximaxing local concavity (range=0.0-1.0)", "0.05"); parser.addOption(vHacdDeltaOption); + const QCommandLineOption vHacdConcavityOption("concavity", "Maximum allowed concavity (range=0.0-1.0)", "0.0025"); + parser.addOption(vHacdConcavityOption); + + const QCommandLineOption vHacdPlanedownsamplingOption("planedownsampling", "Controls the granularity of the search for" + " the \"best\" clipping plane (range=1-16)", "4"); + parser.addOption(vHacdPlanedownsamplingOption); + + if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; @@ -180,15 +191,24 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : vHacdDelta = parser.value(vHacdDeltaOption).toFloat(); } + float vHacdConcavity = 0.0025; + if (parser.isSet(vHacdConcavityOption)) { + vHacdConcavity = parser.value(vHacdConcavityOption).toFloat(); + } + + int vHacdPlanedownsampling = 4; + if (parser.isSet(vHacdPlanedownsamplingOption)) { + vHacdPlanedownsampling = parser.value(vHacdPlanedownsamplingOption).toInt(); + } //set parameters for V-HACD params.m_callback = &pCallBack; //progress callback params.m_resolution = vHacdResolution; // 100000 params.m_depth = vHacdDepth; // 20 - params.m_concavity = 0.001; // 0.001 + params.m_concavity = vHacdConcavity; // 0.001 params.m_delta = vHacdDelta; // 0.05 - params.m_planeDownsampling = 4; // 4 + params.m_planeDownsampling = vHacdPlanedownsampling; // 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 From a01ade2d8d0b134848003656f489b94e65a3bb17 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 2 Apr 2015 09:19:47 -0700 Subject: [PATCH 16/16] more command-line options --- tools/vhacd/src/VHACDUtilApp.cpp | 44 +++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/tools/vhacd/src/VHACDUtilApp.cpp b/tools/vhacd/src/VHACDUtilApp.cpp index 98fbb342c5..199f9a9cec 100644 --- a/tools/vhacd/src/VHACDUtilApp.cpp +++ b/tools/vhacd/src/VHACDUtilApp.cpp @@ -123,6 +123,25 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : " the \"best\" clipping plane (range=1-16)", "4"); parser.addOption(vHacdPlanedownsamplingOption); + const QCommandLineOption vHacdConvexhulldownsamplingOption("convexhulldownsampling", "Controls the precision of the " + "convex-hull generation process during the clipping " + "plane selection stage (range=1-16)", "4"); + parser.addOption(vHacdConvexhulldownsamplingOption); + + // alpha + // beta + // gamma + // delta + // pca + // mode + + const QCommandLineOption vHacdMaxVerticesPerCHOption("maxvertices", "Controls the maximum number of triangles per " + "convex-hull (range=4-1024)", "64"); + parser.addOption(vHacdMaxVerticesPerCHOption); + + // minVolumePerCH + + // convexhullApproximation if (!parser.parse(QCoreApplication::arguments())) { @@ -201,21 +220,32 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : vHacdPlanedownsampling = parser.value(vHacdPlanedownsamplingOption).toInt(); } + int vHacdConvexhulldownsampling = 4; + if (parser.isSet(vHacdConvexhulldownsamplingOption)) { + vHacdConvexhulldownsampling = parser.value(vHacdConvexhulldownsamplingOption).toInt(); + } + + int vHacdMaxVerticesPerCH = 64; + if (parser.isSet(vHacdMaxVerticesPerCHOption)) { + vHacdMaxVerticesPerCH = parser.value(vHacdMaxVerticesPerCHOption).toInt(); + } + + //set parameters for V-HACD params.m_callback = &pCallBack; //progress callback - params.m_resolution = vHacdResolution; // 100000 - params.m_depth = vHacdDepth; // 20 - params.m_concavity = vHacdConcavity; // 0.001 - params.m_delta = vHacdDelta; // 0.05 - params.m_planeDownsampling = vHacdPlanedownsampling; // 4 - params.m_convexhullDownsampling = 4; // 4 + params.m_resolution = vHacdResolution; + params.m_depth = vHacdDepth; + params.m_concavity = vHacdConcavity; + params.m_delta = vHacdDelta; + params.m_planeDownsampling = vHacdPlanedownsampling; + params.m_convexhullDownsampling = vHacdConvexhulldownsampling; 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_maxNumVerticesPerCH = vHacdMaxVerticesPerCH; params.m_minVolumePerCH = 0.0001; // 0.0001 params.m_callback = 0; // 0 params.m_logger = 0; // 0