diff --git a/rect3i.h b/rect3i.h index 1d134ea..9eda644 100644 --- a/rect3i.h +++ b/rect3i.h @@ -53,6 +53,22 @@ public: return String("(o:{0}, s:{1})").format(varray(pos.to_vec3(), size.to_vec3())); } + bool intersects(Rect3i other) { + if (pos.x > other.pos.x + other.size.x) + return false; + if (pos.y > other.pos.y + other.size.y) + return false; + if (pos.z > other.pos.z + other.size.z) + return false; + if (other.pos.x > pos.x + size.x) + return false; + if (other.pos.y > pos.y + size.y) + return false; + if (other.pos.z > pos.z + size.z) + return false; + return true; + } + }; inline bool operator!=(const Rect3i & a, const Rect3i & b) { diff --git a/vector3i.h b/vector3i.h index a4fbbd7..a083910 100644 --- a/vector3i.h +++ b/vector3i.h @@ -84,6 +84,7 @@ struct Vector3i { 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; diff --git a/voxel_buffer.cpp b/voxel_buffer.cpp index 81b98af..d4922ac 100644 --- a/voxel_buffer.cpp +++ b/voxel_buffer.cpp @@ -78,6 +78,24 @@ void VoxelBuffer::set_voxel(int value, int x, int y, int z, unsigned int channel } } +// This version does not cause errors if out of bounds. Use only if it's okay to be outside. +void VoxelBuffer::try_set_voxel(int x, int y, int z, int value, unsigned int channel_index) { + ERR_FAIL_INDEX(channel_index, MAX_CHANNELS); + if(!validate_pos(x, y, z)) + return; + + Channel &channel = _channels[channel_index]; + + if (channel.data == NULL) { + if (channel.defval != value) { + create_channel(channel_index, _size); + channel.data[index(x, y, z)] = value; + } + } else { + channel.data[index(x, y, z)] = value; + } +} + void VoxelBuffer::set_voxel_v(int value, Vector3 pos, unsigned int channel_index) { set_voxel(value, pos.x, pos.y, pos.z, channel_index); } @@ -109,10 +127,13 @@ void VoxelBuffer::fill_area(int defval, Vector3i min, Vector3i max, unsigned int Vector3i::sort_min_max(min, max); - min.clamp_to(Vector3i(0, 0, 0), _size); + min.clamp_to(Vector3i(0, 0, 0), _size + Vector3i(1, 1, 1)); max.clamp_to(Vector3i(0, 0, 0), _size + Vector3i(1, 1, 1)); Vector3i area_size = max - min; + if(area_size.x == 0 || area_size.y == 0 || area_size.z == 0) + return; + Channel &channel = _channels[channel_index]; if (channel.data == NULL) { if (channel.defval == defval) @@ -122,9 +143,11 @@ void VoxelBuffer::fill_area(int defval, Vector3i min, Vector3i max, unsigned int } Vector3i pos; + int volume = get_volume(); for (pos.z = min.z; pos.z < max.z; ++pos.z) { for (pos.x = min.x; pos.x < max.x; ++pos.x) { unsigned int dst_ri = index(pos.x, pos.y + min.y, pos.z); + CRASH_COND(dst_ri >= volume); memset(&channel.data[dst_ri], defval, area_size.y * sizeof(uint8_t)); } } diff --git a/voxel_buffer.h b/voxel_buffer.h index c46eeb8..c072828 100644 --- a/voxel_buffer.h +++ b/voxel_buffer.h @@ -46,6 +46,8 @@ public: void set_voxel(int value, int x, int y, int z, unsigned int channel_index = 0); void set_voxel_v(int value, Vector3 pos, unsigned int channel_index = 0); + void try_set_voxel(int x, int y, int z, int value, unsigned int channel_index = 0); + _FORCE_INLINE_ void set_voxel_iso(real_t value, int x, int y, int z, unsigned int channel_index = 0) { set_voxel(iso_to_byte(value), x, y, z, channel_index); } _FORCE_INLINE_ real_t get_voxel_iso(int x, int y, int z, unsigned int channel_index = 0) const { return byte_to_iso(get_voxel(x, y, z, channel_index)); }