Re-use dualgrid memory

This commit is contained in:
Marc Gilleron 2019-04-22 23:36:42 +01:00
parent 3c366b1f09
commit 0e569df945
2 changed files with 108 additions and 98 deletions

View File

@ -1,6 +1,5 @@
#include "voxel_mesher_dmc.h" #include "voxel_mesher_dmc.h"
#include "../cube_tables.h" #include "../cube_tables.h"
#include "hermite_value.h"
#include "marching_cubes_tables.h" #include "marching_cubes_tables.h"
#include "mesh_builder.h" #include "mesh_builder.h"
#include "octree_utility.h" #include "octree_utility.h"
@ -363,47 +362,6 @@ Ref<ArrayMesh> generate_debug_octree_mesh(OctreeNode *root) {
return mesh; return mesh;
} }
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);
corners[i] = vertex;
values[i] = value;
}
};
struct DualGrid {
std::vector<DualCell> cells;
inline void add_cell(
const Vector3 c0,
const Vector3 c1,
const Vector3 c2,
const Vector3 c3,
const Vector3 c4,
const Vector3 c5,
const Vector3 c6,
const Vector3 c7) {
DualCell cell;
cell.corners[0] = c0;
cell.corners[1] = c1;
cell.corners[2] = c2;
cell.corners[3] = c3;
cell.corners[4] = c4;
cell.corners[5] = c5;
cell.corners[6] = c6;
cell.corners[7] = c7;
cells.push_back(cell);
}
};
Ref<ArrayMesh> generate_debug_dual_grid_mesh(const DualGrid &grid) { Ref<ArrayMesh> generate_debug_dual_grid_mesh(const DualGrid &grid) {
PoolVector3Array positions; PoolVector3Array positions;
@ -676,6 +634,29 @@ private:
void face_proc_xz(OctreeNode *n0, OctreeNode *n1); void face_proc_xz(OctreeNode *n0, OctreeNode *n1);
}; };
inline void add_cell(DualGrid &grid,
const Vector3 c0,
const Vector3 c1,
const Vector3 c2,
const Vector3 c3,
const Vector3 c4,
const Vector3 c5,
const Vector3 c6,
const Vector3 c7) {
DualCell cell;
cell.corners[0] = c0;
cell.corners[1] = c1;
cell.corners[2] = c2;
cell.corners[3] = c3;
cell.corners[4] = c4;
cell.corners[5] = c5;
cell.corners[6] = c6;
cell.corners[7] = c7;
cell.has_values = false;
grid.cells.push_back(cell);
}
void DualGridGenerator::create_border_cells( void DualGridGenerator::create_border_cells(
const OctreeNode *n0, const OctreeNode *n0,
const OctreeNode *n1, const OctreeNode *n1,
@ -692,26 +673,26 @@ void DualGridGenerator::create_border_cells(
if (is_border_back(n0) && is_border_back(n1) && is_border_back(n4) && is_border_back(n5)) { if (is_border_back(n0) && is_border_back(n1) && is_border_back(n4) && is_border_back(n5)) {
grid.add_cell( add_cell(grid,
get_center_back(n0), get_center_back(n1), get_center(n1), get_center(n0), get_center_back(n0), get_center_back(n1), get_center(n1), get_center(n0),
get_center_back(n4), get_center_back(n5), get_center(n5), get_center(n4)); get_center_back(n4), get_center_back(n5), get_center(n5), get_center(n4));
// Generate back edge border cells // Generate back edge border cells
if (is_border_top(n4, _octree_root_size) && is_border_top(n5, _octree_root_size)) { if (is_border_top(n4, _octree_root_size) && is_border_top(n5, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center_back(n4), get_center_back(n5), get_center(n5), get_center(n4), get_center_back(n4), get_center_back(n5), get_center(n5), get_center(n4),
get_center_back_top(n4), get_center_back_top(n5), get_center_top(n5), get_center_top(n4)); get_center_back_top(n4), get_center_back_top(n5), get_center_top(n5), get_center_top(n4));
// Generate back top corner cells // Generate back top corner cells
if (is_border_left(n4)) { if (is_border_left(n4)) {
grid.add_cell( add_cell(grid,
get_center_back_left(n4), get_center_back(n4), get_center(n4), get_center_left(n4), get_center_back_left(n4), get_center_back(n4), get_center(n4), get_center_left(n4),
get_corner4(n4), get_center_back_top(n4), get_center_top(n4), get_center_left_top(n4)); get_corner4(n4), get_center_back_top(n4), get_center_top(n4), get_center_left_top(n4));
} }
if (is_border_right(n4, _octree_root_size)) { if (is_border_right(n4, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center_back(n5), get_center_back_right(n5), get_center_right(n5), get_center(n5), get_center_back(n5), get_center_back_right(n5), get_center_right(n5), get_center(n5),
get_center_back_top(n5), get_corner5(n5), get_center_right_top(n5), get_center_top(n5)); get_center_back_top(n5), get_corner5(n5), get_center_right_top(n5), get_center_top(n5));
} }
@ -719,18 +700,18 @@ void DualGridGenerator::create_border_cells(
if (is_border_bottom(n0) && is_border_bottom(n1)) { if (is_border_bottom(n0) && is_border_bottom(n1)) {
grid.add_cell( add_cell(grid,
get_center_back_bottom(n0), get_center_back_bottom(n1), get_center_bottom(n1), get_center_bottom(n0), get_center_back_bottom(n0), get_center_back_bottom(n1), get_center_bottom(n1), get_center_bottom(n0),
get_center_back(n0), get_center_back(n1), get_center(n1), get_center(n0)); get_center_back(n0), get_center_back(n1), get_center(n1), get_center(n0));
// Generate back bottom corner cells // Generate back bottom corner cells
if (is_border_left(n0)) { if (is_border_left(n0)) {
grid.add_cell(n0->origin.to_vec3(), get_center_back_bottom(n0), get_center_bottom(n0), get_center_left_bottom(n0), add_cell(grid, n0->origin.to_vec3(), get_center_back_bottom(n0), get_center_bottom(n0), get_center_left_bottom(n0),
get_center_back_left(n0), get_center_back(n0), get_center(n0), get_center_left(n0)); get_center_back_left(n0), get_center_back(n0), get_center(n0), get_center_left(n0));
} }
if (is_border_right(n1, _octree_root_size)) { if (is_border_right(n1, _octree_root_size)) {
grid.add_cell(get_center_back_bottom(n1), get_corner1(n1), get_center_right_bottom(n1), get_center_bottom(n1), add_cell(grid, get_center_back_bottom(n1), get_corner1(n1), get_center_right_bottom(n1), get_center_bottom(n1),
get_center_back(n1), get_center_back_right(n1), get_center_right(n1), get_center(n1)); get_center_back(n1), get_center_back_right(n1), get_center_right(n1), get_center(n1));
} }
} }
@ -741,26 +722,26 @@ void DualGridGenerator::create_border_cells(
is_border_front(n6, _octree_root_size) && is_border_front(n6, _octree_root_size) &&
is_border_front(n7, _octree_root_size)) { is_border_front(n7, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center(n3), get_center(n2), get_center_front(n2), get_center_front(n3), get_center(n3), get_center(n2), get_center_front(n2), get_center_front(n3),
get_center(n7), get_center(n6), get_center_front(n6), get_center_front(n7)); get_center(n7), get_center(n6), get_center_front(n6), get_center_front(n7));
// Generate front edge border cells // Generate front edge border cells
if (is_border_top(n6, _octree_root_size) && is_border_top(n7, _octree_root_size)) { if (is_border_top(n6, _octree_root_size) && is_border_top(n7, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center(n7), get_center(n6), get_center_front(n6), get_center_front(n7), get_center(n7), get_center(n6), get_center_front(n6), get_center_front(n7),
get_center_top(n7), get_center_top(n6), get_center_front_top(n6), get_center_front_top(n7)); get_center_top(n7), get_center_top(n6), get_center_front_top(n6), get_center_front_top(n7));
// Generate back bottom corner cells // Generate back bottom corner cells
if (is_border_left(n7)) { if (is_border_left(n7)) {
grid.add_cell( add_cell(grid,
get_center_left(n7), get_center(n7), get_center_front(n7), get_center_front_left(n7), get_center_left(n7), get_center(n7), get_center_front(n7), get_center_front_left(n7),
get_center_left_top(n7), get_center_top(n7), get_center_front_top(n7), get_corner7(n7)); get_center_left_top(n7), get_center_top(n7), get_center_front_top(n7), get_corner7(n7));
} }
if (is_border_right(n6, _octree_root_size)) { if (is_border_right(n6, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center(n6), get_center_right(n6), get_center_front_right(n6), get_center_front(n6), get_center(n6), get_center_right(n6), get_center_front_right(n6), get_center_front(n6),
get_center_top(n6), get_center_right_top(n6), get_corner6(n6), get_center_front_top(n6)); get_center_top(n6), get_center_right_top(n6), get_corner6(n6), get_center_front_top(n6));
} }
@ -768,18 +749,18 @@ void DualGridGenerator::create_border_cells(
if (is_border_bottom(n3) && is_border_bottom(n2)) { if (is_border_bottom(n3) && is_border_bottom(n2)) {
grid.add_cell( add_cell(grid,
get_center_bottom(n3), get_center_bottom(n2), get_center_front_bottom(n2), get_center_front_bottom(n3), get_center_bottom(n3), get_center_bottom(n2), get_center_front_bottom(n2), get_center_front_bottom(n3),
get_center(n3), get_center(n2), get_center_front(n2), get_center_front(n3)); get_center(n3), get_center(n2), get_center_front(n2), get_center_front(n3));
// Generate back bottom corner cells // Generate back bottom corner cells
if (is_border_left(n3)) { if (is_border_left(n3)) {
grid.add_cell( add_cell(grid,
get_center_left_bottom(n3), get_center_bottom(n3), get_center_front_bottom(n3), get_corner3(n3), get_center_left_bottom(n3), get_center_bottom(n3), get_center_front_bottom(n3), get_corner3(n3),
get_center_left(n3), get_center(n3), get_center_front(n3), get_center_front_left(n3)); get_center_left(n3), get_center(n3), get_center_front(n3), get_center_front_left(n3));
} }
if (is_border_right(n2, _octree_root_size)) { if (is_border_right(n2, _octree_root_size)) {
grid.add_cell(get_center_bottom(n2), get_center_right_bottom(n2), get_corner2(n2), get_center_front_bottom(n2), add_cell(grid, get_center_bottom(n2), get_center_right_bottom(n2), get_corner2(n2), get_center_front_bottom(n2),
get_center(n2), get_center_right(n2), get_center_front_right(n2), get_center_front(n2)); get_center(n2), get_center_right(n2), get_center_front_right(n2), get_center_front(n2));
} }
} }
@ -787,31 +768,31 @@ void DualGridGenerator::create_border_cells(
if (is_border_left(n0) && is_border_left(n3) && is_border_left(n4) && is_border_left(n7)) { if (is_border_left(n0) && is_border_left(n3) && is_border_left(n4) && is_border_left(n7)) {
grid.add_cell( add_cell(grid,
get_center_left(n0), get_center(n0), get_center(n3), get_center_left(n3), get_center_left(n0), get_center(n0), get_center(n3), get_center_left(n3),
get_center_left(n4), get_center(n4), get_center(n7), get_center_left(n7)); get_center_left(n4), get_center(n4), get_center(n7), get_center_left(n7));
// Generate left edge border cells // Generate left edge border cells
if (is_border_top(n4, _octree_root_size) && is_border_top(n7, _octree_root_size)) { if (is_border_top(n4, _octree_root_size) && is_border_top(n7, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center_left(n4), get_center(n4), get_center(n7), get_center_left(n7), get_center_left(n4), get_center(n4), get_center(n7), get_center_left(n7),
get_center_left_top(n4), get_center_top(n4), get_center_top(n7), get_center_left_top(n7)); get_center_left_top(n4), get_center_top(n4), get_center_top(n7), get_center_left_top(n7));
} }
if (is_border_bottom(n0) && is_border_bottom(n3)) { if (is_border_bottom(n0) && is_border_bottom(n3)) {
grid.add_cell( add_cell(grid,
get_center_left_bottom(n0), get_center_bottom(n0), get_center_bottom(n3), get_center_left_bottom(n3), get_center_left_bottom(n0), get_center_bottom(n0), get_center_bottom(n3), get_center_left_bottom(n3),
get_center_left(n0), get_center(n0), get_center(n3), get_center_left(n3)); get_center_left(n0), get_center(n0), get_center(n3), get_center_left(n3));
} }
if (is_border_back(n0) && is_border_back(n4)) { if (is_border_back(n0) && is_border_back(n4)) {
grid.add_cell( add_cell(grid,
get_center_back_left(n0), get_center_back(n0), get_center(n0), get_center_left(n0), get_center_back_left(n0), get_center_back(n0), get_center(n0), get_center_left(n0),
get_center_back_left(n4), get_center_back(n4), get_center(n4), get_center_left(n4)); get_center_back_left(n4), get_center_back(n4), get_center(n4), get_center_left(n4));
} }
if (is_border_front(n3, _octree_root_size) && is_border_front(n7, _octree_root_size)) { if (is_border_front(n3, _octree_root_size) && is_border_front(n7, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center_left(n3), get_center(n3), get_center_front(n3), get_center_front_left(n3), get_center_left(n3), get_center(n3), get_center_front(n3), get_center_front_left(n3),
get_center_left(n7), get_center(n7), get_center_front(n7), get_center_front_left(n7)); get_center_left(n7), get_center(n7), get_center_front(n7), get_center_front_left(n7));
} }
@ -822,31 +803,31 @@ void DualGridGenerator::create_border_cells(
is_border_right(n5, _octree_root_size) && is_border_right(n5, _octree_root_size) &&
is_border_right(n6, _octree_root_size)) { is_border_right(n6, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center(n1), get_center_right(n1), get_center_right(n2), get_center(n2), get_center(n1), get_center_right(n1), get_center_right(n2), get_center(n2),
get_center(n5), get_center_right(n5), get_center_right(n6), get_center(n6)); get_center(n5), get_center_right(n5), get_center_right(n6), get_center(n6));
// Generate right edge border cells // Generate right edge border cells
if (is_border_top(n5, _octree_root_size) && is_border_top(n6, _octree_root_size)) { if (is_border_top(n5, _octree_root_size) && is_border_top(n6, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center(n5), get_center_right(n5), get_center_right(n6), get_center(n6), get_center(n5), get_center_right(n5), get_center_right(n6), get_center(n6),
get_center_top(n5), get_center_right_top(n5), get_center_right_top(n6), get_center_top(n6)); get_center_top(n5), get_center_right_top(n5), get_center_right_top(n6), get_center_top(n6));
} }
if (is_border_bottom(n1) && is_border_bottom(n2)) { if (is_border_bottom(n1) && is_border_bottom(n2)) {
grid.add_cell( add_cell(grid,
get_center_bottom(n1), get_center_right_bottom(n1), get_center_right_bottom(n2), get_center_bottom(n2), get_center_bottom(n1), get_center_right_bottom(n1), get_center_right_bottom(n2), get_center_bottom(n2),
get_center(n1), get_center_right(n1), get_center_right(n2), get_center(n2)); get_center(n1), get_center_right(n1), get_center_right(n2), get_center(n2));
} }
if (is_border_back(n1) && is_border_back(n5)) { if (is_border_back(n1) && is_border_back(n5)) {
grid.add_cell( add_cell(grid,
get_center_back(n1), get_center_back_right(n1), get_center_right(n1), get_center(n1), get_center_back(n1), get_center_back_right(n1), get_center_right(n1), get_center(n1),
get_center_back(n5), get_center_back_right(n5), get_center_right(n5), get_center(n5)); get_center_back(n5), get_center_back_right(n5), get_center_right(n5), get_center(n5));
} }
if (is_border_front(n2, _octree_root_size) && is_border_front(n6, _octree_root_size)) { if (is_border_front(n2, _octree_root_size) && is_border_front(n6, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center(n2), get_center_right(n2), get_center_front_right(n2), get_center_front(n2), get_center(n2), get_center_right(n2), get_center_front_right(n2), get_center_front(n2),
get_center(n6), get_center_right(n6), get_center_front_right(n6), get_center_front(n6)); get_center(n6), get_center_right(n6), get_center_front_right(n6), get_center_front(n6));
} }
@ -857,13 +838,13 @@ void DualGridGenerator::create_border_cells(
is_border_top(n6, _octree_root_size) && is_border_top(n6, _octree_root_size) &&
is_border_top(n7, _octree_root_size)) { is_border_top(n7, _octree_root_size)) {
grid.add_cell( add_cell(grid,
get_center(n4), get_center(n5), get_center(n6), get_center(n7), get_center(n4), get_center(n5), get_center(n6), get_center(n7),
get_center_top(n4), get_center_top(n5), get_center_top(n6), get_center_top(n7)); get_center_top(n4), get_center_top(n5), get_center_top(n6), get_center_top(n7));
} }
if (is_border_bottom(n0) && is_border_bottom(n1) && is_border_bottom(n2) && is_border_bottom(n3)) { if (is_border_bottom(n0) && is_border_bottom(n1) && is_border_bottom(n2) && is_border_bottom(n3)) {
grid.add_cell( add_cell(grid,
get_center_bottom(n0), get_center_bottom(n1), get_center_bottom(n2), get_center_bottom(n3), get_center_bottom(n0), get_center_bottom(n1), get_center_bottom(n2), get_center_bottom(n3),
get_center(n0), get_center(n1), get_center(n2), get_center(n3)); get_center(n0), get_center(n1), get_center(n2), get_center(n3));
} }
@ -1312,43 +1293,47 @@ Ref<ArrayMesh> VoxelMesherDMC::build_mesh(const VoxelBuffer &voxels, real_t geom
root->size = chunk_size; root->size = chunk_size;
dmc::generate_octree_top_down(root, voxels_access, geometric_error); dmc::generate_octree_top_down(root, voxels_access, geometric_error);
#endif #endif
// TODO OctreeNode pool to stop allocating. Or, flat octree?
_stats.octree_build_time = OS::get_singleton()->get_ticks_usec() - time_before; _stats.octree_build_time = OS::get_singleton()->get_ticks_usec() - time_before;
if (root == nullptr) { Ref<ArrayMesh> mesh;
return Ref<ArrayMesh>();
} if (root != nullptr) {
// TODO OctreeNode pool to stop allocating. Or, flat octree?
if (mode == VoxelMesherDMC::MODE_DEBUG_OCTREE) {
mesh = dmc::generate_debug_octree_mesh(root);
} else {
time_before = OS::get_singleton()->get_ticks_usec();
dmc::DualGridGenerator dual_grid_generator(_dual_grid, root->size);
dual_grid_generator.node_proc(root);
// TODO Handle non-subdivided octree
_stats.dualgrid_derivation_time = OS::get_singleton()->get_ticks_usec() - time_before;
if (mode == VoxelMesherDMC::MODE_DEBUG_DUAL_GRID) {
mesh = dmc::generate_debug_dual_grid_mesh(_dual_grid);
} else {
time_before = OS::get_singleton()->get_ticks_usec();
dmc::polygonize_dual_grid(_dual_grid, voxels_access, _mesh_builder);
_stats.meshing_time = OS::get_singleton()->get_ticks_usec() - time_before;
time_before = OS::get_singleton()->get_ticks_usec();
mesh = _mesh_builder.commit(mode == VoxelMesherDMC::MODE_WIREFRAME);
_stats.commit_time = OS::get_singleton()->get_ticks_usec() - time_before;
}
_dual_grid.cells.clear();
}
if (mode == VoxelMesherDMC::MODE_DEBUG_OCTREE) {
Ref<ArrayMesh> mesh = dmc::generate_debug_octree_mesh(root);
memdelete(root); memdelete(root);
return mesh;
} }
time_before = OS::get_singleton()->get_ticks_usec();
dmc::DualGrid grid;
dmc::DualGridGenerator dual_grid_generator(grid, root->size);
dual_grid_generator.node_proc(root);
_stats.dualgrid_derivation_time = OS::get_singleton()->get_ticks_usec() - time_before;
memdelete(root);
// TODO Handle non-subdivided octree
if (mode == VoxelMesherDMC::MODE_DEBUG_DUAL_GRID) {
return dmc::generate_debug_dual_grid_mesh(grid);
}
time_before = OS::get_singleton()->get_ticks_usec();
dmc::polygonize_dual_grid(grid, voxels_access, _mesh_builder);
_stats.meshing_time = OS::get_singleton()->get_ticks_usec() - time_before;
time_before = OS::get_singleton()->get_ticks_usec();
Ref<ArrayMesh> mesh = _mesh_builder.commit(mode == VoxelMesherDMC::MODE_WIREFRAME);
_stats.commit_time = OS::get_singleton()->get_ticks_usec() - time_before;
// TODO Marching squares skirts // TODO Marching squares skirts
return mesh; return mesh;

View File

@ -2,9 +2,33 @@
#define VOXEL_MESHER_DMC_H #define VOXEL_MESHER_DMC_H
#include "../voxel_buffer.h" #include "../voxel_buffer.h"
#include "hermite_value.h"
#include "mesh_builder.h" #include "mesh_builder.h"
#include "scene/resources/mesh.h" #include "scene/resources/mesh.h"
namespace dmc {
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);
corners[i] = vertex;
values[i] = value;
}
};
struct DualGrid {
std::vector<DualCell> cells;
};
} // namespace dmc
class VoxelMesherDMC : public Reference { class VoxelMesherDMC : public Reference {
GDCLASS(VoxelMesherDMC, Reference) GDCLASS(VoxelMesherDMC, Reference)
public: public:
@ -24,6 +48,7 @@ protected:
private: private:
dmc::MeshBuilder _mesh_builder; dmc::MeshBuilder _mesh_builder;
dmc::DualGrid _dual_grid;
struct Stats { struct Stats {
real_t octree_build_time; real_t octree_build_time;