test_fastnoise_lite.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /**************************************************************************/
  2. /* test_fastnoise_lite.h */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #ifndef TEST_FASTNOISE_LITE_H
  31. #define TEST_FASTNOISE_LITE_H
  32. #include "../fastnoise_lite.h"
  33. #include "tests/test_macros.h"
  34. namespace TestFastNoiseLite {
  35. // Uitility functions for finding differences in noise generation
  36. bool all_equal_approx(const Vector<real_t> &p_values_1, const Vector<real_t> &p_values_2) {
  37. ERR_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.");
  38. for (int i = 0; i < p_values_1.size(); i++) {
  39. if (!Math::is_equal_approx(p_values_1[i], p_values_2[i])) {
  40. return false;
  41. }
  42. }
  43. return true;
  44. }
  45. Vector<Pair<size_t, size_t>> find_approx_equal_vec_pairs(std::initializer_list<Vector<real_t>> inputs) {
  46. Vector<Vector<real_t>> p_array = Vector<Vector<real_t>>(inputs);
  47. Vector<Pair<size_t, size_t>> result;
  48. for (int i = 0; i < p_array.size(); i++) {
  49. for (int j = i + 1; j < p_array.size(); j++) {
  50. if (all_equal_approx(p_array[i], p_array[j])) {
  51. result.push_back(Pair<size_t, size_t>(i, j));
  52. }
  53. }
  54. }
  55. return result;
  56. }
  57. #define CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(...) \
  58. { \
  59. Vector<Pair<size_t, size_t>> equal_pairs = find_approx_equal_vec_pairs({ __VA_ARGS__ }); \
  60. for (Pair<size_t, size_t> p : equal_pairs) { \
  61. MESSAGE("Argument with index ", p.first, " is approximately equal to argument with index ", p.second); \
  62. } \
  63. CHECK_MESSAGE(equal_pairs.size() == 0, "All arguments should be pairwise distinct."); \
  64. }
  65. Vector<real_t> get_noise_samples_1d(const FastNoiseLite &p_noise, size_t p_count = 32) {
  66. Vector<real_t> result;
  67. result.resize(p_count);
  68. for (size_t i = 0; i < p_count; i++) {
  69. result.write[i] = p_noise.get_noise_1d(i);
  70. }
  71. return result;
  72. }
  73. Vector<real_t> get_noise_samples_2d(const FastNoiseLite &p_noise, size_t p_count = 32) {
  74. Vector<real_t> result;
  75. result.resize(p_count);
  76. for (size_t i = 0; i < p_count; i++) {
  77. result.write[i] = p_noise.get_noise_2d(i, i);
  78. }
  79. return result;
  80. }
  81. Vector<real_t> get_noise_samples_3d(const FastNoiseLite &p_noise, size_t p_count = 32) {
  82. Vector<real_t> result;
  83. result.resize(p_count);
  84. for (size_t i = 0; i < p_count; i++) {
  85. result.write[i] = p_noise.get_noise_3d(i, i, i);
  86. }
  87. return result;
  88. }
  89. // The following test suite is rather for testing the wrapper code than the actual noise generation.
  90. TEST_CASE("[FastNoiseLite] Getter and setter") {
  91. FastNoiseLite noise;
  92. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX_SMOOTH);
  93. CHECK(noise.get_noise_type() == FastNoiseLite::NoiseType::TYPE_SIMPLEX_SMOOTH);
  94. noise.set_seed(123);
  95. CHECK(noise.get_seed() == 123);
  96. noise.set_frequency(0.123);
  97. CHECK(noise.get_frequency() == doctest::Approx(0.123));
  98. noise.set_offset(Vector3(1, 2, 3));
  99. CHECK(noise.get_offset() == Vector3(1, 2, 3));
  100. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_PING_PONG);
  101. CHECK(noise.get_fractal_type() == FastNoiseLite::FractalType::FRACTAL_PING_PONG);
  102. noise.set_fractal_octaves(2);
  103. CHECK(noise.get_fractal_octaves() == 2);
  104. noise.set_fractal_lacunarity(1.123);
  105. CHECK(noise.get_fractal_lacunarity() == doctest::Approx(1.123));
  106. noise.set_fractal_gain(0.123);
  107. CHECK(noise.get_fractal_gain() == doctest::Approx(0.123));
  108. noise.set_fractal_weighted_strength(0.123);
  109. CHECK(noise.get_fractal_weighted_strength() == doctest::Approx(0.123));
  110. noise.set_fractal_ping_pong_strength(0.123);
  111. CHECK(noise.get_fractal_ping_pong_strength() == doctest::Approx(0.123));
  112. noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_MANHATTAN);
  113. CHECK(noise.get_cellular_distance_function() == FastNoiseLite::CellularDistanceFunction::DISTANCE_MANHATTAN);
  114. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_SUB);
  115. CHECK(noise.get_cellular_return_type() == FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_SUB);
  116. noise.set_cellular_jitter(0.123);
  117. CHECK(noise.get_cellular_jitter() == doctest::Approx(0.123));
  118. noise.set_domain_warp_enabled(true);
  119. CHECK(noise.is_domain_warp_enabled() == true);
  120. noise.set_domain_warp_enabled(false);
  121. CHECK(noise.is_domain_warp_enabled() == false);
  122. noise.set_domain_warp_type(FastNoiseLite::DomainWarpType::DOMAIN_WARP_SIMPLEX_REDUCED);
  123. CHECK(noise.get_domain_warp_type() == FastNoiseLite::DomainWarpType::DOMAIN_WARP_SIMPLEX_REDUCED);
  124. noise.set_domain_warp_amplitude(0.123);
  125. CHECK(noise.get_domain_warp_amplitude() == doctest::Approx(0.123));
  126. noise.set_domain_warp_frequency(0.123);
  127. CHECK(noise.get_domain_warp_frequency() == doctest::Approx(0.123));
  128. noise.set_domain_warp_fractal_type(FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_INDEPENDENT);
  129. CHECK(noise.get_domain_warp_fractal_type() == FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_INDEPENDENT);
  130. noise.set_domain_warp_fractal_octaves(2);
  131. CHECK(noise.get_domain_warp_fractal_octaves() == 2);
  132. noise.set_domain_warp_fractal_lacunarity(1.123);
  133. CHECK(noise.get_domain_warp_fractal_lacunarity() == doctest::Approx(1.123));
  134. noise.set_domain_warp_fractal_gain(0.123);
  135. CHECK(noise.get_domain_warp_fractal_gain() == doctest::Approx(0.123));
  136. }
  137. TEST_CASE("[FastNoiseLite] Basic noise generation") {
  138. FastNoiseLite noise;
  139. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);
  140. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_NONE);
  141. noise.set_seed(123);
  142. noise.set_offset(Vector3(10, 10, 10));
  143. // 1D noise will be checked just in the cases where there's the possibility of
  144. // finding a bug/regression in the wrapper function.
  145. // (since it uses FastNoise's 2D noise generator with the Y coordinate set to 0).
  146. SUBCASE("Determinacy of noise generation (all noise types)") {
  147. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);
  148. CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));
  149. CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));
  150. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX_SMOOTH);
  151. CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));
  152. CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));
  153. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_CELLULAR);
  154. CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));
  155. CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));
  156. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_PERLIN);
  157. CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));
  158. CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));
  159. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_VALUE);
  160. CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));
  161. CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));
  162. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_VALUE_CUBIC);
  163. CHECK(noise.get_noise_2d(0, 0) == doctest::Approx(noise.get_noise_2d(0, 0)));
  164. CHECK(noise.get_noise_3d(0, 0, 0) == doctest::Approx(noise.get_noise_3d(0, 0, 0)));
  165. }
  166. SUBCASE("Different seeds should produce different noise") {
  167. noise.set_seed(456);
  168. Vector<real_t> noise_seed_1_1d = get_noise_samples_1d(noise);
  169. Vector<real_t> noise_seed_1_2d = get_noise_samples_2d(noise);
  170. Vector<real_t> noise_seed_1_3d = get_noise_samples_3d(noise);
  171. noise.set_seed(123);
  172. Vector<real_t> noise_seed_2_1d = get_noise_samples_1d(noise);
  173. Vector<real_t> noise_seed_2_2d = get_noise_samples_2d(noise);
  174. Vector<real_t> noise_seed_2_3d = get_noise_samples_3d(noise);
  175. CHECK_FALSE(all_equal_approx(noise_seed_1_1d, noise_seed_2_1d));
  176. CHECK_FALSE(all_equal_approx(noise_seed_1_2d, noise_seed_2_2d));
  177. CHECK_FALSE(all_equal_approx(noise_seed_1_3d, noise_seed_2_3d));
  178. }
  179. SUBCASE("Different frequencies should produce different noise") {
  180. noise.set_frequency(0.1);
  181. Vector<real_t> noise_frequency_1_1d = get_noise_samples_1d(noise);
  182. Vector<real_t> noise_frequency_1_2d = get_noise_samples_2d(noise);
  183. Vector<real_t> noise_frequency_1_3d = get_noise_samples_3d(noise);
  184. noise.set_frequency(1.0);
  185. Vector<real_t> noise_frequency_2_1d = get_noise_samples_1d(noise);
  186. Vector<real_t> noise_frequency_2_2d = get_noise_samples_2d(noise);
  187. Vector<real_t> noise_frequency_2_3d = get_noise_samples_3d(noise);
  188. CHECK_FALSE(all_equal_approx(noise_frequency_1_1d, noise_frequency_2_1d));
  189. CHECK_FALSE(all_equal_approx(noise_frequency_1_2d, noise_frequency_2_2d));
  190. CHECK_FALSE(all_equal_approx(noise_frequency_1_3d, noise_frequency_2_3d));
  191. }
  192. SUBCASE("Noise should be offset by the offset parameter") {
  193. noise.set_offset(Vector3(1, 2, 3));
  194. Vector<real_t> noise_offset_1_1d = get_noise_samples_1d(noise);
  195. Vector<real_t> noise_offset_1_2d = get_noise_samples_2d(noise);
  196. Vector<real_t> noise_offset_1_3d = get_noise_samples_3d(noise);
  197. noise.set_offset(Vector3(4, 5, 6));
  198. Vector<real_t> noise_offset_2_1d = get_noise_samples_1d(noise);
  199. Vector<real_t> noise_offset_2_2d = get_noise_samples_2d(noise);
  200. Vector<real_t> noise_offset_2_3d = get_noise_samples_3d(noise);
  201. CHECK_FALSE(all_equal_approx(noise_offset_1_1d, noise_offset_2_1d));
  202. CHECK_FALSE(all_equal_approx(noise_offset_1_2d, noise_offset_2_2d));
  203. CHECK_FALSE(all_equal_approx(noise_offset_1_3d, noise_offset_2_3d));
  204. }
  205. SUBCASE("Different noise types should produce different noise") {
  206. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);
  207. Vector<real_t> noise_type_simplex_2d = get_noise_samples_2d(noise);
  208. Vector<real_t> noise_type_simplex_3d = get_noise_samples_3d(noise);
  209. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX_SMOOTH);
  210. Vector<real_t> noise_type_simplex_smooth_2d = get_noise_samples_2d(noise);
  211. Vector<real_t> noise_type_simplex_smooth_3d = get_noise_samples_3d(noise);
  212. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_CELLULAR);
  213. Vector<real_t> noise_type_cellular_2d = get_noise_samples_2d(noise);
  214. Vector<real_t> noise_type_cellular_3d = get_noise_samples_3d(noise);
  215. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_PERLIN);
  216. Vector<real_t> noise_type_perlin_2d = get_noise_samples_2d(noise);
  217. Vector<real_t> noise_type_perlin_3d = get_noise_samples_3d(noise);
  218. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_VALUE);
  219. Vector<real_t> noise_type_value_2d = get_noise_samples_2d(noise);
  220. Vector<real_t> noise_type_value_3d = get_noise_samples_3d(noise);
  221. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_VALUE_CUBIC);
  222. Vector<real_t> noise_type_value_cubic_2d = get_noise_samples_2d(noise);
  223. Vector<real_t> noise_type_value_cubic_3d = get_noise_samples_3d(noise);
  224. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(noise_type_simplex_2d,
  225. noise_type_simplex_smooth_2d,
  226. noise_type_cellular_2d,
  227. noise_type_perlin_2d,
  228. noise_type_value_2d,
  229. noise_type_value_cubic_2d);
  230. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(noise_type_simplex_3d,
  231. noise_type_simplex_smooth_3d,
  232. noise_type_cellular_3d,
  233. noise_type_perlin_3d,
  234. noise_type_value_3d,
  235. noise_type_value_cubic_3d);
  236. }
  237. }
  238. TEST_CASE("[FastNoiseLite] Fractal noise") {
  239. FastNoiseLite noise;
  240. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);
  241. noise.set_offset(Vector3(10, 10, 10));
  242. noise.set_frequency(0.01);
  243. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_FBM);
  244. noise.set_fractal_octaves(4);
  245. noise.set_fractal_lacunarity(2.0);
  246. noise.set_fractal_gain(0.5);
  247. noise.set_fractal_weighted_strength(0.5);
  248. noise.set_fractal_ping_pong_strength(2.0);
  249. SUBCASE("Different fractal types should produce different results") {
  250. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_NONE);
  251. Vector<real_t> fractal_type_none_2d = get_noise_samples_2d(noise);
  252. Vector<real_t> fractal_type_none_3d = get_noise_samples_3d(noise);
  253. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_FBM);
  254. Vector<real_t> fractal_type_fbm_2d = get_noise_samples_2d(noise);
  255. Vector<real_t> fractal_type_fbm_3d = get_noise_samples_3d(noise);
  256. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_RIDGED);
  257. Vector<real_t> fractal_type_ridged_2d = get_noise_samples_2d(noise);
  258. Vector<real_t> fractal_type_ridged_3d = get_noise_samples_3d(noise);
  259. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_PING_PONG);
  260. Vector<real_t> fractal_type_ping_pong_2d = get_noise_samples_2d(noise);
  261. Vector<real_t> fractal_type_ping_pong_3d = get_noise_samples_3d(noise);
  262. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(fractal_type_none_2d,
  263. fractal_type_fbm_2d,
  264. fractal_type_ridged_2d,
  265. fractal_type_ping_pong_2d);
  266. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(fractal_type_none_3d,
  267. fractal_type_fbm_3d,
  268. fractal_type_ridged_3d,
  269. fractal_type_ping_pong_3d);
  270. }
  271. SUBCASE("Different octaves should produce different results") {
  272. noise.set_fractal_octaves(1.0);
  273. Vector<real_t> fractal_octaves_1_2d = get_noise_samples_2d(noise);
  274. Vector<real_t> fractal_octaves_1_3d = get_noise_samples_3d(noise);
  275. noise.set_fractal_octaves(8.0);
  276. Vector<real_t> fractal_octaves_2_2d = get_noise_samples_2d(noise);
  277. Vector<real_t> fractal_octaves_2_3d = get_noise_samples_3d(noise);
  278. CHECK_FALSE(all_equal_approx(fractal_octaves_1_2d, fractal_octaves_2_2d));
  279. CHECK_FALSE(all_equal_approx(fractal_octaves_1_3d, fractal_octaves_2_3d));
  280. }
  281. SUBCASE("Different lacunarity should produce different results") {
  282. noise.set_fractal_lacunarity(1.0);
  283. Vector<real_t> fractal_lacunarity_1_2d = get_noise_samples_2d(noise);
  284. Vector<real_t> fractal_lacunarity_1_3d = get_noise_samples_3d(noise);
  285. noise.set_fractal_lacunarity(2.0);
  286. Vector<real_t> fractal_lacunarity_2_2d = get_noise_samples_2d(noise);
  287. Vector<real_t> fractal_lacunarity_2_3d = get_noise_samples_3d(noise);
  288. CHECK_FALSE(all_equal_approx(fractal_lacunarity_1_2d, fractal_lacunarity_2_2d));
  289. CHECK_FALSE(all_equal_approx(fractal_lacunarity_1_3d, fractal_lacunarity_2_3d));
  290. }
  291. SUBCASE("Different gain should produce different results") {
  292. noise.set_fractal_gain(0.5);
  293. Vector<real_t> fractal_gain_1_2d = get_noise_samples_2d(noise);
  294. Vector<real_t> fractal_gain_1_3d = get_noise_samples_3d(noise);
  295. noise.set_fractal_gain(0.75);
  296. Vector<real_t> fractal_gain_2_2d = get_noise_samples_2d(noise);
  297. Vector<real_t> fractal_gain_2_3d = get_noise_samples_3d(noise);
  298. CHECK_FALSE(all_equal_approx(fractal_gain_1_2d, fractal_gain_2_2d));
  299. CHECK_FALSE(all_equal_approx(fractal_gain_1_3d, fractal_gain_2_3d));
  300. }
  301. SUBCASE("Different weights should produce different results") {
  302. noise.set_fractal_weighted_strength(0.5);
  303. Vector<real_t> fractal_weighted_strength_1_2d = get_noise_samples_2d(noise);
  304. Vector<real_t> fractal_weighted_strength_1_3d = get_noise_samples_3d(noise);
  305. noise.set_fractal_weighted_strength(0.75);
  306. Vector<real_t> fractal_weighted_strength_2_2d = get_noise_samples_2d(noise);
  307. Vector<real_t> fractal_weighted_strength_2_3d = get_noise_samples_3d(noise);
  308. CHECK_FALSE(all_equal_approx(fractal_weighted_strength_1_2d, fractal_weighted_strength_2_2d));
  309. CHECK_FALSE(all_equal_approx(fractal_weighted_strength_1_3d, fractal_weighted_strength_2_3d));
  310. }
  311. SUBCASE("Different ping pong strength should produce different results") {
  312. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_PING_PONG);
  313. noise.set_fractal_ping_pong_strength(0.5);
  314. Vector<real_t> fractal_ping_pong_strength_1_2d = get_noise_samples_2d(noise);
  315. Vector<real_t> fractal_ping_pong_strength_1_3d = get_noise_samples_3d(noise);
  316. noise.set_fractal_ping_pong_strength(0.75);
  317. Vector<real_t> fractal_ping_pong_strength_2_2d = get_noise_samples_2d(noise);
  318. Vector<real_t> fractal_ping_pong_strength_2_3d = get_noise_samples_3d(noise);
  319. CHECK_FALSE(all_equal_approx(fractal_ping_pong_strength_1_2d, fractal_ping_pong_strength_2_2d));
  320. CHECK_FALSE(all_equal_approx(fractal_ping_pong_strength_1_3d, fractal_ping_pong_strength_2_3d));
  321. }
  322. }
  323. TEST_CASE("[FastNoiseLite] Cellular noise") {
  324. FastNoiseLite noise;
  325. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_NONE);
  326. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_CELLULAR);
  327. noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_EUCLIDEAN);
  328. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE);
  329. noise.set_frequency(1.0);
  330. SUBCASE("Different distance functions should produce different results") {
  331. noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_EUCLIDEAN);
  332. Vector<real_t> cellular_distance_function_euclidean_2d = get_noise_samples_2d(noise);
  333. Vector<real_t> cellular_distance_function_euclidean_3d = get_noise_samples_3d(noise);
  334. noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_EUCLIDEAN_SQUARED);
  335. Vector<real_t> cellular_distance_function_euclidean_squared_2d = get_noise_samples_2d(noise);
  336. Vector<real_t> cellular_distance_function_euclidean_squared_3d = get_noise_samples_3d(noise);
  337. noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_MANHATTAN);
  338. Vector<real_t> cellular_distance_function_manhattan_2d = get_noise_samples_2d(noise);
  339. Vector<real_t> cellular_distance_function_manhattan_3d = get_noise_samples_3d(noise);
  340. noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_HYBRID);
  341. Vector<real_t> cellular_distance_function_hybrid_2d = get_noise_samples_2d(noise);
  342. Vector<real_t> cellular_distance_function_hybrid_3d = get_noise_samples_3d(noise);
  343. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(cellular_distance_function_euclidean_2d,
  344. cellular_distance_function_euclidean_squared_2d,
  345. cellular_distance_function_manhattan_2d,
  346. cellular_distance_function_hybrid_2d);
  347. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(cellular_distance_function_euclidean_3d,
  348. cellular_distance_function_euclidean_squared_3d,
  349. cellular_distance_function_manhattan_3d,
  350. cellular_distance_function_hybrid_3d);
  351. }
  352. SUBCASE("Different return function types should produce different results") {
  353. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_CELL_VALUE);
  354. Vector<real_t> cellular_return_type_cell_value_2d = get_noise_samples_2d(noise);
  355. Vector<real_t> cellular_return_type_cell_value_3d = get_noise_samples_3d(noise);
  356. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE);
  357. Vector<real_t> cellular_return_type_distance_2d = get_noise_samples_2d(noise);
  358. Vector<real_t> cellular_return_type_distance_3d = get_noise_samples_3d(noise);
  359. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2);
  360. Vector<real_t> cellular_return_type_distance2_2d = get_noise_samples_2d(noise);
  361. Vector<real_t> cellular_return_type_distance2_3d = get_noise_samples_3d(noise);
  362. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_ADD);
  363. Vector<real_t> cellular_return_type_distance2_add_2d = get_noise_samples_2d(noise);
  364. Vector<real_t> cellular_return_type_distance2_add_3d = get_noise_samples_3d(noise);
  365. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_SUB);
  366. Vector<real_t> cellular_return_type_distance2_sub_2d = get_noise_samples_2d(noise);
  367. Vector<real_t> cellular_return_type_distance2_sub_3d = get_noise_samples_3d(noise);
  368. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_MUL);
  369. Vector<real_t> cellular_return_type_distance2_mul_2d = get_noise_samples_2d(noise);
  370. Vector<real_t> cellular_return_type_distance2_mul_3d = get_noise_samples_3d(noise);
  371. noise.set_cellular_return_type(FastNoiseLite::CellularReturnType::RETURN_DISTANCE2_DIV);
  372. Vector<real_t> cellular_return_type_distance2_div_2d = get_noise_samples_2d(noise);
  373. Vector<real_t> cellular_return_type_distance2_div_3d = get_noise_samples_3d(noise);
  374. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(cellular_return_type_cell_value_2d,
  375. cellular_return_type_distance_2d,
  376. cellular_return_type_distance2_2d,
  377. cellular_return_type_distance2_add_2d,
  378. cellular_return_type_distance2_sub_2d,
  379. cellular_return_type_distance2_mul_2d,
  380. cellular_return_type_distance2_div_2d);
  381. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(cellular_return_type_cell_value_3d,
  382. cellular_return_type_distance_3d,
  383. cellular_return_type_distance2_3d,
  384. cellular_return_type_distance2_add_3d,
  385. cellular_return_type_distance2_sub_3d,
  386. cellular_return_type_distance2_mul_3d,
  387. cellular_return_type_distance2_div_3d);
  388. }
  389. SUBCASE("Different cellular jitter should produce different results") {
  390. noise.set_cellular_jitter(0.0);
  391. Vector<real_t> cellular_jitter_1_2d = get_noise_samples_2d(noise);
  392. Vector<real_t> cellular_jitter_1_3d = get_noise_samples_3d(noise);
  393. noise.set_cellular_jitter(0.5);
  394. Vector<real_t> cellular_jitter_2_2d = get_noise_samples_2d(noise);
  395. Vector<real_t> cellular_jitter_2_3d = get_noise_samples_3d(noise);
  396. CHECK_FALSE(all_equal_approx(cellular_jitter_1_2d, cellular_jitter_2_2d));
  397. CHECK_FALSE(all_equal_approx(cellular_jitter_1_3d, cellular_jitter_2_3d));
  398. }
  399. }
  400. TEST_CASE("[FastNoiseLite] Domain warp") {
  401. FastNoiseLite noise;
  402. noise.set_frequency(1.0);
  403. noise.set_domain_warp_amplitude(200.0);
  404. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_SIMPLEX);
  405. noise.set_domain_warp_enabled(true);
  406. SUBCASE("Different domain warp types should produce different results") {
  407. noise.set_domain_warp_type(FastNoiseLite::DomainWarpType::DOMAIN_WARP_SIMPLEX);
  408. Vector<real_t> domain_warp_type_simplex_2d = get_noise_samples_2d(noise);
  409. Vector<real_t> domain_warp_type_simplex_3d = get_noise_samples_3d(noise);
  410. noise.set_domain_warp_type(FastNoiseLite::DomainWarpType::DOMAIN_WARP_SIMPLEX_REDUCED);
  411. Vector<real_t> domain_warp_type_simplex_reduced_2d = get_noise_samples_2d(noise);
  412. Vector<real_t> domain_warp_type_simplex_reduced_3d = get_noise_samples_3d(noise);
  413. noise.set_domain_warp_type(FastNoiseLite::DomainWarpType::DOMAIN_WARP_BASIC_GRID);
  414. Vector<real_t> domain_warp_type_basic_grid_2d = get_noise_samples_2d(noise);
  415. Vector<real_t> domain_warp_type_basic_grid_3d = get_noise_samples_3d(noise);
  416. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(domain_warp_type_simplex_2d,
  417. domain_warp_type_simplex_reduced_2d,
  418. domain_warp_type_basic_grid_2d);
  419. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(domain_warp_type_simplex_3d,
  420. domain_warp_type_simplex_reduced_3d,
  421. domain_warp_type_basic_grid_3d);
  422. }
  423. SUBCASE("Different domain warp amplitude should produce different results") {
  424. noise.set_domain_warp_amplitude(0.0);
  425. Vector<real_t> domain_warp_amplitude_1_2d = get_noise_samples_2d(noise);
  426. Vector<real_t> domain_warp_amplitude_1_3d = get_noise_samples_3d(noise);
  427. noise.set_domain_warp_amplitude(100.0);
  428. Vector<real_t> domain_warp_amplitude_2_2d = get_noise_samples_2d(noise);
  429. Vector<real_t> domain_warp_amplitude_2_3d = get_noise_samples_3d(noise);
  430. CHECK_FALSE(all_equal_approx(domain_warp_amplitude_1_2d, domain_warp_amplitude_2_2d));
  431. CHECK_FALSE(all_equal_approx(domain_warp_amplitude_1_3d, domain_warp_amplitude_2_3d));
  432. }
  433. SUBCASE("Different domain warp frequency should produce different results") {
  434. noise.set_domain_warp_frequency(0.1);
  435. Vector<real_t> domain_warp_frequency_1_2d = get_noise_samples_2d(noise);
  436. Vector<real_t> domain_warp_frequency_1_3d = get_noise_samples_3d(noise);
  437. noise.set_domain_warp_frequency(2.0);
  438. Vector<real_t> domain_warp_frequency_2_2d = get_noise_samples_2d(noise);
  439. Vector<real_t> domain_warp_frequency_2_3d = get_noise_samples_3d(noise);
  440. CHECK_FALSE(all_equal_approx(domain_warp_frequency_1_2d, domain_warp_frequency_2_2d));
  441. CHECK_FALSE(all_equal_approx(domain_warp_frequency_1_3d, domain_warp_frequency_2_3d));
  442. }
  443. SUBCASE("Different domain warp fractal type should produce different results") {
  444. noise.set_domain_warp_fractal_type(FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_NONE);
  445. Vector<real_t> domain_warp_fractal_type_none_2d = get_noise_samples_2d(noise);
  446. Vector<real_t> domain_warp_fractal_type_none_3d = get_noise_samples_3d(noise);
  447. noise.set_domain_warp_fractal_type(FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_PROGRESSIVE);
  448. Vector<real_t> domain_warp_fractal_type_progressive_2d = get_noise_samples_2d(noise);
  449. Vector<real_t> domain_warp_fractal_type_progressive_3d = get_noise_samples_3d(noise);
  450. noise.set_domain_warp_fractal_type(FastNoiseLite::DomainWarpFractalType::DOMAIN_WARP_FRACTAL_INDEPENDENT);
  451. Vector<real_t> domain_warp_fractal_type_independent_2d = get_noise_samples_2d(noise);
  452. Vector<real_t> domain_warp_fractal_type_independent_3d = get_noise_samples_3d(noise);
  453. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(domain_warp_fractal_type_none_2d,
  454. domain_warp_fractal_type_progressive_2d,
  455. domain_warp_fractal_type_independent_2d);
  456. CHECK_ARGS_APPROX_PAIRWISE_DISTINCT_VECS(domain_warp_fractal_type_none_3d,
  457. domain_warp_fractal_type_progressive_3d,
  458. domain_warp_fractal_type_independent_3d);
  459. }
  460. SUBCASE("Different domain warp fractal octaves should produce different results") {
  461. noise.set_domain_warp_fractal_octaves(1);
  462. Vector<real_t> domain_warp_fractal_octaves_1_2d = get_noise_samples_2d(noise);
  463. Vector<real_t> domain_warp_fractal_octaves_1_3d = get_noise_samples_3d(noise);
  464. noise.set_domain_warp_fractal_octaves(6);
  465. Vector<real_t> domain_warp_fractal_octaves_2_2d = get_noise_samples_2d(noise);
  466. Vector<real_t> domain_warp_fractal_octaves_2_3d = get_noise_samples_3d(noise);
  467. CHECK_FALSE(all_equal_approx(domain_warp_fractal_octaves_1_2d, domain_warp_fractal_octaves_2_2d));
  468. CHECK_FALSE(all_equal_approx(domain_warp_fractal_octaves_1_3d, domain_warp_fractal_octaves_2_3d));
  469. }
  470. SUBCASE("Different domain warp fractal lacunarity should produce different results") {
  471. noise.set_domain_warp_fractal_lacunarity(0.5);
  472. Vector<real_t> domain_warp_fractal_lacunarity_1_2d = get_noise_samples_2d(noise);
  473. Vector<real_t> domain_warp_fractal_lacunarity_1_3d = get_noise_samples_3d(noise);
  474. noise.set_domain_warp_fractal_lacunarity(5.0);
  475. Vector<real_t> domain_warp_fractal_lacunarity_2_2d = get_noise_samples_2d(noise);
  476. Vector<real_t> domain_warp_fractal_lacunarity_2_3d = get_noise_samples_3d(noise);
  477. CHECK_FALSE(all_equal_approx(domain_warp_fractal_lacunarity_1_2d, domain_warp_fractal_lacunarity_2_2d));
  478. CHECK_FALSE(all_equal_approx(domain_warp_fractal_lacunarity_1_3d, domain_warp_fractal_lacunarity_2_3d));
  479. }
  480. SUBCASE("Different domain warp fractal gain should produce different results") {
  481. noise.set_domain_warp_fractal_gain(0.1);
  482. Vector<real_t> domain_warp_fractal_gain_1_2d = get_noise_samples_2d(noise);
  483. Vector<real_t> domain_warp_fractal_gain_1_3d = get_noise_samples_3d(noise);
  484. noise.set_domain_warp_fractal_gain(0.9);
  485. Vector<real_t> domain_warp_fractal_gain_2_2d = get_noise_samples_2d(noise);
  486. Vector<real_t> domain_warp_fractal_gain_2_3d = get_noise_samples_3d(noise);
  487. CHECK_FALSE(all_equal_approx(domain_warp_fractal_gain_1_2d, domain_warp_fractal_gain_2_2d));
  488. CHECK_FALSE(all_equal_approx(domain_warp_fractal_gain_1_3d, domain_warp_fractal_gain_2_3d));
  489. }
  490. }
  491. // Raw image data for the reference images used in the regression tests.
  492. // Generated with the following code:
  493. // for (int y = 0; y < img->get_data().size(); y++) {
  494. // printf("0x%x,", img->get_data()[y]);
  495. // }
  496. const 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 };
  497. const 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 };
  498. const 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 };
  499. // Utiliy function to compare two images pixel by pixel (for easy debugging of regressions)
  500. void compare_image_with_reference(const Ref<Image> &p_img, const Ref<Image> &p_reference_img) {
  501. for (int y = 0; y < p_img->get_height(); y++) {
  502. for (int x = 0; x < p_img->get_width(); x++) {
  503. CHECK(p_img->get_pixel(x, y) == p_reference_img->get_pixel(x, y));
  504. }
  505. }
  506. }
  507. TEST_CASE("[FastNoiseLite] Generating seamless 2D images (11x11px) and compare to reference images") {
  508. FastNoiseLite noise;
  509. noise.set_noise_type(FastNoiseLite::NoiseType::TYPE_CELLULAR);
  510. noise.set_fractal_type(FastNoiseLite::FractalType::FRACTAL_NONE);
  511. noise.set_cellular_distance_function(FastNoiseLite::CellularDistanceFunction::DISTANCE_EUCLIDEAN);
  512. noise.set_frequency(0.1);
  513. noise.set_cellular_jitter(0.0);
  514. SUBCASE("Blend skirt 0.0") {
  515. Ref<Image> img = noise.get_seamless_image(11, 11, false, false, 0.0);
  516. Ref<Image> ref_img_1 = memnew(Image);
  517. ref_img_1->set_data(11, 11, false, Image::FORMAT_L8, ref_img_1_data);
  518. compare_image_with_reference(img, ref_img_1);
  519. }
  520. SUBCASE("Blend skirt 0.1") {
  521. Ref<Image> img = noise.get_seamless_image(11, 11, false, false, 0.1);
  522. Ref<Image> ref_img_2 = memnew(Image);
  523. ref_img_2->set_data(11, 11, false, Image::FORMAT_L8, ref_img_2_data);
  524. compare_image_with_reference(img, ref_img_2);
  525. }
  526. SUBCASE("Blend skirt 1.0") {
  527. Ref<Image> img = noise.get_seamless_image(11, 11, false, false, 0.1);
  528. Ref<Image> ref_img_3 = memnew(Image);
  529. ref_img_3->set_data(11, 11, false, Image::FORMAT_L8, ref_img_3_data);
  530. compare_image_with_reference(img, ref_img_3);
  531. }
  532. }
  533. } //namespace TestFastNoiseLite
  534. #endif // TEST_FASTNOISE_LITE_H