Implemented nearest neighbor downscaling (to be tested)
parent
a24e6d1b5a
commit
2e1467edd7
|
@ -90,12 +90,12 @@ struct Vector3i {
|
|||
return coords[i];
|
||||
}
|
||||
|
||||
// Clamps between min and max, where max is excluded
|
||||
void clamp_to(const Vector3i min, const Vector3i max) {
|
||||
if (x < min.x) x = min.x;
|
||||
if (y < min.y) y = min.y;
|
||||
if (z < min.z) z = min.z;
|
||||
|
||||
// TODO Not sure it should clamp like that...
|
||||
if (x >= max.x) x = max.x - 1;
|
||||
if (y >= max.y) y = max.y - 1;
|
||||
if (z >= max.z) z = max.z - 1;
|
||||
|
|
|
@ -328,6 +328,54 @@ void VoxelBuffer::delete_channel(int i) {
|
|||
channel.data = NULL;
|
||||
}
|
||||
|
||||
void VoxelBuffer::downscale_to(VoxelBuffer &dst, Vector3i src_min, Vector3i src_max, Vector3i dst_min) const {
|
||||
|
||||
// TODO Align input to multiple of two
|
||||
|
||||
src_min.clamp_to(Vector3i(), _size);
|
||||
src_max.clamp_to(Vector3i(), _size);
|
||||
|
||||
Vector3i dst_max = dst_min + (src_max - src_min) >> 2;
|
||||
|
||||
dst_min.clamp_to(Vector3i(), dst._size);
|
||||
dst_max.clamp_to(Vector3i(), dst._size);
|
||||
|
||||
for (int channel_index = 0; channel_index < MAX_CHANNELS; ++channel_index) {
|
||||
|
||||
const Channel &src_channel = _channels[channel_index];
|
||||
const Channel &dst_channel = _channels[channel_index];
|
||||
|
||||
if (src_channel.data == nullptr && dst_channel.data == nullptr && src_channel.defval == dst_channel.defval) {
|
||||
// No action needed
|
||||
continue;
|
||||
}
|
||||
|
||||
// Nearest-neighbor downscaling
|
||||
|
||||
Vector3i pos;
|
||||
for (pos.z = dst_min.z; pos.z < dst_max.z; ++pos.z) {
|
||||
for (pos.x = dst_min.x; pos.x < dst_max.x; ++pos.x) {
|
||||
for (pos.y = dst_min.y; pos.y < dst_max.y; ++pos.y) {
|
||||
|
||||
Vector3i src_pos = src_min + (pos - dst_min) << 2;
|
||||
|
||||
// TODO Remove check once it works
|
||||
CRASH_COND(!validate_pos(src_pos.x, src_pos.y, src_pos.z));
|
||||
|
||||
int v;
|
||||
if (src_channel.data) {
|
||||
v = src_channel.data[index(src_pos.x, src_pos.y, src_pos.z)];
|
||||
} else {
|
||||
v = src_channel.defval;
|
||||
}
|
||||
|
||||
dst.set_voxel(v, pos, channel_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBuffer::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("create", "sx", "sy", "sz"), &VoxelBuffer::create);
|
||||
|
|
|
@ -118,6 +118,8 @@ public:
|
|||
|
||||
uint8_t *get_channel_raw(unsigned int channel_index) const;
|
||||
|
||||
void downscale_to(VoxelBuffer &dst, Vector3i src_min, Vector3i src_max, Vector3i dst_min) const;
|
||||
|
||||
private:
|
||||
void create_channel_noinit(int i, Vector3i size);
|
||||
void create_channel(int i, Vector3i size, uint8_t defval);
|
||||
|
|
Loading…
Reference in New Issue