diff --git a/dmc/marching_cubes_tables.h b/dmc/marching_cubes_tables.h new file mode 100644 index 00000000..6c977014 --- /dev/null +++ b/dmc/marching_cubes_tables.h @@ -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 diff --git a/dmc/voxel_mesher_dmc.cpp b/dmc/voxel_mesher_dmc.cpp index 1faba6ac..802a0e4f 100644 --- a/dmc/voxel_mesher_dmc.cpp +++ b/dmc/voxel_mesher_dmc.cpp @@ -1,5 +1,8 @@ #include "voxel_mesher_dmc.h" #include "../cube_tables.h" +#include "../utility.h" +#include "marching_cubes_tables.h" +#include #include // 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 +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(pos.x); + int y0 = static_cast(pos.y); + int z0 = static_cast(pos.z); + + int x1 = static_cast(Math::ceil(pos.x)); + int y1 = static_cast(Math::ceil(pos.y)); + int z1 = static_cast(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 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 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 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 commit(bool wireframe) { + + if (_positions.size() == 0) { + return Ref(); + } + + ERR_FAIL_COND_V(_indices.size() % 3 != 0, Ref()); + + if (wireframe) { + + // Debug purpose, no effort to be fast here + std::vector 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 mesh; + mesh.instance(); + mesh->add_surface_from_arrays(wireframe ? Mesh::PRIMITIVE_LINES : Mesh::PRIMITIVE_TRIANGLES, surface); + + return mesh; + } + +private: + std::vector _positions; + std::vector _normals; + std::vector _indices; + std::map _position_to_index; +}; + +Ref 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 polygonize(const VoxelBuffer &voxels, float geometric_error, VoxelMesherDMC::Mode mode) { int padding = 1; int chunk_size = CHUNK_SIZE; @@ -1067,22 +1300,35 @@ Ref 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 VoxelMesherDMC::build_mesh(Ref voxels, real_t geometric_error) { +Ref VoxelMesherDMC::build_mesh(Ref voxels, real_t geometric_error, Mode mode) { ERR_FAIL_COND_V(voxels.is_null(), Ref()); - 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); } diff --git a/dmc/voxel_mesher_dmc.h b/dmc/voxel_mesher_dmc.h index 2fd380cc..b6557b73 100644 --- a/dmc/voxel_mesher_dmc.h +++ b/dmc/voxel_mesher_dmc.h @@ -12,10 +12,19 @@ Ref polygonize(const VoxelBuffer &voxels, float geometric_error); class VoxelMesherDMC : public Reference { GDCLASS(VoxelMesherDMC, Reference) public: - Ref build_mesh(Ref voxels, real_t geometric_error); + enum Mode { + MODE_NORMAL, + MODE_WIREFRAME, + MODE_DEBUG_OCTREE, + MODE_DEBUG_DUAL_GRID + }; + + Ref build_mesh(Ref voxels, real_t geometric_error, Mode mode); protected: static void _bind_methods(); }; +VARIANT_ENUM_CAST(VoxelMesherDMC::Mode) + #endif // VOXEL_MESHER_DMC_H diff --git a/utility.h b/utility.h index f37dd3fd..ee62580a 100644 --- a/utility.h +++ b/utility.h @@ -4,6 +4,7 @@ #include "vector3i.h" #include #include +#include // 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 +void raw_copy_to(PoolVector &to, const std::vector &from) { + to.resize(from.size()); + typename PoolVector::Write w = to.write(); + memcpy(w.ptr(), from.data(), from.size() * sizeof(T)); +} + #endif // HEADER_VOXEL_UTILITY_H