From dec4fcd40239da6ae389c483a7146493d177c287 Mon Sep 17 00:00:00 2001 From: Relintai Date: Wed, 4 Mar 2020 14:59:34 +0100 Subject: [PATCH] Added get_max_frame_chunk_build_steps to be able to limit the chunk build steps launched per frame. Also a few smaller improvements. --- world/voxel_world.cpp | 70 +++++++++++++++++++++++++++++++++---------- world/voxel_world.h | 19 ++++++++---- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/world/voxel_world.cpp b/world/voxel_world.cpp index 388ae0c..d3f0a77 100644 --- a/world/voxel_world.cpp +++ b/world/voxel_world.cpp @@ -73,14 +73,21 @@ void VoxelWorld::set_use_threads(bool value) { _use_threads = OS::get_singleton()->can_use_threads() ? value : false; } -uint32_t VoxelWorld::get_max_concurrent_generations() { +uint32_t VoxelWorld::get_max_concurrent_generations() const { return _max_concurrent_generations; } -void VoxelWorld::set_max_concurrent_generations(uint32_t value) { +void VoxelWorld::set_max_concurrent_generations(const uint32_t value) { _max_concurrent_generations = OS::get_singleton()->can_use_threads() ? value : 1; } -Ref VoxelWorld::get_library() const { +uint32_t VoxelWorld::get_max_frame_chunk_build_steps() const { + return _max_frame_chunk_build_steps; +} +void VoxelWorld::set_max_frame_chunk_build_steps(const uint32_t value) { + _max_frame_chunk_build_steps = value; +} + +Ref VoxelWorld::get_library() { return _library; } void VoxelWorld::set_library(const Ref library) { @@ -147,9 +154,15 @@ int VoxelWorld::get_world_area_count() const { } void VoxelWorld::add_chunk(VoxelChunk *chunk, const int x, const int y, const int z) { + ERR_FAIL_COND(!ObjectDB::instance_validate(chunk)); + + IntPos pos(x, y, z); + + ERR_FAIL_COND(_chunks.has(pos)); + chunk->set_position(x, y, z); - _chunks.set(IntPos(x, y, z), chunk); + _chunks.set(pos, chunk); _chunks_vector.push_back(chunk); } void VoxelWorld::add_chunk_bind(Node *chunk, const int x, const int y, const int z) { @@ -159,16 +172,22 @@ void VoxelWorld::add_chunk_bind(Node *chunk, const int x, const int y, const int add_chunk(v, x, y, z); } -VoxelChunk *VoxelWorld::get_chunk(const int x, const int y, const int z) const { - if (_chunks.has(IntPos(x, y, z))) - return _chunks.get(IntPos(x, y, z)); +bool VoxelWorld::has_chunk(const int x, const int y, const int z) const { + return _chunks.has(IntPos(x, y, z)); +} +VoxelChunk *VoxelWorld::get_chunk(const int x, const int y, const int z) { + IntPos pos(x, y, z); + + if (_chunks.has(pos)) + return _chunks.get(pos); return NULL; } VoxelChunk *VoxelWorld::remove_chunk(const int x, const int y, const int z) { IntPos pos(x, y, z); - ERR_FAIL_COND_V(!_chunks.has(pos), NULL); + if (!_chunks.has(pos)) + return NULL; VoxelChunk *chunk = _chunks.get(pos); @@ -179,7 +198,9 @@ VoxelChunk *VoxelWorld::remove_chunk(const int x, const int y, const int z) { } } - _chunks.erase(pos); + ERR_FAIL_COND_V(!_chunks.erase(pos), NULL); + + //_chunks.erase(pos); return chunk; } @@ -188,7 +209,7 @@ VoxelChunk *VoxelWorld::remove_chunk_index(const int index) { VoxelChunk *chunk = _chunks_vector.get(index); _chunks_vector.remove(index); - _chunks.erase(IntPos(chunk->get_position())); + _chunks.erase(IntPos(chunk->get_position_x(), chunk->get_position_y(), chunk->get_position_z())); return chunk; } @@ -316,13 +337,12 @@ void VoxelWorld::generate_chunk(VoxelChunk *p_chunk) { p_chunk->build_deferred(); } -void VoxelWorld::_generate_chunk(Node *p_chunk) { - VoxelChunk *chunk = Object::cast_to(p_chunk); +bool VoxelWorld::can_chunk_do_build_step() { + if (_max_frame_chunk_build_steps == 0) { + return true; + } - ERR_FAIL_COND(!ObjectDB::instance_validate(chunk)); - ERR_FAIL_COND(!_level_generator.is_valid()); - - _level_generator->generate_chunk(chunk); + return _num_frame_chunk_build_steps++ < _max_frame_chunk_build_steps; } VoxelWorld::VoxelWorld() { @@ -340,6 +360,8 @@ VoxelWorld::VoxelWorld() { _chunk_spawn_range = 4; _player = NULL; + _max_frame_chunk_build_steps = 0; + _num_frame_chunk_build_steps = 0; } VoxelWorld ::~VoxelWorld() { @@ -356,6 +378,15 @@ VoxelWorld ::~VoxelWorld() { _generating.clear(); } +void VoxelWorld::_generate_chunk(Node *p_chunk) { + VoxelChunk *chunk = Object::cast_to(p_chunk); + + ERR_FAIL_COND(!ObjectDB::instance_validate(chunk)); + ERR_FAIL_COND(!_level_generator.is_valid()); + + _level_generator->generate_chunk(chunk); +} + void VoxelWorld::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -365,6 +396,8 @@ void VoxelWorld::_notification(int p_what) { _library->refresh_rects(); } case NOTIFICATION_INTERNAL_PROCESS: { + _num_frame_chunk_build_steps = 0; + if (_generation_queue.empty() && _generating.empty()) { call("_generation_finished"); @@ -439,6 +472,10 @@ void VoxelWorld::_bind_methods() { ClassDB::bind_method(D_METHOD("set_max_concurrent_generations", "value"), &VoxelWorld::set_max_concurrent_generations); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_concurrent_generations"), "set_max_concurrent_generations", "get_max_concurrent_generations"); + ClassDB::bind_method(D_METHOD("get_max_frame_chunk_build_steps"), &VoxelWorld::get_max_frame_chunk_build_steps); + ClassDB::bind_method(D_METHOD("set_max_frame_chunk_build_steps", "value"), &VoxelWorld::set_max_frame_chunk_build_steps); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_frame_chunk_build_steps"), "set_max_frame_chunk_build_steps", "get_max_frame_chunk_build_steps"); + ClassDB::bind_method(D_METHOD("get_library"), &VoxelWorld::get_library); ClassDB::bind_method(D_METHOD("set_library", "library"), &VoxelWorld::set_library); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "VoxelmanLibrary"), "set_library", "get_library"); @@ -470,6 +507,7 @@ void VoxelWorld::_bind_methods() { ClassDB::bind_method(D_METHOD("get_world_area_count"), &VoxelWorld::get_world_area_count); ClassDB::bind_method(D_METHOD("add_chunk", "chunk", "x", "y", "z"), &VoxelWorld::add_chunk_bind); + ClassDB::bind_method(D_METHOD("has_chunk", "x", "y", "z"), &VoxelWorld::has_chunk); ClassDB::bind_method(D_METHOD("get_chunk", "x", "y", "z"), &VoxelWorld::get_chunk); ClassDB::bind_method(D_METHOD("remove_chunk", "x", "y", "z"), &VoxelWorld::remove_chunk); ClassDB::bind_method(D_METHOD("remove_chunk_index", "index"), &VoxelWorld::remove_chunk_index); diff --git a/world/voxel_world.h b/world/voxel_world.h index 8a3b2a0..9930deb 100644 --- a/world/voxel_world.h +++ b/world/voxel_world.h @@ -60,10 +60,13 @@ public: bool get_use_threads(); void set_use_threads(bool value); - uint32_t get_max_concurrent_generations(); - void set_max_concurrent_generations(uint32_t value); + uint32_t get_max_concurrent_generations() const; + void set_max_concurrent_generations(const uint32_t value); - Ref get_library() const; + uint32_t get_max_frame_chunk_build_steps() const; + void set_max_frame_chunk_build_steps(const uint32_t value); + + Ref get_library(); void set_library(const Ref library); Ref get_level_generator() const; @@ -90,7 +93,8 @@ public: void add_chunk(VoxelChunk *chunk, const int x, const int y, const int z); void add_chunk_bind(Node *chunk, const int x, const int y, const int z); - VoxelChunk *get_chunk(const int x, const int y, const int z) const; + bool has_chunk(const int x, const int y, const int z) const; + VoxelChunk *get_chunk(const int x, const int y, const int z); VoxelChunk *remove_chunk(const int x, const int y, const int z); VoxelChunk *remove_chunk_index(const int index); @@ -116,12 +120,15 @@ public: void generate_chunk_bind(Node *p_chunk); void generate_chunk(VoxelChunk *p_chunk); - void _generate_chunk(Node *p_chunk); + + bool can_chunk_do_build_step(); VoxelWorld(); ~VoxelWorld(); protected: + void _generate_chunk(Node *p_chunk); + virtual void _notification(int p_what); static void _bind_methods(); @@ -183,6 +190,8 @@ private: uint32_t _max_concurrent_generations; Vector _generation_queue; Vector _generating; + uint32_t _max_frame_chunk_build_steps; + uint32_t _num_frame_chunk_build_steps; }; _FORCE_INLINE_ bool operator==(const VoxelWorld::IntPos &a, const VoxelWorld::IntPos &b) {