118 lines
2.7 KiB
C++
118 lines
2.7 KiB
C++
#pragma once
|
|
|
|
#include <functional>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
#include <glm/vec3.hpp>
|
|
#include <glm/gtc/epsilon.hpp>
|
|
|
|
#include <MarchingCube.h>
|
|
#include <logger.h>
|
|
|
|
#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<glm::vec3> vertices;
|
|
std::vector<glm::uvec3> triangles;
|
|
|
|
Density &density;
|
|
|
|
Polygonizer(Density &density) :
|
|
density(density) {
|
|
|
|
}
|
|
|
|
void polygonize(float isolevel, float resolution) {
|
|
vertices.clear();
|
|
triangles.clear();
|
|
|
|
std::map<glm::vec3, int, CompareVec3> 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<glm::vec3, int>::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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
};
|