Drop gradient channels, fix misconception about what gradient is

This commit is contained in:
Marc Gilleron 2019-04-22 21:17:19 +01:00
parent 572dcbf680
commit bed8ac8cb9
4 changed files with 38 additions and 96 deletions

View File

@ -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);

View File

@ -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 /**/

View File

@ -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);
}

View File

@ -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);