catmullRom.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "util/catmullRom.h"
  24. #include "math/mMathFn.h"
  25. const F32 CatmullRomBase::smX[] =
  26. {
  27. 0.0000000000f, 0.5384693101f, -0.5384693101f, 0.9061798459f, -0.9061798459f
  28. };
  29. const F32 CatmullRomBase::smC[] =
  30. {
  31. 0.5688888889f, 0.4786286705f, 0.4786286705f, 0.2369268850f, 0.2369268850f
  32. };
  33. CatmullRomBase::CatmullRomBase()
  34. : mTimes( NULL ),
  35. mLengths( NULL ),
  36. mTotalLength( 0.0f ),
  37. mCount( 0 )
  38. {
  39. }
  40. void CatmullRomBase::_initialize( U32 count, const F32 *times )
  41. {
  42. //AssertFatal( times, "CatmullRomBase::_initialize() - Got null position!" )
  43. AssertFatal( count > 1, "CatmullRomBase::_initialize() - Must have more than 2 points!" );
  44. // set up arrays
  45. mTimes = new F32[count];
  46. mCount = count;
  47. // set up curve segment lengths
  48. mLengths = new F32[count-1];
  49. mTotalLength = 0.0f;
  50. for ( U32 i = 0; i < count-1; ++i )
  51. {
  52. mLengths[i] = segmentArcLength(i, 0.0f, 1.0f);
  53. mTotalLength += mLengths[i];
  54. }
  55. // copy the times if we have them.
  56. F32 l = 0.0f;
  57. for ( U32 i = 0; i < count; ++i )
  58. {
  59. if ( times )
  60. mTimes[i] = times[i];
  61. else
  62. {
  63. if ( mIsZero( mTotalLength ) )
  64. mTimes[i] = 0.0f;
  65. else
  66. mTimes[i] = l / mTotalLength;
  67. if ( i < count-1 )
  68. l += mLengths[i];
  69. }
  70. }
  71. }
  72. void CatmullRomBase::clear()
  73. {
  74. delete [] mTimes;
  75. mTimes = NULL;
  76. delete [] mLengths;
  77. mLengths = NULL;
  78. mTotalLength = 0.0f;
  79. mCount = 0;
  80. }
  81. F32 CatmullRomBase::arcLength( F32 t1, F32 t2 )
  82. {
  83. if ( t2 <= t1 )
  84. return 0.0f;
  85. if ( t1 < mTimes[0] )
  86. t1 = mTimes[0];
  87. if ( t2 > mTimes[mCount-1] )
  88. t2 = mTimes[mCount-1];
  89. // find segment and parameter
  90. U32 seg1;
  91. for ( seg1 = 0; seg1 < mCount-1; ++seg1 )
  92. {
  93. if ( t1 <= mTimes[seg1+1] )
  94. {
  95. break;
  96. }
  97. }
  98. F32 u1 = (t1 - mTimes[seg1])/(mTimes[seg1+1] - mTimes[seg1]);
  99. // find segment and parameter
  100. U32 seg2;
  101. for ( seg2 = 0; seg2 < mCount-1; ++seg2 )
  102. {
  103. if ( t2 <= mTimes[seg2+1] )
  104. {
  105. break;
  106. }
  107. }
  108. F32 u2 = (t2 - mTimes[seg2])/(mTimes[seg2+1] - mTimes[seg2]);
  109. F32 result;
  110. // both parameters lie in one segment
  111. if ( seg1 == seg2 )
  112. {
  113. result = segmentArcLength( seg1, u1, u2 );
  114. }
  115. // parameters cross segments
  116. else
  117. {
  118. result = segmentArcLength( seg1, u1, 1.0f );
  119. for ( U32 i = seg1+1; i < seg2; ++i )
  120. result += mLengths[i];
  121. result += segmentArcLength( seg2, 0.0f, u2 );
  122. }
  123. return result;
  124. }
  125. U32 CatmullRomBase::getPrevNode( F32 t )
  126. {
  127. AssertFatal( mCount >= 2, "CatmullRomBase::getPrevNode - Bad point count!" );
  128. // handle boundary conditions
  129. if ( t <= mTimes[0] )
  130. return 0;
  131. else if ( t >= mTimes[mCount-1] )
  132. return mCount-1;
  133. // find segment and parameter
  134. U32 i; // segment #
  135. for ( i = 0; i < mCount-1; ++i )
  136. {
  137. if ( t <= mTimes[i+1] )
  138. break;
  139. }
  140. AssertFatal( i >= 0 && i < mCount, "CatmullRomBase::getPrevNode - Got bad output index!" );
  141. return i;
  142. }
  143. F32 CatmullRomBase::getTime( U32 idx )
  144. {
  145. AssertFatal( idx >= 0 && idx < mCount, "CatmullRomBase::getTime - Got bad index!" );
  146. return mTimes[idx];
  147. }