@@ -38,9 +38,10 @@ namespace Nif
3838 T mValue {};
3939 T mInTan {};
4040 T mOutTan {};
41- float mTension ;
42- float mContinuity ;
43- float mBias ;
41+ float mA ; // Coefficients based on the TCB parameters
42+ float mB ; // Only used by tangent calculations
43+ float mC ;
44+ float mD ;
4445 };
4546
4647 template <typename T, T (NIFStream::*getValue)()>
@@ -151,11 +152,20 @@ namespace Nif
151152
152153 static void readTCBKey (NIFStream& nif, TCBKey<T>& value)
153154 {
155+ float tension;
156+ float continuity;
157+ float bias;
158+
154159 nif.read (value.mTime );
155160 value.mValue = (nif.*getValue)();
156- nif.read (value.mTension );
157- nif.read (value.mContinuity );
158- nif.read (value.mBias );
161+ nif.read (tension);
162+ nif.read (continuity);
163+ nif.read (bias);
164+
165+ value.mA = (1 .f - tension) * (1 .f - continuity) * (1 .f + bias);
166+ value.mB = (1 .f - tension) * (1 .f + continuity) * (1 .f - bias);
167+ value.mC = (1 .f - tension) * (1 .f + continuity) * (1 .f + bias);
168+ value.mD = (1 .f - tension) * (1 .f - continuity) * (1 .f - bias);
159169 }
160170
161171 template <typename U>
@@ -164,23 +174,32 @@ namespace Nif
164174 if (keys.size () <= 1 )
165175 return ;
166176
167- for (std::size_t i = 0 ; i < keys.size (); ++i)
168177 {
169- TCBKey<U>& curr = keys[i];
170- const TCBKey<U>* prev = (i == 0 ) ? nullptr : &keys[i - 1 ];
171- const TCBKey<U>* next = (i == keys.size () - 1 ) ? nullptr : &keys[i + 1 ];
172- const float prevLen = prev != nullptr && next != nullptr ? curr.mTime - prev->mTime : 1 .f ;
173- const float nextLen = prev != nullptr && next != nullptr ? next->mTime - curr.mTime : 1 .f ;
174- if (prevLen + nextLen == 0 .f )
178+ TCBKey<U>& first = keys[0 ];
179+ const U delta = keys[1 ].mValue - first.mValue ;
180+ first.mInTan = delta * ((first.mA + first.mB ) * 0 .5f );
181+ first.mOutTan = delta * ((first.mC + first.mD ) * 0 .5f );
182+ }
183+
184+ for (std::size_t i = 1 ; i < keys.size () - 1 ; ++i)
185+ {
186+ const TCBKey<U>& prev = keys[i - 1 ];
187+ const TCBKey<U>& next = keys[i + 1 ];
188+ const float timeSpan = next.mTime - prev.mTime ;
189+ if (timeSpan == 0 .f )
175190 continue ;
176- const float x = (1 .f - curr.mTension ) * (1 .f - curr.mContinuity ) * (1 .f + curr.mBias );
177- const float y = (1 .f - curr.mTension ) * (1 .f + curr.mContinuity ) * (1 .f - curr.mBias );
178- const float z = (1 .f - curr.mTension ) * (1 .f + curr.mContinuity ) * (1 .f + curr.mBias );
179- const float w = (1 .f - curr.mTension ) * (1 .f - curr.mContinuity ) * (1 .f - curr.mBias );
180- const U prevDelta = prev != nullptr ? curr.mValue - prev->mValue : next->mValue - curr.mValue ;
181- const U nextDelta = next != nullptr ? next->mValue - curr.mValue : curr.mValue - prev->mValue ;
182- curr.mInTan = (prevDelta * x + nextDelta * y) * prevLen / (prevLen + nextLen);
183- curr.mOutTan = (prevDelta * z + nextDelta * w) * nextLen / (prevLen + nextLen);
191+ TCBKey<U>& key = keys[i];
192+ const U prevDelta = key.mValue - prev.mValue ;
193+ const U nextDelta = next.mValue - key.mValue ;
194+ key.mInTan = (prevDelta * key.mA + nextDelta * key.mB ) * ((key.mTime - prev.mTime ) / timeSpan);
195+ key.mOutTan = (prevDelta * key.mC + nextDelta * key.mD ) * ((next.mTime - key.mTime ) / timeSpan);
196+ }
197+
198+ {
199+ TCBKey<U>& last = keys.back ();
200+ const U delta = last.mValue - keys[keys.size () - 2 ].mValue ;
201+ last.mInTan = delta * ((last.mA + last.mB ) * 0 .5f );
202+ last.mOutTan = delta * ((last.mC + last.mD ) * 0 .5f );
184203 }
185204 }
186205
0 commit comments