Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

162 righe
4.7 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2013-2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
  6. // (c) 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com>
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the Do What The Fuck You Want To
  9. // Public License, Version 2, as published by Sam Hocevar. See
  10. // http://www.wtfpl.net/ for more details.
  11. //
  12. #pragma once
  13. namespace lol
  14. {
  15. template<int N, /* Dimension of the space */
  16. typename T = float> /* Interpolated type */
  17. class simplex_interpolator
  18. {
  19. public:
  20. simplex_interpolator(arraynd<N, T> const & samples) :
  21. m_samples(samples)
  22. {
  23. this->InitBase();
  24. }
  25. inline arraynd<N, T> const & GetSamples() const
  26. {
  27. return this->m_samples;
  28. }
  29. // Single interpolation
  30. inline T Interp(vec_t<float, N> position) const
  31. {
  32. // Computing position in simplex referential
  33. vec_t<float, N> simplex_position = m_base_inverse * position;
  34. // Retrieving the closest floor point and decimals
  35. vec_t<int, N> floor_point;
  36. vec_t<float, N> decimal_point;
  37. this->ExtractFloorDecimal(simplex_position, floor_point, decimal_point);
  38. // Retrieving simplex samples to use
  39. int sign;
  40. this->GetReference(floor_point, decimal_point, sign);
  41. return this->LastInterp(floor_point, decimal_point, sign);
  42. }
  43. protected:
  44. inline T LastInterp(vec_t<int, N> const & floor_point,
  45. vec_t<float, N> const & decimal_point,
  46. int const & sign) const
  47. {
  48. T result(0);
  49. float floor_coeff = 0;
  50. float divider = 0;
  51. for (int i = 0 ; i < N ; ++i)
  52. {
  53. vec_t<int, N> samples_index = floor_point;
  54. samples_index[i] = this->Mod(samples_index[i] + sign, i);
  55. result += decimal_point[i] * this->m_samples[samples_index];
  56. floor_coeff += decimal_point[i];
  57. divider += decimal_point[i];
  58. }
  59. float sqr_norm = N;
  60. result += (1 - 2 * floor_coeff / sqr_norm) * this->m_samples[floor_point];
  61. divider += (1 - 2 * floor_coeff / sqr_norm);
  62. return result / divider;
  63. }
  64. inline int Mod(int value, int index) const
  65. {
  66. int const dim = this->m_samples.GetSize()[index];
  67. int const ret = value % dim;
  68. return ret >= 0 ? ret : ret + dim;
  69. }
  70. inline void GetReference(vec_t<int, N> & floor_point, vec_t<float, N> & decimal_point, int & sign) const
  71. {
  72. // Choosing the reference point which determines in which simplex we are working
  73. // ie. (0, 0, 0, …) and upper or (1, 1, 1, …) and lower
  74. float cumul = 0;
  75. for (int i = 0 ; i < N ; ++i)
  76. cumul += decimal_point[i];
  77. if (cumul < (sqrt((float)N) / 2))
  78. sign = 1;
  79. else
  80. {
  81. sign = -1;
  82. decimal_point = vec_t<float, N>(1) - decimal_point;
  83. floor_point = floor_point + vec_t<int, N>(1);
  84. }
  85. }
  86. inline void ExtractFloorDecimal(vec_t<float, N> const & simplex_position, vec_t<int, N> & floor_point, vec_t<float, N> & decimal_point) const
  87. {
  88. // Finding floor point index
  89. for (int i = 0 ; i < N ; ++i)
  90. floor_point[i] = (int) simplex_position[i];
  91. // Extracting decimal part from simplex sample
  92. for (int i = 0 ; i < N ; ++i)
  93. decimal_point[i] = simplex_position[i] - floor_point[i];
  94. // Never exceed the size of the samples and loop on it
  95. for (int i = 0 ; i < N ; ++i)
  96. floor_point[i] = this->Mod(floor_point[i], i);
  97. }
  98. inline void InitBase()
  99. {
  100. /* Matrix coordinate transformation to skew simplex referential is done
  101. by inversing the base matrix M which is written as follows:
  102. M = | a b b b … | M^(-1) = | c d d d … |
  103. | b a b b … | | d c d d … |
  104. | b b a b … | | d d c d … |
  105. | … | | … |
  106. where a and b are computed below ↴
  107. */
  108. T b = (1 - sqrt((N+1)))/(N * N * N));
  109. T a = b + sqrt((N+1)/N);
  110. // determinant of matrix M
  111. T det = a * (a + (N-2) * b) - (b * b) * (N-1);
  112. T c = (a + (N-2)*b) / det;
  113. T d = b / det;
  114. for (int i = 0; i < N; ++i)
  115. {
  116. for (int j = 0; j < N; ++j)
  117. {
  118. m_base[i][j] = (i == j ? a : b);
  119. m_base_inverse[i][j] = (i == j ? c : d);
  120. }
  121. }
  122. }
  123. mat_t<float, N, N> m_base, m_base_inverse;
  124. arraynd<N, T> m_samples;
  125. };
  126. }