mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 02:48:12 +02:00
better variable names and fewer magic numbers
This commit is contained in:
parent
21ef30d410
commit
e8e059c637
2 changed files with 84 additions and 75 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue