Removed internal offset from VoxelBuffer and improved Vector3i

This commit is contained in:
Marc Gilleron 2016-05-08 02:12:47 +02:00
parent 7305fd7b27
commit e990286b54
4 changed files with 82 additions and 82 deletions

View File

@ -5,9 +5,14 @@
struct Vector3i {
int x;
int y;
int z;
union {
struct {
int x;
int y;
int z;
};
int coords[3];
};
_FORCE_INLINE_ Vector3i() : x(0), y(0), z(0) {}
@ -34,28 +39,20 @@ struct Vector3i {
return *this;
}
_FORCE_INLINE_ Vector3i operator+(const Vector3i & other) const {
return Vector3i(x + other.x, y + other.y, z + other.z);
_FORCE_INLINE_ void operator+=(const Vector3i & other) {
x += other.x;
y += other.y;
z += other.z;
}
_FORCE_INLINE_ Vector3i operator-(const Vector3i & other) const {
return Vector3i(x - other.x, y - other.y, z - other.z);
_FORCE_INLINE_ void operator-=(const Vector3i & other) {
x -= other.x;
y -= other.y;
z -= other.z;
}
_FORCE_INLINE_ Vector3i operator*(int n) const {
return Vector3i(x * n, y * n, z * n);
}
_FORCE_INLINE_ Vector3i operator/(int n) const {
return Vector3i(x / n, y / n, z / n);
}
_FORCE_INLINE_ bool operator==(const Vector3i & other) const {
return x == other.x && y == other.y && z == other.z;
}
_FORCE_INLINE_ bool operator!=(const Vector3i & other) const {
return x != other.x && y != other.y && z != other.z;
_FORCE_INLINE_ int & operator[](unsigned int i) {
return coords[i];
}
void clamp_to(const Vector3i min, const Vector3i max) {
@ -68,9 +65,49 @@ struct Vector3i {
if (z >= max.z) z = max.z;
}
_FORCE_INLINE_ bool is_contained_in(const Vector3i & min, const Vector3i & max) {
return x >= min.x && y >= min.y && z >= min.z
&& x < max.x && y < max.y && z < max.z;
}
_FORCE_INLINE_ Vector3i wrap(const Vector3i & size) {
return Vector3i(
x % size.x,
y % size.y,
z % size.z
);
}
};
_FORCE_INLINE_ Vector3i operator+(const Vector3i a, const Vector3i & b) {
return Vector3i(a.x + b.x, a.y + b.y, a.z + b.z);
}
_FORCE_INLINE_ Vector3i operator-(const Vector3i & a, const Vector3i & b) {
return Vector3i(a.x - b.x, a.y - b.y, a.z - b.z);
}
_FORCE_INLINE_ Vector3i operator*(const Vector3i & a, int n) {
return Vector3i(a.x * n, a.y * n, a.z * n);
}
_FORCE_INLINE_ Vector3i operator*(int n, const Vector3i & a) {
return Vector3i(a.x * n, a.y * n, a.z * n);
}
_FORCE_INLINE_ Vector3i operator/(const Vector3i & a, int n) {
return Vector3i(a.x / n, a.y / n, a.z / n);
}
_FORCE_INLINE_ bool operator==(const Vector3i & a, const Vector3i & b) {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
_FORCE_INLINE_ bool operator!=(const Vector3i & a, const Vector3i & b) {
return a.x != b.x && a.y != b.y && a.z != b.z;
}
struct Vector3iHasher {
static _FORCE_INLINE_ uint32_t hash(const Vector3i & v) {
uint32_t hash = hash_djb2_one_32(v.x);

View File

@ -49,13 +49,9 @@ void VoxelBuffer::clear_channel(unsigned int channel_index, int clear_value) {
int VoxelBuffer::get_voxel(int x, int y, int z, unsigned int channel_index) const {
ERR_FAIL_INDEX_V(channel_index, MAX_CHANNELS, 0);
x -= _offset.x;
y -= _offset.y;
z -= _offset.z;
const Channel & channel = _channels[channel_index];
if (validate_local_pos(x, y, z) && channel.data) {
if (validate_pos(x, y, z) && channel.data) {
return VOXEL_AT(channel.data, x,y,z);
}
else {
@ -63,27 +59,9 @@ int VoxelBuffer::get_voxel(int x, int y, int z, unsigned int channel_index) cons
}
}
int VoxelBuffer::get_voxel_local(int x, int y, int z, unsigned int channel_index) const {
ERR_FAIL_INDEX_V(channel_index, MAX_CHANNELS, 0);
const Channel & channel = _channels[channel_index];
if (validate_local_pos(x, y, z) && channel.data) {
return VOXEL_AT(channel.data, x, y, z);
}
else {
return channel.defval;
}
}
void VoxelBuffer::set_voxel(int value, int x, int y, int z, unsigned int channel_index) {
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
x -= _offset.x;
y -= _offset.y;
z -= _offset.z;
ERR_FAIL_COND(!validate_local_pos(x, y, z));
ERR_FAIL_COND(!validate_pos(x, y, z));
Channel & channel = _channels[channel_index];
@ -254,16 +232,9 @@ void VoxelBuffer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_size_y"), &VoxelBuffer::get_size_y);
ObjectTypeDB::bind_method(_MD("get_size_z"), &VoxelBuffer::get_size_z);
ObjectTypeDB::bind_method(_MD("get_offset_x"), &VoxelBuffer::get_offset_x);
ObjectTypeDB::bind_method(_MD("get_offset_y"), &VoxelBuffer::get_offset_y);
ObjectTypeDB::bind_method(_MD("get_offset_z"), &VoxelBuffer::get_offset_z);
ObjectTypeDB::bind_method(_MD("get_offset"), &VoxelBuffer::_get_offset_binding);
ObjectTypeDB::bind_method(_MD("set_offset", "x", "y", "z"), &VoxelBuffer::_set_offset_binding);
ObjectTypeDB::bind_method(_MD("set_voxel", "value", "x", "y", "z", "channel"), &VoxelBuffer::set_voxel, DEFVAL(0));
ObjectTypeDB::bind_method(_MD("set_voxel", "value", "x", "y", "z", "channel"), &VoxelBuffer::_set_voxel_binding, DEFVAL(0));
ObjectTypeDB::bind_method(_MD("set_voxel_v", "value", "pos", "channel"), &VoxelBuffer::set_voxel_v, DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_voxel", "x", "y", "z", "channel"), &VoxelBuffer::get_voxel, DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_voxel", "x", "y", "z", "channel"), &VoxelBuffer::_get_voxel_binding, DEFVAL(0));
ObjectTypeDB::bind_method(_MD("fill", "value", "channel"), &VoxelBuffer::fill, DEFVAL(0));
ObjectTypeDB::bind_method(_MD("fill_area", "value", "min", "max", "channel"), &VoxelBuffer::_fill_area_binding, DEFVAL(0));

View File

@ -36,10 +36,6 @@ private:
// How many voxels are there in the three directions. All populated channels have the same size.
Vector3i _size;
// Offset applied to coordinates when accessing voxels.
// Use _local versions to bypass this.
Vector3i _offset;
public:
VoxelBuffer();
~VoxelBuffer();
@ -48,22 +44,13 @@ public:
void clear();
void clear_channel(unsigned int channel_index, int clear_value=0);
_FORCE_INLINE_ int get_size_x() const { return _size.x; }
_FORCE_INLINE_ int get_size_y() const { return _size.y; }
_FORCE_INLINE_ int get_size_z() const { return _size.z; }
_FORCE_INLINE_ Vector3i get_size() const { return _size; }
_FORCE_INLINE_ int get_offset_x() const { return _offset.x; }
_FORCE_INLINE_ int get_offset_y() const { return _offset.y; }
_FORCE_INLINE_ int get_offset_z() const { return _offset.z; }
_FORCE_INLINE_ void set_offset(int x, int y, int z) { _offset = Vector3i(x,y,z); }
_FORCE_INLINE_ void set_offset(Vector3i pos) { _offset = pos; }
int get_voxel(int x, int y, int z, unsigned int channel_index=0) const;
int get_voxel_local(int x, int y, int z, unsigned int channel_index=0) const;
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);
_FORCE_INLINE_ int get_voxel(const Vector3i pos, unsigned int channel_index = 0) const { return get_voxel(pos.x, pos.y, pos.z, channel_index); }
_FORCE_INLINE_ void set_voxel(int value, const Vector3i pos, unsigned int channel_index = 0) { set_voxel(value, pos.x, pos.y, pos.z, channel_index); }
void fill(int defval, unsigned int channel_index = 0);
void fill_area(int defval, Vector3i min, Vector3i max, unsigned int channel_index = 0);
@ -75,7 +62,7 @@ public:
void copy_from(const VoxelBuffer & other, unsigned int channel_index=0);
void copy_from(const VoxelBuffer & other, Vector3i src_min, Vector3i src_max, Vector3i dst_min, unsigned int channel_index = 0);
_FORCE_INLINE_ bool validate_local_pos(unsigned int x, unsigned int y, unsigned int z) const {
_FORCE_INLINE_ bool validate_pos(unsigned int x, unsigned int y, unsigned int z) const {
return x < _size.x
&& y < _size.y
&& z < _size.x;
@ -98,15 +85,19 @@ private:
void create_channel(int i, Vector3i size, uint8_t defval=0);
void delete_channel(int i, Vector3i size);
_FORCE_INLINE_ void _set_offset_binding(int x, int y, int z) { set_offset(x, y, z); }
_FORCE_INLINE_ Vector3 _get_offset_binding() const { return Vector3(_offset.x, _offset.y, _offset.z); }
protected:
static void _bind_methods();
_FORCE_INLINE_ int get_size_x() const { return _size.x; }
_FORCE_INLINE_ int get_size_y() const { return _size.y; }
_FORCE_INLINE_ int get_size_z() const { return _size.z; }
_FORCE_INLINE_ int _get_voxel_binding(int x, int y, int z, unsigned int channel) const { return get_voxel(x, y, z, channel); }
_FORCE_INLINE_ void _set_voxel_binding(int value, int x, int y, int z, unsigned int channel) { set_voxel(value, x, y, z, channel); }
void _copy_from_binding(Ref<VoxelBuffer> other, unsigned int channel);
void _copy_from_area_binding(Ref<VoxelBuffer> other, Vector3 src_min, Vector3 src_max, Vector3 dst_min, unsigned int channel);
_FORCE_INLINE_ void _fill_area_binding(int defval, Vector3 min, Vector3 max, unsigned int channel_index) { fill_area(defval, Vector3i(min), Vector3i(max), channel_index); }
protected:
static void _bind_methods();
};
#endif // VOXEL_BUFFER_H

View File

@ -190,11 +190,12 @@ Ref<Mesh> VoxelMesher::build(Ref<VoxelBuffer> buffer_ref) {
// Iterate 3D padded data to extract voxel faces.
// This is the most intensive job in this class, so all required data should be as fit as possible.
for (unsigned int z = 1; z < buffer.get_size_z()-1; ++z) {
for (unsigned int x = 1; x < buffer.get_size_x()-1; ++x) {
for (unsigned int y = 1; y < buffer.get_size_y()-1; ++y) {
const Vector3i buffer_size = buffer.get_size();
for (unsigned int z = 1; z < buffer_size.z-1; ++z) {
for (unsigned int x = 1; x < buffer_size.x-1; ++x) {
for (unsigned int y = 1; y < buffer_size.y-1; ++y) {
int voxel_id = buffer.get_voxel_local(x, y, z, 0);
int voxel_id = buffer.get_voxel(x, y, z, 0);
if (voxel_id != 0 && library.has_voxel(voxel_id)) {
@ -216,7 +217,7 @@ Ref<Mesh> VoxelMesher::build(Ref<VoxelBuffer> buffer_ref) {
unsigned ny = y + normal.y;
unsigned nz = z + normal.z;
int neighbor_voxel_id = buffer.get_voxel_local(nx, ny, nz, 0);
int neighbor_voxel_id = buffer.get_voxel(nx, ny, nz, 0);
// TODO Better face visibility test
if (is_face_visible(library, voxel, neighbor_voxel_id)) {
@ -234,7 +235,7 @@ Ref<Mesh> VoxelMesher::build(Ref<VoxelBuffer> buffer_ref) {
unsigned ex = x + edge_normal.x;
unsigned ey = y + edge_normal.y;
unsigned ez = z + edge_normal.z;
if (!is_transparent(library, buffer.get_voxel_local(ex, ey, ez))) {
if (!is_transparent(library, buffer.get_voxel(ex, ey, ez))) {
shaded_corner[g_edge_corners[edge][0]] += 1;
shaded_corner[g_edge_corners[edge][1]] += 1;
}
@ -249,7 +250,7 @@ Ref<Mesh> VoxelMesher::build(Ref<VoxelBuffer> buffer_ref) {
unsigned int cx = x + corner_normal.x;
unsigned int cy = y + corner_normal.y;
unsigned int cz = z + corner_normal.z;
if (!is_transparent(library, buffer.get_voxel_local(cx, cy, cz))) {
if (!is_transparent(library, buffer.get_voxel(cx, cy, cz))) {
shaded_corner[corner] += 1;
}
}