Counter Strike : Global Offensive Source Code
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.

179 lines
5.3 KiB

  1. #include <tier0/platform.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <stdlib.h>
  6. #include "bitmap/floatbitmap.h"
  7. #include <filesystem.h>
  8. #include <mathlib/vector.h>
  9. #include "mathlib/spherical_geometry.h"
  10. // NOTE: This has to be the last file included!
  11. #include "tier0/memdbgon.h"
  12. static Vector face_xvector[6]={ // direction of x pixels on face
  13. Vector( - 1, 0, 0 ), // back
  14. Vector( 1, 0, 0 ), // down
  15. Vector( 1, 0, 0 ), // front
  16. Vector( 0, 1, 0 ), // left
  17. Vector( 0, - 1, 0 ), // right
  18. Vector( 1, 0, 0 ) // up
  19. };
  20. static Vector face_yvector[6]={ // direction of y pixels on face
  21. Vector( 0, 0, - 1 ), // back
  22. Vector( 0, 1, 0 ), // down
  23. Vector( 0, 0, - 1 ), // front
  24. Vector( 0, 0, - 1 ), // left
  25. Vector( 0, 0, - 1 ), // right
  26. Vector( 0, - 1, 0 ) // up
  27. };
  28. static Vector face_zvector[6]={
  29. Vector( 1, 1, 1 ), // back
  30. Vector( - 1, - 1, - 1 ), // down
  31. Vector( - 1, - 1, 1 ), // front
  32. Vector( 1, - 1, 1 ), // left
  33. Vector( - 1, 1, 1 ), // right
  34. Vector( - 1, 1, 1 ) // up
  35. };
  36. static char const *namepts[6]={"%sbk.pfm","%sdn.pfm","%sft.pfm","%slf.pfm","%srt.pfm","%sup.pfm"};
  37. FloatCubeMap_t::FloatCubeMap_t( char const *basename )
  38. {
  39. for( int f = 0;f < 6;f++ )
  40. {
  41. char fnamebuf[512];
  42. sprintf( fnamebuf, namepts[f], basename );
  43. face_maps[f].LoadFromPFM( fnamebuf );
  44. }
  45. }
  46. void FloatCubeMap_t::WritePFMs( char const *basename )
  47. {
  48. for( int f = 0;f < 6;f++ )
  49. {
  50. char fnamebuf[512];
  51. sprintf( fnamebuf, namepts[f], basename );
  52. face_maps[f].WritePFM( fnamebuf );
  53. }
  54. }
  55. Vector FloatCubeMap_t::PixelDirection( int face, int x, int y )
  56. {
  57. FloatBitMap_t const & bm = face_maps[face];
  58. float xc = x * 1.0 / ( bm.NumCols() - 1 );
  59. float yc = y * 1.0 / ( bm.NumRows() - 1 );
  60. Vector dir = 2 * xc * face_xvector[face]+
  61. 2 * yc * face_yvector[face]+ face_zvector[face];
  62. VectorNormalize( dir );
  63. return dir;
  64. }
  65. Vector FloatCubeMap_t::FaceNormal( int face )
  66. {
  67. float xc = 0.5;
  68. float yc = 0.5;
  69. Vector dir = 2 * xc * face_xvector[face]+
  70. 2 * yc * face_yvector[face]+ face_zvector[face];
  71. VectorNormalize( dir );
  72. return dir;
  73. }
  74. void FloatCubeMap_t::Resample( FloatCubeMap_t & out, float flPhongExponent )
  75. {
  76. // terribly slow brute force algorithm just so I can try it out
  77. for( int dface = 0;dface < 6;dface++ )
  78. {
  79. for( int dy = 0;dy < out.face_maps[dface].NumRows();dy++ )
  80. for( int dx = 0;dx < out.face_maps[dface].NumCols();dx++ )
  81. {
  82. float sum_weights = 0;
  83. float sum_rgb[3]={0, 0, 0};
  84. for( int sface = 0;sface < 6;sface++ )
  85. {
  86. // easy 15% optimization - check if faces point away from each other
  87. if ( DotProduct( FaceNormal( sface ), FaceNormal( sface ) ) >- 0.9 )
  88. {
  89. Vector ddir = out.PixelDirection( dface, dx, dy );
  90. for( int sy = 0;sy < face_maps[sface].NumRows();sy++ )
  91. for( int sx = 0;sx < face_maps[sface].NumCols();sx++ )
  92. {
  93. float dp = DotProduct( ddir, PixelDirection( sface, sx, sy ) );
  94. if ( dp > 0.0 )
  95. {
  96. dp = pow( dp, flPhongExponent );
  97. sum_weights += dp;
  98. for( int c = 0;c < 3;c++ )
  99. sum_rgb[c] += dp * face_maps[sface].Pixel( sx, sy, 0, c );
  100. }
  101. }
  102. }
  103. }
  104. for( int c = 0;c < 3;c++ )
  105. out.face_maps[dface].Pixel( dx, dy, 0, c ) = sum_rgb[c] * ( 1.0 / sum_weights );
  106. }
  107. }
  108. }
  109. void FloatCubeMap_t::CalculateSphericalHarmonicApproximation( int nOrder, Vector *flCoeffs )
  110. {
  111. for( int nL = 0; nL <= nOrder; nL++ )
  112. {
  113. for( int nM = - nL ; nM <= nL; nM++ )
  114. {
  115. Vector vecSum( 0, 0, 0 );
  116. float flSumWeights = 0.;
  117. for( int nFace = 0; nFace < 6; nFace++ )
  118. for( int nY = 0; nY < face_maps[nFace].NumRows(); nY++ )
  119. for( int nX = 0; nX < face_maps[nFace].NumCols(); nX++ )
  120. {
  121. // determine direction and area of sample. !!speed!! this could be incremental
  122. Vector dir00 = PixelDirection( nFace, nX, nY );
  123. Vector dir01 = PixelDirection( nFace, nX, nY + 1 );
  124. Vector dir10 = PixelDirection( nFace, nX + 1 , nY );
  125. Vector dir11 = PixelDirection( nFace, nX + 1, nY + 1 );
  126. float flArea = UnitSphereTriangleArea( dir00, dir10, dir11 ) +
  127. UnitSphereTriangleArea( dir00, dir01, dir11 );
  128. float flHarmonic = SphericalHarmonic( nL, nM, dir00 );
  129. flSumWeights += flArea;
  130. for( int c = 0; c < 3; c++ )
  131. vecSum[c] += flHarmonic * face_maps[nFace].Pixel( nX, nY, 0, c ) * flArea;
  132. }
  133. vecSum *= ( ( 4 * M_PI ) / flSumWeights );
  134. *( flCoeffs++ ) = vecSum;
  135. }
  136. }
  137. }
  138. void FloatCubeMap_t::GenerateFromSphericalHarmonics( int nOrder, Vector const *flCoeffs )
  139. {
  140. for( int nFace = 0; nFace < 6; nFace++ )
  141. face_maps[nFace].Clear( 0, 0, 0, 1 );
  142. for( int nL = 0; nL <= nOrder; nL++ )
  143. {
  144. for( int nM = - nL ; nM <= nL; nM++ )
  145. {
  146. for( int nFace = 0; nFace < 6; nFace++ )
  147. for( int nY = 0; nY < face_maps[nFace].NumRows(); nY++ )
  148. for( int nX = 0; nX < face_maps[nFace].NumCols(); nX++ )
  149. {
  150. // determine direction and area of sample. !!speed!! this could be incremental
  151. Vector dir00 = PixelDirection( nFace, nX, nY );
  152. float flHarmonic = SphericalHarmonic( nL, nM, dir00 );
  153. for( int c = 0; c < 3; c++ )
  154. face_maps[nFace].Pixel( nX, nY, 0, c ) += ( *flCoeffs )[c] * flHarmonic;
  155. }
  156. flCoeffs++;
  157. }
  158. }
  159. }