Curve.h 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __MATH_CURVE_H__
  21. #define __MATH_CURVE_H__
  22. /*
  23. ===============================================================================
  24. Curve base template.
  25. ===============================================================================
  26. */
  27. template< class type >
  28. class idCurve {
  29. public:
  30. idCurve();
  31. virtual ~idCurve();
  32. virtual int AddValue( const float time, const type &value );
  33. virtual void RemoveIndex( const int index ) { values.RemoveIndex(index); times.RemoveIndex(index); changed = true; }
  34. virtual void Clear() { values.Clear(); times.Clear(); currentIndex = -1; changed = true; }
  35. virtual type GetCurrentValue( const float time ) const;
  36. virtual type GetCurrentFirstDerivative( const float time ) const;
  37. virtual type GetCurrentSecondDerivative( const float time ) const;
  38. virtual bool IsDone( const float time ) const;
  39. int GetNumValues() const { return values.Num(); }
  40. void SetValue( const int index, const type &value ) { values[index] = value; changed = true; }
  41. type GetValue( const int index ) const { return values[index]; }
  42. type * GetValueAddress( const int index ) { return &values[index]; }
  43. float GetTime( const int index ) const { return times[index]; }
  44. float GetLengthForTime( const float time ) const;
  45. float GetTimeForLength( const float length, const float epsilon = 0.1f ) const;
  46. float GetLengthBetweenKnots( const int i0, const int i1 ) const;
  47. void MakeUniform( const float totalTime );
  48. void SetConstantSpeed( const float totalTime );
  49. void ShiftTime( const float deltaTime );
  50. void Translate( const type &translation );
  51. protected:
  52. idList<float> times; // knots
  53. idList<type> values; // knot values
  54. mutable int currentIndex; // cached index for fast lookup
  55. mutable bool changed; // set whenever the curve changes
  56. int IndexForTime( const float time ) const;
  57. float TimeForIndex( const int index ) const;
  58. type ValueForIndex( const int index ) const;
  59. float GetSpeed( const float time ) const;
  60. float RombergIntegral( const float t0, const float t1, const int order ) const;
  61. };
  62. /*
  63. ====================
  64. idCurve::idCurve
  65. ====================
  66. */
  67. template< class type >
  68. ID_INLINE idCurve<type>::idCurve() {
  69. currentIndex = -1;
  70. changed = false;
  71. }
  72. /*
  73. ====================
  74. idCurve::~idCurve
  75. ====================
  76. */
  77. template< class type >
  78. ID_INLINE idCurve<type>::~idCurve() {
  79. }
  80. /*
  81. ====================
  82. idCurve::AddValue
  83. add a timed/value pair to the spline
  84. returns the index to the inserted pair
  85. ====================
  86. */
  87. template< class type >
  88. ID_INLINE int idCurve<type>::AddValue( const float time, const type &value ) {
  89. int i;
  90. i = IndexForTime( time );
  91. times.Insert( time, i );
  92. values.Insert( value, i );
  93. changed = true;
  94. return i;
  95. }
  96. /*
  97. ====================
  98. idCurve::GetCurrentValue
  99. get the value for the given time
  100. ====================
  101. */
  102. template< class type >
  103. ID_INLINE type idCurve<type>::GetCurrentValue( const float time ) const {
  104. int i;
  105. i = IndexForTime( time );
  106. if ( i >= values.Num() ) {
  107. return values[values.Num() - 1];
  108. } else {
  109. return values[i];
  110. }
  111. }
  112. /*
  113. ====================
  114. idCurve::GetCurrentFirstDerivative
  115. get the first derivative for the given time
  116. ====================
  117. */
  118. template< class type >
  119. ID_INLINE type idCurve<type>::GetCurrentFirstDerivative( const float time ) const {
  120. return ( values[0] - values[0] ); //-V501
  121. }
  122. /*
  123. ====================
  124. idCurve::GetCurrentSecondDerivative
  125. get the second derivative for the given time
  126. ====================
  127. */
  128. template< class type >
  129. ID_INLINE type idCurve<type>::GetCurrentSecondDerivative( const float time ) const {
  130. return ( values[0] - values[0] ); //-V501
  131. }
  132. /*
  133. ====================
  134. idCurve::IsDone
  135. ====================
  136. */
  137. template< class type >
  138. ID_INLINE bool idCurve<type>::IsDone( const float time ) const {
  139. return ( time >= times[ times.Num() - 1 ] );
  140. }
  141. /*
  142. ====================
  143. idCurve::GetSpeed
  144. ====================
  145. */
  146. template< class type >
  147. ID_INLINE float idCurve<type>::GetSpeed( const float time ) const {
  148. int i;
  149. float speed;
  150. type value;
  151. value = GetCurrentFirstDerivative( time );
  152. for ( speed = 0.0f, i = 0; i < value.GetDimension(); i++ ) {
  153. speed += value[i] * value[i];
  154. }
  155. return idMath::Sqrt( speed );
  156. }
  157. /*
  158. ====================
  159. idCurve::RombergIntegral
  160. ====================
  161. */
  162. template< class type >
  163. ID_INLINE float idCurve<type>::RombergIntegral( const float t0, const float t1, const int order ) const {
  164. int i, j, k, m, n;
  165. float sum, delta;
  166. float *temp[2];
  167. temp[0] = (float *) _alloca16( order * sizeof( float ) );
  168. temp[1] = (float *) _alloca16( order * sizeof( float ) );
  169. delta = t1 - t0;
  170. temp[0][0] = 0.5f * delta * ( GetSpeed( t0 ) + GetSpeed( t1 ) );
  171. for ( i = 2, m = 1; i <= order; i++, m *= 2, delta *= 0.5f ) {
  172. // approximate using the trapezoid rule
  173. sum = 0.0f;
  174. for ( j = 1; j <= m; j++ ) {
  175. sum += GetSpeed( t0 + delta * ( j - 0.5f ) );
  176. }
  177. // Richardson extrapolation
  178. temp[1][0] = 0.5f * ( temp[0][0] + delta * sum );
  179. for ( k = 1, n = 4; k < i; k++, n *= 4 ) {
  180. temp[1][k] = ( n * temp[1][k-1] - temp[0][k-1] ) / ( n - 1 );
  181. }
  182. for ( j = 0; j < i; j++ ) {
  183. temp[0][j] = temp[1][j];
  184. }
  185. }
  186. return temp[0][order-1];
  187. }
  188. /*
  189. ====================
  190. idCurve::GetLengthBetweenKnots
  191. ====================
  192. */
  193. template< class type >
  194. ID_INLINE float idCurve<type>::GetLengthBetweenKnots( const int i0, const int i1 ) const {
  195. float length = 0.0f;
  196. for ( int i = i0; i < i1; i++ ) {
  197. length += RombergIntegral( times[i], times[i+1], 5 );
  198. }
  199. return length;
  200. }
  201. /*
  202. ====================
  203. idCurve::GetLengthForTime
  204. ====================
  205. */
  206. template< class type >
  207. ID_INLINE float idCurve<type>::GetLengthForTime( const float time ) const {
  208. float length = 0.0f;
  209. int index = IndexForTime( time );
  210. for ( int i = 0; i < index; i++ ) {
  211. length += RombergIntegral( times[i], times[i+1], 5 );
  212. }
  213. length += RombergIntegral( times[index], time, 5 );
  214. return length;
  215. }
  216. /*
  217. ====================
  218. idCurve::GetTimeForLength
  219. ====================
  220. */
  221. template< class type >
  222. ID_INLINE float idCurve<type>::GetTimeForLength( const float length, const float epsilon ) const {
  223. int i, index;
  224. float *accumLength, totalLength, len0, len1, t, diff;
  225. if ( length <= 0.0f ) {
  226. return times[0];
  227. }
  228. accumLength = (float *) _alloca16( values.Num() * sizeof( float ) );
  229. totalLength = 0.0f;
  230. for ( index = 0; index < values.Num() - 1; index++ ) {
  231. totalLength += GetLengthBetweenKnots( index, index + 1 );
  232. accumLength[index] = totalLength;
  233. if ( length < accumLength[index] ) {
  234. break;
  235. }
  236. }
  237. if ( index >= values.Num() - 1 ) {
  238. return times[times.Num() - 1];
  239. }
  240. if ( index == 0 ) {
  241. len0 = length;
  242. len1 = accumLength[0];
  243. } else {
  244. len0 = length - accumLength[index-1];
  245. len1 = accumLength[index] - accumLength[index-1];
  246. }
  247. // invert the arc length integral using Newton's method
  248. t = ( times[index+1] - times[index] ) * len0 / len1;
  249. for ( i = 0; i < 32; i++ ) {
  250. diff = RombergIntegral( times[index], times[index] + t, 5 ) - len0;
  251. if ( idMath::Fabs( diff ) <= epsilon ) {
  252. return times[index] + t;
  253. }
  254. t -= diff / GetSpeed( times[index] + t );
  255. }
  256. return times[index] + t;
  257. }
  258. /*
  259. ====================
  260. idCurve::MakeUniform
  261. ====================
  262. */
  263. template< class type >
  264. ID_INLINE void idCurve<type>::MakeUniform( const float totalTime ) {
  265. int i, n;
  266. n = times.Num() - 1;
  267. for ( i = 0; i <= n; i++ ) {
  268. times[i] = i * totalTime / n;
  269. }
  270. changed = true;
  271. }
  272. /*
  273. ====================
  274. idCurve::SetConstantSpeed
  275. ====================
  276. */
  277. template< class type >
  278. ID_INLINE void idCurve<type>::SetConstantSpeed( const float totalTime ) {
  279. int i, j;
  280. float *length, totalLength, scale, t;
  281. length = (float *) _alloca16( values.Num() * sizeof( float ) );
  282. totalLength = 0.0f;
  283. for ( i = 0; i < values.Num() - 1; i++ ) {
  284. length[i] = GetLengthBetweenKnots( i, i + 1 );
  285. totalLength += length[i];
  286. }
  287. scale = totalTime / totalLength;
  288. for ( t = 0.0f, i = 0; i < times.Num() - 1; i++ ) {
  289. times[i] = t;
  290. t += scale * length[i];
  291. }
  292. times[times.Num() - 1] = totalTime;
  293. changed = true;
  294. }
  295. /*
  296. ====================
  297. idCurve::ShiftTime
  298. ====================
  299. */
  300. template< class type >
  301. ID_INLINE void idCurve<type>::ShiftTime( const float deltaTime ) {
  302. for ( int i = 0; i < times.Num(); i++ ) {
  303. times[i] += deltaTime;
  304. }
  305. changed = true;
  306. }
  307. /*
  308. ====================
  309. idCurve::Translate
  310. ====================
  311. */
  312. template< class type >
  313. ID_INLINE void idCurve<type>::Translate( const type &translation ) {
  314. for ( int i = 0; i < values.Num(); i++ ) {
  315. values[i] += translation;
  316. }
  317. changed = true;
  318. }
  319. /*
  320. ====================
  321. idCurve::IndexForTime
  322. find the index for the first time greater than or equal to the given time
  323. ====================
  324. */
  325. template< class type >
  326. ID_INLINE int idCurve<type>::IndexForTime( const float time ) const {
  327. int len, mid, offset, res;
  328. if ( currentIndex >= 0 && currentIndex <= times.Num() ) {
  329. // use the cached index if it is still valid
  330. if ( currentIndex == 0 ) {
  331. if ( time <= times[currentIndex] ) {
  332. return currentIndex;
  333. }
  334. } else if ( currentIndex == times.Num() ) {
  335. if ( time > times[currentIndex-1] ) {
  336. return currentIndex;
  337. }
  338. } else if ( time > times[currentIndex-1] && time <= times[currentIndex] ) {
  339. return currentIndex;
  340. } else if ( time > times[currentIndex] && ( currentIndex+1 == times.Num() || time <= times[currentIndex+1] ) ) {
  341. // use the next index
  342. currentIndex++;
  343. return currentIndex;
  344. }
  345. }
  346. // use binary search to find the index for the given time
  347. len = times.Num();
  348. mid = len;
  349. offset = 0;
  350. res = 0;
  351. while( mid > 0 ) {
  352. mid = len >> 1;
  353. if ( time == times[offset+mid] ) {
  354. return offset+mid;
  355. } else if ( time > times[offset+mid] ) {
  356. offset += mid;
  357. len -= mid;
  358. res = 1;
  359. } else {
  360. len -= mid;
  361. res = 0;
  362. }
  363. }
  364. currentIndex = offset+res;
  365. return currentIndex;
  366. }
  367. /*
  368. ====================
  369. idCurve::ValueForIndex
  370. get the value for the given time
  371. ====================
  372. */
  373. template< class type >
  374. ID_INLINE type idCurve<type>::ValueForIndex( const int index ) const {
  375. int n = values.Num()-1;
  376. if ( index < 0 ) {
  377. return values[0] + index * ( values[1] - values[0] );
  378. } else if ( index > n ) {
  379. return values[n] + ( index - n ) * ( values[n] - values[n-1] );
  380. }
  381. return values[index];
  382. }
  383. /*
  384. ====================
  385. idCurve::TimeForIndex
  386. get the value for the given time
  387. ====================
  388. */
  389. template< class type >
  390. ID_INLINE float idCurve<type>::TimeForIndex( const int index ) const {
  391. int n = times.Num()-1;
  392. if ( index < 0 ) {
  393. return times[0] + index * ( times[1] - times[0] );
  394. } else if ( index > n ) {
  395. return times[n] + ( index - n ) * ( times[n] - times[n-1] );
  396. }
  397. return times[index];
  398. }
  399. /*
  400. ===============================================================================
  401. Bezier Curve template.
  402. The degree of the polynomial equals the number of knots minus one.
  403. ===============================================================================
  404. */
  405. template< class type >
  406. class idCurve_Bezier : public idCurve<type> {
  407. public:
  408. idCurve_Bezier();
  409. virtual type GetCurrentValue( const float time ) const;
  410. virtual type GetCurrentFirstDerivative( const float time ) const;
  411. virtual type GetCurrentSecondDerivative( const float time ) const;
  412. protected:
  413. void Basis( const int order, const float t, float *bvals ) const;
  414. void BasisFirstDerivative( const int order, const float t, float *bvals ) const;
  415. void BasisSecondDerivative( const int order, const float t, float *bvals ) const;
  416. };
  417. /*
  418. ====================
  419. idCurve_Bezier::idCurve_Bezier
  420. ====================
  421. */
  422. template< class type >
  423. ID_INLINE idCurve_Bezier<type>::idCurve_Bezier() {
  424. }
  425. /*
  426. ====================
  427. idCurve_Bezier::GetCurrentValue
  428. get the value for the given time
  429. ====================
  430. */
  431. template< class type >
  432. ID_INLINE type idCurve_Bezier<type>::GetCurrentValue( const float time ) const {
  433. int i;
  434. float *bvals;
  435. type v;
  436. bvals = (float *) _alloca16( this->values.Num() * sizeof( float ) );
  437. Basis( this->values.Num(), time, bvals );
  438. v = bvals[0] * this->values[0];
  439. for ( i = 1; i < this->values.Num(); i++ ) {
  440. v += bvals[i] * this->values[i];
  441. }
  442. return v;
  443. }
  444. /*
  445. ====================
  446. idCurve_Bezier::GetCurrentFirstDerivative
  447. get the first derivative for the given time
  448. ====================
  449. */
  450. template< class type >
  451. ID_INLINE type idCurve_Bezier<type>::GetCurrentFirstDerivative( const float time ) const {
  452. int i;
  453. float *bvals, d;
  454. type v;
  455. bvals = (float *) _alloca16( this->values.Num() * sizeof( float ) );
  456. BasisFirstDerivative( this->values.Num(), time, bvals );
  457. v = bvals[0] * this->values[0];
  458. for ( i = 1; i < this->values.Num(); i++ ) {
  459. v += bvals[i] * this->values[i];
  460. }
  461. d = ( this->times[this->times.Num()-1] - this->times[0] );
  462. return ( (float) (this->values.Num()-1) / d ) * v;
  463. }
  464. /*
  465. ====================
  466. idCurve_Bezier::GetCurrentSecondDerivative
  467. get the second derivative for the given time
  468. ====================
  469. */
  470. template< class type >
  471. ID_INLINE type idCurve_Bezier<type>::GetCurrentSecondDerivative( const float time ) const {
  472. int i;
  473. float *bvals, d;
  474. type v;
  475. bvals = (float *) _alloca16( this->values.Num() * sizeof( float ) );
  476. BasisSecondDerivative( this->values.Num(), time, bvals );
  477. v = bvals[0] * this->values[0];
  478. for ( i = 1; i < this->values.Num(); i++ ) {
  479. v += bvals[i] * this->values[i];
  480. }
  481. d = ( this->times[this->times.Num()-1] - this->times[0] );
  482. return ( (float) (this->values.Num()-2) * (this->values.Num()-1) / ( d * d ) ) * v;
  483. }
  484. /*
  485. ====================
  486. idCurve_Bezier::Basis
  487. bezier basis functions
  488. ====================
  489. */
  490. template< class type >
  491. ID_INLINE void idCurve_Bezier<type>::Basis( const int order, const float t, float *bvals ) const {
  492. int i, j, d;
  493. float *c, c1, c2, s, o, ps, po;
  494. bvals[0] = 1.0f;
  495. d = order - 1;
  496. if ( d <= 0 ) {
  497. return;
  498. }
  499. c = (float *) _alloca16( (d+1) * sizeof( float ) );
  500. s = (float) ( t - this->times[0] ) / ( this->times[this->times.Num()-1] - this->times[0] );
  501. o = 1.0f - s;
  502. ps = s;
  503. po = o;
  504. for ( i = 1; i < d; i++ ) {
  505. c[i] = 1.0f;
  506. }
  507. for ( i = 1; i < d; i++ ) {
  508. c[i-1] = 0.0f;
  509. c1 = c[i];
  510. c[i] = 1.0f;
  511. for ( j = i+1; j <= d; j++ ) {
  512. c2 = c[j];
  513. c[j] = c1 + c[j-1];
  514. c1 = c2;
  515. }
  516. bvals[i] = c[d] * ps;
  517. ps *= s;
  518. }
  519. for ( i = d-1; i >= 0; i-- ) {
  520. bvals[i] *= po;
  521. po *= o;
  522. }
  523. bvals[d] = ps;
  524. }
  525. /*
  526. ====================
  527. idCurve_Bezier::BasisFirstDerivative
  528. first derivative of bezier basis functions
  529. ====================
  530. */
  531. template< class type >
  532. ID_INLINE void idCurve_Bezier<type>::BasisFirstDerivative( const int order, const float t, float *bvals ) const {
  533. int i;
  534. Basis( order-1, t, bvals+1 );
  535. bvals[0] = 0.0f;
  536. for ( i = 0; i < order-1; i++ ) {
  537. bvals[i] -= bvals[i+1];
  538. }
  539. }
  540. /*
  541. ====================
  542. idCurve_Bezier::BasisSecondDerivative
  543. second derivative of bezier basis functions
  544. ====================
  545. */
  546. template< class type >
  547. ID_INLINE void idCurve_Bezier<type>::BasisSecondDerivative( const int order, const float t, float *bvals ) const {
  548. int i;
  549. BasisFirstDerivative( order-1, t, bvals+1 );
  550. bvals[0] = 0.0f;
  551. for ( i = 0; i < order-1; i++ ) {
  552. bvals[i] -= bvals[i+1];
  553. }
  554. }
  555. /*
  556. ===============================================================================
  557. Quadratic Bezier Curve template.
  558. Should always have exactly three knots.
  559. ===============================================================================
  560. */
  561. template< class type >
  562. class idCurve_QuadraticBezier : public idCurve<type> {
  563. public:
  564. idCurve_QuadraticBezier();
  565. virtual type GetCurrentValue( const float time ) const;
  566. virtual type GetCurrentFirstDerivative( const float time ) const;
  567. virtual type GetCurrentSecondDerivative( const float time ) const;
  568. protected:
  569. void Basis( const float t, float *bvals ) const;
  570. void BasisFirstDerivative( const float t, float *bvals ) const;
  571. void BasisSecondDerivative( const float t, float *bvals ) const;
  572. };
  573. /*
  574. ====================
  575. idCurve_QuadraticBezier::idCurve_QuadraticBezier
  576. ====================
  577. */
  578. template< class type >
  579. ID_INLINE idCurve_QuadraticBezier<type>::idCurve_QuadraticBezier() {
  580. }
  581. /*
  582. ====================
  583. idCurve_QuadraticBezier::GetCurrentValue
  584. get the value for the given time
  585. ====================
  586. */
  587. template< class type >
  588. ID_INLINE type idCurve_QuadraticBezier<type>::GetCurrentValue( const float time ) const {
  589. float bvals[3];
  590. assert( this->values.Num() == 3 );
  591. Basis( time, bvals );
  592. return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] );
  593. }
  594. /*
  595. ====================
  596. idCurve_QuadraticBezier::GetCurrentFirstDerivative
  597. get the first derivative for the given time
  598. ====================
  599. */
  600. template< class type >
  601. ID_INLINE type idCurve_QuadraticBezier<type>::GetCurrentFirstDerivative( const float time ) const {
  602. float bvals[3], d;
  603. assert( this->values.Num() == 3 );
  604. BasisFirstDerivative( time, bvals );
  605. d = ( this->times[2] - this->times[0] );
  606. return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] ) / d;
  607. }
  608. /*
  609. ====================
  610. idCurve_QuadraticBezier::GetCurrentSecondDerivative
  611. get the second derivative for the given time
  612. ====================
  613. */
  614. template< class type >
  615. ID_INLINE type idCurve_QuadraticBezier<type>::GetCurrentSecondDerivative( const float time ) const {
  616. float bvals[3], d;
  617. assert( this->values.Num() == 3 );
  618. BasisSecondDerivative( time, bvals );
  619. d = ( this->times[2] - this->times[0] );
  620. return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] ) / ( d * d );
  621. }
  622. /*
  623. ====================
  624. idCurve_QuadraticBezier::Basis
  625. quadratic bezier basis functions
  626. ====================
  627. */
  628. template< class type >
  629. ID_INLINE void idCurve_QuadraticBezier<type>::Basis( const float t, float *bvals ) const {
  630. float s1 = (float) ( t - this->times[0] ) / ( this->times[2] - this->times[0] );
  631. float s2 = s1 * s1;
  632. bvals[0] = s2 - 2.0f * s1 + 1.0f;
  633. bvals[1] = -2.0f * s2 + 2.0f * s1;
  634. bvals[2] = s2;
  635. }
  636. /*
  637. ====================
  638. idCurve_QuadraticBezier::BasisFirstDerivative
  639. first derivative of quadratic bezier basis functions
  640. ====================
  641. */
  642. template< class type >
  643. ID_INLINE void idCurve_QuadraticBezier<type>::BasisFirstDerivative( const float t, float *bvals ) const {
  644. float s1 = (float) ( t - this->times[0] ) / ( this->times[2] - this->times[0] );
  645. bvals[0] = 2.0f * s1 - 2.0f;
  646. bvals[1] = -4.0f * s1 + 2.0f;
  647. bvals[2] = 2.0f * s1;
  648. }
  649. /*
  650. ====================
  651. idCurve_QuadraticBezier::BasisSecondDerivative
  652. second derivative of quadratic bezier basis functions
  653. ====================
  654. */
  655. template< class type >
  656. ID_INLINE void idCurve_QuadraticBezier<type>::BasisSecondDerivative( const float t, float *bvals ) const {
  657. float s1 = (float) ( t - this->times[0] ) / ( this->times[2] - this->times[0] );
  658. bvals[0] = 2.0f;
  659. bvals[1] = -4.0f;
  660. bvals[2] = 2.0f;
  661. }
  662. /*
  663. ===============================================================================
  664. Cubic Bezier Curve template.
  665. Should always have exactly four knots.
  666. ===============================================================================
  667. */
  668. template< class type >
  669. class idCurve_CubicBezier : public idCurve<type> {
  670. public:
  671. idCurve_CubicBezier();
  672. virtual type GetCurrentValue( const float time ) const;
  673. virtual type GetCurrentFirstDerivative( const float time ) const;
  674. virtual type GetCurrentSecondDerivative( const float time ) const;
  675. protected:
  676. void Basis( const float t, float *bvals ) const;
  677. void BasisFirstDerivative( const float t, float *bvals ) const;
  678. void BasisSecondDerivative( const float t, float *bvals ) const;
  679. };
  680. /*
  681. ====================
  682. idCurve_CubicBezier::idCurve_CubicBezier
  683. ====================
  684. */
  685. template< class type >
  686. ID_INLINE idCurve_CubicBezier<type>::idCurve_CubicBezier() {
  687. }
  688. /*
  689. ====================
  690. idCurve_CubicBezier::GetCurrentValue
  691. get the value for the given time
  692. ====================
  693. */
  694. template< class type >
  695. ID_INLINE type idCurve_CubicBezier<type>::GetCurrentValue( const float time ) const {
  696. float bvals[4];
  697. assert( this->values.Num() == 4 );
  698. Basis( time, bvals );
  699. return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] + bvals[3] * this->values[3] );
  700. }
  701. /*
  702. ====================
  703. idCurve_CubicBezier::GetCurrentFirstDerivative
  704. get the first derivative for the given time
  705. ====================
  706. */
  707. template< class type >
  708. ID_INLINE type idCurve_CubicBezier<type>::GetCurrentFirstDerivative( const float time ) const {
  709. float bvals[4], d;
  710. assert( this->values.Num() == 4 );
  711. BasisFirstDerivative( time, bvals );
  712. d = ( this->times[3] - this->times[0] );
  713. return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] + bvals[3] * this->values[3] ) / d;
  714. }
  715. /*
  716. ====================
  717. idCurve_CubicBezier::GetCurrentSecondDerivative
  718. get the second derivative for the given time
  719. ====================
  720. */
  721. template< class type >
  722. ID_INLINE type idCurve_CubicBezier<type>::GetCurrentSecondDerivative( const float time ) const {
  723. float bvals[4], d;
  724. assert( this->values.Num() == 4 );
  725. BasisSecondDerivative( time, bvals );
  726. d = ( this->times[3] - this->times[0] );
  727. return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] + bvals[3] * this->values[3] ) / ( d * d );
  728. }
  729. /*
  730. ====================
  731. idCurve_CubicBezier::Basis
  732. cubic bezier basis functions
  733. ====================
  734. */
  735. template< class type >
  736. ID_INLINE void idCurve_CubicBezier<type>::Basis( const float t, float *bvals ) const {
  737. float s1 = (float) ( t - this->times[0] ) / ( this->times[3] - this->times[0] );
  738. float s2 = s1 * s1;
  739. float s3 = s2 * s1;
  740. bvals[0] = -s3 + 3.0f * s2 - 3.0f * s1 + 1.0f;
  741. bvals[1] = 3.0f * s3 - 6.0f * s2 + 3.0f * s1;
  742. bvals[2] = -3.0f * s3 + 3.0f * s2;
  743. bvals[3] = s3;
  744. }
  745. /*
  746. ====================
  747. idCurve_CubicBezier::BasisFirstDerivative
  748. first derivative of cubic bezier basis functions
  749. ====================
  750. */
  751. template< class type >
  752. ID_INLINE void idCurve_CubicBezier<type>::BasisFirstDerivative( const float t, float *bvals ) const {
  753. float s1 = (float) ( t - this->times[0] ) / ( this->times[3] - this->times[0] );
  754. float s2 = s1 * s1;
  755. bvals[0] = -3.0f * s2 + 6.0f * s1 - 3.0f;
  756. bvals[1] = 9.0f * s2 - 12.0f * s1 + 3.0f;
  757. bvals[2] = -9.0f * s2 + 6.0f * s1;
  758. bvals[3] = 3.0f * s2;
  759. }
  760. /*
  761. ====================
  762. idCurve_CubicBezier::BasisSecondDerivative
  763. second derivative of cubic bezier basis functions
  764. ====================
  765. */
  766. template< class type >
  767. ID_INLINE void idCurve_CubicBezier<type>::BasisSecondDerivative( const float t, float *bvals ) const {
  768. float s1 = (float) ( t - this->times[0] ) / ( this->times[3] - this->times[0] );
  769. bvals[0] = -6.0f * s1 + 6.0f;
  770. bvals[1] = 18.0f * s1 - 12.0f;
  771. bvals[2] = -18.0f * s1 + 6.0f;
  772. bvals[3] = 6.0f * s1;
  773. }
  774. /*
  775. ===============================================================================
  776. Spline base template.
  777. ===============================================================================
  778. */
  779. template< class type >
  780. class idCurve_Spline : public idCurve<type> {
  781. public:
  782. enum boundary_t { BT_FREE, BT_CLAMPED, BT_CLOSED };
  783. idCurve_Spline();
  784. virtual bool IsDone( const float time ) const;
  785. virtual void SetBoundaryType( const boundary_t bt ) { boundaryType = bt; this->changed = true; }
  786. virtual boundary_t GetBoundaryType() const { return boundaryType; }
  787. virtual void SetCloseTime( const float t ) { closeTime = t; this->changed = true; }
  788. virtual float GetCloseTime() { return boundaryType == BT_CLOSED ? closeTime : 0.0f; }
  789. protected:
  790. boundary_t boundaryType;
  791. float closeTime;
  792. type ValueForIndex( const int index ) const;
  793. float TimeForIndex( const int index ) const;
  794. float ClampedTime( const float t ) const;
  795. };
  796. /*
  797. ====================
  798. idCurve_Spline::idCurve_Spline
  799. ====================
  800. */
  801. template< class type >
  802. ID_INLINE idCurve_Spline<type>::idCurve_Spline() {
  803. boundaryType = BT_FREE;
  804. closeTime = 0.0f;
  805. }
  806. /*
  807. ====================
  808. idCurve_Spline::ValueForIndex
  809. get the value for the given time
  810. ====================
  811. */
  812. template< class type >
  813. ID_INLINE type idCurve_Spline<type>::ValueForIndex( const int index ) const {
  814. int n = this->values.Num()-1;
  815. if ( index < 0 ) {
  816. if ( boundaryType == BT_CLOSED ) {
  817. return this->values[ this->values.Num() + index % this->values.Num() ];
  818. }
  819. else {
  820. return this->values[0] + index * ( this->values[1] - this->values[0] );
  821. }
  822. }
  823. else if ( index > n ) {
  824. if ( boundaryType == BT_CLOSED ) {
  825. return this->values[ index % this->values.Num() ];
  826. }
  827. else {
  828. return this->values[n] + ( index - n ) * ( this->values[n] - this->values[n-1] );
  829. }
  830. }
  831. return this->values[index];
  832. }
  833. /*
  834. ====================
  835. idCurve_Spline::TimeForIndex
  836. get the value for the given time
  837. ====================
  838. */
  839. template< class type >
  840. ID_INLINE float idCurve_Spline<type>::TimeForIndex( const int index ) const {
  841. int n = this->times.Num()-1;
  842. if ( index < 0 ) {
  843. if ( boundaryType == BT_CLOSED ) {
  844. return ( index / this->times.Num() ) * ( this->times[n] + closeTime ) - ( this->times[n] + closeTime - this->times[this->times.Num() + index % this->times.Num()] );
  845. }
  846. else {
  847. return this->times[0] + index * ( this->times[1] - this->times[0] );
  848. }
  849. }
  850. else if ( index > n ) {
  851. if ( boundaryType == BT_CLOSED ) {
  852. return ( index / this->times.Num() ) * ( this->times[n] + closeTime ) + this->times[index % this->times.Num()];
  853. }
  854. else {
  855. return this->times[n] + ( index - n ) * ( this->times[n] - this->times[n-1] );
  856. }
  857. }
  858. return this->times[index];
  859. }
  860. /*
  861. ====================
  862. idCurve_Spline::ClampedTime
  863. return the clamped time based on the boundary type
  864. ====================
  865. */
  866. template< class type >
  867. ID_INLINE float idCurve_Spline<type>::ClampedTime( const float t ) const {
  868. if ( boundaryType == BT_CLAMPED ) {
  869. if ( t < this->times[0] ) {
  870. return this->times[0];
  871. }
  872. else if ( t >= this->times[this->times.Num()-1] ) {
  873. return this->times[this->times.Num()-1];
  874. }
  875. }
  876. return t;
  877. }
  878. /*
  879. ====================
  880. idCurve_Spline::IsDone
  881. ====================
  882. */
  883. template< class type >
  884. ID_INLINE bool idCurve_Spline<type>::IsDone( const float time ) const {
  885. return ( boundaryType != BT_CLOSED && time >= this->times[ this->times.Num() - 1 ] );
  886. }
  887. /*
  888. ===============================================================================
  889. Cubic Interpolating Spline template.
  890. The curve goes through all the knots.
  891. ===============================================================================
  892. */
  893. template< class type >
  894. class idCurve_NaturalCubicSpline : public idCurve_Spline<type> {
  895. public:
  896. idCurve_NaturalCubicSpline();
  897. virtual void Clear() { idCurve_Spline<type>::Clear(); this->values.Clear(); b.Clear(); c.Clear(); d.Clear(); }
  898. virtual type GetCurrentValue( const float time ) const;
  899. virtual type GetCurrentFirstDerivative( const float time ) const;
  900. virtual type GetCurrentSecondDerivative( const float time ) const;
  901. protected:
  902. mutable idList<type>b;
  903. mutable idList<type>c;
  904. mutable idList<type>d;
  905. void Setup() const;
  906. void SetupFree() const;
  907. void SetupClamped() const;
  908. void SetupClosed() const;
  909. };
  910. /*
  911. ====================
  912. idCurve_NaturalCubicSpline::idCurve_NaturalCubicSpline
  913. ====================
  914. */
  915. template< class type >
  916. ID_INLINE idCurve_NaturalCubicSpline<type>::idCurve_NaturalCubicSpline() {
  917. }
  918. /*
  919. ====================
  920. idCurve_NaturalCubicSpline::GetCurrentValue
  921. get the value for the given time
  922. ====================
  923. */
  924. template< class type >
  925. ID_INLINE type idCurve_NaturalCubicSpline<type>::GetCurrentValue( const float time ) const {
  926. float clampedTime = this->ClampedTime( time );
  927. int i = this->IndexForTime( clampedTime );
  928. float s = time - this->TimeForIndex( i );
  929. Setup();
  930. return ( this->values[i] + s * ( b[i] + s * ( c[i] + s * d[i] ) ) );
  931. }
  932. /*
  933. ====================
  934. idCurve_NaturalCubicSpline::GetCurrentFirstDerivative
  935. get the first derivative for the given time
  936. ====================
  937. */
  938. template< class type >
  939. ID_INLINE type idCurve_NaturalCubicSpline<type>::GetCurrentFirstDerivative( const float time ) const {
  940. float clampedTime = this->ClampedTime( time );
  941. int i = this->IndexForTime( clampedTime );
  942. float s = time - this->TimeForIndex( i );
  943. Setup();
  944. return ( b[i] + s * ( 2.0f * c[i] + 3.0f * s * d[i] ) );
  945. }
  946. /*
  947. ====================
  948. idCurve_NaturalCubicSpline::GetCurrentSecondDerivative
  949. get the second derivative for the given time
  950. ====================
  951. */
  952. template< class type >
  953. ID_INLINE type idCurve_NaturalCubicSpline<type>::GetCurrentSecondDerivative( const float time ) const {
  954. float clampedTime = this->ClampedTime( time );
  955. int i = this->IndexForTime( clampedTime );
  956. float s = time - this->TimeForIndex( i );
  957. Setup();
  958. return ( 2.0f * c[i] + 6.0f * s * d[i] );
  959. }
  960. /*
  961. ====================
  962. idCurve_NaturalCubicSpline::Setup
  963. ====================
  964. */
  965. template< class type >
  966. ID_INLINE void idCurve_NaturalCubicSpline<type>::Setup() const {
  967. if ( this->changed ) {
  968. switch( this->boundaryType ) {
  969. case idCurve_Spline<type>::BT_FREE: SetupFree(); break;
  970. case idCurve_Spline<type>::BT_CLAMPED: SetupClamped(); break;
  971. case idCurve_Spline<type>::BT_CLOSED: SetupClosed(); break;
  972. }
  973. this->changed = false;
  974. }
  975. }
  976. /*
  977. ====================
  978. idCurve_NaturalCubicSpline::SetupFree
  979. ====================
  980. */
  981. template< class type >
  982. ID_INLINE void idCurve_NaturalCubicSpline<type>::SetupFree() const {
  983. int i;
  984. float inv;
  985. float *d0, *d1, *beta, *gamma;
  986. type *alpha, *delta;
  987. d0 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
  988. d1 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
  989. alpha = (type *) _alloca16( ( this->values.Num() - 1 ) * sizeof( type ) );
  990. beta = (float *) _alloca16( this->values.Num() * sizeof( float ) );
  991. gamma = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
  992. delta = (type *) _alloca16( this->values.Num() * sizeof( type ) );
  993. for ( i = 0; i < this->values.Num() - 1; i++ ) {
  994. d0[i] = this->times[i+1] - this->times[i];
  995. }
  996. for ( i = 1; i < this->values.Num() - 1; i++ ) {
  997. d1[i] = this->times[i+1] - this->times[i-1];
  998. }
  999. for ( i = 1; i < this->values.Num() - 1; i++ ) {
  1000. type sum = 3.0f * ( d0[i-1] * this->values[i+1] - d1[i] * this->values[i] + d0[i] * this->values[i-1] );
  1001. inv = 1.0f / ( d0[i-1] * d0[i] );
  1002. alpha[i] = inv * sum;
  1003. }
  1004. beta[0] = 1.0f;
  1005. gamma[0] = 0.0f;
  1006. delta[0] = this->values[0] - this->values[0]; //-V501
  1007. for ( i = 1; i < this->values.Num() - 1; i++ ) {
  1008. beta[i] = 2.0f * d1[i] - d0[i-1] * gamma[i-1];
  1009. inv = 1.0f / beta[i];
  1010. gamma[i] = inv * d0[i];
  1011. delta[i] = inv * ( alpha[i] - d0[i-1] * delta[i-1] );
  1012. }
  1013. beta[this->values.Num() - 1] = 1.0f;
  1014. delta[this->values.Num() - 1] = this->values[0] - this->values[0]; //-V501
  1015. b.AssureSize( this->values.Num() );
  1016. c.AssureSize( this->values.Num() );
  1017. d.AssureSize( this->values.Num() );
  1018. c[this->values.Num() - 1] = this->values[0] - this->values[0]; //-V501
  1019. for ( i = this->values.Num() - 2; i >= 0; i-- ) {
  1020. c[i] = delta[i] - gamma[i] * c[i+1];
  1021. inv = 1.0f / d0[i];
  1022. b[i] = inv * ( this->values[i+1] - this->values[i] ) - ( 1.0f / 3.0f ) * d0[i] * ( c[i+1] + 2.0f * c[i] );
  1023. d[i] = ( 1.0f / 3.0f ) * inv * ( c[i+1] - c[i] );
  1024. }
  1025. }
  1026. /*
  1027. ====================
  1028. idCurve_NaturalCubicSpline::SetupClamped
  1029. ====================
  1030. */
  1031. template< class type >
  1032. ID_INLINE void idCurve_NaturalCubicSpline<type>::SetupClamped() const {
  1033. int i;
  1034. float inv;
  1035. float *d0, *d1, *beta, *gamma;
  1036. type *alpha, *delta;
  1037. d0 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
  1038. d1 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
  1039. alpha = (type *) _alloca16( ( this->values.Num() - 1 ) * sizeof( type ) );
  1040. beta = (float *) _alloca16( this->values.Num() * sizeof( float ) );
  1041. gamma = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
  1042. delta = (type *) _alloca16( this->values.Num() * sizeof( type ) );
  1043. for ( i = 0; i < this->values.Num() - 1; i++ ) {
  1044. d0[i] = this->times[i+1] - this->times[i];
  1045. }
  1046. for ( i = 1; i < this->values.Num() - 1; i++ ) {
  1047. d1[i] = this->times[i+1] - this->times[i-1];
  1048. }
  1049. inv = 1.0f / d0[0];
  1050. alpha[0] = 3.0f * ( inv - 1.0f ) * ( this->values[1] - this->values[0] );
  1051. inv = 1.0f / d0[this->values.Num() - 2];
  1052. alpha[this->values.Num() - 1] = 3.0f * ( 1.0f - inv ) * ( this->values[this->values.Num() - 1] - this->values[this->values.Num() - 2] );
  1053. for ( i = 1; i < this->values.Num() - 1; i++ ) {
  1054. type sum = 3.0f * ( d0[i-1] * this->values[i+1] - d1[i] * this->values[i] + d0[i] * this->values[i-1] );
  1055. inv = 1.0f / ( d0[i-1] * d0[i] );
  1056. alpha[i] = inv * sum;
  1057. }
  1058. beta[0] = 2.0f * d0[0];
  1059. gamma[0] = 0.5f;
  1060. inv = 1.0f / beta[0];
  1061. delta[0] = inv * alpha[0];
  1062. for ( i = 1; i < this->values.Num() - 1; i++ ) {
  1063. beta[i] = 2.0f * d1[i] - d0[i-1] * gamma[i-1];
  1064. inv = 1.0f / beta[i];
  1065. gamma[i] = inv * d0[i];
  1066. delta[i] = inv * ( alpha[i] - d0[i-1] * delta[i-1] );
  1067. }
  1068. beta[this->values.Num() - 1] = d0[this->values.Num() - 2] * ( 2.0f - gamma[this->values.Num() - 2] );
  1069. inv = 1.0f / beta[this->values.Num() - 1];
  1070. delta[this->values.Num() - 1] = inv * ( alpha[this->values.Num() - 1] - d0[this->values.Num() - 2] * delta[this->values.Num() - 2] );
  1071. b.AssureSize( this->values.Num() );
  1072. c.AssureSize( this->values.Num() );
  1073. d.AssureSize( this->values.Num() );
  1074. c[this->values.Num() - 1] = delta[this->values.Num() - 1];
  1075. for ( i = this->values.Num() - 2; i >= 0; i-- ) {
  1076. c[i] = delta[i] - gamma[i] * c[i+1];
  1077. inv = 1.0f / d0[i];
  1078. b[i] = inv * ( this->values[i+1] - this->values[i] ) - ( 1.0f / 3.0f ) * d0[i]* ( c[i+1] + 2.0f * c[i] );
  1079. d[i] = ( 1.0f / 3.0f ) * inv * ( c[i+1] - c[i] );
  1080. }
  1081. }
  1082. /*
  1083. ====================
  1084. idCurve_NaturalCubicSpline::SetupClosed
  1085. ====================
  1086. */
  1087. template< class type >
  1088. ID_INLINE void idCurve_NaturalCubicSpline<type>::SetupClosed() const {
  1089. int i, j;
  1090. float c0, c1;
  1091. float *d0;
  1092. idMatX mat;
  1093. idVecX x;
  1094. d0 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
  1095. x.SetData( this->values.Num(), VECX_ALLOCA( this->values.Num() ) );
  1096. mat.SetData( this->values.Num(), this->values.Num(), MATX_ALLOCA( this->values.Num() * this->values.Num() ) );
  1097. b.AssureSize( this->values.Num() );
  1098. c.AssureSize( this->values.Num() );
  1099. d.AssureSize( this->values.Num() );
  1100. for ( i = 0; i < this->values.Num() - 1; i++ ) {
  1101. d0[i] = this->times[i+1] - this->times[i];
  1102. }
  1103. // matrix of system
  1104. mat[0][0] = 1.0f;
  1105. mat[0][this->values.Num() - 1] = -1.0f;
  1106. for ( i = 1; i <= this->values.Num() - 2; i++ ) {
  1107. mat[i][i-1] = d0[i-1];
  1108. mat[i][i ] = 2.0f * ( d0[i-1] + d0[i] );
  1109. mat[i][i+1] = d0[i];
  1110. }
  1111. mat[this->values.Num() - 1][this->values.Num() - 2] = d0[this->values.Num() - 2];
  1112. mat[this->values.Num() - 1][0] = 2.0f * ( d0[this->values.Num() - 2] + d0[0] );
  1113. mat[this->values.Num() - 1][1] = d0[0];
  1114. // right-hand side
  1115. c[0].Zero();
  1116. for ( i = 1; i <= this->values.Num() - 2; i++ ) {
  1117. c0 = 1.0f / d0[i];
  1118. c1 = 1.0f / d0[i-1];
  1119. c[i] = 3.0f * ( c0 * ( this->values[i + 1] - this->values[i] ) - c1 * ( this->values[i] - this->values[i - 1] ) );
  1120. }
  1121. c0 = 1.0f / d0[0];
  1122. c1 = 1.0f / d0[this->values.Num() - 2];
  1123. c[this->values.Num() - 1] = 3.0f * ( c0 * ( this->values[1] - this->values[0] ) - c1 * ( this->values[0] - this->values[this->values.Num() - 2] ) );
  1124. // solve system for each dimension
  1125. mat.LU_Factor( NULL );
  1126. for ( i = 0; i < this->values[0].GetDimension(); i++ ) {
  1127. for ( j = 0; j < this->values.Num(); j++ ) {
  1128. x[j] = c[j][i];
  1129. }
  1130. mat.LU_Solve( x, x, NULL );
  1131. for ( j = 0; j < this->values.Num(); j++ ) {
  1132. c[j][i] = x[j];
  1133. }
  1134. }
  1135. for ( i = 0; i < this->values.Num() - 1; i++ ) {
  1136. c0 = 1.0f / d0[i];
  1137. b[i] = c0 * ( this->values[i + 1] - this->values[i] ) - ( 1.0f / 3.0f ) * ( c[i+1] + 2.0f * c[i] ) * d0[i];
  1138. d[i] = ( 1.0f / 3.0f ) * c0 * ( c[i + 1] - c[i] );
  1139. }
  1140. }
  1141. /*
  1142. ===============================================================================
  1143. Uniform Cubic Interpolating Spline template.
  1144. The curve goes through all the knots.
  1145. ===============================================================================
  1146. */
  1147. template< class type >
  1148. class idCurve_CatmullRomSpline : public idCurve_Spline<type> {
  1149. public:
  1150. idCurve_CatmullRomSpline();
  1151. virtual type GetCurrentValue( const float time ) const;
  1152. virtual type GetCurrentFirstDerivative( const float time ) const;
  1153. virtual type GetCurrentSecondDerivative( const float time ) const;
  1154. protected:
  1155. void Basis( const int index, const float t, float *bvals ) const;
  1156. void BasisFirstDerivative( const int index, const float t, float *bvals ) const;
  1157. void BasisSecondDerivative( const int index, const float t, float *bvals ) const;
  1158. };
  1159. /*
  1160. ====================
  1161. idCurve_CatmullRomSpline::idCurve_CatmullRomSpline
  1162. ====================
  1163. */
  1164. template< class type >
  1165. ID_INLINE idCurve_CatmullRomSpline<type>::idCurve_CatmullRomSpline() {
  1166. }
  1167. /*
  1168. ====================
  1169. idCurve_CatmullRomSpline::GetCurrentValue
  1170. get the value for the given time
  1171. ====================
  1172. */
  1173. template< class type >
  1174. ID_INLINE type idCurve_CatmullRomSpline<type>::GetCurrentValue( const float time ) const {
  1175. int i, j, k;
  1176. float bvals[4], clampedTime;
  1177. type v;
  1178. if ( this->times.Num() == 1 ) {
  1179. return this->values[0];
  1180. }
  1181. clampedTime = this->ClampedTime( time );
  1182. i = this->IndexForTime( clampedTime );
  1183. Basis( i-1, clampedTime, bvals );
  1184. v = this->values[0] - this->values[0]; //-V501
  1185. for ( j = 0; j < 4; j++ ) {
  1186. k = i + j - 2;
  1187. v += bvals[j] * this->ValueForIndex( k );
  1188. }
  1189. return v;
  1190. }
  1191. /*
  1192. ====================
  1193. idCurve_CatmullRomSpline::GetCurrentFirstDerivative
  1194. get the first derivative for the given time
  1195. ====================
  1196. */
  1197. template< class type >
  1198. ID_INLINE type idCurve_CatmullRomSpline<type>::GetCurrentFirstDerivative( const float time ) const {
  1199. int i, j, k;
  1200. float bvals[4], d, clampedTime;
  1201. type v;
  1202. if ( this->times.Num() == 1 ) {
  1203. return ( this->values[0] - this->values[0] ); //-V501
  1204. }
  1205. clampedTime = this->ClampedTime( time );
  1206. i = this->IndexForTime( clampedTime );
  1207. BasisFirstDerivative( i-1, clampedTime, bvals );
  1208. v = this->values[0] - this->values[0]; //-V501
  1209. for ( j = 0; j < 4; j++ ) {
  1210. k = i + j - 2;
  1211. v += bvals[j] * this->ValueForIndex( k );
  1212. }
  1213. d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
  1214. return v / d;
  1215. }
  1216. /*
  1217. ====================
  1218. idCurve_CatmullRomSpline::GetCurrentSecondDerivative
  1219. get the second derivative for the given time
  1220. ====================
  1221. */
  1222. template< class type >
  1223. ID_INLINE type idCurve_CatmullRomSpline<type>::GetCurrentSecondDerivative( const float time ) const {
  1224. int i, j, k;
  1225. float bvals[4], d, clampedTime;
  1226. type v;
  1227. if ( this->times.Num() == 1 ) {
  1228. return ( this->values[0] - this->values[0] ); //-V501
  1229. }
  1230. clampedTime = this->ClampedTime( time );
  1231. i = this->IndexForTime( clampedTime );
  1232. BasisSecondDerivative( i-1, clampedTime, bvals );
  1233. v = this->values[0] - this->values[0]; //-V501
  1234. for ( j = 0; j < 4; j++ ) {
  1235. k = i + j - 2;
  1236. v += bvals[j] * this->ValueForIndex( k );
  1237. }
  1238. d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
  1239. return v / ( d * d );
  1240. }
  1241. /*
  1242. ====================
  1243. idCurve_CatmullRomSpline::Basis
  1244. spline basis functions
  1245. ====================
  1246. */
  1247. template< class type >
  1248. ID_INLINE void idCurve_CatmullRomSpline<type>::Basis( const int index, const float t, float *bvals ) const {
  1249. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1250. bvals[0] = ( ( -s + 2.0f ) * s - 1.0f ) * s * 0.5f; // -0.5f s * s * s + s * s - 0.5f * s
  1251. bvals[1] = ( ( ( 3.0f * s - 5.0f ) * s ) * s + 2.0f ) * 0.5f; // 1.5f * s * s * s - 2.5f * s * s + 1.0f
  1252. bvals[2] = ( ( -3.0f * s + 4.0f ) * s + 1.0f ) * s * 0.5f; // -1.5f * s * s * s - 2.0f * s * s + 0.5f s
  1253. bvals[3] = ( ( s - 1.0f ) * s * s ) * 0.5f; // 0.5f * s * s * s - 0.5f * s * s
  1254. }
  1255. /*
  1256. ====================
  1257. idCurve_CatmullRomSpline::BasisFirstDerivative
  1258. first derivative of spline basis functions
  1259. ====================
  1260. */
  1261. template< class type >
  1262. ID_INLINE void idCurve_CatmullRomSpline<type>::BasisFirstDerivative( const int index, const float t, float *bvals ) const {
  1263. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1264. bvals[0] = ( -1.5f * s + 2.0f ) * s - 0.5f; // -1.5f * s * s + 2.0f * s - 0.5f
  1265. bvals[1] = ( 4.5f * s - 5.0f ) * s; // 4.5f * s * s - 5.0f * s
  1266. bvals[2] = ( -4.5 * s + 4.0f ) * s + 0.5f; // -4.5 * s * s + 4.0f * s + 0.5f
  1267. bvals[3] = 1.5f * s * s - s; // 1.5f * s * s - s
  1268. }
  1269. /*
  1270. ====================
  1271. idCurve_CatmullRomSpline::BasisSecondDerivative
  1272. second derivative of spline basis functions
  1273. ====================
  1274. */
  1275. template< class type >
  1276. ID_INLINE void idCurve_CatmullRomSpline<type>::BasisSecondDerivative( const int index, const float t, float *bvals ) const {
  1277. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1278. bvals[0] = -3.0f * s + 2.0f;
  1279. bvals[1] = 9.0f * s - 5.0f;
  1280. bvals[2] = -9.0f * s + 4.0f;
  1281. bvals[3] = 3.0f * s - 1.0f;
  1282. }
  1283. /*
  1284. ===============================================================================
  1285. Cubic Interpolating Spline template.
  1286. The curve goes through all the knots.
  1287. The curve becomes the Catmull-Rom spline if the tension,
  1288. continuity and bias are all set to zero.
  1289. ===============================================================================
  1290. */
  1291. template< class type >
  1292. class idCurve_KochanekBartelsSpline : public idCurve_Spline<type> {
  1293. public:
  1294. idCurve_KochanekBartelsSpline();
  1295. virtual int AddValue( const float time, const type &value );
  1296. virtual int AddValue( const float time, const type &value, const float tension, const float continuity, const float bias );
  1297. virtual void RemoveIndex( const int index ) { this->values.RemoveIndex(index); this->times.RemoveIndex(index); tension.RemoveIndex(index); continuity.RemoveIndex(index); bias.RemoveIndex(index); }
  1298. virtual void Clear() { this->values.Clear(); this->times.Clear(); tension.Clear(); continuity.Clear(); bias.Clear(); this->currentIndex = -1; }
  1299. virtual type GetCurrentValue( const float time ) const;
  1300. virtual type GetCurrentFirstDerivative( const float time ) const;
  1301. virtual type GetCurrentSecondDerivative( const float time ) const;
  1302. protected:
  1303. idList<float> tension;
  1304. idList<float> continuity;
  1305. idList<float> bias;
  1306. void TangentsForIndex( const int index, type &t0, type &t1 ) const;
  1307. void Basis( const int index, const float t, float *bvals ) const;
  1308. void BasisFirstDerivative( const int index, const float t, float *bvals ) const;
  1309. void BasisSecondDerivative( const int index, const float t, float *bvals ) const;
  1310. };
  1311. /*
  1312. ====================
  1313. idCurve_KochanekBartelsSpline::idCurve_KochanekBartelsSpline
  1314. ====================
  1315. */
  1316. template< class type >
  1317. ID_INLINE idCurve_KochanekBartelsSpline<type>::idCurve_KochanekBartelsSpline() {
  1318. }
  1319. /*
  1320. ====================
  1321. idCurve_KochanekBartelsSpline::AddValue
  1322. add a timed/value pair to the spline
  1323. returns the index to the inserted pair
  1324. ====================
  1325. */
  1326. template< class type >
  1327. ID_INLINE int idCurve_KochanekBartelsSpline<type>::AddValue( const float time, const type &value ) {
  1328. int i;
  1329. i = this->IndexForTime( time );
  1330. this->times.Insert( time, i );
  1331. this->values.Insert( value, i );
  1332. tension.Insert( 0.0f, i );
  1333. continuity.Insert( 0.0f, i );
  1334. bias.Insert( 0.0f, i );
  1335. return i;
  1336. }
  1337. /*
  1338. ====================
  1339. idCurve_KochanekBartelsSpline::AddValue
  1340. add a timed/value pair to the spline
  1341. returns the index to the inserted pair
  1342. ====================
  1343. */
  1344. template< class type >
  1345. ID_INLINE int idCurve_KochanekBartelsSpline<type>::AddValue( const float time, const type &value, const float tension, const float continuity, const float bias ) {
  1346. int i;
  1347. i = this->IndexForTime( time );
  1348. this->times.Insert( time, i );
  1349. this->values.Insert( value, i );
  1350. this->tension.Insert( tension, i );
  1351. this->continuity.Insert( continuity, i );
  1352. this->bias.Insert( bias, i );
  1353. return i;
  1354. }
  1355. /*
  1356. ====================
  1357. idCurve_KochanekBartelsSpline::GetCurrentValue
  1358. get the value for the given time
  1359. ====================
  1360. */
  1361. template< class type >
  1362. ID_INLINE type idCurve_KochanekBartelsSpline<type>::GetCurrentValue( const float time ) const {
  1363. int i;
  1364. float bvals[4], clampedTime;
  1365. type v, t0, t1;
  1366. if ( this->times.Num() == 1 ) {
  1367. return this->values[0];
  1368. }
  1369. clampedTime = this->ClampedTime( time );
  1370. i = this->IndexForTime( clampedTime );
  1371. TangentsForIndex( i - 1, t0, t1 );
  1372. Basis( i - 1, clampedTime, bvals );
  1373. v = bvals[0] * this->ValueForIndex( i - 1 );
  1374. v += bvals[1] * this->ValueForIndex( i );
  1375. v += bvals[2] * t0;
  1376. v += bvals[3] * t1;
  1377. return v;
  1378. }
  1379. /*
  1380. ====================
  1381. idCurve_KochanekBartelsSpline::GetCurrentFirstDerivative
  1382. get the first derivative for the given time
  1383. ====================
  1384. */
  1385. template< class type >
  1386. ID_INLINE type idCurve_KochanekBartelsSpline<type>::GetCurrentFirstDerivative( const float time ) const {
  1387. int i;
  1388. float bvals[4], d, clampedTime;
  1389. type v, t0, t1;
  1390. if ( this->times.Num() == 1 ) {
  1391. return ( this->values[0] - this->values[0] ); //-V501
  1392. }
  1393. clampedTime = this->ClampedTime( time );
  1394. i = this->IndexForTime( clampedTime );
  1395. TangentsForIndex( i - 1, t0, t1 );
  1396. BasisFirstDerivative( i - 1, clampedTime, bvals );
  1397. v = bvals[0] * this->ValueForIndex( i - 1 );
  1398. v += bvals[1] * this->ValueForIndex( i );
  1399. v += bvals[2] * t0;
  1400. v += bvals[3] * t1;
  1401. d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
  1402. return v / d;
  1403. }
  1404. /*
  1405. ====================
  1406. idCurve_KochanekBartelsSpline::GetCurrentSecondDerivative
  1407. get the second derivative for the given time
  1408. ====================
  1409. */
  1410. template< class type >
  1411. ID_INLINE type idCurve_KochanekBartelsSpline<type>::GetCurrentSecondDerivative( const float time ) const {
  1412. int i;
  1413. float bvals[4], d, clampedTime;
  1414. type v, t0, t1;
  1415. if ( this->times.Num() == 1 ) {
  1416. return ( this->values[0] - this->values[0] ); //-V501
  1417. }
  1418. clampedTime = this->ClampedTime( time );
  1419. i = this->IndexForTime( clampedTime );
  1420. TangentsForIndex( i - 1, t0, t1 );
  1421. BasisSecondDerivative( i - 1, clampedTime, bvals );
  1422. v = bvals[0] * this->ValueForIndex( i - 1 );
  1423. v += bvals[1] * this->ValueForIndex( i );
  1424. v += bvals[2] * t0;
  1425. v += bvals[3] * t1;
  1426. d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
  1427. return v / ( d * d );
  1428. }
  1429. /*
  1430. ====================
  1431. idCurve_KochanekBartelsSpline::TangentsForIndex
  1432. ====================
  1433. */
  1434. template< class type >
  1435. ID_INLINE void idCurve_KochanekBartelsSpline<type>::TangentsForIndex( const int index, type &t0, type &t1 ) const {
  1436. float dt, omt, omc, opc, omb, opb, adj, s0, s1;
  1437. type delta;
  1438. delta = this->ValueForIndex( index + 1 ) - this->ValueForIndex( index );
  1439. dt = this->TimeForIndex( index + 1 ) - this->TimeForIndex( index );
  1440. omt = 1.0f - tension[index];
  1441. omc = 1.0f - continuity[index];
  1442. opc = 1.0f + continuity[index];
  1443. omb = 1.0f - bias[index];
  1444. opb = 1.0f + bias[index];
  1445. adj = 2.0f * dt / ( this->TimeForIndex( index + 1 ) - this->TimeForIndex( index - 1 ) );
  1446. s0 = 0.5f * adj * omt * opc * opb;
  1447. s1 = 0.5f * adj * omt * omc * omb;
  1448. // outgoing tangent at first point
  1449. t0 = s1 * delta + s0 * ( this->ValueForIndex( index ) - this->ValueForIndex( index - 1 ) );
  1450. omt = 1.0f - tension[index + 1];
  1451. omc = 1.0f - continuity[index + 1];
  1452. opc = 1.0f + continuity[index + 1];
  1453. omb = 1.0f - bias[index + 1];
  1454. opb = 1.0f + bias[index + 1];
  1455. adj = 2.0f * dt / ( this->TimeForIndex( index + 2 ) - this->TimeForIndex( index ) );
  1456. s0 = 0.5f * adj * omt * omc * opb;
  1457. s1 = 0.5f * adj * omt * opc * omb;
  1458. // incoming tangent at second point
  1459. t1 = s1 * ( this->ValueForIndex( index + 2 ) - this->ValueForIndex( index + 1 ) ) + s0 * delta;
  1460. }
  1461. /*
  1462. ====================
  1463. idCurve_KochanekBartelsSpline::Basis
  1464. spline basis functions
  1465. ====================
  1466. */
  1467. template< class type >
  1468. ID_INLINE void idCurve_KochanekBartelsSpline<type>::Basis( const int index, const float t, float *bvals ) const {
  1469. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1470. bvals[0] = ( ( 2.0f * s - 3.0f ) * s ) * s + 1.0f; // 2.0f * s * s * s - 3.0f * s * s + 1.0f
  1471. bvals[1] = ( ( -2.0f * s + 3.0f ) * s ) * s; // -2.0f * s * s * s + 3.0f * s * s
  1472. bvals[2] = ( ( s - 2.0f ) * s ) * s + s; // s * s * s - 2.0f * s * s + s
  1473. bvals[3] = ( ( s - 1.0f ) * s ) * s; // s * s * s - s * s
  1474. }
  1475. /*
  1476. ====================
  1477. idCurve_KochanekBartelsSpline::BasisFirstDerivative
  1478. first derivative of spline basis functions
  1479. ====================
  1480. */
  1481. template< class type >
  1482. ID_INLINE void idCurve_KochanekBartelsSpline<type>::BasisFirstDerivative( const int index, const float t, float *bvals ) const {
  1483. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1484. bvals[0] = ( 6.0f * s - 6.0f ) * s; // 6.0f * s * s - 6.0f * s
  1485. bvals[1] = ( -6.0f * s + 6.0f ) * s; // -6.0f * s * s + 6.0f * s
  1486. bvals[2] = ( 3.0f * s - 4.0f ) * s + 1.0f; // 3.0f * s * s - 4.0f * s + 1.0f
  1487. bvals[3] = ( 3.0f * s - 2.0f ) * s; // 3.0f * s * s - 2.0f * s
  1488. }
  1489. /*
  1490. ====================
  1491. idCurve_KochanekBartelsSpline::BasisSecondDerivative
  1492. second derivative of spline basis functions
  1493. ====================
  1494. */
  1495. template< class type >
  1496. ID_INLINE void idCurve_KochanekBartelsSpline<type>::BasisSecondDerivative( const int index, const float t, float *bvals ) const {
  1497. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1498. bvals[0] = 12.0f * s - 6.0f;
  1499. bvals[1] = -12.0f * s + 6.0f;
  1500. bvals[2] = 6.0f * s - 4.0f;
  1501. bvals[3] = 6.0f * s - 2.0f;
  1502. }
  1503. /*
  1504. ===============================================================================
  1505. B-Spline base template. Uses recursive definition and is slow.
  1506. Use idCurve_UniformCubicBSpline or idCurve_NonUniformBSpline instead.
  1507. ===============================================================================
  1508. */
  1509. template< class type >
  1510. class idCurve_BSpline : public idCurve_Spline<type> {
  1511. public:
  1512. idCurve_BSpline();
  1513. virtual int GetOrder() const { return order; }
  1514. virtual void SetOrder( const int i ) { assert( i > 0 && i < 10 ); order = i; }
  1515. virtual type GetCurrentValue( const float time ) const;
  1516. virtual type GetCurrentFirstDerivative( const float time ) const;
  1517. virtual type GetCurrentSecondDerivative( const float time ) const;
  1518. protected:
  1519. int order;
  1520. float Basis( const int index, const int order, const float t ) const;
  1521. float BasisFirstDerivative( const int index, const int order, const float t ) const;
  1522. float BasisSecondDerivative( const int index, const int order, const float t ) const;
  1523. };
  1524. /*
  1525. ====================
  1526. idCurve_BSpline::idCurve_NaturalCubicSpline
  1527. ====================
  1528. */
  1529. template< class type >
  1530. ID_INLINE idCurve_BSpline<type>::idCurve_BSpline() {
  1531. order = 4; // default to cubic
  1532. }
  1533. /*
  1534. ====================
  1535. idCurve_BSpline::GetCurrentValue
  1536. get the value for the given time
  1537. ====================
  1538. */
  1539. template< class type >
  1540. ID_INLINE type idCurve_BSpline<type>::GetCurrentValue( const float time ) const {
  1541. int i, j, k;
  1542. float clampedTime;
  1543. type v;
  1544. if ( this->times.Num() == 1 ) {
  1545. return this->values[0];
  1546. }
  1547. clampedTime = this->ClampedTime( time );
  1548. i = this->IndexForTime( clampedTime );
  1549. v = this->values[0] - this->values[0]; //-V501
  1550. for ( j = 0; j < order; j++ ) {
  1551. k = i + j - ( order >> 1 );
  1552. v += Basis( k-2, order, clampedTime ) * this->ValueForIndex( k );
  1553. }
  1554. return v;
  1555. }
  1556. /*
  1557. ====================
  1558. idCurve_BSpline::GetCurrentFirstDerivative
  1559. get the first derivative for the given time
  1560. ====================
  1561. */
  1562. template< class type >
  1563. ID_INLINE type idCurve_BSpline<type>::GetCurrentFirstDerivative( const float time ) const {
  1564. int i, j, k;
  1565. float clampedTime;
  1566. type v;
  1567. if ( this->times.Num() == 1 ) {
  1568. return this->values[0];
  1569. }
  1570. clampedTime = this->ClampedTime( time );
  1571. i = this->IndexForTime( clampedTime );
  1572. v = this->values[0] - this->values[0]; //-V501
  1573. for ( j = 0; j < order; j++ ) {
  1574. k = i + j - ( order >> 1 );
  1575. v += BasisFirstDerivative( k-2, order, clampedTime ) * this->ValueForIndex( k );
  1576. }
  1577. return v;
  1578. }
  1579. /*
  1580. ====================
  1581. idCurve_BSpline::GetCurrentSecondDerivative
  1582. get the second derivative for the given time
  1583. ====================
  1584. */
  1585. template< class type >
  1586. ID_INLINE type idCurve_BSpline<type>::GetCurrentSecondDerivative( const float time ) const {
  1587. int i, j, k;
  1588. float clampedTime;
  1589. type v;
  1590. if ( this->times.Num() == 1 ) {
  1591. return this->values[0];
  1592. }
  1593. clampedTime = this->ClampedTime( time );
  1594. i = this->IndexForTime( clampedTime );
  1595. v = this->values[0] - this->values[0]; //-V501
  1596. for ( j = 0; j < order; j++ ) {
  1597. k = i + j - ( order >> 1 );
  1598. v += BasisSecondDerivative( k-2, order, clampedTime ) * this->ValueForIndex( k );
  1599. }
  1600. return v;
  1601. }
  1602. /*
  1603. ====================
  1604. idCurve_BSpline::Basis
  1605. spline basis function
  1606. ====================
  1607. */
  1608. template< class type >
  1609. ID_INLINE float idCurve_BSpline<type>::Basis( const int index, const int order, const float t ) const {
  1610. if ( order <= 1 ) {
  1611. if ( this->TimeForIndex( index ) < t && t <= this->TimeForIndex( index + 1 ) ) {
  1612. return 1.0f;
  1613. } else {
  1614. return 0.0f;
  1615. }
  1616. } else {
  1617. float sum = 0.0f;
  1618. float d1 = this->TimeForIndex( index+order-1 ) - this->TimeForIndex( index );
  1619. if ( d1 != 0.0f ) {
  1620. sum += (float) ( t - this->TimeForIndex( index ) ) * Basis( index, order-1, t ) / d1;
  1621. }
  1622. float d2 = this->TimeForIndex( index+order ) - this->TimeForIndex( index+1 );
  1623. if ( d2 != 0.0f ) {
  1624. sum += (float) ( this->TimeForIndex( index+order ) - t ) * Basis( index+1, order-1, t ) / d2;
  1625. }
  1626. return sum;
  1627. }
  1628. }
  1629. /*
  1630. ====================
  1631. idCurve_BSpline::BasisFirstDerivative
  1632. first derivative of spline basis function
  1633. ====================
  1634. */
  1635. template< class type >
  1636. ID_INLINE float idCurve_BSpline<type>::BasisFirstDerivative( const int index, const int order, const float t ) const {
  1637. return ( Basis( index, order-1, t ) - Basis( index+1, order-1, t ) ) *
  1638. (float) ( order - 1 ) / ( this->TimeForIndex( index + ( order - 1 ) - 2 ) - this->TimeForIndex( index - 2 ) );
  1639. }
  1640. /*
  1641. ====================
  1642. idCurve_BSpline::BasisSecondDerivative
  1643. second derivative of spline basis function
  1644. ====================
  1645. */
  1646. template< class type >
  1647. ID_INLINE float idCurve_BSpline<type>::BasisSecondDerivative( const int index, const int order, const float t ) const {
  1648. return ( BasisFirstDerivative( index, order-1, t ) - BasisFirstDerivative( index+1, order-1, t ) ) *
  1649. (float) ( order - 1 ) / ( this->TimeForIndex( index + ( order - 1 ) - 2 ) - this->TimeForIndex( index - 2 ) );
  1650. }
  1651. /*
  1652. ===============================================================================
  1653. Uniform Non-Rational Cubic B-Spline template.
  1654. ===============================================================================
  1655. */
  1656. template< class type >
  1657. class idCurve_UniformCubicBSpline : public idCurve_BSpline<type> {
  1658. public:
  1659. idCurve_UniformCubicBSpline();
  1660. virtual type GetCurrentValue( const float time ) const;
  1661. virtual type GetCurrentFirstDerivative( const float time ) const;
  1662. virtual type GetCurrentSecondDerivative( const float time ) const;
  1663. protected:
  1664. void Basis( const int index, const float t, float *bvals ) const;
  1665. void BasisFirstDerivative( const int index, const float t, float *bvals ) const;
  1666. void BasisSecondDerivative( const int index, const float t, float *bvals ) const;
  1667. };
  1668. /*
  1669. ====================
  1670. idCurve_UniformCubicBSpline::idCurve_UniformCubicBSpline
  1671. ====================
  1672. */
  1673. template< class type >
  1674. ID_INLINE idCurve_UniformCubicBSpline<type>::idCurve_UniformCubicBSpline() {
  1675. this->order = 4; // always cubic
  1676. }
  1677. /*
  1678. ====================
  1679. idCurve_UniformCubicBSpline::GetCurrentValue
  1680. get the value for the given time
  1681. ====================
  1682. */
  1683. template< class type >
  1684. ID_INLINE type idCurve_UniformCubicBSpline<type>::GetCurrentValue( const float time ) const {
  1685. int i, j, k;
  1686. float bvals[4], clampedTime;
  1687. type v;
  1688. if ( this->times.Num() == 1 ) {
  1689. return this->values[0];
  1690. }
  1691. clampedTime = this->ClampedTime( time );
  1692. i = this->IndexForTime( clampedTime );
  1693. Basis( i-1, clampedTime, bvals );
  1694. v = this->values[0] - this->values[0]; //-V501
  1695. for ( j = 0; j < 4; j++ ) {
  1696. k = i + j - 2;
  1697. v += bvals[j] * this->ValueForIndex( k );
  1698. }
  1699. return v;
  1700. }
  1701. /*
  1702. ====================
  1703. idCurve_UniformCubicBSpline::GetCurrentFirstDerivative
  1704. get the first derivative for the given time
  1705. ====================
  1706. */
  1707. template< class type >
  1708. ID_INLINE type idCurve_UniformCubicBSpline<type>::GetCurrentFirstDerivative( const float time ) const {
  1709. int i, j, k;
  1710. float bvals[4], d, clampedTime;
  1711. type v;
  1712. if ( this->times.Num() == 1 ) {
  1713. return ( this->values[0] - this->values[0] ); //-V501
  1714. }
  1715. clampedTime = this->ClampedTime( time );
  1716. i = this->IndexForTime( clampedTime );
  1717. BasisFirstDerivative( i-1, clampedTime, bvals );
  1718. v = this->values[0] - this->values[0]; //-V501
  1719. for ( j = 0; j < 4; j++ ) {
  1720. k = i + j - 2;
  1721. v += bvals[j] * this->ValueForIndex( k );
  1722. }
  1723. d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
  1724. return v / d;
  1725. }
  1726. /*
  1727. ====================
  1728. idCurve_UniformCubicBSpline::GetCurrentSecondDerivative
  1729. get the second derivative for the given time
  1730. ====================
  1731. */
  1732. template< class type >
  1733. ID_INLINE type idCurve_UniformCubicBSpline<type>::GetCurrentSecondDerivative( const float time ) const {
  1734. int i, j, k;
  1735. float bvals[4], d, clampedTime;
  1736. type v;
  1737. if ( this->times.Num() == 1 ) {
  1738. return ( this->values[0] - this->values[0] ); //-V501
  1739. }
  1740. clampedTime = this->ClampedTime( time );
  1741. i = this->IndexForTime( clampedTime );
  1742. BasisSecondDerivative( i-1, clampedTime, bvals );
  1743. v = this->values[0] - this->values[0]; //-V501
  1744. for ( j = 0; j < 4; j++ ) {
  1745. k = i + j - 2;
  1746. v += bvals[j] * this->ValueForIndex( k );
  1747. }
  1748. d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
  1749. return v / ( d * d );
  1750. }
  1751. /*
  1752. ====================
  1753. idCurve_UniformCubicBSpline::Basis
  1754. spline basis functions
  1755. ====================
  1756. */
  1757. template< class type >
  1758. ID_INLINE void idCurve_UniformCubicBSpline<type>::Basis( const int index, const float t, float *bvals ) const {
  1759. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1760. bvals[0] = ( ( ( -s + 3.0f ) * s - 3.0f ) * s + 1.0f ) * ( 1.0f / 6.0f );
  1761. bvals[1] = ( ( ( 3.0f * s - 6.0f ) * s ) * s + 4.0f ) * ( 1.0f / 6.0f );
  1762. bvals[2] = ( ( ( -3.0f * s + 3.0f ) * s + 3.0f ) * s + 1.0f ) * ( 1.0f / 6.0f );
  1763. bvals[3] = ( s * s * s ) * ( 1.0f / 6.0f );
  1764. }
  1765. /*
  1766. ====================
  1767. idCurve_UniformCubicBSpline::BasisFirstDerivative
  1768. first derivative of spline basis functions
  1769. ====================
  1770. */
  1771. template< class type >
  1772. ID_INLINE void idCurve_UniformCubicBSpline<type>::BasisFirstDerivative( const int index, const float t, float *bvals ) const {
  1773. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1774. bvals[0] = -0.5f * s * s + s - 0.5f;
  1775. bvals[1] = 1.5f * s * s - 2.0f * s;
  1776. bvals[2] = -1.5f * s * s + s + 0.5f;
  1777. bvals[3] = 0.5f * s * s;
  1778. }
  1779. /*
  1780. ====================
  1781. idCurve_UniformCubicBSpline::BasisSecondDerivative
  1782. second derivative of spline basis functions
  1783. ====================
  1784. */
  1785. template< class type >
  1786. ID_INLINE void idCurve_UniformCubicBSpline<type>::BasisSecondDerivative( const int index, const float t, float *bvals ) const {
  1787. float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
  1788. bvals[0] = -s + 1.0f;
  1789. bvals[1] = 3.0f * s - 2.0f;
  1790. bvals[2] = -3.0f * s + 1.0f;
  1791. bvals[3] = s;
  1792. }
  1793. /*
  1794. ===============================================================================
  1795. Non-Uniform Non-Rational B-Spline (NUBS) template.
  1796. ===============================================================================
  1797. */
  1798. template< class type >
  1799. class idCurve_NonUniformBSpline : public idCurve_BSpline<type> {
  1800. public:
  1801. idCurve_NonUniformBSpline();
  1802. virtual type GetCurrentValue( const float time ) const;
  1803. virtual type GetCurrentFirstDerivative( const float time ) const;
  1804. virtual type GetCurrentSecondDerivative( const float time ) const;
  1805. protected:
  1806. void Basis( const int index, const int order, const float t, float *bvals ) const;
  1807. void BasisFirstDerivative( const int index, const int order, const float t, float *bvals ) const;
  1808. void BasisSecondDerivative( const int index, const int order, const float t, float *bvals ) const;
  1809. };
  1810. /*
  1811. ====================
  1812. idCurve_NonUniformBSpline::idCurve_NonUniformBSpline
  1813. ====================
  1814. */
  1815. template< class type >
  1816. ID_INLINE idCurve_NonUniformBSpline<type>::idCurve_NonUniformBSpline() {
  1817. }
  1818. /*
  1819. ====================
  1820. idCurve_NonUniformBSpline::GetCurrentValue
  1821. get the value for the given time
  1822. ====================
  1823. */
  1824. template< class type >
  1825. ID_INLINE type idCurve_NonUniformBSpline<type>::GetCurrentValue( const float time ) const {
  1826. int i, j, k;
  1827. float clampedTime;
  1828. type v;
  1829. float *bvals = (float *) _alloca16( this->order * sizeof(float) );
  1830. if ( this->times.Num() == 1 ) {
  1831. return this->values[0];
  1832. }
  1833. clampedTime = this->ClampedTime( time );
  1834. i = this->IndexForTime( clampedTime );
  1835. Basis( i-1, this->order, clampedTime, bvals );
  1836. v = this->values[0] - this->values[0]; //-V501
  1837. for ( j = 0; j < this->order; j++ ) {
  1838. k = i + j - ( this->order >> 1 );
  1839. v += bvals[j] * this->ValueForIndex( k );
  1840. }
  1841. return v;
  1842. }
  1843. /*
  1844. ====================
  1845. idCurve_NonUniformBSpline::GetCurrentFirstDerivative
  1846. get the first derivative for the given time
  1847. ====================
  1848. */
  1849. template< class type >
  1850. ID_INLINE type idCurve_NonUniformBSpline<type>::GetCurrentFirstDerivative( const float time ) const {
  1851. int i, j, k;
  1852. float clampedTime;
  1853. type v;
  1854. float *bvals = (float *) _alloca16( this->order * sizeof(float) );
  1855. if ( this->times.Num() == 1 ) {
  1856. return ( this->values[0] - this->values[0] ); //-V501
  1857. }
  1858. clampedTime = this->ClampedTime( time );
  1859. i = this->IndexForTime( clampedTime );
  1860. BasisFirstDerivative( i-1, this->order, clampedTime, bvals );
  1861. v = this->values[0] - this->values[0]; //-V501
  1862. for ( j = 0; j < this->order; j++ ) {
  1863. k = i + j - ( this->order >> 1 );
  1864. v += bvals[j] * this->ValueForIndex( k );
  1865. }
  1866. return v;
  1867. }
  1868. /*
  1869. ====================
  1870. idCurve_NonUniformBSpline::GetCurrentSecondDerivative
  1871. get the second derivative for the given time
  1872. ====================
  1873. */
  1874. template< class type >
  1875. ID_INLINE type idCurve_NonUniformBSpline<type>::GetCurrentSecondDerivative( const float time ) const {
  1876. int i, j, k;
  1877. float clampedTime;
  1878. type v;
  1879. float *bvals = (float *) _alloca16( this->order * sizeof(float) );
  1880. if ( this->times.Num() == 1 ) {
  1881. return ( this->values[0] - this->values[0] ); //-V501
  1882. }
  1883. clampedTime = this->ClampedTime( time );
  1884. i = this->IndexForTime( clampedTime );
  1885. BasisSecondDerivative( i-1, this->order, clampedTime, bvals );
  1886. v = this->values[0] - this->values[0]; //-V501
  1887. for ( j = 0; j < this->order; j++ ) {
  1888. k = i + j - ( this->order >> 1 );
  1889. v += bvals[j] * this->ValueForIndex( k );
  1890. }
  1891. return v;
  1892. }
  1893. /*
  1894. ====================
  1895. idCurve_NonUniformBSpline::Basis
  1896. spline basis functions
  1897. ====================
  1898. */
  1899. template< class type >
  1900. ID_INLINE void idCurve_NonUniformBSpline<type>::Basis( const int index, const int order, const float t, float *bvals ) const {
  1901. int r, s, i;
  1902. float omega;
  1903. bvals[order-1] = 1.0f;
  1904. for ( r = 2; r <= order; r++ ) {
  1905. i = index - r + 1;
  1906. bvals[order - r] = 0.0f;
  1907. for ( s = order - r + 1; s < order; s++ ) {
  1908. i++;
  1909. omega = (float) ( t - this->TimeForIndex( i ) ) / ( this->TimeForIndex( i + r - 1 ) - this->TimeForIndex( i ) );
  1910. bvals[s - 1] += ( 1.0f - omega ) * bvals[s];
  1911. bvals[s] *= omega;
  1912. }
  1913. }
  1914. }
  1915. /*
  1916. ====================
  1917. idCurve_NonUniformBSpline::BasisFirstDerivative
  1918. first derivative of spline basis functions
  1919. ====================
  1920. */
  1921. template< class type >
  1922. ID_INLINE void idCurve_NonUniformBSpline<type>::BasisFirstDerivative( const int index, const int order, const float t, float *bvals ) const {
  1923. int i;
  1924. Basis( index, order-1, t, bvals+1 );
  1925. bvals[0] = 0.0f;
  1926. for ( i = 0; i < order-1; i++ ) {
  1927. bvals[i] -= bvals[i+1];
  1928. bvals[i] *= (float) ( order - 1) / ( this->TimeForIndex( index + i + (order-1) - 2 ) - this->TimeForIndex( index + i - 2 ) );
  1929. }
  1930. bvals[i] *= (float) ( order - 1) / ( this->TimeForIndex( index + i + (order-1) - 2 ) - this->TimeForIndex( index + i - 2 ) );
  1931. }
  1932. /*
  1933. ====================
  1934. idCurve_NonUniformBSpline::BasisSecondDerivative
  1935. second derivative of spline basis functions
  1936. ====================
  1937. */
  1938. template< class type >
  1939. ID_INLINE void idCurve_NonUniformBSpline<type>::BasisSecondDerivative( const int index, const int order, const float t, float *bvals ) const {
  1940. int i;
  1941. BasisFirstDerivative( index, order-1, t, bvals+1 );
  1942. bvals[0] = 0.0f;
  1943. for ( i = 0; i < order-1; i++ ) {
  1944. bvals[i] -= bvals[i+1];
  1945. bvals[i] *= (float) ( order - 1) / ( this->TimeForIndex( index + i + (order-1) - 2 ) - this->TimeForIndex( index + i - 2 ) );
  1946. }
  1947. bvals[i] *= (float) ( order - 1) / ( this->TimeForIndex( index + i + (order-1) - 2 ) - this->TimeForIndex( index + i - 2 ) );
  1948. }
  1949. /*
  1950. ===============================================================================
  1951. Non-Uniform Rational B-Spline (NURBS) template.
  1952. ===============================================================================
  1953. */
  1954. template< class type >
  1955. class idCurve_NURBS : public idCurve_NonUniformBSpline<type> {
  1956. public:
  1957. idCurve_NURBS();
  1958. virtual int AddValue( const float time, const type &value );
  1959. virtual int AddValue( const float time, const type &value, const float weight );
  1960. virtual void RemoveIndex( const int index ) { this->values.RemoveIndex(index); this->times.RemoveIndex(index); weights.RemoveIndex(index); }
  1961. virtual void Clear() { this->values.Clear(); this->times.Clear(); weights.Clear(); this->currentIndex = -1; }
  1962. virtual type GetCurrentValue( const float time ) const;
  1963. virtual type GetCurrentFirstDerivative( const float time ) const;
  1964. virtual type GetCurrentSecondDerivative( const float time ) const;
  1965. protected:
  1966. idList<float> weights;
  1967. float WeightForIndex( const int index ) const;
  1968. };
  1969. /*
  1970. ====================
  1971. idCurve_NURBS::idCurve_NURBS
  1972. ====================
  1973. */
  1974. template< class type >
  1975. ID_INLINE idCurve_NURBS<type>::idCurve_NURBS() {
  1976. }
  1977. /*
  1978. ====================
  1979. idCurve_NURBS::AddValue
  1980. add a timed/value pair to the spline
  1981. returns the index to the inserted pair
  1982. ====================
  1983. */
  1984. template< class type >
  1985. ID_INLINE int idCurve_NURBS<type>::AddValue( const float time, const type &value ) {
  1986. int i;
  1987. i = this->IndexForTime( time );
  1988. this->times.Insert( time, i );
  1989. this->values.Insert( value, i );
  1990. weights.Insert( 1.0f, i );
  1991. return i;
  1992. }
  1993. /*
  1994. ====================
  1995. idCurve_NURBS::AddValue
  1996. add a timed/value pair to the spline
  1997. returns the index to the inserted pair
  1998. ====================
  1999. */
  2000. template< class type >
  2001. ID_INLINE int idCurve_NURBS<type>::AddValue( const float time, const type &value, const float weight ) {
  2002. int i;
  2003. i = this->IndexForTime( time );
  2004. this->times.Insert( time, i );
  2005. this->values.Insert( value, i );
  2006. weights.Insert( weight, i );
  2007. return i;
  2008. }
  2009. /*
  2010. ====================
  2011. idCurve_NURBS::GetCurrentValue
  2012. get the value for the given time
  2013. ====================
  2014. */
  2015. template< class type >
  2016. ID_INLINE type idCurve_NURBS<type>::GetCurrentValue( const float time ) const {
  2017. int i, j, k;
  2018. float w, b, *bvals, clampedTime;
  2019. type v;
  2020. if ( this->times.Num() == 1 ) {
  2021. return this->values[0];
  2022. }
  2023. bvals = (float *) _alloca16( this->order * sizeof(float) );
  2024. clampedTime = this->ClampedTime( time );
  2025. i = this->IndexForTime( clampedTime );
  2026. this->Basis( i-1, this->order, clampedTime, bvals );
  2027. v = this->values[0] - this->values[0]; //-V501
  2028. w = 0.0f;
  2029. for ( j = 0; j < this->order; j++ ) {
  2030. k = i + j - ( this->order >> 1 );
  2031. b = bvals[j] * WeightForIndex( k );
  2032. w += b;
  2033. v += b * this->ValueForIndex( k );
  2034. }
  2035. return v / w;
  2036. }
  2037. /*
  2038. ====================
  2039. idCurve_NURBS::GetCurrentFirstDerivative
  2040. get the first derivative for the given time
  2041. ====================
  2042. */
  2043. template< class type >
  2044. ID_INLINE type idCurve_NURBS<type>::GetCurrentFirstDerivative( const float time ) const {
  2045. int i, j, k;
  2046. float w, wb, wd1, b, d1, *bvals, *d1vals, clampedTime;
  2047. type v, vb, vd1;
  2048. if ( this->times.Num() == 1 ) {
  2049. return this->values[0];
  2050. }
  2051. bvals = (float *) _alloca16( this->order * sizeof(float) );
  2052. d1vals = (float *) _alloca16( this->order * sizeof(float) );
  2053. clampedTime = this->ClampedTime( time );
  2054. i = this->IndexForTime( clampedTime );
  2055. this->Basis( i-1, this->order, clampedTime, bvals );
  2056. this->BasisFirstDerivative( i-1, this->order, clampedTime, d1vals );
  2057. vb = vd1 = this->values[0] - this->values[0]; //-V501
  2058. wb = wd1 = 0.0f;
  2059. for ( j = 0; j < this->order; j++ ) {
  2060. k = i + j - ( this->order >> 1 );
  2061. w = WeightForIndex( k );
  2062. b = bvals[j] * w;
  2063. d1 = d1vals[j] * w;
  2064. wb += b;
  2065. wd1 += d1;
  2066. v = this->ValueForIndex( k );
  2067. vb += b * v;
  2068. vd1 += d1 * v;
  2069. }
  2070. return ( wb * vd1 - vb * wd1 ) / ( wb * wb );
  2071. }
  2072. /*
  2073. ====================
  2074. idCurve_NURBS::GetCurrentSecondDerivative
  2075. get the second derivative for the given time
  2076. ====================
  2077. */
  2078. template< class type >
  2079. ID_INLINE type idCurve_NURBS<type>::GetCurrentSecondDerivative( const float time ) const {
  2080. int i, j, k;
  2081. float w, wb, wd1, wd2, b, d1, d2, *bvals, *d1vals, *d2vals, clampedTime;
  2082. type v, vb, vd1, vd2;
  2083. if ( this->times.Num() == 1 ) {
  2084. return this->values[0];
  2085. }
  2086. bvals = (float *) _alloca16( this->order * sizeof(float) );
  2087. d1vals = (float *) _alloca16( this->order * sizeof(float) );
  2088. d2vals = (float *) _alloca16( this->order * sizeof(float) );
  2089. clampedTime = this->ClampedTime( time );
  2090. i = this->IndexForTime( clampedTime );
  2091. this->Basis( i-1, this->order, clampedTime, bvals );
  2092. this->BasisFirstDerivative( i-1, this->order, clampedTime, d1vals );
  2093. this->BasisSecondDerivative( i-1, this->order, clampedTime, d2vals );
  2094. vb = vd1 = vd2 = this->values[0] - this->values[0]; //-V501
  2095. wb = wd1 = wd2 = 0.0f;
  2096. for ( j = 0; j < this->order; j++ ) {
  2097. k = i + j - ( this->order >> 1 );
  2098. w = WeightForIndex( k );
  2099. b = bvals[j] * w;
  2100. d1 = d1vals[j] * w;
  2101. d2 = d2vals[j] * w;
  2102. wb += b;
  2103. wd1 += d1;
  2104. wd2 += d2;
  2105. v = this->ValueForIndex( k );
  2106. vb += b * v;
  2107. vd1 += d1 * v;
  2108. vd2 += d2 * v;
  2109. }
  2110. return ( ( wb * wb ) * ( wb * vd2 - vb * wd2 ) - ( wb * vd1 - vb * wd1 ) * 2.0f * wb * wd1 ) / ( wb * wb * wb * wb );
  2111. }
  2112. /*
  2113. ====================
  2114. idCurve_NURBS::WeightForIndex
  2115. get the weight for the given index
  2116. ====================
  2117. */
  2118. template< class type >
  2119. ID_INLINE float idCurve_NURBS<type>::WeightForIndex( const int index ) const {
  2120. int n = weights.Num()-1;
  2121. if ( index < 0 ) {
  2122. if ( this->boundaryType == idCurve_Spline<type>::BT_CLOSED ) {
  2123. return weights[ weights.Num() + index % weights.Num() ];
  2124. } else {
  2125. return weights[0] + index * ( weights[1] - weights[0] );
  2126. }
  2127. } else if ( index > n ) {
  2128. if ( this->boundaryType == idCurve_Spline<type>::BT_CLOSED ) {
  2129. return weights[ index % weights.Num() ];
  2130. } else {
  2131. return weights[n] + ( index - n ) * ( weights[n] - weights[n-1] );
  2132. }
  2133. }
  2134. return weights[index];
  2135. }
  2136. #endif /* !__MATH_CURVE_H__ */