Merge branch 'master' into full_load_mode
commit
375c68b0de
|
@ -56,6 +56,7 @@ Ongoing development - `master`
|
|||
- `VoxelTerrain`: fixed materials shown under the wrong inspector category
|
||||
- `VoxelStreamRegionFiles`: fixed errors caused by meta file being sometimes written with wrong depth values
|
||||
- `VoxelStreamBlockFiles`: fixed warning about channels always shown in the scene tree
|
||||
- `VoxelStreamSQLite`: fixed blocks above LOD0 being saved at wrong locations, causing them to be reloaded often floating in the air
|
||||
- Fix some crashes occurring when all PoolVector allocs are in use (Godot 3.x limitation). It will print errors instead, but crashes can still occur inside Godot's code as it's not often checking for this
|
||||
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 8.7 KiB |
|
@ -67,13 +67,11 @@ No test framework is used at the moment, instead they just run by either printin
|
|||
Threads
|
||||
---------
|
||||
|
||||
The module uses several background thread pools to process voxels. The number of threads is currently hardcoded, but it is planned to make it detect CPU concurrency automatically, and expose maximum thread counts in Project Settings.
|
||||
The module uses several background thread pools to process voxels. The number of threads can be adjusted in Project Settings.
|
||||
|
||||
![Schema of threads](images/threads_schema.png)
|
||||
|
||||
- A single streaming thread is handling files. If a block of voxels cannot be found, it can pass tasks to one of the generation threads.
|
||||
- One or more generation threads are used for procedural generation. They can pass tasks to the streaming thread if the option to save generated outputs is enabled.
|
||||
- One or more meshing threads are used to polygonize voxels into meshes.
|
||||
There are two pools of threads currently. One pool is actually just one thread dedicated to streaming (files I/O), and another pool uses more threads for every other type of task. This pool can be given many tasks and distributes them to all its threads. So the more threads are available, the quicker large amounts of tasks get done. Tasks are also sorted by priority, so for example updating a mesh near a player will run before generating a voxel block 300 meters away.
|
||||
|
||||
Threads are managed in [VoxelServer](api/VoxelServer.md).
|
||||
|
||||
|
@ -99,6 +97,7 @@ For the most part, use `clang-format` and follow Godot conventions.
|
|||
- Indent with tabs
|
||||
- Use Clang-format to automate most of these rules (the one included in Godot should do it)
|
||||
- Constructors and destructors go on top
|
||||
- Public API goes on top, private stuff goes below
|
||||
- Bindings go at the bottom. Private wrapper functions can be used to adapt to the script API and are prefixed with `_b_`.
|
||||
- Avoid long lines. Preferred ruler is 120 characters. Don't fit too many operations on the same line, use locals.
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ protected:
|
|||
// Output is blocky, so we can go for just one sample
|
||||
float h = params.range.xform(height_func(gx, gz));
|
||||
h -= origin.y;
|
||||
int ih = int(h);
|
||||
int ih = int(h) >> lod;
|
||||
if (ih > 0) {
|
||||
if (ih > bs.y) {
|
||||
ih = bs.y;
|
||||
|
|
|
@ -96,11 +96,12 @@ void VoxelMemoryPool::clear() {
|
|||
CRASH_COND(ptr == nullptr);
|
||||
memfree(ptr);
|
||||
}
|
||||
memdelete(pool);
|
||||
}
|
||||
_pools.clear();
|
||||
_used_memory = 0;
|
||||
_total_memory = 0;
|
||||
_used_blocks;
|
||||
_used_blocks = 0;
|
||||
}
|
||||
|
||||
void VoxelMemoryPool::debug_print() {
|
||||
|
|
|
@ -661,7 +661,7 @@ void VoxelStreamSQLite::emerge_blocks(Span<VoxelBlockRequest> p_blocks, Vector<R
|
|||
Vector<int> blocks_to_load;
|
||||
for (unsigned int i = 0; i < p_blocks.size(); ++i) {
|
||||
VoxelBlockRequest &wr = p_blocks[i];
|
||||
const Vector3i pos = wr.origin_in_voxels >> bs_po2;
|
||||
const Vector3i pos = wr.origin_in_voxels >> (bs_po2 + wr.lod);
|
||||
|
||||
Ref<VoxelBuffer> vb;
|
||||
if (_cache.load_voxel_block(pos, wr.lod, wr.voxel_buffer)) {
|
||||
|
@ -687,10 +687,12 @@ void VoxelStreamSQLite::emerge_blocks(Span<VoxelBlockRequest> p_blocks, Vector<R
|
|||
const int ri = blocks_to_load[i];
|
||||
const VoxelBlockRequest &r = p_blocks[ri];
|
||||
|
||||
const unsigned int po2 = bs_po2 + r.lod;
|
||||
|
||||
BlockLocation loc;
|
||||
loc.x = r.origin_in_voxels.x >> bs_po2;
|
||||
loc.y = r.origin_in_voxels.y >> bs_po2;
|
||||
loc.z = r.origin_in_voxels.z >> bs_po2;
|
||||
loc.x = r.origin_in_voxels.x >> po2;
|
||||
loc.y = r.origin_in_voxels.y >> po2;
|
||||
loc.z = r.origin_in_voxels.z >> po2;
|
||||
loc.lod = r.lod;
|
||||
|
||||
const Result res = con->load_block(loc, _temp_block_data, VoxelStreamSQLiteInternal::VOXELS);
|
||||
|
@ -716,7 +718,7 @@ void VoxelStreamSQLite::immerge_blocks(Span<VoxelBlockRequest> p_blocks) {
|
|||
// First put in cache
|
||||
for (unsigned int i = 0; i < p_blocks.size(); ++i) {
|
||||
VoxelBlockRequest &r = p_blocks[i];
|
||||
const Vector3i pos = r.origin_in_voxels >> bs_po2;
|
||||
const Vector3i pos = r.origin_in_voxels >> (bs_po2 + r.lod);
|
||||
|
||||
if (!BlockLocation::validate(pos, r.lod)) {
|
||||
ERR_PRINT(String("Block position {0} is outside of supported range").format(varray(pos.to_vec3())));
|
||||
|
|
|
@ -177,6 +177,7 @@ Array VoxelInstanceLibraryItem::serialize_multimesh_item_properties() const {
|
|||
}
|
||||
|
||||
void VoxelInstanceLibraryItem::deserialize_multimesh_item_properties(Array a) {
|
||||
ERR_FAIL_COND(a.size() != _mesh_lods.size() + 6);
|
||||
int ai = 0;
|
||||
for (unsigned int i = 0; i < _mesh_lods.size(); ++i) {
|
||||
_mesh_lods[i] = a[ai++];
|
||||
|
|
Loading…
Reference in New Issue