Renamed VoxelServer => VoxelEngine

master
Marc Gilleron 2022-07-16 23:59:06 +01:00
parent bc8e03c780
commit 5ca09d712e
45 changed files with 320 additions and 312 deletions

2
SCsub
View File

@ -48,7 +48,7 @@ voxel_files = [
"terrain/fixed_lod/*.cpp",
"terrain/variable_lod/*.cpp",
"server/*.cpp",
"engine/*.cpp",
"edition/*.cpp",
"thirdparty/lz4/*.c",

View File

@ -23,10 +23,9 @@ def get_icons_path():
def get_doc_classes():
return [
"VoxelServer",
"VoxelEngine",
"ZN_ThreadedTask",
"Voxel",
"VoxelLibrary",
"VoxelColorPalette",
"VoxelInstanceLibrary",

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VoxelServer" inherits="Object" version="3.5">
<class name="VoxelEngine" inherits="Object" version="3.5">
<brief_description>
Singleton handling common voxel processing in background threads.
Singleton handling common voxel processing tasks in background threads.
</brief_description>
<description>
</description>

View File

@ -62,7 +62,7 @@ nav:
- api/VoxelMesherTransvoxel.md
- api/VoxelNode.md
- api/VoxelRaycastResult.md
- api/VoxelServer.md
- api/VoxelEngine.md
- api/VoxelStream.md
- api/VoxelStreamBlockFiles.md
- api/VoxelStreamRegionFiles.md

View File

@ -1,4 +1,4 @@
# VoxelServer
# VoxelEngine
Inherits: [Object](https://docs.godotengine.org/en/stable/classes/class_object.html)

View File

@ -48,7 +48,7 @@ meshers/ | Only depends on voxel storage, math and some Godot graphics API
streams/ | Files handling code. Only depends on filesystem and storage.
util/ | Generic utility functions and structures. They don't depend on voxel stuff.
thirdparty/ | Third-party libraries, in source code form. They are compiled statically so Godot remains a single executable.
server/ | Contains task management. Depends on meshers, streams, storage but not directly on nodes.
engine/ | Contains task management. Depends on meshers, streams, storage but not directly on nodes.
storage/ | Storage and memory data structures.
terrain/ | Contains all the nodes. Depends on the rest of the module, except editor-only parts.
tests/ | Contains tests. These run when Godot starts if enabled in the build script.

View File

@ -1,6 +1,6 @@
#include "voxel_mesh_sdf_gd.h"
#include "../server/voxel_server.h"
#include "../server/voxel_server_updater.h"
#include "../engine/voxel_engine.h"
#include "../engine/voxel_engine_updater.h"
#include "../storage/voxel_buffer_gd.h"
#include "../util/dstack.h"
#include "../util/godot/funcs.h"
@ -154,7 +154,7 @@ void VoxelMeshSDF::bake() {
void VoxelMeshSDF::bake_async(SceneTree *scene_tree) {
ZN_ASSERT_RETURN(scene_tree != nullptr);
VoxelServerUpdater::ensure_existence(scene_tree);
VoxelEngineUpdater::ensure_existence(scene_tree);
//ZN_ASSERT_RETURN_MSG(!_is_baking, "Already baking");
@ -247,7 +247,7 @@ void VoxelMeshSDF::bake_async(SceneTree *scene_tree) {
task->box = Box3i(Vector3i(0, 0, z), Vector3i(res.x, res.y, 1));
task->obj_to_notify = obj_to_notify;
VoxelServer::get_singleton().push_async_task(task);
VoxelEngine::get_singleton().push_async_task(task);
}
} break;
@ -315,7 +315,7 @@ void VoxelMeshSDF::bake_async(SceneTree *scene_tree) {
task->surface = surface;
task->obj_to_notify.reference_ptr(this);
task->boundary_sign_fix = _boundary_sign_fix;
VoxelServer::get_singleton().push_async_task(task);
VoxelEngine::get_singleton().push_async_task(task);
}
void VoxelMeshSDF::_on_bake_async_completed(Ref<gd::VoxelBuffer> buffer, Vector3 min_pos, Vector3 max_pos) {

View File

@ -1,6 +1,6 @@
#include "voxel_terrain_editor_plugin.h"
#include "../../engine/voxel_engine_gd.h"
#include "../../generators/voxel_generator.h"
#include "../../server/voxel_server_gd.h"
#include "../../storage/modifiers_gd.h"
#include "../../terrain/fixed_lod/voxel_terrain.h"
#include "../../terrain/variable_lod/voxel_lod_terrain.h"
@ -74,17 +74,17 @@ void VoxelTerrainEditorPlugin::generate_menu_items(MenuButton *menu_button, bool
void VoxelTerrainEditorPlugin::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
_editor_viewer_id = VoxelServer::get_singleton().add_viewer();
VoxelServer::get_singleton().set_viewer_distance(_editor_viewer_id, 512);
_editor_viewer_id = VoxelEngine::get_singleton().add_viewer();
VoxelEngine::get_singleton().set_viewer_distance(_editor_viewer_id, 512);
// No collision needed in editor, also it updates faster without
VoxelServer::get_singleton().set_viewer_requires_collisions(_editor_viewer_id, false);
VoxelEngine::get_singleton().set_viewer_requires_collisions(_editor_viewer_id, false);
_inspector_plugin.instantiate();
add_inspector_plugin(_inspector_plugin);
break;
case NOTIFICATION_EXIT_TREE:
VoxelServer::get_singleton().remove_viewer(_editor_viewer_id);
VoxelEngine::get_singleton().remove_viewer(_editor_viewer_id);
remove_inspector_plugin(_inspector_plugin);
break;
@ -195,12 +195,12 @@ void VoxelTerrainEditorPlugin::make_visible(bool visible) {
EditorPlugin::AfterGUIInput VoxelTerrainEditorPlugin::forward_spatial_gui_input(
Camera3D *p_camera, const Ref<InputEvent> &p_event) {
VoxelServer::get_singleton().set_viewer_distance(_editor_viewer_id, p_camera->get_far());
VoxelEngine::get_singleton().set_viewer_distance(_editor_viewer_id, p_camera->get_far());
_editor_camera_last_position = p_camera->get_global_transform().origin;
if (_editor_viewer_follows_camera) {
VoxelServer::get_singleton().set_viewer_position(_editor_viewer_id, _editor_camera_last_position);
gd::VoxelServer::get_singleton()->set_editor_camera_info(
VoxelEngine::get_singleton().set_viewer_position(_editor_viewer_id, _editor_camera_last_position);
gd::VoxelEngine::get_singleton()->set_editor_camera_info(
_editor_camera_last_position, get_forward(p_camera->get_global_transform()));
}
@ -223,7 +223,7 @@ void VoxelTerrainEditorPlugin::_on_menu_item_selected(int id) {
_editor_viewer_follows_camera = !_editor_viewer_follows_camera;
if (_editor_viewer_follows_camera) {
VoxelServer::get_singleton().set_viewer_position(_editor_viewer_id, _editor_camera_last_position);
VoxelEngine::get_singleton().set_viewer_position(_editor_viewer_id, _editor_camera_last_position);
}
const int i = _menu_button->get_popup()->get_item_index(MENU_STREAM_FOLLOW_CAMERA);

View File

@ -1,7 +1,7 @@
#ifndef VOXEL_TERRAIN_EDITOR_TASK_INDICATOR_H
#define VOXEL_TERRAIN_EDITOR_TASK_INDICATOR_H
#include "../../server/voxel_server.h"
#include "../../engine/voxel_engine.h"
#include <editor/editor_scale.h>
#include <scene/gui/box_container.h>
@ -44,7 +44,7 @@ public:
}
void update_stats() {
const VoxelServer::Stats stats = VoxelServer::get_singleton().get_stats();
const VoxelEngine::Stats stats = VoxelEngine::get_singleton().get_stats();
set_stat(STAT_STREAM_TASKS, stats.streaming_tasks);
set_stat(STAT_GENERATE_TASKS, stats.generation_tasks);
set_stat(STAT_MESH_TASKS, stats.meshing_tasks);

View File

@ -6,7 +6,7 @@
#include "../util/profiling.h"
#include "../util/string_funcs.h"
#include "save_block_data_task.h"
#include "voxel_server.h"
#include "voxel_engine.h"
namespace zylann::voxel {
@ -67,7 +67,7 @@ void GenerateBlockTask::run(zylann::ThreadedTaskContext ctx) {
SaveBlockDataTask *save_task =
memnew(SaveBlockDataTask(volume_id, position, lod, block_size, voxels_copy, stream_dependency));
VoxelServer::get_singleton().push_async_task(save_task);
VoxelEngine::get_singleton().push_async_task(save_task);
}
}
@ -88,14 +88,14 @@ bool GenerateBlockTask::is_cancelled() {
void GenerateBlockTask::apply_result() {
bool aborted = true;
if (VoxelServer::get_singleton().is_volume_valid(volume_id)) {
if (VoxelEngine::get_singleton().is_volume_valid(volume_id)) {
// TODO Comparing pointer may not be guaranteed
// The request response must match the dependency it would have been requested with.
// If it doesn't match, we are no longer interested in the result.
if (stream_dependency->valid) {
Ref<VoxelStream> stream = stream_dependency->stream;
VoxelServer::BlockDataOutput o;
VoxelEngine::BlockDataOutput o;
o.voxels = voxels;
o.position = position;
o.lod = lod;
@ -103,14 +103,14 @@ void GenerateBlockTask::apply_result() {
if (stream.is_valid() && stream->get_save_generator_output()) {
// We can't consider the block as "generated" since there is no state to tell that once saved,
// so it has to be considered an edited block
o.type = VoxelServer::BlockDataOutput::TYPE_LOADED;
o.type = VoxelEngine::BlockDataOutput::TYPE_LOADED;
} else {
o.type = VoxelServer::BlockDataOutput::TYPE_GENERATED;
o.type = VoxelEngine::BlockDataOutput::TYPE_GENERATED;
}
o.max_lod_hint = max_lod_hint;
o.initial_load = false;
VoxelServer::VolumeCallbacks callbacks = VoxelServer::get_singleton().get_volume_callbacks(volume_id);
VoxelEngine::VolumeCallbacks callbacks = VoxelEngine::get_singleton().get_volume_callbacks(volume_id);
ERR_FAIL_COND(callbacks.data_output_callback == nullptr);
callbacks.data_output_callback(callbacks.data, o);

View File

@ -2,7 +2,7 @@
#include "../util/log.h"
#include "../util/profiling.h"
#include "../util/string_funcs.h"
#include "voxel_server.h"
#include "voxel_engine.h"
namespace zylann::voxel {
@ -27,18 +27,18 @@ bool LoadAllBlocksDataTask::is_cancelled() {
}
void LoadAllBlocksDataTask::apply_result() {
if (VoxelServer::get_singleton().is_volume_valid(volume_id)) {
if (VoxelEngine::get_singleton().is_volume_valid(volume_id)) {
// TODO Comparing pointer may not be guaranteed
// The request response must match the dependency it would have been requested with.
// If it doesn't match, we are no longer interested in the result.
if (stream_dependency->valid) {
VoxelServer::VolumeCallbacks callbacks = VoxelServer::get_singleton().get_volume_callbacks(volume_id);
VoxelEngine::VolumeCallbacks callbacks = VoxelEngine::get_singleton().get_volume_callbacks(volume_id);
ERR_FAIL_COND(callbacks.data_output_callback == nullptr);
for (auto it = _result.blocks.begin(); it != _result.blocks.end(); ++it) {
VoxelStream::FullLoadingResult::Block &rb = *it;
VoxelServer::BlockDataOutput o;
VoxelEngine::BlockDataOutput o;
o.voxels = rb.voxels;
o.instances = std::move(rb.instances_data);
o.position = rb.position;

View File

@ -5,7 +5,7 @@
#include "../util/log.h"
#include "../util/profiling.h"
#include "generate_block_task.h"
#include "voxel_server.h"
#include "voxel_engine.h"
namespace zylann::voxel {
@ -76,7 +76,7 @@ void LoadBlockDataTask::run(zylann::ThreadedTaskContext ctx) {
task->stream_dependency = _stream_dependency;
task->priority_dependency = _priority_dependency;
VoxelServer::get_singleton().push_async_task(task);
VoxelEngine::get_singleton().push_async_task(task);
_requested_generator_task = true;
} else {
@ -120,12 +120,12 @@ bool LoadBlockDataTask::is_cancelled() {
}
void LoadBlockDataTask::apply_result() {
if (VoxelServer::get_singleton().is_volume_valid(_volume_id)) {
if (VoxelEngine::get_singleton().is_volume_valid(_volume_id)) {
// TODO Comparing pointer may not be guaranteed
// The request response must match the dependency it would have been requested with.
// If it doesn't match, we are no longer interested in the result.
if (_stream_dependency->valid && !_requested_generator_task) {
VoxelServer::BlockDataOutput o;
VoxelEngine::BlockDataOutput o;
o.voxels = _voxels;
o.instances = std::move(_instances);
o.position = _position;
@ -133,9 +133,9 @@ void LoadBlockDataTask::apply_result() {
o.dropped = !_has_run;
o.max_lod_hint = _max_lod_hint;
o.initial_load = false;
o.type = VoxelServer::BlockDataOutput::TYPE_LOADED;
o.type = VoxelEngine::BlockDataOutput::TYPE_LOADED;
VoxelServer::VolumeCallbacks callbacks = VoxelServer::get_singleton().get_volume_callbacks(_volume_id);
VoxelEngine::VolumeCallbacks callbacks = VoxelEngine::get_singleton().get_volume_callbacks(_volume_id);
CRASH_COND(callbacks.data_output_callback == nullptr);
callbacks.data_output_callback(callbacks.data, o);
}

View File

@ -5,7 +5,7 @@
#include "../util/godot/funcs.h"
#include "../util/log.h"
#include "../util/profiling.h"
#include "voxel_server.h"
#include "voxel_engine.h"
namespace zylann::voxel {
@ -301,7 +301,7 @@ void MeshBlockTask::run(zylann::ThreadedTaskContext ctx) {
lod_index, collision_hint, lod_hint };
mesher->build(_surfaces_output, input);
if (VoxelServer::get_singleton().is_threaded_mesh_resource_building_enabled()) {
if (VoxelEngine::get_singleton().is_threaded_mesh_resource_building_enabled()) {
// This shall only run if Godot supports building meshes from multiple threads
_mesh = build_mesh(to_span(_surfaces_output.surfaces), _surfaces_output.primitive_type,
_surfaces_output.mesh_flags, _mesh_material_indices);
@ -325,18 +325,18 @@ bool MeshBlockTask::is_cancelled() {
}
void MeshBlockTask::apply_result() {
if (VoxelServer::get_singleton().is_volume_valid(volume_id)) {
if (VoxelEngine::get_singleton().is_volume_valid(volume_id)) {
// The request response must match the dependency it would have been requested with.
// If it doesn't match, we are no longer interested in the result.
// It is assumed that if a dependency is changed, a new copy of it is made and the old one is marked invalid.
if (meshing_dependency->valid) {
VoxelServer::BlockMeshOutput o;
VoxelEngine::BlockMeshOutput o;
// TODO Check for invalidation due to property changes
if (_has_run) {
o.type = VoxelServer::BlockMeshOutput::TYPE_MESHED;
o.type = VoxelEngine::BlockMeshOutput::TYPE_MESHED;
} else {
o.type = VoxelServer::BlockMeshOutput::TYPE_DROPPED;
o.type = VoxelEngine::BlockMeshOutput::TYPE_DROPPED;
}
o.position = position;
@ -346,7 +346,7 @@ void MeshBlockTask::apply_result() {
o.mesh_material_indices = std::move(_mesh_material_indices);
o.has_mesh_resource = _has_mesh_resource;
VoxelServer::VolumeCallbacks callbacks = VoxelServer::get_singleton().get_volume_callbacks(volume_id);
VoxelEngine::VolumeCallbacks callbacks = VoxelEngine::get_singleton().get_volume_callbacks(volume_id);
ERR_FAIL_COND(callbacks.mesh_output_callback == nullptr);
ERR_FAIL_COND(callbacks.data == nullptr);
callbacks.mesh_output_callback(callbacks.data, o);

View File

@ -4,7 +4,7 @@
#include "../util/profiling.h"
#include "../util/string_funcs.h"
#include "generate_block_task.h"
#include "voxel_server.h"
#include "voxel_engine.h"
namespace zylann::voxel {
@ -94,18 +94,18 @@ bool SaveBlockDataTask::is_cancelled() {
}
void SaveBlockDataTask::apply_result() {
if (VoxelServer::get_singleton().is_volume_valid(_volume_id)) {
if (VoxelEngine::get_singleton().is_volume_valid(_volume_id)) {
if (_stream_dependency->valid) {
// TODO Perhaps separate save and load callbacks?
VoxelServer::BlockDataOutput o;
VoxelEngine::BlockDataOutput o;
o.position = _position;
o.lod = _lod;
o.dropped = !_has_run;
o.max_lod_hint = false; // Unused
o.initial_load = false; // Unused
o.type = VoxelServer::BlockDataOutput::TYPE_SAVED;
o.type = VoxelEngine::BlockDataOutput::TYPE_SAVED;
VoxelServer::VolumeCallbacks callbacks = VoxelServer::get_singleton().get_volume_callbacks(_volume_id);
VoxelEngine::VolumeCallbacks callbacks = VoxelEngine::get_singleton().get_volume_callbacks(_volume_id);
CRASH_COND(callbacks.data_output_callback == nullptr);
callbacks.data_output_callback(callbacks.data, o);
}

View File

@ -1,4 +1,4 @@
#include "voxel_server.h"
#include "voxel_engine.h"
#include "../constants/voxel_constants.h"
#include "../util/log.h"
#include "../util/macros.h"
@ -12,25 +12,25 @@
namespace zylann::voxel {
VoxelServer *g_voxel_server = nullptr;
VoxelEngine *g_voxel_engine = nullptr;
VoxelServer &VoxelServer::get_singleton() {
ZN_ASSERT_MSG(g_voxel_server != nullptr, "Accessing singleton while it's null");
return *g_voxel_server;
VoxelEngine &VoxelEngine::get_singleton() {
ZN_ASSERT_MSG(g_voxel_engine != nullptr, "Accessing singleton while it's null");
return *g_voxel_engine;
}
void VoxelServer::create_singleton(ThreadsConfig threads_config) {
ZN_ASSERT_MSG(g_voxel_server == nullptr, "Creating singleton twice");
g_voxel_server = ZN_NEW(VoxelServer(threads_config));
void VoxelEngine::create_singleton(ThreadsConfig threads_config) {
ZN_ASSERT_MSG(g_voxel_engine == nullptr, "Creating singleton twice");
g_voxel_engine = ZN_NEW(VoxelEngine(threads_config));
}
void VoxelServer::destroy_singleton() {
ZN_ASSERT_MSG(g_voxel_server != nullptr, "Destroying singleton twice");
ZN_DELETE(g_voxel_server);
g_voxel_server = nullptr;
void VoxelEngine::destroy_singleton() {
ZN_ASSERT_MSG(g_voxel_engine != nullptr, "Destroying singleton twice");
ZN_DELETE(g_voxel_engine);
g_voxel_engine = nullptr;
}
VoxelServer::VoxelServer(ThreadsConfig threads_config) {
VoxelEngine::VoxelEngine(ThreadsConfig threads_config) {
const int hw_threads_hint = Thread::get_hardware_concurrency();
ZN_PRINT_VERBOSE(format("Voxel: HW threads hint: {}", hw_threads_hint));
@ -65,7 +65,7 @@ VoxelServer::VoxelServer(ThreadsConfig threads_config) {
ZN_PRINT_VERBOSE(format("Size of MeshBlockTask: {}", sizeof(MeshBlockTask)));
}
VoxelServer::~VoxelServer() {
VoxelEngine::~VoxelEngine() {
// The GDScriptLanguage singleton can get destroyed before ours, so any script referenced by tasks
// cannot be freed. To work this around, tasks are cleared when the scene tree autoload is destroyed.
// So normally there should not be any task left to clear here,
@ -74,7 +74,7 @@ VoxelServer::~VoxelServer() {
wait_and_clear_all_tasks(true);
}
void VoxelServer::wait_and_clear_all_tasks(bool warn) {
void VoxelEngine::wait_and_clear_all_tasks(bool warn) {
_general_thread_pool.wait_for_all_tasks();
_general_thread_pool.dequeue_completed_tasks([warn](zylann::IThreadedTask *task) {
@ -86,19 +86,19 @@ void VoxelServer::wait_and_clear_all_tasks(bool warn) {
});
}
uint32_t VoxelServer::add_volume(VolumeCallbacks callbacks) {
uint32_t VoxelEngine::add_volume(VolumeCallbacks callbacks) {
ZN_ASSERT(callbacks.check_callbacks());
Volume volume;
volume.callbacks = callbacks;
return _world.volumes.create(volume);
}
VoxelServer::VolumeCallbacks VoxelServer::get_volume_callbacks(uint32_t volume_id) const {
VoxelEngine::VolumeCallbacks VoxelEngine::get_volume_callbacks(uint32_t volume_id) const {
const Volume &volume = _world.volumes.get(volume_id);
return volume.callbacks;
}
void VoxelServer::remove_volume(uint32_t volume_id) {
void VoxelEngine::remove_volume(uint32_t volume_id) {
_world.volumes.destroy(volume_id);
// TODO How to cancel meshing tasks?
@ -109,120 +109,120 @@ void VoxelServer::remove_volume(uint32_t volume_id) {
}
}
bool VoxelServer::is_volume_valid(uint32_t volume_id) const {
bool VoxelEngine::is_volume_valid(uint32_t volume_id) const {
return _world.volumes.is_valid(volume_id);
}
uint32_t VoxelServer::add_viewer() {
uint32_t VoxelEngine::add_viewer() {
return _world.viewers.create(Viewer());
}
void VoxelServer::remove_viewer(uint32_t viewer_id) {
void VoxelEngine::remove_viewer(uint32_t viewer_id) {
_world.viewers.destroy(viewer_id);
}
void VoxelServer::set_viewer_position(uint32_t viewer_id, Vector3 position) {
void VoxelEngine::set_viewer_position(uint32_t viewer_id, Vector3 position) {
Viewer &viewer = _world.viewers.get(viewer_id);
viewer.world_position = position;
}
void VoxelServer::set_viewer_distance(uint32_t viewer_id, unsigned int distance) {
void VoxelEngine::set_viewer_distance(uint32_t viewer_id, unsigned int distance) {
Viewer &viewer = _world.viewers.get(viewer_id);
viewer.view_distance = distance;
}
unsigned int VoxelServer::get_viewer_distance(uint32_t viewer_id) const {
unsigned int VoxelEngine::get_viewer_distance(uint32_t viewer_id) const {
const Viewer &viewer = _world.viewers.get(viewer_id);
return viewer.view_distance;
}
void VoxelServer::set_viewer_requires_visuals(uint32_t viewer_id, bool enabled) {
void VoxelEngine::set_viewer_requires_visuals(uint32_t viewer_id, bool enabled) {
Viewer &viewer = _world.viewers.get(viewer_id);
viewer.require_visuals = enabled;
}
bool VoxelServer::is_viewer_requiring_visuals(uint32_t viewer_id) const {
bool VoxelEngine::is_viewer_requiring_visuals(uint32_t viewer_id) const {
const Viewer &viewer = _world.viewers.get(viewer_id);
return viewer.require_visuals;
}
void VoxelServer::set_viewer_requires_collisions(uint32_t viewer_id, bool enabled) {
void VoxelEngine::set_viewer_requires_collisions(uint32_t viewer_id, bool enabled) {
Viewer &viewer = _world.viewers.get(viewer_id);
viewer.require_collisions = enabled;
}
bool VoxelServer::is_viewer_requiring_collisions(uint32_t viewer_id) const {
bool VoxelEngine::is_viewer_requiring_collisions(uint32_t viewer_id) const {
const Viewer &viewer = _world.viewers.get(viewer_id);
return viewer.require_collisions;
}
void VoxelServer::set_viewer_requires_data_block_notifications(uint32_t viewer_id, bool enabled) {
void VoxelEngine::set_viewer_requires_data_block_notifications(uint32_t viewer_id, bool enabled) {
Viewer &viewer = _world.viewers.get(viewer_id);
viewer.requires_data_block_notifications = enabled;
}
bool VoxelServer::is_viewer_requiring_data_block_notifications(uint32_t viewer_id) const {
bool VoxelEngine::is_viewer_requiring_data_block_notifications(uint32_t viewer_id) const {
const Viewer &viewer = _world.viewers.get(viewer_id);
return viewer.requires_data_block_notifications;
}
void VoxelServer::set_viewer_network_peer_id(uint32_t viewer_id, int peer_id) {
void VoxelEngine::set_viewer_network_peer_id(uint32_t viewer_id, int peer_id) {
Viewer &viewer = _world.viewers.get(viewer_id);
viewer.network_peer_id = peer_id;
}
int VoxelServer::get_viewer_network_peer_id(uint32_t viewer_id) const {
int VoxelEngine::get_viewer_network_peer_id(uint32_t viewer_id) const {
const Viewer &viewer = _world.viewers.get(viewer_id);
return viewer.network_peer_id;
}
bool VoxelServer::viewer_exists(uint32_t viewer_id) const {
bool VoxelEngine::viewer_exists(uint32_t viewer_id) const {
return _world.viewers.is_valid(viewer_id);
}
void VoxelServer::push_main_thread_time_spread_task(
void VoxelEngine::push_main_thread_time_spread_task(
zylann::ITimeSpreadTask *task, TimeSpreadTaskRunner::Priority priority) {
_time_spread_task_runner.push(task, priority);
}
void VoxelServer::push_main_thread_progressive_task(zylann::IProgressiveTask *task) {
void VoxelEngine::push_main_thread_progressive_task(zylann::IProgressiveTask *task) {
_progressive_task_runner.push(task);
}
int VoxelServer::get_main_thread_time_budget_usec() const {
int VoxelEngine::get_main_thread_time_budget_usec() const {
return _main_thread_time_budget_usec;
}
void VoxelServer::set_main_thread_time_budget_usec(unsigned int usec) {
void VoxelEngine::set_main_thread_time_budget_usec(unsigned int usec) {
_main_thread_time_budget_usec = usec;
}
void VoxelServer::set_threaded_mesh_resource_building_enabled(bool enable) {
void VoxelEngine::set_threaded_mesh_resource_building_enabled(bool enable) {
_threaded_mesh_resource_building_enabled = enable;
}
bool VoxelServer::is_threaded_mesh_resource_building_enabled() const {
bool VoxelEngine::is_threaded_mesh_resource_building_enabled() const {
return _threaded_mesh_resource_building_enabled;
}
void VoxelServer::push_async_task(zylann::IThreadedTask *task) {
void VoxelEngine::push_async_task(zylann::IThreadedTask *task) {
_general_thread_pool.enqueue(task, false);
}
void VoxelServer::push_async_tasks(Span<zylann::IThreadedTask *> tasks) {
void VoxelEngine::push_async_tasks(Span<zylann::IThreadedTask *> tasks) {
_general_thread_pool.enqueue(tasks, false);
}
void VoxelServer::push_async_io_task(zylann::IThreadedTask *task) {
void VoxelEngine::push_async_io_task(zylann::IThreadedTask *task) {
// I/O tasks run in serial because they usually can't run well in parallel due to locking shared resources.
_general_thread_pool.enqueue(task, true);
}
void VoxelServer::push_async_io_tasks(Span<zylann::IThreadedTask *> tasks) {
void VoxelEngine::push_async_io_tasks(Span<zylann::IThreadedTask *> tasks) {
_general_thread_pool.enqueue(tasks, true);
}
void VoxelServer::process() {
void VoxelEngine::process() {
ZN_PROFILE_SCOPE();
ZN_PROFILE_PLOT("Static memory usage", int64_t(OS::get_singleton()->get_static_memory_usage()));
ZN_PROFILE_PLOT("TimeSpread tasks", int64_t(_time_spread_task_runner.get_pending_count()));
@ -275,15 +275,15 @@ static unsigned int debug_get_active_thread_count(const zylann::ThreadedTaskRunn
return active_count;
}
static VoxelServer::Stats::ThreadPoolStats debug_get_pool_stats(const zylann::ThreadedTaskRunner &pool) {
VoxelServer::Stats::ThreadPoolStats d;
static VoxelEngine::Stats::ThreadPoolStats debug_get_pool_stats(const zylann::ThreadedTaskRunner &pool) {
VoxelEngine::Stats::ThreadPoolStats d;
d.tasks = pool.get_debug_remaining_tasks();
d.active_threads = debug_get_active_thread_count(pool);
d.thread_count = pool.get_thread_count();
return d;
}
VoxelServer::Stats VoxelServer::get_stats() const {
VoxelEngine::Stats VoxelEngine::get_stats() const {
Stats s;
s.general = debug_get_pool_stats(_general_thread_pool);
s.generation_tasks = GenerateBlockTask::debug_get_running_count();

View File

@ -1,5 +1,5 @@
#ifndef VOXEL_SERVER_H
#define VOXEL_SERVER_H
#ifndef VOXEL_ENGINE_H
#define VOXEL_ENGINE_H
#include "../meshers/voxel_mesher.h"
#include "../streams/instance_data.h"
@ -14,7 +14,9 @@
namespace zylann::voxel {
// Singleton for common things, notably the task system and shared viewers list.
class VoxelServer {
// In Godot terminology this used to be called a "server", but I dont really agree with the term here, and it can be
// confused with networking features.
class VoxelEngine {
public:
struct BlockMeshOutput {
enum Type {
@ -94,7 +96,7 @@ public:
float thread_count_ratio_over_max = 0.5;
};
static VoxelServer &get_singleton();
static VoxelEngine &get_singleton();
static void create_singleton(ThreadsConfig threads_config);
static void destroy_singleton();
@ -181,10 +183,10 @@ public:
Stats get_stats() const;
// TODO Should be private, but can't because `memdelete<T>` would be unable to call it otherwise...
~VoxelServer();
~VoxelEngine();
private:
VoxelServer(ThreadsConfig threads_config);
VoxelEngine(ThreadsConfig threads_config);
// Since we are going to send data to tasks running in multiple threads, a few strategies are in place:
//
@ -226,11 +228,11 @@ private:
struct VoxelFileLockerRead {
VoxelFileLockerRead(const std::string &path) : _path(path) {
VoxelServer::get_singleton().get_file_locker().lock_read(path);
VoxelEngine::get_singleton().get_file_locker().lock_read(path);
}
~VoxelFileLockerRead() {
VoxelServer::get_singleton().get_file_locker().unlock(_path);
VoxelEngine::get_singleton().get_file_locker().unlock(_path);
}
std::string _path;
@ -238,11 +240,11 @@ struct VoxelFileLockerRead {
struct VoxelFileLockerWrite {
VoxelFileLockerWrite(const std::string &path) : _path(path) {
VoxelServer::get_singleton().get_file_locker().lock_write(path);
VoxelEngine::get_singleton().get_file_locker().lock_write(path);
}
~VoxelFileLockerWrite() {
VoxelServer::get_singleton().get_file_locker().unlock(_path);
VoxelEngine::get_singleton().get_file_locker().unlock(_path);
}
std::string _path;
@ -262,8 +264,8 @@ public:
}
inline void flush() {
VoxelServer::get_singleton().push_async_tasks(to_span(_main_tasks));
VoxelServer::get_singleton().push_async_io_tasks(to_span(_io_tasks));
VoxelEngine::get_singleton().push_async_tasks(to_span(_main_tasks));
VoxelEngine::get_singleton().push_async_io_tasks(to_span(_io_tasks));
_main_tasks.clear();
_io_tasks.clear();
}
@ -277,4 +279,4 @@ private:
} // namespace zylann::voxel
#endif // VOXEL_SERVER_H
#endif // VOXEL_ENGINE_H

View File

@ -1,38 +1,38 @@
#include "voxel_server_gd.h"
#include "voxel_engine_gd.h"
#include "../storage/voxel_memory_pool.h"
#include "../util/macros.h"
#include "../util/profiling.h"
#include "../util/tasks/godot/threaded_task_gd.h"
#include "voxel_server.h"
#include "voxel_engine.h"
namespace zylann::voxel::gd {
VoxelServer *g_voxel_server = nullptr;
VoxelEngine *g_voxel_engine = nullptr;
VoxelServer *VoxelServer::get_singleton() {
CRASH_COND_MSG(g_voxel_server == nullptr, "Accessing singleton while it's null");
return g_voxel_server;
VoxelEngine *VoxelEngine::get_singleton() {
CRASH_COND_MSG(g_voxel_engine == nullptr, "Accessing singleton while it's null");
return g_voxel_engine;
}
void VoxelServer::create_singleton() {
CRASH_COND_MSG(g_voxel_server != nullptr, "Creating singleton twice");
g_voxel_server = memnew(VoxelServer);
void VoxelEngine::create_singleton() {
CRASH_COND_MSG(g_voxel_engine != nullptr, "Creating singleton twice");
g_voxel_engine = memnew(VoxelEngine);
}
void VoxelServer::destroy_singleton() {
CRASH_COND_MSG(g_voxel_server == nullptr, "Destroying singleton twice");
memdelete(g_voxel_server);
g_voxel_server = nullptr;
void VoxelEngine::destroy_singleton() {
CRASH_COND_MSG(g_voxel_engine == nullptr, "Destroying singleton twice");
memdelete(g_voxel_engine);
g_voxel_engine = nullptr;
}
VoxelServer::VoxelServer() {
VoxelEngine::VoxelEngine() {
#ifdef ZN_PROFILER_ENABLED
CRASH_COND(RenderingServer::get_singleton() == nullptr);
RenderingServer::get_singleton()->connect(
SNAME("frame_post_draw"), callable_mp(this, &VoxelServer::_on_rendering_server_frame_post_draw));
SNAME("frame_post_draw"), callable_mp(this, &VoxelEngine::_on_rendering_server_frame_post_draw));
#endif
}
Dictionary to_dict(const zylann::voxel::VoxelServer::Stats::ThreadPoolStats &stats) {
Dictionary to_dict(const zylann::voxel::VoxelEngine::Stats::ThreadPoolStats &stats) {
Dictionary d;
d["tasks"] = stats.tasks;
d["active_threads"] = stats.active_threads;
@ -40,7 +40,7 @@ Dictionary to_dict(const zylann::voxel::VoxelServer::Stats::ThreadPoolStats &sta
return d;
}
Dictionary to_dict(const zylann::voxel::VoxelServer::Stats &stats) {
Dictionary to_dict(const zylann::voxel::VoxelEngine::Stats &stats) {
Dictionary pools;
pools["general"] = to_dict(stats.general);
@ -63,17 +63,17 @@ Dictionary to_dict(const zylann::voxel::VoxelServer::Stats &stats) {
return d;
}
Dictionary VoxelServer::get_stats() const {
return to_dict(zylann::voxel::VoxelServer::get_singleton().get_stats());
Dictionary VoxelEngine::get_stats() const {
return to_dict(zylann::voxel::VoxelEngine::get_singleton().get_stats());
}
void VoxelServer::schedule_task(Ref<ZN_ThreadedTask> task) {
void VoxelEngine::schedule_task(Ref<ZN_ThreadedTask> task) {
ERR_FAIL_COND(task.is_null());
ERR_FAIL_COND_MSG(task->is_scheduled(), "Cannot schedule again a task that is already scheduled");
zylann::voxel::VoxelServer::get_singleton().push_async_task(task->create_task());
zylann::voxel::VoxelEngine::get_singleton().push_async_task(task->create_task());
}
void VoxelServer::_on_rendering_server_frame_post_draw() {
void VoxelEngine::_on_rendering_server_frame_post_draw() {
#ifdef ZN_PROFILER_ENABLED
ZN_PROFILE_MARK_FRAME();
#endif
@ -81,23 +81,23 @@ void VoxelServer::_on_rendering_server_frame_post_draw() {
#ifdef TOOLS_ENABLED
void VoxelServer::set_editor_camera_info(Vector3 position, Vector3 direction) {
void VoxelEngine::set_editor_camera_info(Vector3 position, Vector3 direction) {
_editor_camera_position = position;
_editor_camera_direction = direction;
}
Vector3 VoxelServer::get_editor_camera_position() const {
Vector3 VoxelEngine::get_editor_camera_position() const {
return _editor_camera_position;
}
Vector3 VoxelServer::get_editor_camera_direction() const {
Vector3 VoxelEngine::get_editor_camera_direction() const {
return _editor_camera_direction;
}
#endif
void VoxelServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stats"), &VoxelServer::get_stats);
void VoxelEngine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stats"), &VoxelEngine::get_stats);
}
} // namespace zylann::voxel::gd

View File

@ -1,5 +1,5 @@
#ifndef VOXEL_SERVER_GD_H
#define VOXEL_SERVER_GD_H
#ifndef VOXEL_ENGINE_GD_H
#define VOXEL_ENGINE_GD_H
#include "core/object/class_db.h"
#include <core/object/object.h>
@ -12,14 +12,14 @@ namespace zylann::voxel::gd {
// Godot-facing singleton class.
// the real class is internal and does not need anything from Object.
class VoxelServer : public Object {
GDCLASS(VoxelServer, Object)
class VoxelEngine : public Object {
GDCLASS(VoxelEngine, Object)
public:
static VoxelServer *get_singleton();
static VoxelEngine *get_singleton();
static void create_singleton();
static void destroy_singleton();
VoxelServer();
VoxelEngine();
Dictionary get_stats() const;
void schedule_task(Ref<ZN_ThreadedTask> task);
@ -43,4 +43,4 @@ private:
} // namespace zylann::voxel::gd
#endif // VOXEL_SERVER_GD_H
#endif // VOXEL_ENGINE_GD_H

View File

@ -1,6 +1,6 @@
#include "voxel_server_updater.h"
#include "voxel_engine_updater.h"
#include "../util/log.h"
#include "voxel_server.h"
#include "voxel_engine.h"
// Needed for doing `Node *root = SceneTree::get_root()`, Window* is forward-declared
#include <scene/main/window.h>
@ -9,17 +9,17 @@ namespace zylann::voxel {
bool g_updater_created = false;
VoxelServerUpdater::VoxelServerUpdater() {
ZN_PRINT_VERBOSE("Creating VoxelServerUpdater");
VoxelEngineUpdater::VoxelEngineUpdater() {
ZN_PRINT_VERBOSE("Creating VoxelEngineUpdater");
set_process(true);
g_updater_created = true;
}
VoxelServerUpdater::~VoxelServerUpdater() {
VoxelEngineUpdater::~VoxelEngineUpdater() {
g_updater_created = false;
}
void VoxelServerUpdater::ensure_existence(SceneTree *st) {
void VoxelEngineUpdater::ensure_existence(SceneTree *st) {
if (st == nullptr) {
return;
}
@ -28,27 +28,27 @@ void VoxelServerUpdater::ensure_existence(SceneTree *st) {
}
Node *root = st->get_root();
for (int i = 0; i < root->get_child_count(); ++i) {
VoxelServerUpdater *u = Object::cast_to<VoxelServerUpdater>(root->get_child(i));
VoxelEngineUpdater *u = Object::cast_to<VoxelEngineUpdater>(root->get_child(i));
if (u != nullptr) {
return;
}
}
VoxelServerUpdater *u = memnew(VoxelServerUpdater);
u->set_name("VoxelServerUpdater_dont_touch_this");
VoxelEngineUpdater *u = memnew(VoxelEngineUpdater);
u->set_name("VoxelEngineUpdater_dont_touch_this");
// TODO This can fail (for example if `Node::data.blocked > 0` while in `_ready()`) but Godot offers no API to check
// anything. So if this fail, the node will leak.
root->add_child(u);
}
void VoxelServerUpdater::_notification(int p_what) {
void VoxelEngineUpdater::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_PROCESS:
// To workaround the absence of API to have a custom server processing in the main loop
zylann::voxel::VoxelServer::get_singleton().process();
zylann::voxel::VoxelEngine::get_singleton().process();
break;
case NOTIFICATION_PREDELETE:
ZN_PRINT_VERBOSE("Deleting VoxelServerUpdater");
ZN_PRINT_VERBOSE("Deleting VoxelEngineUpdater");
break;
default:

View File

@ -5,18 +5,18 @@
namespace zylann::voxel {
// TODO Hack to make VoxelServer update... need ways to integrate callbacks from main loop!
class VoxelServerUpdater : public Node {
GDCLASS(VoxelServerUpdater, Node)
// TODO Hack to make VoxelEngine update... need ways to integrate callbacks from main loop!
class VoxelEngineUpdater : public Node {
GDCLASS(VoxelEngineUpdater, Node)
public:
~VoxelServerUpdater();
~VoxelEngineUpdater();
static void ensure_existence(SceneTree *st);
protected:
void _notification(int p_what);
private:
VoxelServerUpdater();
VoxelEngineUpdater();
};
} // namespace zylann::voxel

7
gource_view.sh Normal file
View File

@ -0,0 +1,7 @@
# You need Gource to run this command.
# Get it here : https://gource.io/
# -s : seconds per day
# Displays an animation of a versionned project over time.
gource -s 0.2 -i 0 --hide filenames --max-user-speed 1000 --auto-skip-seconds 1

View File

@ -5,6 +5,7 @@
#include "edition/voxel_tool_buffer.h"
#include "edition/voxel_tool_lod_terrain.h"
#include "edition/voxel_tool_terrain.h"
#include "engine/voxel_engine_gd.h"
#include "generators/graph/voxel_generator_graph.h"
#include "generators/graph/voxel_graph_node_db.h"
#include "generators/simple/voxel_generator_flat.h"
@ -19,7 +20,6 @@
#include "meshers/cubes/voxel_mesher_cubes.h"
#include "meshers/dmc/voxel_mesher_dmc.h"
#include "meshers/transvoxel/voxel_mesher_transvoxel.h"
#include "server/voxel_server_gd.h"
#include "storage/modifiers_gd.h"
#include "storage/voxel_buffer_gd.h"
#include "storage/voxel_memory_pool.h"
@ -72,10 +72,10 @@
namespace zylann::voxel {
static VoxelServer::ThreadsConfig get_config_from_godot(unsigned int &out_main_thread_time_budget_usec) {
static VoxelEngine::ThreadsConfig get_config_from_godot(unsigned int &out_main_thread_time_budget_usec) {
CRASH_COND(ProjectSettings::get_singleton() == nullptr);
VoxelServer::ThreadsConfig config;
VoxelEngine::ThreadsConfig config;
// Compute thread count for general pool.
// Note that the I/O thread counts as one used thread and will always be present.
@ -126,19 +126,19 @@ void initialize_voxel_module(ModuleInitializationLevel p_level) {
VoxelGraphNodeDB::create_singleton();
unsigned int main_thread_budget_usec;
const VoxelServer::ThreadsConfig threads_config = get_config_from_godot(main_thread_budget_usec);
VoxelServer::create_singleton(threads_config);
VoxelServer::get_singleton().set_main_thread_time_budget_usec(main_thread_budget_usec);
const VoxelEngine::ThreadsConfig threads_config = get_config_from_godot(main_thread_budget_usec);
VoxelEngine::create_singleton(threads_config);
VoxelEngine::get_singleton().set_main_thread_time_budget_usec(main_thread_budget_usec);
// TODO Pick this from the current renderer + user option (at time of writing, Godot 4 has only one renderer and
// has not figured out how such option would be exposed).
// Could use `can_create_resources_async` but this is internal.
// AFAIK `is_low_end` will be `true` only for OpenGL backends, which are the only ones not supporting async
// resource creation.
VoxelServer::get_singleton().set_threaded_mesh_resource_building_enabled(
VoxelEngine::get_singleton().set_threaded_mesh_resource_building_enabled(
RenderingServer::get_singleton()->is_low_end() == false);
gd::VoxelServer::create_singleton();
Engine::get_singleton()->add_singleton(Engine::Singleton("VoxelServer", gd::VoxelServer::get_singleton()));
gd::VoxelEngine::create_singleton();
Engine::get_singleton()->add_singleton(Engine::Singleton("VoxelEngine", gd::VoxelEngine::get_singleton()));
VoxelMetadataFactory::get_singleton().add_constructor_by_type<gd::VoxelMetadataVariant>(
gd::METADATA_TYPE_VARIANT);
@ -147,7 +147,7 @@ void initialize_voxel_module(ModuleInitializationLevel p_level) {
// TODO Can I prevent users from instancing it? is "register_virtual_class" correct for a class that's not
// abstract?
ClassDB::register_class<gd::VoxelServer>();
ClassDB::register_class<gd::VoxelEngine>();
// Misc
ClassDB::register_class<VoxelBlockyModel>();
@ -271,17 +271,17 @@ void uninitialize_voxel_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
// At this point, the GDScript module has nullified GDScriptLanguage::singleton!!
// That means it's impossible to free scripts still referenced by VoxelServer. And that can happen, because
// That means it's impossible to free scripts still referenced by VoxelEngine. And that can happen, because
// users can write custom generators, which run inside threads, and these threads are hosted in the server...
// See https://github.com/Zylann/godot_voxel/issues/189
VoxelMesherTransvoxel::free_static_resources();
VoxelStringNames::destroy_singleton();
VoxelGraphNodeDB::destroy_singleton();
gd::VoxelServer::destroy_singleton();
VoxelServer::destroy_singleton();
gd::VoxelEngine::destroy_singleton();
VoxelEngine::destroy_singleton();
// Do this last as VoxelServer might still be holding some refs to voxel blocks
// Do this last as VoxelEngine might still be holding some refs to voxel blocks
VoxelMemoryPool::destroy_singleton();
// TODO No remove?
}

View File

@ -1,5 +1,5 @@
#include "file_utils.h"
#include "../server/voxel_server.h"
#include "../engine/voxel_engine.h"
#include <core/io/dir_access.h>
namespace zylann {

View File

@ -1,5 +1,5 @@
#include "voxel_stream_region_files.h"
#include "../../server/voxel_server.h"
#include "../../engine/voxel_engine.h"
#include "../../util/godot/funcs.h"
#include "../../util/log.h"
#include "../../util/math/box3i.h"

View File

@ -1,5 +1,5 @@
#include "voxel_stream_block_files.h"
#include "../server/voxel_server.h"
#include "../engine/voxel_engine.h"
#include "voxel_block_serializer.h"
#include <core/io/dir_access.h>

View File

@ -2,13 +2,13 @@
#include "../../constants/voxel_constants.h"
#include "../../constants/voxel_string_names.h"
#include "../../edition/voxel_tool_terrain.h"
#include "../../engine/generate_block_task.h"
#include "../../engine/load_block_data_task.h"
#include "../../engine/mesh_block_task.h"
#include "../../engine/save_block_data_task.h"
#include "../../engine/voxel_engine.h"
#include "../../engine/voxel_engine_updater.h"
#include "../../meshers/blocky/voxel_mesher_blocky.h"
#include "../../server/generate_block_task.h"
#include "../../server/load_block_data_task.h"
#include "../../server/mesh_block_task.h"
#include "../../server/save_block_data_task.h"
#include "../../server/voxel_server.h"
#include "../../server/voxel_server_updater.h"
#include "../../storage/voxel_buffer_gd.h"
#include "../../util/container_funcs.h"
#include "../../util/macros.h"
@ -42,7 +42,7 @@ VoxelTerrain::VoxelTerrain() {
struct ApplyMeshUpdateTask : public ITimeSpreadTask {
void run(TimeSpreadTaskContext &ctx) override {
if (!VoxelServer::get_singleton().is_volume_valid(volume_id)) {
if (!VoxelEngine::get_singleton().is_volume_valid(volume_id)) {
// The node can have been destroyed while this task was still pending
ZN_PRINT_VERBOSE("Cancelling ApplyMeshUpdateTask, volume_id is invalid");
return;
@ -51,28 +51,28 @@ VoxelTerrain::VoxelTerrain() {
}
uint32_t volume_id = 0;
VoxelTerrain *self = nullptr;
VoxelServer::BlockMeshOutput data;
VoxelEngine::BlockMeshOutput data;
};
// Mesh updates are spread over frames by scheduling them in a task runner of VoxelServer,
// Mesh updates are spread over frames by scheduling them in a task runner of VoxelEngine,
// but instead of using a reception buffer we use a callback,
// because this kind of task scheduling would otherwise delay the update by 1 frame
VoxelServer::VolumeCallbacks callbacks;
VoxelEngine::VolumeCallbacks callbacks;
callbacks.data = this;
callbacks.mesh_output_callback = [](void *cb_data, VoxelServer::BlockMeshOutput &ob) {
callbacks.mesh_output_callback = [](void *cb_data, VoxelEngine::BlockMeshOutput &ob) {
VoxelTerrain *self = reinterpret_cast<VoxelTerrain *>(cb_data);
ApplyMeshUpdateTask *task = memnew(ApplyMeshUpdateTask);
task->volume_id = self->_volume_id;
task->self = self;
task->data = std::move(ob);
VoxelServer::get_singleton().push_main_thread_time_spread_task(task);
VoxelEngine::get_singleton().push_main_thread_time_spread_task(task);
};
callbacks.data_output_callback = [](void *cb_data, VoxelServer::BlockDataOutput &ob) {
callbacks.data_output_callback = [](void *cb_data, VoxelEngine::BlockDataOutput &ob) {
VoxelTerrain *self = reinterpret_cast<VoxelTerrain *>(cb_data);
self->apply_data_block_response(ob);
};
_volume_id = VoxelServer::get_singleton().add_volume(callbacks);
_volume_id = VoxelEngine::get_singleton().add_volume(callbacks);
// TODO Can't setup a default mesher anymore due to a Godot 4 warning...
// For ease of use in editor
@ -85,7 +85,7 @@ VoxelTerrain::~VoxelTerrain() {
ZN_PRINT_VERBOSE("Destroying VoxelTerrain");
_streaming_dependency->valid = false;
_meshing_dependency->valid = false;
VoxelServer::get_singleton().remove_volume(_volume_id);
VoxelEngine::get_singleton().remove_volume(_volume_id);
}
void VoxelTerrain::set_material_override(Ref<Material> material) {
@ -233,7 +233,7 @@ void VoxelTerrain::set_mesh_block_size(unsigned int mesh_block_size) {
viewer.prev_state.mesh_box = Box3i();
}
// VoxelServer::get_singleton().set_volume_render_block_size(_volume_id, mesh_block_size);
// VoxelEngine::get_singleton().set_volume_render_block_size(_volume_id, mesh_block_size);
// No update on bounds because we can support a mismatch, as long as it is a multiple of data block size
//set_bounds(_bounds_in_voxels);
@ -252,8 +252,8 @@ void VoxelTerrain::_on_stream_params_changed() {
_set_block_size_po2(stream_block_size_po2);
}
// VoxelServer::get_singleton().set_volume_data_block_size(_volume_id, 1 << get_data_block_size_pow2());
// VoxelServer::get_singleton().set_volume_render_block_size(_volume_id, 1 << get_mesh_block_size_pow2());
// VoxelEngine::get_singleton().set_volume_data_block_size(_volume_id, 1 << get_data_block_size_pow2());
// VoxelEngine::get_singleton().set_volume_render_block_size(_volume_id, 1 << get_mesh_block_size_pow2());
// The whole map might change, so regenerate it
reset_map();
@ -706,14 +706,14 @@ void VoxelTerrain::start_updater() {
}
}
// VoxelServer::get_singleton().set_volume_mesher(_volume_id, _mesher);
// VoxelEngine::get_singleton().set_volume_mesher(_volume_id, _mesher);
}
void VoxelTerrain::stop_updater() {
// Invalidate pending tasks
MeshingDependency::reset(_meshing_dependency, _mesher, _generator);
// VoxelServer::get_singleton().set_volume_mesher(_volume_id, Ref<VoxelMesher>());
// VoxelEngine::get_singleton().set_volume_mesher(_volume_id, Ref<VoxelMesher>());
// TODO We can still receive a few mesh delayed mesh updates after this. Is it a problem?
//_reception_buffers.mesh_output.clear();
@ -768,15 +768,15 @@ void VoxelTerrain::generate_block_async(Vector3i block_position) {
}
void VoxelTerrain::start_streamer() {
// VoxelServer::get_singleton().set_volume_stream(_volume_id, _stream);
// VoxelServer::get_singleton().set_volume_generator(_volume_id, _generator);
// VoxelEngine::get_singleton().set_volume_stream(_volume_id, _stream);
// VoxelEngine::get_singleton().set_volume_generator(_volume_id, _generator);
}
void VoxelTerrain::stop_streamer() {
// Invalidate pending tasks
StreamingDependency::reset(_streaming_dependency, _stream, _generator);
// VoxelServer::get_singleton().set_volume_stream(_volume_id, Ref<VoxelStream>());
// VoxelServer::get_singleton().set_volume_generator(_volume_id, Ref<VoxelGenerator>());
// VoxelEngine::get_singleton().set_volume_stream(_volume_id, Ref<VoxelStream>());
// VoxelEngine::get_singleton().set_volume_generator(_volume_id, Ref<VoxelGenerator>());
_loading_blocks.clear();
_blocks_pending_load.clear();
}
@ -868,7 +868,7 @@ void VoxelTerrain::_notification(int p_what) {
// Can't do that in enter tree because Godot is "still setting up children".
// Can't do that in ready either because Godot says node state is locked.
// This hack is quite miserable.
VoxelServerUpdater::ensure_existence(get_tree());
VoxelEngineUpdater::ensure_existence(get_tree());
_process();
break;
@ -890,7 +890,7 @@ void VoxelTerrain::_notification(int p_what) {
case NOTIFICATION_TRANSFORM_CHANGED: {
const Transform3D transform = get_global_transform();
// VoxelServer::get_singleton().set_volume_transform(_volume_id, transform);
// VoxelEngine::get_singleton().set_volume_transform(_volume_id, transform);
if (!is_inside_tree()) {
// The transform and other properties can be set by the scene loader,
@ -943,7 +943,7 @@ static void request_block_load(uint32_t volume_id, std::shared_ptr<StreamingDepe
LoadBlockDataTask *task = ZN_NEW(LoadBlockDataTask(volume_id, block_pos, 0, data_block_size, request_instances,
stream_dependency, priority_dependency, true));
VoxelServer::get_singleton().push_async_io_task(task);
VoxelEngine::get_singleton().push_async_io_task(task);
} else {
// Directly generate the block without checking the stream
@ -959,7 +959,7 @@ static void request_block_load(uint32_t volume_id, std::shared_ptr<StreamingDepe
init_sparse_grid_priority_dependency(
task->priority_dependency, block_pos, data_block_size, shared_viewers_data, volume_transform);
VoxelServer::get_singleton().push_async_task(task);
VoxelEngine::get_singleton().push_async_task(task);
}
}
@ -974,14 +974,14 @@ static void request_voxel_block_save(uint32_t volume_id, const std::shared_ptr<V
// No priority data, saving doesnt need sorting
VoxelServer::get_singleton().push_async_io_task(task);
VoxelEngine::get_singleton().push_async_io_task(task);
}
void VoxelTerrain::send_block_data_requests() {
ZN_PROFILE_SCOPE();
std::shared_ptr<PriorityDependency::ViewersData> shared_viewers_data =
VoxelServer::get_singleton().get_shared_viewers_data_from_default_world();
VoxelEngine::get_singleton().get_shared_viewers_data_from_default_world();
const Transform3D volume_transform = get_global_transform();
@ -1044,7 +1044,7 @@ bool VoxelTerrain::try_get_paired_viewer_index(uint32_t id, size_t &out_i) const
// TODO It is unclear yet if this API will stay. I have a feeling it might consume a lot of CPU
void VoxelTerrain::notify_data_block_enter(VoxelDataBlock &block, Vector3i bpos, uint32_t viewer_id) {
if (!VoxelServer::get_singleton().viewer_exists(viewer_id)) {
if (!VoxelEngine::get_singleton().viewer_exists(viewer_id)) {
// The viewer might have been removed between the moment we requested the block and the moment we finished
// loading it
return;
@ -1052,7 +1052,7 @@ void VoxelTerrain::notify_data_block_enter(VoxelDataBlock &block, Vector3i bpos,
if (_data_block_enter_info_obj == nullptr) {
_data_block_enter_info_obj = gd_make_unique<VoxelDataBlockEnterInfo>();
}
_data_block_enter_info_obj->network_peer_id = VoxelServer::get_singleton().get_viewer_network_peer_id(viewer_id);
_data_block_enter_info_obj->network_peer_id = VoxelEngine::get_singleton().get_viewer_network_peer_id(viewer_id);
_data_block_enter_info_obj->voxel_block = &block;
_data_block_enter_info_obj->block_position = bpos;
@ -1082,7 +1082,7 @@ void VoxelTerrain::process_viewers() {
// Destroyed viewers
for (size_t i = 0; i < _paired_viewers.size(); ++i) {
PairedViewer &p = _paired_viewers[i];
if (!VoxelServer::get_singleton().viewer_exists(p.id)) {
if (!VoxelEngine::get_singleton().viewer_exists(p.id)) {
ZN_PRINT_VERBOSE("Detected destroyed viewer in VoxelTerrain");
// Interpret removal as nullified view distance so the same code handling loading of blocks
// will be used to unload those viewed by this viewer.
@ -1109,7 +1109,7 @@ void VoxelTerrain::process_viewers() {
const Transform3D world_to_local_transform;
const float view_distance_scale;
inline void operator()(const VoxelServer::Viewer &viewer, uint32_t viewer_id) {
inline void operator()(const VoxelEngine::Viewer &viewer, uint32_t viewer_id) {
size_t paired_viewer_index;
if (!self.try_get_paired_viewer_index(viewer_id, paired_viewer_index)) {
PairedViewer p;
@ -1128,9 +1128,9 @@ void VoxelTerrain::process_viewers() {
state.view_distance_voxels = math::min(view_distance_voxels, self._max_view_distance_voxels);
state.local_position_voxels = math::floor_to_int(local_position);
state.requires_collisions = VoxelServer::get_singleton().is_viewer_requiring_collisions(viewer_id);
state.requires_collisions = VoxelEngine::get_singleton().is_viewer_requiring_collisions(viewer_id);
state.requires_meshes =
VoxelServer::get_singleton().is_viewer_requiring_visuals(viewer_id) && self._mesher.is_valid();
VoxelEngine::get_singleton().is_viewer_requiring_visuals(viewer_id) && self._mesher.is_valid();
// Update data and mesh view boxes
@ -1169,7 +1169,7 @@ void VoxelTerrain::process_viewers() {
// New viewers and updates
UpdatePairedViewer u{ *this, bounds_in_data_blocks, bounds_in_mesh_blocks, world_to_local_transform,
view_distance_scale };
VoxelServer::get_singleton().for_each_viewer(u);
VoxelEngine::get_singleton().for_each_viewer(u);
}
const bool can_load_blocks = (_automatic_loading_enabled && (_stream.is_valid() || _generator.is_valid())) &&
@ -1190,7 +1190,7 @@ void VoxelTerrain::process_viewers() {
ZN_PROFILE_SCOPE();
const bool require_notifications = _block_enter_notification_enabled &&
VoxelServer::get_singleton().is_viewer_requiring_data_block_notifications(viewer.id);
VoxelEngine::get_singleton().is_viewer_requiring_data_block_notifications(viewer.id);
// Unview blocks that just fell out of range
prev_data_box.difference(new_data_box, [this](Box3i out_of_range_box) {
@ -1289,20 +1289,20 @@ void VoxelTerrain::process_viewers() {
_stats.time_request_blocks_to_load = profiling_clock.restart();
}
void VoxelTerrain::apply_data_block_response(VoxelServer::BlockDataOutput &ob) {
void VoxelTerrain::apply_data_block_response(VoxelEngine::BlockDataOutput &ob) {
ZN_PROFILE_SCOPE();
//print_line(String("Receiving {0} blocks").format(varray(output.emerged_blocks.size())));
if (ob.type == VoxelServer::BlockDataOutput::TYPE_SAVED) {
if (ob.type == VoxelEngine::BlockDataOutput::TYPE_SAVED) {
if (ob.dropped) {
ERR_PRINT(String("Could not save block {0}").format(varray(ob.position)));
}
return;
}
CRASH_COND(ob.type != VoxelServer::BlockDataOutput::TYPE_LOADED &&
ob.type != VoxelServer::BlockDataOutput::TYPE_GENERATED);
CRASH_COND(ob.type != VoxelEngine::BlockDataOutput::TYPE_LOADED &&
ob.type != VoxelEngine::BlockDataOutput::TYPE_GENERATED);
const Vector3i block_pos = ob.position;
@ -1354,7 +1354,7 @@ void VoxelTerrain::apply_data_block_response(VoxelServer::BlockDataOutput &ob) {
block = _data_map.set_block_buffer(block_pos, ob.voxels, true);
CRASH_COND(block == nullptr);
block->set_edited(ob.type == VoxelServer::BlockDataOutput::TYPE_LOADED);
block->set_edited(ob.type == VoxelEngine::BlockDataOutput::TYPE_LOADED);
if (was_not_loaded) {
// Set viewers count that are currently expecting the block
@ -1445,7 +1445,7 @@ void VoxelTerrain::process_meshing() {
const Transform3D volume_transform = get_global_transform();
std::shared_ptr<PriorityDependency::ViewersData> shared_viewers_data =
VoxelServer::get_singleton().get_shared_viewers_data_from_default_world();
VoxelEngine::get_singleton().get_shared_viewers_data_from_default_world();
//const int used_channels_mask = get_used_channels_mask();
const int mesh_to_data_factor = get_mesh_block_size() / get_data_block_size();
@ -1482,7 +1482,7 @@ void VoxelTerrain::process_meshing() {
task->data_block_size = get_data_block_size();
task->collision_hint = _generate_collisions;
// This iteration order is specifically chosen to match VoxelServer and threaded access
// This iteration order is specifically chosen to match VoxelEngine and threaded access
task->blocks_count = 0;
data_box.for_each_cell_zxy([this, task](Vector3i data_block_pos) {
VoxelDataBlock *data_block = _data_map.get_block(data_block_pos);
@ -1512,7 +1512,7 @@ void VoxelTerrain::process_meshing() {
init_sparse_grid_priority_dependency(task->priority_dependency, task->position, get_mesh_block_size(),
shared_viewers_data, volume_transform);
VoxelServer::get_singleton().push_async_task(task);
VoxelEngine::get_singleton().push_async_task(task);
mesh_block->set_mesh_state(VoxelMeshBlockVT::MESH_UPDATE_SENT);
}
@ -1526,7 +1526,7 @@ void VoxelTerrain::process_meshing() {
//String::num(_block_update_queue.size()));
}
void VoxelTerrain::apply_mesh_update(const VoxelServer::BlockMeshOutput &ob) {
void VoxelTerrain::apply_mesh_update(const VoxelEngine::BlockMeshOutput &ob) {
ZN_PROFILE_SCOPE();
//print_line(String("DDD receive {0}").format(varray(ob.position.to_vec3())));
@ -1538,7 +1538,7 @@ void VoxelTerrain::apply_mesh_update(const VoxelServer::BlockMeshOutput &ob) {
return;
}
if (ob.type == VoxelServer::BlockMeshOutput::TYPE_DROPPED) {
if (ob.type == VoxelEngine::BlockMeshOutput::TYPE_DROPPED) {
// That block is loaded, but its meshing request was dropped.
// TODO Not sure what to do in this case, the code sending update queries has to be tweaked
ZN_PRINT_VERBOSE("Received a block mesh drop while we were still expecting it");
@ -1729,7 +1729,7 @@ PackedInt32Array VoxelTerrain::_b_get_viewer_network_peer_ids_in_area(Vector3i a
PackedInt32Array peer_ids;
peer_ids.resize(viewer_ids.size());
for (size_t i = 0; i < viewer_ids.size(); ++i) {
const int peer_id = VoxelServer::get_singleton().get_viewer_network_peer_id(viewer_ids[i]);
const int peer_id = VoxelEngine::get_singleton().get_viewer_network_peer_id(viewer_ids[i]);
peer_ids.write[i] = peer_id;
}

View File

@ -1,7 +1,7 @@
#ifndef VOXEL_TERRAIN_H
#define VOXEL_TERRAIN_H
#include "../../server/meshing_dependency.h"
#include "../../engine/meshing_dependency.h"
#include "../../storage/voxel_data_map.h"
#include "../../util/godot/funcs.h"
#include "../voxel_data_block_enter_info.h"
@ -151,8 +151,8 @@ private:
void process_viewers();
//void process_received_data_blocks();
void process_meshing();
void apply_mesh_update(const VoxelServer::BlockMeshOutput &ob);
void apply_data_block_response(VoxelServer::BlockDataOutput &ob);
void apply_mesh_update(const VoxelEngine::BlockMeshOutput &ob);
void apply_data_block_response(VoxelEngine::BlockDataOutput &ob);
void _on_stream_params_changed();
void _set_block_size_po2(int p_block_size_po2);

View File

@ -1,7 +1,7 @@
#ifndef VOXEL_FREE_MESH_TASK_H
#define VOXEL_FREE_MESH_TASK_H
#include "../server/voxel_server.h"
#include "../engine/voxel_engine.h"
#include "../util/godot/direct_mesh_instance.h"
#include "../util/tasks/progressive_task_runner.h"
@ -22,7 +22,7 @@ public:
static void add(Ref<Mesh> mesh) {
CRASH_COND(mesh.is_null());
FreeMeshTask *task = memnew(FreeMeshTask(mesh));
VoxelServer::get_singleton().push_main_thread_progressive_task(task);
VoxelEngine::get_singleton().push_main_thread_progressive_task(task);
}
FreeMeshTask(Ref<Mesh> p_mesh) : mesh(p_mesh) {}

View File

@ -1,5 +1,5 @@
#include "../../edition/voxel_tool.h"
#include "../../server/save_block_data_task.h"
#include "../../engine/save_block_data_task.h"
#include "../../util/container_funcs.h"
#include "../../util/godot/funcs.h"
#include "../../util/math/conv.h"
@ -1255,7 +1255,7 @@ void VoxelInstancer::save_block(Vector3i data_grid_pos, int lod_index) const {
volume_id, data_grid_pos, lod_index, data_block_size, std::move(data), stream_dependency));
// No priority data, saving doesnt need sorting
VoxelServer::get_singleton().push_async_io_task(task);
VoxelEngine::get_singleton().push_async_io_task(task);
}
void VoxelInstancer::remove_floating_multimesh_instances(Block &block, const Transform3D &parent_transform,

View File

@ -1,11 +1,11 @@
#include "voxel_lod_terrain.h"
#include "../../constants/voxel_string_names.h"
#include "../../edition/voxel_tool_lod_terrain.h"
#include "../../engine/load_all_blocks_data_task.h"
#include "../../engine/voxel_engine_gd.h"
#include "../../engine/voxel_engine_updater.h"
#include "../../meshers/blocky/voxel_mesher_blocky.h"
#include "../../meshers/transvoxel/voxel_mesher_transvoxel.h"
#include "../../server/load_all_blocks_data_task.h"
#include "../../server/voxel_server_gd.h"
#include "../../server/voxel_server_updater.h"
#include "../../storage/voxel_buffer_gd.h"
#include "../../util/container_funcs.h"
#include "../../util/godot/funcs.h"
@ -102,7 +102,7 @@ static inline uint64_t get_ticks_msec() {
} // namespace
void VoxelLodTerrain::ApplyMeshUpdateTask::run(TimeSpreadTaskContext &ctx) {
if (!VoxelServer::get_singleton().is_volume_valid(volume_id)) {
if (!VoxelEngine::get_singleton().is_volume_valid(volume_id)) {
// The node can have been destroyed while this task was still pending
ZN_PRINT_VERBOSE("Cancelling ApplyMeshUpdateTask, volume_id is invalid");
return;
@ -146,18 +146,18 @@ VoxelLodTerrain::VoxelLodTerrain() {
_update_data->settings.bounds_in_voxels =
Box3i::from_center_extents(Vector3i(), Vector3iUtil::create(constants::MAX_VOLUME_EXTENT));
// Mesh updates are spread over frames by scheduling them in a task runner of VoxelServer,
// Mesh updates are spread over frames by scheduling them in a task runner of VoxelEngine,
// but instead of using a reception buffer we use a callback,
// because this kind of task scheduling would otherwise delay the update by 1 frame
VoxelServer::VolumeCallbacks callbacks;
VoxelEngine::VolumeCallbacks callbacks;
callbacks.data = this;
callbacks.mesh_output_callback = [](void *cb_data, VoxelServer::BlockMeshOutput &ob) {
callbacks.mesh_output_callback = [](void *cb_data, VoxelEngine::BlockMeshOutput &ob) {
VoxelLodTerrain *self = reinterpret_cast<VoxelLodTerrain *>(cb_data);
ApplyMeshUpdateTask *task = memnew(ApplyMeshUpdateTask);
task->volume_id = self->get_volume_id();
task->self = self;
task->data = std::move(ob);
VoxelServer::get_singleton().push_main_thread_time_spread_task(task);
VoxelEngine::get_singleton().push_main_thread_time_spread_task(task);
// If two tasks are queued for the same mesh, cancel the old ones.
// This is for cases where creating the mesh is slower than the speed at which it is generated,
@ -169,13 +169,13 @@ VoxelLodTerrain::VoxelLodTerrain() {
p.first->second.add();
}
};
callbacks.data_output_callback = [](void *cb_data, VoxelServer::BlockDataOutput &ob) {
callbacks.data_output_callback = [](void *cb_data, VoxelEngine::BlockDataOutput &ob) {
VoxelLodTerrain *self = reinterpret_cast<VoxelLodTerrain *>(cb_data);
self->apply_data_block_response(ob);
};
_volume_id = VoxelServer::get_singleton().add_volume(callbacks);
// VoxelServer::get_singleton().set_volume_octree_lod_distance(_volume_id, get_lod_distance());
_volume_id = VoxelEngine::get_singleton().add_volume(callbacks);
// VoxelEngine::get_singleton().set_volume_octree_lod_distance(_volume_id, get_lod_distance());
// TODO Being able to set a LOD smaller than the stream is probably a bad idea,
// Because it prevents edits from propagating up to the last one, they will be left out of sync
@ -189,7 +189,7 @@ VoxelLodTerrain::~VoxelLodTerrain() {
abort_async_edits();
_streaming_dependency->valid = false;
_meshing_dependency->valid = false;
VoxelServer::get_singleton().remove_volume(_volume_id);
VoxelEngine::get_singleton().remove_volume(_volume_id);
// Instancer can take care of itself
}
@ -352,8 +352,8 @@ void VoxelLodTerrain::_on_stream_params_changed() {
}
}
// VoxelServer::get_singleton().set_volume_data_block_size(_volume_id, get_data_block_size());
// VoxelServer::get_singleton().set_volume_render_block_size(_volume_id, get_mesh_block_size());
// VoxelEngine::get_singleton().set_volume_data_block_size(_volume_id, get_data_block_size());
// VoxelEngine::get_singleton().set_volume_render_block_size(_volume_id, get_mesh_block_size());
reset_maps();
// TODO Size other than 16 is not really supported though.
@ -788,13 +788,13 @@ void VoxelLodTerrain::start_updater() {
}
}
// VoxelServer::get_singleton().set_volume_mesher(_volume_id, _mesher);
// VoxelEngine::get_singleton().set_volume_mesher(_volume_id, _mesher);
}
void VoxelLodTerrain::stop_updater() {
// Invalidate pending tasks
MeshingDependency::reset(_meshing_dependency, _mesher, _generator);
// VoxelServer::get_singleton().set_volume_mesher(_volume_id, Ref<VoxelMesher>());
// VoxelEngine::get_singleton().set_volume_mesher(_volume_id, Ref<VoxelMesher>());
// TODO We can still receive a few mesh delayed mesh updates after this. Is it a problem?
//_reception_buffers.mesh_output.clear();
@ -815,8 +815,8 @@ void VoxelLodTerrain::stop_updater() {
}
void VoxelLodTerrain::start_streamer() {
// VoxelServer::get_singleton().set_volume_stream(_volume_id, _stream);
// VoxelServer::get_singleton().set_volume_generator(_volume_id, _generator);
// VoxelEngine::get_singleton().set_volume_stream(_volume_id, _stream);
// VoxelEngine::get_singleton().set_volume_generator(_volume_id, _generator);
if (_update_data->settings.full_load_mode && _stream.is_valid()) {
// TODO May want to defer this to be sure it's not done multiple times.
@ -829,13 +829,13 @@ void VoxelLodTerrain::start_streamer() {
task->volume_id = _volume_id;
task->stream_dependency = _streaming_dependency;
VoxelServer::get_singleton().push_async_io_task(task);
VoxelEngine::get_singleton().push_async_io_task(task);
}
}
void VoxelLodTerrain::stop_streamer() {
// VoxelServer::get_singleton().set_volume_stream(_volume_id, Ref<VoxelStream>());
// VoxelServer::get_singleton().set_volume_generator(_volume_id, Ref<VoxelGenerator>());
// VoxelEngine::get_singleton().set_volume_stream(_volume_id, Ref<VoxelStream>());
// VoxelEngine::get_singleton().set_volume_generator(_volume_id, Ref<VoxelGenerator>());
_update_data->wait_for_end_of_task();
@ -860,7 +860,7 @@ void VoxelLodTerrain::set_lod_distance(float p_lod_distance) {
math::clamp(p_lod_distance, constants::MINIMUM_LOD_DISTANCE, constants::MAXIMUM_LOD_DISTANCE);
_update_data->settings.lod_distance = lod_distance;
_update_data->state.force_update_octrees_next_update = true;
// VoxelServer::get_singleton().set_volume_octree_lod_distance(_volume_id, get_lod_distance());
// VoxelEngine::get_singleton().set_volume_octree_lod_distance(_volume_id, get_lod_distance());
if (_instancer != nullptr) {
_instancer->set_mesh_lod_distance(lod_distance);
@ -1063,11 +1063,11 @@ float VoxelLodTerrain::get_collision_margin() const {
}
int VoxelLodTerrain::get_data_block_region_extent() const {
return VoxelServer::get_octree_lod_block_region_extent(_update_data->settings.lod_distance, get_data_block_size());
return VoxelEngine::get_octree_lod_block_region_extent(_update_data->settings.lod_distance, get_data_block_size());
}
int VoxelLodTerrain::get_mesh_block_region_extent() const {
return VoxelServer::get_octree_lod_block_region_extent(_update_data->settings.lod_distance, get_mesh_block_size());
return VoxelEngine::get_octree_lod_block_region_extent(_update_data->settings.lod_distance, get_mesh_block_size());
}
Vector3i VoxelLodTerrain::voxel_to_data_block_position(Vector3 vpos, int lod_index) const {
@ -1100,7 +1100,7 @@ void VoxelLodTerrain::_notification(int p_what) {
// Can't do that in enter tree because Godot is "still setting up children".
// Can't do that in ready either because Godot says node state is locked.
// This hack is quite miserable.
VoxelServerUpdater::ensure_existence(get_tree());
VoxelEngineUpdater::ensure_existence(get_tree());
_process(get_process_delta_time());
}
break;
@ -1111,7 +1111,7 @@ void VoxelLodTerrain::_notification(int p_what) {
// Can't do that in enter tree because Godot is "still setting up children".
// Can't do that in ready either because Godot says node state is locked.
// This hack is quite miserable.
VoxelServerUpdater::ensure_existence(get_tree());
VoxelEngineUpdater::ensure_existence(get_tree());
_process(get_physics_process_delta_time());
break;
}
@ -1172,7 +1172,7 @@ void VoxelLodTerrain::_notification(int p_what) {
ZN_PROFILE_SCOPE_NAMED("VoxelLodTerrain::NOTIFICATION_TRANSFORM_CHANGED");
const Transform3D transform = get_global_transform();
// VoxelServer::get_singleton().set_volume_transform(_volume_id, transform);
// VoxelEngine::get_singleton().set_volume_transform(_volume_id, transform);
if (!is_inside_tree()) {
// The transform and other properties can be set by the scene loader,
@ -1204,8 +1204,8 @@ Vector3 VoxelLodTerrain::get_local_viewer_pos() const {
Vector3 pos = _update_data->state.lods[0].last_viewer_data_block_pos << get_data_block_size_pow2();
// TODO Support for multiple viewers, this is a placeholder implementation
VoxelServer::get_singleton().for_each_viewer( //
[&pos](const VoxelServer::Viewer &viewer, uint32_t viewer_id) { //
VoxelEngine::get_singleton().for_each_viewer( //
[&pos](const VoxelEngine::Viewer &viewer, uint32_t viewer_id) { //
pos = viewer.world_position;
});
@ -1223,7 +1223,7 @@ inline bool check_block_sizes(int data_block_size, int mesh_block_size) {
// for (unsigned int i = 0; i < blocks_to_save.size(); ++i) {
// BlockToSave &b = blocks_to_save[i];
// ZN_PRINT_VERBOSE(String("Requesting save of block {0} lod {1}").format(varray(b.position, b.lod)));
// VoxelServer::get_singleton().request_voxel_block_save(_volume_id, b.voxels, b.position, b.lod);
// VoxelEngine::get_singleton().request_voxel_block_save(_volume_id, b.voxels, b.position, b.lod);
// }
// }
@ -1244,7 +1244,7 @@ void VoxelLodTerrain::_process(float delta) {
//process_block_loading_responses();
// TODO This could go into time spread tasks too
process_deferred_collision_updates(VoxelServer::get_singleton().get_main_thread_time_budget_usec());
process_deferred_collision_updates(VoxelEngine::get_singleton().get_main_thread_time_budget_usec());
#ifdef TOOLS_ENABLED
if (debug_is_draw_enabled() && is_visible_in_tree()) {
@ -1262,7 +1262,7 @@ void VoxelLodTerrain::_process(float delta) {
// TODO Optimization: pool tasks instead of allocating?
VoxelLodTerrainUpdateTask *task = memnew(VoxelLodTerrainUpdateTask(_data, _update_data, _streaming_dependency,
_meshing_dependency, VoxelServer::get_singleton().get_shared_viewers_data_from_default_world(),
_meshing_dependency, VoxelEngine::get_singleton().get_shared_viewers_data_from_default_world(),
viewer_pos, _instancer != nullptr, _volume_id, get_global_transform()));
_update_data->task_is_complete = false;
@ -1270,7 +1270,7 @@ void VoxelLodTerrain::_process(float delta) {
if (_threaded_update_enabled) {
// Schedule task at the end, so it is less likely to have contention with other logic than if it was done at
// the beginnning of `_process`
VoxelServer::get_singleton().push_async_task(task);
VoxelEngine::get_singleton().push_async_task(task);
} else {
task->run(ThreadedTaskContext{ 0 });
@ -1480,10 +1480,10 @@ bool thread_safe_contains(const std::unordered_set<T> &set, T v, BinaryMutex &mu
return it != set.end();
}
void VoxelLodTerrain::apply_data_block_response(VoxelServer::BlockDataOutput &ob) {
void VoxelLodTerrain::apply_data_block_response(VoxelEngine::BlockDataOutput &ob) {
ZN_PROFILE_SCOPE();
if (ob.type == VoxelServer::BlockDataOutput::TYPE_SAVED) {
if (ob.type == VoxelEngine::BlockDataOutput::TYPE_SAVED) {
// That's a save confirmation event.
// Note: in the future, if blocks don't get copied before being sent for saving,
// we will need to use block versionning to know when we can reset the `modified` flag properly
@ -1537,7 +1537,7 @@ void VoxelLodTerrain::apply_data_block_response(VoxelServer::BlockDataOutput &ob
RWLockWrite wlock(data_lod.map_lock);
VoxelDataBlock *block = data_lod.map.set_block_buffer(ob.position, ob.voxels, false);
CRASH_COND(block == nullptr);
block->set_edited(ob.type == VoxelServer::BlockDataOutput::TYPE_LOADED);
block->set_edited(ob.type == VoxelEngine::BlockDataOutput::TYPE_LOADED);
} else {
// Loading returned an empty block: that means we know the stream does not contain a block here.
@ -1560,7 +1560,7 @@ void VoxelLodTerrain::apply_data_block_response(VoxelServer::BlockDataOutput &ob
}
}
void VoxelLodTerrain::apply_mesh_update(VoxelServer::BlockMeshOutput &ob) {
void VoxelLodTerrain::apply_mesh_update(VoxelEngine::BlockMeshOutput &ob) {
// The following is done on the main thread because Godot doesn't really support everything done here.
// Building meshes can be done in the threaded task when using Vulkan, but not OpenGL.
// Setting up mesh instances might not be well threaded?
@ -1594,7 +1594,7 @@ void VoxelLodTerrain::apply_mesh_update(VoxelServer::BlockMeshOutput &ob) {
++_stats.dropped_block_meshs;
return;
}
if (ob.type == VoxelServer::BlockMeshOutput::TYPE_DROPPED) {
if (ob.type == VoxelEngine::BlockMeshOutput::TYPE_DROPPED) {
// That block is loaded, but its meshing request was dropped.
// TODO Not sure what to do in this case, the code sending update queries has to be tweaked
ZN_PRINT_VERBOSE("Received a block mesh drop while we were still expecting it");
@ -1882,8 +1882,8 @@ VoxelLodTerrain::LocalCameraInfo VoxelLodTerrain::get_local_camera_info() const
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
// Falling back on the editor's camera
info.position = gd::VoxelServer::get_singleton()->get_editor_camera_position();
info.forward = gd::VoxelServer::get_singleton()->get_editor_camera_direction();
info.position = gd::VoxelEngine::get_singleton()->get_editor_camera_position();
info.forward = gd::VoxelEngine::get_singleton()->get_editor_camera_direction();
return info;
}
#endif

View File

@ -1,8 +1,8 @@
#ifndef VOXEL_LOD_TERRAIN_HPP
#define VOXEL_LOD_TERRAIN_HPP
#include "../../server/mesh_block_task.h"
#include "../../server/voxel_server.h"
#include "../../engine/mesh_block_task.h"
#include "../../engine/voxel_engine.h"
#include "../../storage/voxel_data_map.h"
#include "../voxel_mesh_map.h"
#include "../voxel_node.h"
@ -263,8 +263,8 @@ private:
void _process(float delta);
void apply_main_thread_update_tasks();
void apply_mesh_update(VoxelServer::BlockMeshOutput &ob);
void apply_data_block_response(VoxelServer::BlockDataOutput &ob);
void apply_mesh_update(VoxelEngine::BlockMeshOutput &ob);
void apply_data_block_response(VoxelEngine::BlockDataOutput &ob);
void start_updater();
void stop_updater();
@ -377,7 +377,7 @@ private:
uint32_t volume_id = 0;
VoxelLodTerrain *self = nullptr;
VoxelServer::BlockMeshOutput data;
VoxelEngine::BlockMeshOutput data;
};
FixedArray<std::unordered_map<Vector3i, RefCount>, constants::MAX_LOD> _queued_main_thread_mesh_updates;

View File

@ -1,9 +1,9 @@
#include "voxel_lod_terrain_update_task.h"
#include "../../server/generate_block_task.h"
#include "../../server/load_block_data_task.h"
#include "../../server/mesh_block_task.h"
#include "../../server/save_block_data_task.h"
#include "../../server/voxel_server.h"
#include "../../engine/generate_block_task.h"
#include "../../engine/load_block_data_task.h"
#include "../../engine/mesh_block_task.h"
#include "../../engine/save_block_data_task.h"
#include "../../engine/voxel_engine.h"
#include "../../util/container_funcs.h"
#include "../../util/dstack.h"
#include "../../util/math/conv.h"
@ -223,7 +223,7 @@ static void process_unload_data_blocks_sliding_box(VoxelLodTerrainUpdateData::St
const int data_block_size = data.lods[0].map.get_block_size();
const int data_block_size_po2 = data.lods[0].map.get_block_size_pow2();
const int data_block_region_extent =
VoxelServer::get_octree_lod_block_region_extent(settings.lod_distance, data_block_size);
VoxelEngine::get_octree_lod_block_region_extent(settings.lod_distance, data_block_size);
const int mesh_block_size = 1 << settings.mesh_block_size_po2;
@ -312,7 +312,7 @@ static void process_unload_mesh_blocks_sliding_box(VoxelLodTerrainUpdateData::St
const int mesh_block_size_po2 = settings.mesh_block_size_po2;
const int mesh_block_size = 1 << mesh_block_size_po2;
const int mesh_block_region_extent =
VoxelServer::get_octree_lod_block_region_extent(settings.lod_distance, mesh_block_size);
VoxelEngine::get_octree_lod_block_region_extent(settings.lod_distance, mesh_block_size);
// Ignore largest lod because it can extend a little beyond due to the view distance setting.
// Instead, those blocks are unloaded by the octree forest management.
@ -1061,7 +1061,7 @@ static void init_sparse_octree_priority_dependency(PriorityDependency &dep, Vect
// This does not depend on viewer's view distance, but on LOD precision instead.
// TODO Should `data_block_size` be used here? Should it be mesh_block_size instead?
dep.drop_distance_squared = math::squared(2.f * transformed_block_radius *
VoxelServer::get_octree_lod_block_region_extent(octree_lod_distance, data_block_size));
VoxelEngine::get_octree_lod_block_region_extent(octree_lod_distance, data_block_size));
}
// This is only if we want to cache voxel data
@ -1212,7 +1212,7 @@ static void send_mesh_requests(uint32_t volume_id, VoxelLodTerrainUpdateData::St
ERR_CONTINUE(mesh_block.state != VoxelLodTerrainUpdateData::MESH_UPDATE_NOT_SENT);
// Get block and its neighbors
// VoxelServer::BlockMeshInput mesh_request;
// VoxelEngine::BlockMeshInput mesh_request;
// mesh_request.render_block_position = mesh_block_pos;
// mesh_request.lod = lod_index;
@ -1324,7 +1324,7 @@ static std::shared_ptr<AsyncDependencyTracker> preload_boxes_async(VoxelLodTerra
// This may first run the generation tasks, and then the edits
tracker = make_shared_instance<AsyncDependencyTracker>(
todo.size(), next_tasks, [](Span<IThreadedTask *> p_next_tasks) {
VoxelServer::get_singleton().push_async_tasks(p_next_tasks);
VoxelEngine::get_singleton().push_async_tasks(p_next_tasks);
});
for (unsigned int i = 0; i < todo.size(); ++i) {
@ -1336,7 +1336,7 @@ static std::shared_ptr<AsyncDependencyTracker> preload_boxes_async(VoxelLodTerra
} else if (next_tasks.size() > 0) {
// Nothing to preload, we may schedule `next_tasks` right now
VoxelServer::get_singleton().push_async_tasks(next_tasks);
VoxelEngine::get_singleton().push_async_tasks(next_tasks);
}
return tracker;

View File

@ -1,7 +1,7 @@
#ifndef VOXEL_LOD_TERRAIN_UPDATE_TASK_H
#define VOXEL_LOD_TERRAIN_UPDATE_TASK_H
#include "../../server/priority_dependency.h"
#include "../../engine/priority_dependency.h"
#include "../../util/tasks/threaded_task.h"
#include "voxel_lod_terrain_update_data.h"

View File

@ -1,7 +1,7 @@
#ifndef VOXEL_MESH_MAP_H
#define VOXEL_MESH_MAP_H
#include "../server/voxel_server.h"
#include "../engine/voxel_engine.h"
#include "../util/macros.h"
#include <unordered_map>
@ -185,7 +185,7 @@ private:
ERR_FAIL_COND(block == nullptr);
FreeMeshBlockTask *task = memnew(FreeMeshBlockTask);
task->block = block;
VoxelServer::get_singleton().push_main_thread_time_spread_task(task);
VoxelEngine::get_singleton().push_main_thread_time_spread_task(task);
}
private:

View File

@ -1,9 +1,9 @@
#ifndef VOXEL_NODE_H
#define VOXEL_NODE_H
#include "../engine/streaming_dependency.h"
#include "../generators/voxel_generator.h"
#include "../meshers/voxel_mesher.h"
#include "../server/streaming_dependency.h"
#include "../streams/voxel_stream.h"
#include <scene/3d/node_3d.h>

View File

@ -1,5 +1,5 @@
#include "voxel_viewer.h"
#include "../server/voxel_server.h"
#include "../engine/voxel_engine.h"
#include <core/config/engine.h>
namespace zylann::voxel {
@ -11,7 +11,7 @@ VoxelViewer::VoxelViewer() {
void VoxelViewer::set_view_distance(unsigned int distance) {
_view_distance = distance;
if (is_active()) {
VoxelServer::get_singleton().set_viewer_distance(_viewer_id, distance);
VoxelEngine::get_singleton().set_viewer_distance(_viewer_id, distance);
}
}
@ -22,7 +22,7 @@ unsigned int VoxelViewer::get_view_distance() const {
void VoxelViewer::set_requires_visuals(bool enabled) {
_requires_visuals = enabled;
if (is_active()) {
VoxelServer::get_singleton().set_viewer_requires_visuals(_viewer_id, enabled);
VoxelEngine::get_singleton().set_viewer_requires_visuals(_viewer_id, enabled);
}
}
@ -33,7 +33,7 @@ bool VoxelViewer::is_requiring_visuals() const {
void VoxelViewer::set_requires_collisions(bool enabled) {
_requires_collisions = enabled;
if (is_active()) {
VoxelServer::get_singleton().set_viewer_requires_collisions(_viewer_id, enabled);
VoxelEngine::get_singleton().set_viewer_requires_collisions(_viewer_id, enabled);
}
}
@ -44,7 +44,7 @@ bool VoxelViewer::is_requiring_collisions() const {
void VoxelViewer::set_requires_data_block_notifications(bool enabled) {
_requires_data_block_notifications = enabled;
if (is_active()) {
VoxelServer::get_singleton().set_viewer_requires_data_block_notifications(_viewer_id, enabled);
VoxelEngine::get_singleton().set_viewer_requires_data_block_notifications(_viewer_id, enabled);
}
}
@ -55,7 +55,7 @@ bool VoxelViewer::is_requiring_data_block_notifications() const {
void VoxelViewer::set_network_peer_id(int id) {
_network_peer_id = id;
if (is_active()) {
VoxelServer::get_singleton().set_viewer_network_peer_id(_viewer_id, id);
VoxelEngine::get_singleton().set_viewer_network_peer_id(_viewer_id, id);
}
}
@ -67,28 +67,28 @@ void VoxelViewer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (!Engine::get_singleton()->is_editor_hint()) {
_viewer_id = VoxelServer::get_singleton().add_viewer();
VoxelServer::get_singleton().set_viewer_distance(_viewer_id, _view_distance);
VoxelServer::get_singleton().set_viewer_requires_visuals(_viewer_id, _requires_visuals);
VoxelServer::get_singleton().set_viewer_requires_collisions(_viewer_id, _requires_collisions);
VoxelServer::get_singleton().set_viewer_requires_data_block_notifications(
_viewer_id = VoxelEngine::get_singleton().add_viewer();
VoxelEngine::get_singleton().set_viewer_distance(_viewer_id, _view_distance);
VoxelEngine::get_singleton().set_viewer_requires_visuals(_viewer_id, _requires_visuals);
VoxelEngine::get_singleton().set_viewer_requires_collisions(_viewer_id, _requires_collisions);
VoxelEngine::get_singleton().set_viewer_requires_data_block_notifications(
_viewer_id, _requires_data_block_notifications);
VoxelServer::get_singleton().set_viewer_network_peer_id(_viewer_id, _network_peer_id);
VoxelEngine::get_singleton().set_viewer_network_peer_id(_viewer_id, _network_peer_id);
const Vector3 pos = get_global_transform().origin;
VoxelServer::get_singleton().set_viewer_position(_viewer_id, pos);
VoxelEngine::get_singleton().set_viewer_position(_viewer_id, pos);
}
} break;
case NOTIFICATION_EXIT_TREE:
if (!Engine::get_singleton()->is_editor_hint()) {
VoxelServer::get_singleton().remove_viewer(_viewer_id);
VoxelEngine::get_singleton().remove_viewer(_viewer_id);
}
break;
case NOTIFICATION_TRANSFORM_CHANGED:
if (is_active()) {
const Vector3 pos = get_global_transform().origin;
VoxelServer::get_singleton().set_viewer_position(_viewer_id, pos);
VoxelEngine::get_singleton().set_viewer_position(_viewer_id, pos);
}
break;