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.

109 lines
4.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Fast low quality noise suitable for real time use
  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/ssemath.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. #include "noisedata.h"
  17. #define MAGIC_NUMBER (1<<15) // gives 8 bits of fraction
  18. static fltx4 Four_MagicNumbers = { MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER };
  19. static ALIGN16 int32 idx_mask[4]= {0xffff, 0xffff, 0xffff, 0xffff};
  20. #define MASK255 (*((fltx4 *)(& idx_mask )))
  21. // returns 0..1
  22. static inline float GetLatticePointValue( int idx_x, int idx_y, int idx_z )
  23. {
  24. NOTE_UNUSED(perm_d);
  25. NOTE_UNUSED(impulse_ycoords);
  26. NOTE_UNUSED(impulse_zcoords);
  27. int ret_idx = perm_a[idx_x & 0xff];
  28. ret_idx = perm_b[( idx_y + ret_idx ) & 0xff];
  29. ret_idx = perm_c[( idx_z + ret_idx ) & 0xff];
  30. return impulse_xcoords[ret_idx];
  31. }
  32. fltx4 NoiseSIMD( const fltx4 & x, const fltx4 & y, const fltx4 & z )
  33. {
  34. // use magic to convert to integer index
  35. fltx4 x_idx = AndSIMD( MASK255, AddSIMD( x, Four_MagicNumbers ) );
  36. fltx4 y_idx = AndSIMD( MASK255, AddSIMD( y, Four_MagicNumbers ) );
  37. fltx4 z_idx = AndSIMD( MASK255, AddSIMD( z, Four_MagicNumbers ) );
  38. fltx4 lattice000 = Four_Zeros, lattice001 = Four_Zeros, lattice010 = Four_Zeros, lattice011 = Four_Zeros;
  39. fltx4 lattice100 = Four_Zeros, lattice101 = Four_Zeros, lattice110 = Four_Zeros, lattice111 = Four_Zeros;
  40. // FIXME: Converting the input vectors to int indices will cause load-hit-stores (48 bytes)
  41. // Converting the indexed noise values back to vectors will cause more (128 bytes)
  42. // The noise table could store vectors if we chunked it into 2x2x2 blocks.
  43. fltx4 xfrac = Four_Zeros, yfrac = Four_Zeros, zfrac = Four_Zeros;
  44. #define DOPASS(i) \
  45. { unsigned int xi = SubInt( x_idx, i ); \
  46. unsigned int yi = SubInt( y_idx, i ); \
  47. unsigned int zi = SubInt( z_idx, i ); \
  48. SubFloat( xfrac, i ) = (xi & 0xff)*(1.0/256.0); \
  49. SubFloat( yfrac, i ) = (yi & 0xff)*(1.0/256.0); \
  50. SubFloat( zfrac, i ) = (zi & 0xff)*(1.0/256.0); \
  51. xi>>=8; \
  52. yi>>=8; \
  53. zi>>=8; \
  54. \
  55. SubFloat( lattice000, i ) = GetLatticePointValue( xi,yi,zi ); \
  56. SubFloat( lattice001, i ) = GetLatticePointValue( xi,yi,zi+1 ); \
  57. SubFloat( lattice010, i ) = GetLatticePointValue( xi,yi+1,zi ); \
  58. SubFloat( lattice011, i ) = GetLatticePointValue( xi,yi+1,zi+1 ); \
  59. SubFloat( lattice100, i ) = GetLatticePointValue( xi+1,yi,zi ); \
  60. SubFloat( lattice101, i ) = GetLatticePointValue( xi+1,yi,zi+1 ); \
  61. SubFloat( lattice110, i ) = GetLatticePointValue( xi+1,yi+1,zi ); \
  62. SubFloat( lattice111, i ) = GetLatticePointValue( xi+1,yi+1,zi+1 ); \
  63. }
  64. DOPASS( 0 );
  65. DOPASS( 1 );
  66. DOPASS( 2 );
  67. DOPASS( 3 );
  68. // now, we have 8 lattice values for each of four points as m128s, and interpolant values for
  69. // each axis in m128 form in [xyz]frac. Perfom the trilinear interpolation as SIMD ops
  70. // first, do x interpolation
  71. fltx4 l2d00 = AddSIMD( lattice000, MulSIMD( xfrac, SubSIMD( lattice100, lattice000 ) ) );
  72. fltx4 l2d01 = AddSIMD( lattice001, MulSIMD( xfrac, SubSIMD( lattice101, lattice001 ) ) );
  73. fltx4 l2d10 = AddSIMD( lattice010, MulSIMD( xfrac, SubSIMD( lattice110, lattice010 ) ) );
  74. fltx4 l2d11 = AddSIMD( lattice011, MulSIMD( xfrac, SubSIMD( lattice111, lattice011 ) ) );
  75. // now, do y interpolation
  76. fltx4 l1d0 = AddSIMD( l2d00, MulSIMD( yfrac, SubSIMD( l2d10, l2d00 ) ) );
  77. fltx4 l1d1 = AddSIMD( l2d01, MulSIMD( yfrac, SubSIMD( l2d11, l2d01 ) ) );
  78. // final z interpolation
  79. fltx4 rslt = AddSIMD( l1d0, MulSIMD( zfrac, SubSIMD( l1d1, l1d0 ) ) );
  80. // map to 0..1
  81. return MulSIMD( Four_Twos, SubSIMD( rslt, Four_PointFives ) );
  82. }
  83. fltx4 NoiseSIMD( FourVectors const &pos )
  84. {
  85. return NoiseSIMD( pos.x, pos.y, pos.z );
  86. }