#pragma once #include #include #include #include #include #include #include #include "Density.h" struct CompareVec3 { bool operator()(const glm::vec3 &lhs, const glm::vec3 &rhs) { static const float epsilon = 1e-5; if (lhs.x < rhs.x - epsilon) return true; else if (lhs.x > rhs.x + epsilon) return false; else { if (lhs.y < rhs.y - epsilon) return true; else if (lhs.y > rhs.y + epsilon) return false; else { if (lhs.z < rhs.z - epsilon) return true; else if (lhs.z > rhs.z + epsilon) return false; else { return false; } } } } }; class Polygonizer { public: std::vector vertices; std::vector triangles; Density &density; Polygonizer(Density &density) : density(density) { } void polygonize(float isolevel, float resolution) { vertices.clear(); triangles.clear(); std::map vertexLookup; size_t nSteps = 1.f / resolution - 1; size_t nT = 0; for (size_t ix = 0; ix < nSteps; ix++) { double x = (double(ix) + 0.5) * resolution; for (size_t iy = 0; iy < nSteps; iy++) { double y = (double(iy) + 0.5) * resolution; for (size_t iz = 0; iz < nSteps; iz++) { double z = (double(iz) + 0.5) * resolution; GRIDCELL gridCell; gridCell.p[0] = vec3(x, y, z); gridCell.p[1] = vec3(x + resolution, y, z); gridCell.p[2] = vec3(x + resolution, y + resolution, z); gridCell.p[3] = vec3(x, y + resolution, z); gridCell.p[4] = vec3(x, y, z + resolution); gridCell.p[5] = vec3(x + resolution, y, z + resolution); gridCell.p[6] = vec3(x + resolution, y + resolution, z + resolution); gridCell.p[7] = vec3(x, y + resolution, z + resolution); for (size_t iCell = 0; iCell < 8; iCell++) { gridCell.val[iCell] = density(gridCell.p[iCell]); } TRIANGLE tris[6]; int nTris = Polygonise(gridCell, isolevel, tris); nT += nTris; for (int iTri = 0; iTri < nTris; iTri++) { vec3 *ps = tris[iTri].p; // skip degenerate vertices if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) || all(epsilonEqual(ps[0], ps[2], 1e-8f)) || all(epsilonEqual(ps[2], ps[1], 1e-8f))) continue; glm::uvec3 idc; for (size_t k = 0; k < 3; k++) { glm::vec3 &p = tris[iTri].p[k]; std::map::iterator vit = vertexLookup.find(p); if (vit != vertexLookup.end()) { idc[k] = vit->second; } else { idc[k] = vertices.size(); vertices.push_back(p); vertexLookup[p] = idc[k]; } } triangles.push_back(idc); } } } } } };