catmullRom.cpp
Engine/source/util/catmullRom.cpp
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