Added try_set_voxel and fix fill_area in cases where the box is out of range

This commit is contained in:
Marc Gilleron 2018-10-04 23:13:03 +01:00
parent 20d8cf876b
commit b052f7fc2d
4 changed files with 43 additions and 1 deletions

View File

@ -53,6 +53,22 @@ public:
return String("(o:{0}, s:{1})").format(varray(pos.to_vec3(), size.to_vec3())); 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) { inline bool operator!=(const Rect3i & a, const Rect3i & b) {

View File

@ -84,6 +84,7 @@ struct Vector3i {
if (y < min.y) y = min.y; if (y < min.y) y = min.y;
if (z < min.z) z = min.z; if (z < min.z) z = min.z;
// TODO Not sure it should clamp like that...
if (x >= max.x) x = max.x - 1; if (x >= max.x) x = max.x - 1;
if (y >= max.y) y = max.y - 1; if (y >= max.y) y = max.y - 1;
if (z >= max.z) z = max.z - 1; if (z >= max.z) z = max.z - 1;

View File

@ -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) { void VoxelBuffer::set_voxel_v(int value, Vector3 pos, unsigned int channel_index) {
set_voxel(value, pos.x, pos.y, pos.z, 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); 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)); max.clamp_to(Vector3i(0, 0, 0), _size + Vector3i(1, 1, 1));
Vector3i area_size = max - min; Vector3i area_size = max - min;
if(area_size.x == 0 || area_size.y == 0 || area_size.z == 0)
return;
Channel &channel = _channels[channel_index]; Channel &channel = _channels[channel_index];
if (channel.data == NULL) { if (channel.data == NULL) {
if (channel.defval == defval) if (channel.defval == defval)
@ -122,9 +143,11 @@ void VoxelBuffer::fill_area(int defval, Vector3i min, Vector3i max, unsigned int
} }
Vector3i pos; Vector3i pos;
int volume = get_volume();
for (pos.z = min.z; pos.z < max.z; ++pos.z) { for (pos.z = min.z; pos.z < max.z; ++pos.z) {
for (pos.x = min.x; pos.x < max.x; ++pos.x) { for (pos.x = min.x; pos.x < max.x; ++pos.x) {
unsigned int dst_ri = index(pos.x, pos.y + min.y, pos.z); 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)); memset(&channel.data[dst_ri], defval, area_size.y * sizeof(uint8_t));
} }
} }

View File

@ -46,6 +46,8 @@ public:
void set_voxel(int value, int x, int y, int z, unsigned int channel_index = 0); 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 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_ 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)); } _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)); }