mirror of
https://github.com/Relintai/godot_voxel.git
synced 2024-12-25 16:27:16 +01:00
Removed internal offset from VoxelBuffer and improved Vector3i
This commit is contained in:
parent
7305fd7b27
commit
e990286b54
73
vector3i.h
73
vector3i.h
@ -5,9 +5,14 @@
|
||||
|
||||
struct Vector3i {
|
||||
|
||||
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);
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user