mirror of
https://github.com/Relintai/godot_voxel.git
synced 2024-12-22 01:26:50 +01:00
Drop gradient channels, fix misconception about what gradient is
This commit is contained in:
parent
572dcbf680
commit
bed8ac8cb9
@ -17,19 +17,28 @@ struct HermiteValue {
|
||||
}
|
||||
};
|
||||
|
||||
inline HermiteValue get_hermite_value(const VoxelBuffer &voxels, unsigned int x, unsigned int y, unsigned int z) {
|
||||
inline float get_isolevel_clamped(const VoxelBuffer &voxels, unsigned int x, unsigned int y, unsigned int z) {
|
||||
|
||||
x = x >= voxels.get_size().x ? voxels.get_size().x - 1 : x;
|
||||
x = x >= voxels.get_size().y ? voxels.get_size().y - 1 : x;
|
||||
x = x >= voxels.get_size().z ? voxels.get_size().z - 1 : x;
|
||||
y = y >= voxels.get_size().y ? voxels.get_size().y - 1 : y;
|
||||
z = z >= voxels.get_size().z ? voxels.get_size().z - 1 : z;
|
||||
|
||||
return voxels.get_voxel(x, y, z, VoxelBuffer::CHANNEL_ISOLEVEL);
|
||||
}
|
||||
|
||||
inline HermiteValue get_hermite_value(const VoxelBuffer &voxels, unsigned int x, unsigned int y, unsigned int z) {
|
||||
|
||||
HermiteValue v;
|
||||
|
||||
v.value = voxels.get_voxel_iso(x, y, z, VoxelBuffer::CHANNEL_ISOLEVEL);
|
||||
// TODO It looks like this gradient should not be a normalized vector!
|
||||
v.gradient.x = voxels.get_voxel_iso(x, y, z, VoxelBuffer::CHANNEL_GRADIENT_X);
|
||||
v.gradient.y = voxels.get_voxel_iso(x, y, z, VoxelBuffer::CHANNEL_GRADIENT_Y);
|
||||
v.gradient.z = voxels.get_voxel_iso(x, y, z, VoxelBuffer::CHANNEL_GRADIENT_Z);
|
||||
|
||||
Vector3 gradient;
|
||||
|
||||
gradient.x = get_isolevel_clamped(voxels, x + 1, y, z) - get_isolevel_clamped(voxels, x - 1, y, z);
|
||||
gradient.y = get_isolevel_clamped(voxels, x, y + 1, z) - get_isolevel_clamped(voxels, x, y - 1, z);
|
||||
gradient.z = get_isolevel_clamped(voxels, x, y, z + 1) - get_isolevel_clamped(voxels, x, y, z - 1);
|
||||
|
||||
v.gradient = gradient;
|
||||
|
||||
return v;
|
||||
}
|
||||
@ -44,6 +53,8 @@ inline HermiteValue get_interpolated_hermite_value(const VoxelBuffer &voxels, Ve
|
||||
int y1 = static_cast<int>(Math::ceil(pos.y));
|
||||
int z1 = static_cast<int>(Math::ceil(pos.z));
|
||||
|
||||
// TODO There are lots of hidden grid accesses here, could be optimized
|
||||
|
||||
HermiteValue v0 = get_hermite_value(voxels, x0, y0, z0);
|
||||
HermiteValue v1 = get_hermite_value(voxels, x1, y0, z0);
|
||||
HermiteValue v2 = get_hermite_value(voxels, x1, y0, z1);
|
||||
|
@ -92,11 +92,11 @@ bool can_split(Vector3i node_origin, int node_size, const VoxelAccess &voxels, f
|
||||
int channel = VoxelBuffer::CHANNEL_ISOLEVEL;
|
||||
|
||||
// Don't split if nothing is inside, i.e isolevel distance is greater than the size of the cube we are in
|
||||
// Vector3i center_pos = node_origin + Vector3i(node_size / 2);
|
||||
// HermiteValue center_value = voxels.get_hermite_value(center_pos.x, center_pos.y, center_pos.z);
|
||||
// if (Math::abs(center_value.value) > SQRT3 * (float)node_size) {
|
||||
// return false;
|
||||
// }
|
||||
Vector3i center_pos = node_origin + Vector3i(node_size / 2);
|
||||
HermiteValue center_value = voxels.get_hermite_value(center_pos.x, center_pos.y, center_pos.z);
|
||||
if (Math::abs(center_value.value) > SQRT3 * (float)node_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fighting with Clang-format here /**/
|
||||
|
||||
|
@ -281,79 +281,6 @@ void VoxelBuffer::delete_channel(int i) {
|
||||
channel.data = NULL;
|
||||
}
|
||||
|
||||
void VoxelBuffer::compute_gradients() {
|
||||
|
||||
const Channel &iso_channel = _channels[CHANNEL_ISOLEVEL];
|
||||
|
||||
const int gradient_x_channel = CHANNEL_GRADIENT_X;
|
||||
const int gradient_y_channel = CHANNEL_GRADIENT_Y;
|
||||
const int gradient_z_channel = CHANNEL_GRADIENT_Z;
|
||||
|
||||
if (iso_channel.data == nullptr) {
|
||||
|
||||
// The channel is uniform, gradient will be zero
|
||||
fill(0, gradient_x_channel);
|
||||
fill(0, gradient_y_channel);
|
||||
fill(0, gradient_z_channel);
|
||||
|
||||
} else {
|
||||
|
||||
if (_channels[gradient_x_channel].data == nullptr) {
|
||||
create_channel_noinit(gradient_x_channel, _size);
|
||||
}
|
||||
if (_channels[gradient_y_channel].data == nullptr) {
|
||||
create_channel_noinit(gradient_y_channel, _size);
|
||||
}
|
||||
if (_channels[gradient_z_channel].data == nullptr) {
|
||||
create_channel_noinit(gradient_z_channel, _size);
|
||||
}
|
||||
|
||||
Channel &gx_channel = _channels[gradient_x_channel];
|
||||
Channel &gy_channel = _channels[gradient_y_channel];
|
||||
Channel &gz_channel = _channels[gradient_z_channel];
|
||||
|
||||
const int padding = 1;
|
||||
|
||||
const int min_x = padding;
|
||||
const int min_y = padding;
|
||||
const int min_z = padding;
|
||||
|
||||
const int max_z = _size.z - padding;
|
||||
const int max_x = _size.x - padding;
|
||||
const int max_y = _size.y - padding;
|
||||
|
||||
const int lookup_left = -_size.x;
|
||||
const int lookup_right = -lookup_left;
|
||||
const int lookup_back = -_size.z * _size.x;
|
||||
const int lookup_front = -lookup_back;
|
||||
const int lookup_down = -1;
|
||||
const int lookup_up = -lookup_down;
|
||||
|
||||
for (int z = min_z; z < max_z; ++z) {
|
||||
for (int x = min_x; x < max_x; ++x) {
|
||||
|
||||
int i = index(x, min_y, z);
|
||||
|
||||
for (int y = min_y; y < max_y; ++y) {
|
||||
|
||||
Vector3 v(
|
||||
byte_to_iso(iso_channel.data[i + lookup_right]) - byte_to_iso(iso_channel.data[i + lookup_left]),
|
||||
byte_to_iso(iso_channel.data[i + lookup_up]) - byte_to_iso(iso_channel.data[i + lookup_down]),
|
||||
byte_to_iso(iso_channel.data[i + lookup_front]) - byte_to_iso(iso_channel.data[i + lookup_back]));
|
||||
|
||||
v.normalize();
|
||||
|
||||
gx_channel.data[i] = iso_to_byte(v.x);
|
||||
gy_channel.data[i] = iso_to_byte(v.y);
|
||||
gz_channel.data[i] = iso_to_byte(v.z);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBuffer::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("create", "sx", "sy", "sz"), &VoxelBuffer::create);
|
||||
@ -377,16 +304,15 @@ void VoxelBuffer::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_uniform", "channel"), &VoxelBuffer::is_uniform, DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("optimize"), &VoxelBuffer::optimize);
|
||||
ClassDB::bind_method(D_METHOD("compute_gradients"), &VoxelBuffer::compute_gradients);
|
||||
|
||||
BIND_ENUM_CONSTANT(CHANNEL_TYPE);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_ISOLEVEL);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_GRADIENT_X);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_GRADIENT_Y);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_GRADIENT_Z);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_DATA);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_DATA2);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_DATA3);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_DATA4);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_DATA5);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_DATA6);
|
||||
BIND_ENUM_CONSTANT(CHANNEL_DATA7);
|
||||
BIND_ENUM_CONSTANT(MAX_CHANNELS);
|
||||
}
|
||||
|
||||
|
@ -16,16 +16,23 @@ public:
|
||||
enum ChannelId {
|
||||
CHANNEL_TYPE = 0,
|
||||
CHANNEL_ISOLEVEL,
|
||||
CHANNEL_GRADIENT_X,
|
||||
CHANNEL_GRADIENT_Y,
|
||||
CHANNEL_GRADIENT_Z,
|
||||
CHANNEL_DATA,
|
||||
CHANNEL_DATA2,
|
||||
CHANNEL_DATA3,
|
||||
CHANNEL_DATA4,
|
||||
CHANNEL_DATA5,
|
||||
CHANNEL_DATA6,
|
||||
CHANNEL_DATA7,
|
||||
// Arbitrary value, 8 should be enough. Tweak for your needs.
|
||||
MAX_CHANNELS
|
||||
};
|
||||
|
||||
// TODO Quantification options
|
||||
// enum ChannelFormat {
|
||||
// FORMAT_I8_Q255U, // 0..255 integer
|
||||
// FORMAT_F8_Q1S, // -1..1 float stored in 8 bits
|
||||
// FORMAT_F16_Q128S // -128..128 float stored in 16 bits
|
||||
// };
|
||||
|
||||
// Converts -1..1 float into 0..255 integer
|
||||
static inline int iso_to_byte(real_t iso) {
|
||||
int v = static_cast<int>(128.f * iso + 128.f);
|
||||
@ -94,8 +101,6 @@ public:
|
||||
|
||||
uint8_t *get_channel_raw(unsigned int channel_index) const;
|
||||
|
||||
void compute_gradients();
|
||||
|
||||
private:
|
||||
void create_channel_noinit(int i, Vector3i size);
|
||||
void create_channel(int i, Vector3i size, uint8_t defval);
|
||||
|
Loading…
Reference in New Issue
Block a user