From 141745da3ac0700c67879c638b5b1e2b83d5b32d Mon Sep 17 00:00:00 2001 From: Perminder Singh <127239756+perminder-17@users.noreply.github.com> Date: Sun, 17 Nov 2024 03:27:25 +0530 Subject: [PATCH] Use flying edges for mesh generation (#1741) * adding-new-tables-for-flying-edges * adding codes for flying-edges algo, still fixing left * fixing laplace smoothing, only cleanups left Signed-off-by: Perminder Singh <127239756+perminder-17@users.noreply.github.com> --------- Signed-off-by: Perminder Signed-off-by: Geoff Hutchison Signed-off-by: Perminder Singh <127239756+perminder-17@users.noreply.github.com> --- avogadro/core/cube.cpp | 156 ++- avogadro/core/cube.h | 65 +- avogadro/core/mesh.cpp | 155 ++- avogadro/core/mesh.h | 5 + avogadro/qtgui/meshgenerator.cpp | 1569 ++++++++++++++++++-------- avogadro/qtgui/meshgenerator.h | 155 ++- avogadro/qtplugins/meshes/meshes.cpp | 40 +- avogadro/rendering/meshgeometry.cpp | 5 +- avogadro/rendering/meshgeometry.h | 4 +- 9 files changed, 1514 insertions(+), 640 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index df50fd5ace..aadbe4c709 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -37,7 +37,6 @@ bool Cube::setLimits(const Vector3& min_, const Vector3& max_, m_data.resize(m_points.x() * m_points.y() * m_points.z()); return true; } - bool Cube::setLimits(const Vector3& min_, const Vector3& max_, float spacing_) { Vector3 delta = max_ - min_; @@ -194,8 +193,159 @@ float Cube::value(int i, int j, int k) const return 0.0; } -float Cube::value(const Vector3i& pos) const +std::array Cube::computeGradient(int i, int j, int k) const +{ + int nx = m_points.x(); + int ny = m_points.y(); + int nz = m_points.z(); + int dataIdx = (i * ny * nz) + (j * nz) + k; + + std::array, 3> x; + std::array run; + + // X-direction + if (i == 0) { + x[0][0] = m_data[dataIdx + ny * nz]; + x[0][1] = m_data[dataIdx]; + run[0] = m_spacing.x(); + } else if (i == (nx - 1)) { + x[0][0] = m_data[dataIdx]; + x[0][1] = m_data[dataIdx - ny * nz]; + run[0] = m_spacing.x(); + } else { + x[0][0] = m_data[dataIdx + ny * nz]; + x[0][1] = m_data[dataIdx - ny * nz]; + run[0] = 2 * m_spacing.x(); + } + + // Y-direction + if (j == 0) { + x[1][0] = m_data[dataIdx + nz]; + x[1][1] = m_data[dataIdx]; + run[1] = m_spacing.y(); + } else if (j == (ny - 1)) { + x[1][0] = m_data[dataIdx]; + x[1][1] = m_data[dataIdx - nz]; + run[1] = m_spacing.y(); + } else { + x[1][0] = m_data[dataIdx + nz]; + x[1][1] = m_data[dataIdx - nz]; + run[1] = 2 * m_spacing.y(); + } + + // Z-direction + if (k == 0) { + x[2][0] = m_data[dataIdx + 1]; + x[2][1] = m_data[dataIdx]; + run[2] = m_spacing.z(); + } else if (k == (nz - 1)) { + x[2][0] = m_data[dataIdx]; + x[2][1] = m_data[dataIdx - 1]; + run[2] = m_spacing.z(); + } else { + x[2][0] = m_data[dataIdx + 1]; + x[2][1] = m_data[dataIdx - 1]; + run[2] = 2 * m_spacing.z(); + } + + std::array ret; + + ret[0] = (x[0][1] - x[0][0]) / run[0]; + ret[1] = (x[1][1] - x[1][0]) / run[1]; + ret[2] = (x[2][1] - x[2][0]) / run[2]; + + return ret; +} + +std::array, 8> +Cube::getGradCube(int i, int j, int k) const { + std::array, 8> grad; + + grad[0] = computeGradient(i, j, k); + grad[1] = computeGradient(i + 1, j, k); + grad[2] = computeGradient(i + 1, j + 1, k); + grad[3] = computeGradient(i, j + 1, k); + grad[4] = computeGradient(i, j, k + 1); + grad[5] = computeGradient(i + 1, j, k + 1); + grad[6] = computeGradient(i + 1, j + 1, k + 1); + grad[7] = computeGradient(i, j + 1, k + 1); + + return grad; +} + +std::array Cube::getValsCube(int i, int j, int k) const +{ + std::array vals; + + vals[0] = getData(i, j, k); + vals[1] = getData(i + 1, j, k); + vals[2] = getData(i + 1, j + 1, k); + vals[3] = getData(i, j + 1, k); + vals[4] = getData(i, j, k + 1); + vals[5] = getData(i + 1, j, k + 1); + vals[6] = getData(i + 1, j + 1, k + 1); + vals[7] = getData(i, j + 1, k + 1); + + return vals; +} + + +float Cube::getData(int i, int j, int k) const +{ + int nx = m_points.x(); + int ny = m_points.y(); + int nz = m_points.z(); + return m_data[(i * ny * nz) + (j * nz) + k]; +} + + +std::array, 8> Cube::getPosCube(int i, int j, int k) const +{ + + std::array, 8> pos; + + float xpos = m_min.x() + (i * m_spacing.x()); + float ypos = m_min.y() + (j * m_spacing.y()); + float zpos = m_min.z() + (k * m_spacing.z()); + + pos[0][0] = xpos; + pos[0][1] = ypos; + pos[0][2] = zpos; + + pos[1][0] = xpos + m_spacing.x(); + pos[1][1] = ypos; + pos[1][2] = zpos; + + pos[2][0] = xpos + m_spacing.x(); + pos[2][1] = ypos + m_spacing.y(); + pos[2][2] = zpos; + + pos[3][0] = xpos; + pos[3][1] = ypos + m_spacing.y(); + pos[3][2] = zpos; + + pos[4][0] = xpos; + pos[4][1] = ypos; + pos[4][2] = zpos + m_spacing.z(); + + pos[5][0] = xpos + m_spacing.x(); + pos[5][1] = ypos; + pos[5][2] = zpos + m_spacing.z(); + + pos[6][0] = xpos + m_spacing.x(); + pos[6][1] = ypos + m_spacing.y(); + pos[6][2] = zpos + m_spacing.z(); + + pos[7][0] = xpos; + pos[7][1] = ypos + m_spacing.y(); + pos[7][2] = zpos + m_spacing.z(); + + return pos; +} + +float Cube::value(const Vector3i& pos) const +{ unsigned int index = pos.x() * m_points.y() * m_points.z() + pos.y() * m_points.z() + pos.z(); if (index < m_data.size()) @@ -294,4 +444,4 @@ bool Cube::fillStripe( return true; } -} // End Avogadro namespace +} // End Avogadro namespace \ No newline at end of file diff --git a/avogadro/core/cube.h b/avogadro/core/cube.h index f43fd6d3d6..7d3fcda9a4 100644 --- a/avogadro/core/cube.h +++ b/avogadro/core/cube.h @@ -11,6 +11,7 @@ #include "vector.h" #include +#include namespace Avogadro::Core { @@ -21,6 +22,7 @@ class Mutex; * @class Cube cube.h * @brief Provide a data structure for regularly spaced 3D grids. * @author Marcus D. Hanwell + * @author Perminder Singh */ class AVOGADROCORE_EXPORT Cube @@ -115,7 +117,7 @@ class AVOGADROCORE_EXPORT Cube bool setLimits(const Molecule& mol, float spacing, float padding); /** - * @return Vector containing all the data in a one-dimensional array. + * @return Pointer to the vector containing all the data in a one-dimensional array. */ std::vector* data(); const std::vector* data() const; @@ -130,6 +132,11 @@ class AVOGADROCORE_EXPORT Cube */ bool addData(const std::vector& values); + /** + * @return Const iterator to the beginning of a specific row in the cube data. + */ + std::vector::const_iterator getRowIter(int j, int k) const; + /** * @return Index of the point closest to the position supplied. * @param pos Position to get closest index for. @@ -198,7 +205,7 @@ class AVOGADROCORE_EXPORT Cube * @param value Value to fill the cube with. */ void fill(float value); - + /** * Sets all indices in a Z stripe of the cube to the specified value. * @param i x component of the position. @@ -212,12 +219,12 @@ class AVOGADROCORE_EXPORT Cube ); /** - * @return The minimum value at any point in the Cube. + * @return The minimum value at any point in the Cube. */ float minValue() const { return m_minValue; } /** - * @return The maximum value at any point in the Cube. + * @return The maximum value at any point in the Cube. */ float maxValue() const { return m_maxValue; } @@ -232,6 +239,56 @@ class AVOGADROCORE_EXPORT Cube */ Mutex* lock() const { return m_lock; } + /** + * Compute the gradient at a specific point in the cube. + * @param i x index + * @param j y index + * @param k z index + * @return Gradient vector at the specified point. + */ + std::array computeGradient(int i, int j, int k) const; + + /** + * Get the values of the eight corners of a cube defined by the indices (i, j, k). + * @param i x index + * @param j y index + * @param k z index + * @return Array of values at the eight corners. + */ + std::array getValsCube(int i, int j, int k) const; + + /** + * Get the gradients at the eight corners of the cube defined by the indices (i, j, k). + * @param i x index + * @param j y index + * @param k z index + * @return Array of gradients at the eight corners. Each gradient is a 3D vector. + */ + std::array, 8> getGradCube(int i, int j, int k) const; + + /** + * Get the data value at the specified indices. + * @param i x index + * @param j y index + * @param k z index + * @return Value at the specified indices. + */ + float getData(int i, int j, int k) const; + +/** + * Retrieves the positions of the eight corners of a cube at grid indices (i, j, k). + * + * The indices (i, j, k) are converted to real-space positions (xpos, ypos, zpos), mapping grid indices to physical coordinates. + * The method returns a cube that spans one step in each of the x, y, and z directions, with step sizes defined by `m_spacing`. + * + * @param i X-index. + * @param j Y-index. + * @param k Z-index. + * @return A `std::array` of eight `(x, y, z)` coordinates representing the cube's corners. + */ + +std::array, 8> getPosCube(int i, int j, int k) const; + protected: std::vector m_data; Vector3 m_min, m_max, m_spacing; diff --git a/avogadro/core/mesh.cpp b/avogadro/core/mesh.cpp index 4cab117aa7..6f6ad8089d 100644 --- a/avogadro/core/mesh.cpp +++ b/avogadro/core/mesh.cpp @@ -21,7 +21,7 @@ Mesh::Mesh(const Mesh& other) : m_vertices(other.m_vertices), m_normals(other.m_normals), m_colors(other.m_colors), m_name(other.m_name), m_stable(true), m_isoValue(other.m_isoValue), m_other(other.m_other), m_cube(other.m_cube), - m_lock(new Mutex) + m_lock(new Mutex), m_triangles(other.m_triangles) { } @@ -60,6 +60,20 @@ const Vector3f* Mesh::vertex(int n) const return &(m_vertices[n * 3]); } + +bool Mesh::setTriangles(const Core::Array& values) +{ + m_triangles.clear(); + m_triangles = values; + return true; +} + +const Core::Array&Mesh::triangles() const +{ + return m_triangles; +} + + bool Mesh::setVertices(const Core::Array& values) { m_vertices.clear(); @@ -165,101 +179,78 @@ Mesh& Mesh::operator=(const Mesh& other) m_colors = other.m_colors; m_name = other.m_name; m_isoValue = other.m_isoValue; + m_triangles = other.m_triangles; return *this; } -void Mesh::smooth(int iterationCount) -{ - if (m_vertices.size() == 0) - return; - if (iterationCount <= 0) +void Mesh::smooth(int iterationCount) { + if (m_vertices.empty() || iterationCount <= 0) return; - // Map vertices to a plane and pass them to NeighborPerceiver - // a line gives less performance, and a volume offers no more benefit - Array planarList(m_vertices.size()); - for (size_t i = 0; i < m_vertices.size(); i++) - // Empirical constant to make the distribution more homogeneous - planarList[i] = Vector3( - double(m_vertices[i](0) + 1.31*m_vertices[i](1)), - 0.0, m_vertices[i](2)); - NeighborPerceiver perceiver(planarList, 0.1); - - // Identify degenerate vertices - std::vector indexToVertexID(m_vertices.size(), -1); - std::vector> vertexIDToIndices; - Array neighbors; - for (size_t i = 0; i < m_vertices.size(); i++) { - if (indexToVertexID[i] != -1) - continue; - perceiver.getNeighborsInclusiveInPlace(neighbors, planarList[i]); - size_t vertexID = vertexIDToIndices.size(); - for (size_t n: neighbors) { - if ((m_vertices[n] - m_vertices[i]).norm() < 0.0001) { - if (vertexID == vertexIDToIndices.size()) - vertexIDToIndices.emplace_back(); - indexToVertexID[n] = vertexID; - vertexIDToIndices[vertexID].push_back(n); - } - } + // Build vertex adjacency information from triangles (1-ring) + std::vector> adjacencyList(m_vertices.size()); + for (const auto& tri : m_triangles) { + size_t i = static_cast(tri.x()); + size_t j = static_cast(tri.y()); + size_t k = static_cast(tri.z()); + + adjacencyList[i].push_back(j); + adjacencyList[i].push_back(k); + adjacencyList[j].push_back(i); + adjacencyList[j].push_back(k); + adjacencyList[k].push_back(i); + adjacencyList[k].push_back(j); } - // Compute 1-ring - std::vector> vertexIDTo1Ring(vertexIDToIndices.size()); - for (size_t id = 0; id < vertexIDToIndices.size(); id++) { - for (size_t v: vertexIDToIndices[id]) { - size_t relative = v % 3; - size_t triangle = v - relative; - std::array candidates{{ - triangle + (relative + 1) % 3, - triangle + (relative + 2) % 3 - }}; - for (size_t candidate: candidates) { - size_t newID = indexToVertexID[candidate]; - if (std::find(vertexIDToIndices[id].begin(), vertexIDToIndices[id].end(), newID) - == vertexIDToIndices[id].end()) - vertexIDTo1Ring[id].push_back(newID); - } - } + // Remove duplicate neighbors and sort for faster lookups later (if needed) + for (auto& neighbors : adjacencyList) { + std::sort(neighbors.begin(), neighbors.end()); + neighbors.erase(std::unique(neighbors.begin(), neighbors.end()), neighbors.end()); } + float weight = 1.0f; - for (int iteration = iterationCount; iteration > 0; iteration--) { - // Copy vertices by ID into source array - std::vector inputVertices(vertexIDToIndices.size()); - for (size_t id = 0; id < vertexIDToIndices.size(); id++) - inputVertices[id] = m_vertices[vertexIDToIndices[id][0]]; - - // Apply Laplacian smoothing - for (size_t id = 0; id < inputVertices.size(); id++) { - Vector3f output(0.0f, 0.0f, 0.0f); - for (size_t neighbor: vertexIDTo1Ring[id]) - output += inputVertices[neighbor]; - output += weight * inputVertices[id]; - output *= 1.0f / (weight + vertexIDTo1Ring[id].size()); - if (iteration == 1) - for (size_t i: vertexIDToIndices[id]) - m_vertices[i] = output; - else - m_vertices[vertexIDToIndices[id][0]] = output; + for (int iteration = 0; iteration < iterationCount; ++iteration) { + Array newVertices = m_vertices; // Store smoothed vertices + + for (size_t i = 0; i < m_vertices.size(); ++i) { + Vector3f sum(0.0f, 0.0f, 0.0f); + size_t neighborCount = adjacencyList[i].size(); + + if (neighborCount > 0) { // Prevent division by zero for isolated vertices + for (size_t neighbor : adjacencyList[i]) { + sum += m_vertices[neighbor]; + } + sum += weight * m_vertices[i]; + newVertices[i] = sum / (weight + neighborCount); + } // Else keep the original vertex position if isolated } + m_vertices = newVertices; // Update vertices after processing all } - // Recompute normals - for (auto & vertexIDToIndice : vertexIDToIndices) { - Vector3f normal(0.0f, 0.0f, 0.0f); - for (size_t v: vertexIDToIndice) { - size_t relative = v % 3; - size_t triangle = v - relative; - Vector3f &a = m_vertices[v]; - Vector3f &b = m_vertices[triangle + (relative + 1) % 3]; - Vector3f &c = m_vertices[triangle + (relative + 2) % 3]; - Vector3f triangleNormal = (b - a).cross(c - a); - normal += triangleNormal.normalized(); - } - for (size_t i: vertexIDToIndice) - m_normals[i] = normal.normalized(); + + m_normals.clear(); + m_normals.resize(m_vertices.size(), Vector3f(0.0f, 0.0f, 0.0f)); + + for (const auto& tri : m_triangles) { + size_t i = static_cast(tri.x()); + size_t j = static_cast(tri.y()); + size_t k = static_cast(tri.z()); + + Vector3f a = m_vertices[i]; + Vector3f b = m_vertices[j]; + Vector3f c = m_vertices[k]; + Vector3f triangleNormal = (b - a).cross(c - a).normalized(); + + m_normals[i] += triangleNormal; + m_normals[j] += triangleNormal; + m_normals[k] += triangleNormal; + + } + + for (auto& normal : m_normals) { + normal.normalize(); } } diff --git a/avogadro/core/mesh.h b/avogadro/core/mesh.h index b1872fd59c..e3e37b7073 100644 --- a/avogadro/core/mesh.h +++ b/avogadro/core/mesh.h @@ -119,6 +119,10 @@ class AVOGADROCORE_EXPORT Mesh */ const Vector3f* vertex(int n) const; + bool setTriangles(const Core::Array& values); + const Core::Array& triangles() const; + + /** * Clear the vertices vector and assign new values. */ @@ -225,6 +229,7 @@ class AVOGADROCORE_EXPORT Mesh Core::Array m_vertices; Core::Array m_normals; Core::Array m_colors; + Core::Array m_triangles; std::string m_name; bool m_stable; float m_isoValue; diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 45219537cf..42628b4766 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -47,19 +47,427 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, m_iso = iso; m_passes = passes; m_reverseWinding = reverse; - if (!m_cube->lock()->tryLock()) { - qDebug() << "Cannot get a read lock…"; - return false; - } + + for (unsigned int i = 0; i < 3; ++i) m_stepSize[i] = static_cast(m_cube->spacing()[i]); m_min = m_cube->min().cast(); m_dim = m_cube->dimensions(); + edgeCases.resize((m_dim.x() - 1) * (m_dim.y()) * (m_dim.z())); + cubeCases.resize((m_dim.x() - 1) * (m_dim.y() - 1) * (m_dim.z() - 1)); + gridEdges.resize(m_dim.y() * m_dim.z()); + triCounter.resize((m_dim.y() - 1) * (m_dim.z() - 1)); + m_progmax = m_dim.x(); - m_cube->lock()->unlock(); + return true; } +void MeshGenerator::FlyingEdgesAlgorithmPass1() +{ + for (int k = 0; k != m_dim.z(); ++k) { + for (int j = 0; j != m_dim.y(); ++j) { + + auto curEdgeCases = edgeCases.begin() + (m_dim.x() - 1) * (k * m_dim.y() + j); + std::array isGE; + isGE[0] = (m_cube->getData(0, j, k) >= m_iso); + + for (int i = 1; i != m_dim.x(); ++i) { + isGE[i % 2] = (m_cube->getData(i, j, k) >= m_iso); + curEdgeCases[i - 1] = calcCaseEdge(isGE[(i + 1) % 2], isGE[i % 2]); + } + } + } + + for(int k = 0; k != m_dim.z(); ++k){ + for(int j = 0; j != m_dim.y(); ++j) + { + gridEdge& curGridEdge = gridEdges[k * m_dim.y() + j]; + curGridEdge.xl = m_dim.x(); + + + for(int i = 1; i != m_dim.x(); ++i) + { + // if the edge is cut + if(isCutEdge(i-1, j, k)) + { + if(curGridEdge.xl == m_dim.x()) + { + curGridEdge.xl = i-1; + } + curGridEdge.xr = i; + } + } + }} +} + + +void MeshGenerator::FlyingEdgesAlgorithmPass2() +{ + for(int k = 0; k != m_dim.z() - 1; ++k){ + for(int j = 0; j != m_dim.y() - 1; ++j) + { + int xl, xr; + calcTrimValues(xl, xr, j, k); // xl, xr set in this function + + gridEdge& ge0 = gridEdges[k * m_dim.y() + j]; + gridEdge& ge1 = gridEdges[k* m_dim.y() +j + 1]; + gridEdge& ge2 = gridEdges[(k+1) * m_dim.y() + j]; + gridEdge& ge3 = gridEdges[(k+1) * m_dim.y() + j + 1]; + + auto const& ec0 = edgeCases.begin() + (m_dim.x()-1) * (k * m_dim.y() + j); + auto const& ec1 = edgeCases.begin() + (m_dim.x()-1) * (k * m_dim.y() + j + 1); + auto const& ec2 = edgeCases.begin() + (m_dim.x()-1) * ((k+1) * m_dim.y() + j); + auto const& ec3 = edgeCases.begin() + (m_dim.x()-1) * ((k+1) * m_dim.y() + j + 1); + + // Count the number of triangles along this row of cubes + int& curTriCounter = *(triCounter.begin() + k * (m_dim.y() - 1) + j); + + + auto curCubeCaseIds = cubeCases.begin() + (m_dim.x() - 1) * (k * (m_dim.y() - 1) + j); + + bool isYEnd = (j == m_dim.y() - 2); + bool isZEnd = (k == m_dim.z() - 2); + + + + for(int i = xl; i != xr; ++i) + { + bool isXEnd = (i == m_dim.x() - 2); + + unsigned char caseId = calcCubeCase(ec0[i], ec1[i], ec2[i], ec3[i]); // todo cubeCase not decleared + curCubeCaseIds[i] = caseId; + + if(caseId == 0 || caseId == 255) + { + continue; + } + + curTriCounter += m_numTris[caseId]; // not declared + + const bool* isCutCase = m_isCut[caseId]; // size 12 + + ge0.xstart += isCutCase[0]; + ge0.ystart += isCutCase[3]; + ge0.zstart += isCutCase[8]; + + if(isXEnd) + { + ge0.ystart += isCutCase[1]; + ge0.zstart += isCutCase[9]; + } + + if(isYEnd) + { + ge1.xstart += isCutCase[2]; + ge1.zstart += isCutCase[10]; + } + if(isZEnd) + { + ge2.xstart += isCutCase[4]; + ge2.ystart += isCutCase[7]; + } + if(isXEnd && isYEnd) + { + ge1.zstart += isCutCase[11]; + } + if(isXEnd && isZEnd) + { + ge2.ystart += isCutCase[5]; + } + if(isYEnd && isZEnd) + { + ge3.xstart += isCutCase[6]; + } + } + } + } +} + + + +void MeshGenerator::FlyingEdgesAlgorithmPass3() +{ + int tmp; + int triAccum = 0; + for(int k = 0; k != m_dim.z() -1; ++k) { + for(int j = 0; j != m_dim.y()-1; ++j) + { + int& curTriCounter = triCounter[k*(m_dim.y()-1)+j]; + + tmp = curTriCounter; + curTriCounter = triAccum; + triAccum += tmp; + }} + + int pointAccum = 0; + for(int k = 0; k != m_dim.z(); ++k) { + for(int j = 0; j != m_dim.y(); ++j) + { + gridEdge& curGridEdge = gridEdges[(k * m_dim.y()) + j]; + + tmp = curGridEdge.xstart; + curGridEdge.xstart = pointAccum; + pointAccum += tmp; + + tmp = curGridEdge.ystart; + curGridEdge.ystart = pointAccum; + pointAccum += tmp; + + tmp = curGridEdge.zstart; + curGridEdge.zstart = pointAccum; + pointAccum += tmp; + }} + + m_vertices.resize(pointAccum); + m_normals.resize(pointAccum); + m_triangles.resize(triAccum); + +} + +void MeshGenerator::FlyingEdgesAlgorithmPass4() +{ + + for(int k = 0; k != m_dim.z() -1; ++k) { + for(int j = 0; j != m_dim.y()-1; ++j) + { + // find adjusted trim values + int xl, xr; + calcTrimValues(xl, xr, j, k); // xl, xr set in this function + + if(xl == xr) + continue; + + int triIdx = triCounter[(k*(m_dim.y()-1)) + j]; + auto curCubeCaseIds = cubeCases.begin() + (m_dim.x()-1)*(k*(m_dim.y()-1) + j); + + gridEdge const& ge0 = gridEdges[k* m_dim.y() + j]; + gridEdge const& ge1 = gridEdges[k* m_dim.y() + j + 1]; + gridEdge const& ge2 = gridEdges[(k+1)* m_dim.y() + j]; + gridEdge const& ge3 = gridEdges[(k+1)* m_dim.y() + j + 1]; + + int x0counter = 0; + int y0counter = 0; + int z0counter = 0; + + int x1counter = 0; + int z1counter = 0; + + int x2counter = 0; + int y2counter = 0; + + int x3counter = 0; + + bool isYEnd = (j == m_dim.y()-2); + bool isZEnd = (k == m_dim.z()-2); + + for(int i = xl; i != xr; ++i) + { + bool isXEnd = (i == m_dim.x()-2); + + unsigned char caseId = curCubeCaseIds[i]; + + if(caseId == 0 || caseId == 255) + { + continue; + } + + const bool* isCutCase = m_isCut[caseId]; // size 12 + std::array, 8> pointCube = m_cube->getPosCube(i, j, k); + std::array isovalCube = m_cube->getValsCube(i, j, k); + std::array, 8> gradCube = m_cube->getGradCube(i, j, k); + + // Add Points and normals. + // Calculate global indices for triangles + std::array globalIdxs; + + if(isCutCase[0]) + { + // points-> array + int idx = ge0.xstart + x0counter; + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 0); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 0); + + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + globalIdxs[0] = idx; + ++x0counter; + } + + if(isCutCase[3]) + { + int idx = ge0.ystart + y0counter; + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 3); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 3); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + globalIdxs[3] = idx; + ++y0counter; + } + + if(isCutCase[8]) + { + int idx = ge0.zstart + z0counter; + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 8); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 8); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + globalIdxs[8] = idx; + ++z0counter; + } + + if(isCutCase[1]) + { + int idx = ge0.ystart + y0counter; + if(isXEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 1); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 1); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + // y0counter counter doesn't need to be incremented + // because it won't be used again. + } + globalIdxs[1] = idx; + } + + if(isCutCase[9]) + { + int idx = ge0.zstart + z0counter; + if(isXEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 9); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 9); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + // z0counter doesn't need to in incremented. + } + globalIdxs[9] = idx; + } + + if(isCutCase[2]) + { + int idx = ge1.xstart + x1counter; + if(isYEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 2); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 2); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + } + globalIdxs[2] = idx; + ++x1counter; + } + + if(isCutCase[10]) + { + int idx = ge1.zstart + z1counter; + + if(isYEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 10); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 10); + + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + } + globalIdxs[10] = idx; + ++z1counter; + } + + if(isCutCase[4]) + { + int idx = ge2.xstart + x2counter; + if(isZEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 4); + + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 4); + + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + } + globalIdxs[4] = idx; + ++x2counter; + } + + if(isCutCase[7]) + { + int idx = ge2.ystart + y2counter; + if(isZEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 7); + + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 7); + + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + } + globalIdxs[7] = idx; + ++y2counter; + } + + if(isCutCase[11]) + { + int idx = ge1.zstart + z1counter; + if(isXEnd && isYEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 11); + + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 11); + + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + } + globalIdxs[11] = idx; + } + + if(isCutCase[5]) + { + int idx = ge2.ystart + y2counter; + if(isXEnd && isZEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 5); + + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 5); + + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + // y2 counter does not need to be incremented. + } + globalIdxs[5] = idx; + } + + if(isCutCase[6]) + { + int idx = ge3.xstart + x3counter; + if(isYEnd && isZEnd) + { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 6); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 6); + + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + } + globalIdxs[6] = idx; + ++x3counter; + } + + // Add triangles + const char* caseTri = m_caseTriangles[caseId]; // size 16 + for(int idx = 0; caseTri[idx] != -1; idx += 3) + { + + m_triangles[triIdx][0] = globalIdxs[caseTri[idx]]; + m_triangles[triIdx][1] = globalIdxs[caseTri[idx+1]]; + m_triangles[triIdx][2] = globalIdxs[caseTri[idx+2]]; + ++triIdx; + } + } + }} +} + + void MeshGenerator::run() { if (!m_cube || !m_mesh) { @@ -67,46 +475,32 @@ void MeshGenerator::run() return; } - // Attempt to obtain a lock, wait one second between attempts. - while (!m_cube->lock()->tryLock()) - sleep(1); - - // Mark the mesh as being worked on and clear it m_mesh->setStable(false); m_mesh->clear(); - m_vertices.reserve(m_dim.x() * m_dim.y() * m_dim.z() * 3); - m_normals.reserve(m_dim.x() * m_dim.y() * m_dim.z() * 3); - - // Now to march the cube - for (int i = 0; i < m_dim.x() - 1; ++i) { - for (int j = 0; j < m_dim.y() - 1; ++j) { - for (int k = 0; k < m_dim.z() - 1; ++k) { - marchingCube(Vector3i(i, j, k)); - } - } - if (m_vertices.capacity() < m_vertices.size() + m_dim.y() * m_dim.x() * 3) { - m_vertices.reserve(m_vertices.capacity() * 2); - m_normals.reserve(m_normals.capacity() * 2); - } - emit progressValueChanged(i); - } + // flying-edges passes for the creation of normal, vertices and triangles + FlyingEdgesAlgorithmPass1(); + FlyingEdgesAlgorithmPass2(); + FlyingEdgesAlgorithmPass3(); + FlyingEdgesAlgorithmPass4(); - m_cube->lock()->unlock(); - - // Copy the data across m_mesh->setVertices(m_vertices); m_mesh->setNormals(m_normals); + m_mesh->setTriangles(m_triangles); + m_mesh->smooth(m_passes); m_mesh->setStable(true); - // Now we are done give all that memory back + // clearing the memory m_vertices.resize(0); m_normals.resize(0); - - // Smooth out the mesh - m_mesh->smooth(m_passes); + m_triangles.resize(0); + edgeCases.resize(0); + cubeCases.resize(0); + gridEdges.resize(0); + triCounter.resize(0); } + void MeshGenerator::clear() { m_iso = 0.0; @@ -120,23 +514,83 @@ void MeshGenerator::clear() m_progmax = 0; } -Vector3f MeshGenerator::normal(const Vector3f& pos) +unsigned char MeshGenerator::calcCubeCase( + unsigned char const& ec0, unsigned char const& ec1, + unsigned char const& ec2, unsigned char const& ec3) const +{ + unsigned char caseId = 0; + if ((ec0 == 0) || (ec0 == 2)) // Vertex 0 at (i, j, k) + caseId |= 1; + if ((ec0 == 0) || (ec0 == 1)) // Vertex 1 at (i+1, j, k) + caseId |= 2; + if ((ec1 == 0) || (ec1 == 1)) // Vertex 2 at (i+1, j+1, k) + caseId |= 4; + if ((ec1 == 0) || (ec1 == 2)) // Vertex 3 at (i, j+1, k) + caseId |= 8; + if ((ec2 == 0) || (ec2 == 2)) // Vertex 4 at (i, j, k+1) + caseId |= 16; + if ((ec2 == 0) || (ec2 == 1)) // Vertex 5 at (i+1, j, k+1) + caseId |= 32; + if ((ec3 == 0) || (ec3 == 1)) // Vertex 6 at (i+1, j+1, k+1) + caseId |= 64; + if ((ec3 == 0) || (ec3 == 2)) // Vertex 7 at (i, j+1, k+1) + caseId |= 128; + return caseId; +} + + +bool MeshGenerator::isCutEdge(int const& i, int const& j, int const& k) const { - Vector3f norm(m_cube->valuef(pos - Vector3f(0.01f, 0.00f, 0.00f)) - - m_cube->valuef(pos + Vector3f(0.01f, 0.00f, 0.00f)), - m_cube->valuef(pos - Vector3f(0.00f, 0.01f, 0.00f)) - - m_cube->valuef(pos + Vector3f(0.00f, 0.01f, 0.00f)), - m_cube->valuef(pos - Vector3f(0.00f, 0.00f, 0.01f)) - - m_cube->valuef(pos + Vector3f(0.00f, 0.00f, 0.01f))); - norm.normalize(); - return norm; + // Assuming edgeCases are all set + int edgeCaseIdx = k * ((m_dim.x() - 1) * m_dim.y()) + (j * (m_dim.x() - 1)) + i; + unsigned char edgeCase = edgeCases[edgeCaseIdx]; + + if (edgeCase == 1 || edgeCase == 2) + { + return true; + } + + if (j != m_dim.y() - 1) + { + int edgeCaseIdxY = (k * (m_dim.x() - 1) * m_dim.y()) + ((j + 1) * (m_dim.x() - 1)) + i; + unsigned char edgeCaseY = edgeCases[edgeCaseIdxY]; + + // If the sum is odd, the edge along the y-axis is cut + if ((edgeCase + edgeCaseY) % 2 == 1) + { + return true; + } + } + + if (k != m_dim.z() - 1) + { + int edgeCaseIdxZ = ((k + 1) * (m_dim.x() - 1) * m_dim.y()) + (j * (m_dim.x() - 1)) + i; + unsigned char edgeCaseZ = edgeCases[edgeCaseIdxZ]; + + // If the sum is odd, the edge along the z-axis is cut + if ((edgeCase + edgeCaseZ) % 2 == 1) + { + return true; + } + } + return false; } -inline float MeshGenerator::offset(float val1, float val2) +unsigned char MeshGenerator::calcCaseEdge(bool const& prevEdge, bool const& currEdge) const { - if (val2 - val1 < 1.0e-9f && val1 - val2 < 1.0e-9f) - return 0.5; - return (m_iso - val1) / (val2 - val1); + // o -- is greater than or equal to + // case 0: prevEdge = true, currEdge = true + // case 1: prevEdge = false, currEdge = true + // case 2: prevEdge = true, currEdge = false + // case 3: prevEdge = false, currEdge = false + if (prevEdge && currEdge) + return 0; + if (!prevEdge && currEdge) + return 1; + if (prevEdge && !currEdge) + return 2; + else // !prevEdge && !currEdge + return 3; } unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) @@ -145,469 +599,598 @@ unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) return 0; } -bool MeshGenerator::marchingCube(const Vector3i& pos) +void MeshGenerator::calcTrimValues(int& xl, int& xr, int const& j, int const& k) const { - float afCubeValue[8]; - Vector3f asEdgeVertex[12]; - Vector3f asEdgeNorm[12]; - // Calculate the position in the Cube - Vector3f fPos; - for (unsigned int i = 0; i < 3; ++i) - fPos[i] = static_cast(pos[i]) * m_stepSize[i] + m_min[i]; + const gridEdge& ge0 = gridEdges[k * m_dim.y() + j]; + const gridEdge& ge1 = gridEdges[k * m_dim.y() + j + 1]; + const gridEdge& ge2 = gridEdges[(k + 1) * m_dim.y() + j]; + const gridEdge& ge3 = gridEdges[(k + 1) * m_dim.y() + j + 1]; - // Make a local copy of the values at the cube's corners - for (int i = 0; i < 8; ++i) { - afCubeValue[i] = static_cast( - m_cube->value(Vector3i(pos + Vector3i(a2iVertexOffset[i])))); - } + xl = std::min({ge0.xl, ge1.xl, ge2.xl, ge3.xl}); + xr = std::max({ge0.xr, ge1.xr, ge2.xr, ge3.xr}); - // Find which vertices are inside of the surface and which are outside - long iFlagIndex = 0; - for (int i = 0; i < 8; ++i) { - if (afCubeValue[i] <= m_iso) { - iFlagIndex |= 1 << i; - } - } - - // Find which edges are intersected by the surface - long iEdgeFlags = aiCubeEdgeFlags[iFlagIndex]; - - // No intersections if the cube is entirely inside or outside of the surface - if (iEdgeFlags == 0) { - return false; - } - - // Find the point of intersection of the surface with each edge - // Then find the normal to the surface at those points - for (int i = 0; i < 12; ++i) { - // if there is an intersection on this edge - if (iEdgeFlags & (1 << i)) { - float fOffset = offset(afCubeValue[a2iEdgeConnection[i][0]], - afCubeValue[a2iEdgeConnection[i][1]]); - - asEdgeVertex[i] = - Vector3f(fPos.x() + - (a2fVertexOffset[a2iEdgeConnection[i][0]][0] + - fOffset * a2fEdgeDirection[i][0]) * - m_stepSize[0], - fPos.y() + - (a2fVertexOffset[a2iEdgeConnection[i][0]][1] + - fOffset * a2fEdgeDirection[i][1]) * - m_stepSize[1], - fPos.z() + - (a2fVertexOffset[a2iEdgeConnection[i][0]][2] + - fOffset * a2fEdgeDirection[i][2]) * - m_stepSize[2]); - - /// FIXME Optimize this to only calculate normals when required - asEdgeNorm[i] = normal(asEdgeVertex[i]); - } - } - // Store the triangles that were found, there can be up to five per cube - for (int i = 0; i < 5; ++i) { - if (a2iTriangleConnectionTable[iFlagIndex][3 * i] < 0) - break; - int iVertex = 0; - iEdgeFlags = a2iTriangleConnectionTable[iFlagIndex][3 * i]; - // Make sure we get the triangle winding the right way around! - if (!m_reverseWinding) { - for (int j = 0; j < 3; ++j) { - iVertex = a2iTriangleConnectionTable[iFlagIndex][3 * i + j]; - m_indices.push_back(static_cast(m_vertices.size())); - m_normals.push_back(asEdgeNorm[iVertex]); - m_vertices.push_back(asEdgeVertex[iVertex]); - } - } else { - for (int j = 2; j >= 0; --j) { - iVertex = a2iTriangleConnectionTable[iFlagIndex][3 * i + j]; - m_indices.push_back(static_cast(m_vertices.size())); - m_normals.push_back(-asEdgeNorm[iVertex]); - m_vertices.push_back(asEdgeVertex[iVertex]); - } - } - } - return true; + if (xl > xr) + xl = xr; } -// Lists the positions, relative to vertex0, of the 8 vertices of a cube -const float MeshGenerator::a2fVertexOffset[8][3] = { - { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 }, - { 0.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 1.0, 1.0 }, { 0.0, 1.0, 1.0 } -}; +inline std::array +MeshGenerator::interpolateOnCube( + std::array, 8> const& pts, + std::array const& isovals, + unsigned char const& edge) const +{ + unsigned char i0 = m_edgeVertices[edge][0]; + unsigned char i1 = m_edgeVertices[edge][1]; -// Integer form of the vertex offsets, more useful for Avogadro Cubes -const int MeshGenerator::a2iVertexOffset[8][3] = { { 0, 0, 0 }, { 1, 0, 0 }, - { 1, 1, 0 }, { 0, 1, 0 }, - { 0, 0, 1 }, { 1, 0, 1 }, - { 1, 1, 1 }, { 0, 1, 1 } }; + float weight = (m_iso - isovals[i0]) / (isovals[i1] - isovals[i0]); + return interpolate(pts[i0], pts[i1], weight); -// Lists the index of the endpoint vertices for the 12 edges of the cube -const int MeshGenerator::a2iEdgeConnection[12][2] = { - { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 4, 5 }, { 5, 6 }, - { 6, 7 }, { 7, 4 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } -}; +} -// Lists the direction vector (vertex1-vertex0) for each edge in the cube -const float MeshGenerator::a2fEdgeDirection[12][3] = { - { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { -1.0, 0.0, 0.0 }, { 0.0, -1.0, 0.0 }, - { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { -1.0, 0.0, 0.0 }, { 0.0, -1.0, 0.0 }, - { 0.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 } -}; +inline std::array +MeshGenerator::interpolate( + std::array const& a, + std::array const& b, + float const& weight) const +{ + std::array ret; + ret[0] = a[0] + (weight * (b[0] - a[0])); + ret[1] = a[1] + (weight * (b[1] - a[1])); + ret[2] = a[2] + (weight * (b[2] - a[2])); + return ret; +} -// Lists the index of the endpoint vertices for the 6 edges of the tetrahedron -const int MeshGenerator::a2iTetrahedronEdgeConnection[6][2] = { - { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 3 }, { 1, 3 }, { 2, 3 } -}; +// flying edges tables using: -// Lists the index of vertices from a cube that made up each of the six -// tetrahedrons within the cube -const int MeshGenerator::a2iTetrahedronsInACube[6][4] = { - { 0, 5, 1, 6 }, { 0, 1, 2, 6 }, { 0, 2, 3, 6 }, - { 0, 3, 7, 6 }, { 0, 7, 4, 6 }, { 0, 4, 5, 6 }, -}; -// For any edge, if one vertex is inside of the surface and the other -// is outside of the surface then the edge intersects the surface -// For each of the 4 vertices of the tetrahedron can be two possible -// states : either inside or outside of the surface -// For any tetrahedron the are 2^4=16 possible sets of vertex states -// This table lists the edges intersected by the surface for all 16 -// possible vertex states. -// There are 6 edges. For each entry in the table, if edge #n is -// intersected, then bit #n is set to 1 -const long MeshGenerator::aiTetrahedronEdgeFlags[16] = { - 0x00, 0x0d, 0x13, 0x1e, 0x26, 0x2b, 0x35, 0x38, - 0x38, 0x35, 0x2b, 0x26, 0x1e, 0x13, 0x0d, 0x00, -}; +const unsigned char MeshGenerator::m_numTris[256] = + { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 2, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, + 2, 3, 3, 2, 3, 4, 4, 3, 3, 4, 4, 3, 4, 5, 5, 2, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4, + 2, 3, 3, 4, 3, 4, 2, 3, 3, 4, 4, 5, 4, 5, 3, 2, + 3, 4, 4, 3, 4, 5, 3, 2, 4, 5, 5, 4, 5, 2, 4, 1, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 2, 4, 3, 4, 3, 5, 2, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4, + 3, 4, 4, 3, 4, 5, 5, 4, 4, 3, 5, 2, 5, 4, 2, 1, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 2, 3, 3, 2, + 3, 4, 4, 5, 4, 5, 5, 2, 4, 3, 5, 4, 3, 2, 4, 1, + 3, 4, 4, 5, 4, 5, 3, 4, 4, 5, 5, 2, 3, 4, 2, 1, + 2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0 + }; -// For each of the possible vertex states listed in aiTetrahedronEdgeFlags -// there is a specific triangulation -// of the edge intersection points. a2iTetrahedronTriangles lists all of -// them in the form of -// 0-2 edge triples with the list terminated by the invalid value -1. -// -// I generated this table by hand -const int MeshGenerator::a2iTetrahedronTriangles[16][7] = { - { -1, -1, -1, -1, -1, -1, -1 }, { 0, 3, 2, -1, -1, -1, -1 }, - { 0, 1, 4, -1, -1, -1, -1 }, { 1, 4, 2, 2, 4, 3, -1 }, - - { 1, 2, 5, -1, -1, -1, -1 }, { 0, 3, 5, 0, 5, 1, -1 }, - { 0, 2, 5, 0, 5, 4, -1 }, { 5, 4, 3, -1, -1, -1, -1 }, - - { 3, 4, 5, -1, -1, -1, -1 }, { 4, 5, 0, 5, 2, 0, -1 }, - { 1, 5, 0, 5, 3, 0, -1 }, { 5, 2, 1, -1, -1, -1, -1 }, - - { 3, 4, 2, 2, 4, 1, -1 }, { 4, 1, 0, -1, -1, -1, -1 }, - { 2, 3, 0, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1 }, +const bool MeshGenerator::m_isCut[256][12] = +{ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1}, + {1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1}, + {0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0}, + {1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0}, + {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1}, + {1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1}, + {1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}, + {0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0}, + {1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0}, + {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0}, + {0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0}, + {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1}, + {1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1}, + {1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1}, + {0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1}, + {0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0}, + {1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0}, + {1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0}, + {0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0}, + {0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1}, + {1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1}, + {1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1}, + {0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0}, + {1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0}, + {1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0}, + {0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1}, + {1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1}, + {1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1}, + {0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1}, + {0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0}, + {1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0}, + {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0}, + {0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0}, + {0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1}, + {1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1}, + {1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1}, + {0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0}, + {1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0}, + {1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0}, + {0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1}, + {1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1}, + {1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1}, + {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1}, + {0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0}, + {1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0}, + {1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0}, + {0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0}, + {0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1}, + {1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1}, + {1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1}, + {0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1}, + {1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1}, + {1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1}, + {0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1}, + {0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0}, + {1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0}, + {0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1}, + {1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1}, + {1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1}, + {0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1}, + {0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0}, + {1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0}, + {1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1}, + {1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1}, + {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1}, + {0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1}, + {0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0}, + {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1}, + {1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1}, + {0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0}, + {1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0}, + {1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0}, + {0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1}, + {1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1}, + {1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1}, + {0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1}, + {0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0}, + {1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0}, + {1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1}, + {1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1}, + {0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1}, + {0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, + {1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0}, + {1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0}, + {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1}, + {1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1}, + {1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1}, + {0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1}, + {0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0}, + {1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0}, + {1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1}, + {1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1}, + {1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1}, + {0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1}, + {0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0}, + {1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0}, + {1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0}, + {1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0}, + {1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0}, + {0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1}, + {1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1}, + {1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1}, + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0}, + {1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + {1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0}, + {0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0}, + {0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1}, + {1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1}, + {1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1}, + {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0}, + {1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0}, + {1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0}, + {0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, + {0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1}, + {1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1}, + {1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1}, + {0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1}, + {0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0}, + {1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}, + {1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0}, + {0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0}, + {0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1}, + {1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1}, + {1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1}, + {0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1}, + {0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0}, + {1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0}, + {0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0}, + {0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1}, + {0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0}, + {1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1}, + {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1}, + {1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1}, + {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1}, + {0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0}, + {1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0}, + {1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0}, + {0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0}, + {0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1}, + {1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1}, + {1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1}, + {0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1}, + {0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0}, + {1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0}, + {1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0}, + {0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1}, + {1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1}, + {1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1}, + {1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1}, + {1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1}, + {0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1}, + {0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0}, + {1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0}, + {1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0}, + {0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0}, + {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1}, + {1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1}, + {1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1}, + {0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1}, + {0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0}, + {1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1}, + {1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1}, + {1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1}, + {0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1}, + {0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0}, + {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0}, + {1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1}, + {1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1}, + {1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1}, + {0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1}, + {0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0}, + {1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0}, + {0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, + {1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1}, + {1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1}, + {0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1}, + {0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0}, + {1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0}, + {1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0}, + {0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0}, + {0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1}, + {1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1}, + {1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1}, + {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1}, + {0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0}, + {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0}, + {1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}, + {1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1}, + {1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1}, + {0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, + {1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1}, + {1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1}, + {1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; -// For any edge, if one vertex is inside of the surface and the other is -// outside of the surface -// then the edge intersects the surface -// For each of the 8 vertices of the cube can be two possible states : -// either inside or outside of the surface -// For any cube the are 2^8=256 possible sets of vertex states -// This table lists the edges intersected by the surface for all 256 -// possible vertex states -// There are 12 edges. For each entry in the table, if edge #n is -// intersected, then bit #n is set to 1 -const long MeshGenerator::aiCubeEdgeFlags[256] = { - 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, - 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, - 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, - 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, - 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, - 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, - 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, - 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc, - 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, - 0x55a, 0x256, 0x35f, 0x055, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, - 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xfcc, - 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, - 0xcc6, 0xdcf, 0xec5, 0xfcc, 0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, - 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x055, - 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, - 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, - 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, - 0x066, 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, - 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0, 0xd30, - 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, - 0x13a, 0x033, 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, - 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190, 0xf00, 0xe09, - 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, - 0x203, 0x109, 0x000 -}; +const char MeshGenerator::m_caseTriangles[256][16] + { + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 3, 8, 1, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {9, 11, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {2, 3, 8, 2, 8, 11, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, + {3, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 2, 10, 8, 0, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 0, 9, 2, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 2, 10, 1, 10, 9, 9, 10, 8, -1, -1, -1, -1, -1, -1, -1}, + {3, 1, 11, 10, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 1, 11, 0, 11, 8, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, + {3, 0, 9, 3, 9, 10, 10, 9, 11, -1, -1, -1, -1, -1, -1, -1}, + {9, 11, 8, 11, 10, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 9, 1, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, + {1, 11, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {3, 7, 4, 3, 4, 0, 1, 11, 2, -1, -1, -1, -1, -1, -1, -1}, + {9, 11, 2, 9, 2, 0, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1}, + {2, 9, 11, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, + {8, 7, 4, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {10, 7, 4, 10, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, + {9, 1, 0, 8, 7, 4, 2, 10, 3, -1, -1, -1, -1, -1, -1, -1}, + {4, 10, 7, 9, 10, 4, 9, 2, 10, 9, 1, 2, -1, -1, -1, -1}, + {3, 1, 11, 3, 11, 10, 7, 4, 8, -1, -1, -1, -1, -1, -1, -1}, + {1, 11, 10, 1, 10, 4, 1, 4, 0, 7, 4, 10, -1, -1, -1, -1}, + {4, 8, 7, 9, 10, 0, 9, 11, 10, 10, 3, 0, -1, -1, -1, -1}, + {4, 10, 7, 4, 9, 10, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}, + {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {9, 4, 5, 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, + {1, 11, 2, 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {3, 8, 0, 1, 11, 2, 4, 5, 9, -1, -1, -1, -1, -1, -1, -1}, + {5, 11, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, + {2, 5, 11, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, + {9, 4, 5, 2, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 2, 10, 0, 10, 8, 4, 5, 9, -1, -1, -1, -1, -1, -1, -1}, + {0, 4, 5, 0, 5, 1, 2, 10, 3, -1, -1, -1, -1, -1, -1, -1}, + {2, 5, 1, 2, 8, 5, 2, 10, 8, 4, 5, 8, -1, -1, -1, -1}, + {11, 10, 3, 11, 3, 1, 9, 4, 5, -1, -1, -1, -1, -1, -1, -1}, + {4, 5, 9, 0, 1, 8, 8, 1, 11, 8, 11, 10, -1, -1, -1, -1}, + {5, 0, 4, 5, 10, 0, 5, 11, 10, 10, 3, 0, -1, -1, -1, -1}, + {5, 8, 4, 5, 11, 8, 11, 10, 8, -1, -1, -1, -1, -1, -1, -1}, + {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, + {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, + {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {9, 8, 7, 9, 7, 5, 11, 2, 1, -1, -1, -1, -1, -1, -1, -1}, + {11, 2, 1, 9, 0, 5, 5, 0, 3, 5, 3, 7, -1, -1, -1, -1}, + {8, 2, 0, 8, 5, 2, 8, 7, 5, 11, 2, 5, -1, -1, -1, -1}, + {2, 5, 11, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, + {7, 5, 9, 7, 9, 8, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1}, + {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 10, 7, -1, -1, -1, -1}, + {2, 10, 3, 0, 8, 1, 1, 8, 7, 1, 7, 5, -1, -1, -1, -1}, + {10, 1, 2, 10, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, + {9, 8, 5, 8, 7, 5, 11, 3, 1, 11, 10, 3, -1, -1, -1, -1}, + {5, 0, 7, 5, 9, 0, 7, 0, 10, 1, 11, 0, 10, 0, 11, -1}, + {10, 0, 11, 10, 3, 0, 11, 0, 5, 8, 7, 0, 5, 0, 7, -1}, + {10, 5, 11, 7, 5, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {11, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 3, 8, 5, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {9, 1, 0, 5, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 3, 8, 1, 8, 9, 5, 6, 11, -1, -1, -1, -1, -1, -1, -1}, + {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 5, 6, 1, 6, 2, 3, 8, 0, -1, -1, -1, -1, -1, -1, -1}, + {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, + {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, + {2, 10, 3, 11, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {10, 8, 0, 10, 0, 2, 11, 5, 6, -1, -1, -1, -1, -1, -1, -1}, + {0, 9, 1, 2, 10, 3, 5, 6, 11, -1, -1, -1, -1, -1, -1, -1}, + {5, 6, 11, 1, 2, 9, 9, 2, 10, 9, 10, 8, -1, -1, -1, -1}, + {6, 10, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, + {0, 10, 8, 0, 5, 10, 0, 1, 5, 5, 6, 10, -1, -1, -1, -1}, + {3, 6, 10, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}, + {6, 9, 5, 6, 10, 9, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, + {5, 6, 11, 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 0, 3, 4, 3, 7, 6, 11, 5, -1, -1, -1, -1, -1, -1, -1}, + {1, 0, 9, 5, 6, 11, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1}, + {11, 5, 6, 1, 7, 9, 1, 3, 7, 7, 4, 9, -1, -1, -1, -1}, + {6, 2, 1, 6, 1, 5, 4, 8, 7, -1, -1, -1, -1, -1, -1, -1}, + {1, 5, 2, 5, 6, 2, 3, 4, 0, 3, 7, 4, -1, -1, -1, -1}, + {8, 7, 4, 9, 5, 0, 0, 5, 6, 0, 6, 2, -1, -1, -1, -1}, + {7, 9, 3, 7, 4, 9, 3, 9, 2, 5, 6, 9, 2, 9, 6, -1}, + {3, 2, 10, 7, 4, 8, 11, 5, 6, -1, -1, -1, -1, -1, -1, -1}, + {5, 6, 11, 4, 2, 7, 4, 0, 2, 2, 10, 7, -1, -1, -1, -1}, + {0, 9, 1, 4, 8, 7, 2, 10, 3, 5, 6, 11, -1, -1, -1, -1}, + {9, 1, 2, 9, 2, 10, 9, 10, 4, 7, 4, 10, 5, 6, 11, -1}, + {8, 7, 4, 3, 5, 10, 3, 1, 5, 5, 6, 10, -1, -1, -1, -1}, + {5, 10, 1, 5, 6, 10, 1, 10, 0, 7, 4, 10, 0, 10, 4, -1}, + {0, 9, 5, 0, 5, 6, 0, 6, 3, 10, 3, 6, 8, 7, 4, -1}, + {6, 9, 5, 6, 10, 9, 4, 9, 7, 7, 9, 10, -1, -1, -1, -1}, + {11, 9, 4, 6, 11, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 6, 11, 4, 11, 9, 0, 3, 8, -1, -1, -1, -1, -1, -1, -1}, + {11, 1, 0, 11, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, + {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 11, 1, -1, -1, -1, -1}, + {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, + {3, 8, 0, 1, 9, 2, 2, 9, 4, 2, 4, 6, -1, -1, -1, -1}, + {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, + {11, 9, 4, 11, 4, 6, 10, 3, 2, -1, -1, -1, -1, -1, -1, -1}, + {0, 2, 8, 2, 10, 8, 4, 11, 9, 4, 6, 11, -1, -1, -1, -1}, + {3, 2, 10, 0, 6, 1, 0, 4, 6, 6, 11, 1, -1, -1, -1, -1}, + {6, 1, 4, 6, 11, 1, 4, 1, 8, 2, 10, 1, 8, 1, 10, -1}, + {9, 4, 6, 9, 6, 3, 9, 3, 1, 10, 3, 6, -1, -1, -1, -1}, + {8, 1, 10, 8, 0, 1, 10, 1, 6, 9, 4, 1, 6, 1, 4, -1}, + {3, 6, 10, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}, + {6, 8, 4, 10, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {7, 6, 11, 7, 11, 8, 8, 11, 9, -1, -1, -1, -1, -1, -1, -1}, + {0, 3, 7, 0, 7, 11, 0, 11, 9, 6, 11, 7, -1, -1, -1, -1}, + {11, 7, 6, 1, 7, 11, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}, + {11, 7, 6, 11, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, + {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}, + {2, 9, 6, 2, 1, 9, 6, 9, 7, 0, 3, 9, 7, 9, 3, -1}, + {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}, + {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {2, 10, 3, 11, 8, 6, 11, 9, 8, 8, 7, 6, -1, -1, -1, -1}, + {2, 7, 0, 2, 10, 7, 0, 7, 9, 6, 11, 7, 9, 7, 11, -1}, + {1, 0, 8, 1, 8, 7, 1, 7, 11, 6, 11, 7, 2, 10, 3, -1}, + {10, 1, 2, 10, 7, 1, 11, 1, 6, 6, 1, 7, -1, -1, -1, -1}, + {8, 6, 9, 8, 7, 6, 9, 6, 1, 10, 3, 6, 1, 6, 3, -1}, + {0, 1, 9, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {7, 0, 8, 7, 6, 0, 3, 0, 10, 10, 0, 6, -1, -1, -1, -1}, + {7, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {7, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {3, 8, 0, 10, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 9, 1, 10, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {8, 9, 1, 8, 1, 3, 10, 6, 7, -1, -1, -1, -1, -1, -1, -1}, + {11, 2, 1, 6, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 11, 2, 3, 8, 0, 6, 7, 10, -1, -1, -1, -1, -1, -1, -1}, + {2, 0, 9, 2, 9, 11, 6, 7, 10, -1, -1, -1, -1, -1, -1, -1}, + {6, 7, 10, 2, 3, 11, 11, 3, 8, 11, 8, 9, -1, -1, -1, -1}, + {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, + {2, 6, 7, 2, 7, 3, 0, 9, 1, -1, -1, -1, -1, -1, -1, -1}, + {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, + {11, 6, 7, 11, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, + {11, 6, 7, 1, 11, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, + {0, 7, 3, 0, 11, 7, 0, 9, 11, 6, 7, 11, -1, -1, -1, -1}, + {7, 11, 6, 7, 8, 11, 8, 9, 11, -1, -1, -1, -1, -1, -1, -1}, + {6, 4, 8, 10, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {3, 10, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, + {8, 10, 6, 8, 6, 4, 9, 1, 0, -1, -1, -1, -1, -1, -1, -1}, + {9, 6, 4, 9, 3, 6, 9, 1, 3, 10, 6, 3, -1, -1, -1, -1}, + {6, 4, 8, 6, 8, 10, 2, 1, 11, -1, -1, -1, -1, -1, -1, -1}, + {1, 11, 2, 3, 10, 0, 0, 10, 6, 0, 6, 4, -1, -1, -1, -1}, + {4, 8, 10, 4, 10, 6, 0, 9, 2, 2, 9, 11, -1, -1, -1, -1}, + {11, 3, 9, 11, 2, 3, 9, 3, 4, 10, 6, 3, 4, 3, 6, -1}, + {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, + {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 0, 9, 2, 4, 3, 2, 6, 4, 4, 8, 3, -1, -1, -1, -1}, + {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, + {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 11, -1, -1, -1, -1}, + {11, 0, 1, 11, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, + {4, 3, 6, 4, 8, 3, 6, 3, 11, 0, 9, 3, 11, 3, 9, -1}, + {11, 4, 9, 6, 4, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 5, 9, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 3, 8, 4, 5, 9, 10, 6, 7, -1, -1, -1, -1, -1, -1, -1}, + {5, 1, 0, 5, 0, 4, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1}, + {10, 6, 7, 8, 4, 3, 3, 4, 5, 3, 5, 1, -1, -1, -1, -1}, + {9, 4, 5, 11, 2, 1, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1}, + {6, 7, 10, 1, 11, 2, 0, 3, 8, 4, 5, 9, -1, -1, -1, -1}, + {7, 10, 6, 5, 11, 4, 4, 11, 2, 4, 2, 0, -1, -1, -1, -1}, + {3, 8, 4, 3, 4, 5, 3, 5, 2, 11, 2, 5, 10, 6, 7, -1}, + {7, 3, 2, 7, 2, 6, 5, 9, 4, -1, -1, -1, -1, -1, -1, -1}, + {9, 4, 5, 0, 6, 8, 0, 2, 6, 6, 7, 8, -1, -1, -1, -1}, + {3, 2, 6, 3, 6, 7, 1, 0, 5, 5, 0, 4, -1, -1, -1, -1}, + {6, 8, 2, 6, 7, 8, 2, 8, 1, 4, 5, 8, 1, 8, 5, -1}, + {9, 4, 5, 11, 6, 1, 1, 6, 7, 1, 7, 3, -1, -1, -1, -1}, + {1, 11, 6, 1, 6, 7, 1, 7, 0, 8, 0, 7, 9, 4, 5, -1}, + {4, 11, 0, 4, 5, 11, 0, 11, 3, 6, 7, 11, 3, 11, 7, -1}, + {7, 11, 6, 7, 8, 11, 5, 11, 4, 4, 11, 8, -1, -1, -1, -1}, + {6, 5, 9, 6, 9, 10, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, + {3, 10, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, + {0, 8, 10, 0, 10, 5, 0, 5, 1, 5, 10, 6, -1, -1, -1, -1}, + {6, 3, 10, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, + {1, 11, 2, 9, 10, 5, 9, 8, 10, 10, 6, 5, -1, -1, -1, -1}, + {0, 3, 10, 0, 10, 6, 0, 6, 9, 5, 9, 6, 1, 11, 2, -1}, + {10, 5, 8, 10, 6, 5, 8, 5, 0, 11, 2, 5, 0, 5, 2, -1}, + {6, 3, 10, 6, 5, 3, 2, 3, 11, 11, 3, 5, -1, -1, -1, -1}, + {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}, + {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, + {1, 8, 5, 1, 0, 8, 5, 8, 6, 3, 2, 8, 6, 8, 2, -1}, + {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 6, 3, 1, 11, 6, 3, 6, 8, 5, 9, 6, 8, 6, 9, -1}, + {11, 0, 1, 11, 6, 0, 9, 0, 5, 5, 0, 6, -1, -1, -1, -1}, + {0, 8, 3, 5, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {11, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {10, 11, 5, 7, 10, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {10, 11, 5, 10, 5, 7, 8, 0, 3, -1, -1, -1, -1, -1, -1, -1}, + {5, 7, 10, 5, 10, 11, 1, 0, 9, -1, -1, -1, -1, -1, -1, -1}, + {11, 5, 7, 11, 7, 10, 9, 1, 8, 8, 1, 3, -1, -1, -1, -1}, + {10, 2, 1, 10, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, + {0, 3, 8, 1, 7, 2, 1, 5, 7, 7, 10, 2, -1, -1, -1, -1}, + {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 10, -1, -1, -1, -1}, + {7, 2, 5, 7, 10, 2, 5, 2, 9, 3, 8, 2, 9, 2, 8, -1}, + {2, 11, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, + {8, 0, 2, 8, 2, 5, 8, 5, 7, 11, 5, 2, -1, -1, -1, -1}, + {9, 1, 0, 5, 3, 11, 5, 7, 3, 3, 2, 11, -1, -1, -1, -1}, + {9, 2, 8, 9, 1, 2, 8, 2, 7, 11, 5, 2, 7, 2, 5, -1}, + {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, + {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}, + {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {5, 4, 8, 5, 8, 11, 11, 8, 10, -1, -1, -1, -1, -1, -1, -1}, + {5, 4, 0, 5, 0, 10, 5, 10, 11, 10, 0, 3, -1, -1, -1, -1}, + {0, 9, 1, 8, 11, 4, 8, 10, 11, 11, 5, 4, -1, -1, -1, -1}, + {11, 4, 10, 11, 5, 4, 10, 4, 3, 9, 1, 4, 3, 4, 1, -1}, + {2, 1, 5, 2, 5, 8, 2, 8, 10, 4, 8, 5, -1, -1, -1, -1}, + {0, 10, 4, 0, 3, 10, 4, 10, 5, 2, 1, 10, 5, 10, 1, -1}, + {0, 5, 2, 0, 9, 5, 2, 5, 10, 4, 8, 5, 10, 5, 8, -1}, + {9, 5, 4, 2, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {2, 11, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}, + {5, 2, 11, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, + {3, 2, 11, 3, 11, 5, 3, 5, 8, 4, 8, 5, 0, 9, 1, -1}, + {5, 2, 11, 5, 4, 2, 1, 2, 9, 9, 2, 4, -1, -1, -1, -1}, + {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}, + {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {8, 5, 4, 8, 3, 5, 9, 5, 0, 0, 5, 3, -1, -1, -1, -1}, + {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 7, 10, 4, 10, 9, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, + {0, 3, 8, 4, 7, 9, 9, 7, 10, 9, 10, 11, -1, -1, -1, -1}, + {1, 10, 11, 1, 4, 10, 1, 0, 4, 7, 10, 4, -1, -1, -1, -1}, + {3, 4, 1, 3, 8, 4, 1, 4, 11, 7, 10, 4, 11, 4, 10, -1}, + {4, 7, 10, 9, 4, 10, 9, 10, 2, 9, 2, 1, -1, -1, -1, -1}, + {9, 4, 7, 9, 7, 10, 9, 10, 1, 2, 1, 10, 0, 3, 8, -1}, + {10, 4, 7, 10, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}, + {10, 4, 7, 10, 2, 4, 8, 4, 3, 3, 4, 2, -1, -1, -1, -1}, + {2, 11, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}, + {9, 7, 11, 9, 4, 7, 11, 7, 2, 8, 0, 7, 2, 7, 0, -1}, + {3, 11, 7, 3, 2, 11, 7, 11, 4, 1, 0, 11, 4, 11, 0, -1}, + {1, 2, 11, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}, + {4, 1, 9, 4, 7, 1, 0, 1, 8, 8, 1, 7, -1, -1, -1, -1}, + {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {9, 8, 11, 11, 8, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {3, 9, 0, 3, 10, 9, 10, 11, 9, -1, -1, -1, -1, -1, -1, -1}, + {0, 11, 1, 0, 8, 11, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, + {3, 11, 1, 10, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 10, 2, 1, 9, 10, 9, 8, 10, -1, -1, -1, -1, -1, -1, -1}, + {3, 9, 0, 3, 10, 9, 1, 9, 2, 2, 9, 10, -1, -1, -1, -1}, + {0, 10, 2, 8, 10, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {3, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {2, 8, 3, 2, 11, 8, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}, + {9, 2, 11, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {2, 8, 3, 2, 11, 8, 0, 8, 1, 1, 8, 11, -1, -1, -1, -1}, + {1, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} + }; -// For each of the possible vertex states listed in aiCubeEdgeFlags there is a -// specific triangulation -// of the edge intersection points. a2iTriangleConnectionTable lists all of -// them in the form of -// 0-5 edge triples with the list terminated by the invalid value -1. -// For example: a2iTriangleConnectionTable[3] list the 2 triangles formed when -// corner[0] -// and corner[1] are inside of the surface, but the rest of the cube is not. -// -// I found this table in an example program someone wrote long ago. It was -// probably generated by hand -const int MeshGenerator::a2iTriangleConnectionTable[256][16] = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, - { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, - { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, - { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, - { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, - { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, - { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, - { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, - { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, - { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, - { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, - { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, - { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, - { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, - { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, - { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, - { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, - { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, - { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, - { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, - { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, - { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, - { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, - { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, - { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, - { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, - { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, - { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, - { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, - { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, - { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, - { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, - { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, - { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, - { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, - { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, - { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, - { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, - { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, - { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, - { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, - { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, - { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, - { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, - { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, - { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, - { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, - { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, - { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, - { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, - { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, - { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, - { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, - { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, - { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, - { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, - { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, - { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, - { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, - { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, - { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, - { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, - { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, - { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, - { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, - { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, - { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, - { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, - { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, - { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, - { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, - { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, - { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, - { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, - { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, - { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, - { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, - { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, - { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, - { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, - { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, - { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, - { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, - { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, - { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, - { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, - { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, - { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, - { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, - { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, - { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, - { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, - { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, - { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, - { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, - { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, - { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, - { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, - { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, - { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, - { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, - { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, - { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, - { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, - { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, - { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, - { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, - { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, - { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, - { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, - { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, - { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, - { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, - { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, - { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, - { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, - { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, - { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, - { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, - { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } -}; +const unsigned char MeshGenerator::m_edgeVertices[12][2] = + { + {0,1}, {1,2}, {3,2}, + {0,3}, {4,5}, {5,6}, + {7,6}, {4,7}, {0,4}, + {1,5}, {3,7}, {2,6} + }; } // End namespace Avogadro diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index b5bda13e67..95a9a70a3a 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -26,6 +26,7 @@ namespace QtGui { * @class MeshGenerator meshgenerator.h * @brief Class that can generate Mesh objects from Cube objects. * @author Marcus D. Hanwell + * @author Perminder Singh * * This class implements a method of generating an isosurface Mesh from * volumetric data using the marching cubes algorithm. In the case of the @@ -81,11 +82,95 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread */ void run() override; + /** + * It holds the range and starting offsets of isosurface-intersected + * edges along the x, y, and z axes for each grid cell. + */ + struct gridEdge + { + gridEdge() + : xl(0), + xr(0), + xstart(0), + ystart(0), + zstart(0) + {} + + // trim values + // set on pass 1 + int xl; + int xr; + + // modified on pass 2 + // set on pass 3 + int xstart; + int ystart; + int zstart; + }; + + /** + * Handles duplicate vertices (Not implemented). Placeholder for future functionality. + */ + unsigned long duplicate(const Vector3i& c, const Vector3f& pos); + + + /** + * @name Flying Edges + * Methods to implement the "flying edges" method for isosurface mesh generation. + * Flying edges: A high-performance scalable isocontouring algorithm + * Schroeder; Maynard; Geveci; + * 2015 IEEE 5th Symposium on Large Data Analysis and Visualization (LDAV) + * [10.1109/LDAV.2015.7348069](https://doi.org/10.1109/LDAV.2015.7348069) + * Alternate (non-VTK) implementation at + * https://github.com/sandialabs/miniIsosurface/blob/master/flyingEdges/ + * @{ + + /** + * Pass 1 for flying edges. Pass1 detects and records + * where the isosurface intersects each row of grid edges + * along the x-axis. + */ + void FlyingEdgesAlgorithmPass1(); + + /** + * Pass2 assigns case identifiers to each grid cell based on + * intersected edges and tallies the number of triangles needed + * for mesh construction. + */ + void FlyingEdgesAlgorithmPass2(); + + /** + * Pass3 computes cumulative offsets for triangles + * and vertices and allocates memory for the mesh structures. + */ + void FlyingEdgesAlgorithmPass3(); + + /** + * Calculates normals, triangles and vertices. + */ + void FlyingEdgesAlgorithmPass4(); + + /**@}*/ + /** * @return The Cube being used by the class. */ const Core::Cube* cube() const { return m_cube; } + /** + * Determines the x-range (xl to xr) where isosurface intersections + * occur, optimizing calculations within this range. + */ + inline void calcTrimValues( + int& xl, int& xr, int const& j, int const& k) const; + + /** + * Indicates which edges intersects the isosurface. + */ + inline unsigned char + calcCubeCase(unsigned char const& ec0, unsigned char const& ec1, + unsigned char const& ec2, unsigned char const& ec3) const; + /** * @return The Mesh being generated by the class. */ @@ -107,34 +192,42 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread int progressMaximum() { return m_progmax; } signals: + /** * The current value of the calculation's progress. */ void progressValueChanged(int); protected: - /** - * Get the normal to the supplied point. This operation is quite expensive - * and so should be avoided wherever possible. - * @param pos The position of the vertex whose normal is needed. - * @return The normal vector for the supplied point. - */ - Vector3f normal(const Vector3f& pos); /** - * Get the offset, i.e. the approximate point of intersection of the surface - * between two points. - * @param val1 The position of the vertex whose normal is needed. - * @return The normal vector for the supplied point. - */ - float offset(float val1, float val2); + * isCutEdge checks whether the grid edge at position (i, j, k) is + * intersected by the isosurface based on edge case conditions. + * @return Boolean if it's intersected or not. + */ + bool isCutEdge(int const& i, int const& j, int const& k) const; - unsigned long duplicate(const Vector3i& c, const Vector3f& pos); + /** + * It computes the 3D intersection point on a cube edge via interpolation. + */ + inline std::array interpolateOnCube( + std::array, 8> const& pts, + std::array const& isovals, + unsigned char const& edge) const; + + /** + * It linearly interpolates between two 3D points, a and b, using + * the given weight to determine the intermediate position. + */ + inline std::array interpolate( + std::array const& a, + std::array const& b, + float const& weight) const; /** - * Perform a marching cubes step on a single cube. - */ - bool marchingCube(const Vector3i& pos); + * calcCaseEdge determines an edge case code (0–3) based on two boolean edge comparisons. + */ + inline unsigned char calcCaseEdge(bool const& prevEdge, bool const& currEdge) const; float m_iso; /** The value of the isosurface. */ int m_passes; /** Number of smoothing passes to perform. */ @@ -144,26 +237,24 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread Vector3f m_stepSize; /** The step size vector for cube. */ Vector3f m_min; /** The minimum point in the cube. */ Vector3i m_dim; /** The dimensions of the cube. */ - Core::Array m_vertices, m_normals; - Core::Array m_indices; + + Core::Array m_normals, m_vertices; + std::vector gridEdges; // size (m_dim.y() * m_dim.z()) + std::vector cubeCases; //size ((m_dim.x() - 1) * (m_dim.y() - 1) * (m_dim.z() - 1)) + std::vector triCounter; // size ((m_dim.y() - 1) * (m_dim.z() - 1)) + std::vector edgeCases; // size ((m_dim.x() - 1) * (m_dim.y()) * (m_dim.z())) + Core::Array m_triangles; // triangles of a mesh int m_progmin; int m_progmax; /** - * These are the tables of constants for the marching cubes and tetrahedra - * algorithms. They are taken from the public domain source at - * http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/ + * These are the lookup tables for flying edges. + * Reference : https://github.com/sandialabs/miniIsosurface/blob/master/flyingEdges/util/MarchingCubesTables.h */ - static const float a2fVertexOffset[8][3]; - static const int a2iVertexOffset[8][3]; - static const int a2iEdgeConnection[12][2]; - static const float a2fEdgeDirection[12][3]; - static const int a2iTetrahedronEdgeConnection[6][2]; - static const int a2iTetrahedronsInACube[6][4]; - static const long aiTetrahedronEdgeFlags[16]; - static const int a2iTetrahedronTriangles[16][7]; - static const long aiCubeEdgeFlags[256]; - static const int a2iTriangleConnectionTable[256][16]; + static const unsigned char m_numTris[256]; + static const bool m_isCut[256][12]; + static const char m_caseTriangles[256][16]; + static const unsigned char m_edgeVertices[12][2]; }; } // End namespace QtGui diff --git a/avogadro/qtplugins/meshes/meshes.cpp b/avogadro/qtplugins/meshes/meshes.cpp index 5353a34ff9..be15055060 100644 --- a/avogadro/qtplugins/meshes/meshes.cpp +++ b/avogadro/qtplugins/meshes/meshes.cpp @@ -68,19 +68,16 @@ void Meshes::process(const QtGui::Molecule& mol, GroupNode& node) const Mesh* mesh = mol.mesh(0); - /// @todo Allow use of MeshGeometry without an index array when all vertices - /// form explicit triangles. - // Create index array: - Sequence indexGenerator; - Core::Array indices(mesh->numVertices()); - std::generate(indices.begin(), indices.end(), indexGenerator); + Core::Array triangles; + + triangles = mesh->triangles(); + bool hasColors = (mesh->colors().size() != 0); auto* mesh1 = new MeshGeometry; geometry->addDrawable(mesh1); mesh1->setOpacity(m_opacity); - if (hasColors) { auto colors = mesh->colors(); Core::Array colorsRGB(colors.size()); @@ -88,34 +85,33 @@ void Meshes::process(const QtGui::Molecule& mol, GroupNode& node) colorsRGB[i] = Vector3ub(colors[i].red() * 255, colors[i].green() * 255, colors[i].blue() * 255); mesh1->addVertices(mesh->vertices(), mesh->normals(), colorsRGB); - } else { // probably a molecular orbital - mesh1->setColor(m_color1); - mesh1->addVertices(mesh->vertices(), mesh->normals()); + } else { + mesh1->setColor(m_color1); + mesh1->addVertices(mesh->vertices(), mesh->normals()); + } + for (size_t i = 0; i < triangles.size(); ++i) { + mesh1->addTriangle(triangles[i][0], triangles[i][1], triangles[i][2]); } - mesh1->addTriangles(indices); - mesh1->setRenderPass(m_opacity == 255 ? Rendering::SolidPass + mesh1->setRenderPass(m_opacity == 255 ? Rendering::SolidPass : Rendering::TranslucentPass); - if (mol.meshCount() >= 2) { // it's a molecular orbital, two parts + if (mol.meshCount() >= 2) { // it's a molecular orbital, two parts + auto* mesh2 = new MeshGeometry; geometry->addDrawable(mesh2); mesh = mol.mesh(1); - if (mesh->numVertices() < indices.size()) { - indices.resize(mesh->numVertices()); - } else if (mesh->numVertices() > indices.size()) { - indexGenerator.reset(); - indices.resize(mesh->numVertices()); - std::generate(indices.begin(), indices.end(), indexGenerator); - } mesh2->setColor(m_color2); mesh2->setOpacity(m_opacity); mesh2->addVertices(mesh->vertices(), mesh->normals()); - mesh2->addTriangles(indices); + for (size_t i = 0; i < triangles.size(); ++i) { + mesh2->addTriangle(triangles[i][0], triangles[i][1], triangles[i][2]); + } mesh2->setRenderPass(m_opacity == 255 ? Rendering::SolidPass : Rendering::TranslucentPass); } } -} + } + void Meshes::setOpacity(int opacity) { diff --git a/avogadro/rendering/meshgeometry.cpp b/avogadro/rendering/meshgeometry.cpp index d3736838cc..8d35724d90 100644 --- a/avogadro/rendering/meshgeometry.cpp +++ b/avogadro/rendering/meshgeometry.cpp @@ -267,8 +267,8 @@ unsigned int MeshGeometry::addVertices(const Core::Array& v, return static_cast(result); } -void MeshGeometry::addTriangle(unsigned int index1, unsigned int index2, - unsigned int index3) +void MeshGeometry::addTriangle( size_t index1, size_t index2, + size_t index3) { m_indices.push_back(index1); m_indices.push_back(index2); @@ -276,6 +276,7 @@ void MeshGeometry::addTriangle(unsigned int index1, unsigned int index2, m_dirty = true; } + void MeshGeometry::addTriangles(const Core::Array& indiceArray) { m_indices.reserve(m_indices.size() + indiceArray.size()); diff --git a/avogadro/rendering/meshgeometry.h b/avogadro/rendering/meshgeometry.h index 42f458a688..ce33e1fc4d 100644 --- a/avogadro/rendering/meshgeometry.h +++ b/avogadro/rendering/meshgeometry.h @@ -92,8 +92,8 @@ class AVOGADRORENDERING_EXPORT MeshGeometry : public Drawable * the valid index range. * @{ */ - void addTriangle(unsigned int index1, unsigned int index2, - unsigned int index3); + void addTriangle( size_t index1, size_t index2, + size_t index3); void addTriangles(const Core::Array& indices); /** @} */