diff --git a/vector3i.h b/vector3i.h index 69902a0..d6d830a 100644 --- a/vector3i.h +++ b/vector3i.h @@ -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); diff --git a/voxel_buffer.cpp b/voxel_buffer.cpp index 41d2c57..88af1ae 100644 --- a/voxel_buffer.cpp +++ b/voxel_buffer.cpp @@ -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)); diff --git a/voxel_buffer.h b/voxel_buffer.h index db40b73..b3f20b4 100644 --- a/voxel_buffer.h +++ b/voxel_buffer.h @@ -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 other, unsigned int channel); void _copy_from_area_binding(Ref 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 diff --git a/voxel_mesher.cpp b/voxel_mesher.cpp index 4674e75..7365bc1 100644 --- a/voxel_mesher.cpp +++ b/voxel_mesher.cpp @@ -190,11 +190,12 @@ Ref VoxelMesher::build(Ref 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 VoxelMesher::build(Ref 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 VoxelMesher::build(Ref 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 VoxelMesher::build(Ref 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; } }