common/animation/offline/animation_builder.cc
// Specialize for rotations in order to normalize quaternions.
// Consecutive opposite quaternions are also fixed up in order to avoid checking
// for the smallest path during the NLerp runtime algorithm.

Specialize for rotations in order to normalize quaternions.
Consecutive opposite quaternions are also fixed up in order to avoid checking
for the smallest path during the NLerp runtime algorithm.
Specialize for rotations in order to normalize quaternions . Consecutive opposite quaternions are also fixed up in order to avoid checking for the smallest path during the NLerp runtime algorithm .
void CopyToAnimation(std::vector<SortingRotationKey>* _src,
					egal::Range<RotationKey>* _dest)
				{
					const size_t src_count = _src->size();
					if (!src_count)
					{
						return;
					}
					size_t track = (std::numeric_limits<size_t>::max)();
					const math::Quaternion identity = math::Quaternion::identity();
					SortingRotationKey* src = &_src->front();
					for (size_t i = 0; i < src_count; ++i)
					{
						math::Quaternion normalized = NormalizeSafe(src[i].key.value, identity);
						if (track != src[i].track)
						{   
							if (normalized.w < 0.f)
							{    
								normalized = -normalized;  
							}
						}
						else
						{  
							const math::Float4 prev(src[i - 1].key.value.x, src[i - 1].key.value.y,
								src[i - 1].key.value.z, src[i - 1].key.value.w);
							const math::Float4 curr(normalized.x, normalized.y, normalized.z,
								normalized.w);
							if (Dot(prev, curr) < 0.f)
							{
								normalized = -normalized;  
							}
						}
						src[i].key.value = normalized;
						track = src[i].track;
					}
					std::sort((*_src).begin(), (*_src).end(),
						&SortingKeyLess<SortingRotationKey>);
					for (size_t i = 0; i < src_count; ++i)
					{
						const SortingRotationKey& skey = src[i];
						RotationKey& dkey = _dest->begin[i];
						dkey.time = skey.key.time;
						dkey.track = skey.track;
						CompressQuat(skey.key.value, &dkey);
					}
				}
void CopyToAnimation ( std :: vector < SortingRotationKey > * _src , egal :: Range < RotationKey > * _dest ) { const size_t src_count = _src -> size ( ) ; if ( ! src_count ) { return ; } size_t track = ( std :: numeric_limits < size_t > :: max ) ( ) ; const math :: Quaternion identity = math :: Quaternion :: identity ( ) ; SortingRotationKey * src = & _src -> front ( ) ; for ( size_t i = 0 ; i < src_count ; ++ i ) { math :: Quaternion normalized = NormalizeSafe ( src [ i ] . key . value , identity ) ; if ( track != src [ i ] . track ) { if ( normalized . w < 0.f ) { normalized = - normalized ; } } else { const math :: Float4 prev ( src [ i - 1 ] . key . value . x , src [ i - 1 ] . key . value . y , src [ i - 1 ] . key . value . z , src [ i - 1 ] . key . value . w ) ; const math :: Float4 curr ( normalized . x , normalized . y , normalized . z , normalized . w ) ; if ( Dot ( prev , curr ) < 0.f ) { normalized = - normalized ; } } src [ i ] . key . value = normalized ; track = src [ i ] . track ; } std :: sort ( ( * _src ) . begin ( ) , ( * _src ) . end ( ) , & SortingKeyLess < SortingRotationKey > ) ; for ( size_t i = 0 ; i < src_count ; ++ i ) { const SortingRotationKey & skey = src [ i ] ; RotationKey & dkey = _dest -> begin [ i ] ; dkey . time = skey . key . time ; dkey . track = skey . track ; CompressQuat ( skey . key . value , & dkey ) ; } }
Specialize for rotations in order to normalize quaternions.
Specialize for rotations in order to normalize quaternions .
// Normalize quaternions.
 // Also fixes-up successive opposite quaternions that would fail to take the
 // shortest path during the normalized-lerp.
 // Note that keys are still sorted per-track at that point, which allows this
 // algorithm to process all consecutive keys.
 // First key of the track.
 // .w eq to a dot with identity quaternion.
 // Q an -Q are the same rotation.
 // Still on the same track: so fixes-up quaternion.
 // Q an -Q are the same rotation.
 // Stores fixed-up quaternion.
 // Sort.
 // Fills rotation keys output.
 // Compress quaternion to destination container.
