Added function to compute gradients from isolevels

This commit is contained in:
Marc Gilleron 2019-04-21 02:54:35 +01:00
parent 9bb81f9bb7
commit d53e43f115
2 changed files with 74 additions and 0 deletions

View File

@ -272,6 +272,77 @@ void VoxelBuffer::delete_channel(int i) {
channel.data = NULL;
}
void VoxelBuffer::compute_gradients(unsigned int isolevel_channel, unsigned int first_gradient_channel) {
ERR_FAIL_COND(isolevel_channel >= MAX_CHANNELS);
ERR_FAIL_COND(first_gradient_channel + 2 >= MAX_CHANNELS);
int gradient_x_channel = first_gradient_channel;
int gradient_y_channel = first_gradient_channel + 1;
int gradient_z_channel = first_gradient_channel + 2;
ERR_FAIL_COND(gradient_x_channel == isolevel_channel);
ERR_FAIL_COND(gradient_y_channel == isolevel_channel);
ERR_FAIL_COND(gradient_z_channel == isolevel_channel);
const Channel &iso_channel = _channels[isolevel_channel];
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];
int max_z = _size.z - 1;
int max_x = _size.x - 1;
int max_y = _size.y - 1;
int lookup_left = -_size.x;
int lookup_right = -lookup_left;
int lookup_back = -_size.z * _size.x;
int lookup_front = -lookup_back;
int lookup_down = -1;
int lookup_up = -lookup_down;
for (int z = 1; z < max_z; ++z) {
for (int x = 1; x < max_x; ++x) {
for (int y = 1; y < max_y; ++y) {
int i = index(x, y, z);
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);
}
}
}
}
}
void VoxelBuffer::_bind_methods() {
ClassDB::bind_method(D_METHOD("create", "sx", "sy", "sz"), &VoxelBuffer::create);
@ -294,6 +365,7 @@ 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", "isolevel_channel", "first_gradient_channel"), &VoxelBuffer::compute_gradients);
}
void VoxelBuffer::_copy_from_binding(Ref<VoxelBuffer> other, unsigned int channel) {

View File

@ -82,6 +82,8 @@ public:
uint8_t *get_channel_raw(unsigned int channel_index) const;
void compute_gradients(unsigned int isolevel_index, unsigned int first_gradient_channel);
private:
void create_channel_noinit(int i, Vector3i size);
void create_channel(int i, Vector3i size, uint8_t defval = 0);