feat: implemented multithreading and chunk lods
This commit is contained in:
parent
49b65a7ade
commit
1951b560ed
6 changed files with 256 additions and 53 deletions
|
|
@ -1,7 +1,14 @@
|
|||
#include "terrain_chunk.h"
|
||||
#include "core/config/engine.h"
|
||||
#include "macros.h"
|
||||
#include "scene/3d/camera_3d.h"
|
||||
#include "scene/main/viewport.h"
|
||||
#include "terrain_editor/terrain_mesh_generator.h"
|
||||
|
||||
void TerrainChunk::_bind_methods() {}
|
||||
void TerrainChunk::_bind_methods() {
|
||||
BIND_PROPERTY(Variant::FLOAT, size);
|
||||
BIND_PROPERTY(Variant::INT, lod0_detail);
|
||||
}
|
||||
|
||||
void TerrainChunk::ready() {
|
||||
if ((this->generator = cast_to<TerrainMeshGenerator>(get_parent()))) {
|
||||
|
|
@ -10,41 +17,85 @@ void TerrainChunk::ready() {
|
|||
print_error(vformat("Chunk %s ready without generator.", get_path()));
|
||||
return;
|
||||
}
|
||||
this->set_mesh(this->lod1);
|
||||
process_lod();
|
||||
on_terrain_changed();
|
||||
}
|
||||
|
||||
void TerrainChunk::on_terrain_changed() {
|
||||
if (this->generator) {
|
||||
Vector3 const position{ get_global_position() };
|
||||
this->generator->generate_grid({ { position.x, position.z }, { this->size, this->size } }, this->mesh, this->lod1_detail);
|
||||
this->meshes.resize_zeroed(5);
|
||||
size_t lod{ 0 };
|
||||
for (MeshStatus &status : this->meshes) {
|
||||
if (!status.mesh.is_valid()) {
|
||||
status.mesh.instantiate();
|
||||
}
|
||||
size_t base_detail{ lod == 0 ? this->lod0_detail : this->lod0_detail / (2 * lod * lod) };
|
||||
status.dirty = true;
|
||||
this->generator->push_task({ { position.x, position.z }, { this->size, this->size } }, status.mesh, base_detail > 1 ? base_detail : 1, callable_mp(this, &self_type::lod_generated).bind(lod));
|
||||
lod++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainChunk::lod_generated(size_t lod) {
|
||||
this->meshes.set(lod, MeshStatus{ this->meshes[lod].mesh, false });
|
||||
}
|
||||
|
||||
void TerrainChunk::process_lod() {
|
||||
size_t result{ (size_t)this->meshes.size() };
|
||||
if (is_ready() && this->meshes.size() > 0) {
|
||||
Vector3 position{ get_global_position() };
|
||||
Vector3 camera{ get_viewport()->get_camera_3d()->get_global_position() };
|
||||
position.y = camera.y = 0;
|
||||
float distance{ camera.distance_to(position) };
|
||||
size_t lod{ size_t(Math::floor(distance / (this->lod4_distance / 5.f))) };
|
||||
result = lod < 5 ? lod : 4;
|
||||
while (this->meshes[result].dirty && result < (this->meshes.size() - 1)) {
|
||||
result++;
|
||||
}
|
||||
if (this->meshes[result].mesh != this->get_mesh()) {
|
||||
this->set_mesh(this->meshes[result].mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainChunk::_notification(int what) {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
}
|
||||
switch (what) {
|
||||
default:
|
||||
return;
|
||||
case NOTIFICATION_READY:
|
||||
set_process_thread_group(ProcessThreadGroup::PROCESS_THREAD_GROUP_SUB_THREAD);
|
||||
set_process(true);
|
||||
ready();
|
||||
return;
|
||||
case NOTIFICATION_PROCESS:
|
||||
process_lod();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainChunk::set_size(float size) {
|
||||
this->size = size;
|
||||
on_terrain_changed();
|
||||
if (is_ready()) {
|
||||
on_terrain_changed();
|
||||
}
|
||||
}
|
||||
|
||||
float TerrainChunk::get_size() const {
|
||||
return this->size;
|
||||
}
|
||||
|
||||
void TerrainChunk::set_lod1_detail(int detail) {
|
||||
this->lod1_detail = detail;
|
||||
on_terrain_changed();
|
||||
void TerrainChunk::set_lod0_detail(int detail) {
|
||||
this->lod0_detail = detail;
|
||||
if (is_ready()) {
|
||||
on_terrain_changed();
|
||||
}
|
||||
}
|
||||
|
||||
int TerrainChunk::get_lod1_detail() const {
|
||||
return this->lod1_detail;
|
||||
int TerrainChunk::get_lod0_detail() const {
|
||||
return this->lod0_detail;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue