supereight
marching_cube.hpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2016-2019 Emanuele Vespa
3  * SPDX-FileCopyrightText: 2020-2021 Smart Robotics Lab, Imperial College London, Technical University of Munich
4  * SPDX-FileCopyrightText: 2020-2021 Nils Funk
5  * SPDX-FileCopyrightText: 2021 Sotiris Papatheodorou
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef SE_MARCHING_CUBE_HPP
10 #define SE_MARCHING_CUBE_HPP
11 
12 
13 
14 #include "edge_tables.hpp"
15 #include "se/common/timings.hpp"
20 
21 
22 
23 namespace se {
24 namespace meshing {
25 
26 enum status : uint8_t {
27  OUTSIDE = 0x0,
28  UNKNOWN = 0xFE, // 254
29  INSIDE = 0xFF, // 255
30 };
31 
33 
34 template<typename OctreeT>
35 inline Eigen::Vector3f compute_intersection(const OctreeT& octree,
36  const Eigen::Vector3i& source_coord,
37  const Eigen::Vector3i& dest_coord);
38 
39 template<typename OctreeT>
40 inline Eigen::Vector3f interp_vertexes(const OctreeT& octree,
41  const unsigned x,
42  const unsigned y,
43  const unsigned z,
44  const int edge);
45 
46 template<typename BlockT>
47 inline void gather_data(const BlockT* block,
48  typename BlockT::DataType data[8],
49  const int x,
50  const int y,
51  const int z);
52 
53 template<typename OctreeT>
54 inline void gather_data(const OctreeT& octree,
55  typename OctreeT::DataType data[8],
56  const int x,
57  const int y,
58  const int z);
59 
60 template<typename OctreeT>
61 uint8_t compute_index(const OctreeT& octree,
62  const typename OctreeT::BlockType* block_ptr,
63  const unsigned x,
64  const unsigned y,
65  const unsigned z);
66 
67 
68 
70 
71 inline Eigen::Vector3f compute_dual_intersection(const float value_0,
72  const float value_1,
73  const Eigen::Vector3f& dual_corner_coord_0,
74  const Eigen::Vector3f& dual_corner_coord_1,
75  const float voxel_dim,
76  const int /* edge_case */);
77 
78 template<typename DataT, typename ValueSelector>
79 inline Eigen::Vector3f
80 interp_dual_vertexes(const int edge,
81  const DataT data[8],
82  const std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>>&
83  dual_corner_coords_f,
84  const float voxel_dim,
85  ValueSelector select_value);
86 
87 /*
88  * Normalised offsets of the dual corners from the primal corner
89  */
90 static const Eigen::Vector3f norm_dual_offset_f[8] = {{-1, -1, -1},
91  {+1, -1, -1},
92  {+1, -1, +1},
93  {-1, -1, +1},
94  {-1, +1, -1},
95  {+1, +1, -1},
96  {+1, +1, +1},
97  {-1, +1, +1}};
98 
99 template<typename BlockT, typename DataT>
100 inline void gather_dual_data(
101  const BlockT* block,
102  const int scale,
103  const Eigen::Vector3f& primal_corner_coord_f,
104  DataT data[8],
105  std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>>& dual_corner_coords_f);
106 
128 inline void norm_dual_corner_idxs(const Eigen::Vector3i& primal_corner_coord_rel,
129  const int block_size,
130  std::vector<int>& lower_priority_neighbours,
131  std::vector<int>& higher_priority_neighbours,
132  std::vector<std::vector<int>>& neighbours);
133 
134 /*
135  * Normalised offsets of the primal corners from the primal corner
136  * The correct coordinates would be {-0.5, -0.5, -0.5}, {0.5, -0.5, -0.5}, ...
137  * However this would cause a lot of extra computations to cast the voxels back and forth and
138  * to make sure that the absolute coordinates {-0.5, y, z} won't be casted to {0, y, z} (and for y, z accordingly).
139  */
140 static const Eigen::Vector3i logical_dual_offset[8] = {{-1, -1, -1},
141  {+0, -1, -1},
142  {+0, -1, +0},
143  {-1, -1, +0},
144  {-1, +0, -1},
145  {+0, +0, -1},
146  {+0, +0, +0},
147  {-1, +0, +0}};
148 
149 template<typename OctreeT, typename DataT>
150 inline void gather_dual_data(
151  const OctreeT& octree,
152  const typename OctreeT::BlockType* block,
153  const int scale,
154  const Eigen::Vector3i& primal_corner_coord,
155  DataT data[8],
156  std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>>& dual_corner_coords_f);
157 
158 template<typename OctreeT, typename DataT>
159 void compute_dual_index(
160  const OctreeT& octree,
161  const typename OctreeT::BlockType* block_ptr,
162  const int scale,
163  const Eigen::Vector3i& primal_corner_coord,
164  uint8_t& edge_pattern_idx,
165  DataT data[8],
166  std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>>& dual_corner_coords_f);
167 
168 inline bool checkVertex(const Eigen::Vector3f& vertex_M, const float dim);
169 
170 } // namespace meshing
171 
172 
173 
174 namespace algorithms {
175 
176 
177 
178 template<typename OctreeT>
179 void marching_cube_kernel(OctreeT& octree,
180  std::vector<typename OctreeT::BlockType*>& block_ptrs,
181  TriangleMesh& triangles);
182 
183 template<typename OctreeT>
184 void dual_marching_cube_kernel(OctreeT& octree,
185  std::vector<typename OctreeT::BlockType*>& block_ptrs,
186  TriangleMesh& triangles);
187 
188 
196 template<typename OctreeT>
197 void marching_cube(OctreeT& octree, TriangleMesh& triangles);
198 
208 template<typename OctreeT>
209 void marching_cube(OctreeT& octree, TriangleMesh& triangles, const int frame);
210 
218 template<typename OctreeT>
219 void dual_marching_cube(OctreeT& octree, TriangleMesh& triangles);
220 
230 template<typename OctreeT>
231 void dual_marching_cube(OctreeT& octree, TriangleMesh& triangles, const int frame);
232 
233 } // namespace algorithms
234 } // namespace se
235 
236 #include "impl/marching_cube_impl.hpp"
237 
238 #endif // SE_MARCHING_CUBE_HPP
void gather_dual_data(const BlockT *block, const int scale, const Eigen::Vector3f &primal_corner_coord_f, DataT data[8], std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f >> &dual_corner_coords_f)
bool checkVertex(const Eigen::Vector3f &vertex_M, const float dim)
void gather_data(const BlockT *block, typename BlockT::DataType data[8], const int x, const int y, const int z)
Eigen::Vector3f interp_dual_vertexes(const int edge, const DataT data[8], const std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f >> &dual_corner_coords_f, const float voxel_dim, ValueSelector select_value)
void dual_marching_cube_kernel(OctreeT &octree, std::vector< typename OctreeT::BlockType *> &block_ptrs, TriangleMesh &triangles)
void marching_cube(OctreeT &octree, TriangleMesh &triangles, const int frame)
Generate the triangle mesh using a primal grid marching cube algorithm.
void dual_marching_cube(OctreeT &octree, TriangleMesh &triangles, const int frame)
Generate the triangle mesh using a dual grid marching cube algorithm.
Eigen::Vector3f compute_intersection(const OctreeT &octree, const Eigen::Vector3i &source_coord, const Eigen::Vector3i &dest_coord)
Single-res marching cube implementation.
se::OctantBase * block(const Eigen::Vector3i &voxel_coord, OctreeT &octree, se::OctantBase *base_parent_ptr)
Allocate a block at the provided voxel coordinates.
static const Eigen::Vector3f norm_dual_offset_f[8]
Definition: marching_cube.hpp:90
void marching_cube_kernel(OctreeT &octree, std::vector< typename OctreeT::BlockType *> &block_ptrs, TriangleMesh &triangles)
Mesh< Triangle > TriangleMesh
Definition: mesh.hpp:41
Eigen::Vector3f interp_vertexes(const OctreeT &octree, const unsigned x, const unsigned y, const unsigned z, const int edge)
Definition: marching_cube.hpp:28
void neighbours(const se::key_t key, std::array< se::key_t, 26 > neighbour_keys)
TODO: 26-connectivity.
void compute_dual_index(const OctreeT &octree, const typename OctreeT::BlockType *block_ptr, const int scale, const Eigen::Vector3i &primal_corner_coord, uint8_t &edge_pattern_idx, DataT data[8], std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f >> &dual_corner_coords_f)
Definition: marching_cube.hpp:29
static const Eigen::Vector3i logical_dual_offset[8]
Definition: marching_cube.hpp:140
uint8_t compute_index(const OctreeT &octree, const typename OctreeT::BlockType *block_ptr, const unsigned x, const unsigned y, const unsigned z)
Definition: marching_cube.hpp:27
Helper wrapper to allocate and de-allocate octants in the octree.
Definition: colour_utils.hpp:17
void norm_dual_corner_idxs(const Eigen::Vector3i &primal_corner_coord_rel, const int block_size, std::vector< int > &lower_priority_neighbours, std::vector< int > &higher_priority_neighbours, std::vector< std::vector< int >> &neighbours)
The following strategy is derived from I.
static const std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f > > scale
The colours used for the various integration scales.
Definition: colour_utils.hpp:22
status
Definition: marching_cube.hpp:26
Eigen::Vector3f compute_dual_intersection(const float value_0, const float value_1, const Eigen::Vector3f &dual_corner_coord_0, const Eigen::Vector3f &dual_corner_coord_1, const float voxel_dim, const int)
Multires-res marching cube implementation.