Added lod parameter to VoxelProvider

This commit is contained in:
Marc Gilleron 2019-04-29 21:57:39 +01:00
parent c80a24ef0b
commit 5851e4849f
9 changed files with 69 additions and 45 deletions

View File

@ -1,43 +1,47 @@
#include "voxel_provider.h"
#include <core/script_language.h>
void VoxelProvider::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels) {
void VoxelProvider::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) {
ERR_FAIL_COND(out_buffer.is_null());
ScriptInstance *script = get_script_instance();
if (script) {
// Call script to generate buffer
Variant arg1 = out_buffer;
Variant arg2 = origin_in_voxels.to_vec3();
const Variant *args[2] = { &arg1, &arg2 };
Variant arg3 = lod;
const Variant *args[3] = { &arg1, &arg2, &arg3 };
//Variant::CallError err; // wut
script->call_multilevel("emerge_block", args, 2);
script->call("emerge_block", args, 3);
}
}
void VoxelProvider::immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels) {
void VoxelProvider::immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod) {
ERR_FAIL_COND(buffer.is_null());
ScriptInstance *script = get_script_instance();
if (script) {
// Call script to save buffer
Variant arg1 = buffer;
Variant arg2 = origin_in_voxels.to_vec3();
const Variant *args[2] = { &arg1, &arg2 };
Variant arg3 = lod;
const Variant *args[3] = { &arg1, &arg2, &arg3 };
//Variant::CallError err; // wut
script->call_multilevel("immerge_block", args, 2);
script->call("immerge_block", args, 3);
}
}
void VoxelProvider::_emerge_block(Ref<VoxelBuffer> out_buffer, Vector3 origin_in_voxels) {
emerge_block(out_buffer, Vector3i(origin_in_voxels));
void VoxelProvider::_emerge_block(Ref<VoxelBuffer> out_buffer, Vector3 origin_in_voxels, int lod) {
ERR_FAIL_COND(lod < 0);
emerge_block(out_buffer, Vector3i(origin_in_voxels), lod);
}
void VoxelProvider::_immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxels) {
immerge_block(buffer, Vector3i(origin_in_voxels));
void VoxelProvider::_immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxels, int lod) {
ERR_FAIL_COND(lod < 0);
immerge_block(buffer, Vector3i(origin_in_voxels), lod);
}
void VoxelProvider::_bind_methods() {
// Note: C++ inheriting classes don't need to re-bind these, because they are bindings that call the actual virtual methods
ClassDB::bind_method(D_METHOD("emerge_block", "out_buffer", "origin_in_voxels"), &VoxelProvider::_emerge_block);
ClassDB::bind_method(D_METHOD("immerge_block", "buffer", "origin_in_voxels"), &VoxelProvider::_immerge_block);
ClassDB::bind_method(D_METHOD("emerge_block", "out_buffer", "origin_in_voxels", "lod"), &VoxelProvider::_emerge_block);
ClassDB::bind_method(D_METHOD("immerge_block", "buffer", "origin_in_voxels", "lod"), &VoxelProvider::_immerge_block);
}

View File

@ -7,14 +7,14 @@
class VoxelProvider : public Resource {
GDCLASS(VoxelProvider, Resource)
public:
virtual void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels);
virtual void immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels);
virtual void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod);
virtual void immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod);
protected:
static void _bind_methods();
void _emerge_block(Ref<VoxelBuffer> out_buffer, Vector3 origin_in_voxels);
void _immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxels);
void _emerge_block(Ref<VoxelBuffer> out_buffer, Vector3 origin_in_voxels, int lod);
void _immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxels, int lod);
};
#endif // VOXEL_PROVIDER_H

View File

@ -41,7 +41,12 @@ inline float get_height_blurred(Image &im, int x, int y) {
} // namespace
void VoxelProviderImage::emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i origin_in_voxels) {
void VoxelProviderImage::emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i origin_in_voxels, int lod) {
if (lod != 0) {
// TODO Handle higher lods
return;
}
int ox = origin_in_voxels.x;
int oy = origin_in_voxels.y;

View File

@ -17,7 +17,7 @@ public:
void set_channel(VoxelBuffer::ChannelId channel);
int get_channel() const;
void emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i origin_in_voxels);
void emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i origin_in_voxels, int lod);
private:
static void _bind_methods();

View File

@ -29,22 +29,27 @@ void VoxelProviderTest::set_pattern_offset(Vector3i offset) {
_pattern_offset = offset;
}
void VoxelProviderTest::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin) {
void VoxelProviderTest::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin, int lod) {
ERR_FAIL_COND(out_buffer.is_null());
if (lod != 0) {
// TODO Handle higher lods
return;
}
switch (_mode) {
case MODE_FLAT:
generate_block_flat(**out_buffer, origin);
generate_block_flat(**out_buffer, origin, lod);
break;
case MODE_WAVES:
generate_block_waves(**out_buffer, origin);
generate_block_waves(**out_buffer, origin, lod);
break;
}
}
void VoxelProviderTest::generate_block_flat(VoxelBuffer &out_buffer, Vector3i origin) {
void VoxelProviderTest::generate_block_flat(VoxelBuffer &out_buffer, Vector3i origin, int lod) {
// TODO Don't expect a block pos, but a voxel pos!
Vector3i size = out_buffer.get_size();
@ -62,7 +67,7 @@ void VoxelProviderTest::generate_block_flat(VoxelBuffer &out_buffer, Vector3i or
}
}
void VoxelProviderTest::generate_block_waves(VoxelBuffer &out_buffer, Vector3i origin) {
void VoxelProviderTest::generate_block_waves(VoxelBuffer &out_buffer, Vector3i origin, int lod) {
// TODO Don't expect a block pos, but a voxel pos!
Vector3i size = out_buffer.get_size();

View File

@ -14,7 +14,7 @@ public:
VoxelProviderTest();
virtual void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin);
virtual void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin, int lod);
void set_mode(Mode mode);
Mode get_mode() const { return _mode; }
@ -29,8 +29,8 @@ public:
void set_pattern_offset(Vector3i offset);
protected:
void generate_block_flat(VoxelBuffer &out_buffer, Vector3i origin);
void generate_block_waves(VoxelBuffer &out_buffer, Vector3i origin);
void generate_block_flat(VoxelBuffer &out_buffer, Vector3i origin, int lod);
void generate_block_waves(VoxelBuffer &out_buffer, Vector3i origin, int lod);
static void _bind_methods();

View File

@ -89,7 +89,7 @@ void VoxelProviderThread::thread_func() {
if (!_input.blocks_to_emerge.empty()) {
Vector3i block_pos = _input.blocks_to_emerge[emerge_index];
EmergeInput block = _input.blocks_to_emerge[emerge_index];
++emerge_index;
if (emerge_index >= _input.blocks_to_emerge.size()) {
@ -101,9 +101,9 @@ void VoxelProviderThread::thread_func() {
buffer->create(bs, bs, bs);
// Query voxel provider
Vector3i block_origin_in_voxels = block_pos * bs;
Vector3i block_origin_in_voxels = block.block_position * bs;
uint64_t time_before = OS::get_singleton()->get_ticks_usec();
_voxel_provider->emerge_block(buffer, block_origin_in_voxels);
_voxel_provider->emerge_block(buffer, block_origin_in_voxels, block.lod);
uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - time_before;
// Do some stats
@ -148,9 +148,12 @@ void VoxelProviderThread::thread_func() {
// Sorts distance to viewer
// The closest block will be the first one in the array
struct BlockPositionComparator {
// In LOD0 block coordinates
Vector3i center;
inline bool operator()(const Vector3i &a, const Vector3i &b) const {
return a.distance_sq(center) < b.distance_sq(center);
inline bool operator()(const VoxelProviderThread::EmergeInput &a, const VoxelProviderThread::EmergeInput &b) const {
int da = (a.block_position * (1 << a.lod)).distance_sq(center);
int db = (b.block_position * (1 << b.lod)).distance_sq(center);
return da < db;
}
};
@ -197,7 +200,7 @@ void VoxelProviderThread::thread_sync(int emerge_index, Stats stats) {
if (!_input.blocks_to_emerge.empty()) {
// Re-sort priority
SortArray<Vector3i, BlockPositionComparator> sorter;
SortArray<EmergeInput, BlockPositionComparator> sorter;
sorter.compare.center = _input.priority_block_position;
sorter.sort(_input.blocks_to_emerge.ptrw(), _input.blocks_to_emerge.size());
}

View File

@ -14,11 +14,17 @@ public:
struct ImmergeInput {
Vector3i origin;
Ref<VoxelBuffer> voxels;
int lod = 0;
};
struct EmergeInput {
Vector3i block_position;
int lod = 0;
};
struct InputData {
Vector<ImmergeInput> blocks_to_immerge;
Vector<Vector3i> blocks_to_emerge;
Vector<EmergeInput> blocks_to_emerge;
Vector3i priority_block_position;
inline bool is_empty() {
@ -29,19 +35,14 @@ public:
struct EmergeOutput {
Ref<VoxelBuffer> voxels;
Vector3i origin_in_voxels;
int lod = 0;
};
struct Stats {
bool first;
uint64_t min_time;
uint64_t max_time;
int remaining_blocks;
Stats() :
first(true),
min_time(0),
max_time(0),
remaining_blocks(0) {}
bool first = true;
uint64_t min_time = 0;
uint64_t max_time = 0;
int remaining_blocks = 0;
};
struct OutputData {

View File

@ -186,6 +186,7 @@ void VoxelTerrain::make_block_dirty(Vector3i bpos) {
_dirty_blocks[bpos] = BLOCK_UPDATE_NOT_SENT;
} else {
_blocks_pending_load.push_back(bpos);
_dirty_blocks[bpos] = BLOCK_LOAD;
}
@ -605,8 +606,13 @@ void VoxelTerrain::_process() {
VoxelProviderThread::InputData input;
input.priority_block_position = viewer_block_pos;
input.blocks_to_emerge.append_array(_blocks_pending_load);
//input.blocks_to_immerge.append_array();
for (int i = 0; i < _blocks_pending_load.size(); ++i) {
VoxelProviderThread::EmergeInput input_block;
input_block.block_position = _blocks_pending_load[i];
input_block.lod = 0;
input.blocks_to_emerge.push_back(input_block);
}
//print_line(String("Sending {0} block requests").format(varray(input.blocks_to_emerge.size())));
_blocks_pending_load.clear();