mirror of
https://github.com/Relintai/godot_voxel.git
synced 2024-11-11 20:35:08 +01:00
Update DMC mesher to the API required to integrate to VoxelTerrain
This commit is contained in:
parent
101f83234a
commit
beace8709b
@ -2,13 +2,13 @@
|
||||
|
||||
namespace dmc {
|
||||
|
||||
Ref<ArrayMesh> MeshBuilder::commit(bool wireframe) {
|
||||
Array MeshBuilder::commit(bool wireframe) {
|
||||
|
||||
if (_positions.size() == 0) {
|
||||
return Ref<ArrayMesh>();
|
||||
return Array();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(_indices.size() % 3 != 0, Ref<ArrayMesh>());
|
||||
ERR_FAIL_COND_V(_indices.size() % 3 != 0, Array());
|
||||
|
||||
if (wireframe) {
|
||||
|
||||
@ -46,11 +46,7 @@ Ref<ArrayMesh> MeshBuilder::commit(bool wireframe) {
|
||||
surface[Mesh::ARRAY_NORMAL] = normals;
|
||||
surface[Mesh::ARRAY_INDEX] = indices;
|
||||
|
||||
Ref<ArrayMesh> mesh;
|
||||
mesh.instance();
|
||||
mesh->add_surface_from_arrays(wireframe ? Mesh::PRIMITIVE_LINES : Mesh::PRIMITIVE_TRIANGLES, surface);
|
||||
|
||||
return mesh;
|
||||
return surface;
|
||||
}
|
||||
|
||||
void MeshBuilder::clear() {
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
_indices.push_back(i);
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> commit(bool wireframe);
|
||||
Array commit(bool wireframe);
|
||||
void clear();
|
||||
|
||||
int get_reused_vertex_count() const { return _reused_vertices; }
|
||||
|
@ -287,7 +287,7 @@ void foreach_node(OctreeNode *root, Action_T &a, int depth = 0) {
|
||||
}
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> generate_debug_octree_mesh(OctreeNode *root) {
|
||||
Array generate_debug_octree_mesh(OctreeNode *root) {
|
||||
|
||||
struct GetMaxDepth {
|
||||
int max_depth;
|
||||
@ -340,7 +340,7 @@ Ref<ArrayMesh> generate_debug_octree_mesh(OctreeNode *root) {
|
||||
foreach_node(root, add_cube);
|
||||
|
||||
if (arrays.positions.size() == 0) {
|
||||
return Ref<ArrayMesh>();
|
||||
return Array();
|
||||
}
|
||||
|
||||
Array surface;
|
||||
@ -349,14 +349,10 @@ Ref<ArrayMesh> generate_debug_octree_mesh(OctreeNode *root) {
|
||||
surface[Mesh::ARRAY_COLOR] = arrays.colors;
|
||||
surface[Mesh::ARRAY_INDEX] = arrays.indices;
|
||||
|
||||
Ref<ArrayMesh> mesh;
|
||||
mesh.instance();
|
||||
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, surface);
|
||||
|
||||
return mesh;
|
||||
return surface;
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> 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<ArrayMesh> generate_debug_dual_grid_mesh(const DualGrid &grid) {
|
||||
}
|
||||
|
||||
if (positions.size() == 0) {
|
||||
return Ref<ArrayMesh>();
|
||||
return Array();
|
||||
}
|
||||
|
||||
Array surface;
|
||||
@ -388,11 +384,7 @@ Ref<ArrayMesh> generate_debug_dual_grid_mesh(const DualGrid &grid) {
|
||||
surface[Mesh::ARRAY_VERTEX] = positions;
|
||||
surface[Mesh::ARRAY_INDEX] = indices;
|
||||
|
||||
Ref<ArrayMesh> 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<ArrayMesh> VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels) {
|
||||
Array VoxelMesherDMC::build(const VoxelBuffer &voxels) {
|
||||
|
||||
// Requirements:
|
||||
// - Voxel data must be padded
|
||||
@ -1339,9 +1331,9 @@ Ref<ArrayMesh> 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<ArrayMesh>());
|
||||
ERR_FAIL_COND_V(voxels.get_size().y < chunk_size + padding * 2, Ref<ArrayMesh>());
|
||||
ERR_FAIL_COND_V(voxels.get_size().z < chunk_size + padding * 2, Ref<ArrayMesh>());
|
||||
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<ArrayMesh> VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels) {
|
||||
|
||||
_stats.octree_build_time = OS::get_singleton()->get_ticks_usec() - time_before;
|
||||
|
||||
Ref<ArrayMesh> 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<ArrayMesh> 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<ArrayMesh> VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels) {
|
||||
_stats.meshing_time = OS::get_singleton()->get_ticks_usec() - time_before;
|
||||
}
|
||||
|
||||
if (surface.empty()) {
|
||||
time_before = OS::get_singleton()->get_ticks_usec();
|
||||
mesh = _mesh_builder.commit(_mesh_mode == MESH_WIREFRAME);
|
||||
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<ArrayMesh> VoxelMesherDMC::_build_mesh_b(Ref<VoxelBuffer> voxels) {
|
||||
Ref<ArrayMesh> VoxelMesherDMC::build_mesh(Ref<VoxelBuffer> voxels) {
|
||||
|
||||
ERR_FAIL_COND_V(voxels.is_null(), Ref<ArrayMesh>());
|
||||
return build_mesh(**voxels);
|
||||
|
||||
Array surfaces = build(**voxels);
|
||||
|
||||
if (surfaces.empty()) {
|
||||
return Ref<ArrayMesh>();
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> 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);
|
||||
|
@ -91,12 +91,13 @@ public:
|
||||
void set_geometric_error(real_t geometric_error);
|
||||
float get_geometric_error() const;
|
||||
|
||||
Ref<ArrayMesh> build_mesh(const VoxelBuffer &voxels);
|
||||
Array build(const VoxelBuffer &voxels);
|
||||
Ref<ArrayMesh> build_mesh(Ref<VoxelBuffer> voxels);
|
||||
|
||||
Dictionary get_stats() const;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
Ref<ArrayMesh> _build_mesh_b(Ref<VoxelBuffer> voxels);
|
||||
|
||||
private:
|
||||
dmc::MeshBuilder _mesh_builder;
|
||||
|
@ -7,12 +7,14 @@ VoxelMeshUpdater::VoxelMeshUpdater(Ref<VoxelLibrary> 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;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <core/os/thread.h>
|
||||
#include <core/vector.h>
|
||||
|
||||
#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<VoxelMesher> _model_mesher;
|
||||
Ref<VoxelMesherTransvoxel> _smooth_mesher;
|
||||
Ref<VoxelMesher> _blocky_mesher;
|
||||
Ref<VoxelMesherDMC> _dmc_mesher;
|
||||
|
||||
Input _input;
|
||||
Output _output;
|
||||
|
@ -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<Mesh>(), Ref<World>());
|
||||
@ -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<Mesh>();
|
||||
}
|
||||
|
||||
block->set_mesh(mesh, world);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user