os/graphics/m3g/m3gcore11/src/m3g_animationtrack.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: AnimationTrack implementation
    15 *
    16 */
    17 
    18 
    19 /*!
    20  * \internal
    21  * \file
    22  * \brief AnimationTrack 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_animationtrack.h"
    30 #include "m3g_keyframesequence.h"
    31 #include "m3g_memory.h"
    32 
    33 
    34 /*----------------------------------------------------------------------
    35  * Internal functions
    36  *--------------------------------------------------------------------*/
    37 
    38 /*!
    39  * \internal
    40  * \brief Destroys this AnimationTrack object.
    41  *
    42  * \param obj AnimationTrack object
    43  */
    44 static void m3gDestroyAnimationTrack(Object *obj)
    45 {
    46     AnimationTrack *animTrack = (AnimationTrack *) obj;
    47     M3G_VALIDATE_OBJECT(animTrack);
    48     
    49     M3G_ASSIGN_REF(animTrack->sequence,   NULL);
    50     M3G_ASSIGN_REF(animTrack->controller, NULL);
    51     
    52     m3gDestroyObject(&animTrack->object);
    53 }
    54 
    55 /*!
    56  * \internal
    57  * \brief Calculates animation track contribution.
    58  *
    59  * \param track AnimationTrack object
    60  * \param time current world time
    61  * \param accumSamples accumulated samples
    62  * \param sampleInfo sample information
    63  */
    64 static void m3gGetContribution(const AnimationTrack *track, M3Gint time,
    65                                M3Gfloat *accumSamples, SampleInfo *sampleInfo)
    66 {
    67     if (track->controller == NULL || !m3gIsActive(track->controller, time)) {
    68         sampleInfo->weight = 0;
    69         sampleInfo->validity = (track->controller ?
    70                                 m3gTimeToActivation(track->controller, time) :
    71                                 0x7FFFFFFF);
    72         if (sampleInfo->validity < 1)
    73             sampleInfo->validity = 1;
    74         return;
    75     }
    76     {
    77         M3Gfloat stackSampleVector[4];
    78         Interface *m3g = M3G_INTERFACE(track);
    79         M3Gint i, sampleTime, sampleValidity;
    80         M3Gfloat weight;
    81         M3Gint sampleLength = m3gGetNumComponents(track->sequence);
    82         M3Gfloat *sample;
    83 
    84         /* Before sampling, make sure that this track has some effect
    85          * on the end result */
    86         
    87         weight = m3gGetWeight(track->controller);
    88         sampleInfo->weight = weight;
    89         
    90         if (weight <= 0.0f) {
    91             sampleInfo->validity = 0x7FFFFFFF;
    92             return;
    93         }
    94             
    95         /* We use the stack-allocated sample vector by default, but
    96          * the MORPH_WEIGHTS target may have more than 4 components,
    97          * in which case we resort to the global temp vector. This
    98          * means that the temp vector can not be used in the keyframe
    99          * sampling code, but it doesn't seem likely that it would be
   100          * needed there. */
   101         
   102         if (sampleLength > 4) {
   103             sample = (M3Gfloat*) m3gAllocTemp(m3g, (M3Gsize) sampleLength * sizeof(M3Gfloat));
   104             if (!sample) {
   105                 sampleInfo->validity = 0;
   106                 return; /* automatic out-of-memory error */
   107             }
   108         }
   109         else {
   110             sample = stackSampleVector;
   111         }
   112         
   113         sampleTime = m3gRoundToInt(m3gGetPosition(track->controller, time));
   114         sampleValidity = m3gGetSample(track->sequence, sampleTime, sample);
   115         sampleInfo->validity = sampleValidity;
   116 
   117         /* Only bother if there was no error in GetSample... */
   118             
   119         if (sampleValidity > 0) {
   120 
   121             /* Resolve the validity time of the sample */
   122                 
   123             sampleValidity = m3gTimeToDeactivation(track->controller, time);
   124             if (sampleValidity < sampleInfo->validity) {
   125                 sampleInfo->validity = sampleValidity;
   126             }
   127                 
   128             /* Add the weighted sample to the accumulated value
   129              * and return */
   130                 
   131             for (i = 0; i < sampleLength; ++i) {
   132                 accumSamples[i] = m3gAdd(accumSamples[i],
   133                                          m3gMul(sample[i], weight));
   134             }
   135         }
   136         if (sample != stackSampleVector) {
   137             m3gFreeTemp(m3g);
   138         }
   139     }
   140 }
   141 
   142 /*!
   143  * \internal
   144  * \brief Checks animation property size.
   145  *
   146  * \param m3g M3G interface
   147  * \param property animation property
   148  * \param numComponents number of components
   149  * \retval M3G_TRUE valid size for property
   150  * \retval M3G_FALSE invalid size for property
   151  */
   152 static M3Gbool m3gIsValidSize(Interface *m3g, M3Gint property, M3Gint numComponents)
   153 {
   154     switch (property) {
   155     case M3G_ANIM_ALPHA:
   156     case M3G_ANIM_DENSITY:
   157     case M3G_ANIM_FAR_DISTANCE:
   158     case M3G_ANIM_FIELD_OF_VIEW:
   159     case M3G_ANIM_INTENSITY:
   160     case M3G_ANIM_NEAR_DISTANCE:
   161     case M3G_ANIM_PICKABILITY:
   162     case M3G_ANIM_SHININESS:
   163     case M3G_ANIM_SPOT_ANGLE:
   164     case M3G_ANIM_SPOT_EXPONENT:
   165     case M3G_ANIM_VISIBILITY:
   166         return (numComponents == 1);
   167     case M3G_ANIM_CROP:
   168         return (numComponents == 2 || numComponents == 4);
   169     case M3G_ANIM_COLOR:
   170     case M3G_ANIM_AMBIENT_COLOR:
   171     case M3G_ANIM_DIFFUSE_COLOR:
   172     case M3G_ANIM_EMISSIVE_COLOR:
   173     case M3G_ANIM_SPECULAR_COLOR:
   174         return (numComponents == 3);
   175     case M3G_ANIM_TRANSLATION:
   176         return (numComponents == 3);
   177     case M3G_ANIM_ORIENTATION:
   178         return (numComponents == 4);
   179     case M3G_ANIM_SCALE:
   180         return (numComponents == 1 || numComponents == 3);
   181     case M3G_ANIM_MORPH_WEIGHTS:
   182         return (numComponents > 0);
   183     default:
   184         m3gRaiseError(m3g, M3G_INVALID_ENUM);
   185     }
   186     return M3G_FALSE;
   187 }
   188 
   189 /*!
   190  * \internal
   191  * \brief Overloaded Object3D method.
   192  *
   193  * \param self AnimationTrack object
   194  * \param references array of reference objects
   195  * \return number of references
   196  */
   197 static M3Gint m3gAnimationTrackDoGetReferences(Object *self, Object **references)
   198 {
   199     AnimationTrack *track = (AnimationTrack *) self;
   200     M3Gint num = m3gObjectDoGetReferences(self, references);
   201     if (track->sequence != NULL) {
   202         if (references != NULL)
   203             references[num] = (Object *)track->sequence;
   204         num++;
   205     }
   206     if (track->controller != NULL) {
   207         if (references != NULL)
   208             references[num] = (Object *)track->controller;
   209         num++;
   210     }
   211     return num;
   212 }
   213 
   214 /*!
   215  * \internal
   216  * \brief Overloaded Object3D method
   217  */
   218 static Object *m3gAnimationTrackFindID(Object *self, M3Gint userID)
   219 {
   220     AnimationTrack *track = (AnimationTrack *) self;
   221     Object *found = m3gObjectFindID(self, userID);
   222     
   223     if (!found && track->sequence != NULL) {
   224         found = m3gFindID((Object*) track->sequence, userID);
   225     }
   226     if (!found && track->controller != NULL) {
   227         found = m3gFindID((Object*) track->controller, userID);
   228     }
   229     return found;
   230 }
   231 
   232 /*!
   233  * \internal
   234  * \brief Overloaded Object3D method.
   235  *
   236  * \param originalObj original AnimationTrack object
   237  * \param cloneObj pointer to cloned AnimationTrack object
   238  * \param pairs array for all object-duplicate pairs
   239  * \param numPairs number of pairs
   240  */
   241 static M3Gbool m3gAnimationTrackDuplicate(const Object *originalObj,
   242                                           Object **cloneObj,
   243                                           Object **pairs,
   244                                           M3Gint *numPairs)
   245 {
   246     AnimationTrack *original = (AnimationTrack *)originalObj;
   247     AnimationTrack *clone =
   248         (AnimationTrack *)m3gCreateAnimationTrack(originalObj->interface,
   249                                                   original->sequence,
   250                                                   original->property);
   251     *cloneObj = (Object *)clone;
   252     if (*cloneObj == NULL) {
   253         return M3G_FALSE;
   254     }
   255 
   256     if(m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
   257         M3G_ASSIGN_REF(clone->controller, original->controller);
   258         return M3G_TRUE;
   259     }
   260     else {
   261         return M3G_FALSE;
   262     }
   263 }
   264 
   265 /*----------------------------------------------------------------------
   266  * Virtual function table
   267  *--------------------------------------------------------------------*/
   268 
   269 static const ObjectVFTable m3gvf_AnimationTrack = {
   270     m3gObjectApplyAnimation,
   271     m3gObjectIsCompatible,
   272     m3gObjectUpdateProperty,
   273     m3gAnimationTrackDoGetReferences,
   274     m3gAnimationTrackFindID,
   275     m3gAnimationTrackDuplicate,
   276     m3gDestroyAnimationTrack
   277 };
   278 
   279 
   280 /*----------------------------------------------------------------------
   281  * Public API functions
   282  *--------------------------------------------------------------------*/
   283 
   284 /*!
   285  * \brief Creates a new AnimationTrack with default values
   286  *
   287  * \param hInterface            M3G interface
   288  * \param hSequence             KeyframeSequence object
   289  * \param property              target animation property
   290  * \retval AnimationTrack new AnimationTrack object
   291  * \retval NULL AnimationTrack creating failed
   292  */
   293 M3G_API M3GAnimationTrack m3gCreateAnimationTrack(M3GInterface hInterface,
   294                                                   M3GKeyframeSequence hSequence,
   295                                                   M3Gint property)
   296 {
   297     KeyframeSequence *sequence = (KeyframeSequence *)hSequence;
   298     Interface *m3g = (Interface *) hInterface;
   299     M3G_VALIDATE_INTERFACE(m3g);
   300 
   301     /* Check for invalid arguments */
   302     
   303     if (sequence == NULL) {
   304         m3gRaiseError(m3g, M3G_NULL_POINTER);
   305         return NULL;
   306     }
   307     if (property < M3G_ANIM_ALPHA || property > M3G_ANIM_VISIBILITY) {
   308         m3gRaiseError(m3g, M3G_INVALID_ENUM);
   309         return NULL;
   310     }
   311     if (!m3gIsValidSize(m3g, property, m3gGetNumComponents(sequence))) {
   312         m3gRaiseError(m3g, M3G_INVALID_VALUE);
   313         return NULL;
   314     }
   315 
   316     /* Allocate and initialize the object */
   317     
   318     {
   319         AnimationTrack *track = m3gAllocZ(m3g, sizeof(AnimationTrack));
   320 
   321         if (track != NULL) {
   322             M3G_ASSIGN_REF(track->sequence, sequence);
   323             track->property = property;
   324             m3gInitObject(&track->object, m3g, M3G_CLASS_ANIMATION_TRACK);
   325         }
   326         
   327         return track;
   328     }
   329 }
   330 
   331 /*!
   332  * \brief Get animation controller.
   333  *
   334  * \param hTrack                AnimationTrack object
   335  * \retval                      AnimationController object
   336  */
   337 M3G_API M3GAnimationController m3gGetController(M3GAnimationTrack hTrack)
   338 {
   339     AnimationTrack *track = (AnimationTrack *) hTrack;
   340     M3G_VALIDATE_OBJECT(track);
   341 
   342     return track->controller;
   343 }
   344 
   345 /*!
   346  * \brief Get key frame sequence.
   347  *
   348  * \param hTrack                AnimationTrack object
   349  * \retval                      KeyframeSequence object
   350  */
   351 M3G_API M3GKeyframeSequence m3gGetSequence(M3GAnimationTrack hTrack)
   352 {
   353     AnimationTrack *track = (AnimationTrack *) hTrack;
   354     M3G_VALIDATE_OBJECT(track);
   355 
   356     return track->sequence;
   357 }
   358 
   359 /*!
   360  * \brief Get animation target property.
   361  *
   362  * \param hTrack                AnimationTrack object
   363  * \retval                      target property
   364  */
   365 M3G_API M3Gint m3gGetTargetProperty(M3GAnimationTrack hTrack)
   366 {
   367     AnimationTrack *track = (AnimationTrack *) hTrack;
   368     M3G_VALIDATE_OBJECT(track);
   369 
   370     return track->property;
   371 }
   372 
   373 /*!
   374  * \brief Set animation controller.
   375  *
   376  * \param hTrack                AnimationTrack object
   377  * \param hController           AnimationController object
   378  */
   379 M3G_API void m3gSetController(M3GAnimationTrack hTrack,
   380                               M3GAnimationController hController)
   381 {
   382     AnimationTrack *track = (AnimationTrack *) hTrack;
   383     M3G_VALIDATE_OBJECT(track);
   384 
   385     M3G_ASSIGN_REF(track->controller, hController);
   386 }
   387