diff --git a/SCsub b/SCsub index 5fd01100..07ad04ad 100644 --- a/SCsub +++ b/SCsub @@ -3,7 +3,7 @@ Import('env_modules') # TODO Support is turned off for now because Godot 3 doesn't compile with C++17. # FastNoise2 use C++17 features and STL both in its headers and runtime as well. -# SIMD noise support would have to wait for Godot 4... +# SIMD noise support would have to wait for Godot 4 (or GDNative port, which will only be worth in Godot 4 too) FAST_NOISE_2_SRC = False FAST_NOISE_2_STATIC = False @@ -63,7 +63,7 @@ if env["tools"]: if RUN_TESTS: voxel_files += [ - "tests/tests.cpp" + "tests/*.cpp" ] env_voxel.Append(CPPDEFINES={"VOXEL_RUN_TESTS": 0}) diff --git a/generators/graph/range_utility.cpp b/generators/graph/range_utility.cpp index 5ba6f9b7..836b3bcc 100644 --- a/generators/graph/range_utility.cpp +++ b/generators/graph/range_utility.cpp @@ -628,333 +628,3 @@ Interval3 get_fnl_gradient_range_3d(const FastNoiseLiteGradient *noise, Interval Interval{ z.min - amp, z.max + amp } }; } - -#ifdef DEBUG_ENABLED - -namespace NoiseTests { - -const int ITERATIONS = 1000000; -const int STEP_RESOLUTION_COUNT = 100; -const double STEP_MIN = 0.0001; -const double STEP_MAX = 0.01; - -enum Tests { - TEST_MIN_MAX = 1, - TEST_DERIVATIVES = 2 -}; - -// Sample a maximum change across the given step. -// The result is not normalized for performance. -template -FloatT get_derivative(FloatT x, FloatT y, FloatT step, F2 noise_func_2d) { - FloatT n0, n1, d; - FloatT max_derivative = 0.0; - - n0 = noise_func_2d(x, y); - - n1 = noise_func_2d(x + step, y); - d = Math::abs(n1 - n0); - if (d > max_derivative) { - max_derivative = d; - } - - n1 = noise_func_2d(x, y + step); - d = Math::abs(n1 - n0); - if (d > max_derivative) { - max_derivative = d; - } - - return max_derivative; -} - -template -FloatT get_derivative(FloatT x, FloatT y, FloatT z, FloatT step, F3 noise_func_3d) { - FloatT n0, n1, d; - FloatT max_derivative = 0.0; - - n0 = noise_func_3d(x, y, z); - - n1 = noise_func_3d(x + step, y, z); - d = Math::abs(n1 - n0); - if (d > max_derivative) { - max_derivative = d; - } - - n1 = noise_func_3d(x, y + step, z); - d = Math::abs(n1 - n0); - if (d > max_derivative) { - max_derivative = d; - } - - n1 = noise_func_3d(x, y, z + step); - d = Math::abs(n1 - n0); - if (d > max_derivative) { - max_derivative = d; - } - - return max_derivative; -} - -template -void test_min_max(F2 noise_func_2d, F3 noise_func_3d) { - FloatT min_value_2d = std::numeric_limits::max(); - FloatT max_value_2d = std::numeric_limits::min(); - - FloatT min_value_3d = std::numeric_limits::max(); - FloatT max_value_3d = std::numeric_limits::min(); - - for (int i = 0; i < ITERATIONS; ++i) { - FloatT x = Math::randd() * 2000.0 - 1000.0; - FloatT y = Math::randd() * 2000.0 - 1000.0; - FloatT z = Math::randd() * 2000.0 - 1000.0; - - FloatT n = noise_func_2d(x, y); - - min_value_2d = min(n, min_value_2d); - max_value_2d = max(n, max_value_2d); - - n = noise_func_3d(x, y, z); - - min_value_3d = min(n, min_value_3d); - max_value_3d = max(n, max_value_3d); - } - - print_line(String("2D | Min: {0}, Max: {1}").format(varray(min_value_2d, max_value_2d))); - print_line(String("3D | Min: {0}, Max: {1}").format(varray(min_value_3d, max_value_3d))); -} - -// Generic analysis for noise functions -template -void test_derivatives_tpl(F2 noise_func_2d, F3 noise_func_3d) { - const int iterations = ITERATIONS; - const int step_resolution_count = STEP_RESOLUTION_COUNT; - const FloatT step_min = STEP_MIN; - const FloatT step_max = STEP_MAX; - - print_line(String("Derivatives across step from {0} to {1}").format(varray(step_min, step_max))); - - const FloatT step_resolution_count_f = step_resolution_count; - - print_line(String("2D:").format(varray(step_min, step_max))); - - FloatT min_max_derivative = std::numeric_limits::max(); - - for (int j = 0; j < step_resolution_count; ++j) { - FloatT max_derivative = 0.0; - const FloatT step = Math::lerp(0.0001, 0.001, static_cast(j) / step_resolution_count_f); - - for (int i = 0; i < iterations; ++i) { - const FloatT x = Math::randd() * 2000.0 - 1000.0; - const FloatT y = Math::randd() * 2000.0 - 1000.0; - - FloatT d = get_derivative(x, y, step, noise_func_2d); - if (d > max_derivative) { - max_derivative = d; - } - } - - max_derivative /= step; - - print_line(String::num_real(max_derivative)); - - if (max_derivative < min_max_derivative) { - min_max_derivative = max_derivative; - } - } - - print_line(String("Min max derivative: {0}").format(varray(min_max_derivative))); - - print_line(String("3D:").format(varray(step_min, step_max))); - - min_max_derivative = std::numeric_limits::max(); - - for (int j = 0; j < step_resolution_count; ++j) { - FloatT max_derivative = 0.0; - const FloatT step = Math::lerp(0.0001, 0.001, static_cast(j) / step_resolution_count_f); - - for (int i = 0; i < iterations; ++i) { - const FloatT x = Math::randd() * 2000.0 - 1000.0; - const FloatT y = Math::randd() * 2000.0 - 1000.0; - const FloatT z = Math::randd() * 2000.0 - 1000.0; - - FloatT d = get_derivative(x, y, z, step, noise_func_3d); - if (d > max_derivative) { - max_derivative = d; - } - } - - max_derivative /= step; - - print_line(String::num_real(max_derivative)); - - if (max_derivative < min_max_derivative) { - min_max_derivative = max_derivative; - } - } - - print_line(String("Min max derivative: {0}").format(varray(min_max_derivative))); -} - -template -void test_derivatives_with_image(String fpath, double step, F3 noise_func_3d) { - const double x_min = 500.0; - const double y = 500.0; - const double z_min = 500.0; - - const int size_x = 512; - const int size_z = 512; - - const double image_step = 1.0; - - const double x_max = x_min + image_step; - const double z_max = z_min + image_step; - - const double min_value = 0.0; - const double max_value = 10.0; - - Ref im; - im.instance(); - im->create(size_x, size_z, false, Image::FORMAT_RGB8); - im->lock(); - - for (int py = 0; py < size_z; ++py) { - for (int px = 0; px < size_x; ++px) { - const double x = Math::lerp(x_min, x_max, static_cast(px) / static_cast(size_x)); - const double z = Math::lerp(z_min, z_max, static_cast(py) / static_cast(size_z)); - const double d = get_derivative(x, y, z, step, noise_func_3d) / step; - const double g = (d - min_value) / (max_value - min_value); - im->set_pixel(px, py, Color(g, g, g)); - } - } - - im->unlock(); - - print_line(String("Saving {0}").format(varray(fpath))); - im->save_png(fpath); -} - -template -void test_derivatives_with_image(String fname, int steps_resolution, F3 noise_func_3d) { - for (int i = 0; i < steps_resolution; ++i) { - const double step = - Math::lerp(STEP_MIN, STEP_MAX, static_cast(i) / static_cast(steps_resolution)); - String fpath = String("{0}_{1}.png").format(varray(fname, i)); - test_derivatives_with_image(fpath, step, noise_func_3d); - } -} - -template -void test_noise(String name, int tests, F2 noise_func_2d, F3 noise_func_3d) { - print_line(String("--- {0}:").format(varray(name))); - - if (tests & TEST_MIN_MAX) { - test_min_max(noise_func_2d, noise_func_3d); - } - if (tests & TEST_DERIVATIVES) { - test_derivatives_tpl(noise_func_2d, noise_func_3d); - test_derivatives_with_image(name + "_3D", 10, noise_func_3d); - } -} - -void test_fnl_noise(fast_noise_lite::FastNoiseLite &fnl, String name, int tests) { - test_noise( - name, tests, - [&fnl](double x, double y) { return fnl.GetNoise(x, y); }, - [&fnl](double x, double y, double z) { return fnl.GetNoise(x, y, z); }); -} - -void test_noises() { - Ref noise; - noise.instance(); - - fast_noise_lite::FastNoiseLite fn; - fn.SetFractalType(fast_noise_lite::FastNoiseLite::FractalType_None); - fn.SetFrequency(1.f); - - osn_context osn_ctx; - open_simplex_noise(131183, &osn_ctx); - - // According to OpenSimplex2 author, the 3D version is supposed to have a max derivative around 4.23718 - // https://www.wolframalpha.com/input/?i=max+d%2Fdx+32.69428253173828125+*+x+*+%28%280.6-x%5E2%29%5E4%29+from+-0.6+to+0.6 - // But empiric measures have shown it around 8. Discontinuities do exist in this noise though, - // which makes this measuring harder (and the reason why multiple step sizes are used) - - fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_OpenSimplex2); - test_fnl_noise(fn, "FNL_OpenSimplex2", TEST_MIN_MAX | TEST_DERIVATIVES); - - fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_OpenSimplex2S); - test_fnl_noise(fn, "FNL_OpenSimplex2S", TEST_MIN_MAX | TEST_DERIVATIVES); - - fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_Perlin); - test_fnl_noise(fn, "FNL_Perlin", TEST_MIN_MAX | TEST_DERIVATIVES); - - fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_Value); - test_fnl_noise(fn, "FNL Value", TEST_MIN_MAX | TEST_DERIVATIVES); - - // ValueCubic seems to be below -1..1 - // 2D | Min: -0.714547, Max: 0.742197 - // 3D | Min: -0.542093, Max: 0.499036 - fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_ValueCubic); - test_fnl_noise(fn, "FNL_ValueCubic", TEST_MIN_MAX | TEST_DERIVATIVES); - - fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_Cellular); - - const char *cell_distance_function_names[] = { - "Euclidean", - "EuclideanSq", - "Manhattan", - "Hybrid" - }; - const char *cell_return_type_names[] = { - "CellValue", - "Distance", - "Distance2", - "Distance2Add", - "Distance2Sub", - "Distance2Mul", - "Distance2Div" - }; - - for (int cell_distance_function = 0; cell_distance_function < 4; ++cell_distance_function) { - for (int cell_return_type = 0; cell_return_type < 7; ++cell_return_type) { - fn.SetCellularDistanceFunction( - static_cast(cell_distance_function)); - fn.SetCellularReturnType( - static_cast(cell_return_type)); - - const char *cell_distance_function_name = cell_distance_function_names[cell_distance_function]; - const char *cell_return_type_name = cell_return_type_names[cell_return_type]; - String noise_name = - String("FNL_Cellular_{0}_{1}").format(varray(cell_distance_function_name, cell_return_type_name)); - - const int jitter_resolution = 10; - - for (int i = 0; i < jitter_resolution; ++i) { - const double jitter = - Math::lerp(0.0, 1.0, static_cast(i) / static_cast(jitter_resolution)); - - fn.SetCellularJitter(jitter); - print_line(String("Cell jitter: {0}").format(varray(jitter))); - - test_fnl_noise(fn, noise_name, TEST_MIN_MAX); - } - } - } - - test_noise( - "OpenSimplex1", TEST_MIN_MAX | TEST_DERIVATIVES, - [&osn_ctx](double x, double y) { return open_simplex_noise2(&osn_ctx, x, y); }, - [&osn_ctx](double x, double y, double z) { return open_simplex_noise3(&osn_ctx, x, y, z); }); - - // Spreadsheet helper: - print_line("Steps:"); - for (int i = 0; i < STEP_RESOLUTION_COUNT; ++i) { - const double step = - Math::lerp(STEP_MIN, STEP_MAX, static_cast(i) / static_cast(STEP_RESOLUTION_COUNT)); - print_line(String::num_real(step)); - } -} - -} // namespace NoiseTests - -#endif diff --git a/generators/graph/range_utility.h b/generators/graph/range_utility.h index a293ab08..e2ddca1e 100644 --- a/generators/graph/range_utility.h +++ b/generators/graph/range_utility.h @@ -63,12 +63,4 @@ Interval get_fnl_range_3d(const FastNoiseLite *noise, Interval x, Interval y, In Interval2 get_fnl_gradient_range_2d(const FastNoiseLiteGradient *noise, Interval x, Interval y); Interval3 get_fnl_gradient_range_3d(const FastNoiseLiteGradient *noise, Interval x, Interval y, Interval z); -#ifdef DEBUG_ENABLED -namespace NoiseTests { - -void test_noises(); - -} // namespace NoiseTests -#endif - #endif // RANGE_UTILITY_H diff --git a/tests/noise_tests.cpp b/tests/noise_tests.cpp new file mode 100644 index 00000000..cb098214 --- /dev/null +++ b/tests/noise_tests.cpp @@ -0,0 +1,339 @@ +#include "../util/math/funcs.h" +#include "../util/noise/fast_noise_lite.h" +#include "tests.h" + +#include +#include + +namespace NoiseTests { + +const int ITERATIONS = 1000000; +const int STEP_RESOLUTION_COUNT = 100; +const double STEP_MIN = 0.0001; +const double STEP_MAX = 0.01; + +enum Tests { + TEST_MIN_MAX = 1, + TEST_DERIVATIVES = 2 +}; + +// Sample a maximum change across the given step. +// The result is not normalized for performance. +template +FloatT get_derivative(FloatT x, FloatT y, FloatT step, F2 noise_func_2d) { + FloatT n0, n1, d; + FloatT max_derivative = 0.0; + + n0 = noise_func_2d(x, y); + + n1 = noise_func_2d(x + step, y); + d = Math::abs(n1 - n0); + if (d > max_derivative) { + max_derivative = d; + } + + n1 = noise_func_2d(x, y + step); + d = Math::abs(n1 - n0); + if (d > max_derivative) { + max_derivative = d; + } + + return max_derivative; +} + +template +FloatT get_derivative(FloatT x, FloatT y, FloatT z, FloatT step, F3 noise_func_3d) { + FloatT n0, n1, d; + FloatT max_derivative = 0.0; + + n0 = noise_func_3d(x, y, z); + + n1 = noise_func_3d(x + step, y, z); + d = Math::abs(n1 - n0); + if (d > max_derivative) { + max_derivative = d; + } + + n1 = noise_func_3d(x, y + step, z); + d = Math::abs(n1 - n0); + if (d > max_derivative) { + max_derivative = d; + } + + n1 = noise_func_3d(x, y, z + step); + d = Math::abs(n1 - n0); + if (d > max_derivative) { + max_derivative = d; + } + + return max_derivative; +} + +template +void test_min_max(F2 noise_func_2d, F3 noise_func_3d) { + FloatT min_value_2d = std::numeric_limits::max(); + FloatT max_value_2d = std::numeric_limits::min(); + + FloatT min_value_3d = std::numeric_limits::max(); + FloatT max_value_3d = std::numeric_limits::min(); + + for (int i = 0; i < ITERATIONS; ++i) { + FloatT x = Math::randd() * 2000.0 - 1000.0; + FloatT y = Math::randd() * 2000.0 - 1000.0; + FloatT z = Math::randd() * 2000.0 - 1000.0; + + FloatT n = noise_func_2d(x, y); + + min_value_2d = min(n, min_value_2d); + max_value_2d = max(n, max_value_2d); + + n = noise_func_3d(x, y, z); + + min_value_3d = min(n, min_value_3d); + max_value_3d = max(n, max_value_3d); + } + + print_line(String("2D | Min: {0}, Max: {1}").format(varray(min_value_2d, max_value_2d))); + print_line(String("3D | Min: {0}, Max: {1}").format(varray(min_value_3d, max_value_3d))); +} + +// Generic analysis for noise functions +template +void test_derivatives_tpl(F2 noise_func_2d, F3 noise_func_3d) { + const int iterations = ITERATIONS; + const int step_resolution_count = STEP_RESOLUTION_COUNT; + const FloatT step_min = STEP_MIN; + const FloatT step_max = STEP_MAX; + + print_line(String("Derivatives across step from {0} to {1}").format(varray(step_min, step_max))); + + const FloatT step_resolution_count_f = step_resolution_count; + + print_line(String("2D:").format(varray(step_min, step_max))); + + FloatT min_max_derivative = std::numeric_limits::max(); + + for (int j = 0; j < step_resolution_count; ++j) { + FloatT max_derivative = 0.0; + const FloatT step = Math::lerp(0.0001, 0.001, static_cast(j) / step_resolution_count_f); + + for (int i = 0; i < iterations; ++i) { + const FloatT x = Math::randd() * 2000.0 - 1000.0; + const FloatT y = Math::randd() * 2000.0 - 1000.0; + + FloatT d = get_derivative(x, y, step, noise_func_2d); + if (d > max_derivative) { + max_derivative = d; + } + } + + max_derivative /= step; + + print_line(String::num_real(max_derivative)); + + if (max_derivative < min_max_derivative) { + min_max_derivative = max_derivative; + } + } + + print_line(String("Min max derivative: {0}").format(varray(min_max_derivative))); + + print_line(String("3D:").format(varray(step_min, step_max))); + + min_max_derivative = std::numeric_limits::max(); + + for (int j = 0; j < step_resolution_count; ++j) { + FloatT max_derivative = 0.0; + const FloatT step = Math::lerp(0.0001, 0.001, static_cast(j) / step_resolution_count_f); + + for (int i = 0; i < iterations; ++i) { + const FloatT x = Math::randd() * 2000.0 - 1000.0; + const FloatT y = Math::randd() * 2000.0 - 1000.0; + const FloatT z = Math::randd() * 2000.0 - 1000.0; + + FloatT d = get_derivative(x, y, z, step, noise_func_3d); + if (d > max_derivative) { + max_derivative = d; + } + } + + max_derivative /= step; + + print_line(String::num_real(max_derivative)); + + if (max_derivative < min_max_derivative) { + min_max_derivative = max_derivative; + } + } + + print_line(String("Min max derivative: {0}").format(varray(min_max_derivative))); +} + +template +void test_derivatives_with_image(String fpath, double step, F3 noise_func_3d) { + const double x_min = 500.0; + const double y = 500.0; + const double z_min = 500.0; + + const int size_x = 512; + const int size_z = 512; + + const double image_step = 1.0; + + const double x_max = x_min + image_step; + const double z_max = z_min + image_step; + + const double min_value = 0.0; + const double max_value = 10.0; + + Ref im; + im.instance(); + im->create(size_x, size_z, false, Image::FORMAT_RGB8); + im->lock(); + + for (int py = 0; py < size_z; ++py) { + for (int px = 0; px < size_x; ++px) { + const double x = Math::lerp(x_min, x_max, static_cast(px) / static_cast(size_x)); + const double z = Math::lerp(z_min, z_max, static_cast(py) / static_cast(size_z)); + const double d = get_derivative(x, y, z, step, noise_func_3d) / step; + const double g = (d - min_value) / (max_value - min_value); + im->set_pixel(px, py, Color(g, g, g)); + } + } + + im->unlock(); + + print_line(String("Saving {0}").format(varray(fpath))); + im->save_png(fpath); +} + +template +void test_derivatives_with_image(String fname, int steps_resolution, F3 noise_func_3d) { + for (int i = 0; i < steps_resolution; ++i) { + const double step = + Math::lerp(STEP_MIN, STEP_MAX, static_cast(i) / static_cast(steps_resolution)); + String fpath = String("{0}_{1}.png").format(varray(fname, i)); + test_derivatives_with_image(fpath, step, noise_func_3d); + } +} + +template +void test_noise(String name, int tests, F2 noise_func_2d, F3 noise_func_3d) { + print_line(String("--- {0}:").format(varray(name))); + + if (tests & TEST_MIN_MAX) { + test_min_max(noise_func_2d, noise_func_3d); + } + if (tests & TEST_DERIVATIVES) { + test_derivatives_tpl(noise_func_2d, noise_func_3d); + test_derivatives_with_image(name + "_3D", 10, noise_func_3d); + } +} + +void test_fnl_noise(fast_noise_lite::FastNoiseLite &fnl, String name, int tests) { + test_noise( + name, tests, + [&fnl](double x, double y) { return fnl.GetNoise(x, y); }, + [&fnl](double x, double y, double z) { return fnl.GetNoise(x, y, z); }); +} + +void test_noises() { + Ref noise; + noise.instance(); + + fast_noise_lite::FastNoiseLite fn; + fn.SetFractalType(fast_noise_lite::FastNoiseLite::FractalType_None); + fn.SetFrequency(1.f); + + osn_context osn_ctx; + open_simplex_noise(131183, &osn_ctx); + + // According to OpenSimplex2 author, the 3D version is supposed to have a max derivative around 4.23718 + // https://www.wolframalpha.com/input/?i=max+d%2Fdx+32.69428253173828125+*+x+*+%28%280.6-x%5E2%29%5E4%29+from+-0.6+to+0.6 + // But empiric measures have shown it around 8. Discontinuities do exist in this noise though, + // which makes this measuring harder (and the reason why multiple step sizes are used) + + fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_OpenSimplex2); + test_fnl_noise(fn, "FNL_OpenSimplex2", TEST_MIN_MAX | TEST_DERIVATIVES); + + fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_OpenSimplex2S); + test_fnl_noise(fn, "FNL_OpenSimplex2S", TEST_MIN_MAX | TEST_DERIVATIVES); + + fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_Perlin); + test_fnl_noise(fn, "FNL_Perlin", TEST_MIN_MAX | TEST_DERIVATIVES); + + fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_Value); + test_fnl_noise(fn, "FNL Value", TEST_MIN_MAX | TEST_DERIVATIVES); + + // ValueCubic seems to be below -1..1 + // 2D | Min: -0.714547, Max: 0.742197 + // 3D | Min: -0.542093, Max: 0.499036 + fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_ValueCubic); + test_fnl_noise(fn, "FNL_ValueCubic", TEST_MIN_MAX | TEST_DERIVATIVES); + + fn.SetNoiseType(fast_noise_lite::FastNoiseLite::NoiseType_Cellular); + + const char *cell_distance_function_names[] = { + "Euclidean", + "EuclideanSq", + "Manhattan", + "Hybrid" + }; + const char *cell_return_type_names[] = { + "CellValue", + "Distance", + "Distance2", + "Distance2Add", + "Distance2Sub", + "Distance2Mul", + "Distance2Div" + }; + + for (int cell_distance_function = 0; cell_distance_function < 4; ++cell_distance_function) { + for (int cell_return_type = 0; cell_return_type < 7; ++cell_return_type) { + fn.SetCellularDistanceFunction( + static_cast(cell_distance_function)); + fn.SetCellularReturnType( + static_cast(cell_return_type)); + + const char *cell_distance_function_name = cell_distance_function_names[cell_distance_function]; + const char *cell_return_type_name = cell_return_type_names[cell_return_type]; + String noise_name = + String("FNL_Cellular_{0}_{1}").format(varray(cell_distance_function_name, cell_return_type_name)); + + const int jitter_resolution = 10; + + for (int i = 0; i < jitter_resolution; ++i) { + const double jitter = + Math::lerp(0.0, 1.0, static_cast(i) / static_cast(jitter_resolution)); + + fn.SetCellularJitter(jitter); + print_line(String("Cell jitter: {0}").format(varray(jitter))); + + test_fnl_noise(fn, noise_name, TEST_MIN_MAX); + } + } + } + + test_noise( + "OpenSimplex1", TEST_MIN_MAX | TEST_DERIVATIVES, + [&osn_ctx](double x, double y) { return open_simplex_noise2(&osn_ctx, x, y); }, + [&osn_ctx](double x, double y, double z) { return open_simplex_noise3(&osn_ctx, x, y, z); }); + + // Spreadsheet helper: + print_line("Steps:"); + for (int i = 0; i < STEP_RESOLUTION_COUNT; ++i) { + const double step = + Math::lerp(STEP_MIN, STEP_MAX, static_cast(i) / static_cast(STEP_RESOLUTION_COUNT)); + print_line(String::num_real(step)); + } +} + +} // namespace NoiseTests + +// These are not actually unit tests, but rather analysis. They could be used with tests in the future, but +// it can be relatively hard for derivatives because empiric tests may bump on irregularities causing false-positives, +// so for now derivative ranges are estimated manually from the results +void run_noise_tests() { + NoiseTests::test_noises(); +} diff --git a/tests/tests.h b/tests/tests.h index 844d7f41..4830581e 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -2,5 +2,6 @@ #define VOXEL_TESTS_H void run_voxel_tests(); +void run_noise_tests(); #endif // VOXEL_TESTS_H