From bed8ac8cb9aa60628d8dcb278c1a5751a0e301e2 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Mon, 22 Apr 2019 21:17:19 +0100 Subject: [PATCH] Drop gradient channels, fix misconception about what gradient is --- dmc/hermite_value.h | 25 ++++++++---- dmc/voxel_mesher_dmc.cpp | 10 ++--- voxel_buffer.cpp | 82 ++-------------------------------------- voxel_buffer.h | 17 ++++++--- 4 files changed, 38 insertions(+), 96 deletions(-) diff --git a/dmc/hermite_value.h b/dmc/hermite_value.h index 01bd35f..355ed5e 100644 --- a/dmc/hermite_value.h +++ b/dmc/hermite_value.h @@ -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(Math::ceil(pos.y)); int z1 = static_cast(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); diff --git a/dmc/voxel_mesher_dmc.cpp b/dmc/voxel_mesher_dmc.cpp index 8c4ef8f..cf01023 100644 --- a/dmc/voxel_mesher_dmc.cpp +++ b/dmc/voxel_mesher_dmc.cpp @@ -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 /**/ diff --git a/voxel_buffer.cpp b/voxel_buffer.cpp index 835b23c..2e991a0 100644 --- a/voxel_buffer.cpp +++ b/voxel_buffer.cpp @@ -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); } diff --git a/voxel_buffer.h b/voxel_buffer.h index 796f66c..b428c2e 100644 --- a/voxel_buffer.h +++ b/voxel_buffer.h @@ -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(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);