Path: blob/master/modules/noise/tests/test_fastnoise_lite.h
10278 views
/**************************************************************************/1/* test_fastnoise_lite.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "../fastnoise_lite.h"3334#include "tests/test_macros.h"3536namespace TestFastNoiseLite {3738// Uitility functions for finding differences in noise generation3940bool all_equal_approx(const Vector<real_t> &p_values_1, const Vector<real_t> &p_values_2) {41ERR_FAIL_COND_V_MSG(p_values_1.size() != p_values_2.size(), false, "Arrays must be the same size. This is a error in the test code.");4243for (int i = 0; i < p_values_1.size(); i++) {44if (!Math::is_equal_approx(p_values_1[i], p_values_2[i])) {45return false;46}47}48return true;49}5051Vector<Pair<size_t, size_t>> find_approx_equal_vec_pairs(std::initializer_list<Vector<real_t>> inputs) {52Vector<Vector<real_t>> p_array = Vector<Vector<real_t>>(inputs);5354Vector<Pair<size_t, size_t>> result;55for (int i = 0; i < p_array.size(); i++) {56for (int j = i + 1; j < p_array.size(); j++) {57if (all_equal_approx(p_array[i], p_array[j])) {58result.push_back(Pair<size_t, size_t>(i, j));59}60}61}62return result;63}6465#define CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(...) \66{ \67Vector<Pair<size_t, size_t>> equal_pairs = find_approx_equal_vec_pairs({ __VA_ARGS__ }); \68for (Pair<size_t, size_t> p : equal_pairs) { \69MESSAGE("Argument with index ", p.first, " is approximately equal to argument with index ", p.second); \70} \71CHECK_MESSAGE(equal_pairs.size() == 0, "All arguments should be pairwise distinct."); \72}7374Vector<real_t> get_noise_samples_1d(const FastNoiseLite &p_noise, size_t p_count = 32) {75Vector<real_t> result;76result.resize(p_count);77for (size_t i = 0; i < p_count; i++) {78result.write[i] = p_noise.get_noise_1d(i);79}80return result;81}8283Vector<real_t> get_noise_samples_2d(const FastNoiseLite &p_noise, size_t p_count = 32) {84Vector<real_t> result;85result.resize(p_count);86for (size_t i = 0; i < p_count; i++) {87result.write[i] = p_noise.get_noise_2d(i, i);88}89return result;90}9192Vector<real_t> get_noise_samples_3d(const FastNoiseLite &p_noise, size_t p_count = 32) {93Vector<real_t> result;94result.resize(p_count);95for (size_t i = 0; i < p_count; i++) {96result.write[i] = p_noise.get_noise_3d(i, i, i);97}98return result;99}100101// The following test suite is rather for testing the wrapper code than the actual noise generation.102103TEST_CASE("[FastNoiseLite] Getter and setter") {104FastNoiseLite noise;105106noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX_SMOOTH);107CHECK(noise.get_noise_type() == FastNoiseLite::NoiseType::TYPE_SIMPLEX_SMOOTH);108109noise.set_seed(123);110CHECK(noise.get_seed() == 123);111112noise.set_frequency(0.123);113CHECK(noise.get_frequency() == doctest::Approx(0.123));114115noise.set_offset(Vector3(1, 2, 3));116CHECK(noise.get_offset() == Vector3(1, 2, 3));117118noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_PING_PONG);119CHECK(noise.get_fractal_type() == FastNoiseLite::FractalType::FRACTAL_PING_PONG);120121noise.set_fractal_octaves(2);122CHECK(noise.get_fractal_octaves() == 2);123124noise.set_fractal_lacunarity(1.123);125CHECK(noise.get_fractal_lacunarity() == doctest::Approx(1.123));126127noise.set_fractal_gain(0.123);128CHECK(noise.get_fractal_gain() == doctest::Approx(0.123));129130noise.set_fractal_weighted_strength(0.123);131CHECK(noise.get_fractal_weighted_strength() == doctest::Approx(0.123));132133noise.set_fractal_ping_pong_strength(0.123);134CHECK(noise.get_fractal_ping_pong_strength() == doctest::Approx(0.123));135136noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_MANHATTAN);137CHECK(noise.get_cellular_distance_function() == FastNoiseLite::CellularDistanceFunction::DISTANCE_MANHATTAN);138139noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_SUB);140CHECK(noise.get_cellular_return_type() == FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_SUB);141142noise.set_cellular_jitter(0.123);143CHECK(noise.get_cellular_jitter() == doctest::Approx(0.123));144145noise.set_domain_warp_enabled(true);146CHECK(noise.is_domain_warp_enabled() == true);147noise.set_domain_warp_enabled(false);148CHECK(noise.is_domain_warp_enabled() == false);149150noise.set_domain_warp_type(FastNoiseLite::DomainWarpType::DOMAIN_WARP_SIMPLEX_REDUCED);151CHECK(noise.get_domain_warp_type() == FastNoiseLite::DomainWarpType::DOMAIN_WARP_SIMPLEX_REDUCED);152153noise.set_domain_warp_amplitude(0.123);154CHECK(noise.get_domain_warp_amplitude() == doctest::Approx(0.123));155156noise.set_domain_warp_frequency(0.123);157CHECK(noise.get_domain_warp_frequency() == doctest::Approx(0.123));158159noise.set_domain_warp_fractal_type(FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_INDEPENDENT);160CHECK(noise.get_domain_warp_fractal_type() == FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_INDEPENDENT);161162noise.set_domain_warp_fractal_octaves(2);163CHECK(noise.get_domain_warp_fractal_octaves() == 2);164165noise.set_domain_warp_fractal_lacunarity(1.123);166CHECK(noise.get_domain_warp_fractal_lacunarity() == doctest::Approx(1.123));167168noise.set_domain_warp_fractal_gain(0.123);169CHECK(noise.get_domain_warp_fractal_gain() == doctest::Approx(0.123));170}171172TEST_CASE("[FastNoiseLite] Basic noise generation") {173FastNoiseLite noise;174noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);175noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_NONE);176noise.set_seed(123);177noise.set_offset(Vector3(10, 10, 10));178179// 1D noise will be checked just in the cases where there's the possibility of180// finding a bug/regression in the wrapper function.181// (since it uses FastNoise's 2D noise generator with the Y coordinate set to 0).182183SUBCASE("Determinacy of noise generation (all noise types)") {184noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);185CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));186CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));187noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX_SMOOTH);188CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));189CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));190noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_CELLULAR);191CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));192CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));193noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_PERLIN);194CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));195CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));196noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_VALUE);197CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));198CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));199noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_VALUE_CUBIC);200CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));201CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));202}203204SUBCASE("Different seeds should produce different noise") {205noise.set_seed(456);206Vector<real_t> noise_seed_1_1d = get_noise_samples_1d(noise);207Vector<real_t> noise_seed_1_2d = get_noise_samples_2d(noise);208Vector<real_t> noise_seed_1_3d = get_noise_samples_3d(noise);209noise.set_seed(123);210Vector<real_t> noise_seed_2_1d = get_noise_samples_1d(noise);211Vector<real_t> noise_seed_2_2d = get_noise_samples_2d(noise);212Vector<real_t> noise_seed_2_3d = get_noise_samples_3d(noise);213214CHECK_FALSE(all_equal_approx(noise_seed_1_1d, noise_seed_2_1d));215CHECK_FALSE(all_equal_approx(noise_seed_1_2d, noise_seed_2_2d));216CHECK_FALSE(all_equal_approx(noise_seed_1_3d, noise_seed_2_3d));217}218219SUBCASE("Different frequencies should produce different noise") {220noise.set_frequency(0.1);221Vector<real_t> noise_frequency_1_1d = get_noise_samples_1d(noise);222Vector<real_t> noise_frequency_1_2d = get_noise_samples_2d(noise);223Vector<real_t> noise_frequency_1_3d = get_noise_samples_3d(noise);224noise.set_frequency(1.0);225Vector<real_t> noise_frequency_2_1d = get_noise_samples_1d(noise);226Vector<real_t> noise_frequency_2_2d = get_noise_samples_2d(noise);227Vector<real_t> noise_frequency_2_3d = get_noise_samples_3d(noise);228229CHECK_FALSE(all_equal_approx(noise_frequency_1_1d, noise_frequency_2_1d));230CHECK_FALSE(all_equal_approx(noise_frequency_1_2d, noise_frequency_2_2d));231CHECK_FALSE(all_equal_approx(noise_frequency_1_3d, noise_frequency_2_3d));232}233234SUBCASE("Noise should be offset by the offset parameter") {235noise.set_offset(Vector3(1, 2, 3));236Vector<real_t> noise_offset_1_1d = get_noise_samples_1d(noise);237Vector<real_t> noise_offset_1_2d = get_noise_samples_2d(noise);238Vector<real_t> noise_offset_1_3d = get_noise_samples_3d(noise);239noise.set_offset(Vector3(4, 5, 6));240Vector<real_t> noise_offset_2_1d = get_noise_samples_1d(noise);241Vector<real_t> noise_offset_2_2d = get_noise_samples_2d(noise);242Vector<real_t> noise_offset_2_3d = get_noise_samples_3d(noise);243244CHECK_FALSE(all_equal_approx(noise_offset_1_1d, noise_offset_2_1d));245CHECK_FALSE(all_equal_approx(noise_offset_1_2d, noise_offset_2_2d));246CHECK_FALSE(all_equal_approx(noise_offset_1_3d, noise_offset_2_3d));247}248249SUBCASE("Different noise types should produce different noise") {250noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);251Vector<real_t> noise_type_simplex_2d = get_noise_samples_2d(noise);252Vector<real_t> noise_type_simplex_3d = get_noise_samples_3d(noise);253noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX_SMOOTH);254Vector<real_t> noise_type_simplex_smooth_2d = get_noise_samples_2d(noise);255Vector<real_t> noise_type_simplex_smooth_3d = get_noise_samples_3d(noise);256noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_CELLULAR);257Vector<real_t> noise_type_cellular_2d = get_noise_samples_2d(noise);258Vector<real_t> noise_type_cellular_3d = get_noise_samples_3d(noise);259noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_PERLIN);260Vector<real_t> noise_type_perlin_2d = get_noise_samples_2d(noise);261Vector<real_t> noise_type_perlin_3d = get_noise_samples_3d(noise);262noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_VALUE);263Vector<real_t> noise_type_value_2d = get_noise_samples_2d(noise);264Vector<real_t> noise_type_value_3d = get_noise_samples_3d(noise);265noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_VALUE_CUBIC);266Vector<real_t> noise_type_value_cubic_2d = get_noise_samples_2d(noise);267Vector<real_t> noise_type_value_cubic_3d = get_noise_samples_3d(noise);268269CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(noise_type_simplex_2d,270noise_type_simplex_smooth_2d,271noise_type_cellular_2d,272noise_type_perlin_2d,273noise_type_value_2d,274noise_type_value_cubic_2d);275276CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(noise_type_simplex_3d,277noise_type_simplex_smooth_3d,278noise_type_cellular_3d,279noise_type_perlin_3d,280noise_type_value_3d,281noise_type_value_cubic_3d);282}283}284285TEST_CASE("[FastNoiseLite] Fractal noise") {286FastNoiseLite noise;287noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);288noise.set_offset(Vector3(10, 10, 10));289noise.set_frequency(0.01);290noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_FBM);291noise.set_fractal_octaves(4);292noise.set_fractal_lacunarity(2.0);293noise.set_fractal_gain(0.5);294noise.set_fractal_weighted_strength(0.5);295noise.set_fractal_ping_pong_strength(2.0);296297SUBCASE("Different fractal types should produce different results") {298noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_NONE);299Vector<real_t> fractal_type_none_2d = get_noise_samples_2d(noise);300Vector<real_t> fractal_type_none_3d = get_noise_samples_3d(noise);301noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_FBM);302Vector<real_t> fractal_type_fbm_2d = get_noise_samples_2d(noise);303Vector<real_t> fractal_type_fbm_3d = get_noise_samples_3d(noise);304noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_RIDGED);305Vector<real_t> fractal_type_ridged_2d = get_noise_samples_2d(noise);306Vector<real_t> fractal_type_ridged_3d = get_noise_samples_3d(noise);307noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_PING_PONG);308Vector<real_t> fractal_type_ping_pong_2d = get_noise_samples_2d(noise);309Vector<real_t> fractal_type_ping_pong_3d = get_noise_samples_3d(noise);310311CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(fractal_type_none_2d,312fractal_type_fbm_2d,313fractal_type_ridged_2d,314fractal_type_ping_pong_2d);315316CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(fractal_type_none_3d,317fractal_type_fbm_3d,318fractal_type_ridged_3d,319fractal_type_ping_pong_3d);320}321322SUBCASE("Different octaves should produce different results") {323noise.set_fractal_octaves(1.0);324Vector<real_t> fractal_octaves_1_2d = get_noise_samples_2d(noise);325Vector<real_t> fractal_octaves_1_3d = get_noise_samples_3d(noise);326noise.set_fractal_octaves(8.0);327Vector<real_t> fractal_octaves_2_2d = get_noise_samples_2d(noise);328Vector<real_t> fractal_octaves_2_3d = get_noise_samples_3d(noise);329330CHECK_FALSE(all_equal_approx(fractal_octaves_1_2d, fractal_octaves_2_2d));331CHECK_FALSE(all_equal_approx(fractal_octaves_1_3d, fractal_octaves_2_3d));332}333334SUBCASE("Different lacunarity should produce different results") {335noise.set_fractal_lacunarity(1.0);336Vector<real_t> fractal_lacunarity_1_2d = get_noise_samples_2d(noise);337Vector<real_t> fractal_lacunarity_1_3d = get_noise_samples_3d(noise);338noise.set_fractal_lacunarity(2.0);339Vector<real_t> fractal_lacunarity_2_2d = get_noise_samples_2d(noise);340Vector<real_t> fractal_lacunarity_2_3d = get_noise_samples_3d(noise);341342CHECK_FALSE(all_equal_approx(fractal_lacunarity_1_2d, fractal_lacunarity_2_2d));343CHECK_FALSE(all_equal_approx(fractal_lacunarity_1_3d, fractal_lacunarity_2_3d));344}345346SUBCASE("Different gain should produce different results") {347noise.set_fractal_gain(0.5);348Vector<real_t> fractal_gain_1_2d = get_noise_samples_2d(noise);349Vector<real_t> fractal_gain_1_3d = get_noise_samples_3d(noise);350noise.set_fractal_gain(0.75);351Vector<real_t> fractal_gain_2_2d = get_noise_samples_2d(noise);352Vector<real_t> fractal_gain_2_3d = get_noise_samples_3d(noise);353354CHECK_FALSE(all_equal_approx(fractal_gain_1_2d, fractal_gain_2_2d));355CHECK_FALSE(all_equal_approx(fractal_gain_1_3d, fractal_gain_2_3d));356}357358SUBCASE("Different weights should produce different results") {359noise.set_fractal_weighted_strength(0.5);360Vector<real_t> fractal_weighted_strength_1_2d = get_noise_samples_2d(noise);361Vector<real_t> fractal_weighted_strength_1_3d = get_noise_samples_3d(noise);362noise.set_fractal_weighted_strength(0.75);363Vector<real_t> fractal_weighted_strength_2_2d = get_noise_samples_2d(noise);364Vector<real_t> fractal_weighted_strength_2_3d = get_noise_samples_3d(noise);365366CHECK_FALSE(all_equal_approx(fractal_weighted_strength_1_2d, fractal_weighted_strength_2_2d));367CHECK_FALSE(all_equal_approx(fractal_weighted_strength_1_3d, fractal_weighted_strength_2_3d));368}369370SUBCASE("Different ping pong strength should produce different results") {371noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_PING_PONG);372noise.set_fractal_ping_pong_strength(0.5);373Vector<real_t> fractal_ping_pong_strength_1_2d = get_noise_samples_2d(noise);374Vector<real_t> fractal_ping_pong_strength_1_3d = get_noise_samples_3d(noise);375noise.set_fractal_ping_pong_strength(0.75);376Vector<real_t> fractal_ping_pong_strength_2_2d = get_noise_samples_2d(noise);377Vector<real_t> fractal_ping_pong_strength_2_3d = get_noise_samples_3d(noise);378379CHECK_FALSE(all_equal_approx(fractal_ping_pong_strength_1_2d, fractal_ping_pong_strength_2_2d));380CHECK_FALSE(all_equal_approx(fractal_ping_pong_strength_1_3d, fractal_ping_pong_strength_2_3d));381}382}383384TEST_CASE("[FastNoiseLite] Cellular noise") {385FastNoiseLite noise;386noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_NONE);387noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_CELLULAR);388noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_EUCLIDEAN);389noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE);390noise.set_frequency(1.0);391392SUBCASE("Different distance functions should produce different results") {393noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_EUCLIDEAN);394Vector<real_t> cellular_distance_function_euclidean_2d = get_noise_samples_2d(noise);395Vector<real_t> cellular_distance_function_euclidean_3d = get_noise_samples_3d(noise);396noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_EUCLIDEAN_SQUARED);397Vector<real_t> cellular_distance_function_euclidean_squared_2d = get_noise_samples_2d(noise);398Vector<real_t> cellular_distance_function_euclidean_squared_3d = get_noise_samples_3d(noise);399noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_MANHATTAN);400Vector<real_t> cellular_distance_function_manhattan_2d = get_noise_samples_2d(noise);401Vector<real_t> cellular_distance_function_manhattan_3d = get_noise_samples_3d(noise);402noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_HYBRID);403Vector<real_t> cellular_distance_function_hybrid_2d = get_noise_samples_2d(noise);404Vector<real_t> cellular_distance_function_hybrid_3d = get_noise_samples_3d(noise);405406CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(cellular_distance_function_euclidean_2d,407cellular_distance_function_euclidean_squared_2d,408cellular_distance_function_manhattan_2d,409cellular_distance_function_hybrid_2d);410411CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(cellular_distance_function_euclidean_3d,412cellular_distance_function_euclidean_squared_3d,413cellular_distance_function_manhattan_3d,414cellular_distance_function_hybrid_3d);415}416417SUBCASE("Different return function types should produce different results") {418noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_CELL_VALUE);419Vector<real_t> cellular_return_type_cell_value_2d = get_noise_samples_2d(noise);420Vector<real_t> cellular_return_type_cell_value_3d = get_noise_samples_3d(noise);421noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE);422Vector<real_t> cellular_return_type_distance_2d = get_noise_samples_2d(noise);423Vector<real_t> cellular_return_type_distance_3d = get_noise_samples_3d(noise);424noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2);425Vector<real_t> cellular_return_type_distance2_2d = get_noise_samples_2d(noise);426Vector<real_t> cellular_return_type_distance2_3d = get_noise_samples_3d(noise);427noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_ADD);428Vector<real_t> cellular_return_type_distance2_add_2d = get_noise_samples_2d(noise);429Vector<real_t> cellular_return_type_distance2_add_3d = get_noise_samples_3d(noise);430noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_SUB);431Vector<real_t> cellular_return_type_distance2_sub_2d = get_noise_samples_2d(noise);432Vector<real_t> cellular_return_type_distance2_sub_3d = get_noise_samples_3d(noise);433noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_MUL);434Vector<real_t> cellular_return_type_distance2_mul_2d = get_noise_samples_2d(noise);435Vector<real_t> cellular_return_type_distance2_mul_3d = get_noise_samples_3d(noise);436noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_DIV);437Vector<real_t> cellular_return_type_distance2_div_2d = get_noise_samples_2d(noise);438Vector<real_t> cellular_return_type_distance2_div_3d = get_noise_samples_3d(noise);439440CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(cellular_return_type_cell_value_2d,441cellular_return_type_distance_2d,442cellular_return_type_distance2_2d,443cellular_return_type_distance2_add_2d,444cellular_return_type_distance2_sub_2d,445cellular_return_type_distance2_mul_2d,446cellular_return_type_distance2_div_2d);447448CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(cellular_return_type_cell_value_3d,449cellular_return_type_distance_3d,450cellular_return_type_distance2_3d,451cellular_return_type_distance2_add_3d,452cellular_return_type_distance2_sub_3d,453cellular_return_type_distance2_mul_3d,454cellular_return_type_distance2_div_3d);455}456457SUBCASE("Different cellular jitter should produce different results") {458noise.set_cellular_jitter(0.0);459Vector<real_t> cellular_jitter_1_2d = get_noise_samples_2d(noise);460Vector<real_t> cellular_jitter_1_3d = get_noise_samples_3d(noise);461noise.set_cellular_jitter(0.5);462Vector<real_t> cellular_jitter_2_2d = get_noise_samples_2d(noise);463Vector<real_t> cellular_jitter_2_3d = get_noise_samples_3d(noise);464465CHECK_FALSE(all_equal_approx(cellular_jitter_1_2d, cellular_jitter_2_2d));466CHECK_FALSE(all_equal_approx(cellular_jitter_1_3d, cellular_jitter_2_3d));467}468}469470TEST_CASE("[FastNoiseLite] Domain warp") {471FastNoiseLite noise;472noise.set_frequency(1.0);473noise.set_domain_warp_amplitude(200.0);474noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);475noise.set_domain_warp_enabled(true);476477SUBCASE("Different domain warp types should produce different results") {478noise.set_domain_warp_type(FastNoiseLite::DomainWarpType::DOMAIN_WARP_SIMPLEX);479Vector<real_t> domain_warp_type_simplex_2d = get_noise_samples_2d(noise);480Vector<real_t> domain_warp_type_simplex_3d = get_noise_samples_3d(noise);481noise.set_domain_warp_type(FastNoiseLite::DomainWarpType::DOMAIN_WARP_SIMPLEX_REDUCED);482Vector<real_t> domain_warp_type_simplex_reduced_2d = get_noise_samples_2d(noise);483Vector<real_t> domain_warp_type_simplex_reduced_3d = get_noise_samples_3d(noise);484noise.set_domain_warp_type(FastNoiseLite::DomainWarpType::DOMAIN_WARP_BASIC_GRID);485Vector<real_t> domain_warp_type_basic_grid_2d = get_noise_samples_2d(noise);486Vector<real_t> domain_warp_type_basic_grid_3d = get_noise_samples_3d(noise);487488CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(domain_warp_type_simplex_2d,489domain_warp_type_simplex_reduced_2d,490domain_warp_type_basic_grid_2d);491492CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(domain_warp_type_simplex_3d,493domain_warp_type_simplex_reduced_3d,494domain_warp_type_basic_grid_3d);495}496497SUBCASE("Different domain warp amplitude should produce different results") {498noise.set_domain_warp_amplitude(0.0);499Vector<real_t> domain_warp_amplitude_1_2d = get_noise_samples_2d(noise);500Vector<real_t> domain_warp_amplitude_1_3d = get_noise_samples_3d(noise);501noise.set_domain_warp_amplitude(100.0);502Vector<real_t> domain_warp_amplitude_2_2d = get_noise_samples_2d(noise);503Vector<real_t> domain_warp_amplitude_2_3d = get_noise_samples_3d(noise);504505CHECK_FALSE(all_equal_approx(domain_warp_amplitude_1_2d, domain_warp_amplitude_2_2d));506CHECK_FALSE(all_equal_approx(domain_warp_amplitude_1_3d, domain_warp_amplitude_2_3d));507}508509SUBCASE("Different domain warp frequency should produce different results") {510noise.set_domain_warp_frequency(0.1);511Vector<real_t> domain_warp_frequency_1_2d = get_noise_samples_2d(noise);512Vector<real_t> domain_warp_frequency_1_3d = get_noise_samples_3d(noise);513noise.set_domain_warp_frequency(2.0);514Vector<real_t> domain_warp_frequency_2_2d = get_noise_samples_2d(noise);515Vector<real_t> domain_warp_frequency_2_3d = get_noise_samples_3d(noise);516517CHECK_FALSE(all_equal_approx(domain_warp_frequency_1_2d, domain_warp_frequency_2_2d));518CHECK_FALSE(all_equal_approx(domain_warp_frequency_1_3d, domain_warp_frequency_2_3d));519}520521SUBCASE("Different domain warp fractal type should produce different results") {522noise.set_domain_warp_fractal_type(FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_NONE);523Vector<real_t> domain_warp_fractal_type_none_2d = get_noise_samples_2d(noise);524Vector<real_t> domain_warp_fractal_type_none_3d = get_noise_samples_3d(noise);525noise.set_domain_warp_fractal_type(FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_PROGRESSIVE);526Vector<real_t> domain_warp_fractal_type_progressive_2d = get_noise_samples_2d(noise);527Vector<real_t> domain_warp_fractal_type_progressive_3d = get_noise_samples_3d(noise);528noise.set_domain_warp_fractal_type(FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_INDEPENDENT);529Vector<real_t> domain_warp_fractal_type_independent_2d = get_noise_samples_2d(noise);530Vector<real_t> domain_warp_fractal_type_independent_3d = get_noise_samples_3d(noise);531532CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(domain_warp_fractal_type_none_2d,533domain_warp_fractal_type_progressive_2d,534domain_warp_fractal_type_independent_2d);535536CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(domain_warp_fractal_type_none_3d,537domain_warp_fractal_type_progressive_3d,538domain_warp_fractal_type_independent_3d);539}540541SUBCASE("Different domain warp fractal octaves should produce different results") {542noise.set_domain_warp_fractal_octaves(1);543Vector<real_t> domain_warp_fractal_octaves_1_2d = get_noise_samples_2d(noise);544Vector<real_t> domain_warp_fractal_octaves_1_3d = get_noise_samples_3d(noise);545noise.set_domain_warp_fractal_octaves(6);546Vector<real_t> domain_warp_fractal_octaves_2_2d = get_noise_samples_2d(noise);547Vector<real_t> domain_warp_fractal_octaves_2_3d = get_noise_samples_3d(noise);548549CHECK_FALSE(all_equal_approx(domain_warp_fractal_octaves_1_2d, domain_warp_fractal_octaves_2_2d));550CHECK_FALSE(all_equal_approx(domain_warp_fractal_octaves_1_3d, domain_warp_fractal_octaves_2_3d));551}552553SUBCASE("Different domain warp fractal lacunarity should produce different results") {554noise.set_domain_warp_fractal_lacunarity(0.5);555Vector<real_t> domain_warp_fractal_lacunarity_1_2d = get_noise_samples_2d(noise);556Vector<real_t> domain_warp_fractal_lacunarity_1_3d = get_noise_samples_3d(noise);557noise.set_domain_warp_fractal_lacunarity(5.0);558Vector<real_t> domain_warp_fractal_lacunarity_2_2d = get_noise_samples_2d(noise);559Vector<real_t> domain_warp_fractal_lacunarity_2_3d = get_noise_samples_3d(noise);560561CHECK_FALSE(all_equal_approx(domain_warp_fractal_lacunarity_1_2d, domain_warp_fractal_lacunarity_2_2d));562CHECK_FALSE(all_equal_approx(domain_warp_fractal_lacunarity_1_3d, domain_warp_fractal_lacunarity_2_3d));563}564565SUBCASE("Different domain warp fractal gain should produce different results") {566noise.set_domain_warp_fractal_gain(0.1);567Vector<real_t> domain_warp_fractal_gain_1_2d = get_noise_samples_2d(noise);568Vector<real_t> domain_warp_fractal_gain_1_3d = get_noise_samples_3d(noise);569noise.set_domain_warp_fractal_gain(0.9);570Vector<real_t> domain_warp_fractal_gain_2_2d = get_noise_samples_2d(noise);571Vector<real_t> domain_warp_fractal_gain_2_3d = get_noise_samples_3d(noise);572573CHECK_FALSE(all_equal_approx(domain_warp_fractal_gain_1_2d, domain_warp_fractal_gain_2_2d));574CHECK_FALSE(all_equal_approx(domain_warp_fractal_gain_1_3d, domain_warp_fractal_gain_2_3d));575}576}577578// Raw image data for the reference images used in the regression tests.579// Generated with the following code:580// for (int y = 0; y < img->get_data().size(); y++) {581// printf("0x%x,", img->get_data()[y]);582// }583584const Vector<uint8_t> ref_img_1_data = { 0xff, 0xe6, 0xd2, 0xc2, 0xb7, 0xb4, 0xb4, 0xb7, 0xc2, 0xd2, 0xe6, 0xe6, 0xcb, 0xb4, 0xa1, 0x94, 0x90, 0x90, 0x94, 0xa1, 0xb4, 0xcb, 0xd2, 0xb4, 0x99, 0x82, 0x72, 0x6c, 0x6c, 0x72, 0x82, 0x99, 0xb4, 0xc2, 0xa1, 0x82, 0x65, 0x50, 0x48, 0x48, 0x50, 0x65, 0x82, 0xa1, 0xb7, 0x94, 0x72, 0x50, 0x32, 0x24, 0x24, 0x32, 0x50, 0x72, 0x94, 0xb4, 0x90, 0x6c, 0x48, 0x24, 0x0, 0x0, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0x90, 0x6c, 0x48, 0x24, 0x0, 0x0, 0x24, 0x48, 0x6c, 0x90, 0xb7, 0x94, 0x72, 0x50, 0x32, 0x24, 0x24, 0x33, 0x50, 0x72, 0x94, 0xc2, 0xa1, 0x82, 0x65, 0x50, 0x48, 0x48, 0x50, 0x66, 0x82, 0xa1, 0xd2, 0xb4, 0x99, 0x82, 0x72, 0x6c, 0x6c, 0x72, 0x82, 0x99, 0xb4, 0xe6, 0xcb, 0xb4, 0xa1, 0x94, 0x90, 0x90, 0x94, 0xa1, 0xb4, 0xcc };585const Vector<uint8_t> ref_img_2_data = { 0xff, 0xe6, 0xd2, 0xc2, 0xb7, 0xb4, 0xb4, 0xb7, 0xc2, 0xd2, 0xe6, 0xe6, 0xcb, 0xb4, 0xa1, 0x94, 0x90, 0x90, 0x94, 0xa1, 0xb4, 0xcb, 0xd2, 0xb4, 0x99, 0x82, 0x72, 0x6c, 0x6c, 0x72, 0x82, 0x99, 0xb4, 0xc2, 0xa1, 0x82, 0x65, 0x50, 0x48, 0x48, 0x50, 0x65, 0x82, 0xa1, 0xb7, 0x94, 0x72, 0x50, 0x32, 0x24, 0x24, 0x32, 0x50, 0x72, 0x94, 0xb4, 0x90, 0x6c, 0x48, 0x24, 0x0, 0x0, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0x90, 0x6c, 0x48, 0x24, 0x0, 0x0, 0x24, 0x48, 0x6c, 0x90, 0xb7, 0x94, 0x72, 0x50, 0x32, 0x24, 0x24, 0x33, 0x50, 0x72, 0x94, 0xc2, 0xa1, 0x82, 0x65, 0x50, 0x48, 0x48, 0x50, 0x66, 0x82, 0xa1, 0xd2, 0xb4, 0x99, 0x82, 0x72, 0x6c, 0x6c, 0x72, 0x82, 0x99, 0xb4, 0xe6, 0xcb, 0xb4, 0xa1, 0x94, 0x90, 0x90, 0x94, 0xa1, 0xb4, 0xcc };586const Vector<uint8_t> ref_img_3_data = { 0xff, 0xe6, 0xd2, 0xc2, 0xb7, 0xb4, 0xb4, 0xb7, 0xc2, 0xd2, 0xe6, 0xe6, 0xcb, 0xb4, 0xa1, 0x94, 0x90, 0x90, 0x94, 0xa1, 0xb4, 0xcb, 0xd2, 0xb4, 0x99, 0x82, 0x72, 0x6c, 0x6c, 0x72, 0x82, 0x99, 0xb4, 0xc2, 0xa1, 0x82, 0x65, 0x50, 0x48, 0x48, 0x50, 0x65, 0x82, 0xa1, 0xb7, 0x94, 0x72, 0x50, 0x32, 0x24, 0x24, 0x32, 0x50, 0x72, 0x94, 0xb4, 0x90, 0x6c, 0x48, 0x24, 0x0, 0x0, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0x90, 0x6c, 0x48, 0x24, 0x0, 0x0, 0x24, 0x48, 0x6c, 0x90, 0xb7, 0x94, 0x72, 0x50, 0x32, 0x24, 0x24, 0x33, 0x50, 0x72, 0x94, 0xc2, 0xa1, 0x82, 0x65, 0x50, 0x48, 0x48, 0x50, 0x66, 0x82, 0xa1, 0xd2, 0xb4, 0x99, 0x82, 0x72, 0x6c, 0x6c, 0x72, 0x82, 0x99, 0xb4, 0xe6, 0xcb, 0xb4, 0xa1, 0x94, 0x90, 0x90, 0x94, 0xa1, 0xb4, 0xcc };587588// Utiliy function to compare two images pixel by pixel (for easy debugging of regressions)589void compare_image_with_reference(const Ref<Image> &p_img, const Ref<Image> &p_reference_img) {590for (int y = 0; y < p_img->get_height(); y++) {591for (int x = 0; x < p_img->get_width(); x++) {592CHECK(p_img->get_pixel(x, y) == p_reference_img->get_pixel(x, y));593}594}595}596597TEST_CASE("[FastNoiseLite] Generating seamless 2D images (11x11px) and compare to reference images") {598FastNoiseLite noise;599noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_CELLULAR);600noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_NONE);601noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_EUCLIDEAN);602noise.set_frequency(0.1);603noise.set_cellular_jitter(0.0);604605SUBCASE("Blend skirt 0.0") {606Ref<Image> img = noise.get_seamless_image(11, 11, false, false, 0.0);607608Ref<Image> ref_img_1 = memnew(Image);609ref_img_1->set_data(11, 11, false, Image::FORMAT_L8, ref_img_1_data);610611compare_image_with_reference(img, ref_img_1);612}613614SUBCASE("Blend skirt 0.1") {615Ref<Image> img = noise.get_seamless_image(11, 11, false, false, 0.1);616617Ref<Image> ref_img_2 = memnew(Image);618ref_img_2->set_data(11, 11, false, Image::FORMAT_L8, ref_img_2_data);619620compare_image_with_reference(img, ref_img_2);621}622623SUBCASE("Blend skirt 1.0") {624Ref<Image> img = noise.get_seamless_image(11, 11, false, false, 0.1);625626Ref<Image> ref_img_3 = memnew(Image);627ref_img_3->set_data(11, 11, false, Image::FORMAT_L8, ref_img_3_data);628629compare_image_with_reference(img, ref_img_3);630}631}632633} //namespace TestFastNoiseLite634635636