From 69f9bee913d3999222156e63344f3ecd2cb5a062 Mon Sep 17 00:00:00 2001 From: Perminder Date: Fri, 18 Oct 2024 02:17:48 +0530 Subject: [PATCH 01/19] adding-new-tables-for-flying-edges Signed-off-by: Perminder --- avogadro/qtgui/meshgenerator.cpp | 953 ++++++++++++++++++------------- avogadro/qtgui/meshgenerator.h | 14 +- 2 files changed, 575 insertions(+), 392 deletions(-) diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 45219537cf..708a4680e5 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -47,15 +47,27 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, m_iso = iso; m_passes = passes; m_reverseWinding = reverse; + + // In BlockMarchFunctor.cpp: + // The volume reader setup happens here with dimensions, origin, and spacing. + // dims = volReader.imageData->getDimension(); + // origin = volReader.imageData->getOrigin(); + // spacing = volReader.imageData->getSpacing(); + 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(); m_progmax = m_dim.x(); + + // Similar to setting up sliceSize and grid traversal boundaries in BlockMarchFunctor.cpp: + // sliceSize = dims[0] * dims[1]; + m_cube->lock()->unlock(); return true; } @@ -78,11 +90,11 @@ void MeshGenerator::run() 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 + // Now to march the cube (Similar to marching loop in BlockMarchFunctor.cpp) 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)); + marchingCube(Vector3i(i, j, k)); // Same logic as marching each cell in BlockMarchFunctor.cpp } } if (m_vertices.capacity() < m_vertices.size() + m_dim.y() * m_dim.x() * 3) { @@ -103,7 +115,7 @@ void MeshGenerator::run() m_vertices.resize(0); m_normals.resize(0); - // Smooth out the mesh + // Smooth out the mesh (Similar smoothing is performed at the end of BlockMarchFunctor.cpp) m_mesh->smooth(m_passes); } @@ -139,6 +151,11 @@ inline float MeshGenerator::offset(float val1, float val2) return (m_iso - val1) / (val2 - val1); } +// This function is similar to interpolating positions in BlockMarchFunctor.cpp: +// In BlockMarchFunctor.cpp: +// T w = (isoval - val[v1]) / (val[v2] - val[v1]); +// Interpolation using lerp() function + unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) { // FIXME Not implemented yet. @@ -156,13 +173,13 @@ bool MeshGenerator::marchingCube(const Vector3i& pos) for (unsigned int i = 0; i < 3; ++i) fPos[i] = static_cast(pos[i]) * m_stepSize[i] + m_min[i]; - // Make a local copy of the values at the cube's corners + // Fetch the cube's corner values (Similar to volReader.getVertexValues in BlockMarchFunctor.cpp) for (int i = 0; i < 8; ++i) { afCubeValue[i] = static_cast( m_cube->value(Vector3i(pos + Vector3i(a2iVertexOffset[i])))); } - // Find which vertices are inside of the surface and which are outside + // Determine which edges are intersected by the isosurface long iFlagIndex = 0; for (int i = 0; i < 8; ++i) { if (afCubeValue[i] <= m_iso) { @@ -173,15 +190,13 @@ bool MeshGenerator::marchingCube(const Vector3i& pos) // 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 there are no intersections, skip the cube (Same as case 0 or 255 in BlockMarchFunctor.cpp) 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 + // Interpolate edge vertices (Similar to interpolation in BlockMarchFunctor.cpp with lerp) 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]]); @@ -200,18 +215,17 @@ bool MeshGenerator::marchingCube(const Vector3i& pos) fOffset * a2fEdgeDirection[i][2]) * m_stepSize[2]); - /// FIXME Optimize this to only calculate normals when required + // Normals are computed similarly in BlockMarchFunctor.cpp with `computeAllGradients` asEdgeNorm[i] = normal(asEdgeVertex[i]); } } - // Store the triangles that were found, there can be up to five per cube + // Store the triangles based on the edges intersected (Same logic as adding triangles in BlockMarchFunctor.cpp) 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]; @@ -231,383 +245,558 @@ bool MeshGenerator::marchingCube(const Vector3i& pos) return true; } -// 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 } -}; -// 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 } }; -// 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 } -}; +// flying edges tables using: -// 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 } -}; -// 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::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 }, -}; - -// 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 bool MeshGenerator::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 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 char MeshGenerator::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} + }; + +const unsigned char 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..041eecd417 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -154,16 +154,10 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread * algorithms. They are taken from the public domain source at * http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/ */ - 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 numTris[256]; + static const bool isCut[256][12]; + static const char caseTriangles[256][16]; + static const unsigned char edgeVertices[12][2]; }; } // End namespace QtGui From 4b9474b950b5046cc6d71748422b5803bfc55fd9 Mon Sep 17 00:00:00 2001 From: Perminder Date: Sun, 27 Oct 2024 15:28:53 +0530 Subject: [PATCH 02/19] adding codes for flying-edges algo, still fixing left Signed-off-by: Perminder --- avogadro/core/cube.cpp | 149 +++++++++ avogadro/core/cube.h | 4 + avogadro/qtgui/meshgenerator.cpp | 499 +++++++++++++++++++++++++++++++ avogadro/qtgui/meshgenerator.h | 21 ++ 4 files changed, 673 insertions(+) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index e05ab01eb5..791a93aefd 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -23,6 +23,13 @@ Cube::~Cube() m_lock = nullptr; } +std::vector::const_iterator +Cube::getRowIter(size_t j, size_t k) const +{ + return m_data.cbegin() + m_points.x() * (k * m_points.y() + j); +} + + bool Cube::setLimits(const Vector3& min_, const Vector3& max_, const Vector3i& points) { @@ -194,6 +201,148 @@ float Cube::value(int i, int j, int k) const return 0.0; } +std::array Cube::computeGradient(size_t i, size_t j, size_t k) const +{ + std::array, 3> x; + std::array run; + + size_t dataIdx = i + j * m_points.x() + k * m_points.x() * m_points.y(); + + if (i == 0) + { + x[0][0] = m_data[dataIdx + 1]; + x[0][1] = m_data[dataIdx]; + run[0] = m_spacing[0]; + } + else if (i == (m_points.x() - 1)) + { + x[0][0] = m_data[dataIdx]; + x[0][1] = m_data[dataIdx - 1]; + run[0] = m_spacing[0]; + } + else + { + x[0][0] = m_data[dataIdx + 1]; + x[0][1] = m_data[dataIdx - 1]; + run[0] = 2 * m_spacing[0]; + } + + if (j == 0) + { + x[1][0] = m_data[dataIdx + nx]; + x[1][1] = m_data[dataIdx]; + run[1] = m_spacing[1]; + } + else if (j == (m_points.y() - 1)) + { + x[1][0] = m_data[dataIdx]; + x[1][1] = m_data[dataIdx - m_points.x()]; + run[1] = m_spacing[1]; + } + else + { + x[1][0] = m_data[dataIdx + m_points.x()]; + x[1][1] = m_data[dataIdx - m_points.x()]; + run[1] = 2 * m_spacing[1]; + } + + if (k == 0) + { + x[2][0] = m_data[dataIdx + m_points.x() * m_points.y()]; + x[2][1] = m_data[dataIdx]; + run[2] = m_spacing[2]; + } + else if (k == (m_points.z() - 1)) + { + x[2][0] = m_data[dataIdx]; + x[2][1] = m_data[dataIdx - m_points.x() * m_points.y()]; + run[2] = m_spacing[2]; + } + else + { + x[2][0] = m_data[dataIdx + m_points.x() * m_points.y()]; + x[2][1] = m_data[dataIdx - m_points.x() * m_points.y()]; + run[2] = 2 * m_spacing[2]; + } + + 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 Cube::getValsCube(size_t i, size_t j, size_t k) const +{ + std::array vals; + + size_t idx = i + j * m_points.x() + k * m_points.x() * m_points.y(); + + 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; +} + + +inline scalar_t +Cube::getData(size_t i, size_t j, size_t k) const +{ + return m_data[k * m_points.x() * m_points.y() + j * m_points.x() + i]; +} + + +std::array Cube::getPosCube(size_t i, size_t j, size_t 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 = diff --git a/avogadro/core/cube.h b/avogadro/core/cube.h index b62709fe9c..a058178dc3 100644 --- a/avogadro/core/cube.h +++ b/avogadro/core/cube.h @@ -133,6 +133,9 @@ class AVOGADROCORE_EXPORT Cube */ bool addData(const std::vector& values); + + std::vector::const_iterator getRowIter(size_t j, size_t k) const; + /** * @return Index of the point closest to the position supplied. * @param pos Position to get closest index for. @@ -240,6 +243,7 @@ class AVOGADROCORE_EXPORT Cube Vector3 m_min, m_max, m_spacing; Vector3i m_points; float m_minValue, m_maxValue; + std::vector data std::string m_name; Type m_cubeType; Mutex* m_lock; diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 708a4680e5..b2d06201a0 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -63,6 +63,8 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, 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() - 1) * (m_dim.z() - 1)); + gridEdges.resize(m_dim.y() * m_dim.z()); m_progmax = m_dim.x(); // Similar to setting up sliceSize and grid traversal boundaries in BlockMarchFunctor.cpp: @@ -72,6 +74,401 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, return true; } +void MeshGenerator::FlyingEdgesAlgorithmPass1() +{ + // Loop through z-dimension + for(size_t k = 0; k != m_dim.z(); ++k) { + // Loop through y-dimension + for(size_t j = 0; j != m_dim.y(); ++j) + { + + // Calculate the starting position of edgeCases for the current row + + auto curEdgeCases = edgeCases.begin() + (m_dim.x() - 1) * (k * m_dim.y() + j); + + // Get an iterator to the current row of point values + + auto curPointValues = m_cube->getRowIter(j, k); + + // Initialize the isGE array to track isosurface crossings + std::array isGE; + isGE[0] = (curPointValues[0] >= m_iso); // first element initialization + + // loop through x-dimension + for(int i = 1; i != m_dim.x(); ++i) + { + // update isGE for the current point + isGE[i % 2] = (curPointValues[i] >= m_iso); + + // calculate edge case and update curEdgeCase + curEdgeCases[i-1] = calcCaseEdge(isGE[(i+1)%2], isGE[i%2]); + } + } +} + + for(size_t k = 0; k != m_dim.z(); ++k){ + for(size_t 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(size_t k = 0; k != m_dim.z() - 1; ++k){ + for(size_t j = 0; j != m_dim.y() - 1; ++j) + { + // find adjusted trim values + size_t xl, xr; + calcTrimValues(xl, xr, j, k); // xl, xr set in this function + + gridEdge& g0 = 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 + size_t& 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(size_t i = xl; i != xr; ++i) + { + bool isXEnd = (i == m_dim.x() - 2); + + unsigned char caseId = calcCubeCase(ec0[i], ec1[i], ec2[i], ec3[i]); + + curCubeCaseIds[i] = caseId; + + if(caseId == 0 || caseId == 255) + { + continue; + } + + + curTrimCounter += numTris[caseId]; + + const bool* isCutCase = 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 and isYEnd) + { + ge1.zstart += isCutCase[11]; + } + if(isXEnd and isZEnd) + { + ge2.ystart += isCutCase[5]; + } + if(isYEnd and isZEnd) + { + ge3.xstart += isCutCase[6]; + } + + } + + } + } +} + + + +void MeshGenerator::FlyingEdgesAlgorithmPass3() +{ + + size_t tmp; + size_t triAccum = 0; + for(size_t k = 0; k != m_dim.z()-1; ++k) { + for(size_t j = 0; j != m_dim.y()-1; ++j) + { + size_t& curTriCounter = triCounter[k*(m_dim.y()-1)+j]; + + tmp = curTriCounter; + curTriCounter = triAccum; + triAccum += tmp; + }} + + size_t pointAccum = 0; + for(size_t k = 0; k != m_dim.z(); ++k) { + for(size_t 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; + }} + + points = std::vector >(pointAccum); + normals = std::vector >(pointAccum); + tris = std::vector >(triAccum); +} + +void MeshGenerator::FlyingEdgesAlgorithmPass4() +{ + for(size_t k = 0; k != m_dim.z()-1; ++k) { + for(size_t j = 0; j != m_dim.y()-1; ++j) + { + // find adjusted trim values + size_t xl, xr; + calcTrimValues(xl, xr, j, k); // xl, xr set in this function + + if(xl == xr) + continue; + + size_t 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]; + + size_t x0counter = 0; + size_t y0counter = 0; + size_t z0counter = 0; + + size_t x1counter = 0; + size_t z1counter = 0; + + size_t x2counter = 0; + size_t y2counter = 0; + + size_t x3counter = 0; + + bool isYEnd = (j == m_dim.y()-2); + bool isZEnd = (k == m_dim.z()-2); + + for(size_t i = xl; i != xr; ++i) + { + bool isXEnd = (i == nx-2); + + unsigned char caseId = curCubeCaseIds[i]; + + if(caseId == 0 || caseId == 255) + { + continue; + } + + cube_t pointCube = m_cube->getPosCube(i, j, k); + scalarCube_t isovalCube = m_cube->getValsCube(i, j, k); + cube_t gradCube = m_cube->getGradCube(i, j, k); + + // Add Points and normals. + // Calculate global indices for triangles + std::array globalIdxs; + + if(isCut[0]) + { + size_t idx = ge0.xstart + x0counter; + points[idx] = interpolateOnCube(pointCube, isovalCube, 0); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 0); + globalIdxs[0] = idx; + ++x0counter; + } + + if(isCut[3]) + { + size_t idx = ge0.ystart + y0counter; + points[idx] = interpolateOnCube(pointCube, isovalCube, 3); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 3); + globalIdxs[3] = idx; + ++y0counter; + } + + if(isCut[8]) + { + size_t idx = ge0.zstart + z0counter; + points[idx] = interpolateOnCube(pointCube, isovalCube, 8); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 8); + globalIdxs[8] = idx; + ++z0counter; + } + + // Note: + // e1, e5, e9 and e11 will be visited in the next iteration + // when they are e3, e7, e8 and 10 respectively. So don't + // increment their counters. When the cube is an edge cube, + // their counters don't need to be incremented because they + // won't be used agin. + + // Manage boundary cases if needed. Otherwise just update + // globalIdx. + if(isCut[1]) + { + size_t idx = ge0.ystart + y0counter; + if(isXEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 1); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 1); + // y0counter counter doesn't need to be incremented + // because it won't be used again. + } + globalIdxs[1] = idx; + } + + if(isCut[9]) + { + size_t idx = ge0.zstart + z0counter; + if(isXEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 9); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 9); + // z0counter doesn't need to in incremented. + } + globalIdxs[9] = idx; + } + + if(isCut[2]) + { + size_t idx = ge1.xstart + x1counter; + if(isYEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 2); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 2); + } + globalIdxs[2] = idx; + ++x1counter; + } + + if(isCut[10]) + { + size_t idx = ge1.zstart + z1counter; + + if(isYEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 10); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 10); + } + globalIdxs[10] = idx; + ++z1counter; + } + + if(isCut[4]) + { + size_t idx = ge2.xstart + x2counter; + if(isZEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 4); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 4); + } + globalIdxs[4] = idx; + ++x2counter; + } + + if(isCut[7]) + { + size_t idx = ge2.ystart + y2counter; + if(isZEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 7); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 7); + } + globalIdxs[7] = idx; + ++y2counter; + } + + if(isCut[11]) + { + size_t idx = ge1.zstart + z1counter; + if(isXEnd and isYEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 11); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 11); + // z1counter does not need to be incremented. + } + globalIdxs[11] = idx; + } + + if(isCut[5]) + { + size_t idx = ge2.ystart + y2counter; + if(isXEnd and isZEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 5); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 5); + // y2 counter does not need to be incremented. + } + globalIdxs[5] = idx; + } + + if(isCut[6]) + { + size_t idx = ge3.xstart + x3counter; + if(isYEnd and isZEnd) + { + points[idx] = interpolateOnCube(pointCube, isovalCube, 6); + normals[idx] = interpolateOnCube(gradCube, isovalCube, 6); + } + globalIdxs[6] = idx; + ++x3counter; + } + + // Add triangles + const char* caseTri = caseTriangles[caseId]; // size 16 + for(int idx = 0; caseTri[idx] != -1; idx += 3) + { + tris[triIdx][0] = globalIdxs[caseTri[idx]]; + tris[triIdx][1] = globalIdxs[caseTri[idx+1]]; + tris[triIdx][2] = globalIdxs[caseTri[idx+2]]; + ++triIdx; + } + } + }} +} + + void MeshGenerator::run() { if (!m_cube || !m_mesh) { @@ -245,8 +642,110 @@ bool MeshGenerator::marchingCube(const Vector3i& pos) return true; } +unsigned char MeshGenerator::calcCubeCase( + unsigned char const& ec0, unsigned char const& ec1, + unsigned char const& ec2, unsigned char const& ec3) const +{ + // ec0 | (i, j, k) + // ec1 | (i, j+1, k) + // ec2 | (i, j, k+1) + // ec3 | (i, j+1, k+1) + + 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(size_t i, size_t j, size_t k) const +{ + size_t nx = m_dim.x(); + size_t ny = m_dim.y(); + size_t nz = m_dim.z(); + + // Assuming edgeCases are all set + size_t edgeCaseIdx = k * (nx - 1) * ny + j * (nx - 1) + i; + unsigned char edgeCase = edgeCases[edgeCaseIdx]; + + if (edgeCase == 1 || edgeCase == 2) + { + return true; + } + + if (j != ny - 1) + { + size_t edgeCaseIdxY = k * (nx - 1) * ny + (j + 1) * (nx - 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 != nz - 1) + { + size_t edgeCaseIdxZ = (k + 1) * (nx - 1) * ny + j * (nx - 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; +} + +unsigned char MeshGenerator::calcCaseEdge(bool const& prevEdge, bool const& currEdge) const +{ + // 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; +} + +void MeshGenerator::calcTrimValues(size_t& xl, size_t& xr, size_t const& j, size_t const& k) const +{ + size_t ny = m_dim.y(); + + const gridEdge& ge0 = gridEdges[k * ny + j]; + const gridEdge& ge1 = gridEdges[k * ny + j + 1]; + const gridEdge& ge2 = gridEdges[(k + 1) * ny + j]; + const gridEdge& ge3 = gridEdges[(k + 1) * ny + j + 1]; + + xl = std::min({ge0.xl, ge1.xl, ge2.xl, ge3.xl}); + xr = std::max({ge0.xr, ge1.xr, ge2.xr, ge3.xr}); + + if (xl > xr) + xl = xr; +} // flying edges tables using: diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index 041eecd417..03400a37b4 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -81,6 +81,17 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread */ void run() override; + struct gridEdge { + int xl; // Left trim index + int xr; // Right trim index + int xstart; // X-coordinate start index + int ystart; // Y-coordinate start index + int zstart; // Z-coordinate start index + + gridEdge() : xl(-1), xr(-1), xstart(-1), ystart(-1), zstart(-1) {} + }; + + void FlyingEdgesAlgorithmPass1(); /** * @return The Cube being used by the class. */ @@ -144,8 +155,18 @@ 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. */ + + std::array, 8> cube_t; + std::array scalarCube_t; + Core::Array m_vertices, m_normals; Core::Array m_indices; + std::vector gridEdges; + std::vector triCounter; // size of (ny-1)*(nz-1) + std::vector edgeCases; + std::vector > points; // + std::vector > normals; // The output + std::vector > tris; int m_progmin; int m_progmax; From 0e9ec3bb28c627f80240db439579c56fa02b5c92 Mon Sep 17 00:00:00 2001 From: Perminder Date: Fri, 1 Nov 2024 04:56:16 +0530 Subject: [PATCH 03/19] some more fixes required Signed-off-by: Perminder --- avogadro/core/cube.cpp | 40 ++- avogadro/core/cube.h | 56 +++- avogadro/qtgui/meshgenerator.cpp | 435 ++++++++++++++++++------------- avogadro/qtgui/meshgenerator.h | 62 ++++- 4 files changed, 382 insertions(+), 211 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index 791a93aefd..86c774b985 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -7,6 +7,7 @@ #include "molecule.h" #include "mutex.h" +#include namespace Avogadro::Core { @@ -23,10 +24,14 @@ Cube::~Cube() m_lock = nullptr; } -std::vector::const_iterator -Cube::getRowIter(size_t j, size_t k) const +std::vector::const_iterator Cube::getRowIter(size_t j, size_t k) const { - return m_data.cbegin() + m_points.x() * (k * m_points.y() + j); + size_t startIdx = k * m_points.x() * m_points.y() + j * m_points.x(); + if (startIdx >= m_data.size()) { + std::cout << "Error: startIdx out of bounds in getRowIter.\n"; + // return m_data.cend(); + } + return m_data.cbegin() + startIdx; } @@ -229,7 +234,7 @@ std::array Cube::computeGradient(size_t i, size_t j, size_t k) const if (j == 0) { - x[1][0] = m_data[dataIdx + nx]; + x[1][0] = m_data[dataIdx + m_points.x()]; x[1][1] = m_data[dataIdx]; run[1] = m_spacing[1]; } @@ -265,7 +270,7 @@ std::array Cube::computeGradient(size_t i, size_t j, size_t k) const run[2] = 2 * m_spacing[2]; } - std::array ret; + std::array ret; ret[0] = (x[0][1] - x[0][0]) / run[0]; ret[1] = (x[1][1] - x[1][0]) / run[1]; @@ -274,9 +279,26 @@ std::array Cube::computeGradient(size_t i, size_t j, size_t k) const return ret; } -std::array Cube::getValsCube(size_t i, size_t j, size_t k) const +std::array, 8> +Cube::getGradCube(size_t i, size_t j, size_t 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(size_t i, size_t j, size_t k) const { - std::array vals; + std::array vals; size_t idx = i + j * m_points.x() + k * m_points.x() * m_points.y(); @@ -293,14 +315,14 @@ std::array Cube::getValsCube(size_t i, size_t j, size_t k) const } -inline scalar_t +inline float Cube::getData(size_t i, size_t j, size_t k) const { return m_data[k * m_points.x() * m_points.y() + j * m_points.x() + i]; } -std::array Cube::getPosCube(size_t i, size_t j, size_t k) const +std::array, 8> Cube::getPosCube(size_t i, size_t j, size_t k) const { std::array, 8> pos; diff --git a/avogadro/core/cube.h b/avogadro/core/cube.h index a058178dc3..1245a9def0 100644 --- a/avogadro/core/cube.h +++ b/avogadro/core/cube.h @@ -13,6 +13,7 @@ #include "vector.h" #include +#include // Include this for std::array namespace Avogadro { namespace Core { @@ -23,9 +24,7 @@ class Mutex; /** * @class Cube cube.h * @brief Provide a data structure for regularly spaced 3D grids. - * @author Marcus D. Hanwell */ - class AVOGADROCORE_EXPORT Cube { public: @@ -118,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; @@ -133,7 +132,9 @@ 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(size_t j, size_t k) const; /** @@ -204,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. @@ -218,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; } @@ -238,12 +239,51 @@ class AVOGADROCORE_EXPORT Cube */ Mutex* lock() const { return m_lock; } + // Add declarations for the functions defined in cube.cpp + /** + * 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(size_t i, size_t j, size_t k) const; + + /** + * Get the values of the eight corners of a cube cell. + * @param i x index + * @param j y index + * @param k z index + * @return Array of values at the eight corners. + */ + std::array getValsCube(size_t i, size_t j, size_t k) const; + + + std::array, 8> getGradCube(size_t i, size_t j, size_t 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(size_t i, size_t j, size_t k) const; + + /** + * Get the positions of the eight corners of a cube cell. + * @param i x index + * @param j y index + * @param k z index + * @return Array of positions at the eight corners. + */ +std::array, 8> getPosCube(size_t i, size_t j, size_t k) const; + protected: std::vector m_data; Vector3 m_min, m_max, m_spacing; Vector3i m_points; float m_minValue, m_maxValue; - std::vector data + // Removed conflicting 'data' member variable std::string m_name; Type m_cubeType; Mutex* m_lock; diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index b2d06201a0..da724ce86e 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -64,7 +64,10 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, m_min = m_cube->min().cast(); m_dim = m_cube->dimensions(); edgeCases.resize((m_dim.x() - 1) * (m_dim.y() - 1) * (m_dim.z() - 1)); + 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.z() - 1) * (m_dim.y() - 1), 0); + m_progmax = m_dim.x(); // Similar to setting up sliceSize and grid traversal boundaries in BlockMarchFunctor.cpp: @@ -74,17 +77,24 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, return true; } +// TODO: nx ko chhod do m_dim.x() hi rkho aur loop me use kro int use krke +// doosra cheez...baaki sab theek ho jayega + void MeshGenerator::FlyingEdgesAlgorithmPass1() { // Loop through z-dimension - for(size_t k = 0; k != m_dim.z(); ++k) { + qDebug() << "i started"; + size_t nx = m_dim.x(); + size_t ny = m_dim.y(); + size_t nz = m_dim.z(); + + for(size_t k = 0; k != nz; ++k) { // Loop through y-dimension - for(size_t j = 0; j != m_dim.y(); ++j) + for(size_t j = 0; j != ny; ++j) { - // Calculate the starting position of edgeCases for the current row - auto curEdgeCases = edgeCases.begin() + (m_dim.x() - 1) * (k * m_dim.y() + j); + auto curEdgeCases = edgeCases.begin() + (nx - 1) * (k * ny + j); // Get an iterator to the current row of point values @@ -98,19 +108,22 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() for(int i = 1; i != m_dim.x(); ++i) { // update isGE for the current point + isGE[i % 2] = (curPointValues[i] >= m_iso); - // calculate edge case and update curEdgeCase + // calculate edge case and up++date curEdgeCase curEdgeCases[i-1] = calcCaseEdge(isGE[(i+1)%2], isGE[i%2]); } } } + qDebug() << "kafi door aagya"; - for(size_t k = 0; k != m_dim.z(); ++k){ - for(size_t j = 0; j != m_dim.y(); ++j) + + for(size_t k = 0; k != nz; ++k){ + for(size_t j = 0; j != ny; ++j) { - gridEdge& curGridEdge = gridEdges[k * m_dim.y() + j]; - curGridEdge.xl = m_dim.x(); + gridEdge& curGridEdge = gridEdges[k * ny + j]; + curGridEdge.xl = m_dim.x(); for(int i = 1; i != m_dim.x(); ++i) { @@ -122,7 +135,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() curGridEdge.xl = i-1; } curGridEdge.xr = i; - } + } } }} } @@ -130,18 +143,20 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() void MeshGenerator::FlyingEdgesAlgorithmPass2() { - - for(size_t k = 0; k != m_dim.z() - 1; ++k){ - for(size_t j = 0; j != m_dim.y() - 1; ++j) + qDebug() << "pass 2 started"; + size_t nx = m_dim.x(); + size_t ny = m_dim.y(); + size_t nz = m_dim.z(); + for(size_t k = 0; k != nz - 1; ++k){ + for(size_t j = 0; j != ny - 1; ++j) { - // find adjusted trim values size_t xl, xr; calcTrimValues(xl, xr, j, k); // xl, xr set in this function - gridEdge& g0 = 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]; + gridEdge& ge0 = gridEdges[k * ny + j]; + gridEdge& ge1 = gridEdges[k* ny +j + 1]; + gridEdge& ge2 = gridEdges[(k+1) * ny + j]; + gridEdge& ge3 = gridEdges[(k+1) * ny + 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); @@ -149,19 +164,21 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() 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 - size_t& curTriCounter = *(triCounter.begin() + k * (m_dim.y() - 1) + j); + size_t& curTriCounter = *(triCounter.begin() + k * (ny - 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); + bool isYEnd = (j == ny - 2); + bool isZEnd = (k == nz - 2); + + for(size_t i = xl; i != xr; ++i) { - bool isXEnd = (i == m_dim.x() - 2); - - unsigned char caseId = calcCubeCase(ec0[i], ec1[i], ec2[i], ec3[i]); + bool isXEnd = (i == nx - 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) @@ -169,11 +186,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() continue; } - - curTrimCounter += numTris[caseId]; + curTriCounter += numTris[caseId]; // not declared const bool* isCutCase = isCut[caseId]; // size 12 - ge0.xstart += isCutCase[0]; ge0.ystart += isCutCase[3]; @@ -207,9 +222,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() { ge3.xstart += isCutCase[6]; } - } - } } } @@ -219,12 +232,16 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() void MeshGenerator::FlyingEdgesAlgorithmPass3() { + qDebug() << "pass 3 started"; size_t tmp; size_t triAccum = 0; - for(size_t k = 0; k != m_dim.z()-1; ++k) { - for(size_t j = 0; j != m_dim.y()-1; ++j) + size_t nx = m_dim.x(); + size_t ny = m_dim.y(); + size_t nz = m_dim.z(); + for(size_t k = 0; k != nz -1; ++k) { + for(size_t j = 0; j != ny-1; ++j) { - size_t& curTriCounter = triCounter[k*(m_dim.y()-1)+j]; + size_t& curTriCounter = triCounter[k*(ny-1)+j]; tmp = curTriCounter; curTriCounter = triAccum; @@ -232,10 +249,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() }} size_t pointAccum = 0; - for(size_t k = 0; k != m_dim.z(); ++k) { - for(size_t j = 0; j != m_dim.y(); ++j) + for(size_t k = 0; k != nz; ++k) { + for(size_t j = 0; j != ny; ++j) { - gridEdge& curGridEdge = gridEdges[k * m_dim.y() + j]; + gridEdge& curGridEdge = gridEdges[k * ny + j]; tmp = curGridEdge.xstart; curGridEdge.xstart = pointAccum; @@ -250,15 +267,20 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() pointAccum += tmp; }} - points = std::vector >(pointAccum); - normals = std::vector >(pointAccum); + points.resize(pointAccum); + normals.resize(pointAccum); tris = std::vector >(triAccum); } void MeshGenerator::FlyingEdgesAlgorithmPass4() { - for(size_t k = 0; k != m_dim.z()-1; ++k) { - for(size_t j = 0; j != m_dim.y()-1; ++j) + + size_t nx = m_dim.x(); + size_t ny = m_dim.y(); + size_t nz = m_dim.z(); + + for(size_t k = 0; k != nz -1; ++k) { + for(size_t j = 0; j != ny-1; ++j) { // find adjusted trim values size_t xl, xr; @@ -267,7 +289,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(xl == xr) continue; - size_t triIdx = triCounter[k*(m_dim.y()-1) + j]; + size_t triIdx = triCounter[k*(ny-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]; @@ -287,8 +309,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t x3counter = 0; - bool isYEnd = (j == m_dim.y()-2); - bool isZEnd = (k == m_dim.z()-2); + bool isYEnd = (j == ny-2); + bool isZEnd = (k == nz-2); for(size_t i = xl; i != xr; ++i) { @@ -301,9 +323,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() continue; } - cube_t pointCube = m_cube->getPosCube(i, j, k); - scalarCube_t isovalCube = m_cube->getValsCube(i, j, k); - cube_t gradCube = m_cube->getGradCube(i, j, k); + 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 @@ -312,8 +334,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCut[0]) { size_t idx = ge0.xstart + x0counter; - points[idx] = interpolateOnCube(pointCube, isovalCube, 0); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 0); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 0); + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[0] = idx; ++x0counter; } @@ -321,8 +344,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCut[3]) { size_t idx = ge0.ystart + y0counter; - points[idx] = interpolateOnCube(pointCube, isovalCube, 3); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 3); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 3); + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[3] = idx; ++y0counter; } @@ -330,8 +354,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCut[8]) { size_t idx = ge0.zstart + z0counter; - points[idx] = interpolateOnCube(pointCube, isovalCube, 8); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 8); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 8); + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[8] = idx; ++z0counter; } @@ -350,8 +375,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge0.ystart + y0counter; if(isXEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 1); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 1); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 1); + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); // y0counter counter doesn't need to be incremented // because it won't be used again. } @@ -363,8 +389,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge0.zstart + z0counter; if(isXEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 9); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 9); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 9); + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); // z0counter doesn't need to in incremented. } globalIdxs[9] = idx; @@ -375,8 +402,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge1.xstart + x1counter; if(isYEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 2); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 2); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 2); + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[2] = idx; ++x1counter; @@ -388,8 +416,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isYEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 10); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 10); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 10); + + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[10] = idx; ++z1counter; @@ -400,8 +430,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge2.xstart + x2counter; if(isZEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 4); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 4); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 4); + + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[4] = idx; ++x2counter; @@ -412,8 +444,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge2.ystart + y2counter; if(isZEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 7); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 7); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 7); + + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[7] = idx; ++y2counter; @@ -424,8 +458,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge1.zstart + z1counter; if(isXEnd and isYEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 11); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 11); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 11); + + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); // z1counter does not need to be incremented. } globalIdxs[11] = idx; @@ -436,8 +472,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge2.ystart + y2counter; if(isXEnd and isZEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 5); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 5); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 5); + + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); // y2 counter does not need to be incremented. } globalIdxs[5] = idx; @@ -448,8 +486,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge3.xstart + x3counter; if(isYEnd and isZEnd) { - points[idx] = interpolateOnCube(pointCube, isovalCube, 6); - normals[idx] = interpolateOnCube(gradCube, isovalCube, 6); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 6); + + points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[6] = idx; ++x3counter; @@ -476,46 +516,47 @@ 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 (Similar to marching loop in BlockMarchFunctor.cpp) - 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)); // Same logic as marching each cell in BlockMarchFunctor.cpp - } - } - 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); - } - - m_cube->lock()->unlock(); - - // Copy the data across - m_mesh->setVertices(m_vertices); - m_mesh->setNormals(m_normals); + // Perform the Flying Edges algorithm passes + FlyingEdgesAlgorithmPass1(); + FlyingEdgesAlgorithmPass2(); + FlyingEdgesAlgorithmPass3(); + FlyingEdgesAlgorithmPass4(); + + // Now assemble the mesh from the generated data + // std::vector meshVertices; + // std::vector meshNormals; + // std::vector meshIndices; + + // for (const auto& tri : tris) { + // for (size_t idx = 0; idx < 3; ++idx) { + // size_t pointIdx = tri[idx]; + // meshVertices.push_back(points[pointIdx]); + // meshNormals.push_back(normals[pointIdx]); + // // meshIndices.push_back(static_cast(meshVertices.size()) - 1); + // } + // } + + // Copy the data to m_mesh + m_mesh->setVertices(points); + m_mesh->setNormals(normals); + // m_mesh->setIndices(meshIndices); m_mesh->setStable(true); - // Now we are done give all that memory back - m_vertices.resize(0); - m_normals.resize(0); + // Clear temporary data + points.clear(); + normals.clear(); + // tris.clear(); - // Smooth out the mesh (Similar smoothing is performed at the end of BlockMarchFunctor.cpp) - m_mesh->smooth(m_passes); + // Smooth out the mesh (if required) + // m_mesh->smooth(m_passes); } + + void MeshGenerator::clear() { m_iso = 0.0; @@ -559,88 +600,88 @@ unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) return 0; } -bool MeshGenerator::marchingCube(const Vector3i& pos) -{ - 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]; - - // Fetch the cube's corner values (Similar to volReader.getVertexValues in BlockMarchFunctor.cpp) - for (int i = 0; i < 8; ++i) { - afCubeValue[i] = static_cast( - m_cube->value(Vector3i(pos + Vector3i(a2iVertexOffset[i])))); - } - - // Determine which edges are intersected by the isosurface - 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]; - - // If there are no intersections, skip the cube (Same as case 0 or 255 in BlockMarchFunctor.cpp) - if (iEdgeFlags == 0) { - return false; - } - - // Interpolate edge vertices (Similar to interpolation in BlockMarchFunctor.cpp with lerp) - for (int i = 0; i < 12; ++i) { - 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]); - - // Normals are computed similarly in BlockMarchFunctor.cpp with `computeAllGradients` - asEdgeNorm[i] = normal(asEdgeVertex[i]); - } - } - - // Store the triangles based on the edges intersected (Same logic as adding triangles in BlockMarchFunctor.cpp) - for (int i = 0; i < 5; ++i) { - if (a2iTriangleConnectionTable[iFlagIndex][3 * i] < 0) - break; - int iVertex = 0; - iEdgeFlags = a2iTriangleConnectionTable[iFlagIndex][3 * i]; - 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; -} +// bool MeshGenerator::marchingCube(const Vector3i& pos) +// { +// 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]; + +// // Fetch the cube's corner values (Similar to volReader.getVertexValues in BlockMarchFunctor.cpp) +// for (int i = 0; i < 8; ++i) { +// afCubeValue[i] = static_cast( +// m_cube->value(Vector3i(pos + Vector3i(a2iVertexOffset[i])))); +// } + +// // Determine which edges are intersected by the isosurface +// 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]; + +// // If there are no intersections, skip the cube (Same as case 0 or 255 in BlockMarchFunctor.cpp) +// if (iEdgeFlags == 0) { +// return false; +// } + +// // Interpolate edge vertices (Similar to interpolation in BlockMarchFunctor.cpp with lerp) +// for (int i = 0; i < 12; ++i) { +// 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]); + +// // Normals are computed similarly in BlockMarchFunctor.cpp with `computeAllGradients` +// asEdgeNorm[i] = normal(asEdgeVertex[i]); +// } +// } + +// // Store the triangles based on the edges intersected (Same logic as adding triangles in BlockMarchFunctor.cpp) +// for (int i = 0; i < 5; ++i) { +// if (a2iTriangleConnectionTable[iFlagIndex][3 * i] < 0) +// break; +// int iVertex = 0; +// iEdgeFlags = a2iTriangleConnectionTable[iFlagIndex][3 * i]; +// 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; +// } unsigned char MeshGenerator::calcCubeCase( unsigned char const& ec0, unsigned char const& ec1, @@ -672,7 +713,7 @@ unsigned char MeshGenerator::calcCubeCase( } -bool MeshGenerator::isCutEdge(size_t i, size_t j, size_t k) const +bool MeshGenerator::isCutEdge(size_t const& i, size_t const& j, size_t const& k) const { size_t nx = m_dim.x(); size_t ny = m_dim.y(); @@ -747,6 +788,32 @@ void MeshGenerator::calcTrimValues(size_t& xl, size_t& xr, size_t const& j, size xl = xr; } +inline std::array +MeshGenerator::interpolateOnCube( + std::array, 8> const& pts, + std::array const& isovals, + unsigned char const& edge) const +{ + unsigned char i0 = edgeVertices[edge][0]; + unsigned char i1 = edgeVertices[edge][1]; + + float weight = (m_iso - isovals[i0]) / (isovals[i1] - isovals[i0]); + return interpolate(pts[i0], pts[i1], weight); +} + +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; +} + // flying edges tables using: @@ -1290,7 +1357,7 @@ const char MeshGenerator::caseTriangles[256][16] {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} }; -const unsigned char edgeVertices[12][2] = +const unsigned char MeshGenerator::edgeVertices[12][2] = { {0,1}, {1,2}, {3,2}, {0,3}, {4,5}, {5,6}, diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index 03400a37b4..84abd380e1 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -81,22 +81,48 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread */ void run() override; - struct gridEdge { - int xl; // Left trim index - int xr; // Right trim index - int xstart; // X-coordinate start index - int ystart; // Y-coordinate start index - int zstart; // Z-coordinate start index + struct gridEdge + { + gridEdge() + : xl(0), + xr(0), + xstart(0), + ystart(0), + zstart(0) + {} + + // trim values + // set on pass 1 + size_t xl; + size_t xr; + + // modified on pass 2 + // set on pass 3 + size_t xstart; + size_t ystart; + size_t zstart; + }; + - gridEdge() : xl(-1), xr(-1), xstart(-1), ystart(-1), zstart(-1) {} - }; void FlyingEdgesAlgorithmPass1(); + void FlyingEdgesAlgorithmPass2(); + void FlyingEdgesAlgorithmPass3(); + void FlyingEdgesAlgorithmPass4(); + /** * @return The Cube being used by the class. */ const Core::Cube* cube() const { return m_cube; } + inline void calcTrimValues( + size_t& xl, size_t& xr, size_t const& j, size_t const& k) const; + + + 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. */ @@ -147,6 +173,20 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread */ bool marchingCube(const Vector3i& pos); + bool isCutEdge(size_t const& i, size_t const& j, size_t const& k) const; + + inline std::array interpolateOnCube( + std::array, 8> const& pts, + std::array const& isovals, + unsigned char const& edge) const; + + inline std::array interpolate( + std::array const& a, + std::array const& b, + float const& weight) const; + + 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. */ bool m_reverseWinding; /** Whether the winding and normals are reversed. */ @@ -162,10 +202,12 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread Core::Array m_vertices, m_normals; Core::Array m_indices; std::vector gridEdges; + std::vector cubeCases; // size (nx-1)*(ny-1)*(nz-1) + std::vector triCounter; // size of (ny-1)*(nz-1) std::vector edgeCases; - std::vector > points; // - std::vector > normals; // The output + Core::Array points; // + Core::Array normals; // The output std::vector > tris; int m_progmin; int m_progmax; From 973fe51100082e3773abc72d1d475b7a227b51c6 Mon Sep 17 00:00:00 2001 From: Perminder Date: Sat, 2 Nov 2024 04:19:41 +0530 Subject: [PATCH 04/19] minor fixes Signed-off-by: Perminder --- avogadro/core/cube.cpp | 13 ++--- avogadro/qtgui/meshgenerator.cpp | 93 +++++++++++++++++--------------- avogadro/qtgui/meshgenerator.h | 2 +- 3 files changed, 59 insertions(+), 49 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index 86c774b985..292159cc67 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -26,12 +26,13 @@ Cube::~Cube() std::vector::const_iterator Cube::getRowIter(size_t j, size_t k) const { - size_t startIdx = k * m_points.x() * m_points.y() + j * m_points.x(); - if (startIdx >= m_data.size()) { - std::cout << "Error: startIdx out of bounds in getRowIter.\n"; - // return m_data.cend(); - } - return m_data.cbegin() + startIdx; + // size_t startIdx = k * m_points.x() * m_points.y() + j * m_points.x(); + // if (startIdx >= m_data.size()) { + // std::cout << "Error: startIdx out of bounds in getRowIter.\n"; + // return m_data.cend(); + // } + return m_data.cbegin() + m_points.x() * (k * m_points.y() + j); + // return m_data.cbegin() + startIdx; } diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index da724ce86e..3fcfd060a1 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -83,7 +83,7 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, void MeshGenerator::FlyingEdgesAlgorithmPass1() { // Loop through z-dimension - qDebug() << "i started"; + // qDebug() << "1st started"; size_t nx = m_dim.x(); size_t ny = m_dim.y(); size_t nz = m_dim.z(); @@ -116,7 +116,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() } } } - qDebug() << "kafi door aagya"; + // qDebug() << "kafi door aagya"; for(size_t k = 0; k != nz; ++k){ @@ -138,12 +138,14 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() } } }} + // qDebug() << "1st ended"; + } void MeshGenerator::FlyingEdgesAlgorithmPass2() { - qDebug() << "pass 2 started"; + // qDebug() << "pass 2 started"; size_t nx = m_dim.x(); size_t ny = m_dim.y(); size_t nz = m_dim.z(); @@ -225,6 +227,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() } } } + // qDebug() << "2nd ended"; + } @@ -232,7 +236,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() void MeshGenerator::FlyingEdgesAlgorithmPass3() { - qDebug() << "pass 3 started"; + // qDebug() << "pass 3 started"; size_t tmp; size_t triAccum = 0; size_t nx = m_dim.x(); @@ -269,11 +273,14 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() points.resize(pointAccum); normals.resize(pointAccum); - tris = std::vector >(triAccum); + tris.resize(triAccum); + // qDebug() << "pass 3 ended"; + } void MeshGenerator::FlyingEdgesAlgorithmPass4() { + // qDebug() << "pass 4 started"; size_t nx = m_dim.x(); size_t ny = m_dim.y(); @@ -334,8 +341,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCut[0]) { size_t idx = ge0.xstart + x0counter; + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 0); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 0); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[0] = idx; ++x0counter; @@ -344,8 +353,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCut[3]) { size_t idx = ge0.ystart + y0counter; + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 3); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 3); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[3] = idx; ++y0counter; @@ -354,8 +364,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCut[8]) { size_t idx = ge0.zstart + z0counter; + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 8); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 8); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[8] = idx; ++z0counter; @@ -375,9 +386,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge0.ystart + y0counter; if(isXEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 1); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 1); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points.push_back(Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2])); + normals.push_back(Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2])); // y0counter counter doesn't need to be incremented // because it won't be used again. } @@ -389,8 +401,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge0.zstart + z0counter; if(isXEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 9); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 9); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); // z0counter doesn't need to in incremented. } @@ -402,8 +415,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge1.xstart + x1counter; if(isYEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 2); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 2); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[2] = idx; @@ -416,9 +430,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isYEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 10); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 10); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[10] = idx; @@ -430,9 +445,11 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge2.xstart + x2counter; if(isZEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 4); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 4); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[4] = idx; @@ -444,9 +461,11 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge2.ystart + y2counter; if(isZEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 7); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 7); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[7] = idx; @@ -458,9 +477,11 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge1.zstart + z1counter; if(isXEnd and isYEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 11); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 11); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); // z1counter does not need to be incremented. } @@ -472,9 +493,11 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge2.ystart + y2counter; if(isXEnd and isZEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 5); + std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 5); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); // y2 counter does not need to be incremented. } @@ -486,9 +509,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() size_t idx = ge3.xstart + x3counter; if(isYEnd and isZEnd) { + std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 6); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 6); - points[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[6] = idx; @@ -506,6 +530,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() } } }} + // qDebug() << "pass 4 ended"; + } @@ -516,43 +542,26 @@ void MeshGenerator::run() return; } - // Mark the mesh as being worked on and clear it m_mesh->setStable(false); m_mesh->clear(); - // Perform the Flying Edges algorithm passes FlyingEdgesAlgorithmPass1(); FlyingEdgesAlgorithmPass2(); FlyingEdgesAlgorithmPass3(); FlyingEdgesAlgorithmPass4(); + + qDebug() << "size-point" << points.size(); + qDebug() << "size-normals" << normals.size(); + - // Now assemble the mesh from the generated data - // std::vector meshVertices; - // std::vector meshNormals; - // std::vector meshIndices; - - // for (const auto& tri : tris) { - // for (size_t idx = 0; idx < 3; ++idx) { - // size_t pointIdx = tri[idx]; - // meshVertices.push_back(points[pointIdx]); - // meshNormals.push_back(normals[pointIdx]); - // // meshIndices.push_back(static_cast(meshVertices.size()) - 1); - // } - // } - - // Copy the data to m_mesh m_mesh->setVertices(points); m_mesh->setNormals(normals); - // m_mesh->setIndices(meshIndices); m_mesh->setStable(true); - // Clear temporary data - points.clear(); - normals.clear(); - // tris.clear(); + points.resize(0); + + normals.resize(0); - // Smooth out the mesh (if required) - // m_mesh->smooth(m_passes); } diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index 84abd380e1..afd5f6a688 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -208,7 +208,7 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread std::vector edgeCases; Core::Array points; // Core::Array normals; // The output - std::vector > tris; + Core::Array tris; int m_progmin; int m_progmax; From bcb02c4dca05ff3f243ab7b66c6c74822f26ad40 Mon Sep 17 00:00:00 2001 From: Perminder Date: Sun, 3 Nov 2024 07:30:25 +0530 Subject: [PATCH 05/19] some fixes Signed-off-by: Perminder --- avogadro/core/cube.cpp | 7 +- avogadro/qtgui/meshgenerator.cpp | 199 ++++++++++--------------------- 2 files changed, 65 insertions(+), 141 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index 292159cc67..ca660aa05a 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -26,13 +26,7 @@ Cube::~Cube() std::vector::const_iterator Cube::getRowIter(size_t j, size_t k) const { - // size_t startIdx = k * m_points.x() * m_points.y() + j * m_points.x(); - // if (startIdx >= m_data.size()) { - // std::cout << "Error: startIdx out of bounds in getRowIter.\n"; - // return m_data.cend(); - // } return m_data.cbegin() + m_points.x() * (k * m_points.y() + j); - // return m_data.cbegin() + startIdx; } @@ -363,6 +357,7 @@ std::array, 8> Cube::getPosCube(size_t i, size_t j, size_t pos[7][1] = ypos + m_spacing.y(); pos[7][2] = zpos + m_spacing.z(); + // std::cout << "pos" << " " << pos[0][0] << std::endl; return pos; } diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 3fcfd060a1..f24742390d 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -63,11 +63,13 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, 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() - 1) * (m_dim.z() - 1)); + 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.z() - 1) * (m_dim.y() - 1), 0); + triCounter.resize((m_dim.y() - 1) * (m_dim.z() - 1)); + + qDebug() << "initialized at first"; m_progmax = m_dim.x(); // Similar to setting up sliceSize and grid traversal boundaries in BlockMarchFunctor.cpp: @@ -83,7 +85,6 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, void MeshGenerator::FlyingEdgesAlgorithmPass1() { // Loop through z-dimension - // qDebug() << "1st started"; size_t nx = m_dim.x(); size_t ny = m_dim.y(); size_t nz = m_dim.z(); @@ -95,7 +96,6 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() // Calculate the starting position of edgeCases for the current row auto curEdgeCases = edgeCases.begin() + (nx - 1) * (k * ny + j); - // Get an iterator to the current row of point values auto curPointValues = m_cube->getRowIter(j, k); @@ -111,7 +111,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() isGE[i % 2] = (curPointValues[i] >= m_iso); - // calculate edge case and up++date curEdgeCase + // calculate edge case and up++date curEdgeCase curEdgeCases[i-1] = calcCaseEdge(isGE[(i+1)%2], isGE[i%2]); } } @@ -226,9 +226,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() } } } - } - // qDebug() << "2nd ended"; - + } } @@ -273,15 +271,13 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() points.resize(pointAccum); normals.resize(pointAccum); - tris.resize(triAccum); - // qDebug() << "pass 3 ended"; + m_vertices.resize(0); + m_normals.resize(0); } void MeshGenerator::FlyingEdgesAlgorithmPass4() { - // qDebug() << "pass 4 started"; - size_t nx = m_dim.x(); size_t ny = m_dim.y(); size_t nz = m_dim.z(); @@ -330,6 +326,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() continue; } + const bool* isCutCase = 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); @@ -338,8 +335,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() // Calculate global indices for triangles std::array globalIdxs; - if(isCut[0]) + if(isCutCase[0]) { + // points-> array size_t idx = ge0.xstart + x0counter; std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 0); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 0); @@ -350,7 +348,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() ++x0counter; } - if(isCut[3]) + if(isCutCase[3]) { size_t idx = ge0.ystart + y0counter; std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 3); @@ -361,7 +359,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() ++y0counter; } - if(isCut[8]) + if(isCutCase[8]) { size_t idx = ge0.zstart + z0counter; std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 8); @@ -372,31 +370,22 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() ++z0counter; } - // Note: - // e1, e5, e9 and e11 will be visited in the next iteration - // when they are e3, e7, e8 and 10 respectively. So don't - // increment their counters. When the cube is an edge cube, - // their counters don't need to be incremented because they - // won't be used agin. - - // Manage boundary cases if needed. Otherwise just update - // globalIdx. - if(isCut[1]) + if(isCutCase[1]) { size_t idx = ge0.ystart + y0counter; if(isXEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 1); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 1); - points.push_back(Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2])); - normals.push_back(Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2])); + points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + 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(isCut[9]) + if(isCutCase[9]) { size_t idx = ge0.zstart + z0counter; if(isXEnd) @@ -410,7 +399,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() globalIdxs[9] = idx; } - if(isCut[2]) + if(isCutCase[2]) { size_t idx = ge1.xstart + x1counter; if(isYEnd) @@ -424,7 +413,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() ++x1counter; } - if(isCut[10]) + if(isCutCase[10]) { size_t idx = ge1.zstart + z1counter; @@ -440,7 +429,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() ++z1counter; } - if(isCut[4]) + if(isCutCase[4]) { size_t idx = ge2.xstart + x2counter; if(isZEnd) @@ -456,7 +445,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() ++x2counter; } - if(isCut[7]) + if(isCutCase[7]) { size_t idx = ge2.ystart + y2counter; if(isZEnd) @@ -472,7 +461,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() ++y2counter; } - if(isCut[11]) + if(isCutCase[11]) { size_t idx = ge1.zstart + z1counter; if(isXEnd and isYEnd) @@ -483,12 +472,11 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); - // z1counter does not need to be incremented. } globalIdxs[11] = idx; } - if(isCut[5]) + if(isCutCase[5]) { size_t idx = ge2.ystart + y2counter; if(isXEnd and isZEnd) @@ -504,7 +492,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() globalIdxs[5] = idx; } - if(isCut[6]) + if(isCutCase[6]) { size_t idx = ge3.xstart + x3counter; if(isYEnd and isZEnd) @@ -523,10 +511,25 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() const char* caseTri = caseTriangles[caseId]; // size 16 for(int idx = 0; caseTri[idx] != -1; idx += 3) { - tris[triIdx][0] = globalIdxs[caseTri[idx]]; - tris[triIdx][1] = globalIdxs[caseTri[idx+1]]; - tris[triIdx][2] = globalIdxs[caseTri[idx+2]]; - ++triIdx; + + + size_t globalIdx = globalIdxs[caseTri[idx]]; + size_t globalIdx1 = globalIdxs[caseTri[idx + 1]]; + size_t globalIdx2 = globalIdxs[caseTri[idx + 2]]; + + + + m_vertices.push_back(points[globalIdx]); + m_vertices.push_back(points[globalIdx1]); + m_vertices.push_back(points[globalIdx2]); + + m_normals.push_back(normals[globalIdx]); + m_normals.push_back(normals[globalIdx1]); + m_normals.push_back(normals[globalIdx2]); + + + + } } }} @@ -545,22 +548,26 @@ void MeshGenerator::run() m_mesh->setStable(false); m_mesh->clear(); + + m_vertices.clear(); + m_normals.clear(); + FlyingEdgesAlgorithmPass1(); FlyingEdgesAlgorithmPass2(); FlyingEdgesAlgorithmPass3(); FlyingEdgesAlgorithmPass4(); - qDebug() << "size-point" << points.size(); - qDebug() << "size-normals" << normals.size(); + qDebug() << "size-point" << m_vertices.size(); + qDebug() << "size-normals" << m_normals.size(); - m_mesh->setVertices(points); - m_mesh->setNormals(normals); + m_mesh->setVertices(m_vertices); + m_mesh->setNormals(m_normals); m_mesh->setStable(true); - points.resize(0); + m_normals.resize(0); + m_vertices.resize(0); - normals.resize(0); } @@ -609,97 +616,10 @@ unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) return 0; } -// bool MeshGenerator::marchingCube(const Vector3i& pos) -// { -// 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]; - -// // Fetch the cube's corner values (Similar to volReader.getVertexValues in BlockMarchFunctor.cpp) -// for (int i = 0; i < 8; ++i) { -// afCubeValue[i] = static_cast( -// m_cube->value(Vector3i(pos + Vector3i(a2iVertexOffset[i])))); -// } - -// // Determine which edges are intersected by the isosurface -// 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]; - -// // If there are no intersections, skip the cube (Same as case 0 or 255 in BlockMarchFunctor.cpp) -// if (iEdgeFlags == 0) { -// return false; -// } - -// // Interpolate edge vertices (Similar to interpolation in BlockMarchFunctor.cpp with lerp) -// for (int i = 0; i < 12; ++i) { -// 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]); - -// // Normals are computed similarly in BlockMarchFunctor.cpp with `computeAllGradients` -// asEdgeNorm[i] = normal(asEdgeVertex[i]); -// } -// } - -// // Store the triangles based on the edges intersected (Same logic as adding triangles in BlockMarchFunctor.cpp) -// for (int i = 0; i < 5; ++i) { -// if (a2iTriangleConnectionTable[iFlagIndex][3 * i] < 0) -// break; -// int iVertex = 0; -// iEdgeFlags = a2iTriangleConnectionTable[iFlagIndex][3 * i]; -// 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; -// } - unsigned char MeshGenerator::calcCubeCase( unsigned char const& ec0, unsigned char const& ec1, unsigned char const& ec2, unsigned char const& ec3) const { - // ec0 | (i, j, k) - // ec1 | (i, j+1, k) - // ec2 | (i, j, k+1) - // ec3 | (i, j+1, k+1) unsigned char caseId = 0; if ((ec0 == 0) || (ec0 == 2)) // Vertex 0 at (i, j, k) @@ -757,10 +677,11 @@ bool MeshGenerator::isCutEdge(size_t const& i, size_t const& j, size_t const& k) // If the sum is odd, the edge along the z-axis is cut if ((edgeCase + edgeCaseZ) % 2 == 1) { + // qDebug() << "true return krega"; return true; } } - + // qDebug() << "false return krega"; return false; } @@ -781,6 +702,7 @@ unsigned char MeshGenerator::calcCaseEdge(bool const& prevEdge, bool const& curr return 3; } +// 2000 void MeshGenerator::calcTrimValues(size_t& xl, size_t& xr, size_t const& j, size_t const& k) const { size_t ny = m_dim.y(); @@ -793,6 +715,7 @@ void MeshGenerator::calcTrimValues(size_t& xl, size_t& xr, size_t const& j, size xl = std::min({ge0.xl, ge1.xl, ge2.xl, ge3.xl}); xr = std::max({ge0.xr, ge1.xr, ge2.xr, ge3.xr}); + if (xl > xr) xl = xr; } @@ -805,8 +728,14 @@ MeshGenerator::interpolateOnCube( { unsigned char i0 = edgeVertices[edge][0]; unsigned char i1 = edgeVertices[edge][1]; + float weight; - float weight = (m_iso - isovals[i0]) / (isovals[i1] - isovals[i0]); + float denom = isovals[i1] - isovals[i0]; + if (fabs(denom) < 1e-9) + weight = 0.5f; + else + weight = (m_iso - isovals[i0]) / denom; + return interpolate(pts[i0], pts[i1], weight); } From 762e943559e4b9019a0444f5ddde9166f73ec697 Mon Sep 17 00:00:00 2001 From: Perminder Date: Wed, 6 Nov 2024 22:11:07 +0530 Subject: [PATCH 06/19] working Signed-off-by: Perminder --- avogadro/core/cube.cpp | 38 ++++++------ avogadro/core/mesh.cpp | 14 +++++ avogadro/core/mesh.h | 13 ++-- avogadro/qtgui/meshgenerator.cpp | 91 ++++++++++------------------ avogadro/qtgui/meshgenerator.h | 4 +- avogadro/qtplugins/meshes/meshes.cpp | 49 ++++----------- avogadro/rendering/meshgeometry.cpp | 5 +- avogadro/rendering/meshgeometry.h | 4 +- 8 files changed, 97 insertions(+), 121 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index ca660aa05a..887a9f1549 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -206,63 +206,64 @@ std::array Cube::computeGradient(size_t i, size_t j, size_t k) const std::array, 3> x; std::array run; - size_t dataIdx = i + j * m_points.x() + k * m_points.x() * m_points.y(); + size_t dataIdx = i + (j * m_points.x()) + (k * m_points.x() * m_points.y()); + // std::cout << m_spacing[0]; if (i == 0) { x[0][0] = m_data[dataIdx + 1]; x[0][1] = m_data[dataIdx]; - run[0] = m_spacing[0]; + run[0] = m_spacing.x(); } else if (i == (m_points.x() - 1)) { x[0][0] = m_data[dataIdx]; x[0][1] = m_data[dataIdx - 1]; - run[0] = m_spacing[0]; + run[0] = m_spacing.x(); } else { x[0][0] = m_data[dataIdx + 1]; x[0][1] = m_data[dataIdx - 1]; - run[0] = 2 * m_spacing[0]; + run[0] = 2 * m_spacing.x(); } if (j == 0) { x[1][0] = m_data[dataIdx + m_points.x()]; x[1][1] = m_data[dataIdx]; - run[1] = m_spacing[1]; + run[1] = m_spacing.y(); } else if (j == (m_points.y() - 1)) { x[1][0] = m_data[dataIdx]; x[1][1] = m_data[dataIdx - m_points.x()]; - run[1] = m_spacing[1]; + run[1] = m_spacing.y(); } else { x[1][0] = m_data[dataIdx + m_points.x()]; x[1][1] = m_data[dataIdx - m_points.x()]; - run[1] = 2 * m_spacing[1]; + run[1] = 2 * m_spacing.y(); } if (k == 0) { - x[2][0] = m_data[dataIdx + m_points.x() * m_points.y()]; + x[2][0] = m_data[dataIdx + (m_points.x() * m_points.y())]; x[2][1] = m_data[dataIdx]; - run[2] = m_spacing[2]; + run[2] = m_spacing.z(); } else if (k == (m_points.z() - 1)) { x[2][0] = m_data[dataIdx]; - x[2][1] = m_data[dataIdx - m_points.x() * m_points.y()]; - run[2] = m_spacing[2]; + x[2][1] = m_data[dataIdx - (m_points.x() * m_points.y())]; + run[2] = m_spacing.z(); } else { - x[2][0] = m_data[dataIdx + m_points.x() * m_points.y()]; - x[2][1] = m_data[dataIdx - m_points.x() * m_points.y()]; - run[2] = 2 * m_spacing[2]; + x[2][0] = m_data[dataIdx + (m_points.x() * m_points.y())]; + x[2][1] = m_data[dataIdx - (m_points.x() * m_points.y())]; + run[2] = 2 * m_spacing.z(); } std::array ret; @@ -295,7 +296,7 @@ std::array Cube::getValsCube(size_t i, size_t j, size_t k) const { std::array vals; - size_t idx = i + j * m_points.x() + k * m_points.x() * m_points.y(); + size_t idx = i + (j * m_points.x()) + (k * m_points.x() * m_points.y()); vals[0] = getData(i, j, k); vals[1] = getData(i + 1, j, k); @@ -313,7 +314,7 @@ std::array Cube::getValsCube(size_t i, size_t j, size_t k) const inline float Cube::getData(size_t i, size_t j, size_t k) const { - return m_data[k * m_points.x() * m_points.y() + j * m_points.x() + i]; + return m_data[(k * m_points.x() * m_points.y()) + (j * m_points.x()) + i]; } @@ -321,8 +322,9 @@ std::array, 8> Cube::getPosCube(size_t i, size_t j, size_t { std::array, 8> pos; - float xpos = m_min.x() + i * m_spacing.x(); - float ypos = m_min.y() + j * m_spacing.y(); + // std::cout<< m_spacing.x(); + float xpos = m_min.x() + i * m_spacing.y(); + float ypos = m_min.y() + j * m_spacing.x(); float zpos = m_min.z() + k * m_spacing.z(); pos[0][0] = xpos; diff --git a/avogadro/core/mesh.cpp b/avogadro/core/mesh.cpp index f28c202513..fc13cc875d 100644 --- a/avogadro/core/mesh.cpp +++ b/avogadro/core/mesh.cpp @@ -62,6 +62,20 @@ const Vector3f* Mesh::vertex(int n) const return &(m_vertices[n * 3]); } + +bool Mesh::setTriangles(const std::vector >& values) +{ + tris.clear(); + tris = values; + return true; +} + +const std::vector >& Mesh::triangles() const +{ + return tris; +} + + bool Mesh::setVertices(const Core::Array& values) { m_vertices.clear(); diff --git a/avogadro/core/mesh.h b/avogadro/core/mesh.h index a2155923a9..5c6b8819b8 100644 --- a/avogadro/core/mesh.h +++ b/avogadro/core/mesh.h @@ -122,6 +122,10 @@ class AVOGADROCORE_EXPORT Mesh */ const Vector3f* vertex(int n) const; + bool setTriangles(const std::vector >& values); + const std::vector >& triangles() const; + + /** * Clear the vertices vector and assign new values. */ @@ -141,10 +145,10 @@ class AVOGADROCORE_EXPORT Mesh /** * @return The number of normals. */ - unsigned int numNormals() const - { - return static_cast(m_normals.size()); - } + // unsigned int numNormals() const + // { + // return static_cast(m_normals.size()); + // } /** * @return Pointer to the first normal of the specified triangle. @@ -228,6 +232,7 @@ class AVOGADROCORE_EXPORT Mesh Core::Array m_vertices; Core::Array m_normals; Core::Array m_colors; + std::vector > tris; std::string m_name; bool m_stable; float m_isoValue; diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index f24742390d..7982755b13 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -39,6 +39,7 @@ MeshGenerator::~MeshGenerator() bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, int passes, bool reverse) + { if (!cube_ || !mesh_) return false; @@ -54,10 +55,10 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, // origin = volReader.imageData->getOrigin(); // spacing = volReader.imageData->getSpacing(); - if (!m_cube->lock()->tryLock()) { - qDebug() << "Cannot get a read lock…"; - return false; - } + // 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]); @@ -75,7 +76,7 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, // Similar to setting up sliceSize and grid traversal boundaries in BlockMarchFunctor.cpp: // sliceSize = dims[0] * dims[1]; - m_cube->lock()->unlock(); + // m_cube->lock()->unlock(); return true; } @@ -90,13 +91,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() size_t nz = m_dim.z(); for(size_t k = 0; k != nz; ++k) { - // Loop through y-dimension for(size_t j = 0; j != ny; ++j) { - // Calculate the starting position of edgeCases for the current row auto curEdgeCases = edgeCases.begin() + (nx - 1) * (k * ny + j); - // Get an iterator to the current row of point values auto curPointValues = m_cube->getRowIter(j, k); @@ -111,13 +109,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() isGE[i % 2] = (curPointValues[i] >= m_iso); - // calculate edge case and up++date curEdgeCase curEdgeCases[i-1] = calcCaseEdge(isGE[(i+1)%2], isGE[i%2]); } } } - // qDebug() << "kafi door aagya"; - for(size_t k = 0; k != nz; ++k){ for(size_t j = 0; j != ny; ++j) @@ -138,14 +133,11 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() } } }} - // qDebug() << "1st ended"; - } void MeshGenerator::FlyingEdgesAlgorithmPass2() { - // qDebug() << "pass 2 started"; size_t nx = m_dim.x(); size_t ny = m_dim.y(); size_t nz = m_dim.z(); @@ -254,7 +246,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() for(size_t k = 0; k != nz; ++k) { for(size_t j = 0; j != ny; ++j) { - gridEdge& curGridEdge = gridEdges[k * ny + j]; + gridEdge& curGridEdge = gridEdges[(k * ny) + j]; tmp = curGridEdge.xstart; curGridEdge.xstart = pointAccum; @@ -271,8 +263,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() points.resize(pointAccum); normals.resize(pointAccum); - m_vertices.resize(0); - m_normals.resize(0); + tris.resize(triAccum); } @@ -292,7 +283,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(xl == xr) continue; - size_t triIdx = triCounter[k*(ny-1) + j]; + size_t triIdx = triCounter[(k*(ny-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]; @@ -511,30 +502,13 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() const char* caseTri = caseTriangles[caseId]; // size 16 for(int idx = 0; caseTri[idx] != -1; idx += 3) { - - - size_t globalIdx = globalIdxs[caseTri[idx]]; - size_t globalIdx1 = globalIdxs[caseTri[idx + 1]]; - size_t globalIdx2 = globalIdxs[caseTri[idx + 2]]; - - - - m_vertices.push_back(points[globalIdx]); - m_vertices.push_back(points[globalIdx1]); - m_vertices.push_back(points[globalIdx2]); - - m_normals.push_back(normals[globalIdx]); - m_normals.push_back(normals[globalIdx1]); - m_normals.push_back(normals[globalIdx2]); - - - - + tris[triIdx][0] = globalIdxs[caseTri[idx]]; + tris[triIdx][1] = globalIdxs[caseTri[idx+1]]; + tris[triIdx][2] = globalIdxs[caseTri[idx+2]]; + ++triIdx; } } }} - // qDebug() << "pass 4 ended"; - } @@ -549,24 +523,30 @@ void MeshGenerator::run() m_mesh->clear(); - m_vertices.clear(); - m_normals.clear(); + // m_verticesear(); FlyingEdgesAlgorithmPass1(); FlyingEdgesAlgorithmPass2(); FlyingEdgesAlgorithmPass3(); FlyingEdgesAlgorithmPass4(); - qDebug() << "size-point" << m_vertices.size(); - qDebug() << "size-normals" << m_normals.size(); + qDebug() << "size-point" << m_dim.x(); + // qDebug + qDebug() << "size-normals" << m_dim.y(); + qDebug() << "tris" << m_dim.z(); + + m_mesh->setVertices(points); + m_mesh->setNormals(normals); + m_mesh->setTriangles(tris); + m_mesh->setStable(true); - m_mesh->setVertices(m_vertices); - m_mesh->setNormals(m_normals); - m_mesh->setStable(true); + points.resize(0); + normals.resize(0); + tris.resize(0); - m_normals.resize(0); - m_vertices.resize(0); + // m_normals.resize(0); + // m_vertices.resize(0); } @@ -649,7 +629,7 @@ bool MeshGenerator::isCutEdge(size_t const& i, size_t const& j, size_t const& k) size_t nz = m_dim.z(); // Assuming edgeCases are all set - size_t edgeCaseIdx = k * (nx - 1) * ny + j * (nx - 1) + i; + size_t edgeCaseIdx = k * ((nx - 1) * ny) + (j * (nx - 1)) + i; unsigned char edgeCase = edgeCases[edgeCaseIdx]; if (edgeCase == 1 || edgeCase == 2) @@ -659,7 +639,7 @@ bool MeshGenerator::isCutEdge(size_t const& i, size_t const& j, size_t const& k) if (j != ny - 1) { - size_t edgeCaseIdxY = k * (nx - 1) * ny + (j + 1) * (nx - 1) + i; + size_t edgeCaseIdxY = (k * (nx - 1) * ny) + ((j + 1) * (nx - 1)) + i; unsigned char edgeCaseY = edgeCases[edgeCaseIdxY]; // If the sum is odd, the edge along the y-axis is cut @@ -671,7 +651,7 @@ bool MeshGenerator::isCutEdge(size_t const& i, size_t const& j, size_t const& k) if (k != nz - 1) { - size_t edgeCaseIdxZ = (k + 1) * (nx - 1) * ny + j * (nx - 1) + i; + size_t edgeCaseIdxZ = ((k + 1) * (nx - 1) * ny) + (j * (nx - 1)) + i; unsigned char edgeCaseZ = edgeCases[edgeCaseIdxZ]; // If the sum is odd, the edge along the z-axis is cut @@ -728,15 +708,10 @@ MeshGenerator::interpolateOnCube( { unsigned char i0 = edgeVertices[edge][0]; unsigned char i1 = edgeVertices[edge][1]; - float weight; - float denom = isovals[i1] - isovals[i0]; - if (fabs(denom) < 1e-9) - weight = 0.5f; - else - weight = (m_iso - isovals[i0]) / denom; - + float weight = (m_iso - isovals[i0]) / (isovals[i1] - isovals[i0]); return interpolate(pts[i0], pts[i1], weight); + } inline std::array diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index afd5f6a688..4fe5e323f5 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -119,6 +119,8 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread size_t& xl, size_t& xr, size_t const& j, size_t const& k) const; + void calculateTotalPoints(); + inline unsigned char calcCubeCase(unsigned char const& ec0, unsigned char const& ec1, unsigned char const& ec2, unsigned char const& ec3) const; @@ -208,7 +210,7 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread std::vector edgeCases; Core::Array points; // Core::Array normals; // The output - Core::Array tris; + std::vector > tris; int m_progmin; int m_progmax; diff --git a/avogadro/qtplugins/meshes/meshes.cpp b/avogadro/qtplugins/meshes/meshes.cpp index 5353a34ff9..a15328e27a 100644 --- a/avogadro/qtplugins/meshes/meshes.cpp +++ b/avogadro/qtplugins/meshes/meshes.cpp @@ -68,12 +68,13 @@ 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); + std::vector > triangles; + triangles = mesh->triangles(); + + + size_t index = 0; + + bool hasColors = (mesh->colors().size() != 0); @@ -81,42 +82,18 @@ void Meshes::process(const QtGui::Molecule& mol, GroupNode& node) geometry->addDrawable(mesh1); mesh1->setOpacity(m_opacity); - if (hasColors) { - auto colors = mesh->colors(); - Core::Array colorsRGB(colors.size()); - for (size_t i = 0; i < colors.size(); i++) - 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()); + 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 - : Rendering::TranslucentPass); + mesh1->addVertices(mesh->vertices(), mesh->normals()); - 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); - mesh2->setRenderPass(m_opacity == 255 ? Rendering::SolidPass - : Rendering::TranslucentPass); - } + mesh1->setRenderPass(m_opacity == 255 ? Rendering::SolidPass + : Rendering::TranslucentPass); } } + void Meshes::setOpacity(int opacity) { m_opacity = 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); /** @} */ From febd8e754878a2754c16a01908167e860a4f75c2 Mon Sep 17 00:00:00 2001 From: Perminder Date: Thu, 7 Nov 2024 04:00:31 +0530 Subject: [PATCH 07/19] minor cleanusp and fixes Signed-off-by: Perminder --- avogadro/core/cube.cpp | 15 ++- avogadro/qtgui/meshgenerator.cpp | 155 ++++++++++++--------------- avogadro/qtgui/meshgenerator.h | 16 +-- avogadro/qtplugins/meshes/meshes.cpp | 36 +++++-- 4 files changed, 111 insertions(+), 111 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index 887a9f1549..dc8e6f80ef 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -33,18 +33,23 @@ std::vector::const_iterator Cube::getRowIter(size_t j, size_t k) const bool Cube::setLimits(const Vector3& min_, const Vector3& max_, const Vector3i& points) { - // We can calculate all necessary properties and initialise our data + // Calculate the maximum dimension + int maxPoints = std::max({points.x(), points.y(), points.z()}); + Vector3i equalPoints(maxPoints, maxPoints, maxPoints); + + // Recalculate spacing based on equal points Vector3 delta = max_ - min_; - m_spacing = - Vector3(delta.x() / (points.x() - 1), delta.y() / (points.y() - 1), - delta.z() / (points.z() - 1)); + m_spacing = Vector3(delta.x() / (equalPoints.x() - 1), + delta.y() / (equalPoints.y() - 1), + delta.z() / (equalPoints.z() - 1)); m_min = min_; m_max = max_; - m_points = points; + m_points = equalPoints; 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_; diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 7982755b13..887579bc89 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -49,16 +49,6 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, m_passes = passes; m_reverseWinding = reverse; - // In BlockMarchFunctor.cpp: - // The volume reader setup happens here with dimensions, origin, and spacing. - // dims = volReader.imageData->getDimension(); - // origin = volReader.imageData->getOrigin(); - // spacing = volReader.imageData->getSpacing(); - - // 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]); @@ -70,7 +60,6 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, triCounter.resize((m_dim.y() - 1) * (m_dim.z() - 1)); - qDebug() << "initialized at first"; m_progmax = m_dim.x(); // Similar to setting up sliceSize and grid traversal boundaries in BlockMarchFunctor.cpp: @@ -86,12 +75,12 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, void MeshGenerator::FlyingEdgesAlgorithmPass1() { // Loop through z-dimension - size_t nx = m_dim.x(); - size_t ny = m_dim.y(); - size_t nz = m_dim.z(); + int nx = m_dim.x(); + int ny = m_dim.y(); + int nz = m_dim.z(); - for(size_t k = 0; k != nz; ++k) { - for(size_t j = 0; j != ny; ++j) + for(int k = 0; k != nz; ++k) { + for(int j = 0; j != ny; ++j) { auto curEdgeCases = edgeCases.begin() + (nx - 1) * (k * ny + j); @@ -114,11 +103,12 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() } } - for(size_t k = 0; k != nz; ++k){ - for(size_t j = 0; j != ny; ++j) + for(int k = 0; k != nz; ++k){ + for(int j = 0; j != ny; ++j) { gridEdge& curGridEdge = gridEdges[k * ny + j]; curGridEdge.xl = m_dim.x(); + for(int i = 1; i != m_dim.x(); ++i) { @@ -138,13 +128,13 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() void MeshGenerator::FlyingEdgesAlgorithmPass2() { - size_t nx = m_dim.x(); - size_t ny = m_dim.y(); - size_t nz = m_dim.z(); - for(size_t k = 0; k != nz - 1; ++k){ - for(size_t j = 0; j != ny - 1; ++j) + int nx = m_dim.x(); + int ny = m_dim.y(); + int nz = m_dim.z(); + for(int k = 0; k != nz - 1; ++k){ + for(int j = 0; j != ny - 1; ++j) { - size_t xl, xr; + int xl, xr; calcTrimValues(xl, xr, j, k); // xl, xr set in this function gridEdge& ge0 = gridEdges[k * ny + j]; @@ -158,7 +148,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() 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 - size_t& curTriCounter = *(triCounter.begin() + k * (ny - 1) + j); + int& curTriCounter = *(triCounter.begin() + k * (ny - 1) + j); auto curCubeCaseIds = cubeCases.begin() + (m_dim.x() - 1) * (k * (m_dim.y() - 1) + j); @@ -168,7 +158,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() - for(size_t i = xl; i != xr; ++i) + for(int i = xl; i != xr; ++i) { bool isXEnd = (i == nx - 2); @@ -226,25 +216,24 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() void MeshGenerator::FlyingEdgesAlgorithmPass3() { - // qDebug() << "pass 3 started"; - size_t tmp; - size_t triAccum = 0; - size_t nx = m_dim.x(); - size_t ny = m_dim.y(); - size_t nz = m_dim.z(); - for(size_t k = 0; k != nz -1; ++k) { - for(size_t j = 0; j != ny-1; ++j) + int tmp; + int triAccum = 0; + int nx = m_dim.x(); + int ny = m_dim.y(); + int nz = m_dim.z(); + for(int k = 0; k != nz -1; ++k) { + for(int j = 0; j != ny-1; ++j) { - size_t& curTriCounter = triCounter[k*(ny-1)+j]; + int& curTriCounter = triCounter[k*(ny-1)+j]; tmp = curTriCounter; curTriCounter = triAccum; triAccum += tmp; }} - size_t pointAccum = 0; - for(size_t k = 0; k != nz; ++k) { - for(size_t j = 0; j != ny; ++j) + int pointAccum = 0; + for(int k = 0; k != nz; ++k) { + for(int j = 0; j != ny; ++j) { gridEdge& curGridEdge = gridEdges[(k * ny) + j]; @@ -269,21 +258,21 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() void MeshGenerator::FlyingEdgesAlgorithmPass4() { - size_t nx = m_dim.x(); - size_t ny = m_dim.y(); - size_t nz = m_dim.z(); + int nx = m_dim.x(); + int ny = m_dim.y(); + int nz = m_dim.z(); - for(size_t k = 0; k != nz -1; ++k) { - for(size_t j = 0; j != ny-1; ++j) + for(int k = 0; k != nz -1; ++k) { + for(int j = 0; j != ny-1; ++j) { // find adjusted trim values - size_t xl, xr; + int xl, xr; calcTrimValues(xl, xr, j, k); // xl, xr set in this function if(xl == xr) continue; - size_t triIdx = triCounter[(k*(ny-1)) + j]; + int triIdx = triCounter[(k*(ny-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]; @@ -291,22 +280,22 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() gridEdge const& ge2 = gridEdges[(k+1)* m_dim.y() + j]; gridEdge const& ge3 = gridEdges[(k+1)* m_dim.y() + j + 1]; - size_t x0counter = 0; - size_t y0counter = 0; - size_t z0counter = 0; + int x0counter = 0; + int y0counter = 0; + int z0counter = 0; - size_t x1counter = 0; - size_t z1counter = 0; + int x1counter = 0; + int z1counter = 0; - size_t x2counter = 0; - size_t y2counter = 0; + int x2counter = 0; + int y2counter = 0; - size_t x3counter = 0; + int x3counter = 0; bool isYEnd = (j == ny-2); bool isZEnd = (k == nz-2); - for(size_t i = xl; i != xr; ++i) + for(int i = xl; i != xr; ++i) { bool isXEnd = (i == nx-2); @@ -324,12 +313,12 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() // Add Points and normals. // Calculate global indices for triangles - std::array globalIdxs; + std::array globalIdxs; if(isCutCase[0]) { // points-> array - size_t idx = ge0.xstart + x0counter; + int idx = ge0.xstart + x0counter; std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 0); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 0); @@ -341,7 +330,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[3]) { - size_t idx = ge0.ystart + y0counter; + int idx = ge0.ystart + y0counter; std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 3); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 3); points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); @@ -352,7 +341,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[8]) { - size_t idx = ge0.zstart + z0counter; + int idx = ge0.zstart + z0counter; std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 8); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 8); points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); @@ -363,7 +352,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[1]) { - size_t idx = ge0.ystart + y0counter; + int idx = ge0.ystart + y0counter; if(isXEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 1); @@ -378,7 +367,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[9]) { - size_t idx = ge0.zstart + z0counter; + int idx = ge0.zstart + z0counter; if(isXEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 9); @@ -392,7 +381,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[2]) { - size_t idx = ge1.xstart + x1counter; + int idx = ge1.xstart + x1counter; if(isYEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 2); @@ -406,7 +395,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[10]) { - size_t idx = ge1.zstart + z1counter; + int idx = ge1.zstart + z1counter; if(isYEnd) { @@ -422,7 +411,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[4]) { - size_t idx = ge2.xstart + x2counter; + int idx = ge2.xstart + x2counter; if(isZEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 4); @@ -438,7 +427,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[7]) { - size_t idx = ge2.ystart + y2counter; + int idx = ge2.ystart + y2counter; if(isZEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 7); @@ -454,7 +443,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[11]) { - size_t idx = ge1.zstart + z1counter; + int idx = ge1.zstart + z1counter; if(isXEnd and isYEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 11); @@ -469,7 +458,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[5]) { - size_t idx = ge2.ystart + y2counter; + int idx = ge2.ystart + y2counter; if(isXEnd and isZEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 5); @@ -485,7 +474,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[6]) { - size_t idx = ge3.xstart + x3counter; + int idx = ge3.xstart + x3counter; if(isYEnd and isZEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 6); @@ -514,6 +503,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() void MeshGenerator::run() { + if (!m_cube || !m_mesh) { qDebug() << "No mesh or cube set - nothing to find isosurface of…"; return; @@ -522,33 +512,22 @@ void MeshGenerator::run() m_mesh->setStable(false); m_mesh->clear(); - // m_verticesear(); FlyingEdgesAlgorithmPass1(); FlyingEdgesAlgorithmPass2(); FlyingEdgesAlgorithmPass3(); FlyingEdgesAlgorithmPass4(); - - qDebug() << "size-point" << m_dim.x(); - // qDebug - qDebug() << "size-normals" << m_dim.y(); - qDebug() << "tris" << m_dim.z(); m_mesh->setVertices(points); m_mesh->setNormals(normals); m_mesh->setTriangles(tris); m_mesh->setStable(true); - points.resize(0); normals.resize(0); tris.resize(0); - // m_normals.resize(0); - // m_vertices.resize(0); - - } @@ -622,14 +601,14 @@ unsigned char MeshGenerator::calcCubeCase( } -bool MeshGenerator::isCutEdge(size_t const& i, size_t const& j, size_t const& k) const +bool MeshGenerator::isCutEdge(int const& i, int const& j, int const& k) const { - size_t nx = m_dim.x(); - size_t ny = m_dim.y(); - size_t nz = m_dim.z(); + int nx = m_dim.x(); + int ny = m_dim.y(); + int nz = m_dim.z(); // Assuming edgeCases are all set - size_t edgeCaseIdx = k * ((nx - 1) * ny) + (j * (nx - 1)) + i; + int edgeCaseIdx = k * ((nx - 1) * ny) + (j * (nx - 1)) + i; unsigned char edgeCase = edgeCases[edgeCaseIdx]; if (edgeCase == 1 || edgeCase == 2) @@ -639,7 +618,7 @@ bool MeshGenerator::isCutEdge(size_t const& i, size_t const& j, size_t const& k) if (j != ny - 1) { - size_t edgeCaseIdxY = (k * (nx - 1) * ny) + ((j + 1) * (nx - 1)) + i; + int edgeCaseIdxY = (k * (nx - 1) * ny) + ((j + 1) * (nx - 1)) + i; unsigned char edgeCaseY = edgeCases[edgeCaseIdxY]; // If the sum is odd, the edge along the y-axis is cut @@ -651,17 +630,15 @@ bool MeshGenerator::isCutEdge(size_t const& i, size_t const& j, size_t const& k) if (k != nz - 1) { - size_t edgeCaseIdxZ = ((k + 1) * (nx - 1) * ny) + (j * (nx - 1)) + i; + int edgeCaseIdxZ = ((k + 1) * (nx - 1) * ny) + (j * (nx - 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) { - // qDebug() << "true return krega"; return true; } } - // qDebug() << "false return krega"; return false; } @@ -683,9 +660,9 @@ unsigned char MeshGenerator::calcCaseEdge(bool const& prevEdge, bool const& curr } // 2000 -void MeshGenerator::calcTrimValues(size_t& xl, size_t& xr, size_t const& j, size_t const& k) const +void MeshGenerator::calcTrimValues(int& xl, int& xr, int const& j, int const& k) const { - size_t ny = m_dim.y(); + int ny = m_dim.y(); const gridEdge& ge0 = gridEdges[k * ny + j]; const gridEdge& ge1 = gridEdges[k * ny + j + 1]; diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index 4fe5e323f5..4d36fc2b4d 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -93,14 +93,14 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread // trim values // set on pass 1 - size_t xl; - size_t xr; + int xl; + int xr; // modified on pass 2 // set on pass 3 - size_t xstart; - size_t ystart; - size_t zstart; + int xstart; + int ystart; + int zstart; }; @@ -116,7 +116,7 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread const Core::Cube* cube() const { return m_cube; } inline void calcTrimValues( - size_t& xl, size_t& xr, size_t const& j, size_t const& k) const; + int& xl, int& xr, int const& j, int const& k) const; void calculateTotalPoints(); @@ -175,7 +175,7 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread */ bool marchingCube(const Vector3i& pos); - bool isCutEdge(size_t const& i, size_t const& j, size_t const& k) const; + bool isCutEdge(int const& i, int const& j, int const& k) const; inline std::array interpolateOnCube( std::array, 8> const& pts, @@ -206,7 +206,7 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread std::vector gridEdges; std::vector cubeCases; // size (nx-1)*(ny-1)*(nz-1) - std::vector triCounter; // size of (ny-1)*(nz-1) + std::vector triCounter; // size of (ny-1)*(nz-1) std::vector edgeCases; Core::Array points; // Core::Array normals; // The output diff --git a/avogadro/qtplugins/meshes/meshes.cpp b/avogadro/qtplugins/meshes/meshes.cpp index a15328e27a..9738e7ec7f 100644 --- a/avogadro/qtplugins/meshes/meshes.cpp +++ b/avogadro/qtplugins/meshes/meshes.cpp @@ -72,26 +72,44 @@ void Meshes::process(const QtGui::Molecule& mol, GroupNode& node) triangles = mesh->triangles(); - size_t index = 0; - - - bool hasColors = (mesh->colors().size() != 0); auto* mesh1 = new MeshGeometry; geometry->addDrawable(mesh1); mesh1->setOpacity(m_opacity); - - mesh1->setColor(m_color1); + if (hasColors) { + auto colors = mesh->colors(); + Core::Array colorsRGB(colors.size()); + for (size_t i = 0; i < colors.size(); i++) + colorsRGB[i] = Vector3ub(colors[i].red() * 255, colors[i].green() * 255, + colors[i].blue() * 255); + mesh1->addVertices(mesh->vertices(), mesh->normals(), colorsRGB); + } 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->addVertices(mesh->vertices(), mesh->normals()); - mesh1->setRenderPass(m_opacity == 255 ? Rendering::SolidPass : Rendering::TranslucentPass); + + if (mol.meshCount() >= 2) { // it's a molecular orbital, two parts + + auto* mesh2 = new MeshGeometry; + geometry->addDrawable(mesh2); + mesh = mol.mesh(1); + mesh2->setColor(m_color2); + mesh2->setOpacity(m_opacity); + mesh2->addVertices(mesh->vertices(), mesh->normals()); + 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) From 46ca336ceb853755bfdc11ed6b62ea0e54b380b3 Mon Sep 17 00:00:00 2001 From: Perminder Date: Thu, 7 Nov 2024 04:18:02 +0530 Subject: [PATCH 08/19] remove helper comments Signed-off-by: Perminder --- avogadro/qtgui/meshgenerator.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 887579bc89..ef16693258 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -62,16 +62,9 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, m_progmax = m_dim.x(); - // Similar to setting up sliceSize and grid traversal boundaries in BlockMarchFunctor.cpp: - // sliceSize = dims[0] * dims[1]; - - // m_cube->lock()->unlock(); return true; } -// TODO: nx ko chhod do m_dim.x() hi rkho aur loop me use kro int use krke -// doosra cheez...baaki sab theek ho jayega - void MeshGenerator::FlyingEdgesAlgorithmPass1() { // Loop through z-dimension @@ -512,7 +505,6 @@ void MeshGenerator::run() m_mesh->setStable(false); m_mesh->clear(); - // m_verticesear(); FlyingEdgesAlgorithmPass1(); FlyingEdgesAlgorithmPass2(); @@ -531,7 +523,6 @@ void MeshGenerator::run() } - void MeshGenerator::clear() { m_iso = 0.0; @@ -564,11 +555,6 @@ inline float MeshGenerator::offset(float val1, float val2) return (m_iso - val1) / (val2 - val1); } -// This function is similar to interpolating positions in BlockMarchFunctor.cpp: -// In BlockMarchFunctor.cpp: -// T w = (isoval - val[v1]) / (val[v2] - val[v1]); -// Interpolation using lerp() function - unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) { // FIXME Not implemented yet. From f37cd3633a6f90d8760490f08ed6260f2a89173c Mon Sep 17 00:00:00 2001 From: Perminder Date: Sun, 10 Nov 2024 06:13:37 +0530 Subject: [PATCH 09/19] fixing laplace smoothing, only cleanups left Signed-off-by: Perminder --- avogadro/core/cube.cpp | 22 ++-- avogadro/core/cube.h | 12 +-- avogadro/core/mesh.cpp | 146 +++++++++++---------------- avogadro/core/mesh.h | 6 +- avogadro/qtgui/meshgenerator.cpp | 2 +- avogadro/qtgui/meshgenerator.h | 2 +- avogadro/qtplugins/meshes/meshes.cpp | 3 +- 7 files changed, 85 insertions(+), 108 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index dc8e6f80ef..ce3facb8fc 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -24,7 +24,7 @@ Cube::~Cube() m_lock = nullptr; } -std::vector::const_iterator Cube::getRowIter(size_t j, size_t k) const +std::vector::const_iterator Cube::getRowIter(int j, int k) const { return m_data.cbegin() + m_points.x() * (k * m_points.y() + j); } @@ -206,12 +206,12 @@ float Cube::value(int i, int j, int k) const return 0.0; } -std::array Cube::computeGradient(size_t i, size_t j, size_t k) const +std::array Cube::computeGradient(int i, int j, int k) const { std::array, 3> x; std::array run; - size_t dataIdx = i + (j * m_points.x()) + (k * m_points.x() * m_points.y()); + int dataIdx = i + (j * m_points.x()) + (k * m_points.x() * m_points.y()); // std::cout << m_spacing[0]; if (i == 0) @@ -281,7 +281,7 @@ std::array Cube::computeGradient(size_t i, size_t j, size_t k) const } std::array, 8> -Cube::getGradCube(size_t i, size_t j, size_t k) const +Cube::getGradCube(int i, int j, int k) const { std::array, 8> grad; @@ -297,11 +297,11 @@ Cube::getGradCube(size_t i, size_t j, size_t k) const return grad; } -std::array Cube::getValsCube(size_t i, size_t j, size_t k) const +std::array Cube::getValsCube(int i, int j, int k) const { std::array vals; - size_t idx = i + (j * m_points.x()) + (k * m_points.x() * m_points.y()); + int idx = i + (j * m_points.x()) + (k * m_points.x() * m_points.y()); vals[0] = getData(i, j, k); vals[1] = getData(i + 1, j, k); @@ -317,20 +317,20 @@ std::array Cube::getValsCube(size_t i, size_t j, size_t k) const inline float -Cube::getData(size_t i, size_t j, size_t k) const +Cube::getData(int i, int j, int k) const { return m_data[(k * m_points.x() * m_points.y()) + (j * m_points.x()) + i]; } -std::array, 8> Cube::getPosCube(size_t i, size_t j, size_t k) const +std::array, 8> Cube::getPosCube(int i, int j, int k) const { std::array, 8> pos; // std::cout<< m_spacing.x(); - float xpos = m_min.x() + i * m_spacing.y(); - float ypos = m_min.y() + j * m_spacing.x(); - float zpos = m_min.z() + k * m_spacing.z(); + 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; diff --git a/avogadro/core/cube.h b/avogadro/core/cube.h index 1245a9def0..359a43d5da 100644 --- a/avogadro/core/cube.h +++ b/avogadro/core/cube.h @@ -135,7 +135,7 @@ class AVOGADROCORE_EXPORT Cube /** * @return Const iterator to the beginning of a specific row in the cube data. */ - std::vector::const_iterator getRowIter(size_t j, size_t k) const; + std::vector::const_iterator getRowIter(int j, int k) const; /** * @return Index of the point closest to the position supplied. @@ -247,7 +247,7 @@ class AVOGADROCORE_EXPORT Cube * @param k z index * @return Gradient vector at the specified point. */ - std::array computeGradient(size_t i, size_t j, size_t k) const; + std::array computeGradient(int i, int j, int k) const; /** * Get the values of the eight corners of a cube cell. @@ -256,10 +256,10 @@ class AVOGADROCORE_EXPORT Cube * @param k z index * @return Array of values at the eight corners. */ - std::array getValsCube(size_t i, size_t j, size_t k) const; + std::array getValsCube(int i, int j, int k) const; - std::array, 8> getGradCube(size_t i, size_t j, size_t k) const; + std::array, 8> getGradCube(int i, int j, int k) const; /** * Get the data value at the specified indices. * @param i x index @@ -267,7 +267,7 @@ class AVOGADROCORE_EXPORT Cube * @param k z index * @return Value at the specified indices. */ - float getData(size_t i, size_t j, size_t k) const; + float getData(int i, int j, int k) const; /** * Get the positions of the eight corners of a cube cell. @@ -276,7 +276,7 @@ class AVOGADROCORE_EXPORT Cube * @param k z index * @return Array of positions at the eight corners. */ -std::array, 8> getPosCube(size_t i, size_t j, size_t k) const; +std::array, 8> getPosCube(int i, int j, int k) const; protected: std::vector m_data; diff --git a/avogadro/core/mesh.cpp b/avogadro/core/mesh.cpp index fc13cc875d..eda48f0258 100644 --- a/avogadro/core/mesh.cpp +++ b/avogadro/core/mesh.cpp @@ -23,7 +23,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), tris(other.tris) { } @@ -63,14 +63,14 @@ const Vector3f* Mesh::vertex(int n) const } -bool Mesh::setTriangles(const std::vector >& values) +bool Mesh::setTriangles(const Core::Array& values) { tris.clear(); tris = values; return true; } -const std::vector >& Mesh::triangles() const +const Core::Array&Mesh::triangles() const { return tris; } @@ -187,102 +187,78 @@ Mesh& Mesh::operator=(const Mesh& other) m_colors = other.m_colors; m_name = other.m_name; m_isoValue = other.m_isoValue; + tris = other.tris; 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 : tris) { + 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 : tris) { + 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(); } } - } // End namespace Avogadro diff --git a/avogadro/core/mesh.h b/avogadro/core/mesh.h index 5c6b8819b8..a19deecf88 100644 --- a/avogadro/core/mesh.h +++ b/avogadro/core/mesh.h @@ -122,8 +122,8 @@ class AVOGADROCORE_EXPORT Mesh */ const Vector3f* vertex(int n) const; - bool setTriangles(const std::vector >& values); - const std::vector >& triangles() const; + bool setTriangles(const Core::Array& values); + const Core::Array& triangles() const; /** @@ -232,7 +232,7 @@ class AVOGADROCORE_EXPORT Mesh Core::Array m_vertices; Core::Array m_normals; Core::Array m_colors; - std::vector > tris; + Core::Array tris; std::string m_name; bool m_stable; float m_isoValue; diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index ef16693258..796acd98eb 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -208,7 +208,6 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() void MeshGenerator::FlyingEdgesAlgorithmPass3() { - int tmp; int triAccum = 0; int nx = m_dim.x(); @@ -514,6 +513,7 @@ void MeshGenerator::run() m_mesh->setVertices(points); m_mesh->setNormals(normals); m_mesh->setTriangles(tris); + m_mesh->smooth(m_passes); m_mesh->setStable(true); points.resize(0); diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index 4d36fc2b4d..fb38199151 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -210,7 +210,7 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread std::vector edgeCases; Core::Array points; // Core::Array normals; // The output - std::vector > tris; + Core::Array tris; int m_progmin; int m_progmax; diff --git a/avogadro/qtplugins/meshes/meshes.cpp b/avogadro/qtplugins/meshes/meshes.cpp index 9738e7ec7f..be15055060 100644 --- a/avogadro/qtplugins/meshes/meshes.cpp +++ b/avogadro/qtplugins/meshes/meshes.cpp @@ -68,7 +68,8 @@ void Meshes::process(const QtGui::Molecule& mol, GroupNode& node) const Mesh* mesh = mol.mesh(0); - std::vector > triangles; + Core::Array triangles; + triangles = mesh->triangles(); From 6507df7db4c3a5e058ec7595cf098771560acabb Mon Sep 17 00:00:00 2001 From: Perminder Date: Sun, 10 Nov 2024 07:04:07 +0530 Subject: [PATCH 10/19] cleanups in the code done, still needs to remove unused functions and variables Signed-off-by: Perminder --- avogadro/core/cube.h | 3 +- avogadro/qtgui/meshgenerator.cpp | 90 +++++++++++++------------------- avogadro/qtgui/meshgenerator.h | 78 ++++++++++++++++++--------- 3 files changed, 93 insertions(+), 78 deletions(-) diff --git a/avogadro/core/cube.h b/avogadro/core/cube.h index 359a43d5da..afafec6267 100644 --- a/avogadro/core/cube.h +++ b/avogadro/core/cube.h @@ -259,7 +259,8 @@ class AVOGADROCORE_EXPORT Cube std::array getValsCube(int i, int j, int k) const; - std::array, 8> getGradCube(int i, int j, int k) const; + std::array, 8> getGradCube(int i, int j, int k) const; + /** * Get the data value at the specified indices. * @param i x index diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 796acd98eb..b6959b6fd9 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -68,15 +68,12 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, void MeshGenerator::FlyingEdgesAlgorithmPass1() { // Loop through z-dimension - int nx = m_dim.x(); - int ny = m_dim.y(); - int nz = m_dim.z(); - for(int k = 0; k != nz; ++k) { - for(int j = 0; j != ny; ++j) + for(int k = 0; k != m_dim.z(); ++k) { + for(int j = 0; j != m_dim.y(); ++j) { - auto curEdgeCases = edgeCases.begin() + (nx - 1) * (k * ny + j); + auto curEdgeCases = edgeCases.begin() + (m_dim.x() - 1) * (k * m_dim.y() + j); auto curPointValues = m_cube->getRowIter(j, k); @@ -96,10 +93,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() } } - for(int k = 0; k != nz; ++k){ - for(int j = 0; j != ny; ++j) + for(int k = 0; k != m_dim.z(); ++k){ + for(int j = 0; j != m_dim.y(); ++j) { - gridEdge& curGridEdge = gridEdges[k * ny + j]; + gridEdge& curGridEdge = gridEdges[k * m_dim.y() + j]; curGridEdge.xl = m_dim.x(); @@ -121,19 +118,16 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() void MeshGenerator::FlyingEdgesAlgorithmPass2() { - int nx = m_dim.x(); - int ny = m_dim.y(); - int nz = m_dim.z(); - for(int k = 0; k != nz - 1; ++k){ - for(int j = 0; j != ny - 1; ++j) + 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 * ny + j]; - gridEdge& ge1 = gridEdges[k* ny +j + 1]; - gridEdge& ge2 = gridEdges[(k+1) * ny + j]; - gridEdge& ge3 = gridEdges[(k+1) * ny + j + 1]; + 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); @@ -141,19 +135,19 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() 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 * (ny - 1) + j); + 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 == ny - 2); - bool isZEnd = (k == nz - 2); + bool isYEnd = (j == m_dim.y() - 2); + bool isZEnd = (k == m_dim.z() - 2); for(int i = xl; i != xr; ++i) { - bool isXEnd = (i == nx - 2); + 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; @@ -210,13 +204,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() { int tmp; int triAccum = 0; - int nx = m_dim.x(); - int ny = m_dim.y(); - int nz = m_dim.z(); - for(int k = 0; k != nz -1; ++k) { - for(int j = 0; j != ny-1; ++j) + for(int k = 0; k != m_dim.z() -1; ++k) { + for(int j = 0; j != m_dim.y()-1; ++j) { - int& curTriCounter = triCounter[k*(ny-1)+j]; + int& curTriCounter = triCounter[k*(m_dim.y()-1)+j]; tmp = curTriCounter; curTriCounter = triAccum; @@ -224,10 +215,10 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() }} int pointAccum = 0; - for(int k = 0; k != nz; ++k) { - for(int j = 0; j != ny; ++j) + for(int k = 0; k != m_dim.z(); ++k) { + for(int j = 0; j != m_dim.y(); ++j) { - gridEdge& curGridEdge = gridEdges[(k * ny) + j]; + gridEdge& curGridEdge = gridEdges[(k * m_dim.y()) + j]; tmp = curGridEdge.xstart; curGridEdge.xstart = pointAccum; @@ -250,12 +241,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() void MeshGenerator::FlyingEdgesAlgorithmPass4() { - int nx = m_dim.x(); - int ny = m_dim.y(); - int nz = m_dim.z(); - for(int k = 0; k != nz -1; ++k) { - for(int j = 0; j != ny-1; ++j) + 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; @@ -264,7 +252,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(xl == xr) continue; - int triIdx = triCounter[(k*(ny-1)) + j]; + 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]; @@ -284,12 +272,12 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() int x3counter = 0; - bool isYEnd = (j == ny-2); - bool isZEnd = (k == nz-2); + bool isYEnd = (j == m_dim.y()-2); + bool isZEnd = (k == m_dim.z()-2); for(int i = xl; i != xr; ++i) { - bool isXEnd = (i == nx-2); + bool isXEnd = (i == m_dim.x()-2); unsigned char caseId = curCubeCaseIds[i]; @@ -589,12 +577,9 @@ unsigned char MeshGenerator::calcCubeCase( bool MeshGenerator::isCutEdge(int const& i, int const& j, int const& k) const { - int nx = m_dim.x(); - int ny = m_dim.y(); - int nz = m_dim.z(); // Assuming edgeCases are all set - int edgeCaseIdx = k * ((nx - 1) * ny) + (j * (nx - 1)) + i; + 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) @@ -602,9 +587,9 @@ bool MeshGenerator::isCutEdge(int const& i, int const& j, int const& k) const return true; } - if (j != ny - 1) + if (j != m_dim.y() - 1) { - int edgeCaseIdxY = (k * (nx - 1) * ny) + ((j + 1) * (nx - 1)) + i; + 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 @@ -614,9 +599,9 @@ bool MeshGenerator::isCutEdge(int const& i, int const& j, int const& k) const } } - if (k != nz - 1) + if (k != m_dim.z() - 1) { - int edgeCaseIdxZ = ((k + 1) * (nx - 1) * ny) + (j * (nx - 1)) + i; + 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 @@ -648,12 +633,11 @@ unsigned char MeshGenerator::calcCaseEdge(bool const& prevEdge, bool const& curr // 2000 void MeshGenerator::calcTrimValues(int& xl, int& xr, int const& j, int const& k) const { - int ny = m_dim.y(); - const gridEdge& ge0 = gridEdges[k * ny + j]; - const gridEdge& ge1 = gridEdges[k * ny + j + 1]; - const gridEdge& ge2 = gridEdges[(k + 1) * ny + j]; - const gridEdge& ge3 = gridEdges[(k + 1) * ny + j + 1]; + 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]; xl = std::min({ge0.xl, ge1.xl, ge2.xl, ge3.xl}); xr = std::max({ge0.xr, ge1.xr, ge2.xr, ge3.xr}); diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index fb38199151..32f8157410 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -81,6 +81,10 @@ 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() @@ -104,10 +108,29 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread }; - + /** + * 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(); /** @@ -115,12 +138,16 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread */ 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; - - void calculateTotalPoints(); - + /** + * 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; @@ -146,6 +173,7 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread int progressMaximum() { return m_progmax; } signals: + /** * The current value of the calculation's progress. */ @@ -171,22 +199,32 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread unsigned long duplicate(const Vector3i& c, const Vector3f& pos); /** - * Perform a marching cubes step on a single cube. - */ - bool marchingCube(const Vector3i& pos); - + * 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; + /** + * 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; + /** + * 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. */ @@ -198,26 +236,18 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread Vector3f m_min; /** The minimum point in the cube. */ Vector3i m_dim; /** The dimensions of the cube. */ - std::array, 8> cube_t; - std::array scalarCube_t; - - Core::Array m_vertices, m_normals; - Core::Array m_indices; - std::vector gridEdges; - std::vector cubeCases; // size (nx-1)*(ny-1)*(nz-1) - - std::vector triCounter; // size of (ny-1)*(nz-1) - std::vector edgeCases; - Core::Array points; // - Core::Array normals; // The output - Core::Array tris; + Core::Array points, normals; + 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 tris; // 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 unsigned char numTris[256]; static const bool isCut[256][12]; From 63324fecd423c648caa8fdc480c27c90fa81f065 Mon Sep 17 00:00:00 2001 From: Perminder Date: Sun, 10 Nov 2024 07:14:25 +0530 Subject: [PATCH 11/19] minor fixes Signed-off-by: Perminder --- avogadro/core/cube.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index ce3facb8fc..b9f8dabf11 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -300,9 +300,7 @@ Cube::getGradCube(int i, int j, int k) const std::array Cube::getValsCube(int i, int j, int k) const { std::array vals; - - int idx = i + (j * m_points.x()) + (k * m_points.x() * m_points.y()); - + vals[0] = getData(i, j, k); vals[1] = getData(i + 1, j, k); vals[2] = getData(i + 1, j + 1, k); @@ -327,7 +325,6 @@ std::array, 8> Cube::getPosCube(int i, int j, int k) const { std::array, 8> pos; - // std::cout<< m_spacing.x(); 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()); From 6afb548e37c3a5291247e8ed9fa1839a0c5ab67c Mon Sep 17 00:00:00 2001 From: Perminder Date: Sun, 10 Nov 2024 07:18:56 +0530 Subject: [PATCH 12/19] minor cleaning Signed-off-by: Perminder --- avogadro/core/cube.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/avogadro/core/cube.h b/avogadro/core/cube.h index afafec6267..8426cb0863 100644 --- a/avogadro/core/cube.h +++ b/avogadro/core/cube.h @@ -13,7 +13,7 @@ #include "vector.h" #include -#include // Include this for std::array +#include namespace Avogadro { namespace Core { @@ -239,7 +239,6 @@ class AVOGADROCORE_EXPORT Cube */ Mutex* lock() const { return m_lock; } - // Add declarations for the functions defined in cube.cpp /** * Compute the gradient at a specific point in the cube. * @param i x index @@ -284,7 +283,6 @@ std::array, 8> getPosCube(int i, int j, int k) const; Vector3 m_min, m_max, m_spacing; Vector3i m_points; float m_minValue, m_maxValue; - // Removed conflicting 'data' member variable std::string m_name; Type m_cubeType; Mutex* m_lock; From ca76e51b622cea5a683a48286d6848a1b64f91b5 Mon Sep 17 00:00:00 2001 From: Perminder Date: Tue, 12 Nov 2024 15:41:52 +0530 Subject: [PATCH 13/19] fix-indexing-issue Signed-off-by: Perminder --- avogadro/core/cube.cpp | 115 ++++++++++++++----------------- avogadro/qtgui/meshgenerator.cpp | 32 +++------ 2 files changed, 62 insertions(+), 85 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index b9f8dabf11..868cdaea35 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -24,27 +24,23 @@ Cube::~Cube() m_lock = nullptr; } -std::vector::const_iterator Cube::getRowIter(int j, int k) const -{ - return m_data.cbegin() + m_points.x() * (k * m_points.y() + j); -} +// std::vector::const_iterator Cube::getRowIter(int j, int k) const +// { +// return m_data.cbegin() + m_points.z() * k * m_points.y() + m_points.z() * j; +// } bool Cube::setLimits(const Vector3& min_, const Vector3& max_, const Vector3i& points) { - // Calculate the maximum dimension - int maxPoints = std::max({points.x(), points.y(), points.z()}); - Vector3i equalPoints(maxPoints, maxPoints, maxPoints); - - // Recalculate spacing based on equal points + // We can calculate all necessary properties and initialise our data Vector3 delta = max_ - min_; - m_spacing = Vector3(delta.x() / (equalPoints.x() - 1), - delta.y() / (equalPoints.y() - 1), - delta.z() / (equalPoints.z() - 1)); + m_spacing = + Vector3(delta.x() / (points.x() - 1), delta.y() / (points.y() - 1), + delta.z() / (points.z() - 1)); m_min = min_; m_max = max_; - m_points = equalPoints; + m_points = points; m_data.resize(m_points.x() * m_points.y() * m_points.z()); return true; } @@ -205,69 +201,58 @@ float Cube::value(int i, int j, int k) const else return 0.0; } - 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; - int dataIdx = i + (j * m_points.x()) + (k * m_points.x() * m_points.y()); - - // std::cout << m_spacing[0]; - if (i == 0) - { - x[0][0] = m_data[dataIdx + 1]; - x[0][1] = m_data[dataIdx]; + // X-direction + if (i == 0) { + x[0][0] = m_data[dataIdx + ny * nz]; // (i+1, j, k) + x[0][1] = m_data[dataIdx]; // (i, j, k) run[0] = m_spacing.x(); - } - else if (i == (m_points.x() - 1)) - { - x[0][0] = m_data[dataIdx]; - x[0][1] = m_data[dataIdx - 1]; + } else if (i == (nx - 1)) { + x[0][0] = m_data[dataIdx]; // (i, j, k) + x[0][1] = m_data[dataIdx - ny * nz]; // (i-1, j, k) run[0] = m_spacing.x(); - } - else - { - x[0][0] = m_data[dataIdx + 1]; - x[0][1] = m_data[dataIdx - 1]; + } else { + x[0][0] = m_data[dataIdx + ny * nz]; // (i+1, j, k) + x[0][1] = m_data[dataIdx - ny * nz]; // (i-1, j, k) run[0] = 2 * m_spacing.x(); } - if (j == 0) - { - x[1][0] = m_data[dataIdx + m_points.x()]; - x[1][1] = m_data[dataIdx]; + // Y-direction + if (j == 0) { + x[1][0] = m_data[dataIdx + nz]; // (i, j+1, k) + x[1][1] = m_data[dataIdx]; // (i, j, k) run[1] = m_spacing.y(); - } - else if (j == (m_points.y() - 1)) - { - x[1][0] = m_data[dataIdx]; - x[1][1] = m_data[dataIdx - m_points.x()]; + } else if (j == (ny - 1)) { + x[1][0] = m_data[dataIdx]; // (i, j, k) + x[1][1] = m_data[dataIdx - nz]; // (i, j-1, k) run[1] = m_spacing.y(); - } - else - { - x[1][0] = m_data[dataIdx + m_points.x()]; - x[1][1] = m_data[dataIdx - m_points.x()]; + } else { + x[1][0] = m_data[dataIdx + nz]; // (i, j+1, k) + x[1][1] = m_data[dataIdx - nz]; // (i, j-1, k) run[1] = 2 * m_spacing.y(); } - if (k == 0) - { - x[2][0] = m_data[dataIdx + (m_points.x() * m_points.y())]; - x[2][1] = m_data[dataIdx]; + // Z-direction + if (k == 0) { + x[2][0] = m_data[dataIdx + 1]; // (i, j, k+1) + x[2][1] = m_data[dataIdx]; // (i, j, k) run[2] = m_spacing.z(); - } - else if (k == (m_points.z() - 1)) - { - x[2][0] = m_data[dataIdx]; - x[2][1] = m_data[dataIdx - (m_points.x() * m_points.y())]; + } else if (k == (nz - 1)) { + x[2][0] = m_data[dataIdx]; // (i, j, k) + x[2][1] = m_data[dataIdx - 1]; // (i, j, k-1) run[2] = m_spacing.z(); - } - else - { - x[2][0] = m_data[dataIdx + (m_points.x() * m_points.y())]; - x[2][1] = m_data[dataIdx - (m_points.x() * m_points.y())]; + } else { + x[2][0] = m_data[dataIdx + 1]; // (i, j, k+1) + x[2][1] = m_data[dataIdx - 1]; // (i, j, k-1) run[2] = 2 * m_spacing.z(); } @@ -314,10 +299,12 @@ std::array Cube::getValsCube(int i, int j, int k) const } -inline float -Cube::getData(int i, int j, int k) const +inline float Cube::getData(int i, int j, int k) const { - return m_data[(k * m_points.x() * m_points.y()) + (j * m_points.x()) + i]; + int nx = m_points.x(); + int ny = m_points.y(); + int nz = m_points.z(); + return m_data[(i * ny * nz) + (j * nz) + k]; } @@ -366,7 +353,7 @@ std::array, 8> Cube::getPosCube(int i, int j, int k) const } 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()) @@ -465,4 +452,4 @@ bool Cube::fillStripe( return true; } -} // End Avogadro namespace +} // End Avogadro namespace \ No newline at end of file diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index b6959b6fd9..37813b1bd8 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -69,29 +69,19 @@ void MeshGenerator::FlyingEdgesAlgorithmPass1() { // Loop through z-dimension - 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); - - auto curPointValues = m_cube->getRowIter(j, k); - - // Initialize the isGE array to track isosurface crossings - std::array isGE; - isGE[0] = (curPointValues[0] >= m_iso); // first element initialization - - // loop through x-dimension - for(int i = 1; i != m_dim.x(); ++i) - { - // update isGE for the current point + for (int k = 0; k != m_dim.z(); ++k) { + for (int j = 0; j != m_dim.y(); ++j) { - isGE[i % 2] = (curPointValues[i] >= m_iso); + 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); - curEdgeCases[i-1] = calcCaseEdge(isGE[(i+1)%2], isGE[i%2]); + 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) @@ -471,6 +461,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() const char* caseTri = caseTriangles[caseId]; // size 16 for(int idx = 0; caseTri[idx] != -1; idx += 3) { + tris[triIdx][0] = globalIdxs[caseTri[idx]]; tris[triIdx][1] = globalIdxs[caseTri[idx+1]]; tris[triIdx][2] = globalIdxs[caseTri[idx+2]]; @@ -488,7 +479,6 @@ void MeshGenerator::run() qDebug() << "No mesh or cube set - nothing to find isosurface of…"; return; } - m_mesh->setStable(false); m_mesh->clear(); From 8de667a79ee16368e3ceae0c8532513f10b2cc70 Mon Sep 17 00:00:00 2001 From: Perminder Date: Wed, 13 Nov 2024 06:05:18 +0530 Subject: [PATCH 14/19] minor-fixes-on-calculating-the-mesh-again Signed-off-by: Perminder --- avogadro/qtgui/meshgenerator.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 37813b1bd8..bba692d00d 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -497,6 +497,10 @@ void MeshGenerator::run() points.resize(0); normals.resize(0); tris.resize(0); + edgeCases.resize(0); + cubeCases.resize(0); + gridEdges.resize(0); + triCounter.resize(0); } From f7bbfc848f4e8ac48131c70f4ad87fe619d481df Mon Sep 17 00:00:00 2001 From: Perminder Date: Thu, 14 Nov 2024 17:38:10 +0530 Subject: [PATCH 15/19] minor cleanups Signed-off-by: Perminder --- avogadro/core/cube.cpp | 50 ++++++++++++++------------------ avogadro/qtgui/meshgenerator.cpp | 32 ++------------------ avogadro/qtgui/meshgenerator.h | 15 ---------- 3 files changed, 24 insertions(+), 73 deletions(-) diff --git a/avogadro/core/cube.cpp b/avogadro/core/cube.cpp index 868cdaea35..64a811a495 100644 --- a/avogadro/core/cube.cpp +++ b/avogadro/core/cube.cpp @@ -7,7 +7,6 @@ #include "molecule.h" #include "mutex.h" -#include namespace Avogadro::Core { @@ -24,12 +23,6 @@ Cube::~Cube() m_lock = nullptr; } -// std::vector::const_iterator Cube::getRowIter(int j, int k) const -// { -// return m_data.cbegin() + m_points.z() * k * m_points.y() + m_points.z() * j; -// } - - bool Cube::setLimits(const Vector3& min_, const Vector3& max_, const Vector3i& points) { @@ -44,8 +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_; @@ -201,6 +192,7 @@ float Cube::value(int i, int j, int k) const else return 0.0; } + std::array Cube::computeGradient(int i, int j, int k) const { int nx = m_points.x(); @@ -213,46 +205,46 @@ std::array Cube::computeGradient(int i, int j, int k) const // X-direction if (i == 0) { - x[0][0] = m_data[dataIdx + ny * nz]; // (i+1, j, k) - x[0][1] = m_data[dataIdx]; // (i, j, k) + 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]; // (i, j, k) - x[0][1] = m_data[dataIdx - ny * nz]; // (i-1, j, k) + 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]; // (i+1, j, k) - x[0][1] = m_data[dataIdx - ny * nz]; // (i-1, j, k) + 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]; // (i, j+1, k) - x[1][1] = m_data[dataIdx]; // (i, j, k) + 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]; // (i, j, k) - x[1][1] = m_data[dataIdx - nz]; // (i, j-1, k) + 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]; // (i, j+1, k) - x[1][1] = m_data[dataIdx - nz]; // (i, j-1, k) + 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]; // (i, j, k+1) - x[2][1] = m_data[dataIdx]; // (i, j, k) + 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]; // (i, j, k) - x[2][1] = m_data[dataIdx - 1]; // (i, j, k-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]; // (i, j, k+1) - x[2][1] = m_data[dataIdx - 1]; // (i, j, k-1) + x[2][0] = m_data[dataIdx + 1]; + x[2][1] = m_data[dataIdx - 1]; run[2] = 2 * m_spacing.z(); } @@ -299,7 +291,7 @@ std::array Cube::getValsCube(int i, int j, int k) const } -inline float Cube::getData(int i, int j, int k) const +float Cube::getData(int i, int j, int k) const { int nx = m_points.x(); int ny = m_points.y(); @@ -310,6 +302,7 @@ inline float Cube::getData(int i, int j, int k) const 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()); @@ -348,7 +341,6 @@ std::array, 8> Cube::getPosCube(int i, int j, int k) const pos[7][1] = ypos + m_spacing.y(); pos[7][2] = zpos + m_spacing.z(); - // std::cout << "pos" << " " << pos[0][0] << std::endl; return pos; } diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index bba692d00d..8b4c17b3a6 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -39,7 +39,6 @@ MeshGenerator::~MeshGenerator() bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, int passes, bool reverse) - { if (!cube_ || !mesh_) return false; @@ -59,7 +58,6 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, gridEdges.resize(m_dim.y() * m_dim.z()); triCounter.resize((m_dim.y() - 1) * (m_dim.z() - 1)); - m_progmax = m_dim.x(); return true; @@ -67,8 +65,6 @@ bool MeshGenerator::initialize(const Cube* cube_, Mesh* mesh_, float iso, void MeshGenerator::FlyingEdgesAlgorithmPass1() { - // Loop through z-dimension - for (int k = 0; k != m_dim.z(); ++k) { for (int j = 0; j != m_dim.y(); ++j) { @@ -474,15 +470,15 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() void MeshGenerator::run() { - if (!m_cube || !m_mesh) { qDebug() << "No mesh or cube set - nothing to find isosurface of…"; return; } + m_mesh->setStable(false); m_mesh->clear(); - + // flying-edges passes for the creation of normal, vertices and triangles FlyingEdgesAlgorithmPass1(); FlyingEdgesAlgorithmPass2(); FlyingEdgesAlgorithmPass3(); @@ -494,6 +490,7 @@ void MeshGenerator::run() m_mesh->smooth(m_passes); m_mesh->setStable(true); + // clearing the memory points.resize(0); normals.resize(0); tris.resize(0); @@ -501,7 +498,6 @@ void MeshGenerator::run() cubeCases.resize(0); gridEdges.resize(0); triCounter.resize(0); - } @@ -518,25 +514,6 @@ void MeshGenerator::clear() m_progmax = 0; } -Vector3f MeshGenerator::normal(const Vector3f& pos) -{ - 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; -} - -inline float MeshGenerator::offset(float val1, float val2) -{ - if (val2 - val1 < 1.0e-9f && val1 - val2 < 1.0e-9f) - return 0.5; - return (m_iso - val1) / (val2 - val1); -} - unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) { // FIXME Not implemented yet. @@ -547,7 +524,6 @@ 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; @@ -571,7 +547,6 @@ unsigned char MeshGenerator::calcCubeCase( bool MeshGenerator::isCutEdge(int const& i, int const& j, int const& k) const { - // 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]; @@ -624,7 +599,6 @@ unsigned char MeshGenerator::calcCaseEdge(bool const& prevEdge, bool const& curr return 3; } -// 2000 void MeshGenerator::calcTrimValues(int& xl, int& xr, int const& j, int const& k) const { diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index 32f8157410..0cdc637342 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -180,21 +180,6 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread 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); unsigned long duplicate(const Vector3i& c, const Vector3f& pos); From 0a60847ba39a32ed889023c992f550683fa7dfab Mon Sep 17 00:00:00 2001 From: Perminder Date: Fri, 15 Nov 2024 10:37:52 +0530 Subject: [PATCH 16/19] fixes on suggestions Signed-off-by: Perminder --- avogadro/core/cube.h | 12 +++- avogadro/core/mesh.cpp | 14 ++--- avogadro/core/mesh.h | 10 +--- avogadro/qtgui/meshgenerator.cpp | 98 +++++++++++++++----------------- avogadro/qtgui/meshgenerator.h | 26 ++++++--- 5 files changed, 81 insertions(+), 79 deletions(-) diff --git a/avogadro/core/cube.h b/avogadro/core/cube.h index 8426cb0863..43775c345c 100644 --- a/avogadro/core/cube.h +++ b/avogadro/core/cube.h @@ -249,7 +249,7 @@ class AVOGADROCORE_EXPORT Cube std::array computeGradient(int i, int j, int k) const; /** - * Get the values of the eight corners of a cube cell. + * 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 @@ -257,7 +257,13 @@ class AVOGADROCORE_EXPORT Cube */ 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; /** @@ -270,7 +276,7 @@ class AVOGADROCORE_EXPORT Cube float getData(int i, int j, int k) const; /** - * Get the positions of the eight corners of a cube cell. + * Get the positions 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 diff --git a/avogadro/core/mesh.cpp b/avogadro/core/mesh.cpp index eda48f0258..49c2fdc3f9 100644 --- a/avogadro/core/mesh.cpp +++ b/avogadro/core/mesh.cpp @@ -23,7 +23,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), tris(other.tris) + m_lock(new Mutex), m_triangles(other.m_triangles) { } @@ -65,14 +65,14 @@ const Vector3f* Mesh::vertex(int n) const bool Mesh::setTriangles(const Core::Array& values) { - tris.clear(); - tris = values; + m_triangles.clear(); + m_triangles = values; return true; } const Core::Array&Mesh::triangles() const { - return tris; + return m_triangles; } @@ -187,7 +187,7 @@ Mesh& Mesh::operator=(const Mesh& other) m_colors = other.m_colors; m_name = other.m_name; m_isoValue = other.m_isoValue; - tris = other.tris; + m_triangles = other.m_triangles; return *this; } @@ -198,7 +198,7 @@ void Mesh::smooth(int iterationCount) { // Build vertex adjacency information from triangles (1-ring) std::vector> adjacencyList(m_vertices.size()); - for (const auto& tri : tris) { + 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()); @@ -241,7 +241,7 @@ void Mesh::smooth(int iterationCount) { m_normals.clear(); m_normals.resize(m_vertices.size(), Vector3f(0.0f, 0.0f, 0.0f)); - for (const auto& tri : tris) { + 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()); diff --git a/avogadro/core/mesh.h b/avogadro/core/mesh.h index a19deecf88..082006f283 100644 --- a/avogadro/core/mesh.h +++ b/avogadro/core/mesh.h @@ -142,14 +142,6 @@ class AVOGADROCORE_EXPORT Mesh */ const Core::Array& normals() const; - /** - * @return The number of normals. - */ - // unsigned int numNormals() const - // { - // return static_cast(m_normals.size()); - // } - /** * @return Pointer to the first normal of the specified triangle. */ @@ -232,7 +224,7 @@ class AVOGADROCORE_EXPORT Mesh Core::Array m_vertices; Core::Array m_normals; Core::Array m_colors; - Core::Array tris; + 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 8b4c17b3a6..3b39c233af 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -143,9 +143,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() continue; } - curTriCounter += numTris[caseId]; // not declared + curTriCounter += m_numTris[caseId]; // not declared - const bool* isCutCase = isCut[caseId]; // size 12 + const bool* isCutCase = m_isCut[caseId]; // size 12 ge0.xstart += isCutCase[0]; ge0.ystart += isCutCase[3]; @@ -219,9 +219,9 @@ void MeshGenerator::FlyingEdgesAlgorithmPass3() pointAccum += tmp; }} - points.resize(pointAccum); - normals.resize(pointAccum); - tris.resize(triAccum); + m_vertices.resize(pointAccum); + m_normals.resize(pointAccum); + m_triangles.resize(triAccum); } @@ -272,7 +272,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() continue; } - const bool* isCutCase = isCut[caseId]; // size 12 + 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); @@ -288,8 +288,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 0); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 0); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[0] = idx; ++x0counter; } @@ -299,8 +299,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() int idx = ge0.ystart + y0counter; std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 3); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 3); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[3] = idx; ++y0counter; } @@ -310,8 +310,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() int idx = ge0.zstart + z0counter; std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 8); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 8); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); globalIdxs[8] = idx; ++z0counter; } @@ -323,8 +323,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 1); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 1); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + 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. } @@ -338,8 +338,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 9); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 9); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + 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; @@ -352,8 +352,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 2); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 2); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[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; @@ -368,8 +368,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 10); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 10); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[10] = idx; ++z1counter; @@ -384,8 +384,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 4); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[4] = idx; ++x2counter; @@ -400,8 +400,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 7); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[7] = idx; ++y2counter; @@ -416,8 +416,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 11); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + m_vertices[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); + m_normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); } globalIdxs[11] = idx; } @@ -431,8 +431,8 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 5); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + 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; @@ -446,21 +446,21 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 6); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 6); - points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]); - normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]); + 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 = caseTriangles[caseId]; // size 16 + const char* caseTri = m_caseTriangles[caseId]; // size 16 for(int idx = 0; caseTri[idx] != -1; idx += 3) { - tris[triIdx][0] = globalIdxs[caseTri[idx]]; - tris[triIdx][1] = globalIdxs[caseTri[idx+1]]; - tris[triIdx][2] = globalIdxs[caseTri[idx+2]]; + m_triangles[triIdx][0] = globalIdxs[caseTri[idx]]; + m_triangles[triIdx][1] = globalIdxs[caseTri[idx+1]]; + m_triangles[triIdx][2] = globalIdxs[caseTri[idx+2]]; ++triIdx; } } @@ -484,16 +484,16 @@ void MeshGenerator::run() FlyingEdgesAlgorithmPass3(); FlyingEdgesAlgorithmPass4(); - m_mesh->setVertices(points); - m_mesh->setNormals(normals); - m_mesh->setTriangles(tris); + m_mesh->setVertices(m_vertices); + m_mesh->setNormals(m_normals); + m_mesh->setTriangles(m_triangles); m_mesh->smooth(m_passes); m_mesh->setStable(true); // clearing the memory - points.resize(0); - normals.resize(0); - tris.resize(0); + m_vertices.resize(0); + m_normals.resize(0); + m_triangles.resize(0); edgeCases.resize(0); cubeCases.resize(0); gridEdges.resize(0); @@ -514,12 +514,6 @@ void MeshGenerator::clear() m_progmax = 0; } -unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) -{ - // FIXME Not implemented yet. - return 0; -} - unsigned char MeshGenerator::calcCubeCase( unsigned char const& ec0, unsigned char const& ec1, unsigned char const& ec2, unsigned char const& ec3) const @@ -621,8 +615,8 @@ MeshGenerator::interpolateOnCube( std::array const& isovals, unsigned char const& edge) const { - unsigned char i0 = edgeVertices[edge][0]; - unsigned char i1 = edgeVertices[edge][1]; + unsigned char i0 = m_edgeVertices[edge][0]; + unsigned char i1 = m_edgeVertices[edge][1]; float weight = (m_iso - isovals[i0]) / (isovals[i1] - isovals[i0]); return interpolate(pts[i0], pts[i1], weight); @@ -645,7 +639,7 @@ MeshGenerator::interpolate( // flying edges tables using: -const unsigned char MeshGenerator::numTris[256] = +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, @@ -665,7 +659,7 @@ const unsigned char MeshGenerator::numTris[256] = 2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0 }; -const bool MeshGenerator::isCut[256][12] = +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}, @@ -925,7 +919,7 @@ const bool MeshGenerator::isCut[256][12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; -const char MeshGenerator::caseTriangles[256][16] +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}, @@ -1185,7 +1179,7 @@ const char MeshGenerator::caseTriangles[256][16] {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} }; -const unsigned char MeshGenerator::edgeVertices[12][2] = +const unsigned char MeshGenerator::m_edgeVertices[12][2] = { {0,1}, {1,2}, {3,2}, {0,3}, {4,5}, {5,6}, diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index 0cdc637342..ab2f27d8d7 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -107,6 +107,16 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread int zstart; }; + /** + * @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 @@ -133,6 +143,8 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread */ void FlyingEdgesAlgorithmPass4(); + // @} + /** * @return The Cube being used by the class. */ @@ -181,8 +193,6 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread protected: - unsigned long duplicate(const Vector3i& c, const Vector3f& pos); - /** * isCutEdge checks whether the grid edge at position (i, j, k) is * intersected by the isosurface based on edge case conditions. @@ -221,12 +231,12 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread Vector3f m_min; /** The minimum point in the cube. */ Vector3i m_dim; /** The dimensions of the cube. */ - Core::Array points, normals; + 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 tris; // triangles of a mesh + Core::Array m_triangles; // triangles of a mesh int m_progmin; int m_progmax; @@ -234,10 +244,10 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread * These are the lookup tables for flying edges. * Reference : https://github.com/sandialabs/miniIsosurface/blob/master/flyingEdges/util/MarchingCubesTables.h */ - static const unsigned char numTris[256]; - static const bool isCut[256][12]; - static const char caseTriangles[256][16]; - static const unsigned char edgeVertices[12][2]; + 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 From 38dcb071121508f34f9235f70ae8829092b69e71 Mon Sep 17 00:00:00 2001 From: Perminder Date: Fri, 15 Nov 2024 12:05:31 +0530 Subject: [PATCH 17/19] fixing Signed-off-by: Perminder --- avogadro/qtgui/meshgenerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index ab2f27d8d7..09935268f4 100644 --- a/avogadro/qtgui/meshgenerator.h +++ b/avogadro/qtgui/meshgenerator.h @@ -143,7 +143,7 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread */ void FlyingEdgesAlgorithmPass4(); - // @} + /**@}*/ /** * @return The Cube being used by the class. From 77d870e732883e621f418e59501a2627ec2be7cf Mon Sep 17 00:00:00 2001 From: Perminder Date: Sat, 16 Nov 2024 16:35:24 +0530 Subject: [PATCH 18/19] fixes Signed-off-by: Perminder --- avogadro/core/cube.h | 22 +++++++++++++++------- avogadro/core/mesh.h | 8 ++++++++ avogadro/qtgui/meshgenerator.cpp | 6 ++++++ avogadro/qtgui/meshgenerator.h | 7 +++++++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/avogadro/core/cube.h b/avogadro/core/cube.h index 43775c345c..562d316fc5 100644 --- a/avogadro/core/cube.h +++ b/avogadro/core/cube.h @@ -24,7 +24,10 @@ 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 { public: @@ -275,13 +278,18 @@ class AVOGADROCORE_EXPORT Cube */ float getData(int i, int j, int k) const; - /** - * Get the positions 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 positions at the eight corners. - */ +/** + * 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: diff --git a/avogadro/core/mesh.h b/avogadro/core/mesh.h index 082006f283..596252aa6a 100644 --- a/avogadro/core/mesh.h +++ b/avogadro/core/mesh.h @@ -142,6 +142,14 @@ class AVOGADROCORE_EXPORT Mesh */ const Core::Array& normals() const; + /** + * @return The number of normals. + */ + unsigned int numNormals() const + { + return static_cast(m_normals.size()); + } + /** * @return Pointer to the first normal of the specified triangle. */ diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 3b39c233af..3bdce50599 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -593,6 +593,12 @@ unsigned char MeshGenerator::calcCaseEdge(bool const& prevEdge, bool const& curr return 3; } +unsigned long MeshGenerator::duplicate(const Vector3i&, const Vector3f&) +{ + // FIXME Not implemented yet. + return 0; +} + void MeshGenerator::calcTrimValues(int& xl, int& xr, int const& j, int const& k) const { diff --git a/avogadro/qtgui/meshgenerator.h b/avogadro/qtgui/meshgenerator.h index 09935268f4..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 @@ -107,6 +108,12 @@ class AVOGADROQTGUI_EXPORT MeshGenerator : public QThread 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. From b33f00139f37998aa51a03220096f87f74163bba Mon Sep 17 00:00:00 2001 From: Perminder Singh <127239756+perminder-17@users.noreply.github.com> Date: Sun, 17 Nov 2024 01:34:11 +0530 Subject: [PATCH 19/19] fixes and->&& Signed-off-by: Perminder Singh <127239756+perminder-17@users.noreply.github.com> --- avogadro/qtgui/meshgenerator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/avogadro/qtgui/meshgenerator.cpp b/avogadro/qtgui/meshgenerator.cpp index 3bdce50599..42628b4766 100644 --- a/avogadro/qtgui/meshgenerator.cpp +++ b/avogadro/qtgui/meshgenerator.cpp @@ -167,15 +167,15 @@ void MeshGenerator::FlyingEdgesAlgorithmPass2() ge2.xstart += isCutCase[4]; ge2.ystart += isCutCase[7]; } - if(isXEnd and isYEnd) + if(isXEnd && isYEnd) { ge1.zstart += isCutCase[11]; } - if(isXEnd and isZEnd) + if(isXEnd && isZEnd) { ge2.ystart += isCutCase[5]; } - if(isYEnd and isZEnd) + if(isYEnd && isZEnd) { ge3.xstart += isCutCase[6]; } @@ -410,7 +410,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[11]) { int idx = ge1.zstart + z1counter; - if(isXEnd and isYEnd) + if(isXEnd && isYEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 11); @@ -425,7 +425,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[5]) { int idx = ge2.ystart + y2counter; - if(isXEnd and isZEnd) + if(isXEnd && isZEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 5); @@ -441,7 +441,7 @@ void MeshGenerator::FlyingEdgesAlgorithmPass4() if(isCutCase[6]) { int idx = ge3.xstart + x3counter; - if(isYEnd and isZEnd) + if(isYEnd && isZEnd) { std::array interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 6); std::array interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 6);