CARLA
MeshReconstruction.h
Go to the documentation of this file.
1 #pragma once
2 #include "DataStructs.h"
3 #include "Cube.h"
4 #include "Triangulation.h"
5 
6 namespace MeshReconstruction
7 {
8  /// Reconstructs a triangle mesh from a given signed distance function using <a href="https://en.wikipedia.org/wiki/Marching_cubes">Marching Cubes</a>.
9  /// @param sdf The <a href="http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm">Signed Distance Function</a>.
10  /// @param domain Domain of reconstruction.
11  /// @returns The reconstructed mesh.
13  Fun3s const &sdf,
14  Rect3 const &domain);
15 
16  /// Reconstructs a triangle mesh from a given signed distance function using <a href="https://en.wikipedia.org/wiki/Marching_cubes">Marching Cubes</a>.
17  /// @param sdf The <a href="http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm">Signed Distance Function</a>.
18  /// @param domain Domain of reconstruction.
19  /// @param cubeSize Size of marching cubes. Smaller cubes yields meshes of higher resolution.
20  /// @param isoLevel Level set of the SDF for which triangulation should be done. Changing this value moves the reconstructed surface.
21  /// @param sdfGrad Gradient of the SDF which yields the vertex normals of the reconstructed mesh. If none is provided a numerical approximation is used.
22  /// @returns The reconstructed mesh.
24  Fun3s const &sdf,
25  Rect3 const &domain,
26  Vec3 const &cubeSize,
27  double isoLevel = 0,
28  Fun3v sdfGrad = nullptr);
29 }
30 
31 using namespace MeshReconstruction;
32 using namespace std;
33 
34 // Adapted from here: http://paulbourke.net/geometry/polygonise/
35 
36 namespace
37 {
38  Vec3 NumGrad(Fun3s const &f, Vec3 const &p)
39  {
40  auto const Eps = 1e-6;
41  Vec3 epsX{Eps, 0, 0}, epsY{0, Eps, 0}, epsZ{0, 0, Eps};
42  auto gx = (f(p + epsX) - f(p - epsX)) / 2;
43  auto gy = (f(p + epsY) - f(p - epsY)) / 2;
44  auto gz = (f(p + epsZ) - f(p - epsZ)) / 2;
45  return {gx, gy, gz};
46  }
47 }
48 
49 Mesh MeshReconstruction::MarchCube(Fun3s const &sdf, Rect3 const &domain)
50 {
51  auto const NumCubes = 50;
52  auto cubeSize = domain.size * (1.0 / NumCubes);
53 
54  return MarchCube(sdf, domain, cubeSize);
55 }
56 
58  Fun3s const &sdf,
59  Rect3 const &domain,
60  Vec3 const &cubeSize,
61  double isoLevel,
62  Fun3v sdfGrad)
63 {
64  // Default value.
65  sdfGrad = sdfGrad == nullptr
66  ? [&sdf](Vec3 const &p)
67  { return NumGrad(sdf, p); }
68  : sdfGrad;
69 
70  auto const NumX = static_cast<int>(ceil(domain.size.x / cubeSize.x));
71  auto const NumY = static_cast<int>(ceil(domain.size.y / cubeSize.y));
72  auto const NumZ = static_cast<int>(ceil(domain.size.z / cubeSize.z));
73 
74  auto const HalfCubeDiag = cubeSize.Norm() / 2.0;
75  auto const HalfCubeSize = cubeSize * 0.5;
76 
77  Mesh mesh;
78 
79  for (auto ix = 0; ix < NumX; ++ix)
80  {
81  auto x = domain.min.x + ix * cubeSize.x;
82 
83  for (auto iy = 0; iy < NumY; ++iy)
84  {
85  auto y = domain.min.y + iy * cubeSize.y;
86 
87  for (auto iz = 0; iz < NumZ; ++iz)
88  {
89  auto z = domain.min.z + iz * cubeSize.z;
90  Vec3 min{x, y, z};
91 
92  // Process only if cube lies within narrow band around surface.
93  auto cubeCenter = min + HalfCubeSize;
94  auto dist = abs(sdf(cubeCenter) - isoLevel);
95  if (dist > HalfCubeDiag)
96  continue;
97 
98  Cube cube({min, cubeSize}, sdf);
99  auto intersect = cube.Intersect(isoLevel);
100  Triangulate(intersect, sdfGrad, mesh);
101  }
102  }
103  }
104 
105  return mesh;
106 }
std::function< double(Vec3 const &)> Fun3s
Definition: DataStructs.h:54
double min(double v1, double v2)
Definition: Simplify.h:294
IntersectInfo Intersect(double isoLevel=0) const
Definition: Cube.h:156
void Triangulate(IntersectInfo const &intersect, Fun3v const &grad, Mesh &mesh)
Given a grid cube and an isolevel the triangles (5 max) required to represent the isosurface in the c...
std::function< Vec3(Vec3 const &)> Fun3v
Definition: DataStructs.h:55
double Norm() const
Definition: DataStructs.h:27
Mesh MarchCube(Fun3s const &sdf, Rect3 const &domain)
Reconstructs a triangle mesh from a given signed distance function using Marching Cubes...