Added marching cubes polygonization, almost works but sometimes holes appear

master
Marc Gilleron 2019-04-20 21:21:45 +01:00
parent a12435266f
commit d74201c93f
4 changed files with 635 additions and 22 deletions

350
dmc/marching_cubes_tables.h Normal file
View File

@ -0,0 +1,350 @@
#ifndef MARCHING_CUBES_TABLES_H
#define MARCHING_CUBES_TABLES_H
namespace MarchingCubes {
// Marching Cubes tables from the public domain code found on http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
// in http://paulbourke.net/geometry/polygonise/marchingsource.cpp
// Thanks!
// Edges table
int mc_edges[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
};
// Triangulation lookup table
int mc_triangles[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 }
};
// Throw in the corners inside of the volume and get a 4 bit array which edges are cutting it.
// Edge indices to check then (Edge between 0 and 4 cut == msEdges[x] & 4).
//
// 0---1---1
// | |
// 4 2
// | |
// 3---3---2
//
int ms_edges[16] = {
0x0, // 0000 Nothing intersects
0x9, // 0001 0
0x3, // 0010 1
0xA, // 0011 0 1
0x6, // 0100 2
0xF, // 0101 0 2
0x5, // 0110 1 2
0xC, // 0111 0 1 2
0xC, // 1000 3
0x5, // 1001 0 3
0xF, // 1010 1 3
0x6, // 1011 0 1 3
0xA, // 1100 2 3
0x3, // 1101 0 2 3
0x9, // 1110 1 2 3
0x0 // 1111 0 1 2 3
};
// To get a triangulation with up to 5 triangles based on the corners inside. Alternative
// ambigous cases added at the end. Indices of the counterclockwise formed triangles:
//
// 0---1---2
// | |
// 7 3
// | |
// 6---5---4
//
int ms_triangles[18][13] = {
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Nothing intersects
{ 7, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // 0
{ 3, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // 1
{ 7, 2, 0, 7, 3, 2, -1, -1, -1, -1, -1, -1, -1 }, // 0 1
{ 5, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // 2
{ 7, 1, 0, 3, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, // 0 2
{ 1, 4, 2, 1, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, // 1 2
{ 0, 7, 5, 0, 5, 4, 0, 4, 2, -1, -1, -1, -1 }, // 0 1 2
{ 7, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // 3
{ 0, 5, 1, 0, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, // 0 3
{ 1, 3, 2, 7, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, // 1 3
{ 3, 6, 5, 3, 0, 6, 3, 2, 0, -1, -1, -1, -1 }, // 0 1 3
{ 7, 6, 4, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1 }, // 2 3
{ 3, 1, 0, 3, 0, 6, 3, 6, 4, -1, -1, -1, -1 }, // 0 2 3
{ 2, 1, 7, 2, 7, 6, 2, 6, 4, -1, -1, -1, -1 }, // 1 2 3
{ 6, 2, 0, 6, 4, 2, -1, -1, -1, -1, -1, -1, -1 }, // 0 1 2 3
{ 1, 0, 7, 1, 7, 5, 1, 5, 4, 1, 4, 3, -1 }, // 0 2 alternative
{ 1, 3, 2, 1, 5, 3, 1, 6, 5, 1, 7, 6, -1 } // 1 3 alternative
};
} // namespace MarchingCubes
#endif // MARCHING_CUBES_TABLES_H

View File

@ -1,5 +1,8 @@
#include "voxel_mesher_dmc.h"
#include "../cube_tables.h"
#include "../utility.h"
#include "marching_cubes_tables.h"
#include <map>
#include <vector>
// Algorithm taken from https://www.volume-gfx.com/volume-rendering/dual-marching-cubes/
@ -14,13 +17,14 @@ enum Channels {
};
const int CHUNK_SIZE = 16;
const float ISO_LEVEL = 0.0;
struct HermiteValue {
float value; // Signed "distance" to surface
Vector3 gradient; // "Normal" of the volume
HermiteValue() :
value(0) {
value(1.0) {
}
};
@ -102,21 +106,48 @@ void split(OctreeNode *node) {
}
}
inline float interpolate(float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, Vector3 position) {
// Trilinear interpolation between corner values of a cube.
// Cube points respect the same position as in the ASCII schema.
template <typename T>
inline T interpolate(const T v0, const T v1, const T v2, const T v3, const T v4, const T v5, const T v6, const T v7, Vector3 position) {
float one_min_x = 1.f - position.x;
float one_min_y = 1.f - position.y;
float one_min_z = 1.f - position.z;
float one_min_x_one_min_y = one_min_x * one_min_y;
float x_one_min_y = position.x * one_min_y;
const float one_min_x = 1.f - position.x;
const float one_min_y = 1.f - position.y;
const float one_min_z = 1.f - position.z;
const float one_min_x_one_min_y = one_min_x * one_min_y;
const float x_one_min_y = position.x * one_min_y;
float res = one_min_z * (v0 * one_min_x_one_min_y + v1 * x_one_min_y + v4 * one_min_x * position.y);
T res = one_min_z * (v0 * one_min_x_one_min_y + v1 * x_one_min_y + v4 * one_min_x * position.y);
res += position.z * (v3 * one_min_x_one_min_y + v2 * x_one_min_y + v7 * one_min_x * position.y);
res += position.x * position.y * (v5 * one_min_z + v6 * position.z);
return res;
}
inline Vector3 interpolate(const Vector3 &v0, const Vector3 &v1, const HermiteValue &val0, const HermiteValue &val1, Vector3 &out_normal) {
if (Math::abs(val0.value - ISO_LEVEL) <= FLT_EPSILON) {
out_normal = val0.gradient;
return v0;
}
if (Math::abs(val1.value - ISO_LEVEL) <= FLT_EPSILON) {
out_normal = val1.gradient;
return v1;
}
if (Math::abs(val1.value - val0.value) <= FLT_EPSILON) {
out_normal = val0.gradient;
return v0;
}
float mu = (ISO_LEVEL - val0.value) / (val1.value - val0.value);
out_normal = val0.gradient + mu * (val1.gradient - val0.gradient);
out_normal.normalize();
return v0 + mu * (v1 - v0);
}
inline HermiteValue get_hermite_value(const VoxelBuffer &voxels, int x, int y, int z) {
HermiteValue v;
v.value = voxels.get_voxel_iso(x, y, z, CHANNEL_VALUE);
@ -127,6 +158,35 @@ inline HermiteValue get_hermite_value(const VoxelBuffer &voxels, int x, int y, i
return v;
}
inline HermiteValue get_interpolated_hermite_value(const VoxelBuffer &voxels, Vector3 pos) {
int x0 = static_cast<int>(pos.x);
int y0 = static_cast<int>(pos.y);
int z0 = static_cast<int>(pos.z);
int x1 = static_cast<int>(Math::ceil(pos.x));
int y1 = static_cast<int>(Math::ceil(pos.y));
int z1 = static_cast<int>(Math::ceil(pos.z));
HermiteValue v0 = get_hermite_value(voxels, x0, y0, z0);
HermiteValue v1 = get_hermite_value(voxels, x1, y0, z0);
HermiteValue v2 = get_hermite_value(voxels, x1, y0, z1);
HermiteValue v3 = get_hermite_value(voxels, x0, y0, z1);
HermiteValue v4 = get_hermite_value(voxels, x0, y1, z0);
HermiteValue v5 = get_hermite_value(voxels, x1, y1, z0);
HermiteValue v6 = get_hermite_value(voxels, x1, y1, z1);
HermiteValue v7 = get_hermite_value(voxels, x0, y1, z1);
Vector3 rpos = pos - Vector3(x0, y0, z0);
HermiteValue v;
v.value = interpolate(v0.value, v1.value, v2.value, v3.value, v4.value, v5.value, v6.value, v7.value, rpos);
v.gradient = interpolate(v0.gradient, v1.gradient, v2.gradient, v3.gradient, v4.gradient, v5.gradient, v6.gradient, v7.gradient, rpos);
return v;
}
bool can_split(OctreeNode *node, const VoxelBuffer &voxels, float geometric_error) {
if (node->size == 1) {
@ -262,24 +322,19 @@ Ref<ArrayMesh> generate_debug_octree_mesh(OctreeNode *root) {
struct GetMaxDepth {
int max_depth;
void operator()(OctreeNode *node, int depth) {
void operator()(OctreeNode *_, int depth) {
if (depth > max_depth) {
max_depth = depth;
}
}
};
GetMaxDepth get_max_depth;
foreach_node(root, get_max_depth);
struct Arrays {
PoolVector3Array positions;
PoolColorArray colors;
PoolIntArray indices;
};
Arrays arrays;
struct AddCube {
Arrays *arrays;
int max_depth;
@ -306,6 +361,10 @@ Ref<ArrayMesh> generate_debug_octree_mesh(OctreeNode *root) {
}
};
GetMaxDepth get_max_depth;
foreach_node(root, get_max_depth);
Arrays arrays;
AddCube add_cube;
add_cube.arrays = &arrays;
add_cube.max_depth = get_max_depth.max_depth;
@ -343,6 +402,10 @@ inline bool is_surface_near(OctreeNode *node) {
struct DualCell {
Vector3 corners[8];
HermiteValue values[8];
bool has_values;
DualCell() :
has_values(false) {}
inline void set_corner(int i, Vector3 vertex, HermiteValue value) {
CRASH_COND(i < 0 || i >= 8);
@ -836,6 +899,7 @@ void vert_proc(DualGrid &grid, OctreeNode *n0, OctreeNode *n1, OctreeNode *n2, O
cell.set_corner(5, get_center(n5), n5->center_value);
cell.set_corner(6, get_center(n6), n6->center_value);
cell.set_corner(7, get_center(n7), n7->center_value);
cell.has_values = true;
grid.cells.push_back(cell);
create_border_cells(grid, n0, n1, n2, n3, n4, n5, n6, n7);
@ -1053,7 +1117,176 @@ void node_proc(DualGrid &grid, OctreeNode *node) {
vert_proc(grid, children[0], children[1], children[2], children[3], children[4], children[5], children[6], children[7]);
}
Ref<ArrayMesh> polygonize(const VoxelBuffer &voxels, float geometric_error) {
class MeshBuilder {
public:
void add_vertex(Vector3 position, Vector3 normal) {
int i = 0;
if (_position_to_index.find(position) != _position_to_index.end()) {
i = _position_to_index[position];
} else {
i = _positions.size();
_position_to_index[position] = i;
_positions.push_back(position);
_normals.push_back(normal);
}
_indices.push_back(i);
}
Ref<ArrayMesh> commit(bool wireframe) {
if (_positions.size() == 0) {
return Ref<ArrayMesh>();
}
ERR_FAIL_COND_V(_indices.size() % 3 != 0, Ref<ArrayMesh>());
if (wireframe) {
// Debug purpose, no effort to be fast here
std::vector<int> wireframe_indices;
for (int i = 0; i < _indices.size(); i += 3) {
wireframe_indices.push_back(_indices[i]);
wireframe_indices.push_back(_indices[i + 1]);
wireframe_indices.push_back(_indices[i + 1]);
wireframe_indices.push_back(_indices[i + 2]);
wireframe_indices.push_back(_indices[i + 2]);
wireframe_indices.push_back(_indices[i]);
}
_indices = wireframe_indices;
}
PoolVector3Array positions;
PoolVector3Array normals;
PoolIntArray indices;
raw_copy_to(positions, _positions);
raw_copy_to(normals, _normals);
raw_copy_to(indices, _indices);
Array surface;
surface.resize(Mesh::ARRAY_MAX);
surface[Mesh::ARRAY_VERTEX] = positions;
surface[Mesh::ARRAY_NORMAL] = normals;
surface[Mesh::ARRAY_INDEX] = indices;
Ref<ArrayMesh> mesh;
mesh.instance();
mesh->add_surface_from_arrays(wireframe ? Mesh::PRIMITIVE_LINES : Mesh::PRIMITIVE_TRIANGLES, surface);
return mesh;
}
private:
std::vector<Vector3> _positions;
std::vector<Vector3> _normals;
std::vector<int> _indices;
std::map<Vector3, int> _position_to_index;
};
Ref<ArrayMesh> polygonize_dual_grid(const DualGrid &grid, const VoxelBuffer &voxels, bool wireframe) {
MeshBuilder mesh_builder;
for (int dci = 0; dci < grid.cells.size(); ++dci) {
const DualCell &cell = grid.cells[dci];
const Vector3 *corners = cell.corners;
// Polygonize using regular marching cubes
unsigned char case_index = 0;
HermiteValue values[8];
for (int i = 0; i < 8; ++i) {
if (cell.has_values) {
values[i] = cell.values[i];
} else {
values[i] = get_interpolated_hermite_value(voxels, corners[i]);
}
if (values[i].value >= ISO_LEVEL) {
case_index |= 1 << i;
}
}
int edge = MarchingCubes::mc_edges[case_index];
if (!edge) {
// Nothing intersects
continue;
}
// Find the intersection vertices
Vector3 intersection_points[12];
Vector3 intersection_normals[12];
if (edge & 1) {
intersection_points[0] = interpolate(corners[0], corners[1], values[0], values[1], intersection_normals[0]);
}
if (edge & 2) {
intersection_points[1] = interpolate(corners[1], corners[2], values[1], values[2], intersection_normals[1]);
}
if (edge & 4) {
intersection_points[2] = interpolate(corners[2], corners[3], values[2], values[3], intersection_normals[2]);
}
if (edge & 8) {
intersection_points[3] = interpolate(corners[3], corners[0], values[3], values[0], intersection_normals[3]);
}
if (edge & 16) {
intersection_points[4] = interpolate(corners[4], corners[5], values[4], values[5], intersection_normals[4]);
}
if (edge & 32) {
intersection_points[5] = interpolate(corners[5], corners[6], values[5], values[6], intersection_normals[5]);
}
if (edge & 64) {
intersection_points[6] = interpolate(corners[6], corners[7], values[6], values[7], intersection_normals[6]);
}
if (edge & 128) {
intersection_points[7] = interpolate(corners[7], corners[4], values[7], values[4], intersection_normals[7]);
}
if (edge & 256) {
intersection_points[8] = interpolate(corners[0], corners[4], values[0], values[4], intersection_normals[8]);
}
if (edge & 512) {
intersection_points[9] = interpolate(corners[1], corners[5], values[1], values[5], intersection_normals[9]);
}
if (edge & 1024) {
intersection_points[10] = interpolate(corners[2], corners[6], values[2], values[6], intersection_normals[10]);
}
if (edge & 2048) {
intersection_points[11] = interpolate(corners[3], corners[7], values[3], values[7], intersection_normals[11]);
}
// Create the triangles according to the table.
for (int i = 0; MarchingCubes::mc_triangles[case_index][i] != -1; i += 3) {
mesh_builder.add_vertex(
intersection_points[MarchingCubes::mc_triangles[case_index][i]],
intersection_normals[MarchingCubes::mc_triangles[case_index][i]]);
mesh_builder.add_vertex(
intersection_points[MarchingCubes::mc_triangles[case_index][i + 1]],
intersection_normals[MarchingCubes::mc_triangles[case_index][i + 1]]);
mesh_builder.add_vertex(
intersection_points[MarchingCubes::mc_triangles[case_index][i + 2]],
intersection_normals[MarchingCubes::mc_triangles[case_index][i + 2]]);
}
}
return mesh_builder.commit(wireframe);
}
Ref<ArrayMesh> polygonize(const VoxelBuffer &voxels, float geometric_error, VoxelMesherDMC::Mode mode) {
int padding = 1;
int chunk_size = CHUNK_SIZE;
@ -1067,22 +1300,35 @@ Ref<ArrayMesh> polygonize(const VoxelBuffer &voxels, float geometric_error) {
root.origin = Vector3i();
root.size = chunk_size;
generate_octree_top_down(&root, voxels, geometric_error);
//return generate_debug_octree_mesh(&root);
if (mode == VoxelMesherDMC::MODE_DEBUG_OCTREE) {
return generate_debug_octree_mesh(&root);
}
DualGrid grid;
node_proc(grid, &root);
return generate_debug_dual_grid_mesh(grid);
// TODO Handle non-subdivided octree
if (mode == VoxelMesherDMC::MODE_DEBUG_DUAL_GRID) {
return generate_debug_dual_grid_mesh(grid);
}
// TODO
return polygonize_dual_grid(grid, voxels, mode == VoxelMesherDMC::MODE_WIREFRAME);
// TODO Marching squares skirts
}
} // namespace dmc
Ref<ArrayMesh> VoxelMesherDMC::build_mesh(Ref<VoxelBuffer> voxels, real_t geometric_error) {
Ref<ArrayMesh> VoxelMesherDMC::build_mesh(Ref<VoxelBuffer> voxels, real_t geometric_error, Mode mode) {
ERR_FAIL_COND_V(voxels.is_null(), Ref<ArrayMesh>());
return dmc::polygonize(**voxels, geometric_error);
return dmc::polygonize(**voxels, geometric_error, mode);
}
void VoxelMesherDMC::_bind_methods() {
ClassDB::bind_method(D_METHOD("build_mesh", "voxel_buffer", "geometric_error"), &VoxelMesherDMC::build_mesh);
ClassDB::bind_method(D_METHOD("build_mesh", "voxel_buffer", "geometric_error", "mode"), &VoxelMesherDMC::build_mesh, DEFVAL(MODE_NORMAL));
BIND_ENUM_CONSTANT(MODE_NORMAL);
BIND_ENUM_CONSTANT(MODE_WIREFRAME);
BIND_ENUM_CONSTANT(MODE_DEBUG_OCTREE);
BIND_ENUM_CONSTANT(MODE_DEBUG_DUAL_GRID);
}

View File

@ -12,10 +12,19 @@ Ref<ArrayMesh> polygonize(const VoxelBuffer &voxels, float geometric_error);
class VoxelMesherDMC : public Reference {
GDCLASS(VoxelMesherDMC, Reference)
public:
Ref<ArrayMesh> build_mesh(Ref<VoxelBuffer> voxels, real_t geometric_error);
enum Mode {
MODE_NORMAL,
MODE_WIREFRAME,
MODE_DEBUG_OCTREE,
MODE_DEBUG_DUAL_GRID
};
Ref<ArrayMesh> build_mesh(Ref<VoxelBuffer> voxels, real_t geometric_error, Mode mode);
protected:
static void _bind_methods();
};
VARIANT_ENUM_CAST(VoxelMesherDMC::Mode)
#endif // VOXEL_MESHER_DMC_H

View File

@ -4,6 +4,7 @@
#include "vector3i.h"
#include <core/ustring.h>
#include <core/vector.h>
#include <vector>
// Takes elements starting from a given position and moves them at the beginning,
// then shrink the array to fit them. Other elements are discarded.
@ -44,4 +45,11 @@ inline String ptr2s(const void *p) {
return String::num_uint64((uint64_t)p, 16);
}
template <typename T>
void raw_copy_to(PoolVector<T> &to, const std::vector<T> &from) {
to.resize(from.size());
typename PoolVector<T>::Write w = to.write();
memcpy(w.ptr(), from.data(), from.size() * sizeof(T));
}
#endif // HEADER_VOXEL_UTILITY_H