12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- 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.
- 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.
- ===========================================================================
- */
- #ifndef __MATH_CURVE_H__
- #define __MATH_CURVE_H__
- /*
- ===============================================================================
- Curve base template.
- ===============================================================================
- */
- template< class type >
- class idCurve {
- public:
- idCurve();
- virtual ~idCurve();
- virtual int AddValue( const float time, const type &value );
- virtual void RemoveIndex( const int index ) { values.RemoveIndex(index); times.RemoveIndex(index); changed = true; }
- virtual void Clear() { values.Clear(); times.Clear(); currentIndex = -1; changed = true; }
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- virtual bool IsDone( const float time ) const;
- int GetNumValues() const { return values.Num(); }
- void SetValue( const int index, const type &value ) { values[index] = value; changed = true; }
- type GetValue( const int index ) const { return values[index]; }
- type * GetValueAddress( const int index ) { return &values[index]; }
- float GetTime( const int index ) const { return times[index]; }
- float GetLengthForTime( const float time ) const;
- float GetTimeForLength( const float length, const float epsilon = 0.1f ) const;
- float GetLengthBetweenKnots( const int i0, const int i1 ) const;
- void MakeUniform( const float totalTime );
- void SetConstantSpeed( const float totalTime );
- void ShiftTime( const float deltaTime );
- void Translate( const type &translation );
- protected:
- idList<float> times; // knots
- idList<type> values; // knot values
-
- mutable int currentIndex; // cached index for fast lookup
- mutable bool changed; // set whenever the curve changes
- int IndexForTime( const float time ) const;
- float TimeForIndex( const int index ) const;
- type ValueForIndex( const int index ) const;
- float GetSpeed( const float time ) const;
- float RombergIntegral( const float t0, const float t1, const int order ) const;
- };
- /*
- ====================
- idCurve::idCurve
- ====================
- */
- template< class type >
- ID_INLINE idCurve<type>::idCurve() {
- currentIndex = -1;
- changed = false;
- }
- /*
- ====================
- idCurve::~idCurve
- ====================
- */
- template< class type >
- ID_INLINE idCurve<type>::~idCurve() {
- }
- /*
- ====================
- idCurve::AddValue
- add a timed/value pair to the spline
- returns the index to the inserted pair
- ====================
- */
- template< class type >
- ID_INLINE int idCurve<type>::AddValue( const float time, const type &value ) {
- int i;
- i = IndexForTime( time );
- times.Insert( time, i );
- values.Insert( value, i );
- changed = true;
- return i;
- }
- /*
- ====================
- idCurve::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve<type>::GetCurrentValue( const float time ) const {
- int i;
- i = IndexForTime( time );
- if ( i >= values.Num() ) {
- return values[values.Num() - 1];
- } else {
- return values[i];
- }
- }
- /*
- ====================
- idCurve::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve<type>::GetCurrentFirstDerivative( const float time ) const {
- return ( values[0] - values[0] ); //-V501
- }
- /*
- ====================
- idCurve::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve<type>::GetCurrentSecondDerivative( const float time ) const {
- return ( values[0] - values[0] ); //-V501
- }
- /*
- ====================
- idCurve::IsDone
- ====================
- */
- template< class type >
- ID_INLINE bool idCurve<type>::IsDone( const float time ) const {
- return ( time >= times[ times.Num() - 1 ] );
- }
- /*
- ====================
- idCurve::GetSpeed
- ====================
- */
- template< class type >
- ID_INLINE float idCurve<type>::GetSpeed( const float time ) const {
- int i;
- float speed;
- type value;
- value = GetCurrentFirstDerivative( time );
- for ( speed = 0.0f, i = 0; i < value.GetDimension(); i++ ) {
- speed += value[i] * value[i];
- }
- return idMath::Sqrt( speed );
- }
- /*
- ====================
- idCurve::RombergIntegral
- ====================
- */
- template< class type >
- ID_INLINE float idCurve<type>::RombergIntegral( const float t0, const float t1, const int order ) const {
- int i, j, k, m, n;
- float sum, delta;
- float *temp[2];
- temp[0] = (float *) _alloca16( order * sizeof( float ) );
- temp[1] = (float *) _alloca16( order * sizeof( float ) );
- delta = t1 - t0;
- temp[0][0] = 0.5f * delta * ( GetSpeed( t0 ) + GetSpeed( t1 ) );
- for ( i = 2, m = 1; i <= order; i++, m *= 2, delta *= 0.5f ) {
- // approximate using the trapezoid rule
- sum = 0.0f;
- for ( j = 1; j <= m; j++ ) {
- sum += GetSpeed( t0 + delta * ( j - 0.5f ) );
- }
- // Richardson extrapolation
- temp[1][0] = 0.5f * ( temp[0][0] + delta * sum );
- for ( k = 1, n = 4; k < i; k++, n *= 4 ) {
- temp[1][k] = ( n * temp[1][k-1] - temp[0][k-1] ) / ( n - 1 );
- }
- for ( j = 0; j < i; j++ ) {
- temp[0][j] = temp[1][j];
- }
- }
- return temp[0][order-1];
- }
- /*
- ====================
- idCurve::GetLengthBetweenKnots
- ====================
- */
- template< class type >
- ID_INLINE float idCurve<type>::GetLengthBetweenKnots( const int i0, const int i1 ) const {
- float length = 0.0f;
- for ( int i = i0; i < i1; i++ ) {
- length += RombergIntegral( times[i], times[i+1], 5 );
- }
- return length;
- }
- /*
- ====================
- idCurve::GetLengthForTime
- ====================
- */
- template< class type >
- ID_INLINE float idCurve<type>::GetLengthForTime( const float time ) const {
- float length = 0.0f;
- int index = IndexForTime( time );
- for ( int i = 0; i < index; i++ ) {
- length += RombergIntegral( times[i], times[i+1], 5 );
- }
- length += RombergIntegral( times[index], time, 5 );
- return length;
- }
- /*
- ====================
- idCurve::GetTimeForLength
- ====================
- */
- template< class type >
- ID_INLINE float idCurve<type>::GetTimeForLength( const float length, const float epsilon ) const {
- int i, index;
- float *accumLength, totalLength, len0, len1, t, diff;
- if ( length <= 0.0f ) {
- return times[0];
- }
- accumLength = (float *) _alloca16( values.Num() * sizeof( float ) );
- totalLength = 0.0f;
- for ( index = 0; index < values.Num() - 1; index++ ) {
- totalLength += GetLengthBetweenKnots( index, index + 1 );
- accumLength[index] = totalLength;
- if ( length < accumLength[index] ) {
- break;
- }
- }
- if ( index >= values.Num() - 1 ) {
- return times[times.Num() - 1];
- }
- if ( index == 0 ) {
- len0 = length;
- len1 = accumLength[0];
- } else {
- len0 = length - accumLength[index-1];
- len1 = accumLength[index] - accumLength[index-1];
- }
- // invert the arc length integral using Newton's method
- t = ( times[index+1] - times[index] ) * len0 / len1;
- for ( i = 0; i < 32; i++ ) {
- diff = RombergIntegral( times[index], times[index] + t, 5 ) - len0;
- if ( idMath::Fabs( diff ) <= epsilon ) {
- return times[index] + t;
- }
- t -= diff / GetSpeed( times[index] + t );
- }
- return times[index] + t;
- }
- /*
- ====================
- idCurve::MakeUniform
- ====================
- */
- template< class type >
- ID_INLINE void idCurve<type>::MakeUniform( const float totalTime ) {
- int i, n;
- n = times.Num() - 1;
- for ( i = 0; i <= n; i++ ) {
- times[i] = i * totalTime / n;
- }
- changed = true;
- }
- /*
- ====================
- idCurve::SetConstantSpeed
- ====================
- */
- template< class type >
- ID_INLINE void idCurve<type>::SetConstantSpeed( const float totalTime ) {
- int i, j;
- float *length, totalLength, scale, t;
- length = (float *) _alloca16( values.Num() * sizeof( float ) );
- totalLength = 0.0f;
- for ( i = 0; i < values.Num() - 1; i++ ) {
- length[i] = GetLengthBetweenKnots( i, i + 1 );
- totalLength += length[i];
- }
- scale = totalTime / totalLength;
- for ( t = 0.0f, i = 0; i < times.Num() - 1; i++ ) {
- times[i] = t;
- t += scale * length[i];
- }
- times[times.Num() - 1] = totalTime;
- changed = true;
- }
- /*
- ====================
- idCurve::ShiftTime
- ====================
- */
- template< class type >
- ID_INLINE void idCurve<type>::ShiftTime( const float deltaTime ) {
- for ( int i = 0; i < times.Num(); i++ ) {
- times[i] += deltaTime;
- }
- changed = true;
- }
- /*
- ====================
- idCurve::Translate
- ====================
- */
- template< class type >
- ID_INLINE void idCurve<type>::Translate( const type &translation ) {
- for ( int i = 0; i < values.Num(); i++ ) {
- values[i] += translation;
- }
- changed = true;
- }
- /*
- ====================
- idCurve::IndexForTime
- find the index for the first time greater than or equal to the given time
- ====================
- */
- template< class type >
- ID_INLINE int idCurve<type>::IndexForTime( const float time ) const {
- int len, mid, offset, res;
- if ( currentIndex >= 0 && currentIndex <= times.Num() ) {
- // use the cached index if it is still valid
- if ( currentIndex == 0 ) {
- if ( time <= times[currentIndex] ) {
- return currentIndex;
- }
- } else if ( currentIndex == times.Num() ) {
- if ( time > times[currentIndex-1] ) {
- return currentIndex;
- }
- } else if ( time > times[currentIndex-1] && time <= times[currentIndex] ) {
- return currentIndex;
- } else if ( time > times[currentIndex] && ( currentIndex+1 == times.Num() || time <= times[currentIndex+1] ) ) {
- // use the next index
- currentIndex++;
- return currentIndex;
- }
- }
- // use binary search to find the index for the given time
- len = times.Num();
- mid = len;
- offset = 0;
- res = 0;
- while( mid > 0 ) {
- mid = len >> 1;
- if ( time == times[offset+mid] ) {
- return offset+mid;
- } else if ( time > times[offset+mid] ) {
- offset += mid;
- len -= mid;
- res = 1;
- } else {
- len -= mid;
- res = 0;
- }
- }
- currentIndex = offset+res;
- return currentIndex;
- }
- /*
- ====================
- idCurve::ValueForIndex
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve<type>::ValueForIndex( const int index ) const {
- int n = values.Num()-1;
- if ( index < 0 ) {
- return values[0] + index * ( values[1] - values[0] );
- } else if ( index > n ) {
- return values[n] + ( index - n ) * ( values[n] - values[n-1] );
- }
- return values[index];
- }
- /*
- ====================
- idCurve::TimeForIndex
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE float idCurve<type>::TimeForIndex( const int index ) const {
- int n = times.Num()-1;
- if ( index < 0 ) {
- return times[0] + index * ( times[1] - times[0] );
- } else if ( index > n ) {
- return times[n] + ( index - n ) * ( times[n] - times[n-1] );
- }
- return times[index];
- }
- /*
- ===============================================================================
- Bezier Curve template.
- The degree of the polynomial equals the number of knots minus one.
- ===============================================================================
- */
- template< class type >
- class idCurve_Bezier : public idCurve<type> {
- public:
- idCurve_Bezier();
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- void Basis( const int order, const float t, float *bvals ) const;
- void BasisFirstDerivative( const int order, const float t, float *bvals ) const;
- void BasisSecondDerivative( const int order, const float t, float *bvals ) const;
- };
- /*
- ====================
- idCurve_Bezier::idCurve_Bezier
- ====================
- */
- template< class type >
- ID_INLINE idCurve_Bezier<type>::idCurve_Bezier() {
- }
- /*
- ====================
- idCurve_Bezier::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_Bezier<type>::GetCurrentValue( const float time ) const {
- int i;
- float *bvals;
- type v;
- bvals = (float *) _alloca16( this->values.Num() * sizeof( float ) );
- Basis( this->values.Num(), time, bvals );
- v = bvals[0] * this->values[0];
- for ( i = 1; i < this->values.Num(); i++ ) {
- v += bvals[i] * this->values[i];
- }
- return v;
- }
- /*
- ====================
- idCurve_Bezier::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_Bezier<type>::GetCurrentFirstDerivative( const float time ) const {
- int i;
- float *bvals, d;
- type v;
- bvals = (float *) _alloca16( this->values.Num() * sizeof( float ) );
- BasisFirstDerivative( this->values.Num(), time, bvals );
- v = bvals[0] * this->values[0];
- for ( i = 1; i < this->values.Num(); i++ ) {
- v += bvals[i] * this->values[i];
- }
- d = ( this->times[this->times.Num()-1] - this->times[0] );
- return ( (float) (this->values.Num()-1) / d ) * v;
- }
- /*
- ====================
- idCurve_Bezier::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_Bezier<type>::GetCurrentSecondDerivative( const float time ) const {
- int i;
- float *bvals, d;
- type v;
- bvals = (float *) _alloca16( this->values.Num() * sizeof( float ) );
- BasisSecondDerivative( this->values.Num(), time, bvals );
- v = bvals[0] * this->values[0];
- for ( i = 1; i < this->values.Num(); i++ ) {
- v += bvals[i] * this->values[i];
- }
- d = ( this->times[this->times.Num()-1] - this->times[0] );
- return ( (float) (this->values.Num()-2) * (this->values.Num()-1) / ( d * d ) ) * v;
- }
- /*
- ====================
- idCurve_Bezier::Basis
- bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_Bezier<type>::Basis( const int order, const float t, float *bvals ) const {
- int i, j, d;
- float *c, c1, c2, s, o, ps, po;
- bvals[0] = 1.0f;
- d = order - 1;
- if ( d <= 0 ) {
- return;
- }
- c = (float *) _alloca16( (d+1) * sizeof( float ) );
- s = (float) ( t - this->times[0] ) / ( this->times[this->times.Num()-1] - this->times[0] );
- o = 1.0f - s;
- ps = s;
- po = o;
- for ( i = 1; i < d; i++ ) {
- c[i] = 1.0f;
- }
- for ( i = 1; i < d; i++ ) {
- c[i-1] = 0.0f;
- c1 = c[i];
- c[i] = 1.0f;
- for ( j = i+1; j <= d; j++ ) {
- c2 = c[j];
- c[j] = c1 + c[j-1];
- c1 = c2;
- }
- bvals[i] = c[d] * ps;
- ps *= s;
- }
- for ( i = d-1; i >= 0; i-- ) {
- bvals[i] *= po;
- po *= o;
- }
- bvals[d] = ps;
- }
- /*
- ====================
- idCurve_Bezier::BasisFirstDerivative
- first derivative of bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_Bezier<type>::BasisFirstDerivative( const int order, const float t, float *bvals ) const {
- int i;
- Basis( order-1, t, bvals+1 );
- bvals[0] = 0.0f;
- for ( i = 0; i < order-1; i++ ) {
- bvals[i] -= bvals[i+1];
- }
- }
- /*
- ====================
- idCurve_Bezier::BasisSecondDerivative
- second derivative of bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_Bezier<type>::BasisSecondDerivative( const int order, const float t, float *bvals ) const {
- int i;
- BasisFirstDerivative( order-1, t, bvals+1 );
- bvals[0] = 0.0f;
- for ( i = 0; i < order-1; i++ ) {
- bvals[i] -= bvals[i+1];
- }
- }
- /*
- ===============================================================================
- Quadratic Bezier Curve template.
- Should always have exactly three knots.
- ===============================================================================
- */
- template< class type >
- class idCurve_QuadraticBezier : public idCurve<type> {
- public:
- idCurve_QuadraticBezier();
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- void Basis( const float t, float *bvals ) const;
- void BasisFirstDerivative( const float t, float *bvals ) const;
- void BasisSecondDerivative( const float t, float *bvals ) const;
- };
- /*
- ====================
- idCurve_QuadraticBezier::idCurve_QuadraticBezier
- ====================
- */
- template< class type >
- ID_INLINE idCurve_QuadraticBezier<type>::idCurve_QuadraticBezier() {
- }
- /*
- ====================
- idCurve_QuadraticBezier::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_QuadraticBezier<type>::GetCurrentValue( const float time ) const {
- float bvals[3];
- assert( this->values.Num() == 3 );
- Basis( time, bvals );
- return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] );
- }
- /*
- ====================
- idCurve_QuadraticBezier::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_QuadraticBezier<type>::GetCurrentFirstDerivative( const float time ) const {
- float bvals[3], d;
- assert( this->values.Num() == 3 );
- BasisFirstDerivative( time, bvals );
- d = ( this->times[2] - this->times[0] );
- return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] ) / d;
- }
- /*
- ====================
- idCurve_QuadraticBezier::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_QuadraticBezier<type>::GetCurrentSecondDerivative( const float time ) const {
- float bvals[3], d;
- assert( this->values.Num() == 3 );
- BasisSecondDerivative( time, bvals );
- d = ( this->times[2] - this->times[0] );
- return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] ) / ( d * d );
- }
- /*
- ====================
- idCurve_QuadraticBezier::Basis
- quadratic bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_QuadraticBezier<type>::Basis( const float t, float *bvals ) const {
- float s1 = (float) ( t - this->times[0] ) / ( this->times[2] - this->times[0] );
- float s2 = s1 * s1;
- bvals[0] = s2 - 2.0f * s1 + 1.0f;
- bvals[1] = -2.0f * s2 + 2.0f * s1;
- bvals[2] = s2;
- }
- /*
- ====================
- idCurve_QuadraticBezier::BasisFirstDerivative
- first derivative of quadratic bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_QuadraticBezier<type>::BasisFirstDerivative( const float t, float *bvals ) const {
- float s1 = (float) ( t - this->times[0] ) / ( this->times[2] - this->times[0] );
- bvals[0] = 2.0f * s1 - 2.0f;
- bvals[1] = -4.0f * s1 + 2.0f;
- bvals[2] = 2.0f * s1;
- }
- /*
- ====================
- idCurve_QuadraticBezier::BasisSecondDerivative
- second derivative of quadratic bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_QuadraticBezier<type>::BasisSecondDerivative( const float t, float *bvals ) const {
- float s1 = (float) ( t - this->times[0] ) / ( this->times[2] - this->times[0] );
- bvals[0] = 2.0f;
- bvals[1] = -4.0f;
- bvals[2] = 2.0f;
- }
- /*
- ===============================================================================
- Cubic Bezier Curve template.
- Should always have exactly four knots.
- ===============================================================================
- */
- template< class type >
- class idCurve_CubicBezier : public idCurve<type> {
- public:
- idCurve_CubicBezier();
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- void Basis( const float t, float *bvals ) const;
- void BasisFirstDerivative( const float t, float *bvals ) const;
- void BasisSecondDerivative( const float t, float *bvals ) const;
- };
- /*
- ====================
- idCurve_CubicBezier::idCurve_CubicBezier
- ====================
- */
- template< class type >
- ID_INLINE idCurve_CubicBezier<type>::idCurve_CubicBezier() {
- }
- /*
- ====================
- idCurve_CubicBezier::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_CubicBezier<type>::GetCurrentValue( const float time ) const {
- float bvals[4];
- assert( this->values.Num() == 4 );
- Basis( time, bvals );
- return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] + bvals[3] * this->values[3] );
- }
- /*
- ====================
- idCurve_CubicBezier::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_CubicBezier<type>::GetCurrentFirstDerivative( const float time ) const {
- float bvals[4], d;
- assert( this->values.Num() == 4 );
- BasisFirstDerivative( time, bvals );
- d = ( this->times[3] - this->times[0] );
- return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] + bvals[3] * this->values[3] ) / d;
- }
- /*
- ====================
- idCurve_CubicBezier::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_CubicBezier<type>::GetCurrentSecondDerivative( const float time ) const {
- float bvals[4], d;
- assert( this->values.Num() == 4 );
- BasisSecondDerivative( time, bvals );
- d = ( this->times[3] - this->times[0] );
- return ( bvals[0] * this->values[0] + bvals[1] * this->values[1] + bvals[2] * this->values[2] + bvals[3] * this->values[3] ) / ( d * d );
- }
- /*
- ====================
- idCurve_CubicBezier::Basis
- cubic bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_CubicBezier<type>::Basis( const float t, float *bvals ) const {
- float s1 = (float) ( t - this->times[0] ) / ( this->times[3] - this->times[0] );
- float s2 = s1 * s1;
- float s3 = s2 * s1;
- bvals[0] = -s3 + 3.0f * s2 - 3.0f * s1 + 1.0f;
- bvals[1] = 3.0f * s3 - 6.0f * s2 + 3.0f * s1;
- bvals[2] = -3.0f * s3 + 3.0f * s2;
- bvals[3] = s3;
- }
- /*
- ====================
- idCurve_CubicBezier::BasisFirstDerivative
- first derivative of cubic bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_CubicBezier<type>::BasisFirstDerivative( const float t, float *bvals ) const {
- float s1 = (float) ( t - this->times[0] ) / ( this->times[3] - this->times[0] );
- float s2 = s1 * s1;
- bvals[0] = -3.0f * s2 + 6.0f * s1 - 3.0f;
- bvals[1] = 9.0f * s2 - 12.0f * s1 + 3.0f;
- bvals[2] = -9.0f * s2 + 6.0f * s1;
- bvals[3] = 3.0f * s2;
- }
- /*
- ====================
- idCurve_CubicBezier::BasisSecondDerivative
- second derivative of cubic bezier basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_CubicBezier<type>::BasisSecondDerivative( const float t, float *bvals ) const {
- float s1 = (float) ( t - this->times[0] ) / ( this->times[3] - this->times[0] );
- bvals[0] = -6.0f * s1 + 6.0f;
- bvals[1] = 18.0f * s1 - 12.0f;
- bvals[2] = -18.0f * s1 + 6.0f;
- bvals[3] = 6.0f * s1;
- }
- /*
- ===============================================================================
- Spline base template.
- ===============================================================================
- */
- template< class type >
- class idCurve_Spline : public idCurve<type> {
- public:
- enum boundary_t { BT_FREE, BT_CLAMPED, BT_CLOSED };
- idCurve_Spline();
- virtual bool IsDone( const float time ) const;
- virtual void SetBoundaryType( const boundary_t bt ) { boundaryType = bt; this->changed = true; }
- virtual boundary_t GetBoundaryType() const { return boundaryType; }
- virtual void SetCloseTime( const float t ) { closeTime = t; this->changed = true; }
- virtual float GetCloseTime() { return boundaryType == BT_CLOSED ? closeTime : 0.0f; }
- protected:
- boundary_t boundaryType;
- float closeTime;
- type ValueForIndex( const int index ) const;
- float TimeForIndex( const int index ) const;
- float ClampedTime( const float t ) const;
- };
- /*
- ====================
- idCurve_Spline::idCurve_Spline
- ====================
- */
- template< class type >
- ID_INLINE idCurve_Spline<type>::idCurve_Spline() {
- boundaryType = BT_FREE;
- closeTime = 0.0f;
- }
- /*
- ====================
- idCurve_Spline::ValueForIndex
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_Spline<type>::ValueForIndex( const int index ) const {
- int n = this->values.Num()-1;
- if ( index < 0 ) {
- if ( boundaryType == BT_CLOSED ) {
- return this->values[ this->values.Num() + index % this->values.Num() ];
- }
- else {
- return this->values[0] + index * ( this->values[1] - this->values[0] );
- }
- }
- else if ( index > n ) {
- if ( boundaryType == BT_CLOSED ) {
- return this->values[ index % this->values.Num() ];
- }
- else {
- return this->values[n] + ( index - n ) * ( this->values[n] - this->values[n-1] );
- }
- }
- return this->values[index];
- }
- /*
- ====================
- idCurve_Spline::TimeForIndex
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE float idCurve_Spline<type>::TimeForIndex( const int index ) const {
- int n = this->times.Num()-1;
- if ( index < 0 ) {
- if ( boundaryType == BT_CLOSED ) {
- return ( index / this->times.Num() ) * ( this->times[n] + closeTime ) - ( this->times[n] + closeTime - this->times[this->times.Num() + index % this->times.Num()] );
- }
- else {
- return this->times[0] + index * ( this->times[1] - this->times[0] );
- }
- }
- else if ( index > n ) {
- if ( boundaryType == BT_CLOSED ) {
- return ( index / this->times.Num() ) * ( this->times[n] + closeTime ) + this->times[index % this->times.Num()];
- }
- else {
- return this->times[n] + ( index - n ) * ( this->times[n] - this->times[n-1] );
- }
- }
- return this->times[index];
- }
- /*
- ====================
- idCurve_Spline::ClampedTime
- return the clamped time based on the boundary type
- ====================
- */
- template< class type >
- ID_INLINE float idCurve_Spline<type>::ClampedTime( const float t ) const {
- if ( boundaryType == BT_CLAMPED ) {
- if ( t < this->times[0] ) {
- return this->times[0];
- }
- else if ( t >= this->times[this->times.Num()-1] ) {
- return this->times[this->times.Num()-1];
- }
- }
- return t;
- }
- /*
- ====================
- idCurve_Spline::IsDone
- ====================
- */
- template< class type >
- ID_INLINE bool idCurve_Spline<type>::IsDone( const float time ) const {
- return ( boundaryType != BT_CLOSED && time >= this->times[ this->times.Num() - 1 ] );
- }
- /*
- ===============================================================================
- Cubic Interpolating Spline template.
- The curve goes through all the knots.
- ===============================================================================
- */
- template< class type >
- class idCurve_NaturalCubicSpline : public idCurve_Spline<type> {
- public:
- idCurve_NaturalCubicSpline();
- virtual void Clear() { idCurve_Spline<type>::Clear(); this->values.Clear(); b.Clear(); c.Clear(); d.Clear(); }
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- mutable idList<type>b;
- mutable idList<type>c;
- mutable idList<type>d;
- void Setup() const;
- void SetupFree() const;
- void SetupClamped() const;
- void SetupClosed() const;
- };
- /*
- ====================
- idCurve_NaturalCubicSpline::idCurve_NaturalCubicSpline
- ====================
- */
- template< class type >
- ID_INLINE idCurve_NaturalCubicSpline<type>::idCurve_NaturalCubicSpline() {
- }
- /*
- ====================
- idCurve_NaturalCubicSpline::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NaturalCubicSpline<type>::GetCurrentValue( const float time ) const {
- float clampedTime = this->ClampedTime( time );
- int i = this->IndexForTime( clampedTime );
- float s = time - this->TimeForIndex( i );
- Setup();
- return ( this->values[i] + s * ( b[i] + s * ( c[i] + s * d[i] ) ) );
- }
- /*
- ====================
- idCurve_NaturalCubicSpline::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NaturalCubicSpline<type>::GetCurrentFirstDerivative( const float time ) const {
- float clampedTime = this->ClampedTime( time );
- int i = this->IndexForTime( clampedTime );
- float s = time - this->TimeForIndex( i );
- Setup();
- return ( b[i] + s * ( 2.0f * c[i] + 3.0f * s * d[i] ) );
- }
- /*
- ====================
- idCurve_NaturalCubicSpline::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NaturalCubicSpline<type>::GetCurrentSecondDerivative( const float time ) const {
- float clampedTime = this->ClampedTime( time );
- int i = this->IndexForTime( clampedTime );
- float s = time - this->TimeForIndex( i );
- Setup();
- return ( 2.0f * c[i] + 6.0f * s * d[i] );
- }
- /*
- ====================
- idCurve_NaturalCubicSpline::Setup
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_NaturalCubicSpline<type>::Setup() const {
- if ( this->changed ) {
- switch( this->boundaryType ) {
- case idCurve_Spline<type>::BT_FREE: SetupFree(); break;
- case idCurve_Spline<type>::BT_CLAMPED: SetupClamped(); break;
- case idCurve_Spline<type>::BT_CLOSED: SetupClosed(); break;
- }
- this->changed = false;
- }
- }
- /*
- ====================
- idCurve_NaturalCubicSpline::SetupFree
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_NaturalCubicSpline<type>::SetupFree() const {
- int i;
- float inv;
- float *d0, *d1, *beta, *gamma;
- type *alpha, *delta;
- d0 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
- d1 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
- alpha = (type *) _alloca16( ( this->values.Num() - 1 ) * sizeof( type ) );
- beta = (float *) _alloca16( this->values.Num() * sizeof( float ) );
- gamma = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
- delta = (type *) _alloca16( this->values.Num() * sizeof( type ) );
- for ( i = 0; i < this->values.Num() - 1; i++ ) {
- d0[i] = this->times[i+1] - this->times[i];
- }
- for ( i = 1; i < this->values.Num() - 1; i++ ) {
- d1[i] = this->times[i+1] - this->times[i-1];
- }
- for ( i = 1; i < this->values.Num() - 1; i++ ) {
- type sum = 3.0f * ( d0[i-1] * this->values[i+1] - d1[i] * this->values[i] + d0[i] * this->values[i-1] );
- inv = 1.0f / ( d0[i-1] * d0[i] );
- alpha[i] = inv * sum;
- }
- beta[0] = 1.0f;
- gamma[0] = 0.0f;
- delta[0] = this->values[0] - this->values[0]; //-V501
- for ( i = 1; i < this->values.Num() - 1; i++ ) {
- beta[i] = 2.0f * d1[i] - d0[i-1] * gamma[i-1];
- inv = 1.0f / beta[i];
- gamma[i] = inv * d0[i];
- delta[i] = inv * ( alpha[i] - d0[i-1] * delta[i-1] );
- }
- beta[this->values.Num() - 1] = 1.0f;
- delta[this->values.Num() - 1] = this->values[0] - this->values[0]; //-V501
- b.AssureSize( this->values.Num() );
- c.AssureSize( this->values.Num() );
- d.AssureSize( this->values.Num() );
- c[this->values.Num() - 1] = this->values[0] - this->values[0]; //-V501
- for ( i = this->values.Num() - 2; i >= 0; i-- ) {
- c[i] = delta[i] - gamma[i] * c[i+1];
- inv = 1.0f / d0[i];
- b[i] = inv * ( this->values[i+1] - this->values[i] ) - ( 1.0f / 3.0f ) * d0[i] * ( c[i+1] + 2.0f * c[i] );
- d[i] = ( 1.0f / 3.0f ) * inv * ( c[i+1] - c[i] );
- }
- }
- /*
- ====================
- idCurve_NaturalCubicSpline::SetupClamped
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_NaturalCubicSpline<type>::SetupClamped() const {
- int i;
- float inv;
- float *d0, *d1, *beta, *gamma;
- type *alpha, *delta;
- d0 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
- d1 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
- alpha = (type *) _alloca16( ( this->values.Num() - 1 ) * sizeof( type ) );
- beta = (float *) _alloca16( this->values.Num() * sizeof( float ) );
- gamma = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
- delta = (type *) _alloca16( this->values.Num() * sizeof( type ) );
- for ( i = 0; i < this->values.Num() - 1; i++ ) {
- d0[i] = this->times[i+1] - this->times[i];
- }
- for ( i = 1; i < this->values.Num() - 1; i++ ) {
- d1[i] = this->times[i+1] - this->times[i-1];
- }
- inv = 1.0f / d0[0];
- alpha[0] = 3.0f * ( inv - 1.0f ) * ( this->values[1] - this->values[0] );
- inv = 1.0f / d0[this->values.Num() - 2];
- alpha[this->values.Num() - 1] = 3.0f * ( 1.0f - inv ) * ( this->values[this->values.Num() - 1] - this->values[this->values.Num() - 2] );
- for ( i = 1; i < this->values.Num() - 1; i++ ) {
- type sum = 3.0f * ( d0[i-1] * this->values[i+1] - d1[i] * this->values[i] + d0[i] * this->values[i-1] );
- inv = 1.0f / ( d0[i-1] * d0[i] );
- alpha[i] = inv * sum;
- }
- beta[0] = 2.0f * d0[0];
- gamma[0] = 0.5f;
- inv = 1.0f / beta[0];
- delta[0] = inv * alpha[0];
- for ( i = 1; i < this->values.Num() - 1; i++ ) {
- beta[i] = 2.0f * d1[i] - d0[i-1] * gamma[i-1];
- inv = 1.0f / beta[i];
- gamma[i] = inv * d0[i];
- delta[i] = inv * ( alpha[i] - d0[i-1] * delta[i-1] );
- }
- beta[this->values.Num() - 1] = d0[this->values.Num() - 2] * ( 2.0f - gamma[this->values.Num() - 2] );
- inv = 1.0f / beta[this->values.Num() - 1];
- delta[this->values.Num() - 1] = inv * ( alpha[this->values.Num() - 1] - d0[this->values.Num() - 2] * delta[this->values.Num() - 2] );
- b.AssureSize( this->values.Num() );
- c.AssureSize( this->values.Num() );
- d.AssureSize( this->values.Num() );
- c[this->values.Num() - 1] = delta[this->values.Num() - 1];
- for ( i = this->values.Num() - 2; i >= 0; i-- ) {
- c[i] = delta[i] - gamma[i] * c[i+1];
- inv = 1.0f / d0[i];
- b[i] = inv * ( this->values[i+1] - this->values[i] ) - ( 1.0f / 3.0f ) * d0[i]* ( c[i+1] + 2.0f * c[i] );
- d[i] = ( 1.0f / 3.0f ) * inv * ( c[i+1] - c[i] );
- }
- }
- /*
- ====================
- idCurve_NaturalCubicSpline::SetupClosed
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_NaturalCubicSpline<type>::SetupClosed() const {
- int i, j;
- float c0, c1;
- float *d0;
- idMatX mat;
- idVecX x;
- d0 = (float *) _alloca16( ( this->values.Num() - 1 ) * sizeof( float ) );
- x.SetData( this->values.Num(), VECX_ALLOCA( this->values.Num() ) );
- mat.SetData( this->values.Num(), this->values.Num(), MATX_ALLOCA( this->values.Num() * this->values.Num() ) );
- b.AssureSize( this->values.Num() );
- c.AssureSize( this->values.Num() );
- d.AssureSize( this->values.Num() );
- for ( i = 0; i < this->values.Num() - 1; i++ ) {
- d0[i] = this->times[i+1] - this->times[i];
- }
- // matrix of system
- mat[0][0] = 1.0f;
- mat[0][this->values.Num() - 1] = -1.0f;
- for ( i = 1; i <= this->values.Num() - 2; i++ ) {
- mat[i][i-1] = d0[i-1];
- mat[i][i ] = 2.0f * ( d0[i-1] + d0[i] );
- mat[i][i+1] = d0[i];
- }
- mat[this->values.Num() - 1][this->values.Num() - 2] = d0[this->values.Num() - 2];
- mat[this->values.Num() - 1][0] = 2.0f * ( d0[this->values.Num() - 2] + d0[0] );
- mat[this->values.Num() - 1][1] = d0[0];
- // right-hand side
- c[0].Zero();
- for ( i = 1; i <= this->values.Num() - 2; i++ ) {
- c0 = 1.0f / d0[i];
- c1 = 1.0f / d0[i-1];
- c[i] = 3.0f * ( c0 * ( this->values[i + 1] - this->values[i] ) - c1 * ( this->values[i] - this->values[i - 1] ) );
- }
- c0 = 1.0f / d0[0];
- c1 = 1.0f / d0[this->values.Num() - 2];
- c[this->values.Num() - 1] = 3.0f * ( c0 * ( this->values[1] - this->values[0] ) - c1 * ( this->values[0] - this->values[this->values.Num() - 2] ) );
- // solve system for each dimension
- mat.LU_Factor( NULL );
- for ( i = 0; i < this->values[0].GetDimension(); i++ ) {
- for ( j = 0; j < this->values.Num(); j++ ) {
- x[j] = c[j][i];
- }
- mat.LU_Solve( x, x, NULL );
- for ( j = 0; j < this->values.Num(); j++ ) {
- c[j][i] = x[j];
- }
- }
- for ( i = 0; i < this->values.Num() - 1; i++ ) {
- c0 = 1.0f / d0[i];
- b[i] = c0 * ( this->values[i + 1] - this->values[i] ) - ( 1.0f / 3.0f ) * ( c[i+1] + 2.0f * c[i] ) * d0[i];
- d[i] = ( 1.0f / 3.0f ) * c0 * ( c[i + 1] - c[i] );
- }
- }
- /*
- ===============================================================================
- Uniform Cubic Interpolating Spline template.
- The curve goes through all the knots.
- ===============================================================================
- */
- template< class type >
- class idCurve_CatmullRomSpline : public idCurve_Spline<type> {
- public:
- idCurve_CatmullRomSpline();
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- void Basis( const int index, const float t, float *bvals ) const;
- void BasisFirstDerivative( const int index, const float t, float *bvals ) const;
- void BasisSecondDerivative( const int index, const float t, float *bvals ) const;
- };
- /*
- ====================
- idCurve_CatmullRomSpline::idCurve_CatmullRomSpline
- ====================
- */
- template< class type >
- ID_INLINE idCurve_CatmullRomSpline<type>::idCurve_CatmullRomSpline() {
- }
- /*
- ====================
- idCurve_CatmullRomSpline::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_CatmullRomSpline<type>::GetCurrentValue( const float time ) const {
- int i, j, k;
- float bvals[4], clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- Basis( i-1, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < 4; j++ ) {
- k = i + j - 2;
- v += bvals[j] * this->ValueForIndex( k );
- }
- return v;
- }
- /*
- ====================
- idCurve_CatmullRomSpline::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_CatmullRomSpline<type>::GetCurrentFirstDerivative( const float time ) const {
- int i, j, k;
- float bvals[4], d, clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return ( this->values[0] - this->values[0] ); //-V501
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- BasisFirstDerivative( i-1, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < 4; j++ ) {
- k = i + j - 2;
- v += bvals[j] * this->ValueForIndex( k );
- }
- d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
- return v / d;
- }
- /*
- ====================
- idCurve_CatmullRomSpline::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_CatmullRomSpline<type>::GetCurrentSecondDerivative( const float time ) const {
- int i, j, k;
- float bvals[4], d, clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return ( this->values[0] - this->values[0] ); //-V501
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- BasisSecondDerivative( i-1, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < 4; j++ ) {
- k = i + j - 2;
- v += bvals[j] * this->ValueForIndex( k );
- }
- d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
- return v / ( d * d );
- }
- /*
- ====================
- idCurve_CatmullRomSpline::Basis
- spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_CatmullRomSpline<type>::Basis( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = ( ( -s + 2.0f ) * s - 1.0f ) * s * 0.5f; // -0.5f s * s * s + s * s - 0.5f * s
- bvals[1] = ( ( ( 3.0f * s - 5.0f ) * s ) * s + 2.0f ) * 0.5f; // 1.5f * s * s * s - 2.5f * s * s + 1.0f
- 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
- bvals[3] = ( ( s - 1.0f ) * s * s ) * 0.5f; // 0.5f * s * s * s - 0.5f * s * s
- }
- /*
- ====================
- idCurve_CatmullRomSpline::BasisFirstDerivative
- first derivative of spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_CatmullRomSpline<type>::BasisFirstDerivative( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = ( -1.5f * s + 2.0f ) * s - 0.5f; // -1.5f * s * s + 2.0f * s - 0.5f
- bvals[1] = ( 4.5f * s - 5.0f ) * s; // 4.5f * s * s - 5.0f * s
- bvals[2] = ( -4.5 * s + 4.0f ) * s + 0.5f; // -4.5 * s * s + 4.0f * s + 0.5f
- bvals[3] = 1.5f * s * s - s; // 1.5f * s * s - s
- }
- /*
- ====================
- idCurve_CatmullRomSpline::BasisSecondDerivative
- second derivative of spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_CatmullRomSpline<type>::BasisSecondDerivative( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = -3.0f * s + 2.0f;
- bvals[1] = 9.0f * s - 5.0f;
- bvals[2] = -9.0f * s + 4.0f;
- bvals[3] = 3.0f * s - 1.0f;
- }
- /*
- ===============================================================================
- Cubic Interpolating Spline template.
- The curve goes through all the knots.
- The curve becomes the Catmull-Rom spline if the tension,
- continuity and bias are all set to zero.
- ===============================================================================
- */
- template< class type >
- class idCurve_KochanekBartelsSpline : public idCurve_Spline<type> {
- public:
- idCurve_KochanekBartelsSpline();
- virtual int AddValue( const float time, const type &value );
- virtual int AddValue( const float time, const type &value, const float tension, const float continuity, const float bias );
- virtual void RemoveIndex( const int index ) { this->values.RemoveIndex(index); this->times.RemoveIndex(index); tension.RemoveIndex(index); continuity.RemoveIndex(index); bias.RemoveIndex(index); }
- virtual void Clear() { this->values.Clear(); this->times.Clear(); tension.Clear(); continuity.Clear(); bias.Clear(); this->currentIndex = -1; }
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- idList<float> tension;
- idList<float> continuity;
- idList<float> bias;
- void TangentsForIndex( const int index, type &t0, type &t1 ) const;
- void Basis( const int index, const float t, float *bvals ) const;
- void BasisFirstDerivative( const int index, const float t, float *bvals ) const;
- void BasisSecondDerivative( const int index, const float t, float *bvals ) const;
- };
- /*
- ====================
- idCurve_KochanekBartelsSpline::idCurve_KochanekBartelsSpline
- ====================
- */
- template< class type >
- ID_INLINE idCurve_KochanekBartelsSpline<type>::idCurve_KochanekBartelsSpline() {
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::AddValue
- add a timed/value pair to the spline
- returns the index to the inserted pair
- ====================
- */
- template< class type >
- ID_INLINE int idCurve_KochanekBartelsSpline<type>::AddValue( const float time, const type &value ) {
- int i;
- i = this->IndexForTime( time );
- this->times.Insert( time, i );
- this->values.Insert( value, i );
- tension.Insert( 0.0f, i );
- continuity.Insert( 0.0f, i );
- bias.Insert( 0.0f, i );
- return i;
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::AddValue
- add a timed/value pair to the spline
- returns the index to the inserted pair
- ====================
- */
- template< class type >
- ID_INLINE int idCurve_KochanekBartelsSpline<type>::AddValue( const float time, const type &value, const float tension, const float continuity, const float bias ) {
- int i;
- i = this->IndexForTime( time );
- this->times.Insert( time, i );
- this->values.Insert( value, i );
- this->tension.Insert( tension, i );
- this->continuity.Insert( continuity, i );
- this->bias.Insert( bias, i );
- return i;
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_KochanekBartelsSpline<type>::GetCurrentValue( const float time ) const {
- int i;
- float bvals[4], clampedTime;
- type v, t0, t1;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- TangentsForIndex( i - 1, t0, t1 );
- Basis( i - 1, clampedTime, bvals );
- v = bvals[0] * this->ValueForIndex( i - 1 );
- v += bvals[1] * this->ValueForIndex( i );
- v += bvals[2] * t0;
- v += bvals[3] * t1;
- return v;
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_KochanekBartelsSpline<type>::GetCurrentFirstDerivative( const float time ) const {
- int i;
- float bvals[4], d, clampedTime;
- type v, t0, t1;
- if ( this->times.Num() == 1 ) {
- return ( this->values[0] - this->values[0] ); //-V501
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- TangentsForIndex( i - 1, t0, t1 );
- BasisFirstDerivative( i - 1, clampedTime, bvals );
- v = bvals[0] * this->ValueForIndex( i - 1 );
- v += bvals[1] * this->ValueForIndex( i );
- v += bvals[2] * t0;
- v += bvals[3] * t1;
- d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
- return v / d;
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_KochanekBartelsSpline<type>::GetCurrentSecondDerivative( const float time ) const {
- int i;
- float bvals[4], d, clampedTime;
- type v, t0, t1;
- if ( this->times.Num() == 1 ) {
- return ( this->values[0] - this->values[0] ); //-V501
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- TangentsForIndex( i - 1, t0, t1 );
- BasisSecondDerivative( i - 1, clampedTime, bvals );
- v = bvals[0] * this->ValueForIndex( i - 1 );
- v += bvals[1] * this->ValueForIndex( i );
- v += bvals[2] * t0;
- v += bvals[3] * t1;
- d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
- return v / ( d * d );
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::TangentsForIndex
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_KochanekBartelsSpline<type>::TangentsForIndex( const int index, type &t0, type &t1 ) const {
- float dt, omt, omc, opc, omb, opb, adj, s0, s1;
- type delta;
- delta = this->ValueForIndex( index + 1 ) - this->ValueForIndex( index );
- dt = this->TimeForIndex( index + 1 ) - this->TimeForIndex( index );
- omt = 1.0f - tension[index];
- omc = 1.0f - continuity[index];
- opc = 1.0f + continuity[index];
- omb = 1.0f - bias[index];
- opb = 1.0f + bias[index];
- adj = 2.0f * dt / ( this->TimeForIndex( index + 1 ) - this->TimeForIndex( index - 1 ) );
- s0 = 0.5f * adj * omt * opc * opb;
- s1 = 0.5f * adj * omt * omc * omb;
- // outgoing tangent at first point
- t0 = s1 * delta + s0 * ( this->ValueForIndex( index ) - this->ValueForIndex( index - 1 ) );
- omt = 1.0f - tension[index + 1];
- omc = 1.0f - continuity[index + 1];
- opc = 1.0f + continuity[index + 1];
- omb = 1.0f - bias[index + 1];
- opb = 1.0f + bias[index + 1];
- adj = 2.0f * dt / ( this->TimeForIndex( index + 2 ) - this->TimeForIndex( index ) );
- s0 = 0.5f * adj * omt * omc * opb;
- s1 = 0.5f * adj * omt * opc * omb;
- // incoming tangent at second point
- t1 = s1 * ( this->ValueForIndex( index + 2 ) - this->ValueForIndex( index + 1 ) ) + s0 * delta;
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::Basis
- spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_KochanekBartelsSpline<type>::Basis( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = ( ( 2.0f * s - 3.0f ) * s ) * s + 1.0f; // 2.0f * s * s * s - 3.0f * s * s + 1.0f
- bvals[1] = ( ( -2.0f * s + 3.0f ) * s ) * s; // -2.0f * s * s * s + 3.0f * s * s
- bvals[2] = ( ( s - 2.0f ) * s ) * s + s; // s * s * s - 2.0f * s * s + s
- bvals[3] = ( ( s - 1.0f ) * s ) * s; // s * s * s - s * s
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::BasisFirstDerivative
- first derivative of spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_KochanekBartelsSpline<type>::BasisFirstDerivative( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = ( 6.0f * s - 6.0f ) * s; // 6.0f * s * s - 6.0f * s
- bvals[1] = ( -6.0f * s + 6.0f ) * s; // -6.0f * s * s + 6.0f * s
- bvals[2] = ( 3.0f * s - 4.0f ) * s + 1.0f; // 3.0f * s * s - 4.0f * s + 1.0f
- bvals[3] = ( 3.0f * s - 2.0f ) * s; // 3.0f * s * s - 2.0f * s
- }
- /*
- ====================
- idCurve_KochanekBartelsSpline::BasisSecondDerivative
- second derivative of spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_KochanekBartelsSpline<type>::BasisSecondDerivative( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = 12.0f * s - 6.0f;
- bvals[1] = -12.0f * s + 6.0f;
- bvals[2] = 6.0f * s - 4.0f;
- bvals[3] = 6.0f * s - 2.0f;
- }
- /*
- ===============================================================================
- B-Spline base template. Uses recursive definition and is slow.
- Use idCurve_UniformCubicBSpline or idCurve_NonUniformBSpline instead.
- ===============================================================================
- */
- template< class type >
- class idCurve_BSpline : public idCurve_Spline<type> {
- public:
- idCurve_BSpline();
- virtual int GetOrder() const { return order; }
- virtual void SetOrder( const int i ) { assert( i > 0 && i < 10 ); order = i; }
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- int order;
- float Basis( const int index, const int order, const float t ) const;
- float BasisFirstDerivative( const int index, const int order, const float t ) const;
- float BasisSecondDerivative( const int index, const int order, const float t ) const;
- };
- /*
- ====================
- idCurve_BSpline::idCurve_NaturalCubicSpline
- ====================
- */
- template< class type >
- ID_INLINE idCurve_BSpline<type>::idCurve_BSpline() {
- order = 4; // default to cubic
- }
- /*
- ====================
- idCurve_BSpline::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_BSpline<type>::GetCurrentValue( const float time ) const {
- int i, j, k;
- float clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < order; j++ ) {
- k = i + j - ( order >> 1 );
- v += Basis( k-2, order, clampedTime ) * this->ValueForIndex( k );
- }
- return v;
- }
- /*
- ====================
- idCurve_BSpline::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_BSpline<type>::GetCurrentFirstDerivative( const float time ) const {
- int i, j, k;
- float clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < order; j++ ) {
- k = i + j - ( order >> 1 );
- v += BasisFirstDerivative( k-2, order, clampedTime ) * this->ValueForIndex( k );
- }
- return v;
- }
- /*
- ====================
- idCurve_BSpline::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_BSpline<type>::GetCurrentSecondDerivative( const float time ) const {
- int i, j, k;
- float clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < order; j++ ) {
- k = i + j - ( order >> 1 );
- v += BasisSecondDerivative( k-2, order, clampedTime ) * this->ValueForIndex( k );
- }
- return v;
- }
- /*
- ====================
- idCurve_BSpline::Basis
- spline basis function
- ====================
- */
- template< class type >
- ID_INLINE float idCurve_BSpline<type>::Basis( const int index, const int order, const float t ) const {
- if ( order <= 1 ) {
- if ( this->TimeForIndex( index ) < t && t <= this->TimeForIndex( index + 1 ) ) {
- return 1.0f;
- } else {
- return 0.0f;
- }
- } else {
- float sum = 0.0f;
- float d1 = this->TimeForIndex( index+order-1 ) - this->TimeForIndex( index );
- if ( d1 != 0.0f ) {
- sum += (float) ( t - this->TimeForIndex( index ) ) * Basis( index, order-1, t ) / d1;
- }
- float d2 = this->TimeForIndex( index+order ) - this->TimeForIndex( index+1 );
- if ( d2 != 0.0f ) {
- sum += (float) ( this->TimeForIndex( index+order ) - t ) * Basis( index+1, order-1, t ) / d2;
- }
- return sum;
- }
- }
- /*
- ====================
- idCurve_BSpline::BasisFirstDerivative
- first derivative of spline basis function
- ====================
- */
- template< class type >
- ID_INLINE float idCurve_BSpline<type>::BasisFirstDerivative( const int index, const int order, const float t ) const {
- return ( Basis( index, order-1, t ) - Basis( index+1, order-1, t ) ) *
- (float) ( order - 1 ) / ( this->TimeForIndex( index + ( order - 1 ) - 2 ) - this->TimeForIndex( index - 2 ) );
- }
- /*
- ====================
- idCurve_BSpline::BasisSecondDerivative
- second derivative of spline basis function
- ====================
- */
- template< class type >
- ID_INLINE float idCurve_BSpline<type>::BasisSecondDerivative( const int index, const int order, const float t ) const {
- return ( BasisFirstDerivative( index, order-1, t ) - BasisFirstDerivative( index+1, order-1, t ) ) *
- (float) ( order - 1 ) / ( this->TimeForIndex( index + ( order - 1 ) - 2 ) - this->TimeForIndex( index - 2 ) );
- }
- /*
- ===============================================================================
- Uniform Non-Rational Cubic B-Spline template.
- ===============================================================================
- */
- template< class type >
- class idCurve_UniformCubicBSpline : public idCurve_BSpline<type> {
-
- public:
- idCurve_UniformCubicBSpline();
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- void Basis( const int index, const float t, float *bvals ) const;
- void BasisFirstDerivative( const int index, const float t, float *bvals ) const;
- void BasisSecondDerivative( const int index, const float t, float *bvals ) const;
- };
- /*
- ====================
- idCurve_UniformCubicBSpline::idCurve_UniformCubicBSpline
- ====================
- */
- template< class type >
- ID_INLINE idCurve_UniformCubicBSpline<type>::idCurve_UniformCubicBSpline() {
- this->order = 4; // always cubic
- }
- /*
- ====================
- idCurve_UniformCubicBSpline::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_UniformCubicBSpline<type>::GetCurrentValue( const float time ) const {
- int i, j, k;
- float bvals[4], clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- Basis( i-1, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < 4; j++ ) {
- k = i + j - 2;
- v += bvals[j] * this->ValueForIndex( k );
- }
- return v;
- }
- /*
- ====================
- idCurve_UniformCubicBSpline::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_UniformCubicBSpline<type>::GetCurrentFirstDerivative( const float time ) const {
- int i, j, k;
- float bvals[4], d, clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return ( this->values[0] - this->values[0] ); //-V501
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- BasisFirstDerivative( i-1, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < 4; j++ ) {
- k = i + j - 2;
- v += bvals[j] * this->ValueForIndex( k );
- }
- d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
- return v / d;
- }
- /*
- ====================
- idCurve_UniformCubicBSpline::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_UniformCubicBSpline<type>::GetCurrentSecondDerivative( const float time ) const {
- int i, j, k;
- float bvals[4], d, clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return ( this->values[0] - this->values[0] ); //-V501
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- BasisSecondDerivative( i-1, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < 4; j++ ) {
- k = i + j - 2;
- v += bvals[j] * this->ValueForIndex( k );
- }
- d = ( this->TimeForIndex( i ) - this->TimeForIndex( i-1 ) );
- return v / ( d * d );
- }
- /*
- ====================
- idCurve_UniformCubicBSpline::Basis
- spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_UniformCubicBSpline<type>::Basis( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = ( ( ( -s + 3.0f ) * s - 3.0f ) * s + 1.0f ) * ( 1.0f / 6.0f );
- bvals[1] = ( ( ( 3.0f * s - 6.0f ) * s ) * s + 4.0f ) * ( 1.0f / 6.0f );
- bvals[2] = ( ( ( -3.0f * s + 3.0f ) * s + 3.0f ) * s + 1.0f ) * ( 1.0f / 6.0f );
- bvals[3] = ( s * s * s ) * ( 1.0f / 6.0f );
- }
- /*
- ====================
- idCurve_UniformCubicBSpline::BasisFirstDerivative
- first derivative of spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_UniformCubicBSpline<type>::BasisFirstDerivative( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = -0.5f * s * s + s - 0.5f;
- bvals[1] = 1.5f * s * s - 2.0f * s;
- bvals[2] = -1.5f * s * s + s + 0.5f;
- bvals[3] = 0.5f * s * s;
- }
- /*
- ====================
- idCurve_UniformCubicBSpline::BasisSecondDerivative
- second derivative of spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_UniformCubicBSpline<type>::BasisSecondDerivative( const int index, const float t, float *bvals ) const {
- float s = (float) ( t - this->TimeForIndex( index ) ) / ( this->TimeForIndex( index+1 ) - this->TimeForIndex( index ) );
- bvals[0] = -s + 1.0f;
- bvals[1] = 3.0f * s - 2.0f;
- bvals[2] = -3.0f * s + 1.0f;
- bvals[3] = s;
- }
- /*
- ===============================================================================
- Non-Uniform Non-Rational B-Spline (NUBS) template.
- ===============================================================================
- */
- template< class type >
- class idCurve_NonUniformBSpline : public idCurve_BSpline<type> {
-
- public:
- idCurve_NonUniformBSpline();
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- void Basis( const int index, const int order, const float t, float *bvals ) const;
- void BasisFirstDerivative( const int index, const int order, const float t, float *bvals ) const;
- void BasisSecondDerivative( const int index, const int order, const float t, float *bvals ) const;
- };
- /*
- ====================
- idCurve_NonUniformBSpline::idCurve_NonUniformBSpline
- ====================
- */
- template< class type >
- ID_INLINE idCurve_NonUniformBSpline<type>::idCurve_NonUniformBSpline() {
- }
- /*
- ====================
- idCurve_NonUniformBSpline::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NonUniformBSpline<type>::GetCurrentValue( const float time ) const {
- int i, j, k;
- float clampedTime;
- type v;
- float *bvals = (float *) _alloca16( this->order * sizeof(float) );
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- Basis( i-1, this->order, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < this->order; j++ ) {
- k = i + j - ( this->order >> 1 );
- v += bvals[j] * this->ValueForIndex( k );
- }
- return v;
- }
- /*
- ====================
- idCurve_NonUniformBSpline::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NonUniformBSpline<type>::GetCurrentFirstDerivative( const float time ) const {
- int i, j, k;
- float clampedTime;
- type v;
- float *bvals = (float *) _alloca16( this->order * sizeof(float) );
- if ( this->times.Num() == 1 ) {
- return ( this->values[0] - this->values[0] ); //-V501
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- BasisFirstDerivative( i-1, this->order, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < this->order; j++ ) {
- k = i + j - ( this->order >> 1 );
- v += bvals[j] * this->ValueForIndex( k );
- }
- return v;
- }
- /*
- ====================
- idCurve_NonUniformBSpline::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NonUniformBSpline<type>::GetCurrentSecondDerivative( const float time ) const {
- int i, j, k;
- float clampedTime;
- type v;
- float *bvals = (float *) _alloca16( this->order * sizeof(float) );
- if ( this->times.Num() == 1 ) {
- return ( this->values[0] - this->values[0] ); //-V501
- }
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- BasisSecondDerivative( i-1, this->order, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- for ( j = 0; j < this->order; j++ ) {
- k = i + j - ( this->order >> 1 );
- v += bvals[j] * this->ValueForIndex( k );
- }
- return v;
- }
- /*
- ====================
- idCurve_NonUniformBSpline::Basis
- spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_NonUniformBSpline<type>::Basis( const int index, const int order, const float t, float *bvals ) const {
- int r, s, i;
- float omega;
- bvals[order-1] = 1.0f;
- for ( r = 2; r <= order; r++ ) {
- i = index - r + 1;
- bvals[order - r] = 0.0f;
- for ( s = order - r + 1; s < order; s++ ) {
- i++;
- omega = (float) ( t - this->TimeForIndex( i ) ) / ( this->TimeForIndex( i + r - 1 ) - this->TimeForIndex( i ) );
- bvals[s - 1] += ( 1.0f - omega ) * bvals[s];
- bvals[s] *= omega;
- }
- }
- }
- /*
- ====================
- idCurve_NonUniformBSpline::BasisFirstDerivative
- first derivative of spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_NonUniformBSpline<type>::BasisFirstDerivative( const int index, const int order, const float t, float *bvals ) const {
- int i;
- Basis( index, order-1, t, bvals+1 );
- bvals[0] = 0.0f;
- for ( i = 0; i < order-1; i++ ) {
- bvals[i] -= bvals[i+1];
- bvals[i] *= (float) ( order - 1) / ( this->TimeForIndex( index + i + (order-1) - 2 ) - this->TimeForIndex( index + i - 2 ) );
- }
- bvals[i] *= (float) ( order - 1) / ( this->TimeForIndex( index + i + (order-1) - 2 ) - this->TimeForIndex( index + i - 2 ) );
- }
- /*
- ====================
- idCurve_NonUniformBSpline::BasisSecondDerivative
- second derivative of spline basis functions
- ====================
- */
- template< class type >
- ID_INLINE void idCurve_NonUniformBSpline<type>::BasisSecondDerivative( const int index, const int order, const float t, float *bvals ) const {
- int i;
- BasisFirstDerivative( index, order-1, t, bvals+1 );
- bvals[0] = 0.0f;
- for ( i = 0; i < order-1; i++ ) {
- bvals[i] -= bvals[i+1];
- bvals[i] *= (float) ( order - 1) / ( this->TimeForIndex( index + i + (order-1) - 2 ) - this->TimeForIndex( index + i - 2 ) );
- }
- bvals[i] *= (float) ( order - 1) / ( this->TimeForIndex( index + i + (order-1) - 2 ) - this->TimeForIndex( index + i - 2 ) );
- }
- /*
- ===============================================================================
- Non-Uniform Rational B-Spline (NURBS) template.
- ===============================================================================
- */
- template< class type >
- class idCurve_NURBS : public idCurve_NonUniformBSpline<type> {
-
- public:
- idCurve_NURBS();
- virtual int AddValue( const float time, const type &value );
- virtual int AddValue( const float time, const type &value, const float weight );
- virtual void RemoveIndex( const int index ) { this->values.RemoveIndex(index); this->times.RemoveIndex(index); weights.RemoveIndex(index); }
- virtual void Clear() { this->values.Clear(); this->times.Clear(); weights.Clear(); this->currentIndex = -1; }
- virtual type GetCurrentValue( const float time ) const;
- virtual type GetCurrentFirstDerivative( const float time ) const;
- virtual type GetCurrentSecondDerivative( const float time ) const;
- protected:
- idList<float> weights;
- float WeightForIndex( const int index ) const;
- };
- /*
- ====================
- idCurve_NURBS::idCurve_NURBS
- ====================
- */
- template< class type >
- ID_INLINE idCurve_NURBS<type>::idCurve_NURBS() {
- }
- /*
- ====================
- idCurve_NURBS::AddValue
- add a timed/value pair to the spline
- returns the index to the inserted pair
- ====================
- */
- template< class type >
- ID_INLINE int idCurve_NURBS<type>::AddValue( const float time, const type &value ) {
- int i;
- i = this->IndexForTime( time );
- this->times.Insert( time, i );
- this->values.Insert( value, i );
- weights.Insert( 1.0f, i );
- return i;
- }
- /*
- ====================
- idCurve_NURBS::AddValue
- add a timed/value pair to the spline
- returns the index to the inserted pair
- ====================
- */
- template< class type >
- ID_INLINE int idCurve_NURBS<type>::AddValue( const float time, const type &value, const float weight ) {
- int i;
- i = this->IndexForTime( time );
- this->times.Insert( time, i );
- this->values.Insert( value, i );
- weights.Insert( weight, i );
- return i;
- }
- /*
- ====================
- idCurve_NURBS::GetCurrentValue
- get the value for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NURBS<type>::GetCurrentValue( const float time ) const {
- int i, j, k;
- float w, b, *bvals, clampedTime;
- type v;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- bvals = (float *) _alloca16( this->order * sizeof(float) );
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- this->Basis( i-1, this->order, clampedTime, bvals );
- v = this->values[0] - this->values[0]; //-V501
- w = 0.0f;
- for ( j = 0; j < this->order; j++ ) {
- k = i + j - ( this->order >> 1 );
- b = bvals[j] * WeightForIndex( k );
- w += b;
- v += b * this->ValueForIndex( k );
- }
- return v / w;
- }
- /*
- ====================
- idCurve_NURBS::GetCurrentFirstDerivative
- get the first derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NURBS<type>::GetCurrentFirstDerivative( const float time ) const {
- int i, j, k;
- float w, wb, wd1, b, d1, *bvals, *d1vals, clampedTime;
- type v, vb, vd1;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- bvals = (float *) _alloca16( this->order * sizeof(float) );
- d1vals = (float *) _alloca16( this->order * sizeof(float) );
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- this->Basis( i-1, this->order, clampedTime, bvals );
- this->BasisFirstDerivative( i-1, this->order, clampedTime, d1vals );
- vb = vd1 = this->values[0] - this->values[0]; //-V501
- wb = wd1 = 0.0f;
- for ( j = 0; j < this->order; j++ ) {
- k = i + j - ( this->order >> 1 );
- w = WeightForIndex( k );
- b = bvals[j] * w;
- d1 = d1vals[j] * w;
- wb += b;
- wd1 += d1;
- v = this->ValueForIndex( k );
- vb += b * v;
- vd1 += d1 * v;
- }
- return ( wb * vd1 - vb * wd1 ) / ( wb * wb );
- }
- /*
- ====================
- idCurve_NURBS::GetCurrentSecondDerivative
- get the second derivative for the given time
- ====================
- */
- template< class type >
- ID_INLINE type idCurve_NURBS<type>::GetCurrentSecondDerivative( const float time ) const {
- int i, j, k;
- float w, wb, wd1, wd2, b, d1, d2, *bvals, *d1vals, *d2vals, clampedTime;
- type v, vb, vd1, vd2;
- if ( this->times.Num() == 1 ) {
- return this->values[0];
- }
- bvals = (float *) _alloca16( this->order * sizeof(float) );
- d1vals = (float *) _alloca16( this->order * sizeof(float) );
- d2vals = (float *) _alloca16( this->order * sizeof(float) );
- clampedTime = this->ClampedTime( time );
- i = this->IndexForTime( clampedTime );
- this->Basis( i-1, this->order, clampedTime, bvals );
- this->BasisFirstDerivative( i-1, this->order, clampedTime, d1vals );
- this->BasisSecondDerivative( i-1, this->order, clampedTime, d2vals );
- vb = vd1 = vd2 = this->values[0] - this->values[0]; //-V501
- wb = wd1 = wd2 = 0.0f;
- for ( j = 0; j < this->order; j++ ) {
- k = i + j - ( this->order >> 1 );
- w = WeightForIndex( k );
- b = bvals[j] * w;
- d1 = d1vals[j] * w;
- d2 = d2vals[j] * w;
- wb += b;
- wd1 += d1;
- wd2 += d2;
- v = this->ValueForIndex( k );
- vb += b * v;
- vd1 += d1 * v;
- vd2 += d2 * v;
- }
- return ( ( wb * wb ) * ( wb * vd2 - vb * wd2 ) - ( wb * vd1 - vb * wd1 ) * 2.0f * wb * wd1 ) / ( wb * wb * wb * wb );
- }
- /*
- ====================
- idCurve_NURBS::WeightForIndex
- get the weight for the given index
- ====================
- */
- template< class type >
- ID_INLINE float idCurve_NURBS<type>::WeightForIndex( const int index ) const {
- int n = weights.Num()-1;
- if ( index < 0 ) {
- if ( this->boundaryType == idCurve_Spline<type>::BT_CLOSED ) {
- return weights[ weights.Num() + index % weights.Num() ];
- } else {
- return weights[0] + index * ( weights[1] - weights[0] );
- }
- } else if ( index > n ) {
- if ( this->boundaryType == idCurve_Spline<type>::BT_CLOSED ) {
- return weights[ index % weights.Num() ];
- } else {
- return weights[n] + ( index - n ) * ( weights[n] - weights[n-1] );
- }
- }
- return weights[index];
- }
- #endif /* !__MATH_CURVE_H__ */
|