Better chunk building setup. And smaller fixes and tweaks.

This commit is contained in:
Relintai 2020-02-10 23:39:57 +01:00
parent db77530ec1
commit fd1ff4b4ff
5 changed files with 119 additions and 41 deletions

View File

@ -34,7 +34,7 @@ void VoxelMesher::set_library(Ref<VoxelmanLibrary> library) {
Ref<Material> VoxelMesher::get_material() {
return _material;
}
void VoxelMesher::set_material(Ref<Material> material) {
void VoxelMesher::set_material(const Ref<Material> &material) {
_material = material;
}

View File

@ -56,7 +56,7 @@ public:
void set_library(Ref<VoxelmanLibrary> library);
Ref<Material> get_material();
void set_material(Ref<Material> material);
void set_material(const Ref<Material> &material);
float get_ao_strength() const;
void set_ao_strength(float value);

View File

@ -538,20 +538,64 @@ void VoxelChunk::finalize_mesh() {
}
}
void VoxelChunk::build() {
void VoxelChunk::build_deferred() {
if (_current_build_phase == BUILD_PHASE_DONE) {
_build_prioritized = false;
set_process_internal(true);
if (_build_thread) {
Thread::wait_to_finish(_build_thread);
memdelete(_build_thread);
_build_thread = NULL;
}
_is_generating = true;
next_phase();
}
}
void VoxelChunk::_build_phase_threaded(void *_userdata) {
void VoxelChunk::build_prioritized() {
if (_current_build_phase == BUILD_PHASE_DONE) {
_build_prioritized = true;
set_process_internal(true);
if (_build_thread) {
Thread::wait_to_finish(_build_thread);
memdelete(_build_thread);
_build_thread = NULL;
}
_is_generating = true;
next_phase();
}
}
void VoxelChunk::_build_step() {
if (_build_prioritized)
build_phase();
if (_is_build_threaded) {
ERR_FAIL_COND(_build_thread != NULL);
_build_thread = Thread::create(_build_threaded, this);
} else {
build_phase();
}
}
void VoxelChunk::_build_threaded(void *_userdata) {
VoxelChunk *vc = (VoxelChunk *)_userdata;
vc->build_phase();
}
void VoxelChunk::build_phase() {
_build_phase_done = false;
call("_build_phase", _current_build_phase);
}
@ -660,6 +704,16 @@ void VoxelChunk::_build_phase(int phase) {
return;
}
/*
case BUILD_PHASE_LIQUID: {
next_phase();
return;
}
case BUILD_PHASE_CLUTTER: {
next_phase();
return;
}
*/
case BUILD_PHASE_FINALIZE: {
if (_mesh_instance_rid != RID())
VS::get_singleton()->instance_set_visible(_mesh_instance_rid, is_visible());
@ -682,37 +736,32 @@ void VoxelChunk::_build_phase(int phase) {
next_phase();
}
bool VoxelChunk::has_next_phase() {
if (_current_build_phase == BUILD_PHASE_DONE)
return false;
return true;
}
void VoxelChunk::next_phase() {
_build_phase_done = true;
if (_abort_build) {
_current_build_phase = BUILD_PHASE_DONE;
_is_generating = false;
return;
}
set_process_internal(false);
if (_build_thread) {
Thread::wait_to_finish(_build_thread);
memdelete(_build_thread);
_build_thread = NULL;
return;
}
++_current_build_phase;
if (_current_build_phase >= _max_build_phases) {
_current_build_phase = BUILD_PHASE_DONE;
_is_generating = false;
set_process_internal(false);
emit_signal("mesh_generation_finished", this);
return;
}
if (_is_build_threaded) {
ERR_FAIL_COND(_build_thread != NULL);
_build_thread = Thread::create(_build_phase_threaded, this);
} else {
build_phase();
}
}
@ -1212,6 +1261,8 @@ VoxelChunk::VoxelChunk() {
_margin_start = 0;
_margin_end = 0;
_build_prioritized = false;
_build_phase_done = false;
_build_thread = NULL;
}
@ -1254,6 +1305,25 @@ void VoxelChunk::_notification(int p_what) {
_build_thread = NULL;
}
}
case NOTIFICATION_INTERNAL_PROCESS: {
if (_build_prioritized) {
while (has_next_phase() && _build_phase_done) {
build_phase();
}
return;
}
if (has_next_phase() && _build_phase_done) {
if (_build_thread) {
Thread::wait_to_finish(_build_thread);
memdelete(_build_thread);
_build_thread = NULL;
}
build_phase();
}
}
}
}
@ -1409,10 +1479,12 @@ void VoxelChunk::_bind_methods() {
BIND_VMETHOD(MethodInfo("_build_phase", PropertyInfo(Variant::INT, "phase")));
ClassDB::bind_method(D_METHOD("build"), &VoxelChunk::build);
ClassDB::bind_method(D_METHOD("build_deferred"), &VoxelChunk::build_deferred);
ClassDB::bind_method(D_METHOD("build_prioritized"), &VoxelChunk::build_prioritized);
ClassDB::bind_method(D_METHOD("build_phase"), &VoxelChunk::build_phase);
ClassDB::bind_method(D_METHOD("_build_phase", "phase"), &VoxelChunk::_build_phase);
ClassDB::bind_method(D_METHOD("next_phase"), &VoxelChunk::next_phase);
ClassDB::bind_method(D_METHOD("has_next_phase"), &VoxelChunk::has_next_phase);
ClassDB::bind_method(D_METHOD("clear"), &VoxelChunk::clear);
ClassDB::bind_method(D_METHOD("create_colliders"), &VoxelChunk::create_colliders);

View File

@ -66,26 +66,26 @@ class VoxelChunk : public Spatial {
public:
enum {
VOXEL_CHUNK_STATE_OK = 0,
VOXEL_CHUNK_STATE_GENERATION_QUEUED = 1,
VOXEL_CHUNK_STATE_GENERATION = 2,
VOXEL_CHUNK_STATE_MESH_GENERATION_QUEUED = 3,
VOXEL_CHUNK_STATE_MESH_GENERATION = 4,
VOXEL_CHUNK_STATE_MAX = 5,
VOXEL_CHUNK_STATE_GENERATION_QUEUED,
VOXEL_CHUNK_STATE_GENERATION,
VOXEL_CHUNK_STATE_MESH_GENERATION_QUEUED,
VOXEL_CHUNK_STATE_MESH_GENERATION,
VOXEL_CHUNK_STATE_MAX,
};
enum {
BUILD_PHASE_DONE = 0,
BUILD_PHASE_SETUP = 1,
BUILD_PHASE_TERRARIN_MESH_SETUP = 2,
BUILD_PHASE_TERRARIN_MESH_COLLIDER = 3,
BUILD_PHASE_LIGHTS = 4,
BUILD_PHASE_TERRARIN_MESH = 5,
BUILD_PHASE_PROP_MESH = 6,
BUILD_PHASE_PROP_COLLIDER = 7,
BUILD_PHASE_LIQUID = 8,
BUILD_PHASE_CLUTTER = 9,
BUILD_PHASE_FINALIZE = 10,
BUILD_PHASE_MAX = 11
BUILD_PHASE_SETUP,
BUILD_PHASE_TERRARIN_MESH_SETUP,
BUILD_PHASE_TERRARIN_MESH_COLLIDER,
BUILD_PHASE_LIGHTS,
BUILD_PHASE_TERRARIN_MESH,
BUILD_PHASE_PROP_MESH,
BUILD_PHASE_PROP_COLLIDER,
//BUILD_PHASE_LIQUID,
//BUILD_PHASE_CLUTTER,
BUILD_PHASE_FINALIZE,
BUILD_PHASE_MAX
};
enum DefaultChannels {
@ -218,10 +218,14 @@ public:
void finalize_mesh();
void build();
static void _build_phase_threaded(void *_userdata);
void build_deferred();
void build_prioritized();
static void _build_threaded(void *_userdata);
void build_phase();
void _build_step();
void _build_phase(int phase);
bool has_next_phase();
void next_phase();
void clear();
@ -368,6 +372,8 @@ protected:
bool _bake_lights;
bool _build_prioritized;
bool _build_phase_done;
Thread *_build_thread;
};

View File

@ -286,7 +286,7 @@ void VoxelWorld::generate_chunk(VoxelChunk *p_chunk) {
call("_generate_chunk", p_chunk);
p_chunk->build();
p_chunk->build_deferred();
}
void VoxelWorld::_generate_chunk(Node *p_chunk) {