DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Curve.h (72505B)


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