m3g/m3gcore11/src/m3g_keyframesequence.c
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     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