better variable names and fewer magic numbers

This commit is contained in:
Andrew Meadows 2016-05-24 12:57:32 -07:00
parent 21ef30d410
commit e8e059c637
2 changed files with 84 additions and 75 deletions

View file

@ -9,11 +9,12 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <unordered_map>
#include <QVector>
#include "VHACDUtil.h" #include "VHACDUtil.h"
const float COLLISION_TETRAHEDRON_SCALE = 0.25f; #include <unordered_map>
#include <QVector>
#include <NumericalConstants.h>
// FBXReader jumbles the order of the meshes by reading them back out of a hashtable. This will put // FBXReader jumbles the order of the meshes by reading them back out of a hashtable. This will put
@ -61,46 +62,46 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) {
} }
void getTrianglesInMeshPart(const FBXMeshPart &meshPart, std::vector<int>& triangles) { void getTrianglesInMeshPart(const FBXMeshPart &meshPart, std::vector<int>& triangleIndices) {
// append all the triangles (and converted quads) from this mesh-part to triangles // append all the triangles (and converted quads) from this mesh-part to triangles
std::vector<int> meshPartTriangles = meshPart.triangleIndices.toStdVector(); std::vector<int> meshPartTriangles = meshPart.triangleIndices.toStdVector();
triangles.insert(triangles.end(), meshPartTriangles.begin(), meshPartTriangles.end()); triangleIndices.insert(triangleIndices.end(), meshPartTriangles.begin(), meshPartTriangles.end());
// convert quads to triangles // convert quads to triangles
unsigned int quadCount = meshPart.quadIndices.size() / 4; const uint32_t QUAD_STRIDE = 4;
for (unsigned int i = 0; i < quadCount; i++) { uint32_t quadCount = meshPart.quadIndices.size() / QUAD_STRIDE;
unsigned int p0Index = meshPart.quadIndices[i * 4]; for (uint32_t i = 0; i < quadCount; i++) {
unsigned int p1Index = meshPart.quadIndices[i * 4 + 1]; uint32_t p0Index = meshPart.quadIndices[i * QUAD_STRIDE];
unsigned int p2Index = meshPart.quadIndices[i * 4 + 2]; uint32_t p1Index = meshPart.quadIndices[i * QUAD_STRIDE + 1];
unsigned int p3Index = meshPart.quadIndices[i * 4 + 3]; uint32_t p2Index = meshPart.quadIndices[i * QUAD_STRIDE + 2];
uint32_t p3Index = meshPart.quadIndices[i * QUAD_STRIDE + 3];
// split each quad into two triangles // split each quad into two triangles
triangles.push_back(p0Index); triangleIndices.push_back(p0Index);
triangles.push_back(p1Index); triangleIndices.push_back(p1Index);
triangles.push_back(p2Index); triangleIndices.push_back(p2Index);
triangles.push_back(p0Index); triangleIndices.push_back(p0Index);
triangles.push_back(p2Index); triangleIndices.push_back(p2Index);
triangles.push_back(p3Index); triangleIndices.push_back(p3Index);
} }
} }
void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result, void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result,
unsigned int& meshPartCount, uint32_t& meshPartCount,
unsigned int startMeshIndex, unsigned int endMeshIndex) const { uint32_t startMeshIndex, uint32_t endMeshIndex) const {
// this is used to make meshes generated from a highfield collidable. each triangle // this is used to make meshes generated from a highfield collidable. each triangle
// is converted into a tetrahedron and made into its own mesh-part. // is converted into a tetrahedron and made into its own mesh-part.
std::vector<int> triangles; std::vector<int> triangleIndices;
foreach (const FBXMeshPart &meshPart, mesh.parts) { foreach (const FBXMeshPart &meshPart, mesh.parts) {
if (meshPartCount < startMeshIndex || meshPartCount >= endMeshIndex) { if (meshPartCount < startMeshIndex || meshPartCount >= endMeshIndex) {
meshPartCount++; meshPartCount++;
continue; continue;
} }
getTrianglesInMeshPart(meshPart, triangles); getTrianglesInMeshPart(meshPart, triangleIndices);
} }
auto triangleCount = triangles.size() / 3; if (triangleIndices.size() == 0) {
if (triangleCount == 0) {
return; return;
} }
@ -115,10 +116,12 @@ void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result,
// turn each triangle into a tetrahedron // turn each triangle into a tetrahedron
for (unsigned int i = 0; i < triangleCount; i++) { const uint32_t TRIANGLE_STRIDE = 3;
int index0 = triangles[i * 3] + indexStartOffset; const float COLLISION_TETRAHEDRON_SCALE = 0.25f;
int index1 = triangles[i * 3 + 1] + indexStartOffset; for (uint32_t i = 0; i < triangleIndices.size(); i += TRIANGLE_STRIDE) {
int index2 = triangles[i * 3 + 2] + indexStartOffset; int index0 = triangleIndices[i] + indexStartOffset;
int index1 = triangleIndices[i + 1] + indexStartOffset;
int index2 = triangleIndices[i + 2] + indexStartOffset;
// TODO: skip triangles with a normal that points more negative-y than positive-y // TODO: skip triangles with a normal that points more negative-y than positive-y
@ -155,23 +158,21 @@ void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result,
} }
} }
AABox getAABoxForMeshPart(const FBXMesh& mesh, const FBXMeshPart &meshPart) { AABox getAABoxForMeshPart(const FBXMesh& mesh, const FBXMeshPart &meshPart) {
AABox aaBox; AABox aaBox;
unsigned int triangleCount = meshPart.triangleIndices.size() / 3; const int TRIANGLE_STRIDE = 3;
for (unsigned int i = 0; i < triangleCount; ++i) { for (int i = 0; i < meshPart.triangleIndices.size(); i += TRIANGLE_STRIDE) {
aaBox += mesh.vertices[meshPart.triangleIndices[i * 3]]; aaBox += mesh.vertices[meshPart.triangleIndices[i]];
aaBox += mesh.vertices[meshPart.triangleIndices[i * 3 + 1]]; aaBox += mesh.vertices[meshPart.triangleIndices[i + 1]];
aaBox += mesh.vertices[meshPart.triangleIndices[i * 3 + 2]]; aaBox += mesh.vertices[meshPart.triangleIndices[i + 2]];
} }
unsigned int quadCount = meshPart.quadIndices.size() / 4; const int QUAD_STRIDE = 4;
for (unsigned int i = 0; i < quadCount; ++i) { for (int i = 0; i < meshPart.quadIndices.size(); i += QUAD_STRIDE) {
aaBox += mesh.vertices[meshPart.quadIndices[i * 4]]; aaBox += mesh.vertices[meshPart.quadIndices[i]];
aaBox += mesh.vertices[meshPart.quadIndices[i * 4 + 1]]; aaBox += mesh.vertices[meshPart.quadIndices[i + 1]];
aaBox += mesh.vertices[meshPart.quadIndices[i * 4 + 2]]; aaBox += mesh.vertices[meshPart.quadIndices[i + 2]];
aaBox += mesh.vertices[meshPart.quadIndices[i * 4 + 3]]; aaBox += mesh.vertices[meshPart.quadIndices[i + 3]];
} }
return aaBox; return aaBox;
@ -187,9 +188,7 @@ struct TriangleEdge {
} }
void sortIndices() { void sortIndices() {
if (indexB < indexA) { if (indexB < indexA) {
int t = indexA; std::swap(indexA, indexB);
indexA = indexB;
indexB = t;
} }
} }
}; };
@ -204,16 +203,18 @@ namespace std {
} }
// returns false if any edge has only one adjacent triangle // returns false if any edge has only one adjacent triangle
bool isClosedManifold(const std::vector<int>& triangles) { bool isClosedManifold(const std::vector<int>& triangleIndices) {
using EdgeList = std::unordered_map<TriangleEdge, int>; using EdgeList = std::unordered_map<TriangleEdge, int>;
EdgeList edges; EdgeList edges;
// count the triangles for each edge // count the triangles for each edge
for (size_t i = 0; i < triangles.size(); i += 3) { const uint32_t TRIANGLE_STRIDE = 3;
for (uint32_t i = 0; i < triangleIndices.size(); i += TRIANGLE_STRIDE) {
TriangleEdge edge; TriangleEdge edge;
// the triangles indices are stored in sequential order
for (int j = 0; j < 3; ++j) { for (int j = 0; j < 3; ++j) {
edge.indexA = triangles[(int)i + j]; edge.indexA = triangleIndices[(int)i + j];
edge.indexB = triangles[i + ((j + 1) % 3)]; edge.indexB = triangleIndices[i + ((j + 1) % 3)];
edge.sortIndices(); edge.sortIndices();
EdgeList::iterator edgeEntry = edges.find(edge); EdgeList::iterator edgeEntry = edges.find(edge);
@ -235,13 +236,14 @@ bool isClosedManifold(const std::vector<int>& triangles) {
void vhacd::VHACDUtil::getConvexResults(VHACD::IVHACD* convexifier, FBXMesh& resultMesh) const { void vhacd::VHACDUtil::getConvexResults(VHACD::IVHACD* convexifier, FBXMesh& resultMesh) const {
// Number of hulls for this input meshPart // Number of hulls for this input meshPart
unsigned int numHulls = convexifier->GetNConvexHulls(); uint32_t numHulls = convexifier->GetNConvexHulls();
if (_verbose) { if (_verbose) {
qDebug() << " hulls =" << numHulls; qDebug() << " hulls =" << numHulls;
} }
// create an output meshPart for each convex hull // create an output meshPart for each convex hull
for (unsigned int j = 0; j < numHulls; j++) { const uint32_t TRIANGLE_STRIDE = 3;
for (uint32_t j = 0; j < numHulls; j++) {
VHACD::IVHACD::ConvexHull hull; VHACD::IVHACD::ConvexHull hull;
convexifier->GetConvexHull(j, hull); convexifier->GetConvexHull(j, hull);
@ -249,17 +251,17 @@ void vhacd::VHACDUtil::getConvexResults(VHACD::IVHACD* convexifier, FBXMesh& res
FBXMeshPart& resultMeshPart = resultMesh.parts.last(); FBXMeshPart& resultMeshPart = resultMesh.parts.last();
int hullIndexStart = resultMesh.vertices.size(); int hullIndexStart = resultMesh.vertices.size();
for (unsigned int i = 0; i < hull.m_nPoints; i++) { for (uint32_t i = 0; i < hull.m_nPoints; i++) {
float x = hull.m_points[i * 3]; float x = hull.m_points[i * TRIANGLE_STRIDE];
float y = hull.m_points[i * 3 + 1]; float y = hull.m_points[i * TRIANGLE_STRIDE + 1];
float z = hull.m_points[i * 3 + 2]; float z = hull.m_points[i * TRIANGLE_STRIDE + 2];
resultMesh.vertices.append(glm::vec3(x, y, z)); resultMesh.vertices.append(glm::vec3(x, y, z));
} }
for (unsigned int i = 0; i < hull.m_nTriangles; i++) { for (uint32_t i = 0; i < hull.m_nTriangles; i++) {
int index0 = hull.m_triangles[i * 3] + hullIndexStart; int index0 = hull.m_triangles[i * TRIANGLE_STRIDE] + hullIndexStart;
int index1 = hull.m_triangles[i * 3 + 1] + hullIndexStart; int index1 = hull.m_triangles[i * TRIANGLE_STRIDE + 1] + hullIndexStart;
int index2 = hull.m_triangles[i * 3 + 2] + hullIndexStart; int index2 = hull.m_triangles[i * TRIANGLE_STRIDE + 2] + hullIndexStart;
resultMeshPart.triangleIndices.append(index0); resultMeshPart.triangleIndices.append(index0);
resultMeshPart.triangleIndices.append(index1); resultMeshPart.triangleIndices.append(index1);
resultMeshPart.triangleIndices.append(index2); resultMeshPart.triangleIndices.append(index2);
@ -273,7 +275,7 @@ void vhacd::VHACDUtil::getConvexResults(VHACD::IVHACD* convexifier, FBXMesh& res
} }
float computeDt(uint64_t start) { float computeDt(uint64_t start) {
return (float)(usecTimestampNow() - start) / 1.0e6f; return (float)(usecTimestampNow() - start) / (float)USECS_PER_SECOND;
} }
bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry, bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
@ -299,6 +301,9 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
result.meshes.append(FBXMesh()); result.meshes.append(FBXMesh());
FBXMesh &resultMesh = result.meshes.last(); FBXMesh &resultMesh = result.meshes.last();
const uint32_t POINT_STRIDE = 3;
const uint32_t TRIANGLE_STRIDE = 3;
int meshIndex = 0; int meshIndex = 0;
int validPartsFound = 0; int validPartsFound = 0;
foreach (const FBXMesh& mesh, geometry.meshes) { foreach (const FBXMesh& mesh, geometry.meshes) {
@ -325,7 +330,7 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
foreach (glm::vec3 vertex, mesh.vertices) { foreach (glm::vec3 vertex, mesh.vertices) {
vertices.push_back(glm::vec3(mesh.modelTransform * glm::vec4(vertex, 1.0f))); vertices.push_back(glm::vec3(mesh.modelTransform * glm::vec4(vertex, 1.0f)));
} }
auto numVertices = vertices.size(); uint32_t numVertices = vertices.size();
if (_verbose) { if (_verbose) {
qDebug() << "mesh" << meshIndex << ": " qDebug() << "mesh" << meshIndex << ": "
@ -337,12 +342,13 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
std::vector<int> openParts; std::vector<int> openParts;
int partIndex = 0; int partIndex = 0;
std::vector<int> triangleIndices;
foreach (const FBXMeshPart &meshPart, mesh.parts) { foreach (const FBXMeshPart &meshPart, mesh.parts) {
std::vector<int> triangles; triangleIndices.clear();
getTrianglesInMeshPart(meshPart, triangles); getTrianglesInMeshPart(meshPart, triangleIndices);
// only process meshes with triangles // only process meshes with triangles
if (triangles.size() <= 0) { if (triangleIndices.size() <= 0) {
if (_verbose) { if (_verbose) {
qDebug() << " skip part" << partIndex << "(zero triangles)"; qDebug() << " skip part" << partIndex << "(zero triangles)";
} }
@ -351,8 +357,8 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
} }
// collapse dupe indices // collapse dupe indices
for (auto& i : triangles) { for (auto& index : triangleIndices) {
i = dupeIndexMap[i]; index = dupeIndexMap[index];
} }
AABox aaBox = getAABoxForMeshPart(mesh, meshPart); AABox aaBox = getAABoxForMeshPart(mesh, meshPart);
@ -375,15 +381,16 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
} }
// figure out if the mesh is a closed manifold or not // figure out if the mesh is a closed manifold or not
bool closed = isClosedManifold(triangles); bool closed = isClosedManifold(triangleIndices);
if (closed) { if (closed) {
unsigned int triangleCount = (unsigned int)(triangles.size()) / 3; uint32_t triangleCount = (uint32_t)(triangleIndices.size()) / TRIANGLE_STRIDE;
if (_verbose) { if (_verbose) {
qDebug() << " process closed part" << partIndex << ": " << " triangles =" << triangleCount; qDebug() << " process closed part" << partIndex << ": " << " triangles =" << triangleCount;
} }
// compute approximate convex decomposition // compute approximate convex decomposition
bool success = convexifier->Compute(&vertices[0].x, 3, (uint)numVertices, &triangles[0], 3, triangleCount, params); bool success = convexifier->Compute(&vertices[0].x, POINT_STRIDE, numVertices,
&triangleIndices[0], TRIANGLE_STRIDE, triangleCount, params);
if (success) { if (success) {
getConvexResults(convexifier, resultMesh); getConvexResults(convexifier, resultMesh);
} else if (_verbose) { } else if (_verbose) {
@ -401,26 +408,27 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
if (! openParts.empty()) { if (! openParts.empty()) {
// combine open meshes in an attempt to produce a closed mesh // combine open meshes in an attempt to produce a closed mesh
std::vector<int> triangles; triangleIndices.clear();
for (auto index : openParts) { for (auto index : openParts) {
const FBXMeshPart &meshPart = mesh.parts[index]; const FBXMeshPart &meshPart = mesh.parts[index];
getTrianglesInMeshPart(meshPart, triangles); getTrianglesInMeshPart(meshPart, triangleIndices);
} }
// collapse dupe indices // collapse dupe indices
for (auto& i : triangles) { for (auto& index : triangleIndices) {
i = dupeIndexMap[i]; index = dupeIndexMap[index];
} }
// this time we don't care if the parts are close or not // this time we don't care if the parts are close or not
unsigned int triangleCount = (unsigned int)(triangles.size()) / 3; uint32_t triangleCount = (uint32_t)(triangleIndices.size()) / TRIANGLE_STRIDE;
if (_verbose) { if (_verbose) {
qDebug() << " process remaining open parts =" << openParts.size() << ": " qDebug() << " process remaining open parts =" << openParts.size() << ": "
<< " triangles =" << triangleCount; << " triangles =" << triangleCount;
} }
// compute approximate convex decomposition // compute approximate convex decomposition
bool success = convexifier->Compute(&vertices[0].x, 3, (uint)numVertices, &triangles[0], 3, triangleCount, params); bool success = convexifier->Compute(&vertices[0].x, POINT_STRIDE, numVertices,
&triangleIndices[0], TRIANGLE_STRIDE, triangleCount, params);
if (success) { if (success) {
getConvexResults(convexifier, resultMesh); getConvexResults(convexifier, resultMesh);
} else if (_verbose) { } else if (_verbose) {

View file

@ -318,10 +318,11 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
return; return;
} }
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();
auto loadDuration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count();
if (verbose) { if (verbose) {
qDebug() << "load time =" << (double)loadDuration / 1000000000.00 << "seconds"; auto loadDuration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count();
const double NANOSECS_PER_SECOND = 1.0e9;
qDebug() << "load time =" << (double)loadDuration / NANOSECS_PER_SECOND << "seconds";
} }
if (splitModel) { if (splitModel) {