Team Fortress 2 Source Code as on 22/4/2020
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.

124 lines
3.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: spherical math routines
  4. //
  5. //=====================================================================================//
  6. #include <math.h>
  7. #include <float.h> // Needed for FLT_EPSILON
  8. #include "basetypes.h"
  9. #include <memory.h>
  10. #include "tier0/dbg.h"
  11. #include "mathlib/mathlib.h"
  12. #include "mathlib/vector.h"
  13. #include "mathlib/spherical_geometry.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. float s_flFactorials[]={
  17. 1.,
  18. 1.,
  19. 2.,
  20. 6.,
  21. 24.,
  22. 120.,
  23. 720.,
  24. 5040.,
  25. 40320.,
  26. 362880.,
  27. 3628800.,
  28. 39916800.,
  29. 479001600.,
  30. 6227020800.,
  31. 87178291200.,
  32. 1307674368000.,
  33. 20922789888000.,
  34. 355687428096000.,
  35. 6402373705728000.,
  36. 121645100408832000.,
  37. 2432902008176640000.,
  38. 51090942171709440000.,
  39. 1124000727777607680000.,
  40. 25852016738884976640000.,
  41. 620448401733239439360000.,
  42. 15511210043330985984000000.,
  43. 403291461126605635584000000.,
  44. 10888869450418352160768000000.,
  45. 304888344611713860501504000000.,
  46. 8841761993739701954543616000000.,
  47. 265252859812191058636308480000000.,
  48. 8222838654177922817725562880000000.,
  49. 263130836933693530167218012160000000.,
  50. 8683317618811886495518194401280000000.
  51. };
  52. float AssociatedLegendrePolynomial( int nL, int nM, float flX )
  53. {
  54. // evaluate associated legendre polynomial at flX, using recurrence relation
  55. float flPmm = 1.;
  56. if ( nM > 0 )
  57. {
  58. float flSomX2 = sqrt( ( 1 - flX ) * ( 1 + flX ) );
  59. float flFact = 1.;
  60. for( int i = 0 ; i < nM; i++ )
  61. {
  62. flPmm *= -flFact * flSomX2;
  63. flFact += 2.0;
  64. }
  65. }
  66. if ( nL == nM )
  67. return flPmm;
  68. float flPmmp1 = flX * ( 2.0 * nM + 1.0 ) * flPmm;
  69. if ( nL == nM + 1 )
  70. return flPmmp1;
  71. float flPll = 0.;
  72. for( int nLL = nM + 2 ; nLL <= nL; nLL++ )
  73. {
  74. flPll = ( ( 2.0 * nLL - 1.0 ) * flX * flPmmp1 - ( nLL + nM - 1.0 ) * flPmm ) * ( 1.0 / ( nLL - nM ) );
  75. flPmm = flPmmp1;
  76. flPmmp1 = flPll;
  77. }
  78. return flPll;
  79. }
  80. static float SHNormalizationFactor( int nL, int nM )
  81. {
  82. double flTemp = ( ( 2. * nL + 1.0 ) * s_flFactorials[ nL - nM ] )/ ( 4. * M_PI * s_flFactorials[ nL + nM ] );
  83. return sqrt( flTemp );
  84. }
  85. #define SQRT_2 1.414213562373095
  86. FORCEINLINE float SphericalHarmonic( int nL, int nM, float flTheta, float flPhi, float flCosTheta )
  87. {
  88. if ( nM == 0 )
  89. return SHNormalizationFactor( nL, 0 ) * AssociatedLegendrePolynomial( nL, nM, flCosTheta );
  90. if ( nM > 0 )
  91. return SQRT_2 * SHNormalizationFactor( nL, nM ) * cos ( nM * flPhi ) *
  92. AssociatedLegendrePolynomial( nL, nM, flCosTheta );
  93. return
  94. SQRT_2 * SHNormalizationFactor( nL, -nM ) * sin( -nM * flPhi ) * AssociatedLegendrePolynomial( nL, -nM, flCosTheta );
  95. }
  96. float SphericalHarmonic( int nL, int nM, float flTheta, float flPhi )
  97. {
  98. return SphericalHarmonic( nL, nM, flTheta, flPhi, cos( flTheta ) );
  99. }
  100. float SphericalHarmonic( int nL, int nM, Vector const &vecDirection )
  101. {
  102. Assert( fabs( VectorLength( vecDirection ) - 1.0 ) < 0.0001 );
  103. float flPhi = acos( vecDirection.z );
  104. float flTheta = 0;
  105. float S = Square( vecDirection.x ) + Square( vecDirection.y );
  106. if ( S > 0 )
  107. {
  108. flTheta = atan2( vecDirection.y, vecDirection.x );
  109. }
  110. return SphericalHarmonic( nL, nM, flTheta, flPhi, cos( flTheta ) );
  111. }