diff --git a/SCsub b/SCsub index 74dd64b..ae3b896 100644 --- a/SCsub +++ b/SCsub @@ -34,6 +34,10 @@ sources = [ "meshers/transvoxel_uv_mesher/voxel_mesher_uv_transvoxel.cpp", "meshers/transvoxel_uv_mesher/transvoxel_tables.cpp", + "meshers/marching_cubes/marching_cubes_cell_data.cpp", + "meshers/marching_cubes/voxel_mesher_marching_cubes.cpp", + "meshers/marching_cubes/marching_cubes_tables.cpp", + "meshers/blocky/voxel_mesher_blocky.cpp", "meshers/blocky/voxel_mesher_liquid_blocky.cpp", "meshers/default/voxel_mesher_default.cpp", diff --git a/config.py b/config.py index 700a58b..e0d2097 100644 --- a/config.py +++ b/config.py @@ -29,6 +29,10 @@ def get_doc_classes(): "TransvoxelCellData", "VoxelMeshData", "VoxelMesherUVTransvoxel", + + "MarchingCubesCellData", + "VoxelMesherMarchingCubes", + "VoxelMesher", "EnvironmentData", diff --git a/meshers/marching_cubes/marching_cubes_cell_data.cpp b/meshers/marching_cubes/marching_cubes_cell_data.cpp new file mode 100644 index 0000000..4c64943 --- /dev/null +++ b/meshers/marching_cubes/marching_cubes_cell_data.cpp @@ -0,0 +1,80 @@ +/* +Copyright (c) 2019-2020 Péter Magyar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "marching_cubes_cell_data.h" + +int MarchingCubesCellData::get_vertex_index(int index) const { + return static_cast(vertexIndex[index]); +} +void MarchingCubesCellData::set_vertex_index(int index, int value) { + ERR_FAIL_INDEX(index, 15); + + vertexIndex[index] = static_cast(value); +} + +int MarchingCubesCellData::get_vertex_count() const { + return (geometryCounts >> 4); +} +void MarchingCubesCellData::set_vertex_count(int value) { + geometryCounts &= 0xFF0F; + + geometryCounts |= value << 4; +} + +int MarchingCubesCellData::get_triangle_count() const { + return (geometryCounts & 0x0F); +} +void MarchingCubesCellData::set_triangle_count(int value) { + geometryCounts &= 0xFFF0; + + geometryCounts |= value; +} + +MarchingCubesCellData::MarchingCubesCellData() { + geometryCounts = 0; + + for (int i = 0; i < 15; ++i) { + vertexIndex[i] = 0; + } +} + +MarchingCubesCellData::MarchingCubesCellData(const RegularCellData &cell_data) { + geometryCounts = cell_data.geometryCounts; + + for (int i = 0; i < 15; ++i) { + vertexIndex[i] = cell_data.vertexIndex[i]; + } +} + +MarchingCubesCellData::~MarchingCubesCellData() { +} + +void MarchingCubesCellData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_vertex_index", "index"), &MarchingCubesCellData::get_vertex_index); + ClassDB::bind_method(D_METHOD("set_vertex_index", "index", "value"), &MarchingCubesCellData::set_vertex_index); + + ClassDB::bind_method(D_METHOD("get_vertex_count"), &MarchingCubesCellData::get_vertex_count); + ClassDB::bind_method(D_METHOD("set_vertex_count", "value"), &MarchingCubesCellData::set_vertex_count); + + ClassDB::bind_method(D_METHOD("get_triangle_count"), &MarchingCubesCellData::get_triangle_count); + ClassDB::bind_method(D_METHOD("set_triangle_count", "value"), &MarchingCubesCellData::set_triangle_count); +} diff --git a/meshers/marching_cubes/marching_cubes_cell_data.h b/meshers/marching_cubes/marching_cubes_cell_data.h new file mode 100644 index 0000000..e757b60 --- /dev/null +++ b/meshers/marching_cubes/marching_cubes_cell_data.h @@ -0,0 +1,57 @@ +/* +Copyright (c) 2019-2020 Péter Magyar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef MARCHING_CUBES_CELL_DATA_H +#define MARCHING_CUBES_CELL_DATA_H + +#include "core/reference.h" + +#include "marching_cubes_tables.h" + +using namespace MarchingCubes; + +class MarchingCubesCellData : public Reference { + GDCLASS(MarchingCubesCellData, Reference) + +public: + int get_vertex_index(int index) const; + void set_vertex_index(int index, int value); + + int get_vertex_count() const; + void set_vertex_count(int value); + + int get_triangle_count() const; + void set_triangle_count(int value); + + MarchingCubesCellData(); + MarchingCubesCellData(const MarchingCubes::RegularCellData &cell_data); + ~MarchingCubesCellData(); + +protected: + static void _bind_methods(); + +private: + long geometryCounts; // High nibble is vertex count, low nibble is triangle count. + unsigned char vertexIndex[15]; // Groups of 3 indexes giving the triangulation. +}; + +#endif diff --git a/meshers/marching_cubes/marching_cubes_tables.cpp b/meshers/marching_cubes/marching_cubes_tables.cpp new file mode 100644 index 0000000..0255570 --- /dev/null +++ b/meshers/marching_cubes/marching_cubes_tables.cpp @@ -0,0 +1,380 @@ +#include "marching_cubes_tables.h" + +//================================================================================ +// +// The MarchingCubes Algorithm look-up tables +// +// These tables have been modified, in order to implement uv mapping. +// Also the transition data have been removed. +// +// Copyright 2009 by Eric Lengyel +// +// The following data originates from Eric Lengyel's MarchingCubes Algorithm. +// http://transvoxel.org/ +// +// The data in this file may be freely used in implementations of the MarchingCubes +// Algorithm. If you do use this data, or any transformation of it, in your own +// projects, commercial or otherwise, please give credit by indicating in your +// source code that the data is part of the author's implementation of the +// MarchingCubes Algorithm and that it came from the web address given above. +// (Simply copying and pasting the two lines of the previous paragraph would be +// perfect.) If you distribute a commercial product with source code included, +// then the credit in the source code is required. +// +// If you distribute any kind of product that uses this data, a credit visible to +// the end-user would be appreciated, but it is not required. However, you may +// not claim that the entire implementation of the MarchingCubes Algorithm is your +// own if you use the data in this file or any transformation of it. +// +// The format of the data in this file is described in the dissertation "Voxel- +// Based Terrain for Real-Time Virtual Simulations", available at the web page +// given above. References to sections and figures below pertain to that paper. +// +// The contents of this file are protected by copyright and may not be publicly +// reproduced without permission. +// +//================================================================================ + +namespace MarchingCubes { + +// The regularCellClass table maps an 8-bit regular Marching Cubes case index to +// an equivalence class index. Even though there are 18 equivalence classes in our +// modified Marching Cubes algorithm, a couple of them use the same exact triangulations, +// just with different vertex locations. We combined those classes for this table so +// that the class index ranges from 0 to 15. + +const unsigned char regularCellClass[256] = { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 0x00, 0x01, 0x01, 0x03, 0x01, 0x03, 0x02, 0x04, 0x01, 0x02, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, // 0 + 0x01, 0x03, 0x02, 0x04, 0x02, 0x04, 0x06, 0x0C, 0x02, 0x05, 0x05, 0x0B, 0x05, 0x0A, 0x07, 0x04, // 16 + 0x01, 0x02, 0x03, 0x04, 0x02, 0x05, 0x05, 0x0A, 0x02, 0x06, 0x04, 0x0C, 0x05, 0x07, 0x0B, 0x04, // 32 + 0x03, 0x04, 0x04, 0x03, 0x05, 0x0B, 0x07, 0x04, 0x05, 0x07, 0x0A, 0x04, 0x08, 0x0E, 0x0E, 0x03, // 48 + 0x01, 0x02, 0x02, 0x05, 0x03, 0x04, 0x05, 0x0B, 0x02, 0x06, 0x05, 0x07, 0x04, 0x0C, 0x0A, 0x04, // 64 + 0x03, 0x04, 0x05, 0x0A, 0x04, 0x03, 0x07, 0x04, 0x05, 0x07, 0x08, 0x0E, 0x0B, 0x04, 0x0E, 0x03, // 80 + 0x02, 0x06, 0x05, 0x07, 0x05, 0x07, 0x08, 0x0E, 0x06, 0x09, 0x07, 0x0F, 0x07, 0x0F, 0x0E, 0x0D, // 96 + 0x04, 0x0C, 0x0B, 0x04, 0x0A, 0x04, 0x0E, 0x03, 0x07, 0x0F, 0x0E, 0x0D, 0x0E, 0x0D, 0x02, 0x01, // 112 + 0x01, 0x02, 0x02, 0x05, 0x02, 0x05, 0x06, 0x07, 0x03, 0x05, 0x04, 0x0A, 0x04, 0x0B, 0x0C, 0x04, // 128 + 0x02, 0x05, 0x06, 0x07, 0x06, 0x07, 0x09, 0x0F, 0x05, 0x08, 0x07, 0x0E, 0x07, 0x0E, 0x0F, 0x0D, // 144 + 0x03, 0x05, 0x04, 0x0B, 0x05, 0x08, 0x07, 0x0E, 0x04, 0x07, 0x03, 0x04, 0x0A, 0x0E, 0x04, 0x03, // 160 + 0x04, 0x0A, 0x0C, 0x04, 0x07, 0x0E, 0x0F, 0x0D, 0x0B, 0x0E, 0x04, 0x03, 0x0E, 0x02, 0x0D, 0x01, // 176 + 0x03, 0x05, 0x05, 0x08, 0x04, 0x0A, 0x07, 0x0E, 0x04, 0x07, 0x0B, 0x0E, 0x03, 0x04, 0x04, 0x03, // 192 + 0x04, 0x0B, 0x07, 0x0E, 0x0C, 0x04, 0x0F, 0x0D, 0x0A, 0x0E, 0x0E, 0x02, 0x04, 0x03, 0x0D, 0x01, // 208 + 0x04, 0x07, 0x0A, 0x0E, 0x0B, 0x0E, 0x0E, 0x02, 0x0C, 0x0F, 0x04, 0x0D, 0x04, 0x0D, 0x03, 0x01, // 224 + 0x03, 0x04, 0x04, 0x03, 0x04, 0x03, 0x0D, 0x01, 0x04, 0x0D, 0x03, 0x01, 0x03, 0x01, 0x01, 0x00 // 240 +}; + +// The regularCellData table holds the triangulation data for all 16 distinct classes to +// which a case can be mapped by the regularCellClass table. + +const RegularCellData regularCellData[16] = { + { 0x00, {} }, + { 0x31, { 0, 1, 2 } }, + { 0x62, { 0, 1, 2, 3, 4, 5 } }, + { 0x62, { 0, 1, 2, 4, 5, 3 } }, //{ 0x42, { 0, 1, 2, 0, 2, 3 } } + { 0x93, { 0, 1, 4, 5, 3, 6, 7, 2, 8 } }, //{ 0x53, { 0, 1, 4, 1, 3, 4, 1, 2, 3 } } + { 0x73, { 0, 1, 2, 0, 2, 3, 4, 5, 6 } }, + { 0x93, { 0, 1, 2, 3, 4, 5, 6, 7, 8 } }, + { 0xC4, { 0, 1, 4, 8, 3, 9, 10, 2, 11, 5, 6, 7 } }, //7 { 0x84, { 0, 1, 4, 1, 3, 4, 1, 2, 3, 5, 6, 7 } }, + { 0x84, { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7 } }, + { 0xC4, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } }, + { 0xC4, { 0, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3 } }, //A { 0x64, { 0, 4, 5, 0, 1, 4, 1, 3, 4, 1, 2, 3 } }, + { 0xC4, { 0, 5, 4, 6, 8, 7, 9, 11, 10, 1, 3, 2 } }, //B { 0x64, { 0, 5, 4, 0, 4, 1, 1, 4, 3, 1, 3, 2 } }, + { 0xC4, { 0, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3 } }, //C { 0x64, { 0, 4, 5, 0, 3, 4, 0, 1, 3, 1, 2, 3 } }, + { 0xC4, { 0, 1, 2, 6, 7, 3, 8, 9, 4, 10, 11, 5 } }, //D { 0x64, { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5 } }, + { 0xF5, { 0, 1, 2, 7, 8, 3, 9, 10, 4, 11, 12, 5, 13, 14, 6 } }, //E { 0x75, { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6 } }, + { 0xF5, { 0, 4, 5, 9, 3, 10, 11, 1, 12, 13, 2, 14, 6, 7, 8 } } //F { 0x95, { 0, 4, 5, 0, 3, 4, 0, 1, 3, 1, 2, 3, 6, 7, 8 } } +}; + +// The regularVertexData table gives the vertex locations for every one of the 256 possible +// cases in the modified Marching Cubes algorithm. Each 16-bit value also provides information +// about whether a vertex can be reused from a neighboring cell. See Section 3.3 for details. +// The low byte contains the indexes for the two endpoints of the edge on which the vertex lies, +// as numbered in Figure 3.7. The high byte contains the vertex reuse data shown in Figure 3.8. + +const unsigned short regularVertexData[256][15] = { + {}, + { 0x6201, 0x5102, 0x3304 }, + { 0x6201, 0x2315, 0x4113 }, + { 0x5102, 0x3304, 0x2315, 0x4113, 0x5102, 0x2315 }, + { 0x5102, 0x4223, 0x1326 }, + { 0x3304, 0x6201, 0x4223, 0x1326, 0x3304, 0x4223 }, + { 0x6201, 0x2315, 0x4113, 0x5102, 0x4223, 0x1326 }, + { 0x4223, 0x1326, 0x3304, 0x2315, 0x4113, 0x1326, 0x4113, 0x1326, 0x2315 }, + { 0x4113, 0x8337, 0x4223 }, + { 0x6201, 0x5102, 0x3304, 0x4223, 0x4113, 0x8337 }, + { 0x6201, 0x2315, 0x8337, 0x4223, 0x6201, 0x8337 }, + { 0x5102, 0x3304, 0x2315, 0x8337, 0x4223, 0x3304, 0x4223, 0x3304, 0x8337 }, + { 0x5102, 0x4113, 0x8337, 0x1326, 0x5102, 0x8337 }, + { 0x4113, 0x8337, 0x1326, 0x3304, 0x6201, 0x8337, 0x6201, 0x8337, 0x3304 }, + { 0x6201, 0x2315, 0x8337, 0x1326, 0x5102, 0x2315, 0x5102, 0x2315, 0x1326 }, + { 0x3304, 0x2315, 0x8337, 0x1326, 0x3304, 0x8337 }, + //16 3 5 15 + { 0x3304, 0x1146, 0x2245 }, + { 0x6201, 0x5102, 0x1146, 0x2245, 0x6201, 0x1146 }, + { 0x6201, 0x2315, 0x4113, 0x3304, 0x1146, 0x2245 }, + { 0x2315, 0x4113, 0x5102, 0x1146, 0x2245, 0x4113, 0x2245, 0x4113, 0x1146 }, + { 0x5102, 0x4223, 0x1326, 0x3304, 0x1146, 0x2245 }, + { 0x1146, 0x2245, 0x6201, 0x4223, 0x1326, 0x2245, 0x1326, 0x2245, 0x4223 }, + { 0x3304, 0x1146, 0x2245, 0x6201, 0x2315, 0x4113, 0x5102, 0x4223, 0x1326 }, + { 0x4223, 0x1326, 0x1146, 0x2245, 0x2315, 0x4113, 0x4223, 0x2245, 0x2315, 0x4223, 0x1326, 0x2245 }, + { 0x4223, 0x4113, 0x8337, 0x3304, 0x1146, 0x2245 }, + { 0x6201, 0x5102, 0x1146, 0x2245, 0x4223, 0x4113, 0x8337 }, + { 0x4223, 0x6201, 0x2315, 0x8337, 0x3304, 0x1146, 0x2245 }, + { 0x4223, 0x8337, 0x2315, 0x2245, 0x1146, 0x5102, 0x4223, 0x8337, 0x1146, 0x8337, 0x2245, 0x1146 }, + { 0x5102, 0x4113, 0x8337, 0x1326, 0x3304, 0x1146, 0x2245 }, + { 0x4113, 0x8337, 0x1326, 0x1146, 0x2245, 0x6201, 0x4113, 0x8337, 0x2245, 0x8337, 0x1146, 0x2245 }, + { 0x6201, 0x2315, 0x8337, 0x1326, 0x5102, 0x3304, 0x1146, 0x2245, 0x2315, 0x5102, 0x2315, 0x1326 }, + { 0x2245, 0x2315, 0x8337, 0x1326, 0x1146, 0x2315, 0x1146, 0x2315, 0x1326 }, + //32 3 10 15 + { 0x2315, 0x2245, 0x8157 }, + { 0x6201, 0x5102, 0x3304, 0x2315, 0x2245, 0x8157 }, + { 0x4113, 0x6201, 0x2245, 0x8157, 0x4113, 0x2245 }, + { 0x2245, 0x8157, 0x4113, 0x5102, 0x3304, 0x8157, 0x3304, 0x8157, 0x5102 }, + { 0x5102, 0x4223, 0x1326, 0x2315, 0x2245, 0x8157 }, + { 0x6201, 0x4223, 0x1326, 0x3304, 0x2315, 0x2245, 0x8157 }, + { 0x6201, 0x2245, 0x8157, 0x4113, 0x5102, 0x4223, 0x1326 }, + { 0x4223, 0x1326, 0x3304, 0x2245, 0x8157, 0x4113, 0x4223, 0x1326, 0x8157, 0x1326, 0x2245, 0x8157 }, + { 0x4223, 0x4113, 0x8337, 0x2315, 0x2245, 0x8157 }, + { 0x6201, 0x5102, 0x3304, 0x4223, 0x4113, 0x8337, 0x2315, 0x2245, 0x8157 }, + { 0x8337, 0x4223, 0x6201, 0x2245, 0x8157, 0x4223, 0x8157, 0x4223, 0x2245 }, + { 0x5102, 0x3304, 0x2245, 0x8157, 0x8337, 0x4223, 0x5102, 0x8157, 0x8337, 0x5102, 0x3304, 0x8157 }, + { 0x5102, 0x4113, 0x8337, 0x1326, 0x2315, 0x2245, 0x8157 }, + { 0x4113, 0x8337, 0x1326, 0x3304, 0x6201, 0x2315, 0x2245, 0x8157, 0x8337, 0x6201, 0x8337, 0x3304 }, + { 0x5102, 0x1326, 0x8337, 0x8157, 0x2245, 0x6201, 0x5102, 0x1326, 0x2245, 0x1326, 0x8157, 0x2245 }, + { 0x8157, 0x8337, 0x1326, 0x3304, 0x2245, 0x8337, 0x2245, 0x8337, 0x3304 }, + //48 1 2 7 11 + { 0x2315, 0x3304, 0x1146, 0x8157, 0x2315, 0x1146 }, + { 0x6201, 0x5102, 0x1146, 0x8157, 0x2315, 0x5102, 0x2315, 0x5102, 0x8157 }, + { 0x3304, 0x1146, 0x8157, 0x4113, 0x6201, 0x1146, 0x6201, 0x1146, 0x4113 }, + { 0x4113, 0x5102, 0x1146, 0x8157, 0x4113, 0x1146 }, + { 0x2315, 0x3304, 0x1146, 0x8157, 0x5102, 0x4223, 0x1326 }, + { 0x1326, 0x4223, 0x6201, 0x2315, 0x8157, 0x1146, 0x1326, 0x4223, 0x8157, 0x4223, 0x2315, 0x8157 }, + { 0x3304, 0x1146, 0x8157, 0x4113, 0x6201, 0x5102, 0x4223, 0x1326, 0x1146, 0x6201, 0x1146, 0x4113 }, + { 0x1326, 0x1146, 0x8157, 0x4113, 0x4223, 0x1146, 0x4223, 0x1146, 0x4113 }, + { 0x2315, 0x3304, 0x1146, 0x8157, 0x4223, 0x4113, 0x8337 }, + { 0x6201, 0x5102, 0x1146, 0x8157, 0x2315, 0x4223, 0x4113, 0x8337, 0x5102, 0x2315, 0x5102, 0x8157 }, + { 0x3304, 0x1146, 0x8157, 0x8337, 0x4223, 0x6201, 0x3304, 0x1146, 0x4223, 0x1146, 0x8337, 0x4223 }, + { 0x4223, 0x5102, 0x1146, 0x8157, 0x8337, 0x5102, 0x8337, 0x5102, 0x8157 }, + { 0x2315, 0x3304, 0x1146, 0x8157, 0x5102, 0x4113, 0x8337, 0x1326 }, + { 0x6201, 0x4113, 0x8337, 0x1326, 0x1146, 0x8157, 0x2315, 0x6201, 0x8337, 0x6201, 0x1326, 0x6201, 0x1146, 0x6201, 0x8157 }, + { 0x6201, 0x3304, 0x1146, 0x8157, 0x8337, 0x1326, 0x5102, 0x6201, 0x1146, 0x6201, 0x8157, 0x6201, 0x8337, 0x6201, 0x1326 }, + { 0x1326, 0x1146, 0x8157, 0x8337, 0x1326, 0x8157 }, + //64 5 12 15 + { 0x1326, 0x8267, 0x1146 }, + { 0x6201, 0x5102, 0x3304, 0x1326, 0x8267, 0x1146 }, + { 0x6201, 0x2315, 0x4113, 0x1326, 0x8267, 0x1146 }, + { 0x5102, 0x3304, 0x2315, 0x4113, 0x1326, 0x8267, 0x1146 }, + { 0x5102, 0x4223, 0x8267, 0x1146, 0x5102, 0x8267 }, + { 0x3304, 0x6201, 0x4223, 0x8267, 0x1146, 0x6201, 0x1146, 0x6201, 0x8267 }, + { 0x5102, 0x4223, 0x8267, 0x1146, 0x6201, 0x2315, 0x4113 }, + { 0x1146, 0x8267, 0x4223, 0x4113, 0x2315, 0x3304, 0x1146, 0x8267, 0x2315, 0x8267, 0x4113, 0x2315 }, + { 0x4113, 0x8337, 0x4223, 0x1326, 0x8267, 0x1146 }, + { 0x6201, 0x5102, 0x3304, 0x4223, 0x4113, 0x8337, 0x1326, 0x8267, 0x1146 }, + { 0x6201, 0x2315, 0x8337, 0x4223, 0x1326, 0x8267, 0x1146 }, + { 0x5102, 0x3304, 0x2315, 0x8337, 0x4223, 0x1326, 0x8267, 0x1146, 0x3304, 0x4223, 0x3304, 0x8337 }, + { 0x8267, 0x1146, 0x5102, 0x4113, 0x8337, 0x1146, 0x8337, 0x1146, 0x4113 }, + { 0x6201, 0x4113, 0x8337, 0x8267, 0x1146, 0x3304, 0x6201, 0x8267, 0x1146, 0x6201, 0x4113, 0x8267 }, + { 0x6201, 0x2315, 0x8337, 0x8267, 0x1146, 0x5102, 0x6201, 0x2315, 0x1146, 0x2315, 0x8267, 0x1146 }, + { 0x1146, 0x3304, 0x2315, 0x8337, 0x8267, 0x3304, 0x8267, 0x3304, 0x8337 }, + //80 1 4 7 13 + { 0x3304, 0x1326, 0x8267, 0x2245, 0x3304, 0x8267 }, + { 0x1326, 0x8267, 0x2245, 0x6201, 0x5102, 0x8267, 0x5102, 0x8267, 0x6201 }, + { 0x3304, 0x1326, 0x8267, 0x2245, 0x6201, 0x2315, 0x4113 }, + { 0x1326, 0x8267, 0x2245, 0x2315, 0x4113, 0x5102, 0x1326, 0x8267, 0x4113, 0x8267, 0x2315, 0x4113 }, + { 0x5102, 0x4223, 0x8267, 0x2245, 0x3304, 0x4223, 0x3304, 0x4223, 0x2245 }, + { 0x6201, 0x4223, 0x8267, 0x2245, 0x6201, 0x8267 }, + { 0x5102, 0x4223, 0x8267, 0x2245, 0x3304, 0x6201, 0x2315, 0x4113, 0x4223, 0x3304, 0x4223, 0x2245 }, + { 0x4113, 0x4223, 0x8267, 0x2245, 0x2315, 0x4223, 0x2315, 0x4223, 0x2245 }, + { 0x3304, 0x1326, 0x8267, 0x2245, 0x4223, 0x4113, 0x8337 }, + { 0x1326, 0x8267, 0x2245, 0x6201, 0x5102, 0x4223, 0x4113, 0x8337, 0x8267, 0x5102, 0x8267, 0x6201 }, + { 0x3304, 0x1326, 0x8267, 0x2245, 0x4223, 0x6201, 0x2315, 0x8337 }, + { 0x5102, 0x1326, 0x8267, 0x2245, 0x2315, 0x8337, 0x4223, 0x5102, 0x8267, 0x5102, 0x2245, 0x5102, 0x2315, 0x5102, 0x8337 }, + { 0x3304, 0x2245, 0x8267, 0x8337, 0x4113, 0x5102, 0x3304, 0x2245, 0x4113, 0x2245, 0x8337, 0x4113 }, + { 0x8337, 0x8267, 0x2245, 0x6201, 0x4113, 0x8267, 0x4113, 0x8267, 0x6201 }, + { 0x5102, 0x6201, 0x2315, 0x8337, 0x8267, 0x2245, 0x3304, 0x5102, 0x2315, 0x5102, 0x8337, 0x5102, 0x8267, 0x5102, 0x2245 }, + { 0x2315, 0x8337, 0x8267, 0x2245, 0x2315, 0x8267 }, + //96 - + { 0x2315, 0x2245, 0x8157, 0x1326, 0x8267, 0x1146 }, + { 0x6201, 0x5102, 0x3304, 0x2315, 0x2245, 0x8157, 0x1326, 0x8267, 0x1146 }, + { 0x6201, 0x2245, 0x8157, 0x4113, 0x1326, 0x8267, 0x1146 }, + { 0x2245, 0x8157, 0x4113, 0x5102, 0x3304, 0x1326, 0x8267, 0x1146, 0x8157, 0x3304, 0x8157, 0x5102 }, + { 0x4223, 0x8267, 0x1146, 0x5102, 0x2315, 0x2245, 0x8157 }, + { 0x3304, 0x6201, 0x4223, 0x8267, 0x1146, 0x2315, 0x2245, 0x8157, 0x6201, 0x1146, 0x6201, 0x8267 }, + { 0x4223, 0x8267, 0x1146, 0x5102, 0x6201, 0x2245, 0x8157, 0x4113 }, + { 0x3304, 0x2245, 0x8157, 0x4113, 0x4223, 0x8267, 0x1146, 0x3304, 0x8157, 0x3304, 0x4113, 0x3304, 0x4223, 0x3304, 0x8267 }, + { 0x4223, 0x4113, 0x8337, 0x2315, 0x2245, 0x8157, 0x1326, 0x8267, 0x1146 }, + { 0x6201, 0x5102, 0x3304, 0x4223, 0x4113, 0x8337, 0x2315, 0x2245, 0x8157, 0x1326, 0x8267, 0x1146 }, + { 0x8337, 0x4223, 0x6201, 0x2245, 0x8157, 0x1326, 0x8267, 0x1146, 0x4223, 0x8157, 0x4223, 0x2245 }, + { 0x4223, 0x5102, 0x3304, 0x2245, 0x8157, 0x8337, 0x1326, 0x8267, 0x1146, 0x4223, 0x8157, 0x4223, 0x2245, 0x5102, 0x2245 }, + { 0x8267, 0x1146, 0x5102, 0x4113, 0x8337, 0x2315, 0x2245, 0x8157, 0x1146, 0x8337, 0x1146, 0x4113 }, + { 0x6201, 0x4113, 0x8337, 0x8267, 0x1146, 0x3304, 0x2315, 0x2245, 0x8157, 0x6201, 0x1146, 0x6201, 0x8267, 0x4113, 0x8267 }, + { 0x8337, 0x8267, 0x1146, 0x5102, 0x6201, 0x2245, 0x8157, 0x8337, 0x1146, 0x8337, 0x5102, 0x8337, 0x6201, 0x8337, 0x2245 }, + { 0x3304, 0x2245, 0x8157, 0x8337, 0x8267, 0x1146, 0x3304, 0x8157, 0x3304, 0x8337, 0x3304, 0x8267 }, + //112 0 3 5 + { 0x8157, 0x2315, 0x3304, 0x1326, 0x8267, 0x2315, 0x8267, 0x2315, 0x1326 }, + { 0x8267, 0x8157, 0x2315, 0x6201, 0x5102, 0x1326, 0x8267, 0x6201, 0x5102, 0x8267, 0x8157, 0x6201 }, + { 0x8267, 0x1326, 0x3304, 0x6201, 0x4113, 0x8157, 0x8267, 0x1326, 0x4113, 0x1326, 0x6201, 0x4113 }, + { 0x8267, 0x8157, 0x4113, 0x5102, 0x1326, 0x8157, 0x1326, 0x8157, 0x5102 }, + { 0x5102, 0x4223, 0x8267, 0x8157, 0x2315, 0x3304, 0x5102, 0x4223, 0x2315, 0x4223, 0x8157, 0x2315 }, + { 0x2315, 0x6201, 0x4223, 0x8267, 0x8157, 0x6201, 0x8157, 0x6201, 0x8267 }, + { 0x3304, 0x5102, 0x4223, 0x8267, 0x8157, 0x4113, 0x6201, 0x3304, 0x4223, 0x3304, 0x8267, 0x3304, 0x8157, 0x3304, 0x4113 }, + { 0x4113, 0x4223, 0x8267, 0x8157, 0x4113, 0x8267 }, + { 0x8157, 0x2315, 0x3304, 0x1326, 0x8267, 0x4223, 0x4113, 0x8337, 0x2315, 0x8267, 0x2315, 0x1326 }, + { 0x8157, 0x2315, 0x6201, 0x5102, 0x1326, 0x8267, 0x4223, 0x4113, 0x8337, 0x8157, 0x1326, 0x8157, 0x5102, 0x2315, 0x5102 }, + { 0x8157, 0x8337, 0x4223, 0x6201, 0x3304, 0x1326, 0x8267, 0x8157, 0x4223, 0x8157, 0x6201, 0x8157, 0x3304, 0x8157, 0x1326 }, + { 0x5102, 0x1326, 0x8267, 0x8157, 0x8337, 0x4223, 0x5102, 0x8267, 0x5102, 0x8157, 0x5102, 0x8337 }, + { 0x8267, 0x8157, 0x2315, 0x3304, 0x5102, 0x4113, 0x8337, 0x8267, 0x2315, 0x8267, 0x3304, 0x8267, 0x5102, 0x8267, 0x4113 }, + { 0x6201, 0x4113, 0x8337, 0x8267, 0x8157, 0x2315, 0x6201, 0x8337, 0x6201, 0x8267, 0x6201, 0x8157 }, + { 0x6201, 0x3304, 0x5102, 0x8337, 0x8267, 0x8157 }, + { 0x8337, 0x8267, 0x8157 }, + //128 10 12 15 + { 0x8337, 0x8157, 0x8267 }, + { 0x6201, 0x5102, 0x3304, 0x8337, 0x8157, 0x8267 }, + { 0x6201, 0x2315, 0x4113, 0x8337, 0x8157, 0x8267 }, + { 0x5102, 0x3304, 0x2315, 0x4113, 0x8337, 0x8157, 0x8267 }, + { 0x5102, 0x4223, 0x1326, 0x8337, 0x8157, 0x8267 }, + { 0x6201, 0x4223, 0x1326, 0x3304, 0x8337, 0x8157, 0x8267 }, + { 0x6201, 0x2315, 0x4113, 0x5102, 0x4223, 0x1326, 0x8337, 0x8157, 0x8267 }, + { 0x4223, 0x1326, 0x3304, 0x2315, 0x4113, 0x8337, 0x8157, 0x8267, 0x1326, 0x4113, 0x1326, 0x2315 }, + { 0x4113, 0x8157, 0x8267, 0x4223, 0x4113, 0x8267 }, + { 0x4223, 0x4113, 0x8157, 0x8267, 0x6201, 0x5102, 0x3304 }, + { 0x8157, 0x8267, 0x4223, 0x6201, 0x2315, 0x8267, 0x2315, 0x8267, 0x6201 }, + { 0x3304, 0x2315, 0x8157, 0x8267, 0x4223, 0x5102, 0x3304, 0x2315, 0x4223, 0x2315, 0x8267, 0x4223 }, + { 0x1326, 0x5102, 0x4113, 0x8157, 0x8267, 0x5102, 0x8267, 0x5102, 0x8157 }, + { 0x8157, 0x4113, 0x6201, 0x3304, 0x1326, 0x8267, 0x8157, 0x4113, 0x1326, 0x4113, 0x3304, 0x1326 }, + { 0x1326, 0x5102, 0x6201, 0x2315, 0x8157, 0x8267, 0x1326, 0x2315, 0x8157, 0x1326, 0x5102, 0x2315 }, + { 0x8267, 0x1326, 0x3304, 0x2315, 0x8157, 0x1326, 0x8157, 0x1326, 0x2315 }, + //144 - + { 0x3304, 0x1146, 0x2245, 0x8337, 0x8157, 0x8267 }, + { 0x6201, 0x5102, 0x1146, 0x2245, 0x8337, 0x8157, 0x8267 }, + { 0x6201, 0x2315, 0x4113, 0x3304, 0x1146, 0x2245, 0x8337, 0x8157, 0x8267 }, + { 0x2315, 0x4113, 0x5102, 0x1146, 0x2245, 0x8337, 0x8157, 0x8267, 0x4113, 0x2245, 0x4113, 0x1146 }, + { 0x5102, 0x4223, 0x1326, 0x3304, 0x1146, 0x2245, 0x8337, 0x8157, 0x8267 }, + { 0x1146, 0x2245, 0x6201, 0x4223, 0x1326, 0x8337, 0x8157, 0x8267, 0x2245, 0x1326, 0x2245, 0x4223 }, + { 0x6201, 0x2315, 0x4113, 0x5102, 0x4223, 0x1326, 0x3304, 0x1146, 0x2245, 0x8337, 0x8157, 0x8267 }, + { 0x4113, 0x4223, 0x1326, 0x1146, 0x2245, 0x2315, 0x8337, 0x8157, 0x8267, 0x4113, 0x2245, 0x4113, 0x1146, 0x4223, 0x1146 }, + { 0x4223, 0x4113, 0x8157, 0x8267, 0x3304, 0x1146, 0x2245 }, + { 0x6201, 0x5102, 0x1146, 0x2245, 0x4223, 0x4113, 0x8157, 0x8267 }, + { 0x8157, 0x8267, 0x4223, 0x6201, 0x2315, 0x3304, 0x1146, 0x2245, 0x8267, 0x2315, 0x8267, 0x6201 }, + { 0x2315, 0x8157, 0x8267, 0x4223, 0x5102, 0x1146, 0x2245, 0x2315, 0x8267, 0x2315, 0x4223, 0x2315, 0x5102, 0x2315, 0x1146 }, + { 0x1326, 0x5102, 0x4113, 0x8157, 0x8267, 0x3304, 0x1146, 0x2245, 0x5102, 0x8267, 0x5102, 0x8157 }, + { 0x1326, 0x1146, 0x2245, 0x6201, 0x4113, 0x8157, 0x8267, 0x1326, 0x2245, 0x1326, 0x6201, 0x1326, 0x4113, 0x1326, 0x8157 }, + { 0x5102, 0x6201, 0x2315, 0x8157, 0x8267, 0x1326, 0x3304, 0x1146, 0x2245, 0x5102, 0x8267, 0x5102, 0x8157, 0x6201, 0x8157 }, + { 0x1326, 0x1146, 0x2245, 0x2315, 0x8157, 0x8267, 0x1326, 0x2245, 0x1326, 0x2315, 0x1326, 0x8157 }, + //160 2 8 11 14 + { 0x2315, 0x2245, 0x8267, 0x8337, 0x2315, 0x8267 }, + { 0x2315, 0x2245, 0x8267, 0x8337, 0x6201, 0x5102, 0x3304 }, + { 0x4113, 0x6201, 0x2245, 0x8267, 0x8337, 0x6201, 0x8337, 0x6201, 0x8267 }, + { 0x5102, 0x4113, 0x8337, 0x8267, 0x2245, 0x3304, 0x5102, 0x4113, 0x2245, 0x4113, 0x8267, 0x2245 }, + { 0x2315, 0x2245, 0x8267, 0x8337, 0x5102, 0x4223, 0x1326 }, + { 0x6201, 0x4223, 0x1326, 0x3304, 0x8337, 0x2315, 0x2245, 0x8267 }, + { 0x4113, 0x6201, 0x2245, 0x8267, 0x8337, 0x5102, 0x4223, 0x1326, 0x6201, 0x8337, 0x6201, 0x8267 }, + { 0x4113, 0x4223, 0x1326, 0x3304, 0x2245, 0x8267, 0x8337, 0x4113, 0x1326, 0x4113, 0x3304, 0x4113, 0x2245, 0x4113, 0x8267 }, + { 0x2315, 0x2245, 0x8267, 0x4223, 0x4113, 0x2245, 0x4113, 0x2245, 0x4223 }, + { 0x2315, 0x2245, 0x8267, 0x4223, 0x4113, 0x6201, 0x5102, 0x3304, 0x2245, 0x4113, 0x2245, 0x4223 }, + { 0x6201, 0x2245, 0x8267, 0x4223, 0x6201, 0x8267 }, + { 0x3304, 0x2245, 0x8267, 0x4223, 0x5102, 0x2245, 0x5102, 0x2245, 0x4223 }, + { 0x5102, 0x4113, 0x2315, 0x2245, 0x8267, 0x1326, 0x5102, 0x4113, 0x8267, 0x4113, 0x2245, 0x8267 }, + { 0x4113, 0x2315, 0x2245, 0x8267, 0x1326, 0x3304, 0x6201, 0x4113, 0x2245, 0x4113, 0x8267, 0x4113, 0x1326, 0x4113, 0x3304 }, + { 0x5102, 0x6201, 0x2245, 0x8267, 0x1326, 0x6201, 0x1326, 0x6201, 0x8267 }, + { 0x3304, 0x2245, 0x8267, 0x1326, 0x3304, 0x8267 }, + //176 0 3 10 + { 0x8267, 0x8337, 0x2315, 0x3304, 0x1146, 0x8337, 0x1146, 0x8337, 0x3304 }, + { 0x5102, 0x1146, 0x8267, 0x8337, 0x2315, 0x6201, 0x5102, 0x1146, 0x2315, 0x1146, 0x8337, 0x2315 }, + { 0x3304, 0x1146, 0x8267, 0x8337, 0x4113, 0x6201, 0x3304, 0x8337, 0x4113, 0x3304, 0x1146, 0x8337 }, + { 0x8337, 0x4113, 0x5102, 0x1146, 0x8267, 0x4113, 0x8267, 0x4113, 0x1146 }, + { 0x8267, 0x8337, 0x2315, 0x3304, 0x1146, 0x5102, 0x4223, 0x1326, 0x8337, 0x1146, 0x8337, 0x3304 }, + { 0x1146, 0x8267, 0x8337, 0x2315, 0x6201, 0x4223, 0x1326, 0x1146, 0x8337, 0x1146, 0x2315, 0x1146, 0x6201, 0x1146, 0x4223 }, + { 0x8267, 0x8337, 0x4113, 0x6201, 0x3304, 0x1146, 0x5102, 0x4223, 0x1326, 0x8267, 0x3304, 0x8267, 0x6201, 0x8337, 0x6201 }, + { 0x4113, 0x4223, 0x1326, 0x1146, 0x8267, 0x8337, 0x4113, 0x1326, 0x4113, 0x1146, 0x4113, 0x8267 }, + { 0x3304, 0x2315, 0x4113, 0x4223, 0x8267, 0x1146, 0x3304, 0x2315, 0x8267, 0x2315, 0x4223, 0x8267 }, + { 0x2315, 0x6201, 0x5102, 0x1146, 0x8267, 0x4223, 0x4113, 0x2315, 0x5102, 0x2315, 0x1146, 0x2315, 0x8267, 0x2315, 0x4223 }, + { 0x1146, 0x8267, 0x4223, 0x6201, 0x3304, 0x8267, 0x3304, 0x8267, 0x6201 }, + { 0x5102, 0x1146, 0x8267, 0x4223, 0x5102, 0x8267 }, + { 0x8267, 0x1326, 0x5102, 0x4113, 0x2315, 0x3304, 0x1146, 0x8267, 0x5102, 0x8267, 0x4113, 0x8267, 0x2315, 0x8267, 0x3304 }, + { 0x6201, 0x4113, 0x2315, 0x1326, 0x1146, 0x8267 }, + { 0x6201, 0x3304, 0x1146, 0x8267, 0x1326, 0x5102, 0x6201, 0x1146, 0x6201, 0x8267, 0x6201, 0x1326 }, + { 0x1326, 0x1146, 0x8267 }, + //192 4 8 13 14 + { 0x1326, 0x8337, 0x8157, 0x1146, 0x1326, 0x8157 }, + { 0x8337, 0x8157, 0x1146, 0x1326, 0x6201, 0x5102, 0x3304 }, + { 0x8337, 0x8157, 0x1146, 0x1326, 0x6201, 0x2315, 0x4113 }, + { 0x4113, 0x5102, 0x3304, 0x2315, 0x1326, 0x8337, 0x8157, 0x1146 }, + { 0x8337, 0x8157, 0x1146, 0x5102, 0x4223, 0x8157, 0x4223, 0x8157, 0x5102 }, + { 0x6201, 0x4223, 0x8337, 0x8157, 0x1146, 0x3304, 0x6201, 0x4223, 0x1146, 0x4223, 0x8157, 0x1146 }, + { 0x8337, 0x8157, 0x1146, 0x5102, 0x4223, 0x6201, 0x2315, 0x4113, 0x8157, 0x4223, 0x8157, 0x5102 }, + { 0x4223, 0x8337, 0x8157, 0x1146, 0x3304, 0x2315, 0x4113, 0x4223, 0x8157, 0x4223, 0x1146, 0x4223, 0x3304, 0x4223, 0x2315 }, + { 0x4223, 0x4113, 0x8157, 0x1146, 0x1326, 0x4113, 0x1326, 0x4113, 0x1146 }, + { 0x4223, 0x4113, 0x8157, 0x1146, 0x1326, 0x6201, 0x5102, 0x3304, 0x4113, 0x1326, 0x4113, 0x1146 }, + { 0x1146, 0x8157, 0x2315, 0x6201, 0x4223, 0x1326, 0x1146, 0x8157, 0x4223, 0x8157, 0x6201, 0x4223 }, + { 0x4223, 0x5102, 0x3304, 0x2315, 0x8157, 0x1146, 0x1326, 0x4223, 0x3304, 0x4223, 0x2315, 0x4223, 0x8157, 0x4223, 0x1146 }, + { 0x4113, 0x8157, 0x1146, 0x5102, 0x4113, 0x1146 }, + { 0x6201, 0x4113, 0x8157, 0x1146, 0x3304, 0x4113, 0x3304, 0x4113, 0x1146 }, + { 0x2315, 0x8157, 0x1146, 0x5102, 0x6201, 0x8157, 0x6201, 0x8157, 0x5102 }, + { 0x2315, 0x8157, 0x1146, 0x3304, 0x2315, 0x1146 }, + //208 0 5 12 + { 0x2245, 0x3304, 0x1326, 0x8337, 0x8157, 0x3304, 0x8157, 0x3304, 0x8337 }, + { 0x6201, 0x2245, 0x8157, 0x8337, 0x1326, 0x5102, 0x6201, 0x2245, 0x1326, 0x2245, 0x8337, 0x1326 }, + { 0x2245, 0x3304, 0x1326, 0x8337, 0x8157, 0x6201, 0x2315, 0x4113, 0x3304, 0x8157, 0x3304, 0x8337 }, + { 0x2245, 0x2315, 0x4113, 0x5102, 0x1326, 0x8337, 0x8157, 0x2245, 0x4113, 0x2245, 0x5102, 0x2245, 0x1326, 0x2245, 0x8337 }, + { 0x4223, 0x8337, 0x8157, 0x2245, 0x3304, 0x5102, 0x4223, 0x2245, 0x3304, 0x4223, 0x8337, 0x2245 }, + { 0x8157, 0x2245, 0x6201, 0x4223, 0x8337, 0x2245, 0x8337, 0x2245, 0x4223 }, + { 0x2245, 0x3304, 0x5102, 0x4223, 0x8337, 0x8157, 0x4113, 0x6201, 0x2315, 0x2245, 0x8337, 0x2245, 0x4223, 0x3304, 0x4223 }, + { 0x4223, 0x8337, 0x8157, 0x2245, 0x2315, 0x4113, 0x4223, 0x8157, 0x4223, 0x2245, 0x4223, 0x2315 }, + { 0x4113, 0x8157, 0x2245, 0x3304, 0x1326, 0x4223, 0x4113, 0x8157, 0x1326, 0x8157, 0x3304, 0x1326 }, + { 0x1326, 0x4223, 0x4113, 0x8157, 0x2245, 0x6201, 0x5102, 0x1326, 0x4113, 0x1326, 0x8157, 0x1326, 0x2245, 0x1326, 0x6201 }, + { 0x8157, 0x2245, 0x3304, 0x1326, 0x4223, 0x6201, 0x2315, 0x8157, 0x3304, 0x8157, 0x1326, 0x8157, 0x4223, 0x8157, 0x6201 }, + { 0x5102, 0x1326, 0x4223, 0x2315, 0x8157, 0x2245 }, + { 0x3304, 0x5102, 0x4113, 0x8157, 0x2245, 0x5102, 0x2245, 0x5102, 0x8157 }, + { 0x4113, 0x8157, 0x2245, 0x6201, 0x4113, 0x2245 }, + { 0x5102, 0x6201, 0x2315, 0x8157, 0x2245, 0x3304, 0x5102, 0x2315, 0x5102, 0x8157, 0x5102, 0x2245 }, + { 0x2315, 0x8157, 0x2245 }, + //224 0 10 12 + { 0x1146, 0x1326, 0x8337, 0x2315, 0x2245, 0x1326, 0x2245, 0x1326, 0x2315 }, + { 0x1146, 0x1326, 0x8337, 0x2315, 0x2245, 0x6201, 0x5102, 0x3304, 0x1326, 0x2245, 0x1326, 0x2315 }, + { 0x6201, 0x2245, 0x1146, 0x1326, 0x8337, 0x4113, 0x6201, 0x2245, 0x8337, 0x2245, 0x1326, 0x8337 }, + { 0x2245, 0x1146, 0x1326, 0x8337, 0x4113, 0x5102, 0x3304, 0x2245, 0x1326, 0x2245, 0x8337, 0x2245, 0x4113, 0x2245, 0x5102 }, + { 0x5102, 0x1146, 0x2245, 0x2315, 0x8337, 0x4223, 0x5102, 0x1146, 0x8337, 0x1146, 0x2315, 0x8337 }, + { 0x1146, 0x3304, 0x6201, 0x4223, 0x8337, 0x2315, 0x2245, 0x1146, 0x6201, 0x1146, 0x4223, 0x1146, 0x8337, 0x1146, 0x2315 }, + { 0x8337, 0x4113, 0x6201, 0x2245, 0x1146, 0x5102, 0x4223, 0x8337, 0x6201, 0x8337, 0x2245, 0x8337, 0x1146, 0x8337, 0x5102 }, + { 0x4223, 0x8337, 0x4113, 0x3304, 0x2245, 0x1146 }, + { 0x4113, 0x2315, 0x2245, 0x1146, 0x1326, 0x4223, 0x4113, 0x1146, 0x1326, 0x4113, 0x2315, 0x1146 }, + { 0x1146, 0x1326, 0x4223, 0x4113, 0x2315, 0x2245, 0x6201, 0x5102, 0x3304, 0x1146, 0x2315, 0x1146, 0x4113, 0x1326, 0x4113 }, + { 0x1326, 0x4223, 0x6201, 0x2245, 0x1146, 0x4223, 0x1146, 0x4223, 0x2245 }, + { 0x4223, 0x5102, 0x3304, 0x2245, 0x1146, 0x1326, 0x4223, 0x3304, 0x4223, 0x2245, 0x4223, 0x1146 }, + { 0x2245, 0x1146, 0x5102, 0x4113, 0x2315, 0x1146, 0x2315, 0x1146, 0x4113 }, + { 0x4113, 0x2315, 0x2245, 0x1146, 0x3304, 0x6201, 0x4113, 0x2245, 0x4113, 0x1146, 0x4113, 0x3304 }, + { 0x6201, 0x2245, 0x1146, 0x5102, 0x6201, 0x1146 }, + { 0x3304, 0x2245, 0x1146 }, + //240 1 2 4 8 + { 0x3304, 0x1326, 0x8337, 0x2315, 0x3304, 0x8337 }, + { 0x5102, 0x1326, 0x8337, 0x2315, 0x6201, 0x1326, 0x6201, 0x1326, 0x2315 }, + { 0x6201, 0x3304, 0x1326, 0x8337, 0x4113, 0x3304, 0x4113, 0x3304, 0x8337 }, + { 0x5102, 0x1326, 0x8337, 0x4113, 0x5102, 0x8337 }, + { 0x4223, 0x8337, 0x2315, 0x3304, 0x5102, 0x8337, 0x5102, 0x8337, 0x3304 }, + { 0x6201, 0x4223, 0x8337, 0x2315, 0x6201, 0x8337 }, + { 0x3304, 0x5102, 0x4223, 0x8337, 0x4113, 0x6201, 0x3304, 0x4223, 0x3304, 0x8337, 0x3304, 0x4113 }, + { 0x4113, 0x4223, 0x8337 }, + { 0x4113, 0x2315, 0x3304, 0x1326, 0x4223, 0x2315, 0x4223, 0x2315, 0x1326 }, + { 0x1326, 0x4223, 0x4113, 0x2315, 0x6201, 0x5102, 0x1326, 0x4113, 0x1326, 0x2315, 0x1326, 0x6201 }, + { 0x3304, 0x1326, 0x4223, 0x6201, 0x3304, 0x4223 }, + { 0x5102, 0x1326, 0x4223 }, + { 0x5102, 0x4113, 0x2315, 0x3304, 0x5102, 0x2315 }, + { 0x6201, 0x4113, 0x2315 }, + { 0x6201, 0x3304, 0x5102 }, + {} + //256 +}; + +const Vector3 marching_cube_vertices[8] = { + Vector3(0, 0, 0), + Vector3(1, 0, 0), + Vector3(0, 0, 1), + Vector3(1, 0, 1), + Vector3(0, 1, 0), + Vector3(1, 1, 0), + Vector3(0, 1, 1), + Vector3(1, 1, 1) +}; + +} // namespace MarchingCubes diff --git a/meshers/marching_cubes/marching_cubes_tables.h b/meshers/marching_cubes/marching_cubes_tables.h new file mode 100644 index 0000000..6af4635 --- /dev/null +++ b/meshers/marching_cubes/marching_cubes_tables.h @@ -0,0 +1,67 @@ +//Please note, that these tables were modified to get support for uv-mapping! + +//================================================================================ +// +// The MarchingCubes Algorithm look-up tables +// +// Copyright 2009 by Eric Lengyel +// +// The following data originates from Eric Lengyel's MarchingCubes Algorithm. +// http://transvoxel.org/ +// +// The data in this file may be freely used in implementations of the MarchingCubes +// Algorithm. If you do use this data, or any transformation of it, in your own +// projects, commercial or otherwise, please give credit by indicating in your +// source code that the data is part of the author's implementation of the +// MarchingCubes Algorithm and that it came from the web address given above. +// (Simply copying and pasting the two lines of the previous paragraph would be +// perfect.) If you distribute a commercial product with source code included, +// then the credit in the source code is required. +// +// If you distribute any kind of product that uses this data, a credit visible to +// the end-user would be appreciated, but it is not required. However, you may +// not claim that the entire implementation of the MarchingCubes Algorithm is your +// own if you use the data in this file or any transformation of it. +// +// The format of the data in this file is described in the dissertation "Voxel- +// Based Terrain for Real-Time Virtual Simulations", available at the web page +// given above. References to sections and figures below pertain to that paper. +// +// The contents of this file are protected by copyright and may not be publicly +// reproduced without permission. +// +//================================================================================ + +#ifndef MARCHING_CUBES_TABLES_H +#define MARCHING_CUBES_TABLES_H + +#include "core/math/vector3.h" + +namespace MarchingCubes { + +// The RegularCellData structure holds information about the triangulation +// used for a single equivalence class in the modified Marching Cubes algorithm, +// described in Section 3.2. + +struct RegularCellData { + unsigned char geometryCounts; // High nibble is vertex count, low nibble is triangle count. + unsigned char vertexIndex[15]; // Groups of 3 indexes giving the triangulation. + + long GetVertexCount(void) const { + return (geometryCounts >> 4); + } + + long GetTriangleCount(void) const { + return (geometryCounts & 0x0F); + } +}; + +extern const unsigned char regularCellClass[256]; +extern const RegularCellData regularCellData[16]; +extern const unsigned short regularVertexData[256][15]; + +extern const Vector3 marching_cube_vertices[8]; + +} // namespace MarchingCubes + +#endif diff --git a/meshers/marching_cubes/voxel_mesher_marching_cubes.cpp b/meshers/marching_cubes/voxel_mesher_marching_cubes.cpp new file mode 100644 index 0000000..c93650e --- /dev/null +++ b/meshers/marching_cubes/voxel_mesher_marching_cubes.cpp @@ -0,0 +1,554 @@ +/* +Copyright (c) 2019-2020 Péter Magyar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "voxel_mesher_marching_cubes.h" + +#include "../../world/default/voxel_chunk_default.h" +#include "../../world/voxel_chunk.h" +#include "core/array.h" +#include "core/dictionary.h" + +#include "core/version.h" + +#if VERSION_MAJOR < 4 +#include "servers/visual_server.h" +#else +#include "servers/rendering_server.h" + +typedef class RenderingServer VisualServer; +#endif + +int VoxelMesherMarchingCubes::get_texture_scale() const { + return _texture_scale; +} +void VoxelMesherMarchingCubes::set_texture_scale(const int value) { + _texture_scale = value; +} + +void VoxelMesherMarchingCubes::get_voxel_type_array(int *arr, Ref chunk, const int x, const int y, const int z, const int size) { + uint8_t *channel_type = chunk->get_channel(VoxelChunkDefault::DEFAULT_CHANNEL_TYPE); + + if (channel_type == NULL) { + arr[0] = 0; + arr[1] = 0; + arr[2] = 0; + arr[3] = 0; + arr[4] = 0; + arr[5] = 0; + arr[6] = 0; + arr[7] = 0; + return; + } + + arr[0] = channel_type[chunk->get_index(x, y, z)]; + arr[1] = channel_type[chunk->get_index(x, y + size, z)]; + arr[2] = channel_type[chunk->get_index(x, y, z + size)]; + arr[3] = channel_type[chunk->get_index(x, y + size, z + size)]; + arr[4] = channel_type[chunk->get_index(x + size, y, z)]; + arr[5] = channel_type[chunk->get_index(x + size, y + size, z)]; + arr[6] = channel_type[chunk->get_index(x + size, y, z + size)]; + arr[7] = channel_type[chunk->get_index(x + size, y + size, z + size)]; +} +int VoxelMesherMarchingCubes::get_case_code_from_arr(const int *data) { + int case_code = 0; + + if (data[0] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_000; + + if (data[1] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_010; + + if (data[2] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_001; + + if (data[3] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_011; + + if (data[4] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_100; + + if (data[5] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_110; + + if (data[6] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_101; + + if (data[7] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_111; + + return case_code; +} +int VoxelMesherMarchingCubes::get_case_code(Ref chunk, const int x, const int y, const int z, const int size) { + uint8_t *channel_type = chunk->get_channel(VoxelChunkDefault::DEFAULT_CHANNEL_TYPE); + + if (channel_type == NULL) { + return 0; + } + + int case_code = 0; + + if (channel_type[chunk->get_index(x, y, z)] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_000; + + if (channel_type[chunk->get_index(x, y + size, z)] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_010; + + if (channel_type[chunk->get_index(x, y, z + size)] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_001; + + if (channel_type[chunk->get_index(x, y + size, z + size)] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_011; + + if (channel_type[chunk->get_index(x + size, y, z)] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_100; + + if (channel_type[chunk->get_index(x + size, y + size, z)] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_110; + + if (channel_type[chunk->get_index(x + size, y, z + size)] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_101; + + if (channel_type[chunk->get_index(x + size, y + size, z + size)] != 0) + case_code = case_code | VOXEL_ENTRY_MASK_111; + + return case_code; +} + +int VoxelMesherMarchingCubes::get_voxel_type(Ref chunk, const int x, const int y, const int z, const int size) { + uint8_t *channel_type = chunk->get_channel(VoxelChunkDefault::DEFAULT_CHANNEL_TYPE); + + if (channel_type == NULL) { + return 0; + } + + int type = 0; + + type = channel_type[chunk->get_index(x, y + size, z)]; + + if (type != 0) + return type; + + type = channel_type[chunk->get_index(x, y, z + size)]; + + if (type != 0) + return type; + + type = channel_type[chunk->get_index(x, y + size, z + size)]; + + if (type != 0) + return type; + + type = channel_type[chunk->get_index(x + size, y + size, z + size)]; + + if (type != 0) + return type; + + type = channel_type[chunk->get_index(x, y, z)]; + + if (type != 0) + return type; + + type = channel_type[chunk->get_index(x + size, y + size, z)]; + + if (type != 0) + return type; + + type = channel_type[chunk->get_index(x + size, y, z)]; + + if (type != 0) + return type; + + type = channel_type[chunk->get_index(x + size, y, z + size)]; + + return type; +} + +void VoxelMesherMarchingCubes::_add_chunk(Ref p_chunk) { + Ref chunk = p_chunk; + + ERR_FAIL_COND(!chunk.is_valid()); + + chunk->generate_ao(); + + int type_arr[8]; + + int x_size = chunk->get_size_x(); + int y_size = chunk->get_size_y(); + int z_size = chunk->get_size_z(); + + int lod_size = get_lod_size(); + + for (int y = 0; y < y_size; y += lod_size) { + for (int z = 0; z < z_size; z += lod_size) { + for (int x = 0; x < x_size; x += lod_size) { + + get_voxel_type_array(type_arr, chunk, x, y, z, lod_size); + int case_code = get_case_code_from_arr(type_arr); + + if (case_code == 0 || case_code == 255) { + continue; + } + + int regular_cell_class = get_regular_cell_class(case_code); + + Ref cell_data = get_regular_cell_data(regular_cell_class); + + int index_count = cell_data->get_triangle_count() * 3; + int vertex_count = cell_data->get_vertex_count(); + + for (int i = 0; i < index_count; ++i) { + int ind = get_vertex_count() + cell_data->get_vertex_index(i); + add_indices(ind); + } + + Vector temp_verts; + + Dictionary carr; + + for (int i = 0; i < 8; ++i) { + int t = type_arr[i]; + + if (carr.has(t)) + carr[t] = static_cast(carr[t]) + 1; + else + carr[t] = 1; + } + + int type_id1 = -1; + int type_id1c = -1; + int type_id2 = -1; + int type_id2c = -1; + + const Variant *K = NULL; + while ((K = carr.next(K))) { + int k = *K; + + if (k == 0) + continue; + + int c = carr[k]; + + if (type_id1c == -1) { + type_id1 = k; + type_id1c = c; + continue; + } + + if (c > type_id1c) { + type_id1 = k; + type_id1c = c; + } + } + + K = NULL; + while ((K = carr.next(K))) { + int k = *K; + + if (k == 0) + continue; + + int c = carr[k]; + + if (type_id2c == -1) { + type_id2 = k; + type_id2c = c; + continue; + } + + if (c > type_id2c && k != type_id1) { + type_id2 = k; + type_id2c = c; + } + } + + float surface_ratio = 1.0; + + if (type_id1 != type_id2) { + if (type_id1c > 0 && type_id2c > 0) { + surface_ratio = 0.5; + } else { + surface_ratio = 0; + } + } + + Ref surface1 = _library->get_voxel_surface(type_id1 - 1); + Ref surface2 = _library->get_voxel_surface(type_id2 - 1); + + for (int i = 0; i < vertex_count; ++i) { + int fv = get_regular_vertex_data_first_vertex(case_code, i); + int sv = get_regular_vertex_data_second_vertex(case_code, i); + + Vector3 offs0 = corner_id_to_vertex(fv) * lod_size; + Vector3 offs1 = corner_id_to_vertex(sv) * lod_size; + + int type = chunk->get_voxel(int(x + offs0.x), int(y + offs0.y), int(z + offs0.z), VoxelChunkDefault::DEFAULT_CHANNEL_TYPE); + + int fill = 0; + + Vector3 vert_pos; + Vector3 vert_dir; + + if (type == 0) { + fill = chunk->get_voxel(int(x + offs1.x), int(y + offs1.y), int(z + offs1.z), VoxelChunkDefault::DEFAULT_CHANNEL_ISOLEVEL); + + vert_pos = get_regular_vertex_second_position(case_code, i); + vert_dir = get_regular_vertex_first_position(case_code, i); + } else { + fill = chunk->get_voxel(int(x + offs0.x), int(y + offs0.y), int(z + offs0.z), VoxelChunkDefault::DEFAULT_CHANNEL_ISOLEVEL); + + vert_pos = get_regular_vertex_first_position(case_code, i); + vert_dir = get_regular_vertex_second_position(case_code, i); + } + + vert_dir = vert_dir - vert_pos; + + vert_pos += vert_dir * (fill / 256.0); + + temp_verts.push_back(vert_pos); + } + + PoolVector temp_normals; + temp_normals.resize(temp_verts.size()); + + for (int i = 0; i < index_count; i += 3) { + int indices[] = { + cell_data->get_vertex_index(i), + cell_data->get_vertex_index(i + 1), + cell_data->get_vertex_index(i + 2) + }; + + Vector3 vertices[] = { + temp_verts[indices[0]], + temp_verts[indices[1]], + temp_verts[indices[2]], + }; + + Vector3 i0 = temp_normals[indices[0]]; + Vector3 i1 = temp_normals[indices[1]]; + Vector3 i2 = temp_normals[indices[2]]; + + Vector3 v0 = vertices[0]; + Vector3 v1 = vertices[1]; + Vector3 v2 = vertices[2]; + + temp_normals.set(indices[0], i0 + (v1 - v0).cross(v0 - v2)); + temp_normals.set(indices[1], i1 + (v2 - v1).cross(v1 - v0)); + temp_normals.set(indices[2], i2 + (v2 - v1).cross(v2 - v0)); + } + for (int i = 0; i < temp_verts.size(); ++i) + temp_normals.set(i, temp_normals[i].normalized()); + + PoolVector temp_uvs; + temp_uvs.resize(temp_verts.size()); + + PoolVector temp_uv2s; + temp_uv2s.resize(temp_verts.size()); + + for (int cvi = 0; cvi < temp_verts.size(); ++cvi) { + Vector3 vertex = temp_verts[cvi]; + Vector3 normal = temp_normals[cvi]; + + Vector3 s; + Vector3 t; + t.x = vertex.z; + t.y = vertex.z; + t.z = vertex.y; + + s.x = vertex.y; + s.y = vertex.x; + s.z = vertex.x; + + real_t bx = ABS(normal.x); + real_t by = ABS(normal.y); + real_t bz = ABS(normal.z); + + if ((bx + 0.0001 > by) && (bx + 0.0001 > bz)) { + Vector2 uv(s.x, t.x); + Rect2 umargin = get_uv_margin(); + uv.x *= umargin.size.x; + uv.y *= umargin.size.y; + + uv.x += umargin.position.x; + uv.y += umargin.position.y; + + temp_uvs.set(cvi, surface1->transform_uv_scaled(VoxelSurface::VOXEL_SIDE_SIDE, uv, x % get_texture_scale(), z % get_texture_scale(), get_texture_scale())); + temp_uv2s.set(cvi, surface2->transform_uv_scaled(VoxelSurface::VOXEL_SIDE_SIDE, uv, x % get_texture_scale(), z % get_texture_scale(), get_texture_scale())); + } else if ((bz + 0.0001 > bx) && (bz + 0.0001 > by)) { + Vector2 uv(s.z, t.z); + Rect2 umargin = get_uv_margin(); + uv.x *= umargin.size.x; + uv.y *= umargin.size.y; + + uv.x += umargin.position.x; + uv.y += umargin.position.y; + + temp_uvs.set(cvi, surface1->transform_uv_scaled(VoxelSurface::VOXEL_SIDE_SIDE, uv, x % get_texture_scale(), z % get_texture_scale(), get_texture_scale())); + temp_uv2s.set(cvi, surface2->transform_uv_scaled(VoxelSurface::VOXEL_SIDE_SIDE, uv, x % get_texture_scale(), z % get_texture_scale(), get_texture_scale())); + } else { + Vector2 uv(s.y, t.y); + Rect2 umargin = get_uv_margin(); + uv.x *= umargin.size.x; + uv.y *= umargin.size.y; + + uv.x += umargin.position.x; + uv.y += umargin.position.y; + + temp_uvs.set(cvi, surface1->transform_uv_scaled(VoxelSurface::VOXEL_SIDE_TOP, uv, x % get_texture_scale(), z % get_texture_scale(), get_texture_scale())); + temp_uv2s.set(cvi, surface2->transform_uv_scaled(VoxelSurface::VOXEL_SIDE_TOP, uv, x % get_texture_scale(), z % get_texture_scale(), get_texture_scale())); + } + } + + for (int i = 0; i < temp_verts.size(); ++i) { + Vector3 vert_pos = temp_verts[i]; + + vert_pos *= float(lod_size); + vert_pos += Vector3(x, y, z); + + Vector3 normal = temp_normals[i]; + + add_color(Color(1.0, 1.0, 1.0, surface_ratio)); + vert_pos *= get_voxel_scale(); + + add_normal(normal); + add_uv(temp_uvs[i]); + add_uv2(temp_uv2s[i]); + add_vertex(vert_pos); + } + } + } + } + + remove_doubles_hashed(); +} + +Vector3 VoxelMesherMarchingCubes::corner_id_to_vertex(int corner_id) const { + ERR_FAIL_COND_V(corner_id < 0 || corner_id > 8, Vector3()); + + return marching_cube_vertices[corner_id]; +} + +int VoxelMesherMarchingCubes::get_regular_cell_class(int index) const { + return static_cast(regularCellClass[index]); +} + +Ref VoxelMesherMarchingCubes::get_regular_cell_data(int index) const { + return _regular_cell_datas[index]; +} + +int VoxelMesherMarchingCubes::get_regular_vertex_data(int index1, int index2) const { + //return static_cast(regularVertexData[index1][index2]); + return regularVertexData[index1][index2]; +} + +//void VoxelMesherMarchingCubes::set_regular_vertex_data(int index1, int index2, int value) { +// ERR_FAIL_INDEX(index1, 256); +// ERR_FAIL_INDEX(index2, 13); + +// regularVertexData[index1][index2] = value; +//} + +int VoxelMesherMarchingCubes::get_regular_vertex_data_first_vertex(int index1, int index2) const { + int vert1 = regularVertexData[index1][index2] & 0x000F; + + return vert1; +} + +int VoxelMesherMarchingCubes::get_regular_vertex_data_second_vertex(int index1, int index2) const { + int vert2 = (regularVertexData[index1][index2] & 0x00F0) >> 4; + + return vert2; +} + +Vector3 VoxelMesherMarchingCubes::get_regular_vertex_first_position(int index1, int index2) const { + int vert = regularVertexData[index1][index2] & 0x000F; + + return marching_cube_vertices[vert]; +} + +Vector3 VoxelMesherMarchingCubes::get_regular_vertex_second_position(int index1, int index2) const { + int vert = (regularVertexData[index1][index2] & 0x00F0) >> 4; + + return marching_cube_vertices[vert]; +} + +Vector3 VoxelMesherMarchingCubes::get_regular_vertex_direction(int index1, int index2) const { + int vert1 = regularVertexData[index1][index2] & 0x000F; + int vert2 = (regularVertexData[index1][index2] & 0x00F0) >> 4; + + return marching_cube_vertices[vert2] - marching_cube_vertices[vert1]; +} + +VoxelMesherMarchingCubes::VoxelMesherMarchingCubes() { + _format = VisualServer::ARRAY_FORMAT_NORMAL | VisualServer::ARRAY_FORMAT_COLOR | VisualServer::ARRAY_FORMAT_TEX_UV | VisualServer::ARRAY_FORMAT_TEX_UV2; + + _texture_scale = 4; + + for (int i = 0; i < 16; ++i) { + _regular_cell_datas[i] = Ref(memnew(MarchingCubesCellData(regularCellData[i]))); + } +} + +VoxelMesherMarchingCubes::~VoxelMesherMarchingCubes() { + for (int i = 0; i < 16; ++i) { + _regular_cell_datas[i].unref(); + } +} + +void VoxelMesherMarchingCubes::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_texture_scale"), &VoxelMesherMarchingCubes::get_texture_scale); + ClassDB::bind_method(D_METHOD("set_texture_scale", "value"), &VoxelMesherMarchingCubes::set_texture_scale); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_scale"), "set_texture_scale", "get_texture_scale"); + + ClassDB::bind_method(D_METHOD("_add_chunk", "chunk"), &VoxelMesherMarchingCubes::_add_chunk); + + ClassDB::bind_method(D_METHOD("corner_id_to_vertex", "index1"), &VoxelMesherMarchingCubes::corner_id_to_vertex); + + ClassDB::bind_method(D_METHOD("get_regular_cell_class", "index"), &VoxelMesherMarchingCubes::get_regular_cell_class); + ClassDB::bind_method(D_METHOD("get_regular_cell_data", "index"), &VoxelMesherMarchingCubes::get_regular_cell_data); + ClassDB::bind_method(D_METHOD("get_regular_vertex_data", "index1", "index2"), &VoxelMesherMarchingCubes::get_regular_vertex_data); + // ClassDB::bind_method(D_METHOD("set_regular_vertex_data", "index1", "index2", "value"), &VoxelMesherMarchingCubes::set_regular_vertex_data); + ClassDB::bind_method(D_METHOD("get_regular_vertex_data_first_vertex", "index1", "index2"), &VoxelMesherMarchingCubes::get_regular_vertex_data_first_vertex); + ClassDB::bind_method(D_METHOD("get_regular_vertex_data_second_vertex", "index1", "index2"), &VoxelMesherMarchingCubes::get_regular_vertex_data_second_vertex); + ClassDB::bind_method(D_METHOD("get_regular_vertex_first_position", "index1", "index2"), &VoxelMesherMarchingCubes::get_regular_vertex_first_position); + ClassDB::bind_method(D_METHOD("get_regular_vertex_second_position", "index1", "index2"), &VoxelMesherMarchingCubes::get_regular_vertex_second_position); + ClassDB::bind_method(D_METHOD("get_regular_vertex_direction", "index1", "index2"), &VoxelMesherMarchingCubes::get_regular_vertex_direction); + + BIND_ENUM_CONSTANT(VOXEL_ENTRY_INDEX_000); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_INDEX_100); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_INDEX_010); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_INDEX_110); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_INDEX_001); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_INDEX_101); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_INDEX_011); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_INDEX_111); + + BIND_ENUM_CONSTANT(VOXEL_ENTRIES_SIZE); + + BIND_ENUM_CONSTANT(VOXEL_ENTRY_MASK_000); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_MASK_100); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_MASK_010); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_MASK_110); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_MASK_001); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_MASK_101); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_MASK_011); + BIND_ENUM_CONSTANT(VOXEL_ENTRY_MASK_111); +} diff --git a/meshers/marching_cubes/voxel_mesher_marching_cubes.h b/meshers/marching_cubes/voxel_mesher_marching_cubes.h new file mode 100644 index 0000000..067d997 --- /dev/null +++ b/meshers/marching_cubes/voxel_mesher_marching_cubes.h @@ -0,0 +1,105 @@ +/* +Copyright (c) 2019-2020 Péter Magyar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef VOXEL_MESHER_MARCHING_CUBES_H +#define VOXEL_MESHER_MARCHING_CUBES_H + +#include "../default/voxel_mesher_default.h" +#include "core/reference.h" + +#include "marching_cubes_cell_data.h" + +#include "marching_cubes_tables.h" + +using namespace MarchingCubes; + +class VoxelMesherMarchingCubes : public VoxelMesherDefault { + GDCLASS(VoxelMesherMarchingCubes, VoxelMesherDefault) + +public: + static const String BINDING_STRING_VOXEL_ENTRY_INDICES; + static const String BINDING_STRING_VOXEL_ENTRY_MASK; + + enum VoxelEntryIndices { + VOXEL_ENTRY_INDEX_000 = 0, + VOXEL_ENTRY_INDEX_100 = 1, + VOXEL_ENTRY_INDEX_001 = 2, + VOXEL_ENTRY_INDEX_101 = 3, + + VOXEL_ENTRY_INDEX_010 = 4, + VOXEL_ENTRY_INDEX_110 = 5, + VOXEL_ENTRY_INDEX_011 = 6, + VOXEL_ENTRY_INDEX_111 = 7, + + VOXEL_ENTRIES_SIZE = 8, + }; + + enum VoxelEntryMask { + VOXEL_ENTRY_MASK_000 = 1 << 0, + VOXEL_ENTRY_MASK_100 = 1 << 1, + VOXEL_ENTRY_MASK_001 = 1 << 2, + VOXEL_ENTRY_MASK_101 = 1 << 3, + + VOXEL_ENTRY_MASK_010 = 1 << 4, + VOXEL_ENTRY_MASK_110 = 1 << 5, + VOXEL_ENTRY_MASK_011 = 1 << 6, + VOXEL_ENTRY_MASK_111 = 1 << 7, + }; + + int get_texture_scale() const; + void set_texture_scale(const int value); + + //arr should have a size of 8 + void get_voxel_type_array(int *arr, Ref chunk, const int x, const int y, const int z, const int size = 1); + int get_case_code_from_arr(const int *data); + int get_case_code(Ref chunk, const int x, const int y, const int z, const int size = 1); + int get_voxel_type(Ref chunk, const int x, const int y, const int z, const int size = 1); + void _add_chunk(Ref p_chunk); + + Vector3 corner_id_to_vertex(int corner_id) const; + + int get_regular_cell_class(int index) const; + + Ref get_regular_cell_data(int index) const; + int get_regular_vertex_data(int index10, int index2) const; + // void set_regular_vertex_data(int index1, int index2, int value); + int get_regular_vertex_data_first_vertex(int index1, int index2) const; + int get_regular_vertex_data_second_vertex(int index1, int index2) const; + Vector3 get_regular_vertex_first_position(int index1, int index2) const; + Vector3 get_regular_vertex_second_position(int index1, int index2) const; + Vector3 get_regular_vertex_direction(int index1, int index2) const; + + VoxelMesherMarchingCubes(); + ~VoxelMesherMarchingCubes(); + +protected: + static void _bind_methods(); + + Ref _regular_cell_datas[16]; + + int _texture_scale; +}; + +VARIANT_ENUM_CAST(VoxelMesherMarchingCubes::VoxelEntryIndices); +VARIANT_ENUM_CAST(VoxelMesherMarchingCubes::VoxelEntryMask); + +#endif // VOXEL_MESHER_SMOOTH_H diff --git a/register_types.cpp b/register_types.cpp index cb56430..a0448a2 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -38,6 +38,9 @@ SOFTWARE. #include "meshers/transvoxel_uv_mesher/voxel_mesher_uv_transvoxel.h" #include "meshers/voxel_mesher.h" +#include "meshers/marching_cubes/marching_cubes_cell_data.h" +#include "meshers/marching_cubes/voxel_mesher_marching_cubes.h" + #include "world/block_voxel_structure.h" #include "world/environment_data.h" #include "world/voxel_chunk.h" @@ -69,6 +72,9 @@ void register_voxelman_types() { ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class();