os/graphics/m3g/m3gcore11/src/m3g_keyframesequence.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: KeyframeSequence implementation
    15 *
    16 */
    17 
    18 
    19 /*!
    20  * \internal
    21  * \file
    22  * \brief KeyframeSequence implementation
    23  */
    24 
    25 #ifndef M3G_CORE_INCLUDE
    26 #   error included by m3g_core.c; do not compile separately.
    27 #endif
    28 
    29 #include "m3g_keyframesequence.h"
    30 #include "m3g_memory.h"
    31 
    32 /*----------------------------------------------------------------------
    33  * Internal functions
    34  *--------------------------------------------------------------------*/
    35 
    36 /*!
    37  * \internal
    38  * \brief Destroys this KeyframeSequence object.
    39  *
    40  * \param obj KeyframeSequence object
    41  */
    42 static void m3gDestroyKeyframeSequence(Object *obj)
    43 {
    44     KeyframeSequence *sequence = (KeyframeSequence *) obj;
    45     M3G_VALIDATE_OBJECT(sequence);
    46     {
    47         Interface *m3g = M3G_INTERFACE(sequence);
    48         m3gFree(m3g, sequence->keyframes);
    49         m3gFree(m3g, sequence->keyframeTimes);
    50         m3gFree(m3g, sequence->inTangents);
    51         m3gFree(m3g, sequence->outTangents);
    52         m3gFree(m3g, sequence->a);
    53         m3gFree(m3g, sequence->b);
    54     }
    55     m3gDestroyObject(&sequence->object);
    56 }
    57 
    58 /*!
    59  * \internal
    60  * \brief Overloaded Object3D method.
    61  *
    62  * \param originalObj original KeyframeSequence object
    63  * \param cloneObj pointer to cloned KeyframeSequence object
    64  * \param pairs array for all object-duplicate pairs
    65  * \param numPairs number of pairs
    66  */
    67 static M3Gbool m3gKeyframeSequenceDuplicate(const Object *originalObj,
    68                                             Object **cloneObj,
    69                                             Object **pairs,
    70                                             M3Gint *numPairs)
    71 {
    72     KeyframeSequence *original = (KeyframeSequence *)originalObj;
    73     KeyframeSequence *clone =
    74         (KeyframeSequence *)m3gCreateKeyframeSequence(originalObj->interface,
    75                                                       original->numKeyframes,
    76                                                       original->numComponents,
    77                                                       original->interpolation);
    78     *cloneObj = (Object *)clone;
    79     if (*cloneObj == NULL) {
    80         return M3G_FALSE;
    81     }
    82 
    83     if(m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
    84         M3Gsizei n = original->numKeyframes * original->numComponents;
    85         
    86         m3gCopy(clone->keyframes, original->keyframes, n * sizeof(M3Gfloat));
    87         m3gCopy(clone->keyframeTimes, original->keyframeTimes, original->numKeyframes * sizeof(M3Gint));
    88         if (original->dirty == M3G_FALSE) {
    89             if (original->inTangents) {
    90                 m3gCopy(clone->inTangents, original->inTangents, n * sizeof(M3Gfloat));
    91                 m3gCopy(clone->outTangents, original->outTangents, n * sizeof(M3Gfloat));
    92             }
    93             if (original->a) {
    94                 m3gCopy(clone->a, original->a, original->numKeyframes * sizeof(Quat));
    95                 m3gCopy(clone->b, original->b, original->numKeyframes * sizeof(Quat));
    96             }
    97         }
    98         else {
    99             clone->dirty = M3G_TRUE;
   100         }
   101 
   102         clone->duration = original->duration;
   103         clone->closed = original->closed;
   104         clone->firstValid = original->firstValid;
   105         clone->lastValid = original->lastValid;
   106         return M3G_TRUE;
   107     }
   108     else {
   109         return M3G_FALSE;
   110     }
   111 }
   112 
   113 /*!
   114  * \internal
   115  * \brief Initializes a KeyframeSequence object. See specification
   116  * for default values.
   117  *
   118  * \param m3g                   M3G interface
   119  * \param sequence              KeyframeSequence object
   120  * \param numKeyframes          number of keyframes
   121  * \param numComponents         number of components
   122  * \param interpolation         interpolation type
   123  * \retval                      KeyframeSequence initialized KeyframeSequence object
   124  * \retval                      NULL initialization failed
   125  */
   126 static KeyframeSequence *m3gInitKeyframeSequence(Interface *m3g,
   127                                                  KeyframeSequence *sequence,
   128                                                  M3Gint numKeyframes,
   129                                                  M3Gint numComponents,
   130                                                  M3Gint interpolation)
   131 {
   132     m3gInitObject(&sequence->object, m3g, M3G_CLASS_KEYFRAME_SEQUENCE);
   133 
   134     /* Set keyframe parameters */
   135     
   136     sequence->numKeyframes = numKeyframes;
   137     sequence->numComponents = numComponents;
   138     sequence->interpolation = interpolation;
   139     sequence->lastValid = numKeyframes - 1; /* firstValid defaults to 0 */
   140 
   141     /* Allocate keyframe and tangent data */
   142     {    
   143         M3Gsizei n = numKeyframes * numComponents;
   144         
   145         sequence->keyframes = (M3Gfloat *)m3gAllocZ(m3g, n * sizeof(M3Gfloat));
   146         if (sequence->keyframes == NULL) {
   147             goto AllocFailed;
   148         }
   149         sequence->keyframeTimes = (M3Gint *)m3gAllocZ(m3g, numKeyframes * sizeof(M3Gint));
   150         if (sequence->keyframeTimes == NULL) {
   151             goto AllocFailed;
   152         }
   153         
   154         if (interpolation == M3G_SPLINE) {
   155             sequence->inTangents  = (M3Gfloat *)m3gAllocZ(m3g, n * sizeof(M3Gfloat));
   156             sequence->outTangents = (M3Gfloat *)m3gAllocZ(m3g, n * sizeof(M3Gfloat));
   157             if (sequence->inTangents == NULL || sequence->outTangents == NULL) {
   158                 goto AllocFailed;
   159             }
   160         }
   161         else if (interpolation == M3G_SQUAD) {
   162             sequence->a = (Quat *)m3gAlloc(m3g, numKeyframes * sizeof(Quat));
   163             sequence->b = (Quat *)m3gAlloc(m3g, numKeyframes * sizeof(Quat));
   164             if (sequence->a == NULL || sequence->b == NULL) {
   165                 goto AllocFailed;
   166             }
   167         }
   168 
   169         /* Success; just make a note that the data is not valid yet */
   170         
   171         sequence->dirty = M3G_TRUE;
   172         return sequence;
   173 
   174 AllocFailed:
   175         /* The destructor contains exactly the code we need for this,
   176          * so just call that */
   177         
   178         m3gDestroyKeyframeSequence((Object*) sequence);
   179         return NULL;
   180     }
   181 }
   182 
   183 /*!
   184  * \internal
   185  * \brief Checks the validity of keyframe timings
   186  *
   187  * \param sequence   KeyframeSequence object
   188  * \retval M3G_TRUE  sequence valid
   189  * \retval M3G_FALSE sequence invalid
   190  */
   191 static M3Gbool m3gValidSequence(const KeyframeSequence *sequence)
   192 {    
   193     const M3Gint last = sequence->lastValid;
   194     M3Gint current = sequence->firstValid;
   195     
   196     while (current != last) {
   197         M3Gint next = (current < sequence->numKeyframes-1) ? current + 1 : 0;
   198         if (sequence->keyframeTimes[next] < sequence->keyframeTimes[current]) {
   199             return M3G_FALSE;
   200         }
   201         current = next;
   202     }
   203     return (sequence->keyframeTimes[last] <= sequence->duration);
   204 }
   205 
   206 
   207 /*!
   208  * \internal
   209  * \brief Get number of components
   210  *
   211  * \param sequence   KeyframeSequence object
   212  * \return number of components
   213  */
   214 static M3Gint m3gGetNumComponents(const KeyframeSequence *sequence)
   215 {
   216     return sequence->numComponents;
   217 }
   218 
   219 /*!
   220  * \internal
   221  * \brief Get next keyframe index
   222  *
   223  * \param sequence  KeyframeSequence object
   224  * \param ind       current index
   225  * \return next index
   226  */
   227 static M3Gint m3gNextKeyframeIndex(const KeyframeSequence *sequence, M3Gint ind)
   228 {
   229     if (ind == sequence->lastValid) {
   230         return sequence->firstValid;
   231     }
   232     else if (ind == sequence->numKeyframes - 1) {
   233         return 0;
   234     }
   235     else {
   236         return (ind + 1);
   237     }
   238 }
   239     
   240 /*!
   241  * \internal
   242  * \brief Get previous keyframe index
   243  *
   244  * \param sequence  KeyframeSequence object
   245  * \param ind       current index
   246  * \return previous index
   247  */
   248 static M3Gint m3gPreviousKeyframeIndex(const KeyframeSequence *sequence, M3Gint ind)
   249 {
   250     if (ind == sequence->firstValid) {
   251         return sequence->lastValid;
   252     }
   253     else if (ind == 0) {
   254         return (sequence->numKeyframes - 1);
   255     }
   256     else {
   257         return (ind - 1);
   258     }
   259 }
   260 
   261 /*!
   262  * \internal
   263  * \brief Get keyframe at index
   264  *
   265  * \param seq       KeyframeSequence object
   266  * \param idx       keyframe index
   267  * \return keyframe value
   268  */
   269 static M3G_INLINE const M3Gfloat *m3gKeyframeAt(const KeyframeSequence *seq, M3Gint idx)
   270 {
   271     return seq->keyframes + idx * seq->numComponents;
   272 }
   273 
   274 /*!
   275  * \internal
   276  * \brief Get keyframe at index -1
   277  *
   278  * \param seq       KeyframeSequence object
   279  * \param idx       keyframe index
   280  * \return keyframe value
   281  */
   282 static M3G_INLINE const M3Gfloat *m3gKeyframeBefore(const KeyframeSequence *seq, M3Gint idx)
   283 {
   284     return m3gKeyframeAt(seq, m3gPreviousKeyframeIndex(seq, idx));
   285 }
   286 
   287 /*!
   288  * \internal
   289  * \brief Get keyframe at index + 1
   290  *
   291  * \param seq       KeyframeSequence object
   292  * \param idx       keyframe index
   293  * \return keyframe value
   294  */
   295 static M3G_INLINE const M3Gfloat *m3gKeyframeAfter(const KeyframeSequence *seq, M3Gint idx)
   296 {
   297     return m3gKeyframeAt(seq, m3gNextKeyframeIndex(seq, idx));
   298 }
   299 
   300 /*!
   301  * \internal
   302  * \brief Get tangent to index
   303  *
   304  * \param seq       KeyframeSequence object
   305  * \param idx       keyframe index
   306  * \return tangent value
   307  */
   308 static M3G_INLINE const M3Gfloat *m3gTangentTo(const KeyframeSequence *seq, M3Gint idx)
   309 {
   310     M3G_ASSERT(seq->inTangents != NULL);
   311     return seq->inTangents + idx * seq->numComponents;
   312 }
   313 
   314 /*!
   315  * \internal
   316  * \brief Get tangent from index
   317  *
   318  * \param seq       KeyframeSequence object
   319  * \param idx       keyframe index
   320  * \return tangent value
   321  */
   322 static M3G_INLINE const M3Gfloat *m3gTangentFrom(const KeyframeSequence *seq, M3Gint idx)
   323 {
   324     M3G_ASSERT(seq->outTangents != NULL);
   325     return seq->outTangents + idx * seq->numComponents;
   326 }
   327 
   328 /*!
   329  * \internal
   330  * \brief Get time delta
   331  *
   332  * \param sequence  KeyframeSequence object
   333  * \param ind       keyframe index
   334  * \return time delta
   335  */
   336 static M3Gint m3gTimeDelta(const KeyframeSequence *sequence, M3Gint ind)
   337 {
   338     if (ind == sequence->lastValid) {
   339         return
   340             (sequence->duration
   341              - sequence->keyframeTimes[sequence->lastValid])
   342             + sequence->keyframeTimes[sequence->firstValid];
   343     }
   344     return sequence->keyframeTimes[m3gNextKeyframeIndex(sequence, ind)]
   345         - sequence->keyframeTimes[ind];
   346 }
   347 
   348 /*!
   349  * \internal
   350  * \brief Get incoming tangent scale
   351  *
   352  * \param sequence  KeyframeSequence object
   353  * \param ind       keyframe index
   354  * \return tangent scale
   355  */
   356 static M3Gfloat m3gIncomingTangentScale(const KeyframeSequence *sequence,
   357                                         M3Gint ind)
   358 {
   359     if (!sequence->closed
   360         && (ind == sequence->firstValid || ind == sequence->lastValid)) {
   361         return 0;
   362     }
   363     else {
   364         M3Gint prevind = m3gPreviousKeyframeIndex(sequence, ind);
   365         return m3gDiv(m3gMul(2.0f, (M3Gfloat) m3gTimeDelta(sequence, prevind)),
   366                       (M3Gfloat)(m3gTimeDelta(sequence, ind)
   367                                  + m3gTimeDelta(sequence, prevind)));
   368     }
   369 }
   370 
   371 /*!
   372  * \internal
   373  * \brief Get outgoing tangent scale
   374  *
   375  * \param sequence  KeyframeSequence object
   376  * \param ind       keyframe index
   377  * \return tangent scale
   378  */
   379 static M3Gfloat m3gOutgoingTangentScale(const KeyframeSequence *sequence,
   380                                         M3Gint ind)
   381 {
   382     if (!sequence->closed
   383         && (ind == sequence->firstValid || ind == sequence->lastValid)) {
   384         return 0;
   385     }
   386     else {
   387         M3Gint prevind = m3gPreviousKeyframeIndex(sequence, ind);
   388         return m3gDiv(m3gMul(2.0f, (M3Gfloat) m3gTimeDelta(sequence, ind)),
   389                       (M3Gfloat)(m3gTimeDelta(sequence, ind)
   390                                  + m3gTimeDelta(sequence, prevind)));
   391     }
   392 }
   393 
   394 /*!
   395  * \internal
   396  * \brief Precalculate all tangents
   397  *
   398  * \param sequence  KeyframeSequence object
   399  */
   400 static void m3gPrecalculateTangents(KeyframeSequence *sequence)
   401 {
   402     M3Gint i, kf = sequence->firstValid;
   403     do {
   404         const M3Gfloat *prev = m3gKeyframeBefore(sequence, kf);
   405         const M3Gfloat *next = m3gKeyframeAfter(sequence, kf);
   406         const M3Gfloat sIn  = m3gIncomingTangentScale(sequence, kf);
   407         const M3Gfloat sOut = m3gOutgoingTangentScale(sequence, kf);
   408         M3Gfloat *in  = (M3Gfloat *) m3gTangentTo(sequence, kf);
   409         M3Gfloat *out = (M3Gfloat *) m3gTangentFrom(sequence, kf);        
   410         
   411         for (i = 0; i < sequence->numComponents; ++i) {
   412             in[i]  = m3gMul(m3gMul(0.5f, (m3gSub(next[i], prev[i]))), sIn);
   413             out[i] = m3gMul(m3gMul(0.5f, (m3gSub(next[i], prev[i]))), sOut);
   414         }
   415         
   416         kf = m3gNextKeyframeIndex(sequence, kf);
   417     } while (kf != sequence->firstValid);
   418 }
   419 
   420 /*!
   421  * \internal
   422  * \brief Precalculate A and B
   423  *
   424  * \param sequence  KeyframeSequence object
   425  */
   426 static void m3gPrecalculateAB(KeyframeSequence *sequence)
   427 {
   428     Quat start, end, prev, next;
   429     Vec3 tangent, cfd;
   430     M3Gfloat temp[4]; /* used for both quats and vectors */
   431     
   432     M3Gint kf = sequence->firstValid;
   433     do {
   434 
   435         m3gSetQuat(&prev, m3gKeyframeBefore(sequence, kf));
   436         m3gSetQuat(&start, m3gKeyframeAt(sequence, kf));
   437         m3gSetQuat(&end, m3gKeyframeAfter(sequence, kf));
   438         m3gSetQuat(&next, m3gKeyframeAfter(sequence, m3gNextKeyframeIndex(sequence, kf)));
   439 
   440         /* Compute the centered finite difference at this
   441            keyframe; note that this would be the tangent for basic
   442            Catmull-Rom interpolation. */
   443 
   444         m3gLogDiffQuat(&cfd, &start, &end);
   445         m3gLogDiffQuat((Vec3*)temp, &prev, &start);
   446         m3gAddVec3(&cfd, (Vec3*)temp);
   447         m3gScaleVec3(&cfd, 0.5f);
   448 
   449         /* Compute the outgoing tangent, scaled to compensate for
   450            keyframe timing, then compute the "A" intermediate
   451            quaternion. */
   452 
   453         tangent = cfd;
   454         m3gScaleVec3(&tangent, m3gOutgoingTangentScale(sequence, kf));
   455 
   456         m3gLogDiffQuat((Vec3*)temp, &start, &end);
   457         m3gSubVec3(&tangent, (Vec3*)temp);
   458         m3gScaleVec3(&tangent, 0.5f);
   459         m3gExpQuat((Quat*)temp, &tangent);
   460         sequence->a[kf] = start;
   461         m3gMulQuat(&(sequence->a[kf]), (Quat*)temp);
   462 
   463         /* Then repeat the same steps for the incoming tangent and
   464            the "B" intermediate quaternion. */
   465 
   466         tangent = cfd;
   467         m3gScaleVec3(&tangent, m3gIncomingTangentScale(sequence, kf));
   468 
   469         m3gLogDiffQuat((Vec3*)temp, &prev, &start);
   470         m3gSubVec3((Vec3*)temp, &tangent);
   471         m3gScaleVec3((Vec3*)temp, 0.5f);
   472         m3gExpQuat((Quat*)temp, (Vec3*)temp);
   473         sequence->b[kf] = start;
   474         m3gMulQuat(&(sequence->b[kf]), (Quat*)temp);
   475         
   476         kf = m3gNextKeyframeIndex(sequence, kf);
   477     } while (kf != sequence->firstValid);
   478 }
   479 
   480 /*!
   481  * \internal
   482  * \brief Update all tangents
   483  *
   484  * \param sequence  KeyframeSequence object
   485  */
   486 static void m3gUpdateTangents(KeyframeSequence *sequence)
   487 {
   488     if (sequence->interpolation == M3G_SPLINE) {
   489         m3gPrecalculateTangents(sequence);
   490     }
   491     else if (sequence->interpolation == M3G_SQUAD) {
   492         m3gPrecalculateAB(sequence);
   493     }
   494 }
   495 
   496 /*!
   497  * \internal
   498  * \brief Linear interpolate
   499  *
   500  * \param sequence      KeyframeSequence object
   501  * \param sample        input samples
   502  * \param s             speed
   503  * \param startIndex    start index
   504  * \param endIndex      end index
   505  */
   506 static M3G_INLINE void m3gLerpSample(const KeyframeSequence *sequence,
   507                                      M3Gfloat *sample,
   508                                      M3Gfloat s,
   509                                      M3Gint startIndex, M3Gint endIndex)
   510 {
   511     const M3Gfloat *start = m3gKeyframeAt(sequence, startIndex);
   512     const M3Gfloat *end   = m3gKeyframeAt(sequence, endIndex);
   513 
   514     m3gLerp(sequence->numComponents, sample, s, start, end);
   515 }
   516 
   517 /*!
   518  * \internal
   519  * \brief Spline interpolate
   520  *
   521  * \param sequence      KeyframeSequence object
   522  * \param sample        input samples
   523  * \param s             speed
   524  * \param startIndex    start index
   525  * \param endIndex      end index
   526  */
   527 static M3G_INLINE void m3gSplineSample(const KeyframeSequence *sequence,
   528                                        M3Gfloat *sample,
   529                                        M3Gfloat s,
   530                                        M3Gint startIndex, M3Gint endIndex)
   531 {
   532     const M3Gfloat *start, *end;
   533     const M3Gfloat *tStart, *tEnd;
   534     
   535     /* Get the required keyframe values and the (one-sided) tangents
   536      * at the ends of the segment. */
   537     
   538     start = m3gKeyframeAt(sequence, startIndex);
   539     end   = m3gKeyframeAt(sequence, endIndex);
   540 
   541     tStart = m3gTangentFrom(sequence, startIndex);
   542     tEnd = m3gTangentTo(sequence, endIndex);
   543 
   544     /* Interpolate the final value using a Hermite spline. */
   545 
   546     m3gHermite(sequence->numComponents, sample, s, start, end, tStart, tEnd);
   547 }
   548 
   549 /*!
   550  * \internal
   551  * \brief Spherical linear interpolate
   552  *
   553  * \param sequence      KeyframeSequence object
   554  * \param sample        input samples
   555  * \param s             speed
   556  * \param startIndex    start index
   557  * \param endIndex      end index
   558  */
   559 static M3G_INLINE void m3gSlerpSample(const KeyframeSequence *sequence,
   560                                       M3Gfloat *sample,
   561                                       M3Gfloat s,
   562                                       M3Gint startIndex, M3Gint endIndex)
   563 {
   564     if (sequence->numComponents != 4) {
   565         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_VALUE);
   566         return;
   567     }
   568     
   569     m3gSlerpQuat((Quat *) sample,
   570                  s,
   571                  (const Quat *) m3gKeyframeAt(sequence, startIndex),
   572                  (const Quat *) m3gKeyframeAt(sequence, endIndex));
   573 }
   574 
   575 /*!
   576  * \internal
   577  * \brief Spline interpolate quats
   578  *
   579  * \param sequence      KeyframeSequence object
   580  * \param sample        input samples
   581  * \param s             speed
   582  * \param startIndex    start index
   583  * \param endIndex      end index
   584  */
   585 static M3G_INLINE void m3gSquadSample(const KeyframeSequence *sequence,
   586                                       M3Gfloat *sample,
   587                                       M3Gfloat s,
   588                                       M3Gint startIndex, M3Gint endIndex)
   589 {
   590     if (sequence->numComponents != 4) {
   591         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_VALUE);
   592         return;
   593     }
   594 
   595     m3gSquadQuat((Quat *) sample,
   596                  s,
   597                  (const Quat *) m3gKeyframeAt(sequence, startIndex),
   598                  &(sequence->a[startIndex]),
   599                  &(sequence->b[endIndex]),
   600                  (const Quat *) m3gKeyframeAt(sequence, endIndex));
   601 }
   602 
   603 /*!
   604  * \internal
   605  * \brief Get sample
   606  *
   607  * \param sequence      KeyframeSequence object
   608  * \param time          time
   609  * \param sample        pointer to sample
   610  * \return              sample validity
   611  */
   612 static M3Gint m3gGetSample(KeyframeSequence *sequence,
   613                            M3Gint time,
   614                            M3Gfloat *sample)
   615 {
   616     M3Gint start, end, i;
   617     const M3Gfloat *value;
   618     M3Gfloat s;
   619     
   620     M3G_VALIDATE_OBJECT(sequence);
   621     
   622     if (sequence->dirty == M3G_TRUE) {
   623         if (!m3gValidSequence(sequence)) {
   624             m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_OPERATION);
   625             return 0;
   626         }
   627         m3gUpdateTangents(sequence);
   628         sequence->dirty = M3G_FALSE;
   629         sequence->probablyNext = sequence->firstValid;
   630     }
   631 
   632     /* First, map the time to the valid range of a repeating
   633        sequence, or handle the special end cases of an open-ended
   634        sequence. */
   635     
   636     if (sequence->closed) {
   637         if (time < 0)
   638             time = (time % sequence->duration) + sequence->duration;
   639         else
   640             time = time % sequence->duration;
   641         if (time < sequence->keyframeTimes[sequence->firstValid]) {
   642             time += sequence->duration;
   643         }
   644     }
   645     else {
   646         if (time < sequence->keyframeTimes[sequence->firstValid]) {
   647             value = m3gKeyframeAt(sequence, sequence->firstValid);
   648             for (i = 0; i < sequence->numComponents; i++)
   649                 sample[i] = value[i];
   650             return (sequence->keyframeTimes[sequence->firstValid] - time);
   651         }
   652         else if (time >= sequence->keyframeTimes[sequence->lastValid]) {
   653             value = m3gKeyframeAt(sequence, sequence->lastValid);
   654             for (i = 0; i < sequence->numComponents; i++)
   655                 sample[i] = value[i];
   656             /* \ define a meaningful constant */
   657             return 0x7FFFFFFF;
   658         }
   659     }
   660 
   661     /* Search for the starting keyframe of the segment to
   662        interpolate. Starting the search from the previously
   663        used keyframe, we are very likely to find the match
   664        sooner than if we'd start from the first keyframe. */
   665 
   666     start = sequence->probablyNext;
   667     if (sequence->keyframeTimes[start] > time)
   668         start = sequence->firstValid;
   669     while (start != sequence->lastValid &&
   670            sequence->keyframeTimes[m3gNextKeyframeIndex(sequence, start)] <= time) {
   671         start = m3gNextKeyframeIndex(sequence, start);
   672     }
   673     sequence->probablyNext = start;
   674     
   675     /* Calculate the interpolation factor if necessary; the quick
   676        exit also avoids a division by zero in the case that we
   677        have a quirky sequence with only multiple coincident
   678        keyframes. */
   679 
   680     if (time == sequence->keyframeTimes[start] || sequence->interpolation == M3G_STEP) {
   681         value = m3gKeyframeAt(sequence, start);
   682         for (i = 0; i < sequence->numComponents; i++)
   683             sample[i] = value[i];
   684         return (sequence->interpolation == M3G_STEP)
   685                ? (m3gTimeDelta(sequence, start) - (time - sequence->keyframeTimes[start]))
   686                : 1;
   687     }
   688     s = m3gDivif(time - sequence->keyframeTimes[start], m3gTimeDelta(sequence, start));
   689     
   690     /* Pick the correct interpolation function and pass the
   691        segment start and end keyframe indices. */
   692 
   693     end = m3gNextKeyframeIndex(sequence, start);
   694 
   695     switch (sequence->interpolation) {
   696     case M3G_LINEAR:
   697         m3gLerpSample(sequence, sample, s, start, end);
   698         break;
   699     case M3G_SLERP:
   700         m3gSlerpSample(sequence, sample, s, start, end);
   701         break;
   702     case M3G_SPLINE:
   703         m3gSplineSample(sequence, sample, s, start, end);
   704         break;
   705     case M3G_SQUAD:
   706         m3gSquadSample(sequence, sample, s, start, end);
   707         break;
   708     default:
   709         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_ENUM);
   710         return 0;
   711     }
   712 
   713     return 1;
   714 }
   715 
   716 /*----------------------------------------------------------------------
   717  * Virtual function table
   718  *--------------------------------------------------------------------*/
   719 
   720 static const ObjectVFTable m3gvf_KeyframeSequence = {
   721     m3gObjectApplyAnimation,
   722     m3gObjectIsCompatible,
   723     m3gObjectUpdateProperty,
   724     m3gObjectDoGetReferences,
   725     m3gObjectFindID,
   726     m3gKeyframeSequenceDuplicate,
   727     m3gDestroyKeyframeSequence
   728 };
   729 
   730 
   731 /*----------------------------------------------------------------------
   732  * Public API functions
   733  *--------------------------------------------------------------------*/
   734 
   735 /*!
   736  * \brief Creates a new KeyframeSequence with default values
   737  * 
   738  * \param hInterface            M3G interface
   739  * \param numKeyframes          number of keyframes
   740  * \param numComponents         number of components
   741  * \param interpolation         interpolation type
   742  * \retval KeyframeSequence new KeyframeSequence object
   743  * \retval NULL KeyframeSequence creating failed
   744  */
   745 /*@access M3GInterface@*/
   746 /*@access M3Gappearance@*/
   747 M3G_API M3GKeyframeSequence m3gCreateKeyframeSequence(M3GInterface hInterface,
   748                                                       M3Gint numKeyframes,
   749                                                       M3Gint numComponents,
   750                                                       M3Gint interpolation)
   751 {
   752     Interface *m3g = (Interface *) hInterface;
   753     M3G_VALIDATE_INTERFACE(m3g);
   754 
   755     if (numKeyframes < 1 || numComponents < 1
   756         || interpolation < M3G_LINEAR || interpolation > M3G_STEP
   757         || ((interpolation == M3G_SLERP || interpolation == M3G_SQUAD)
   758             && numComponents != 4)) {
   759         m3gRaiseError(m3g, M3G_INVALID_VALUE);
   760         return NULL;
   761     }
   762 
   763     {
   764         KeyframeSequence *sequence = m3gAllocZ(m3g, sizeof(KeyframeSequence));
   765 
   766         if (sequence != NULL) {
   767             if (m3gInitKeyframeSequence(m3g,
   768                                         sequence,
   769                                         numKeyframes, numComponents,
   770                                         interpolation) == NULL) {
   771                 m3gFree(m3g, sequence);
   772                 return NULL;
   773             }
   774         }
   775 
   776         return (M3GKeyframeSequence) sequence;
   777     }
   778 }
   779 
   780 /*!
   781  * \brief Assigns a time and value to a keyframe sequence entry
   782  *
   783  * \param handle    handle of the keyframe sequence object
   784  * \param ind       index of the entry to set
   785  * \param time      time to set in the entry
   786  * \param valueSize number of elements in the value; this must match
   787  *                  the number of elements given when constructing
   788  *                  the sequence
   789  * \param value     pointer to an array of \c valueSize floats
   790  */
   791 M3G_API void m3gSetKeyframe(M3GKeyframeSequence handle,
   792                             M3Gint ind,
   793                             M3Gint time,
   794                             M3Gint valueSize, const M3Gfloat *value)
   795 {
   796     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   797     M3G_VALIDATE_OBJECT(sequence);
   798 
   799     /* Check for invalid inputs */
   800     
   801     if (value == NULL) {
   802         m3gRaiseError(M3G_INTERFACE(sequence), M3G_NULL_POINTER);
   803         return;
   804     }
   805     if (valueSize < sequence->numComponents || time < 0) {
   806         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_VALUE);
   807         return;
   808     }
   809     if (ind < 0 || ind >= sequence->numKeyframes) {
   810         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_INDEX);
   811         return;
   812     }
   813 
   814     /* Assign  the  time  and  value. Quaternion  keyframes  are  also
   815      * normalized, as indicated in the specification. */    
   816     {
   817         M3Gfloat *kf = (M3Gfloat *) m3gKeyframeAt(sequence, ind);
   818         int c;
   819         
   820         sequence->keyframeTimes[ind] = time;
   821         
   822         for (c = 0; c < sequence->numComponents; ++c) {
   823             kf[c] = value[c];
   824         }
   825 
   826         if (sequence->interpolation == M3G_SLERP
   827             || sequence->interpolation == M3G_SQUAD) {
   828             m3gNormalizeQuat((Quat*) kf);
   829         }
   830     }
   831     
   832     sequence->dirty = M3G_TRUE;        
   833 }
   834 
   835 /*!
   836  * \brief Set valid range
   837  *
   838  * \param handle    handle of the keyframe sequence object
   839  * \param first     first valid keyframe
   840  * \param last      last valid keyframe
   841  */
   842 M3G_API void m3gSetValidRange(M3GKeyframeSequence handle,
   843                               M3Gint first, M3Gint last)
   844 {
   845     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   846     M3G_VALIDATE_OBJECT(sequence);
   847 
   848     if (first < 0 || first >= sequence->numKeyframes ||
   849         last < 0 || last >= sequence->numKeyframes) {
   850         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_INDEX);
   851         return;
   852     }
   853 
   854     sequence->firstValid = first;
   855     sequence->lastValid = last;
   856     sequence->dirty = M3G_TRUE;
   857 }
   858 
   859 /*!
   860  * \brief Set duration
   861  *
   862  * \param handle    handle of the keyframe sequence object
   863  * \param duration  duration
   864  */
   865 M3G_API void m3gSetDuration(M3GKeyframeSequence handle, M3Gint duration)
   866 {
   867     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   868     M3G_VALIDATE_OBJECT(sequence);
   869 
   870     /* Check for errors */
   871     if (duration <= 0) {
   872         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_VALUE);
   873         return;
   874     }
   875 
   876     sequence->duration = duration;
   877     sequence->dirty = M3G_TRUE;
   878 }
   879 
   880 /*!
   881  * \brief Get duration
   882  *
   883  * \param handle    handle of the keyframe sequence object
   884  * \return          duration
   885  */
   886 M3G_API M3Gint m3gGetDuration(M3GKeyframeSequence handle)
   887 {
   888     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   889     M3G_VALIDATE_OBJECT(sequence);
   890     return sequence->duration;
   891 }
   892 
   893 /*!
   894  * \brief Get component count
   895  *
   896  * \param handle    handle of the keyframe sequence object
   897  * \return          component count
   898  */
   899 M3G_API M3Gint m3gGetComponentCount(M3GKeyframeSequence handle)
   900 {
   901     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   902     M3G_VALIDATE_OBJECT(sequence);
   903     return sequence->numComponents;
   904 }
   905 
   906 /*!
   907  * \brief Get interpolation type
   908  *
   909  * \param handle    handle of the keyframe sequence object
   910  * \return          interpolation type
   911  */
   912 M3G_API M3Gint m3gGetInterpolationType(M3GKeyframeSequence handle)
   913 {
   914     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   915     M3G_VALIDATE_OBJECT(sequence);
   916     return sequence->interpolation;
   917 }
   918 
   919 /*!
   920  * \brief Get keyframe value
   921  *
   922  * \param handle     handle of the keyframe sequence object
   923  * \param frameIndex keyframe index
   924  * \param value      value array
   925  
   926  * \return           time value of the keyframe
   927  */
   928 M3G_API M3Gint m3gGetKeyframe  (M3GKeyframeSequence handle, M3Gint frameIndex, M3Gfloat *value)
   929 {
   930     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   931     M3G_VALIDATE_OBJECT(sequence);
   932 
   933     if (frameIndex < 0 || frameIndex >= sequence->numKeyframes) {
   934         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_INDEX);
   935         return 0;
   936     }
   937 
   938     if (value != NULL) {
   939         m3gCopy(    value,
   940                     sequence->keyframes + frameIndex * sequence->numComponents,
   941                     sequence->numComponents * sizeof(M3Gfloat));
   942     }
   943 
   944     return sequence->keyframeTimes[frameIndex];
   945 }
   946 
   947 /*!
   948  * \brief Get keyframe count
   949  *
   950  * \param handle    handle of the keyframe sequence object
   951  * \return          keyframe count
   952  */
   953 M3G_API M3Gint m3gGetKeyframeCount(M3GKeyframeSequence handle)
   954 {
   955     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   956     M3G_VALIDATE_OBJECT(sequence);
   957     return sequence->numKeyframes;
   958 }
   959 
   960 /*!
   961  * \brief Get valid range
   962  *
   963  * \param handle    handle of the keyframe sequence object
   964  * \param first     pointer to valid range start
   965  * \param last      pointer to valid range end
   966  */
   967 M3G_API void m3gGetValidRange(M3GKeyframeSequence handle, M3Gint *first, M3Gint *last)
   968 {
   969     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   970     M3G_VALIDATE_OBJECT(sequence);
   971     *first = sequence->firstValid;
   972     *last = sequence->lastValid;
   973 }
   974 
   975 /*!
   976  * \brief Set repeat mode
   977  *
   978  * \param handle    handle of the keyframe sequence object
   979  * \param mode      repeat mode
   980  */
   981 M3G_API void m3gSetRepeatMode(M3GKeyframeSequence handle, M3Genum mode)
   982 {
   983     KeyframeSequence *sequence = (KeyframeSequence *)handle;
   984     M3G_VALIDATE_OBJECT(sequence);
   985     if (mode != M3G_CONSTANT && mode != M3G_LOOP) {
   986         m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_ENUM);
   987         return;
   988     }
   989     sequence->closed = (mode == M3G_LOOP) ? M3G_TRUE : M3G_FALSE;
   990 }
   991 
   992 /*!
   993  * \brief Get repeat mode
   994  *
   995  * \param handle    handle of the keyframe sequence object
   996  * \return          repeat mode
   997  */
   998 M3G_API M3Genum m3gGetRepeatMode(M3GKeyframeSequence handle)
   999 {
  1000     KeyframeSequence *sequence = (KeyframeSequence *)handle;
  1001     M3G_VALIDATE_OBJECT(sequence);
  1002     return (sequence->closed ? M3G_LOOP : M3G_CONSTANT);
  1003 }
  1004