diff --git a/dmc/mesh_builder.cpp b/dmc/mesh_builder.cpp index fb1332e..644886b 100644 --- a/dmc/mesh_builder.cpp +++ b/dmc/mesh_builder.cpp @@ -2,13 +2,13 @@ namespace dmc { -Ref MeshBuilder::commit(bool wireframe) { +Array MeshBuilder::commit(bool wireframe) { if (_positions.size() == 0) { - return Ref(); + return Array(); } - ERR_FAIL_COND_V(_indices.size() % 3 != 0, Ref()); + ERR_FAIL_COND_V(_indices.size() % 3 != 0, Array()); if (wireframe) { @@ -46,11 +46,7 @@ Ref MeshBuilder::commit(bool wireframe) { 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; + return surface; } void MeshBuilder::clear() { diff --git a/dmc/mesh_builder.h b/dmc/mesh_builder.h index 41e63e6..46478f2 100644 --- a/dmc/mesh_builder.h +++ b/dmc/mesh_builder.h @@ -37,7 +37,7 @@ public: _indices.push_back(i); } - Ref commit(bool wireframe); + Array commit(bool wireframe); void clear(); int get_reused_vertex_count() const { return _reused_vertices; } diff --git a/dmc/voxel_mesher_dmc.cpp b/dmc/voxel_mesher_dmc.cpp index cc5e7c1..cd3e49d 100644 --- a/dmc/voxel_mesher_dmc.cpp +++ b/dmc/voxel_mesher_dmc.cpp @@ -287,7 +287,7 @@ void foreach_node(OctreeNode *root, Action_T &a, int depth = 0) { } } -Ref generate_debug_octree_mesh(OctreeNode *root) { +Array generate_debug_octree_mesh(OctreeNode *root) { struct GetMaxDepth { int max_depth; @@ -340,7 +340,7 @@ Ref generate_debug_octree_mesh(OctreeNode *root) { foreach_node(root, add_cube); if (arrays.positions.size() == 0) { - return Ref(); + return Array(); } Array surface; @@ -349,14 +349,10 @@ Ref generate_debug_octree_mesh(OctreeNode *root) { surface[Mesh::ARRAY_COLOR] = arrays.colors; surface[Mesh::ARRAY_INDEX] = arrays.indices; - Ref mesh; - mesh.instance(); - mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, surface); - - return mesh; + return surface; } -Ref generate_debug_dual_grid_mesh(const DualGrid &grid) { +Array generate_debug_dual_grid_mesh(const DualGrid &grid) { PoolVector3Array positions; PoolIntArray indices; @@ -380,7 +376,7 @@ Ref generate_debug_dual_grid_mesh(const DualGrid &grid) { } if (positions.size() == 0) { - return Ref(); + return Array(); } Array surface; @@ -388,11 +384,7 @@ Ref generate_debug_dual_grid_mesh(const DualGrid &grid) { surface[Mesh::ARRAY_VERTEX] = positions; surface[Mesh::ARRAY_INDEX] = indices; - Ref mesh; - mesh.instance(); - mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, surface); - - return mesh; + return surface; } inline bool is_border_left(const OctreeNode *node) { @@ -1325,7 +1317,7 @@ float VoxelMesherDMC::get_geometric_error() const { return _geometric_error; } -Ref VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels) { +Array VoxelMesherDMC::build(const VoxelBuffer &voxels) { // Requirements: // - Voxel data must be padded @@ -1339,9 +1331,9 @@ Ref VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels) { // Taking previous power of two because the algorithm uses an integer cubic octree, and data should be padded int chunk_size = previous_power_of_2(MIN(MIN(buffer_size.x, buffer_size.y), buffer_size.z)); - ERR_FAIL_COND_V(voxels.get_size().x < chunk_size + padding * 2, Ref()); - ERR_FAIL_COND_V(voxels.get_size().y < chunk_size + padding * 2, Ref()); - ERR_FAIL_COND_V(voxels.get_size().z < chunk_size + padding * 2, Ref()); + ERR_FAIL_COND_V(voxels.get_size().x < chunk_size + padding * 2, Array()); + ERR_FAIL_COND_V(voxels.get_size().y < chunk_size + padding * 2, Array()); + ERR_FAIL_COND_V(voxels.get_size().z < chunk_size + padding * 2, Array()); // Construct an intermediate to handle padding transparently dmc::VoxelAccess voxels_access(voxels, Vector3i(padding)); @@ -1379,12 +1371,12 @@ Ref VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels) { _stats.octree_build_time = OS::get_singleton()->get_ticks_usec() - time_before; - Ref mesh; + Array surface; if (root != nullptr) { if (_mesh_mode == MESH_DEBUG_OCTREE) { - mesh = dmc::generate_debug_octree_mesh(root); + surface = dmc::generate_debug_octree_mesh(root); } else { @@ -1397,7 +1389,7 @@ Ref VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels) { _stats.dualgrid_derivation_time = OS::get_singleton()->get_ticks_usec() - time_before; if (_mesh_mode == MESH_DEBUG_DUAL_GRID) { - mesh = dmc::generate_debug_dual_grid_mesh(_dual_grid); + surface = dmc::generate_debug_dual_grid_mesh(_dual_grid); } else { @@ -1421,18 +1413,42 @@ Ref VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels) { _stats.meshing_time = OS::get_singleton()->get_ticks_usec() - time_before; } - time_before = OS::get_singleton()->get_ticks_usec(); - mesh = _mesh_builder.commit(_mesh_mode == MESH_WIREFRAME); - _stats.commit_time = OS::get_singleton()->get_ticks_usec() - time_before; + if (surface.empty()) { + time_before = OS::get_singleton()->get_ticks_usec(); + surface = _mesh_builder.commit(_mesh_mode == MESH_WIREFRAME); + _stats.commit_time = OS::get_singleton()->get_ticks_usec() - time_before; + } // TODO Marching squares skirts - return mesh; + // surfaces[material][array_type], for now single material + Array surfaces; + surfaces.append(surface); + return surfaces; } -Ref VoxelMesherDMC::_build_mesh_b(Ref voxels) { +Ref VoxelMesherDMC::build_mesh(Ref voxels) { + ERR_FAIL_COND_V(voxels.is_null(), Ref()); - return build_mesh(**voxels); + + Array surfaces = build(**voxels); + + if (surfaces.empty()) { + return Ref(); + } + + Ref mesh; + mesh.instance(); + + for (int i = 0; i < surfaces.size(); ++i) { + if (_mesh_mode == MESH_NORMAL) { + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surfaces[i]); + } else { + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, surfaces[i]); + } + } + + return mesh; } Dictionary VoxelMesherDMC::get_stats() const { @@ -1455,7 +1471,7 @@ void VoxelMesherDMC::_bind_methods() { ClassDB::bind_method(D_METHOD("set_geometric_error", "error"), &VoxelMesherDMC::set_geometric_error); ClassDB::bind_method(D_METHOD("get_geometric_error"), &VoxelMesherDMC::get_geometric_error); - ClassDB::bind_method(D_METHOD("build_mesh", "voxel_buffer"), &VoxelMesherDMC::_build_mesh_b); + ClassDB::bind_method(D_METHOD("build_mesh", "voxel_buffer"), &VoxelMesherDMC::build_mesh); ClassDB::bind_method(D_METHOD("get_stats"), &VoxelMesherDMC::get_stats); BIND_ENUM_CONSTANT(MESH_NORMAL); diff --git a/dmc/voxel_mesher_dmc.h b/dmc/voxel_mesher_dmc.h index 2d1befc..b6bbca1 100644 --- a/dmc/voxel_mesher_dmc.h +++ b/dmc/voxel_mesher_dmc.h @@ -91,12 +91,13 @@ public: void set_geometric_error(real_t geometric_error); float get_geometric_error() const; - Ref build_mesh(const VoxelBuffer &voxels); + Array build(const VoxelBuffer &voxels); + Ref build_mesh(Ref voxels); + Dictionary get_stats() const; protected: static void _bind_methods(); - Ref _build_mesh_b(Ref voxels); private: dmc::MeshBuilder _mesh_builder; diff --git a/voxel_mesh_updater.cpp b/voxel_mesh_updater.cpp index c516116..5f53054 100644 --- a/voxel_mesh_updater.cpp +++ b/voxel_mesh_updater.cpp @@ -7,12 +7,14 @@ VoxelMeshUpdater::VoxelMeshUpdater(Ref library, MeshingParams para CRASH_COND(library.is_null()); //CRASH_COND(params.materials.size() == 0); - _model_mesher.instance(); - _model_mesher->set_library(library); - _model_mesher->set_occlusion_enabled(params.baked_ao); - _model_mesher->set_occlusion_darkness(params.baked_ao_darkness); + _blocky_mesher.instance(); + _blocky_mesher->set_library(library); + _blocky_mesher->set_occlusion_enabled(params.baked_ao); + _blocky_mesher->set_occlusion_darkness(params.baked_ao_darkness); - _smooth_mesher.instance(); + _dmc_mesher.instance(); + _dmc_mesher->set_geometric_error(0.05); + _dmc_mesher->set_octree_mode(VoxelMesherDMC::OCTREE_NONE); _input_mutex = Mutex::create(); _output_mutex = Mutex::create(); @@ -176,9 +178,9 @@ void VoxelMeshUpdater::process_block(const InputBlock &block, OutputBlock &outpu CRASH_COND(block.voxels.is_null()); // Build cubic parts of the mesh - output.model_surfaces = _model_mesher->build(**block.voxels, Voxel::CHANNEL_TYPE, Vector3i(0, 0, 0), block.voxels->get_size() - Vector3(1, 1, 1)); + output.model_surfaces = _blocky_mesher->build(**block.voxels, Voxel::CHANNEL_TYPE, Vector3i(0, 0, 0), block.voxels->get_size() - Vector3(1, 1, 1)); // Build smooth parts of the mesh - output.smooth_surfaces = _smooth_mesher->build(**block.voxels, Voxel::CHANNEL_ISOLEVEL); + output.smooth_surfaces = _dmc_mesher->build(**block.voxels); output.position = block.position; } diff --git a/voxel_mesh_updater.h b/voxel_mesh_updater.h index 70e0e3e..5dbe048 100644 --- a/voxel_mesh_updater.h +++ b/voxel_mesh_updater.h @@ -5,7 +5,7 @@ #include #include -#include "transvoxel/voxel_mesher_transvoxel.h" +#include "dmc/voxel_mesher_dmc.h" #include "voxel_buffer.h" #include "voxel_mesher.h" @@ -81,8 +81,8 @@ private: Output _shared_output; Mutex *_output_mutex; - Ref _model_mesher; - Ref _smooth_mesher; + Ref _blocky_mesher; + Ref _dmc_mesher; Input _input; Output _output; diff --git a/voxel_terrain.cpp b/voxel_terrain.cpp index ffbf8e5..d55cf8e 100644 --- a/voxel_terrain.cpp +++ b/voxel_terrain.cpp @@ -536,6 +536,7 @@ void VoxelTerrain::_process() { // TODO Use editor's camera here viewer_block_pos = Vector3i(); } else { + // TODO Use viewport camera, much easier Spatial *viewer = get_viewer(_viewer_path); if (viewer) viewer_block_pos = _map->voxel_to_block(viewer->get_translation()); @@ -699,7 +700,10 @@ void VoxelTerrain::_process() { CRASH_COND(*block_state != BLOCK_UPDATE_NOT_SENT); int air_type = 0; - if (block->voxels->is_uniform(Voxel::CHANNEL_TYPE) && block->voxels->get_voxel(0, 0, 0, Voxel::CHANNEL_TYPE) == air_type) { + if ( + block->voxels->is_uniform(Voxel::CHANNEL_TYPE) && + block->voxels->is_uniform(Voxel::CHANNEL_ISOLEVEL) && + block->voxels->get_voxel(0, 0, 0, Voxel::CHANNEL_TYPE) == air_type) { // The block contains empty voxels block->set_mesh(Ref(), Ref()); @@ -718,7 +722,8 @@ void VoxelTerrain::_process() { // TODO Padding set to 3 at the moment because Transvoxel works on 2x2 cells. // It should change for a smarter padding (if smooth isn't used for example). unsigned int block_size = _map->get_block_size(); - nbuffer->create(block_size + 3, block_size + 3, block_size + 3); + //nbuffer->create(block_size + 3, block_size + 3, block_size + 3); + nbuffer->create(block_size + 2, block_size + 2, block_size + 2); _map->get_buffer_copy(_map->block_to_voxel(block_pos) - Vector3i(1, 1, 1), **nbuffer, 0x3); @@ -782,9 +787,11 @@ void VoxelTerrain::_process() { for (int i = 0; i < ob.model_surfaces.size(); ++i) { Array surface = ob.model_surfaces[i]; - if (surface.empty()) + if (surface.empty()) { continue; + } + CRASH_COND(surface.size() != Mesh::ARRAY_MAX); mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface); mesh->surface_set_material(surface_index, _materials[i]); @@ -794,16 +801,21 @@ void VoxelTerrain::_process() { for (int i = 0; i < ob.smooth_surfaces.size(); ++i) { Array surface = ob.smooth_surfaces[i]; - if (surface.empty()) + if (surface.empty()) { continue; + } + CRASH_COND(surface.size() != Mesh::ARRAY_MAX); + // TODO Problem here, the mesher could be configured to output wireframe! Need to output some MeshData struct instead mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface); + mesh->surface_set_material(surface_index, _materials[i]); // No material supported yet ++surface_index; } - if (is_mesh_empty(mesh)) + if (is_mesh_empty(mesh)) { mesh = Ref(); + } block->set_mesh(mesh, world); }