You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

98 line
3.4 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net>
  5. // © 2013—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
  6. // © 2013—2015 Guillaume Bittoun <guillaume.bittoun@gmail.com>
  7. //
  8. // Lol Engine is free software. It comes without any warranty, to
  9. // the extent permitted by applicable law. You can redistribute it
  10. // and/or modify it under the terms of the Do What the Fuck You Want
  11. // to Public License, Version 2, as published by the WTFPL Task Force.
  12. // See http://www.wtfpl.net/ for more details.
  13. //
  14. #pragma once
  15. #include <functional>
  16. namespace lol
  17. {
  18. template<int N>
  19. class gradient_provider
  20. {
  21. public:
  22. gradient_provider(int seed = 0)
  23. : m_seed(seed)
  24. {
  25. }
  26. protected:
  27. vec_t<float, N> get_gradient(vec_t<int, N> origin) const
  28. {
  29. /* Quick shuffle table:
  30. * strings /dev/urandom | grep . -nm256 | sort -k2 -t: | sed 's|:.*|,|'
  31. * Then just replace “256” with “0”. */
  32. static int const shuffle[256] =
  33. {
  34. 111, 14, 180, 186, 221, 114, 219, 79, 66, 46, 152, 81, 246, 200,
  35. 141, 172, 85, 244, 112, 92, 34, 106, 218, 205, 236, 7, 121, 115,
  36. 109, 131, 10, 96, 188, 148, 17, 107, 94, 182, 235, 163, 143, 63,
  37. 248, 202, 52, 154, 37, 241, 53, 129, 25, 159, 242, 38, 171, 213,
  38. 6, 203, 255, 193, 42, 209, 28, 176, 210, 60, 54, 144, 3, 71, 89,
  39. 116, 12, 237, 67, 216, 252, 178, 174, 164, 98, 234, 32, 26, 175,
  40. 24, 130, 128, 113, 99, 212, 62, 11, 75, 185, 73, 93, 31, 30, 44,
  41. 122, 173, 139, 91, 136, 162, 194, 41, 56, 101, 68, 69, 211, 151,
  42. 97, 55, 83, 33, 50, 119, 156, 149, 208, 157, 253, 247, 161, 133,
  43. 230, 166, 225, 204, 224, 13, 110, 123, 142, 64, 65, 155, 215, 9,
  44. 197, 140, 58, 77, 214, 126, 195, 179, 220, 232, 125, 147, 8, 39,
  45. 187, 27, 217, 100, 134, 199, 88, 206, 231, 250, 74, 2, 135, 120,
  46. 21, 245, 118, 243, 82, 183, 238, 150, 158, 61, 4, 177, 146, 153,
  47. 117, 249, 254, 233, 90, 222, 207, 48, 15, 18, 20, 16, 47, 0, 51,
  48. 165, 138, 127, 169, 72, 1, 201, 145, 191, 192, 239, 49, 19, 160,
  49. 226, 228, 84, 181, 251, 36, 87, 22, 43, 70, 45, 105, 5, 189, 95,
  50. 40, 196, 59, 57, 190, 80, 104, 167, 78, 124, 103, 240, 184, 170,
  51. 137, 29, 23, 223, 108, 102, 86, 198, 227, 35, 229, 76, 168, 132,
  52. };
  53. /* Generate 2^(N+2) random vectors, but at least 2^5 (32) and not
  54. * more than 2^20 (~ 1 million). */
  55. int const gradient_count = 1 << min(max(N + 2, 5), 20);
  56. static auto build_gradients = [&]()
  57. {
  58. array<vec_t<float, N>> ret;
  59. for (int k = 0; k < gradient_count; ++k)
  60. {
  61. vec_t<float, N> v;
  62. for (int i = 0; i < N; ++i)
  63. v[i] = rand(-1.f, 1.f);
  64. ret << normalize(v);
  65. }
  66. return ret;
  67. };
  68. static array<vec_t<float, N>> const gradients = build_gradients();
  69. int idx = m_seed;
  70. for (int i = 0; i < N; ++i)
  71. idx ^= shuffle[(idx + origin[i]) & 255];
  72. idx &= (gradient_count - 1);
  73. #if 0
  74. // DEBUG: only output a few gradients
  75. if (idx > 2)
  76. return vec_t<float, N>(0);
  77. #endif
  78. return gradients[idx];
  79. }
  80. private:
  81. /* A user-provided random seed. Defaults to zero. */
  82. int m_seed;
  83. };
  84. }