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.

199 lines
4.8 KiB

  1. #include "movieobjects/timeutils.h"
  2. #include "tier0/dbg.h"
  3. #include "mathlib/mathlib.h"
  4. #include <math.h>
  5. ////////////////////////////////////////////////////////////////////////////////////////
  6. //
  7. // DmeFramerate_t
  8. //
  9. // exact (rational) representation of common framerates - any integral or ntsc framerate
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////////////
  12. DmeFramerate_t::DmeFramerate_t( float fps )
  13. {
  14. SetFramerate( fps );
  15. }
  16. DmeFramerate_t::DmeFramerate_t( int fps /*= 0*/ ) :
  17. m_num( fps ), m_den( 10000 )
  18. {
  19. }
  20. DmeFramerate_t::DmeFramerate_t( int nNumerator, int nDenominator ) :
  21. m_num( nNumerator ), m_den( nDenominator * 10000 )
  22. {
  23. }
  24. void DmeFramerate_t::SetFramerate( float flFrameRate )
  25. {
  26. if ( IsIntegralValue( flFrameRate ) )
  27. {
  28. SetFramerate( RoundFloatToInt( flFrameRate ) );
  29. }
  30. else if ( IsIntegralValue( flFrameRate * 1001.0f / 1000.0f ) ) // 1001 is the ntsc divisor (30*1000/1001 = 29.97, etc)
  31. {
  32. SetFramerateNTSC( RoundFloatToInt( flFrameRate * 1001.0f / 1000.0f ) );
  33. }
  34. else
  35. {
  36. Assert( 0 );
  37. SetFramerate( RoundFloatToInt( flFrameRate ) );
  38. }
  39. }
  40. void DmeFramerate_t::SetFramerate( int fps )
  41. {
  42. m_num = fps;
  43. m_den = 10000;
  44. }
  45. // other (uncommon) options besides 30(29.97 - ntsc video) are 24 (23.976 - ntsc film) and 60 (59.94 - ntsc progressive)
  46. void DmeFramerate_t::SetFramerateNTSC( int multiplier /*= 30*/ )
  47. {
  48. // ntsc = 30 fps * 1000 / 1001
  49. // = ( 30 / 10000 fptms ) * 1000 / 1001
  50. // = 30 / 10010
  51. m_num = multiplier;
  52. m_den = 10010;
  53. }
  54. float DmeFramerate_t::GetFramesPerSecond() const
  55. {
  56. return 10000.0f * m_num / float( m_den );
  57. }
  58. ////////////////////////////////////////////////////////////////////////////////////////
  59. //
  60. // DmeTime_t
  61. //
  62. // representing time as integral tenths of a millisecond (tms)
  63. //
  64. ////////////////////////////////////////////////////////////////////////////////////////
  65. DmeTime_t::DmeTime_t( int frame, DmeFramerate_t framerate )
  66. {
  67. __int64 num = __int64( framerate.m_num );
  68. __int64 prod = frame * __int64( framerate.m_den );
  69. // add signed offset to force integer truncation (towards 0) to give us truncation towards -inf
  70. if ( frame < 0 )
  71. {
  72. prod -= num - 1;
  73. }
  74. m_tms = int( prod / num ); // round tms towards 0
  75. }
  76. // float operators - comment these out to find potentially incorrect uses of DmeTime_t
  77. DmeTime_t DmeTime_t::operator*=( float f )
  78. {
  79. m_tms = int( floor( m_tms * f + 0.5f ) );
  80. return *this;
  81. }
  82. DmeTime_t DmeTime_t::operator/=( float f )
  83. {
  84. m_tms = int( floor( m_tms / f + 0.5f ) );
  85. return *this;
  86. }
  87. // helper methods
  88. void DmeTime_t::Clamp( DmeTime_t lo, DmeTime_t hi )
  89. {
  90. m_tms = clamp( m_tms, lo.m_tms, hi.m_tms );
  91. }
  92. bool DmeTime_t::IsInRange( DmeTime_t lo, DmeTime_t hi ) const
  93. {
  94. return m_tms >= lo.m_tms && m_tms < hi.m_tms;
  95. }
  96. // helper functions
  97. float GetFractionOfTimeBetween( DmeTime_t t, DmeTime_t start, DmeTime_t end, bool bClamp /*= false*/ )
  98. {
  99. return GetFractionOfTime( t - start, end - start, bClamp );
  100. }
  101. float GetFractionOfTime( DmeTime_t t, DmeTime_t duration, bool bClamp /*= false*/ )
  102. {
  103. if ( duration == DMETIME_ZERO )
  104. return 0.0f;
  105. if ( bClamp )
  106. {
  107. t.Clamp( DMETIME_ZERO, duration );
  108. }
  109. return t.m_tms / float( duration.m_tms );
  110. }
  111. int FrameForTime( DmeTime_t t, DmeFramerate_t framerate )
  112. {
  113. return t.CurrentFrame( framerate );
  114. }
  115. // framerate-dependent conversions to/from frames
  116. int DmeTime_t::CurrentFrame( DmeFramerate_t framerate, bool bRoundDown ) const
  117. {
  118. __int64 den = __int64( framerate.m_den );
  119. __int64 num = __int64( framerate.m_num );
  120. __int64 prod = __int64( m_tms ) * num;
  121. // times within this range are considered on a frame: (frame*den/num - 1, frame*den/num]
  122. // this follows from the truncation towards -inf behavior of the frame,framerate constructor above
  123. // the following logic is there to ensure the above rule,
  124. // while working around the truncation towards 0 behavior of integer divide
  125. if ( m_tms < 0 )
  126. {
  127. if ( bRoundDown )
  128. prod -= den - num;
  129. }
  130. else
  131. {
  132. if ( bRoundDown )
  133. prod += num - 1;
  134. else
  135. prod += den - 1;
  136. }
  137. return int( prod / den );
  138. }
  139. DmeTime_t DmeTime_t::TimeAtCurrentFrame( DmeFramerate_t framerate, bool bRoundDown ) const
  140. {
  141. int frame = CurrentFrame( framerate, bRoundDown );
  142. return DmeTime_t( frame, framerate );
  143. }
  144. DmeTime_t DmeTime_t::TimeAtNextFrame( DmeFramerate_t framerate ) const
  145. {
  146. // since we always round towards -inf, go to next frame whether we're on a frame or not
  147. int frame = CurrentFrame( framerate, true );
  148. return DmeTime_t( frame + 1, framerate );
  149. }
  150. DmeTime_t DmeTime_t::TimeAtPrevFrame( DmeFramerate_t framerate ) const
  151. {
  152. int frame = CurrentFrame( framerate, false );
  153. return DmeTime_t( frame - 1, framerate ); // we're exactly on a frame
  154. }
  155. int DmeTime_t::RoundSecondsToTMS( float sec )
  156. {
  157. return floor( 10000.0f * sec + 0.5f ); // round at half-tms boundary
  158. }
  159. int DmeTime_t::RoundSecondsToTMS( double sec )
  160. {
  161. return floor( 10000.0 * sec + 0.5 ); // round at half-tms boundary
  162. }