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 "voxel_provider.h"
#include <core/script_language.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()); ERR_FAIL_COND(out_buffer.is_null());
ScriptInstance *script = get_script_instance(); ScriptInstance *script = get_script_instance();
if (script) { if (script) {
// Call script to generate buffer // Call script to generate buffer
Variant arg1 = out_buffer; Variant arg1 = out_buffer;
Variant arg2 = origin_in_voxels.to_vec3(); 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 //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()); ERR_FAIL_COND(buffer.is_null());
ScriptInstance *script = get_script_instance(); ScriptInstance *script = get_script_instance();
if (script) { if (script) {
// Call script to save buffer // Call script to save buffer
Variant arg1 = buffer; Variant arg1 = buffer;
Variant arg2 = origin_in_voxels.to_vec3(); 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 //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) { void VoxelProvider::_emerge_block(Ref<VoxelBuffer> out_buffer, Vector3 origin_in_voxels, int lod) {
emerge_block(out_buffer, Vector3i(origin_in_voxels)); 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) { void VoxelProvider::_immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxels, int lod) {
immerge_block(buffer, Vector3i(origin_in_voxels)); ERR_FAIL_COND(lod < 0);
immerge_block(buffer, Vector3i(origin_in_voxels), lod);
} }
void VoxelProvider::_bind_methods() { 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 // 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("emerge_block", "out_buffer", "origin_in_voxels", "lod"), &VoxelProvider::_emerge_block);
ClassDB::bind_method(D_METHOD("immerge_block", "buffer", "origin_in_voxels"), &VoxelProvider::_immerge_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 { class VoxelProvider : public Resource {
GDCLASS(VoxelProvider, Resource) GDCLASS(VoxelProvider, Resource)
public: public:
virtual void emerge_block(Ref<VoxelBuffer> out_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); virtual void immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod);
protected: protected:
static void _bind_methods(); static void _bind_methods();
void _emerge_block(Ref<VoxelBuffer> out_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); void _immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxels, int lod);
}; };
#endif // VOXEL_PROVIDER_H #endif // VOXEL_PROVIDER_H

View File

@ -41,7 +41,12 @@ inline float get_height_blurred(Image &im, int x, int y) {
} // namespace } // 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 ox = origin_in_voxels.x;
int oy = origin_in_voxels.y; int oy = origin_in_voxels.y;

View File

@ -17,7 +17,7 @@ public:
void set_channel(VoxelBuffer::ChannelId channel); void set_channel(VoxelBuffer::ChannelId channel);
int get_channel() const; 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: private:
static void _bind_methods(); static void _bind_methods();

View File

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

View File

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

View File

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

View File

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

View File

@ -186,6 +186,7 @@ void VoxelTerrain::make_block_dirty(Vector3i bpos) {
_dirty_blocks[bpos] = BLOCK_UPDATE_NOT_SENT; _dirty_blocks[bpos] = BLOCK_UPDATE_NOT_SENT;
} else { } else {
_blocks_pending_load.push_back(bpos); _blocks_pending_load.push_back(bpos);
_dirty_blocks[bpos] = BLOCK_LOAD; _dirty_blocks[bpos] = BLOCK_LOAD;
} }
@ -605,8 +606,13 @@ void VoxelTerrain::_process() {
VoxelProviderThread::InputData input; VoxelProviderThread::InputData input;
input.priority_block_position = viewer_block_pos; 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()))); //print_line(String("Sending {0} block requests").format(varray(input.blocks_to_emerge.size())));
_blocks_pending_load.clear(); _blocks_pending_load.clear();