Better trilinear interpolation
This commit is contained in:
parent
d145a30816
commit
2f2ab384a6
@ -41,7 +41,7 @@ float get_sdf_interpolated(const Volume_F &f, Vector3 pos) {
|
||||
const float s011 = f(Vector3i(c.x, c.y + 1, c.z + 1));
|
||||
const float s111 = f(Vector3i(c.x + 1, c.y + 1, c.z + 1));
|
||||
|
||||
return math::interpolate(s000, s100, s101, s001, s010, s110, s111, s011, to_vec3f(math::fract(pos)));
|
||||
return math::interpolate_trilinear(s000, s100, s101, s001, s010, s110, s111, s011, to_vec3f(math::fract(pos)));
|
||||
}
|
||||
|
||||
// Binary search can be more accurate than linear regression because the SDF can be inaccurate in the first place.
|
||||
|
@ -67,9 +67,9 @@ inline HermiteValue get_interpolated_hermite_value(const VoxelBufferInternal &vo
|
||||
Vector3f rpos = pos - Vector3f(x0, y0, z0);
|
||||
|
||||
HermiteValue v;
|
||||
v.sdf = math::interpolate(v0.sdf, v1.sdf, v2.sdf, v3.sdf, v4.sdf, v5.sdf, v6.sdf, v7.sdf, rpos);
|
||||
v.gradient = math::interpolate(v0.gradient, v1.gradient, v2.gradient, v3.gradient, v4.gradient, v5.gradient,
|
||||
v6.gradient, v7.gradient, rpos);
|
||||
v.sdf = math::interpolate_trilinear(v0.sdf, v1.sdf, v2.sdf, v3.sdf, v4.sdf, v5.sdf, v6.sdf, v7.sdf, rpos);
|
||||
v.gradient = math::interpolate_trilinear(v0.gradient, v1.gradient, v2.gradient, v3.gradient, v4.gradient,
|
||||
v5.gradient, v6.gradient, v7.gradient, rpos);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ bool can_split(Vector3i node_origin, int node_size, const VoxelAccess &voxels, f
|
||||
|
||||
HermiteValue value = get_hermite_value(voxels.buffer, pos.x, pos.y, pos.z);
|
||||
|
||||
float interpolated_value = math::interpolate(v0, v1, v2, v3, v4, v5, v6, v7, positions_ratio[i]);
|
||||
float interpolated_value = math::interpolate_trilinear(v0, v1, v2, v3, v4, v5, v6, v7, positions_ratio[i]);
|
||||
|
||||
float gradient_magnitude = value.gradient.length();
|
||||
if (gradient_magnitude < FLT_EPSILON) {
|
||||
|
@ -179,7 +179,9 @@ inline Vector3f operator*(float p_scalar, const Vector3f &v) {
|
||||
|
||||
namespace math {
|
||||
|
||||
// Trilinear interpolation between corner values of a cube.
|
||||
// Trilinear interpolation between corner values of a unit-sized cube.
|
||||
// `v***` arguments are corner values named as `vXYZ`, where a coordinate is 0 or 1 on the cube.
|
||||
// Coordinates of `p` are in 0..1, but are not clamped so extrapolation is possible.
|
||||
//
|
||||
// 6---------------7
|
||||
// /| /|
|
||||
@ -193,20 +195,23 @@ namespace math {
|
||||
// |/ |/ |/
|
||||
// 1---------------0 X----o
|
||||
//
|
||||
// p000, p100, p101, p001, p010, p110, p111, p011
|
||||
template <typename T>
|
||||
inline T interpolate(const T v0, const T v1, const T v2, const T v3, const T v4, const T v5, const T v6, const T v7,
|
||||
Vector3f position) {
|
||||
const float one_min_x = 1.f - position.x;
|
||||
const float one_min_y = 1.f - position.y;
|
||||
const float one_min_z = 1.f - position.z;
|
||||
const float one_min_x_one_min_y = one_min_x * one_min_y;
|
||||
const float x_one_min_y = position.x * one_min_y;
|
||||
inline T interpolate_trilinear(const T v000, const T v100, const T v101, const T v001, const T v010, const T v110,
|
||||
const T v111, const T v011, Vector3f p) {
|
||||
//
|
||||
const T v00 = v000 + p.x * (v100 - v000);
|
||||
const T v10 = v010 + p.x * (v110 - v010);
|
||||
const T v01 = v001 + p.x * (v101 - v001);
|
||||
const T v11 = v011 + p.x * (v111 - v011);
|
||||
|
||||
T res = one_min_z * (v0 * one_min_x_one_min_y + v1 * x_one_min_y + v4 * one_min_x * position.y);
|
||||
res += position.z * (v3 * one_min_x_one_min_y + v2 * x_one_min_y + v7 * one_min_x * position.y);
|
||||
res += position.x * position.y * (v5 * one_min_z + v6 * position.z);
|
||||
const T v0 = v00 + p.y * (v10 - v00);
|
||||
const T v1 = v01 + p.y * (v11 - v01);
|
||||
|
||||
return res;
|
||||
const T v = v0 + p.z * (v1 - v0);
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
|
Loading…
x
Reference in New Issue
Block a user