master
Marc Gilleron 2021-05-15 16:31:36 +01:00
parent dd82fc91c8
commit 9b3263d68b
6 changed files with 64 additions and 18 deletions

View File

@ -88,7 +88,7 @@ void VoxelToolTerrain::copy(Vector3i pos, Ref<VoxelBuffer> dst, uint8_t channels
if (channels_mask == 0) {
channels_mask = (1 << _channel);
}
_terrain->get_storage().get_buffer_copy(pos, **dst, channels_mask);
_terrain->get_storage().copy(pos, **dst, channels_mask);
}
void VoxelToolTerrain::paste(Vector3i pos, Ref<VoxelBuffer> p_voxels, uint8_t channels_mask, uint64_t mask_value) {

View File

@ -726,16 +726,14 @@ Ref<VoxelTool> VoxelBuffer::get_voxel_tool() {
return Ref<VoxelTool>(memnew(VoxelToolBuffer(vb)));
}
bool VoxelBuffer::equals(const VoxelBuffer *p_other) const {
CRASH_COND(p_other == nullptr);
if (p_other->_size != _size) {
bool VoxelBuffer::equals(const VoxelBuffer &p_other) const {
if (p_other._size != _size) {
return false;
}
for (int channel_index = 0; channel_index < MAX_CHANNELS; ++channel_index) {
const Channel &channel = _channels[channel_index];
const Channel &other_channel = p_other->_channels[channel_index];
const Channel &other_channel = p_other._channels[channel_index];
if ((channel.data == nullptr) != (other_channel.data == nullptr)) {
// Note: they could still logically be equal if one channel contains uniform voxel memory
@ -752,7 +750,7 @@ bool VoxelBuffer::equals(const VoxelBuffer *p_other) const {
}
} else {
CRASH_COND(channel.size_in_bytes != other_channel.size_in_bytes);
ERR_FAIL_COND_V(channel.size_in_bytes != other_channel.size_in_bytes, false);
for (unsigned int i = 0; i < channel.size_in_bytes; ++i) {
if (channel.data[i] != other_channel.data[i]) {
return false;

View File

@ -187,7 +187,7 @@ public:
void downscale_to(VoxelBuffer &dst, Vector3i src_min, Vector3i src_max, Vector3i dst_min) const;
Ref<VoxelTool> get_voxel_tool();
bool equals(const VoxelBuffer *p_other) const;
bool equals(const VoxelBuffer &p_other) const;
void set_channel_depth(unsigned int channel_index, Depth new_depth);
Depth get_channel_depth(unsigned int channel_index) const;

View File

@ -202,7 +202,7 @@ bool VoxelDataMap::is_block_surrounded(Vector3i pos) const {
return true;
}
void VoxelDataMap::get_buffer_copy(Vector3i min_pos, VoxelBuffer &dst_buffer, unsigned int channels_mask) {
void VoxelDataMap::copy(Vector3i min_pos, VoxelBuffer &dst_buffer, unsigned int channels_mask) {
const Vector3i max_pos = min_pos + dst_buffer.get_size();
const Vector3i min_block_pos = voxel_to_block(min_pos);
@ -219,31 +219,29 @@ void VoxelDataMap::get_buffer_copy(Vector3i min_pos, VoxelBuffer &dst_buffer, un
continue;
}
const VoxelDataBlock *block = get_block(bpos);
const Vector3i src_block_origin = block_to_voxel(bpos);
if (block != nullptr) {
const VoxelBuffer &src_buffer = **block->voxels;
dst_buffer.set_channel_depth(channel, src_buffer.get_channel_depth(channel));
const Vector3i offset = block_to_voxel(bpos);
RWLockRead lock(src_buffer.get_lock());
// Note: copy_from takes care of clamping the area if it's on an edge
dst_buffer.copy_from(src_buffer,
min_pos - offset,
max_pos - offset,
offset - min_pos,
min_pos - src_block_origin,
src_buffer.get_size(),
Vector3i(),
channel);
} else {
// For now, inexistent blocks default to hardcoded defaults, corresponding to "empty space".
// If we want to change this, we may have to add an API for that.
const Vector3i offset = block_to_voxel(bpos);
dst_buffer.fill_area(
_default_voxel[channel],
offset - min_pos,
offset - min_pos + block_size_v,
src_block_origin - min_pos,
src_block_origin - min_pos + block_size_v,
channel);
}
}

View File

@ -56,7 +56,7 @@ public:
int get_default_voxel(unsigned int channel = 0);
// Gets a copy of all voxels in the area starting at min_pos having the same size as dst_buffer.
void get_buffer_copy(Vector3i min_pos, VoxelBuffer &dst_buffer, unsigned int channels_mask);
void copy(Vector3i min_pos, VoxelBuffer &dst_buffer, unsigned int channels_mask);
void paste(Vector3i min_pos, VoxelBuffer &src_buffer, unsigned int channels_mask, uint64_t mask_value,
bool create_new_blocks);

View File

@ -146,6 +146,55 @@ void test_voxel_data_map_paste_mask() {
ERR_FAIL_COND(!outside_is_ok);
}
void test_voxel_data_map_copy() {
static const int voxel_value = 1;
static const int default_value = 0;
static const int channel = VoxelBuffer::CHANNEL_TYPE;
VoxelDataMap map;
map.create(4, 0);
Rect3i box(10, 10, 10, 32, 16, 32);
Ref<VoxelBuffer> buffer;
buffer.instance();
buffer->create(box.size);
// Fill the inside of the buffer with a value, and leave outline to zero,
// so our buffer isn't just uniform
for (int z = 1; z < buffer->get_size().z - 1; ++z) {
for (int x = 1; x < buffer->get_size().x - 1; ++x) {
for (int y = 1; y < buffer->get_size().y - 1; ++y) {
buffer->set_voxel(voxel_value, x, y, z, channel);
}
}
}
map.paste(box.pos, **buffer, (1 << channel), default_value, true);
Ref<VoxelBuffer> buffer2;
buffer2.instance();
buffer2->create(box.size);
map.copy(box.pos, **buffer2, (1 << channel));
// for (int y = 0; y < buffer2->get_size().y; ++y) {
// String line = String("y={0} | ").format(varray(y));
// for (int x = 0; x < buffer2->get_size().x; ++x) {
// const int v = buffer2->get_voxel(Vector3i(x, y, 5), channel);
// if (v == default_value) {
// line += "- ";
// } else if (v == voxel_value) {
// line += "O ";
// } else {
// line += "X ";
// }
// }
// print_line(line);
// }
ERR_FAIL_COND(!buffer->equals(**buffer2));
}
#define VOXEL_TEST(fname) \
print_line(String("Running {0}").format(varray(#fname))); \
fname()
@ -156,6 +205,7 @@ void run_voxel_tests() {
VOXEL_TEST(test_rect3i_for_inner_outline);
VOXEL_TEST(test_voxel_data_map_paste_fill);
VOXEL_TEST(test_voxel_data_map_paste_mask);
VOXEL_TEST(test_voxel_data_map_copy);
print_line("------------ Voxel tests end -------------");
}