catmullRom.cpp

Engine/source/util/catmullRom.cpp

More...

Detailed Description

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